对于小的工作负载,我需要检查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
更大的问题实际上不是集合中的项目数量,而是每个项目所做的工作量和类型。如果您的主体非常小(就CPU时间等而言),那么并行化的成本可能会很快超过好处。
如果每个项目的工作都有CPU限制并且相当大,那么总是并行化是相当安全的,不需要检查。
话虽如此,与往常一样,最好的解决方案是使用您的所有各种选项来实际配置您的应用程序。
对于大多数常见任务,与维护两个代码路径(一个用于小工作负载,另一个用于大工作负载)的开发成本相比,小工作负载有时会产生Parallel.ForEach()开销的CPU成本会很小。
除非用例中的测量结果表明相反,否则我会选择单个Parallel.ForEach()实现。
如果您的任务是关键的(性能方面),特别是如果您的方法WorkItWorkIt()需要某种锁定(例如,对DataTable的写操作),那么这绝对是值得的,但我不会只对1或2个元素进行测试。相反,我会有一个阈值,并根据数据集的大小来决定什么是最佳策略。示例:我处理了一个真实的测试用例,其中Parallel.ForEach()需要4秒来处理DataTable中的1200行,而单线程线性For只需要2秒(时间的1/2)就可以完成相同的任务。