Parallel.For使用step!= 1
有没有办法实现这个for
循环的Parallel.For
版本?
for (int i = 0; i < 100; i += 2) { DoStuff(i); }
我没有看到接受步骤参数的重载,但我想不出任何理由这在逻辑上是不可能的。
对此和此问题的接受答案建议在使用Enumerable.Range
生成的一系列int
上使用Parallel.ForEach
,但在我的情况下,我使用线程本地数据, 因此 。 Parallel.ForEach
不是一个选项
另一种选择是检查我的循环体中是否i % 2 == 0
并return
,但这仍然执行线程本地数据初始化器Func
和终结器Func
。 以下是演示此选项的代码段:
Parallel.For(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 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
数组中获取数据。 您可以使用Enumerable.Range
替换input
(或将其与With
等组合)
如果你想在i
变量中只获得素数,那将完全正常。
转换为VB.NET的新Iterator函数后,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