Можно ли установить два потока или две задачи для выполнения с различным сродством процессора в приложении С#?
Я читал о 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;