Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I set processor affinity to a thread or a Task in .NET?

Can we set two threads or two tasks to execute with different processor affinity in a C# application?

I have read about SetThreadAffinityMask, but have found no example of how that should be used.

Alternatively, is there any way for TPL (Task Parallel Library) to execute two threads/Tasks with high priority to use 100% CPU?

like image 615
mita Avatar asked Mar 24 '10 18:03

mita


People also ask

How would you assign CPU affinity for each thread?

The pthread_setaffinity_np() function sets the CPU affinity mask of the thread thread to the CPU set pointed to by cpuset. If the call is successful, and the thread is not currently running on one of the CPUs in cpuset, then it is migrated to one of those CPUs.

What is thread affinity C#?

So thread affinity means that the thread, in this case the UI thread that instantiates an object is the only thread that can access its members. So for example, dependency object in WPF has thread affinity.


2 Answers

Process and ProcessThread objects have a ProcessorAffinity property of IntPtr type that can be directly manipulated to read/change affinity for up to 64 processors:

  using System.Diagnostics; ...   Process Proc = Process.GetCurrentProcess();   long AffinityMask = (long)Proc.ProcessorAffinity;   AffinityMask &= 0x000F; // use only any of the first 4 available processors   Proc.ProcessorAffinity = (IntPtr)AffinityMask;    ProcessThread Thread = Proc.Threads[0];   AffinityMask = 0x0002; // use only the second processor, despite availability   Thread.ProcessorAffinity = (IntPtr)AffinityMask; ...  

You can also use the thread's IdealProcessor property to allow the scheduler to prefer running the thread on a specified processor (without guarantee).

Yes, it's that easy :)

Reference: MSDN ProcessThread.ProcessorAffinity Property

like image 161
Phillip Avatar answered Oct 02 '22 23:10

Phillip


Actually, .NET Framework and Windows manage the threads pretty well, distributing them evenly on every processor. However, the distribution of threads can be manipulated manually using Process and ProcessThread.

using System; using System.Diagnostics; using System.Threading;  namespace ThreadTest {     class Program     {         static void Main(string[] args)         {             //Get the our application's process.             Process process = Process.GetCurrentProcess();              //Get the processor count of our machine.             int cpuCount = Environment.ProcessorCount;             Console.WriteLine("CPU Count : {0}", cpuCount);              //Since the application starts with a few threads, we have to             //record the offset.             int offset = process.Threads.Count;             Thread[] threads = new Thread[cpuCount];             Console.WriteLine(process.Threads.Count);             LogThreadIds(process);              //Create and start a number of threads that equals to             //our processor count.             for (int i = 0; i < cpuCount; ++i)             {                 Thread t = new Thread(new ThreadStart(Calculation))                 { IsBackground = true };                 t.Start();             }              //Refresh the process information in order to get the newest             //thread list.             process.Refresh();             Console.WriteLine(process.Threads.Count);             LogThreadIds(process);              //Set the affinity of newly created threads.             for (int i = 0; i < cpuCount; ++i)             {                 //process.Threads[i + offset].ProcessorAffinity = (IntPtr)(1L << i);                 //The code above distributes threads evenly on all processors.                 //But now we are making a test, so let's bind all the threads to the                 //second processor.                 process.Threads[i + offset].ProcessorAffinity = (IntPtr)(1L << 1);             }             Console.ReadLine();         }         static void Calculation()         {             //some extreme loads.             while (true)             {                 Random rand = new Random();                 double a = rand.NextDouble();                 a = Math.Sin(Math.Sin(a));             }         }         static void LogThreadIds(Process proc)         {             //This will log out all the thread id binded to the process.             //It is used to test whether newly added threads are the latest elements             //in the collection.             Console.WriteLine("===Thread Ids===");             for (int i = 0; i < proc.Threads.Count; ++i)             {                 Console.WriteLine(proc.Threads[i].Id);             }             Console.WriteLine("===End of Thread Ids===");         }     } } 

Now check the task manager, we can see that that the second processor is taking all the work loads. The task manager window

like image 43
ph3rin Avatar answered Oct 02 '22 22:10

ph3rin