平行的.对于使用step != 1
本文关键字:step 于使用 | 更新日期: 2023-09-27 17:49:31
是否有办法实现for
循环的Parallel.For
版本?
for (int i = 0; i < 100; i += 2) { DoStuff(i); }
我没有看到一个接受step参数的重载,尽管我想不出任何理由这在逻辑上是不可能的。
对此和这个问题的公认答案建议在使用Enumerable.Range
生成的int
s范围内使用Parallel.ForEach
,但在我的情况下,我使用线程本地数据,因此。Parallel.ForEach
不是选项
另一个选择是检查i % 2 == 0
是否在我的循环体和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;
);
}
);
提示:
for (int j = 0; j < 50; j++) { i = 2*j; DoStuff(); }
一般来说,看看你是否能算出迭代的次数,以及从迭代次数到变量值的转换。
下面是处理分级索引的另一种方法
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;
}
}
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
数组中获取数据。您可以将input
替换为Enumerable.Range
(或将其与With
等组合)
如果你想在i
变量中只得到素数,那将工作得非常好。
Toan的答案在转换为VB后对我有效。. NET的新迭代器函数
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