2

Tpl and Plinq automatically assign work to threads (at core/s... {well ,if #threads> #cores then , >1 thread will run on the same core. }).

However , Let's say I have MyMethod1(){..} and MyMethod2(){..} and I need to make sure(!) that each will run on a different core! (e.g. intensive computing)

The nearest solution I found is Plinq's .WithExecutionMode (ParallelExecutionMode.ForceParallelism)

But this is for a different situation where Plinq might think that it is better to do it sequentially rather then parallel.Also ,I dont use Plinq. I only have 2 methods which needs to run on a different core.

How can I do it ?

p.s. there was an answer here at SO which suggested to use TaskCreationOptions.LongRunning but it is only to hint to the TaskScheduler that it should more aggressively create thread pool threads. but those threads can be on the same core. and my situation required them to be at a different core.

Thank you.

4

1 回答 1

8

To do this requires breaking down several layers of abstraction and before doing it I would recommend doing quite a bit of profiling to be certain that doing this will be better performance than letting the framework handle resource allocation. I am somewhat doubtful (though I can't say I've analyzed it).

The first thing you need to do is to make sure that your two Tasks get executed on different managed threads. Because this is trying to assert manual control over something the framework handles, to be certain that this is the case you would need to write your own TaskScheduler. However, realistically you can do this by specifying the TaskCreationOptions.LongRunning flag. On the current desktop CLR, at least, that will always create a new thread. But it's just a hint, API-wise.

The next abstraction to break is that of managed vs native threads. Each of your methods should be wrapped in a thread affinity block. The framework is allowed to switch the physical thread a managed thread is running on. Since processor affinity is a native thread operation, you have to tell the framework not to do that.

Next, you need to get the native thread that corresponds to the current managed thread. In each method, after calling BeginThreadAffinity, get the native thread by calling GetCurrentThreadId via p/invoke.

Now you can do the rest of this in either native or managed land, but I'll assume you want to do it in .NET. In that case, get the ProcessThread object which corresponds to the native thread, and you can set processor affinity or ideal processor from there:

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()
于 2013-03-30T13:11:27.707 回答