it-swarm.com.ru

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

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

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

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

22
mita

Объекты 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;
...

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

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

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

43
Phillip

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

2
Andrey

В следующем примере из 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;
        }
    }
}
1
user3599701

На самом деле .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'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===");
        }
    }
}

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

1
Fawkes Flammer
Process.GetCurrentProcess().ProcessorAffinity = (System.IntPtr)2; 
0
Amey Vartak