2013-04-20 15 views
9

Welches ist der beste Weg, Konstanten in CUDA zu verwenden?Konstanten mit CUDA verwenden

Eine Möglichkeit ist, Konstanten in konstanten Speicher zu definieren, wie:

// CUDA global constants 
__constant__ int M; 

int main(void) 
{ 
    ... 
    cudaMemcpyToSymbol("M", &M, sizeof(M)); 
    ... 
} 

eine alternative Art und Weise wäre es, den C-Vorprozessor zu verwenden:

#define M = ... 

Ich denke, würde Konstanten mit dem C-Vorprozessor definiere ist viel schneller. Welche Vorteile bietet die Verwendung des Konstantenspeichers auf einem CUDA-Gerät?

+1

Konstanten, die zur Kompilierzeit bekannt sind, sollten mit Präprozessor-Makros (d. H. 'Define') definiert werden. In anderen Fällen kann "__constant__" [Variablen] (http://docs.nvidia.com/cuda/cuda-c-programming-guide/index.html#constant) eine Option sein, mit der der CUDA-Programmierer den Code optimiert, auf den zugegriffen wird berechnete Variablen, die sich nicht ändern. Beachten Sie, dass die Verwendung von '" M "' zum Verweis auf ein Symbol in cuda 5 nicht länger gültig ist. –

+0

Es wäre interessant zu wissen, wie groß der Laufzeitunterschied zwischen diesen beiden Möglichkeiten ist. Ich arbeite derzeit an einigen cfd-Codes und möchte die Parameter als Optionen an das Programm übergeben, daher wäre es notwendig, den ersten Ansatz zu verwenden. Auf der anderen Seite, wenn ich Preprozessor-Makros verwende, wäre dies nicht möglich. – jrsm

+0

Da Ihr zweites Beispiel keinen Maschinencode generiert, ist das keine vernünftige Frage. Sie müssen ein tatsächliches Laufzeitnutzungsszenario aufstellen, um diese Frage zu verstehen. Für die anfängliche Ladung eines einzelnen skalaren Direktwerts in eine Variable oder ein Register ist die zweite Methode immer schneller. –

Antwort

9
  1. Konstanten, die zum Zeitpunkt der Kompilierung bekannt sind, soll (z #define) oder über C/C++ const Variablen auf globalem/Dateiumfang mit Präprozessormakros definiert werden.
  2. Verwendung von __constant__ memory kann für Programme nützlich sein, die bestimmte Werte verwenden, die sich für die Dauer des Kernels nicht ändern und für die bestimmte Zugriffsmuster vorhanden sind (z. B. greifen alle Threads gleichzeitig auf denselben Wert zu). Dies ist nicht besser oder schneller als Konstanten, die die Anforderungen von Punkt 1 oben erfüllen.
  3. Wenn die Anzahl der Entscheidungen von einem Programm ist relativ klein an der Zahl, und diese Entscheidungen Ausführung, für zusätzliche Kompilierung-Optimierung ein möglicher Ansatz templated code/kernels
+2

Die Verwendung von C/C++ - Konstanten, Präprozessor-Makros oder C++ - Templates kann aus mehreren Gründen schneller sein als die Verwendung von __constant__ memory: 1. Der Compiler kann zusätzliche Optimierungen anwenden und 2. die Konstante kann als sofortiger Befehl in den Befehl eingebettet werden. Konstante Cache-Zugriffe können den konstanten Cache verpassen und zusätzliche Latenz hinzufügen. –

+0

Werden '# define'd Konstanten nicht-trivialer Typen wegen Konstruktoraufrufen in jedem Thread nicht langsam sein? –

4

Regular C/wäre die Verwendung beeinflussen Kernel vorgenommen werden C++ - Stil-Konstanten: In CUDA C (selbst eine Modifikation von C99) sind Konstanten absolute Kompilierzeit-Entitäten. Dies ist nicht überraschend, da die Menge an Optimierung, die in NVCC stattfindet, angesichts der Art der GPU-Verarbeitung SEHR involviert ist.

#define: Makros sind wie immer sehr unelegant, aber in einer Prise nützlich.

Der __constant__ Variablenbezeichner ist jedoch ein völlig neues Tier und meiner Meinung nach eine Fehlbezeichnung. Ich werde hinstellen, was Nvidia here im Raum unten:

Die __constant__ Qualifier, verwendet gegebenenfalls zusammen mit __device__, erklärt eine Variable, dass:

  • Resides in konstanten Speicherplatz,
  • Hat die Lebensdauer einer Anwendung,
  • Ist von allen Threads im Grid und vom Host über die Laufzeitbibliothek (cudaGetSymbolAddress()/) zugänglich 10 cudaGetSymbolSize()/cudaMemcpyToSymbol()/cudaMemcpyFromSymbol()).

Nvidias Dokumentation gibt an, dass bei __constant__Register Ebene Geschwindigkeit verfügbar ist (nahe Null Latenz), sofern sie die gleiche Konstante ist, die von allen Fäden eines Kett- zugegriffen wird.

Sie werden im CUDA-Code auf globaler Ebene deklariert. JEDOCH basierend auf persönlicher (und momentan laufender) Erfahrung, müssen Sie mit diesem Spezifizierer vorsichtig sein, wenn es um eine separate Kompilierung geht, wie zum Beispiel die Trennung Ihres CUDA-Codes (.cu und.cuh-Dateien) aus Ihrem C/C++ - Code, indem Wrapper-Funktionen in C-Style-Header eingefügt werden.

Im Gegensatz zu herkömmlichen "Konstanten" angegebenen Variablen werden diese jedoch zur Laufzeit vom Host-Code initialisiert, der Gerätespeicher zuweist und schließlich den Kernel startet. Ich wiederhole, ich arbeite derzeit Code, der zeigt diese können zur Laufzeit mit cudaMemcpyToSymbol() vor der Kernel-Ausführung festgelegt werden.

Sie sind ziemlich handlich, um die geläufigste L1-Cache-Level-Geschwindigkeit zu sagen, die für den Zugriff garantiert ist.

Verwandte Themen