.net 任务并行库和多个并行任务

.net 任务并行库和多个并行任务,.net,parallel-processing,task-parallel-library,.net,Parallel Processing,Task Parallel Library,TPL如何处理多个并行调用 示例:我想并行处理两个不相关的集合。 (假设处理每个集合中的一个项目需要很长时间) 目前我是这样做的: Parallel.Invoke(() => Parallel.ForEach(collection1,...), () => Parallel.ForEach(collection2,...)) 这是可行的,但我很好奇TPL调度器将如何处理3个单独的调用 我应该换一种方式吗?首先有两件重要的事情: 如果在Paralle

TPL如何处理多个并行调用

示例:我想并行处理两个不相关的集合。 (假设处理每个集合中的一个项目需要很长时间)

目前我是这样做的:

Parallel.Invoke(() => Parallel.ForEach(collection1,...),
                () => Parallel.ForEach(collection2,...))
这是可行的,但我很好奇TPL调度器将如何处理3个单独的调用


我应该换一种方式吗?

首先有两件重要的事情:

  • 如果在Parallel.For/Parallel.ForEach工作负载(或任何类型的循环中阻塞委托)中有长时间运行的迭代,则应始终使用ParallelOptions.MaxDegreeOfParallelism指定并发级别。这是因为并行循环实现针对更细粒度的工作负载进行了优化,当遇到长时间运行的迭代时,它们可能会注入额外的工作线程

  • 通过同时启动并行循环,您已经迫使这两个循环争夺CPU资源。因此,即使您没有长时间运行的迭代,也应该通过限制每个循环的MaxDOP(实际上我会使用Environment.ProcessorCount/2)来明确地实现负载平衡

要回答您最初的问题:

…3个单独的调用

是的,TPL将处理3个或更多单独的并行。调用很好。在这种嵌套并行场景中,它甚至优化为不浪费线程

我应该换一种方式吗

至少你应该像我上面解释的那样使用MaxDOP。但您可能需要根据以下内容选择不同的DOP策略:

  • 收集工作是否需要大致相同的工作量
  • 您是否有任何循环中的阻塞代理

谢谢。为什么为长迭代增加额外线程是一件坏事?代理中存在大量阻塞(即IO)。较低的MaxDOP不会增加所有线程等待的风险吗?如果迭代是CPU限制的(即非阻塞),那么情况会更糟,在这种情况下,您将获得比#个内核更多的线程,这会导致非常低效的战斗。但是,如果迭代是阻塞的,然后,正如你所说的,超额认购通常是有益的。不幸的是,TPL没有一种机制来跟踪有多少并行迭代被阻止并相应地控制DOP。因此,最好由程序员根据对阻塞特性的估计来设置超额订阅级别。这并不是说“如果迭代受CPU限制,情况会更糟”。TPL使用“爬山”算法分配线程,避免过度订阅。MSDN说,“爬山算法的引入是为了快速确定并调整当前工作负载的最佳线程数。”