2016-09-11 5 views
-5

Это не быстрее - это также намного медленнее.Многопоточность медленнее, чем однострочный

У меня есть процессор с 4 ядрами.

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

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 Время: 2,1183545

[Multithreaded] AVRG Время: +11,6677879333333

+3

[? Как задать хороший вопрос] (http://stackoverflow.com/help/how-to-ask) – buhtz

ответ

0

Прежде всего, btn_Singelthreaded_Click и ForLoop не совпадают. В 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. Конечно, ядра процессора не могут видеть изменения в иностранных регистрах, поэтому в этом сценарии не может быть достигнуто никакого сотрудничества.

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