2010-09-13 5 views
10

Ich habe eine Klasse A, die ich überfordere Operator =. Allerdings ist es erforderlich, dass ich so etwas wie dies tun müssen:C++ flüchtige und Operatorüberlastung für CUDA-Anwendung

volatile A x; 
A y; 
x = y; 

, die einen Fehler ausgelöst beim Kompilieren

error: no operator "=" matches these operands 
     operand types are: volatile A = A 

Wenn ich flüchtig entfernt, es ist übersetzbar. Gibt es trotzdem eine solche kompiliert, ohne die "volatile" zu entfernen (und das Verhalten von volatile beibehalten)?


Im Grunde ist dies ein Programm, in dem CUDA ‚X‘ ist ein gemeinsam genutzter Speicher (alle Threads können ihren Wert zugreifen und diese ändern). Ich möchte, dass es "flüchtig" ist, um die Compileroptimierung zu vermeiden und den Wert wiederzuverwenden, anstatt auf die Speicheradresse zuzugreifen.

Mehr zu dem Problem: am Anfang A ist nur ein primitiver Typ, zB ganze Zahl, volatile funktionierte wie erwartet und verursacht kein Problem, jetzt möchte ich, dass es eine benutzerdefinierte Klasse (Integer 128-Bit zum Beispiel) . Ich bin mir nicht sicher, warum C++ in diesem Fall klagen, aber nicht mit primitiven Datentyp.

Vielen Dank im Voraus.

Antwort

7

Angenommen, die volatile Qualifikation ist erforderlich, müssen Sie einen flüchtigen Zuweisungsoperator zu A hinzufügen (A& A::operator=(const A&) volatile).

const_cast<A&>(x) = y wird es kompilieren, aber wird technisch undefiniertes Verhalten verursachen, und wird sicherlich die Garantien entfernen, die volatile gibt.

+0

Danke! Es ist kompiliert. aber schade :(, es gibt mir das gleiche Verhalten von nichtflüchtigen – w00d

+0

@iKid: Welches Verhalten erwartetest du von 'volatile'? –

+0

Ich fügte meiner Frage – w00d

2

volatile ist nicht viel Verwendung in C++ Threading (siehe Dave Butenhof Erklärung bei http://www.lambdacs.com/cpt/FAQ.html#Q56). Es reicht nicht aus, sicherzustellen, dass Ihr Programm die aus dem zentralen lokalen Cache geschriebenen Daten an einen Punkt löscht, an dem andere Programme die Aktualisierungen im gemeinsam genutzten Speicher sehen können, und heutzutage fast jeden Multi-Core-Prozess. Das ist ein ernstes Problem. Ich schlage vor, dass Sie geeignete Threading-Synchronisierungsmethoden verwenden, beispielsweise Boosts, wenn Ihre Übertragbarkeit es erfordert, oder vielleicht POSIX-Mutexe und Bedingungsvariablen, die Architektur-abhängige Techniken wie Speicherbarrieren oder atomare Operationen, die implizit Speicher zwischen Kernen synchronisieren.

Ich bin sicher, Sie wollen es schnell, aber schnell und instabil ist im Allgemeinen nicht so nützlich wie langsam und zuverlässig, vor allem wenn Sie ein Produkt versenden, das nur instabil auf der Hardware Ihres Kunden ist.

+0

Vor allem wenn man bedenkt, dass 'pthread_mutex'es unglaublich leicht sein können – doron

+0

Weil jeder auf POSIX läuft, amirite? – Puppy

+0

@DeadMG: Nein, weshalb wir portable Wrapper wie Boost.Thread und die C++ 0x Thread-Support-Bibliothek haben. –

2

Der Kommentar "flüchtig ist nicht viel in C++ threading" ist irrelevant für die Frage, die CUDA-spezifisch ist. volatile wird für die Warp-synchrone Codierung in CUDA benötigt.

1

Deklarieren einer Copykonstruktor

volatile A& operator=(volatile A&) volatile; 

für mich mit nvcc gearbeitet. Beachten Sie, dass Sie den nicht primitiven Typ möglicherweise nur als Referenz übergeben müssen. Andernfalls benötigen Sie mehr Kopierkonstruktoren, die flüchtige Instanzen in nichtflüchtige konvertieren, wenn der nicht-primitive Typ an einen nichtflüchtigen Parameter übergeben wird. Es läuft wirklich darauf hinaus, flüchtige Korrektheit zu etablieren (ähnlich wie const-Korrektheit).