Parallel. Per risultati di incoerenza

2

Sto usando VB.net per scrivere un codice basato su parallelo. Io uso Parallel.Per per generare coppie di 500 oggetti o in combinazione C (500,2) come il seguente codice; ma ho scoperto che non generava sempre tutte le combinazioni che dovrebbero essere 124750 (mostrate dal contatore variabile). Nessun altro thread era in esecuzione quando è stato eseguito questo codice. Utilizzo un desktop Win-7 a 32 bit con CPU Intel Core i5 da 650 a 3,2 GHz, 3,33 GHz e RAM da 2 GB. Cosa c'è di sbagliato nel codice e come risolvere questo problema? Grazie.

    Dim Counter As Integer = 0
    Parallel.For(0, 499, Sub(i)
                     For j As Integer = i + 1 To 499
                         Counter += 1
                         Console.Write(i & ":" & j)
                     Next
                 End Sub)
    Console.Writeline("Iteration number: " & Counter)
    
posta ni Gue 阿里扎 02.11.2013 - 08:37
fonte

3 risposte

7

Non è che non tutti siano stati generati, è che il contatore si è rotto. Hai incontrato la lettura / scrittura classica condizioni di gara .

Dovresti utilizzare incremento atomico per risolvere il problema.

Inoltre, la stampa è molto lenta e si blocca internamente. Quindi non otterrai alcuna prestazione utilizzando il parallelismo in questo modo.

Ma questa è una conoscenza di base. Non dovresti, in nessun caso, provare a parallelizzare il tuo codice se non hai questa conoscenza.

    
risposta data 02.11.2013 - 09:08
fonte
1

Parallel.Per utilizzare un pool di thread per elaborare il loop. Non appena uno dei suoi thread è libero, lo assegna all'elemento successivo.

È un problema comune: chiamare qualcosa come count ++ su una variabile condivisa da più thread.

  • Il thread n. 1 legge il valore del conteggio.
  • Il thread n. 2 legge il valore del conteggio.
  • Il thread n. 1 incrementa la sua copia locale.
  • Il thread n. 2 incrementa la copia locale.
  • Il thread n. 1 scrive di nuovo il valore incrementato per contare.
  • Il thread n. 2 scrive di nuovo il valore incrementato per contare.

In questo modo, il valore scritto dal thread # 1 viene sovrascritto dal thread # 2, quindi il valore viene effettivamente incrementato una sola volta.

Quello che devi fare è "bloccare" count ++ o usare Interblocco classe.

lock (lockObject)
{
     Counter += 1
}
    
risposta data 02.11.2013 - 09:14
fonte
0

Grazie per tutte le risposte e ora ho la risposta.

Dim total As Integer = 0
Dim numbers() = Enumerable.Range(1, 500).ToArray
Parallel.For(Of Integer)(0, numbers.Length, Function() 0, 
                         Function(j, [loop], subtotal)
                           For k = j + 1 To numbers.Count - 1
                             subtotal += 1
                           Next
                           Return subtotal
                         End Function,
                         Function(x) Interlocked.Add(total, x))
    
risposta data 25.11.2013 - 08:15
fonte

Leggi altre domande sui tag