【问题标题】:Parallel.Invoke vs Parallel.Foreach for running parallel process on large listParallel.Invoke vs Parallel.Foreach 用于在大型列表上运行并行进程
【发布时间】:2017-11-17 06:43:51
【问题描述】:

我有 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 如何划分列表 分成小块?

请建议,提前谢谢。

【问题讨论】:

标签: c# multithreading parallel.foreach parallel.invoke


【解决方案1】:

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

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

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

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-06-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多