强制TPL任务在单核

时间:2016-01-19 11:16:33

标签: c# .net task-parallel-library

我有ETL项目,它有一些处理组件。单个组件是基于BlockingCollection的生产者 - 消费者。所有组件都是通过Task.Run并行执行的,等待项目从其他组件到达,处理它们并将结果放到它们的输出集合(想想管道)。所有组件都通过Task.Run()执行。

是否有可能强制任务在单个核心上运行(我不希望它们占用100%的多核CPU)而无需为进程设置处理器关联(这看起来有点矫枉过正)?

请注意,我仍然希望任务以并行方式运行 - 只需在单核上运行。

3 个答案:

答案 0 :(得分:2)

是的,这完全有可能。您只需要实现自己的TaskScheduler

事实上,TaskSchduler的API文档中的示例说明了如何完全按照您的意愿完成 - 它们实现了LimitedConcurrencyLevelTaskScheduler,可以让您设置要使用的工作线程数。

API文档的备注部分中的链接也很有价值。 Samples for Parallel Programming with the .NET Framework 4项目包含一系列备用线程调度程序,详细描述了here。它们可能会激励您考虑安排这些任务的替代方法。

这里唯一的变化就是你不能再使用Task.Run()快捷方式了 - 你需要通过一个TaskFactory instead

答案 1 :(得分:1)

任务在一个线程上执行,操作系统决定它执行哪个核心。

除了设置Processor Affinity之外,我不认为还有其他任何方式。

见这里:https://msdn.microsoft.com/en-us/library/system.diagnostics.processthread.processoraffinity.aspx

你确定在一个内核上运行它们会对性能有所帮助,为什么你不想让进程在需要时可能使用100%cpu?操作系统仍然会将其优先于其他进程,而不是必须允许这个

如果你担心的是你的过程使其他操作系统进程紧张,你也可以降低线程/进程优先级:

流程优先级:https://msdn.microsoft.com/en-us/library/system.diagnostics.process.priorityclass.aspx 主题优先级:https://msdn.microsoft.com/en-us/library/system.threading.thread.priority(v=vs.110).aspx

答案 2 :(得分:-1)

使用Task.Run()时,您对工作的控制非常低,并且除使用自定义计划程序外,其他所有内容都是并行的。

我建议使用Task Parallel Library (TPL)而不是这种技术解决方案,它可以看作是处理线程作业的更高层。

在TPL中,您可以选择块类型来处理数据,甚至可以在它们之间连接块,因此,当一个项目刚刚完成处理时,结果可以放入下一个TPL块中。

您可以使用ActionBlock<T> :定义要处理的每个项目要执行的代码,并且当.Post()可用于ActionBlock的数据时,它会自动并行处理。但您可以根据需要指定MaxDegreeOfParallelism=1

因此,使用这种方法,您无法控制在其上执行代码的Core,但要确保所有项目将按顺序处理,并且一次不会使用多个Core。

ActionBlock

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

您也可以阅读此complete article about TPL,非常有趣。