1

我有 C# 列表,其中包含大约 8000 个项目(文件路径)。我想在所有这些项目上并行运行一个方法。为此,我有以下 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 如何将列表分成小块?

请建议,提前谢谢。

4

1 回答 1

4

第一个选项是 的一种形式task-parallelism,在这种形式中,您将任务划分为一组子任务并并行执行它们。从您提供的代码中可以明显看出,您负责在创建子任务时选择粒度级别 [块]。如果不依赖适当的启发式方法,则所选粒度可能太大或太低,并且由此产生的性能增益可能并不显着。Task-parallelism用于对所有输入值执行操作需要相似时间的场景。

第二种选择是 的一种形式data-parallelism,其中输入数据根据可用的硬件线程/内核/处理器的数量分成更小的块,然后单独处理每个单独的块。在这种情况下,.NET 库会为您选择正确的粒度级别并确保更好的 CPU 利用率。传统上,data-parallelism在要执行的操作根据输入值而在所花费的时间方面可能发生变化的情况下使用。

总之,如果您的操作在输入值范围内或多或少是一致的,并且您知道正确的粒度 [块大小],请继续使用第一个选项。但是,如果情况并非如此,或者您对上述问题不确定,请选择第二个选项,该选项通常在大多数情况下效果更好。

注意:如果这是您的应用程序中对性能非常关键的组件,我建议除了上述建议之外,使用这两种方法对生产环境中的性能进行基准测试以获取更多数据。

于 2017-11-17T07:25:12.490 回答