Ich verwende OpenMP und muss die fetch-and-add-Operation verwenden. OpenMP stellt jedoch keine entsprechende Anweisung / Aufruf bereit. Ich möchte die maximale Portabilität beibehalten, daher möchte ich mich nicht auf Compiler-Intrinsics verlassen.
Ich bin eher auf der Suche nach einer Möglichkeit, die atomaren Operationen von OpenMP zu nutzen, um das zu implementieren, aber ich habe eine Sackgasse erreicht. Kann das überhaupt gemacht werden? N.B., der folgende Code fast macht was ich will:
%Vor% Fast - aber nicht ganz, da ich wirklich den alten Wert von x
brauche. fetch_and_add
sollte so definiert werden, dass dasselbe Ergebnis wie das folgende Ergebnis erzielt wird (nur nicht-locking):
(Eine äquivalente Frage könnte für compare-and-swap gestellt werden, aber eine kann in Bezug auf die andere implementiert werden, wenn ich mich nicht irre.)
Ab openmp 3.1 gibt es Unterstützung für atomare Updates, Sie können entweder den alten Wert oder den neuen Wert erfassen. Da wir den Wert aus dem Speicher holen müssen, um ihn zu inkrementieren, macht es nur Sinn, dass wir von einem CPU-Register darauf zugreifen und es in eine thread-private-Variable einfügen können.
Wenn Sie gcc (oder g ++) verwenden, gibt es eine gute Möglichkeit, atomare Built-ins nachzuschlagen: Ссылка
Ich denke, der C / C ++ - Compiler von Intel hat dafür ebenfalls Unterstützung, aber ich habe es nicht ausprobiert.
Für den Augenblick (bis openmp 3.1 implementiert ist) habe ich Inline-Wrapper-Funktionen in C ++ benutzt, wo Sie auswählen können, welche Version zur Kompilierzeit verwendet werden soll:
%Vor%Update: Ich habe gerade den C ++ - Compiler von Intel ausprobiert, er unterstützt momentan openmp 3.1 (Atomic Capture ist implementiert). Intel bietet die kostenlose Nutzung seiner Compiler in Linux für nichtkommerzielle Zwecke an:
GCC 4.7 wird openmp 3.1 unterstützen, wenn es schließlich veröffentlicht wird ... hoffentlich bald:)
Wenn Sie den alten Wert von x erhalten möchten und a nicht geändert wird, verwenden Sie (x-a) als alten Wert:
%Vor%UPDATE: Es war nicht wirklich eine Antwort, weil x nach Atom durch einen anderen Thread geändert werden kann. Es scheint also unmöglich zu sein, universelles "Fetch and Add" mit OMP Pragmas zu machen. Als universell meine ich Operation, die von jedem Ort des OMP-Codes leicht verwendet werden kann.
Sie können omp_*_lock
functions verwenden, um ein Atom zu simulieren:
typedef struct {omp_lock_t lock; int Wert;} atomic_simulated_t;
%Vor%Dies ist hässlich und langsam (macht 2 atomare Operationen statt 1). Aber wenn Sie möchten, dass Ihr Code sehr portabel ist, wird er in allen Fällen nicht der schnellste sein.
Sie sagen "wie folgt (nur nicht verriegeln)". Aber was ist der Unterschied zwischen "non-locking" -Operationen (mit dem Präfix "LOCK" der CPU, LL / SC oder etc) und Locking-Operationen (die selbst mit mehreren atomaren Anweisungen implementiert werden, busy loop für kurze Wartezeit auf Entsperren und OS schlafen für lange Wartezeiten)?
Tags und Links c++ openmp atomic compare-and-swap