对于小的工作负载,我需要检查Parallel.ForEach吗

本文关键字:检查 Parallel ForEach 于小 工作 负载 | 更新日期: 2023-09-27 17:59:07

我在工作负载中有一组可以并行运行的项。有时只有1个,有时很多。当我在大的工作负载上并行.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);
        });
}

对于小的工作负载,我需要检查Parallel.ForEach吗

好吧,带有单个任务的Parallel.ForEach会增加一些开销,但不会太大。Parallel.ForEach实际上会重用主线程,这意味着实际上只有一些小的检查,然后它会运行您的工作。两项工作可能是有价值的,而且越多越好。

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

如果每个项目的工作都有CPU限制并且相当大,那么总是并行化是相当安全的,不需要检查。

话虽如此,与往常一样,最好的解决方案是使用您的所有各种选项来实际配置您的应用程序。

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

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

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