如何在.NET中设置处理器关系?

时间:2010-03-24 18:57:38

标签: c# .net multithreading

我们可以设置两个线程或两个任务在C#应用程序中以不同的处理器关联执行吗?

我已阅读有关SetThreadAffinityMask但未找到应如何使用的示例。

或者,TPL(任务并行库)有没有办法执行两个线程/具有高优先级的任务来使用100%的CPU?

5 个答案:

答案 0 :(得分:43)

ProcessProcessThread个对象具有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 Property

答案 1 :(得分:2)

实际上,操作系统能够对核心/处理器进行负载平衡,但如果您想明确使用,请通过PInvoke提及。你传递线程的id(不是托管的!)和掩码 - 核心的位数组。

答案 2 :(得分:2)

实际上,.NET Framework和Windows很好地管理线程,在每个处理器上均匀分配它们。但是,可以使用ProcessProcessThread手动操作线程的分布

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===");
        }
    }
}

现在检查任务管理器,我们可以看到第二个处理器正在承担所有工作负载。 The task manager window

答案 3 :(得分:1)

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 :(得分:0)

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