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

mit*_*ita 24 .net c# multithreading

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

我已经读过SetThreadAffinityMask但没有找到应该如何使用的例子.

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

Phi*_*lip 45

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属性

  • 问:"我们可以在C#应用程序中设置两个线程或两个任务以执行不同的处理器关联吗?" 请注意,OP在同一个_process_中请求不同的_threads_.所以问题不在于_process_,而在于_thread_ affinity. (2认同)

Kae*_*Rin 6

实际上,.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===");
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

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


And*_*rey 2

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