To set the affinity of CPUs using C#
Asked Answered
A

4

5

I have created a window application in C#.Now I want to set the CPU affinity for this application.I may have 2 processors,4 processors,8 processors or may be more than 8 processors.

I want to set the cpu affinity using input from interface.

How can i achieve this? How can it is possible to set the affinity using Environment.ProcessorCount?

Acetophenetidin answered 12/12, 2012 at 7:7 Comment(2)
Don't. The OS knows more about what's going on, trust it to schedule your application and threads.Longanimity
Why do you want to set CPU affinity? What are you trying to achieve? If you want to avoid cache invalidation, TPL, PLINQ, even simple Threads have their own ways to prevent data movement between processors. If you want to limit resource consumption, there are more efficient ways to do this than setting affinity to a certain (possibly oversubscribed) CPULamkin
I
14

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);
    }
}
Immediacy answered 12/12, 2012 at 7:10 Comment(4)
I have tried this, but when i checked in the task bar,I found that CPU 1 is checked only.Acetophenetidin
Thanx for the answer and got your point.Can I not set the affinity based on Environment.ProcessorCount?Acetophenetidin
I fixed newAffinity = newAffinity | int.Parse(item);Immediacy
Using this, even when selecting 1,2,3,4,5 it will only select the first 3 cores?Samul
E
5

The provided sample program by Alex Filipovivi seems incorrect, in that it ORs processor numbers into newAffinity without first converting them into a set bit. So if you input 3,4 to this program, you get an affinity mask of 7, which is cores 1, 2, and 3! The mask should be set to 12 (hex 0xC, binary 1100, which has bits 2 and 3 set, if bit 0 is the least significant bit).

Replacing

newAffinity = NewAffinity | int.Parse(item);

with

newAffinity = newAffinity | (1 << int.Parse(item)-1);

Is one reasonable way to do that.

Elexa answered 25/7, 2013 at 23:34 Comment(1)
Or you can consider proc 1, 2, 3, 4 to be 1, 2, 4, 8 (powers of 2), then affinity of proc 3 and 4 is affinitiy = 4 | 8, and 1, 4 and 7 is affinity = 1 | 8 | 64.Heretic
E
2

For people looking for thread affinity.

public class CpuAffinity
{
    [DllImport("kernel32.dll")]
    static extern IntPtr GetCurrentThread();

    [DllImport("kernel32.dll")]
    static extern IntPtr SetThreadAffinityMask(IntPtr hThread, IntPtr dwThreadAffinityMask);

    /// <summary>
    /// Sets the current Thread to have affinity to the specified cpu/processor if the system has more than one.
    /// 
    /// Supports most systems as we use a signed int; Anything more than 31 CPU's will not be supported.
    /// </summary>
    /// <param name="cpu">The index of CPU to set.</param>
    public static void SetCurrentThreadToHaveCpuAffinityFor(int cpu)
    {
        if (cpu < 0)
        {
            throw new ArgumentOutOfRangeException("cpu");
        }

        if (Environment.ProcessorCount > 1)
        {
            var ptr = GetCurrentThread();
            SetThreadAffinityMask(ptr, new IntPtr(1 << cpu));

            Debug.WriteLine("Current Thread Of OS Id '{0}' Affinity Set for CPU #{1}.", ptr, cpu);
        }else
        {
            Debug.WriteLine("The System only has one Processor.  It is impossible to set CPU affinity for other CPU's that do not exist.");
        }
    }
}
Eduardo answered 25/3, 2015 at 1:10 Comment(0)
M
1

System.Diagnostics.Process.ProcessorAffinity

What do you want to use Environment.ProcessorCount for? User input validation? Anyway if you want to select a particular processor (#1 or #2 or #3...), create a bitmask like that:

if (userSelection <= 0 || userSelection > Environment.ProcessorCount)
{
    throw new ArgumentOutOfRangeException();
}

int bitMask = 1 << (userSelection - 1);
Process.GetCurrentProcess().ProcessorAffinity = (IntPtr)bitMask;

Where userSelection - is a number of selected processor.

If you'd like to select more than one processor, then do

bitMask |= 1 << (anotherUserSelection - 1);

for each user selection

Merline answered 12/12, 2012 at 7:37 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.