How to Set Processor Affinity to a Thread or a Task in .Net

To set the affinity of CPUs using C#

Try this:

Process.GetCurrentProcess().ProcessorAffinity = (System.IntPtr)2;

Here's more about it.

ProcessorAffinity represents each processor as a bit. Bit 0 represents processor one, bit 1 represents processor two, and so on. The following table shows a subset of the possible ProcessorAffinity for a four-processor system.

Property value (in hexadecimal)  Valid processors

0x0001 1
0x0002 2
0x0003 1 or 2
0x0004 3
0x0005 1 or 3
0x0007 1, 2, or 3
0x000F 1, 2, 3, or 4

Here's a small sample program:

//TODO: manage exceptions
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Total # of processors: {0}", Environment.ProcessorCount);
Console.WriteLine("Current processor affinity: {0}", Process.GetCurrentProcess().ProcessorAffinity);
Console.WriteLine("*********************************");
Console.WriteLine("Insert your selected processors, separated by comma (first CPU index is 1):");
var input = Console.ReadLine();
Console.WriteLine("*********************************");
var usedProcessors = input.Split(',');

//TODO: validate input
int newAffinity = 0;
foreach (var item in usedProcessors)
{
newAffinity = newAffinity | int.Parse(item);
Console.WriteLine("Processor #{0} was selected for affinity.", item);
}
Process.GetCurrentProcess().ProcessorAffinity = (System.IntPtr)newAffinity;
Console.WriteLine("*********************************");
Console.WriteLine("Current processor affinity is {0}", Process.GetCurrentProcess().ProcessorAffinity);
}
}

Set processor affinity for current thread on Mono (Linux)

lupus's answer was on the right track, but it took me some further research to get this implemented (such as the P/Invoke signature for sched_setaffinity and the resolution of libc.so.6). Here's the working code (excluding error-handling) in case anyone needs it:

[DllImport("libc.so.6", SetLastError=true)]
private static extern int sched_setaffinity(int pid, IntPtr cpusetsize,
ref ulong cpuset);

private static void SetAffinity(int processorID)
{
ulong processorMask = 1UL << processorID;
sched_setaffinity(0, new IntPtr(sizeof(ulong)), ref processorMask);
}

Edit: The above signature worked fine for my experiments, but refer to David Heffernan's answer (under my other question) for a suggested correction.

C# Change affinity of an application

Just as an extension to answer by @Rowan Smith, there is an additional way of writing binary numbers in C# 7.0 and higher - binary literals.

To specify hex literal one writes 0x at the beginning of number. For binary literals one should write 0b like this:

0b0000_0000_0000_0001 -> 1
0b0000_0000_0000_0010 -> 2
0b0000_0000_0000_1111 -> 1 & 2 & 3 4

You write them like:

int value = 0b0000_0000_0000_0001; 

Some people might find it easier to write it like this instead of recalculating number between hex and binary representation, although the number itself is longer.

Target specific CPU Cores with Task Parallel Library in .NET?

This kind of micro-optimisation at runtime is way outside the scope of C#. And it should definitely not be hardcoded into the programm itself. Generally the load balancing features of .NET and the OS will deal with running threads efficiently.

With this kind of difference, the speed rant might apply: https://ericlippert.com/2012/12/17/performance-rant/

You can however set up such limits in the OS, without even looking at the applications code: https://www.techjunkie.com/restrict-apps-cpu-cores-processor-affinity/
This sounds more like what you need/should be using.

Is Core Affinity Something that We Can Safely Do in .NET?

No.

.NET threads do not map 1:1 to operating system threads. Thread affinity is for operating system threads. Since the runtime can switch .NET threads between OS threads at will, setting processor affinity will do nothing at best, and waste performance in a typical multi-threaded scenario.

Note that ProcessThread simply contains information about running operating system thread in a process. It's just what you get when you ask what threads a process has - it's part of the OS, not .NET. In contrast, Thread is about your threads, and only the managed ones.



Related Topics



Leave a reply



Submit