简体   繁体   中英

Force TPL Tasks to run on a single core

I have ETL project which has a few processing component. The single component is producer-consumer based on BlockingCollection. All of the components are executed via Task.Run in parallel, wait for items to arrive from other components, process them and put the result to their output collections (think pipelines). All components are executed via Task.Run().

Is it possible to force tasks to run on a single core (I don't want them to take 100% of multi-core CPU) without setting processor affinity for the process (this seems like overkill)?

Please note that I still want tasks to run in parallel fashion - just on a single core.

A Task Executes on a thread,the OS decides on which core it executes.

I don't think there is any other way other than settings Processor Affinity.

see here: https://msdn.microsoft.com/en-us/library/system.diagnostics.processthread.processoraffinity.aspx

Are you sure that running them parallels on one core will benefit you with performance, why do you not want to allow the process to potentially use 100% cpu if it needs to? the os will still prioritize it with other processes and not necceserily allow this

You could also just lower the Thread/Process priority if what worries you is your process straining other OS processes:

Process Priority: https://msdn.microsoft.com/en-us/library/system.diagnostics.process.priorityclass.aspx Thread Priority: https://msdn.microsoft.com/en-us/library/system.threading.thread.priority(v=vs.110).aspx

Yes, this is entirely possible. You just need to implement your own TaskScheduler .

In fact, the example in the TaskSchduler's API docs illustrates how to accomplish exactly what you want--they implement a LimitedConcurrencyLevelTaskScheduler that lets you set the number of worker threads that you want to use.

The links in the Remarks section of the API docs are are also valuable. The Samples for Parallel Programming with the .NET Framework 4 project contains a slew of alternative thread schedulers, described in detailhere . They may inspire you to think of alternative approaches to scheduling these tasks.

The only twist here is that you can't use the Task.Run() shortcut anymore--you'll need to go through a TaskFactory instead .

When using Task.Run() , you have a very low control over job and everything is parallel, except if you use a custom Scheduler.

Rather than this technical solution, I suggest using Task Parallel Library (TPL) , that could be viewed as a higher layer of handling threaded jobs.

In TPL, you can choose blocks types to process your data, and even connect blocks between them, so when an item has just finished processing, the result can be enqueued in next TPL Block.

You can use an ActionBlock<T> : you define the code to execute for each item to be processed, and when data is available for ActionBlock with .Post() , it is automatically processed... in parallel. But for your need, you can specify MaxDegreeOfParallelism=1 .

So with this method you cannot control the Core on which you execute your code, but you ensure all items will be processed sequentially and won't use more than one core at the time.

动作块

var workerBlock = new ActionBlock<int>(
      // Simulate work by suspending the current thread.
      millisecondsTimeout => Thread.Sleep(millisecondsTimeout),
      // Specify a maximum degree of parallelism.
      new ExecutionDataflowBlockOptions
      {
         MaxDegreeOfParallelism = 1
      });
// Source: https://docs.microsoft.com/fr-fr/dotnet/api/system.threading.tasks.dataflow.actionblock-1?view=netcore-3.1

You can also read this complete article about TPL , very interesting.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM