C# 部队任务<;T>;到不同的核心?
C# 部队任务<;T>;到不同的核心?,c#,multithreading,.net-4.0,task-parallel-library,task,C#,Multithreading,.net 4.0,Task Parallel Library,Task,Tpl和Plinq自动将工作分配给线程(在核心处…{好吧,如果#threads>#cores那么,>1个线程将在同一个核心上运行。}) 但是,假设我有MyMethod1(){..}和MyMethod2(){..},我需要确保(!)每个都将在不同的内核上运行!(例如密集型计算) 我找到的最接近的解决方案是Plinq的。WithExecutionMode(ParallelExecutionMode.ForceParallelism) 但这是针对另一种情况,Plinq可能认为按顺序执行比并行执行更好。
Tpl
和Plinq
自动将工作分配给线程(在核心处…{好吧,如果#threads>#cores
那么,>1个线程将在同一个核心上运行。})
但是,假设我有MyMethod1(){..}
和MyMethod2(){..}
,我需要确保(!)每个都将在不同的内核上运行!(例如密集型计算)
我找到的最接近的解决方案是Plinq的。WithExecutionMode(ParallelExecutionMode.ForceParallelism)
但这是针对另一种情况,Plinq可能认为按顺序执行比并行执行更好。而且,我不使用Plinq。我只有两个方法需要在不同的核心上运行
我怎么做
p、 这里有一个答案,建议使用TaskCreationOptions.longlunning
,但这只是为了提示TaskScheduler应该更积极地创建线程池线程。但是这些线程可以在同一个内核上。我的处境要求他们处于不同的核心
谢谢。要做到这一点,需要分解多个抽象层,在这样做之前,我建议进行大量的分析,以确保这样做比让框架处理资源分配的性能更好。我有点怀疑(尽管我不能说我已经分析过了) 您需要做的第一件事是确保在不同的托管线程上执行两个
任务。因为这是在试图对框架处理的东西进行手动控制,所以要确定这种情况,您需要编写自己的TaskScheduler
。但是,实际上,您可以通过指定TaskCreationOptions.longlunning
标志来实现这一点。至少在当前桌面CLR上,这将始终创建一个新线程。但这只是一个提示,API方面
下一个要打破的抽象是托管线程与本机线程的抽象。每个方法都应该包装在一个块中。允许框架切换运行托管线程的物理线程。由于处理器关联是本机线程操作,因此必须告诉框架不要这样做
接下来,需要获取与当前托管线程对应的本机线程。在每个方法中,在调用BeginThreadAffinity
之后,通过p/invoke调用获取本机线程
现在,您可以在本地或管理的土地上完成其余的工作,但我假设您希望在.NET中完成。在这种情况下,获取与本机线程相对应的对象,您可以在此设置或:
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()
Thread.BeginThreadAffinity();
int threadId=GetCurrentThreadId();
Process proc=Process.GetCurrentProcess();
ProcessThread procThread=proc.Threads.Cast().Single(
pt=>pt.Id==threadId
);
procThread.ProcessorAffinity=新的IntPtr(0x01);
//
//工作
//
procThread.ProcessorAffinity=新的IntPtr(0xFFFF);
Thread.EndThreadAffinity()
我认为即使在WinAPI中,您也无法对线程的运行位置进行太多的控制,因为操作系统会决定线程将运行的内核-如果您的硬件至少有两个内核,并且有足够的内存来保证它没有过载准备好的线程,你似乎不需要这样做吗?@MartinJames I认为Windows不会(一开始)知道线程正在运行大量计算,因此它可以在同一个内核上调度两个线程。不过,操作系统会自动在内核之间移动线程@RoyiNamir它不能在一个内核上调度多个线程。如果有两个空闲内核和两个就绪线程,它将向每个内核分派一个线程。