对于小型工作负载,我是否需要检查Parallel.ForEach?

时间:2014-04-18 21:09:24

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

我在工作负载中有一组可以并行运行的项目。有时只有1,有时会有很多。当我在一个大的工作负载上使用Parallel.ForEach时,它明显更快。所以它似乎是Parelle.ForEach的合适用途。

我已经读过,对于1或2的工作负载,最好不要将Parallel.ForEach放在它们上面。这是否意味着我必须用这种模式包装每个Parallel.ForEach的变量工作负载大小?

if (workItems.Count==1)
{
    foreach (MyItem item in workItems)
    {
        bool failed = WorkItWorkIt(item);
    }
}
else
{
    Parallel.ForEach(workItems, (item, loopState) =>
        {
            bool failed = WorkItWorkIt(item);
        });
}

3 个答案:

答案 0 :(得分:7)

嗯,Parallel.ForEach只需一个任务就会增加一些开销,但不会太大。 Parallel.ForEach实际上会重用主线程,这意味着只有一些小支票,然后它会运行你的工作。两个工作项目可能是有价值的,更多只是更好。

Parallel.ForEach的更大问题实际上并不是集合中的项目数量,而是每个项目的工作量和类型。如果你的身体非常小(就CPU时间等而言),并行化的成本可能会快速超过好处。

如果每个项目的工作受CPU限制并且相当大,那么在没有检查的情况下始终并行化是相当安全的。

话虽如此,一如既往,最好的解决方案是实际使用各种选项来分析您的应用程序。

答案 1 :(得分:2)

对于大多数常见任务,与维护两个代码路径的开发成本相比,有时会导致Parallel.ForEach()的小工作负载的CPU成本较小,一个用于小型工作路径,一个用于大型工作负载。

除非您的用例中的测量结果表明相反,否则我会选择单个Parallel.ForEach()实现。

答案 2 :(得分:-1)

如果您的任务很关键 - 性能方面 - 特别是如果您的方法 WorkItWorkIt() 需要某种锁定(例如对 DataTable 的写操作),那绝对值得,但我不会测试它的 1 或 2仅元素。相反,我有一个阈值,并根据数据集大小决定最佳策略。 示例:我处理了一个真实的测试用例,其中 Parallel.ForEach() 需要 4 秒来处理 DataTable 中的 1200 行,其中单线程线性 For 将在 2 秒内完成相同的任务仅(时间的 1/2)。