强制任务<T>到不同的核心?

Roy*_*mir 2 c# multithreading .net-4.0 task task-parallel-library

TplPlinq 自动将工作分配给线程(在core/s ... { 好吧,如果 #threads> #cores那么,> 1个线程将在同一个核心上运行. }).

但是,让我们说我已经 MyMethod1(){..}并且MyMethod2(){..}我需要确保(!)每个都将在不同的核心上运行!(例如密集计算)

我找到的最近的解决方案是Plinq .WithExecutionMode (ParallelExecutionMode.ForceParallelism)

但这是针对一种不同的情况,Plinq可能会认为按顺序而不是并行执行它更好.另外,我不使用Plinq.我只有2种方法需要在不同的核心上运行.

我该怎么做 ?

ps这里有一个答案,建议使用,TaskCreationOptions.LongRunning但它只是暗示TaskScheduler它应该更积极地创建线程池线程.但这些线程可以在同一个核心上.我的情况要求他们处于不同的核心.

谢谢.

Jac*_*cob 8

要做到这一点,需要分解几个抽象层,在做之前我建议进行相当多的分析,以确保这样做比使框架处理资源分配更好.我有点怀疑(虽然我不能说我已经分析了它).

您需要做的第一件事是确保您的两个Task在不同的托管线程上执行.因为这是试图对框架处理的东西进行手动控制,以确保在这种情况下你需要自己编写TaskScheduler.但是,实际上,您可以通过指定TaskCreationOptions.LongRunning标志来完成此操作.至少在当前桌面CLR上,它将始终创建一个新线程.但它只是一个提示,API-wise.

下一个要打破的抽象是托管vs本机线程.您的每个方法都应该包装在线程关联块中.允许框架切换运行托管线程的物理线程.由于处理器关联是本机线程操作,因此您必须告诉框架不要这样做.

接下来,您需要获取与当前托管线程对应的本机线程.在每个方法中,在调用之后BeginThreadAffinity,通过p/invoke 调用GetCurrentThreadId来获取本机线程.

现在你可以在本地或托管领域完成其余的工作,但我假设你想在.NET中完成它.在这种情况下,获取与本机线程对应的ProcessThread对象,您可以从那里设置处理器关联理想处理器:

Thread.BeginThreadAffinity();
int threadId = GetCurrentThreadId();
Process proc = Process.GetCurrentProcess();
ProcessThread procThread = proc.Threads.Cast<ProcessThread>().Single(
    pt => pt.Id == threadId
);
procThread.ProcessorAffinity = new IntPtr(0x01);
//
// work
//
procThread.ProcessorAffinity = new IntPtr(0xFFFF);
Thread.EndThreadAffinity()
Run Code Online (Sandbox Code Playgroud)