多线程比单线程慢

时间:2016-09-11 03:21:47

标签: vb.net multithreading cpu cpu-usage

它并不快 - 它也慢得多。

我有4核的cpu。

=============================================== ===================

Private Sub btn_Singelthreaded_Click(sender As Object, e As EventArgs) Handles btn_Singelthreaded.Click

    Dim Num As Long
    Dim sw As New Stopwatch
    Dim TimeAvrg As Double
    For i = 0 To 8

        Num = 0
        sw.Restart()
        Do Until Num > 500000000 '500,000,000
            Num += 1
        Loop


        TimeAvrg += sw.Elapsed.TotalSeconds
        'sw.Stop()
    Next
    Console.WriteLine($"[Singelthreaded] Avrg Time: {TimeAvrg / 8}{Environment.NewLine}")


End Sub

Private NumThrd As Long
Private swThrd As New Stopwatch
Private Sub btn_Multithreaded_Click(sender As Object, e As EventArgs) Handles btn_Multithreaded.Click


    Dim T1 As New Threading.Thread(AddressOf ForLoop) : T1.Start()
    Dim T2 As New Threading.Thread(AddressOf ForLoop) : T2.Start()
    Dim T3 As New Threading.Thread(AddressOf ForLoop) : T3.Start()

End Sub


Private Sub ForLoop()
    Dim TimeAvrg As Double
    For i = 0 To 2
        TimeAvrg = 0
        NumThrd = 0
        swThrd.Start()
        Do Until NumThrd > '500,000,000
            NumThrd += 1
        Loop
        TimeAvrg += swThrd.Elapsed.TotalSeconds
        'swThrd.Stop()

    Next
    Console.WriteLine($"[Multithreaded] Avrg Time: {TimeAvrg / 3}{Environment.NewLine}")
End Sub

结果: [Singelthreaded] Avrg Time:2.1183545

[Multithreaded] Avrg Time:11.6677879333333

2 个答案:

答案 0 :(得分:1)

实际上,它要快得多。如果我理解你的问题,你试图在一个线程中测量9次迭代的经过时间,而不是将这9次迭代分解为3个线程,每次3次迭代。为此,您可以为秒表创建表单级别。

Private totTime As New Stopwatch

然后按如下方式对按钮进行编码:

Private Sub btn_Singelthreaded_Click(sender As Object, e As EventArgs) Handles btn_Singelthreaded.Click

    Dim Num As Long
    totTime.Restart()
    For i = 0 To 8
        Num = 0
        Do Until Num > 500000000
            Num += 1
        Loop
    Next
    totTime.Stop()
    Console.WriteLine(totTime.Elapsed.TotalSeconds)

End Sub


Private Sub btn_Multithreaded_Click(sender As Object, e As EventArgs) Handles btn_Multithreaded.Click

    totTime.Restart()
    Dim T1 As New Threading.Thread(AddressOf ForLoop) : T1.Start()
    Dim T2 As New Threading.Thread(AddressOf ForLoop) : T2.Start()
    Dim T3 As New Threading.Thread(AddressOf ForLoop) : T3.Start()

    T3.Join()

    totTime.Stop()
    Console.WriteLine(totTime.Elapsed.TotalSeconds)

End Sub

Private Sub ForLoop()

    Dim Num As Long
    For i = 0 To 2
        Num = 0
        Do Until Num > 500000000
            Num += 1
        Loop
    Next

End Sub

答案 1 :(得分:0)

首先,btn_Singelthreaded_ClickForLoop个不相等。在btn_Singelthreaded_Click中,您使用sw.Restart(),但在ForLoop中有swThrd.Start()。我认为这是你的问题的线索。例如,ForLoop的执行时间为2.然后,通过没有swThrs.Restart(),您将获得TimeAvrg = 2 + 4 + 6,最后您将获得TimeAvrg/3 = 4

第二,这是什么意思Do Until NumThrd > '500,000,000?你比较的实际数字在哪里?

第三个。您应该为每个ForEach子运行使用本地秒表。我不认为秒表是线程安全的,因为在MSDN文档中没有提到秒表类的线程安全性。

第四个。在第NumThrd += 1行,您获得了Race condition,因此ForLoop的运行时间超过了它。你应该读一下。

最后,NumThrd没有同步。如果你在这里没有使用任何内存拦截器,那么编译器可以(我认为必须)为你的NumThrd计数器使用处理器寄存器。当然,cpu核心无法看到外国注册商的变化,因此在这种情况下无法达成合作。