¿Cómo puedo configurar la afinidad del procesador en .NET?

¿Podemos establecer dos hilos o dos tareas para ejecutar con diferente afinidad de procesador en una aplicación C #?

He leído sobre SetThreadAffinityMask pero no he encontrado ningún ejemplo de cómo debería usarse.

Alternativamente, ¿hay alguna forma de que TPL (Task Parallel Library) ejecute dos subprocesos / Tareas con alta prioridad para usar 100% de CPU?

ProcessThread objetos Process y ProcessThread tienen una propiedad ProcessorAffinity de tipo IntPtr que se puede manipular directamente para leer / modificar la afinidad de hasta 64 procesadores:

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; ...
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; ... 

También puede usar la propiedad IdealProcessor del IdealProcessor para permitir que el planificador prefiera ejecutar el subproceso en un procesador específico (sin garantía).

Sí, es así de fácil 🙂

Referencia: MSDN ProcessThread.ProcessorAffinity Property

En realidad, OS es capaz de equilibrar la carga de sus núcleos / procesadores, pero si desea hacerlo explícitamente utilice mencionado a través de PInvoke . Usted pasa la identificación del hilo (¡no administrado!) Y la máscara: la matriz de bits de los núcleos.

El siguiente ejemplo de MSDN muestra cómo establecer la propiedad ProcessorAffinity para una instancia de Notepad en el primer procesador.

 using System; using System.Diagnostics; namespace ProcessThreadIdealProcessor { class Program { static void Main(string[] args) { // Make sure there is an instance of notepad running. Process[] notepads = Process.GetProcessesByName("notepad"); if (notepads.Length == 0) Process.Start("notepad"); ProcessThreadCollection threads; //Process[] notepads; // Retrieve the Notepad processes. notepads = Process.GetProcessesByName("Notepad"); // Get the ProcessThread collection for the first instance threads = notepads[0].Threads; // Set the properties on the first ProcessThread in the collection threads[0].IdealProcessor = 0; threads[0].ProcessorAffinity = (IntPtr)1; } } } 

En realidad, .NET Framework y Windows administran los hilos bastante bien, distribuyéndolos uniformemente en cada procesador. Sin embargo, la distribución de subprocesos se puede manipular manualmente mediante Process y 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==="); } } } 

Ahora revise el administrador de tareas, podemos ver que el segundo procesador está tomando todas las cargas de trabajo. La ventana del administrador de tareas