8

有没有办法实现Parallel.For这个for循环的版本?

for (int i = 0; i < 100; i += 2) { DoStuff(i); }

我没有看到接受 step 参数的重载,尽管我想不出任何原因这在逻辑上是不可能的。

对此这个问题的公认答案建议在使用生成Parallel.ForEach的一系列ints 上使用Enumerable.Range,但在我的情况下,我使用的是线程本地数据,因此Parallel.ForEach不是一个选项

另一种选择是只检查i % 2 == 0我的循环体中是否存在 and return,但这仍然会执行线程本地数据初始化器Func和终结器Func。下面是演示此选项的代码片段:

Parallel.For<Bar>(0, limit, 

    () => new Bar(), //thread local data initialize

    (i, state, local) => //loop body
    {
        if (i % 2 != 0) return local;
        local.foo += DoStuff(i);
        return local;
    },

    (local) => //thread local data post-action
    {
        lock (loopLocker)
        {
            globalData.foo += local.foo;
        );
    }
);
4

4 回答 4

14

这里有一个提示:

for (int j = 0; j < 50; j++) { i = 2*j; DoStuff(); }

一般来说,看看你是否可以计算出迭代次数以及从迭代次数到变量值的转换。

于 2012-12-26T19:19:36.640 回答
6

这是处理阶梯索引的另一种方法

private void ParallelForEachProcessSteppedIndexes()
        {
            Parallel.ForEach(SteppedIterator(0, 100, 2), (index) => DoStuff(index));
        }

private static IEnumerable<int> SteppedIterator(int startIndex, int endIndex, int stepSize)
        {
            for (int i = startIndex; i < endIndex; i = i + stepSize)
            {
                yield return i;
            }
        }
于 2012-12-27T10:31:13.290 回答
4

Ben 的建议非常适合恒定步长,例如 +2、+3 等。

或者(如果你的步骤是随机的)你可以使用Parallel.ForEach例如

int[] input = { 1, 3, 4, 5, 7, 10, 20, 25 }; 

Parallel.ForEach(input,
    () => new Bar(), //thread local data initialize
    (i, state, local) => //loop body
    {
        // your code
    },
    (local) => //thread local data post-action
    {
        // your code
    }

变量i将从input数组中获取数据。您可以替换inputEnumerable.Range(或将其与With等结合使用)

如果您只想获得i变量中的素数,那将非常有效。

于 2012-12-26T19:41:21.183 回答
0

转换为 VB.NET 的新迭代器函数后,Toan 的回答对我有用

Private Sub LoopExample()
    Parallel.ForEach(SteppedIterator(1,100,5), AddressOf Test)

End Sub

Private Iterator Function SteppedIterator(startIndex As Integer, endIndex As Integer, stepSize As Integer) As IEnumerable(Of Integer)
    For i As Integer = startIndex To endIndex Step stepSize
        Yield i
    Next

End Function

Private Sub Test(i As Integer, state As ParallelLoopState, index As Long)
    Debug.WriteLine(i.ToString)
End Sub
于 2017-04-11T13:02:05.450 回答