下面是我能够开发的用于计算嵌套在VB.NET(Visual Studio 2010,.NET Framework 4)中的Parallel.for循环内的循环内的运行总和的最佳表示。请注意,当在屏幕上显示“sum”的结果时,两个总和之间存在细微差别,因此并行化变体中的信息丢失。那么信息是如何丢失的,以及发生了什么?任何人都可以提供一些关于在这种背景下保持运行总和的方法的“显微手术”吗? (注意Parallel.for的新用户:我通常不使用从零开始的方法,因此在Parallel.for语句中,I1循环最多为101,因为代码使用101-1作为上限。这是因为假设基于零的计数器,MS开发了并行代码:
Dim sum As Double = 0
Dim lock As New Object
Dim clock As New Stopwatch
Dim i, j As Integer
clock.Start()
sum = 0
For i = 1 To 100
For j = 1 To 100
sum += Math.Log(0.9999)
Next j
Next i
clock.Stop()
MsgBox(sum & " " & clock.ElapsedMilliseconds)
sum = 0
clock.Reset()
clock.Start()
Parallel.For(1, 101, Sub(i1)
Dim temp As Double = 0
For j1 As Integer = 1 To 100
temp += Math.Log(0.9999)
Next
SyncLock lock
sum += temp
End SyncLock
End Sub)
clock.Stop()
MsgBox(sum & " " & clock.ElapsedMilliseconds)
答案 0 :(得分:0)
你正在使用双打和双精简是不准确。 在非并行循环中,所有错误都直接存储在sum中。在并行循环中,您有一个额外的tmp,稍后会添加到sum中。在非并行循环中使用相同的tmp(在内循环运行后添加到sum),最终结果将等于。
Dim sum As Double = 0
Dim lock As New Object
Dim clock As New Stopwatch
Dim i, j As Integer
clock.Start()
sum = 0
For i = 1 To 100
For j = 1 To 100
sum += Math.Log(0.9999)
Next j
Next i
clock.Stop()
Console.WriteLine(sum & " " & clock.ElapsedMilliseconds)
sum = 0
clock.Reset()
clock.Start()
sum = 0
For i = 1 To 100
Dim tmp As Double = 0
For j = 1 To 100
tmp += Math.Log(0.9999)
Next
sum += tmp
Next i
clock.Stop()
Console.WriteLine(sum & " " & clock.ElapsedMilliseconds)
sum = 0
clock.Reset()
clock.Start()
Parallel.For(1, 101, Sub(i1)
Dim temp As Double = 0
For j1 As Integer = 1 To 100
temp += Math.Log(0.9999)
Next
SyncLock lock
sum += temp
End SyncLock
End Sub)
clock.Stop()
Console.WriteLine(sum & " " & clock.ElapsedMilliseconds)
End Sub
输出:
-1,00005000333357 0
-1,00005000333347 0
-1,00005000333347 26
结论:如果你使用double,那么(a + b)+ c不是(总是)等于a +(b + c)
<强>更新强>
一个更简单的例子:
Dim sum As Double
For i = 1 To 100
sum += 0.1
Next
Console.WriteLine(sum)
sum = 0
For i = 1 To 2
Dim tmp As Double = 0
For j = 1 To 50
tmp += 0.1
Next
sum += tmp
Next
Console.WriteLine(sum)
现在输出
9,99999999999998
10