Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/302.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 部队任务<;T>;到不同的核心?_C#_Multithreading_.net 4.0_Task Parallel Library_Task - Fatal编程技术网

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它不能在一个内核上调度多个线程。如果有两个空闲内核和两个就绪线程,它将向每个内核分派一个线程。