Как установить совместимость процессоров в .NET?

Можно ли установить два потока или две задачи для выполнения с различным сродством процессора в приложении С#?

Я читал о SetThreadAffinityMask, но не нашел примера того, как это следует использовать.

В качестве альтернативы, есть ли способ для TPL (Task Parallel Library) выполнить два потока/задачи с высоким приоритетом для использования 100% -ного процессора?

Ответ 1

Объекты

Process и ProcessThread имеют свойство ProcessorAffinity типа IntPtr, которое можно напрямую манипулировать для чтения/изменения сродства до 64 процессоров:


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

Вы также можете использовать свойство thread IdealProcessor, чтобы позволить планировщику предпочесть выполнение потока на указанном процессоре (без гарантии).

Да, это так просто:)

Ссылка: Свойство MSDN ProcessThread.ProcessorAffinity

Ответ 2

Фактически ОС способна балансировать нагрузку на ваши ядра/процессоры, но если вы хотите явно использовать это, используйте PInvoke. Вы передаете идентификатор потока (не управляемый!) И mask - бит-массив ядер.

Ответ 3

В следующем примере из MSDN показано, как установить свойство ProcessorAffinity для экземпляра Notepad для первого процессора.

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

Ответ 4

Собственно,.NET Framework и Windows прекрасно управляют потоками, распределяя их равномерно на каждом процессоре. Однако распределение потоков можно вручную манипулировать с помощью Process и ProcessThread.

using System;
using System.Diagnostics;
using System.Threading;

namespace ThreadTest
{
    class Program
    {
        static void Main(string[] args)
        {
            //Get the our application 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 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===");
        }
    }
}

Теперь проверьте диспетчер задач, мы увидим, что второй процессор принимает все рабочие нагрузки. Окно диспетчера задач

Ответ 5

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