parallel.foreach funktioniert, aber warum?

7

Kann jemand erklären, warum dieses Programm den korrekten Wert für sqrt_min zurückgibt?

%Vor%     
user1193134 06.02.2012, 19:44
quelle

5 Antworten

13

Es funktioniert durch reines Glück. Manchmal, wenn Sie es ausführen, sind Sie glücklich , dass die nicht-atomaren Lese- und Schreibvorgänge im Double nicht zu "zerrissenen" Werten führen. Manchmal sind Sie glücklich , dass die nicht-atomaren Tests und Sets gerade den richtigen Wert einstellen, wenn das Rennen stattfindet. Es gibt keine Garantie, dass dieses Programm zu einem bestimmten Ergebnis führt.

    
Eric Lippert 06.02.2012, 19:49
quelle
5

Ihr Code ist nicht sicher; es funktioniert nur zufällig.

Wenn zwei Threads if gleichzeitig ausführen, wird eines der Minima überschrieben:

  • sqrt_min = 6
  • Thema A: sqrt = 5
  • Thema B: sqrt = 4
  • Thread A gibt if ein
  • Thread B gibt if ein
  • Thread B weist sqrt_min = 4 zu
  • Thread A weist sqrt_min = 5 zu

Auf 32-Bit-Systemen sind Sie auch anfällig für Lese- / Schreib-Tearing.

Es wäre möglich dies mit Interlocked.CompareExchange in einer Schleife sicher zu machen.

    
SLaks 06.02.2012 19:46
quelle
4

Warum Ihr ursprünglicher Code defekt ist, überprüfen Sie die anderen Antworten, ich werde das nicht wiederholen.

Multithreading ist am einfachsten, wenn kein Schreibzugriff auf den gemeinsamen Status besteht. Zum Glück kann Ihr Code so geschrieben werden. Parallel linq kann in solchen Situationen nett sein, aber manchmal ist der Overhead zu groß.

Sie können Ihren Code in Folgendes umschreiben:

%Vor%

In Ihrem speziellen Problem ist es schneller, die Operationen Min und Sqrt zu umgehen, was möglich ist, weil Sqrt monoton ansteigt.

%Vor%     
CodesInChaos 06.02.2012 20:51
quelle
3

Dein Code funktioniert nicht wirklich: Ich habe ihn 100-mal in einer Schleife ausgeführt und es ist einmal auf meinem 8-Kern-Computer gescheitert, diese Ausgabe zu erzeugen:

%Vor%

Ich habe die Läufe verkürzt, damit der Fehler schneller erscheint.

Hier sind meine Änderungen:

%Vor%

Dies ist kein Zufall, wenn man die fehlende Synchronisation um das Lesen und Schreiben einer gemeinsamen Variablen in Betracht zieht.

    
dasblinkenlight 06.02.2012 19:55
quelle
2

Wie andere gesagt haben, funktioniert das nur auf Basis von Scherglück. Sowohl der OP als auch andere Poster hatten Schwierigkeiten, die Race Condition zu schaffen. Das ist ziemlich einfach zu erklären. Der Code generiert viele Race-Bedingungen, aber die überwiegende Mehrheit von ihnen (99,9999% um genau zu sein) sind irrelevant. Am Ende des Tages zählt nur, dass 0 das Min-Ergebnis sein sollte. Wenn Ihr Code denkt, dass Wurzel 5 größer als Wurzel 6 ist oder dass Wurzel 234 größer als Wurzel 235 ist, wird es immer noch nicht brechen. Es muss eine Race-Bedingung geben, speziell mit der Iteration, die 0 erzeugt. Die Wahrscheinlichkeit, dass eine der Iterationen eine Race-Bedingung mit einer anderen hat, ist sehr, sehr hoch. Die Wahrscheinlichkeit, dass die Iteration, die den letzten Gegenstand bearbeitet, eine Wettlaufbedingung hat, ist wirklich ziemlich niedrig.

    
Servy 06.02.2012 20:06
quelle