为什么我的Parallel.ForAll调用最终使用一个线程

本文关键字:线程 一个 Parallel 我的 ForAll 调用 为什么 | 更新日期: 2023-09-27 18:24:45

我最近一直在使用PLINQ来执行一些数据处理。

基本上,我有大约4000个时间序列(所以基本上是Dictionary<DataTime,T>的实例),我把它们存放在一个名为timeSeries的列表中。

为了执行我的操作,我只需执行:

timeSeries.AsParallel().ForAll(x=>myOperation(x))

如果我看看我的不同内核发生了什么,我会注意到,首先,我所有的CPU都在使用,我在控制台上(我在那里输出一些日志)看到几个时间序列同时被处理。

然而,这个过程很长,大约45分钟后,日志记录清楚地表明只有一个线程在工作。为什么?

我试着给它一些思考,我意识到timeSeries在列表的开头和结尾都包含了从myOperation的角度来看更容易处理的实例。所以,我想知道PLINQ使用的算法是否包括将4000个实例拆分在4个核心上,每个核心1000个。然后,当核心完成其工作分配时,它又回到空闲状态。这意味着其中一个核心可能面临更大的工作量。

我的理论正确吗?或者还有其他可能的解释吗?

在运行列表之前,我应该打乱列表吗?或者有什么并行度参数可以用来解决这个问题吗?

为什么我的Parallel.ForAll调用最终使用一个线程

你的理论可能是正确的,尽管有一种叫做"工作tealing"的东西可以反驳这一点。我不知道为什么这在这里不起作用。外端有很多(>=几十个)大型工作还是只有几个?

除了打乱数据之外,您还可以使用接受自定义Partioner的AsParallel()的重载。这样可以让你更好地平衡工作。

附带说明:对于这种情况,我更喜欢Parallel.ForEach(),更多的选项和更干净的语法。