【问题标题】:Why does my Parallel.ForAll call end up using a single thread?为什么我的 Parallel.ForAll 调用最终使用单个线程?
【发布时间】:2013-07-25 07:47:45
【问题描述】:

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

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

要执行我的操作,我只需:

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

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

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

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

我的理论是正确的还是有其他可能的解释?

我应该在运行列表之前对其进行洗牌,还是可以使用某种并行参数来解决该问题?

【问题讨论】:

    标签: c# .net plinq


    【解决方案1】:

    您的理论可能是正确的,尽管有一种叫做“偷工减料”的东西可以反驳这一点。我不确定为什么这在这里不起作用。外部末端有很多(>=几十个)大型工作还是只有几个?

    除了改组您的数据之外,您还可以将the overload 用于接受custom PartionerAsParallel()。这样可以让你更好地平衡工作。

    旁注:对于这种情况,我更喜欢Parallel.ForEach(),更多选项和更简洁的语法。

    【讨论】:

    • 据我所知,工作窃取适用于任务,而不是 PLINQ 中的迭代。如果一个任务从集合中获取一堆项目来处理,其他任务将无法窃取这些。
    • 另外,这里可能不需要自定义分区器,the ones that are provided by the framework 可能就足够了。
    • @svick - 你可能是对的,但这会指向创建一堆任务的 for 循环吗?看起来很笨重。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-03-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-07-09
    • 1970-01-01
    相关资源
    最近更新 更多