Untitled
Untitled
Untitled
Sie wollen auch ein ePaper? Erhöhen Sie die Reichweite Ihrer Titel.
YUMPU macht aus Druck-PDFs automatisch weboptimierte ePaper, die Google liebt.
}<br />
}<br />
3.1 Parallelität auf Schleifenebene 33<br />
for(unsigned int i = 0; i < x.size(); ++i<br />
)<br />
{<br />
y[i] += a * x[i];<br />
}<br />
Der Effekt ist nicht der beabsichtigte: Statt dass sich<br />
die Threads im Team die Arbeit untereinander aufteilten,<br />
führt jeder der Threads die gesamte Berechnung aus! Bei<br />
n Threads wird die ganze Schleife also unnötigerweise nmal<br />
ausgeführt. Im besten Fall wird n-mal a ∗ x[i] zu y[i]<br />
addiert. Hinzu kommen mögliche unbeabsichtige Seiteneffekte,<br />
da die Threads unsynchronisiert auf die gemeinsam<br />
genutzten Vektoren zugreifen und es so zu einer Wettlaufsituation<br />
(engl. Race Condition) kommen kann (siehe hierzu<br />
auch Kapitel 1.2.1). Dies ist z. B. dann der Fall, wenn zwei<br />
parallele Threads den gleichen Wert für die Schleifenvariable<br />
i zur Zeit bearbeiten, den Wert von y[i] jeweils gelesen<br />
haben und davor stehen, den neuen Wert von y[i] zu schreiben.<br />
Beide Threads arbeiten in diesem Fall mit dem alten<br />
Wert von y[i]. Die Änderung durch den Thread, der zuerst<br />
seinen neuen, um a ∗ x[i] erhöhten Wert nach y[i] schreibt,<br />
wird durch den nachfolgenden Thread überschrieben. Die<br />
Änderung von y[i] durch den ersten Thread geht also verloren.<br />
Vielmehr benötigt man für dieses Programm das Arbeit<br />
aufteilende Pragma #pragma omp for, um dem Compiler<br />
mitzuteilen, die Schleifendurchläufe auf mehrere Threads<br />
innerhalb des Teams, das den parallelen Abschnitt ausführt,<br />
aufzuteilen, wie in Listing 3.3 gezeigt.