Nach this link Verständnis, ich versuche, den Betrieb von Kernel-Code zu verstehen (es gibt 2 Versionen dieses Kernel-Code, eine mit volatile local float *source
und das andere mit volatile global float *source
, das heißt local
und global
Versionen). Unten Ich nehme local
Version:das Verfahren zur OpenCL Reduktion auf float
float sum=0;
void atomic_add_local(volatile local float *source, const float operand) {
union {
unsigned int intVal;
float floatVal;
} newVal;
union {
unsigned int intVal;
float floatVal;
} prevVal;
do {
prevVal.floatVal = *source;
newVal.floatVal = prevVal.floatVal + operand;
} while (atomic_cmpxchg((volatile local unsigned int *)source, prevVal.intVal, newVal.intVal) != prevVal.intVal);
}
Wenn ich gut verstehen, jede Arbeit Punkt Aktien der Zugriff auf source
Variable dank der Qualifikation „volatile
“, nicht wahr?
Danach, wenn ich ein Arbeitselement nehme, fügt der Code operand
Wert zu newVal.floatVal
Variable hinzu. Dann rufe ich nach dieser Operation die Funktion atomic_cmpxchg
auf, die prüft, ob die vorherige Zuweisung (preVal.floatVal = *source;
und newVal.floatVal = prevVal.floatVal + operand;
) erfolgt ist, d. H. Durch Vergleichen des in der Adresse source
gespeicherten Wertes mit der preVal.intVal
.
Während dieser atomaren Operation (die nicht unter die Definition UNINTERRUPTIBLE wird), als Wert bei source
gespeichert aus prevVal.intVal
unterschiedlich ist, wird der neue Wert bei source
gespeichert ist newVal.intVal
, die eigentlich ein Schwimmer ist (weil es auf 4 Bytes codiert, wie ganze Zahl).
Können wir sagen, dass jedes Work-Item einen Mutex-Zugriff (ich meine einen gesperrten Zugriff) auf den Wert source address
hat.
Aber für each work-item
Thread, gibt es nur eine Iteration in die while loop
?
Ich denke, es wird eine Iteration geben, weil der Vergleich "*source== prevVal.int ? newVal.intVal : newVal.intVal
" immer newVal.intVal
Wert auf Wert bei source address
gespeichert wird, nicht wahr?
Jede Hilfe ist willkommen, weil ich nicht alle Feinheiten dieses Tricks für diesen Kernel-Code verstanden habe.
UPDATE 1:
Sorry, ich alle Subtilitäten fast verstehen, vor allem im while loop
:
Ersten Fall: für einen bestimmten einzelnen Thread, vor dem Aufruf von atomic_cmpxchg, wenn prevVal.floatVal
ist immer noch gleich *source
, dann atomic_cmpxchg
wird den Wert in source
Zeiger ändern und den Wert in old pointer
, die gleich prevVal.intVal
enthält, zurückgegeben, so dass wir von derbrechen.
Zweiter Fall: Wenn zwischen derprevVal.floatVal = *source;
Anweisung und dem Aufruf von atomic_cmpxchg
, *source
der Wert (von einem anderen Thread ??), dann kehrt atomic_cmpxchg old
Wert, der nicht geändert hat prevVal.floatVal
mehr gleich ist, so dass der Zustand in while loop
ist wahr und wir bleiben in dieser Schleife, bis die vorherige Bedingung nicht mehr überprüft wird.
Meine Interpretation ist richtig?
Dank
Sorry, wenn dies für Sie liegt auf der Hand (ich glaube, ich voll und ganz verstehe die Frage nicht noch) nicht, aber ... die 'while' Schleife ist eine Standardmethode Unteilbarkeit zu erreichen, wie von https: //en.wikipedia. org/wiki/compare-and-Swap – Marco13
Dies ist eine klassische vergleichen Austauschschleife, wie von Marco erwähnt. Ignoriere die Gewerkschaftstricks aus Gründen der Übersichtlichkeit, sie sind nur hier für die Art Punning. Auch wenn Sie OpenCL 2+ haben, gibt es eingebaute Atomics für Floats. –
: Marco13,: Aldwin ok, danke. Nehmen wir einen einfachen Fall mit 2 Threads. Wenn die erste in der while-Schleife ist, dann, bis die zweite ändert den Wert von „prevVal.floatVal“, die while-Schleife für den ersten Thread dauert, nicht wahr? Aber in diesem Fall ist die Operation der Inkrementierung "prevVal.floatVal + operand;" unendlich wird, und so gespeicherte Wert bei der Adresse „source“ (it, bis zweiten Gewindeanschlag) ist sehr hoch, weil ich mit einer sehr großen Anzahl von „Operanden“ Werten tue Summierung.Grüße – youpilat13