我有一个包含大约 8000 个项目(文件路径)的 C# 列表。我想对所有这些项目并行运行一个方法。为此,我有以下 2 个选项:
1) 手动将列表分成小块(比如每个 500 大小)并为这些小列表创建操作数组,然后调用 Parallel.Invoke,如下所示:
var partitionedLists = MainList.DivideIntoChunks(500);
List<Action> actions = new List<Action>();
foreach (var lst in partitionedLists)
{
actions.Add(() => CallMethod(lst));
}
Parallel.Invoke(actions.ToArray())
2) 第二种选择是像下面那样运行 Parallel.ForEach
Parallel.ForEach(MainList, item => { CallMethod(item) });
- 最好的选择是什么?
- Parallel.Foreach 如何划分列表 分成小块?
请建议,在此先感谢。
最佳答案
第一个选项是任务并行化
的一种形式,您可以将任务分成一组子任务并并行执行。从您提供的代码中可以明显看出,您负责在创建子任务时选择粒度级别 [ block ]。如果不依赖于适当的启发式方法,所选的粒度可能太大或太低,并且由此产生的性能增益可能并不显着。 Task-parallelism
用于所有输入值的操作执行时间相似的场景。
第二个选项是数据并行化
的一种形式,其中输入数据根据可用的硬件线程/核心/处理器的数量被分成更小的 block ,然后每个单独的 block 是隔离处理。在这种情况下,.NET 库会为您选择正确的粒度级别并确保更好的 CPU 利用率。通常,data-parallelism
用于要执行的操作根据输入值的不同所花费的时间的情况。
总而言之,如果您的操作在输入值范围内或多或少是统一的,并且您知道正确的粒度 [ block 大小],请继续第一个选项。但是,如果情况并非如此,或者您不确定上述问题,请选择第二个选项,在大多数情况下通常效果更好。
注意:如果这是您应用程序中对性能非常关键的组件,除了上述建议之外,我还建议您使用这两种方法对类似生产环境中的性能进行基准测试以获得更多数据.
关于c# - Parallel.Invoke 与 Parallel.Foreach 用于在大型列表上运行并行进程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47344777/