VB.NET运行总和在Parallel.for Synclock内的嵌套循环中丢失信息 [英] VB.NET running sum in nested loop inside Parallel.for Synclock loses information

查看:281
本文介绍了VB.NET运行总和在Parallel.for Synclock内的嵌套循环中丢失信息的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

以下是我能够开发的最佳表示形式,用于计算嵌套在VB.NET(Visual Studio 2010,.NET Framework 4)的Parallel.for循环内的循环内的运行总和.请注意,当在屏幕上以和"显示结果时,两个和之间存在细微差异,因此在并行化变体中信息丢失.那么,信息如何丢失以及正在发生什么呢?在这种情况下,谁能提供一些有关方法的显微外科手术"以保持连续不断的增长? (请注意Parallel.for的新用户:我通常不使用从零开始的方法,因此在Parallel.for语句中,I1最多循环到101,因为代码使用101-1作为上限.这是因为MS开发了基于零计数器的并行代码):

Below is the best representation I have been able to develop for calculating a running sum inside a loop that's nested inside a Parallel.for loop in VB.NET (Visual Studio 2010, .NET Framework 4). Note that when showing the results in `sum' to the screen, there is a slight difference between the two sums, and hence loss of information in the parallelized variant. So how is the information being lost, and what's happening? Can anyone offer some "microsurgery" on methodology for keeping a running sum in this context? (Note to new users of Parallel.for: I typically don't use zero-based methods, so in the Parallel.for statement the I1 loops up to 101, since the code uses 101-1 as the upper bound. This is because MS developed the parallel code assuming zero-based counters):

    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)    

推荐答案

您正在使用double,而double根本不准确. 在非并行循环中,所有错误均直接存储在总和中.在并行循环中,您有一个附加的tmp,稍后将其添加到sum中.在非并行循环中使用相同的tmp(在内循环运行后加和),最终结果将是相等的.

You are working with doubles and double are simply not accurate. In the non parallel loop, all errors are stored directly in sum. In the parallel loop you have an additional tmp that is later added to sum. Use the same tmp in your non parallel loop (adding to sum after the inner loop has run) and eventually the results wil be equal then.

 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)

Conclusion: If you work with double, then (a + b) + c is NOT (always) equal to 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

这篇关于VB.NET运行总和在Parallel.for Synclock内的嵌套循环中丢失信息的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆