Tpl
和Plinq
自动分配的工作线程(在核心/ S ... { 好了,如果#threads> #cores
然后,> 1个线程将在同一个内核上运行。})。
然而,比方说,我有MyMethod1(){..}
和MyMethod2(){..}
我需要确保 (!),每个都会在不同内核上运行! (例如密集型计算)
我发现最近的解决方案是PLINQ的.WithExecutionMode (ParallelExecutionMode.ForceParallelism)
但是,这是一个不同的情况PLINQ可能会认为这是更好地做到这一点顺序而不是parallel.Also,我不使用PLINQ。 我只有2种方法,其需要在不同内核上运行。
我该怎么做 ?
PS有在这里SO其中建议使用一个答案TaskCreationOptions.LongRunning
但它仅仅是暗示到的TaskScheduler,它应该更积极地创建线程池中的线程。 但这些线程可以在相同的核心。 和我的情况,要求他们是在一个不同的核心。
谢谢。
要做到这一点,需要打破几个抽象层和这样做之前,我建议做相当多的分析中可以肯定 ,这样会比让框架处理资源分配的性能更好。 我有些怀疑(虽然我不能说我已经分析了它)。
你需要做的第一件事是确保你的两个Task
小号得到不同的托管线程执行。 因为这是试图对本东西框架处理手动控制,可以肯定,这是你需要编写自己的情况下TaskScheduler
。 然而,现实你可以通过指定做这个TaskCreationOptions.LongRunning
标志。 在目前的桌面CLR,至少,这总是会创建一个新的线程。 但是,这只是一个提示,API-明智的。
接下来的抽象打破是的,托管VS本地线程。 你的每一个方法都应该被包裹在一个线程关联块。 该框架允许切换管理的线程上运行的物理线程。 由于处理器亲和力是本地线程的操作,你必须告诉框架没有做到这一点。
接下来,你需要获得对应于当前托管线程的本地线程。 在每个方法,调用后BeginThreadAffinity
,通过调用获得本地线程GetCurrentThreadId通过的P / Invoke。
现在,你可以做这个的其余部分是天然的或管理的土地,但我会假设你想要做的.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()