【问题标题】:Changing the incremental value of a C# Parallel.For loop更改 C# Parallel.For 循环的增量值
【发布时间】:2010-10-20 16:45:56
【问题描述】:

我想使用 TPL 将每次通过时将迭代器递增 2 的 for 循环转换为并行 For 循环。数据不依赖于顺序或以任何方式受到约束,但我只想处理源数组的每个其他元素中的数据(在下面的代码中为 _Datalist),因此需要增加 2。

我的 For 循环:

for (int i = 1; i < _DataList.Length - 1; i += 2)
{
     // Do work for _DataList[i]
}

是否可以告诉并行循环我想将 i 增加 2 而不是 1?

这是并行循环,但显然 i 每次迭代只会增加 1:

        Task.Factory.StartNew(() =>
            Parallel.For(1, _DataList.Length, i =>
            {
                // do work for _DataList[i]                    
            })
        );

我可以告诉内部循环体忽略 i 的奇数值,但这似乎有点混乱 - 有没有办法在循环初始化中以某种方式做到这一点?

【问题讨论】:

  • 不要只忽略奇数;这会创建两倍于您需要的任务,这会增加许多不必要的开销。
  • 是的,我明白你的意思

标签: c# parallel-processing task-parallel-library


【解决方案1】:

您可以将步数减半并将索引加倍:

Parallel.For(0, _DataList.Length / 2, i =>
{
    // do work for _DataList[2 * i]                    
});

【讨论】:

    【解决方案2】:

    Darin Dimitrov's answer 展示了一种简单的方法来实现这一点。

    但是,这并没有被添加,因为它通常表明循环体并不是真正不同的。在大多数情况下,需要使用不同的增量值通常只需要按特定顺序进行处理或其他会导致并行化创建竞争条件的问题。

    【讨论】:

    • 注意以供将来参考,但在我应用此循环的情况下,元素的处理顺序真的不是问题
    • @Gareth:我只是提到了这一点,因为 Stephen Toub 实际上有一个讨论(我找不到 atm),特别提到了为什么 Parallel.For 没有添加这个功能 - 它基本上来了归根结底对于并行处理来说通常是有问题的,但是您始终可以通过分区程序或 parallel.foreach 解决它。
    • 我相信这个用例在 .NET 中使用 SIMD 指令时会很自然地出现,因为它们通过为数组的每个第 n 个元素创建一个 Vector&lt;'T&gt; 来操作,其中 N 是向量。您不能将 Parallel.For 用于小型矢量化函数,因为枚举器或乘法技巧会破坏性能优势。
    【解决方案3】:

    跳过偶数值。

    Task.Factory.StartNew(() =>
                    Parallel.For(1, _DataList.Length, i =>
                    {
                        if(i % 2 == 0)
                        {
                            // do work for   
                        }   
                    })
                );
    

    【讨论】:

    • 你能解释一下你的答案吗?为您给出的答案提供一些信息或解释通常被认为是一种很好的做法。这可能对未来的用户或 OP 有更多帮助。
    • 这不是一个好主意,因为您正在创建开销,这也是我试图避免的 - 请参阅该问题的第一条评论。幸运的是 5 年前有一些很好的解决方案 :)
    【解决方案4】:

    怎么样:

    var odds = Enumerable.Range(1, _DataList.Length).Where(i => i % 2 != 0);
    
    Task.Factory.StartNew(() =>
        Parallel.ForEach(odds, i =>
        {
            // do work for _DataList[i]                    
        })
    );
    

    【讨论】:

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