【问题标题】:Parallel.For not utilising all coresParallel.For 不使用所有内核
【发布时间】:2015-08-24 17:29:52
【问题描述】:

我在 Parallel.For 块内并行使用 Math.Net Numerics 进行繁重的数学计算。

当我在具有 4 个核心 (2*2) 的本地系统中运行代码时,它会使用所有 4 个核心。

但是当我在我们的 8 核 (4*2) 开发服务器中运行相同的代码时,它只使用了 4 个核。

我尝试设置 MaxDegreeOfParallism,但无济于事。

知道为什么没有使用所有内核。

下面是示例代码。

Parallel.For(0,10000,(i)=>
{

 // heavy math computations using matrices
});

【问题讨论】:

  • 你的服务器是8核还是4核支持超线程?
  • @vcsjones:4 个 CPU,每个 CPU 有 2 个内核,因此总共 4*2=8 个内核
  • 您使用的是本地提供程序吗?请注意,Math.NET Numerics 中的线性代数本身是并行化的(至少部分是并行化的) - 如果您更喜欢在上面进行自己的并行化,请考虑通过调用 Control.UseSingleThread(); 来禁用 Math.NET 的并行化
  • @ChristophRüegg 我正在使用英特尔 MKL 提供程序。我在每次迭代中执行大量矩阵运算。
  • 显示正在运行的实际代码。

标签: c# task-parallel-library math.net mathnet-numerics parallel.for


【解决方案1】:

来自MSDN

默认情况下,For 和 ForEach 将使用底层调度程序提供的线程数,因此从默认值更改 MaxDegreeOfParallelism 只会限制将使用多少并发任务。

我阅读文档的方式:如果底层调度器只提供单线程,那么设置MaxDegreeOfParallelism > 1仍然会导致单线程。

【讨论】:

  • 已经创建了多个线程/任务。但是当有 8 个内核可用时,它们只在 4 个内核上运行。
  • 池的调度程序和运行时/TPL 实际上决定了哪些线程在何时何地运行。如果运行时仅调度到 4 个逻辑核心,那么这就是将同时运行的数量,而不管已创建的线程数量。
【解决方案2】:

并行化是根据当前条件和许多其他情况在运行时完成的。您不能强制 .NET 使用所有内核(至少在托管代码中)。

来自MSDN

“相反,默认情况下,Parallel.ForEach 和 Parallel.For 方法可以使用可变数量的任务。这就是为什么,例如,ParallelOptions 类具有 MaxDegreeOfParallelism 属性而不是“MinDegreeOfParallelism”属性。这个想法是系统可以使用比请求更少的线程来处理循环。 .NET 线程池通过允许并行任务的工作线程数量随时间变化而动态适应不断变化的工作负载。在运行时,系统会观察增加线程数是提高还是降低了整体吞吐量,并相应地调整工作线程数。

如果您使用并行循环的各个步骤需要几秒钟或更长时间,请务必小心。这可能发生在 I/O 密集型工作负载以及冗长的计算中。如果循环需要很长时间,您可能会遇到工作线程的无限增长,这是由于 .NET ThreadPool 类的线程注入逻辑使用的用于防止线程饥饿的启发式方法。 "

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-01-22
    • 2019-04-16
    • 1970-01-01
    • 1970-01-01
    • 2016-05-31
    • 1970-01-01
    相关资源
    最近更新 更多