2012-04-15 12 views
4

Ich versuche, ein CUDA-Projekt so weit wie möglich zu einem OO-Design zu machen. In dem Moment, fand die Lösung, die ich durch eine Struct unter Verwendung der Daten zu kapseln und für jede Methode, die einige GPU-Verarbeitung, die Umsetzung der drei Funktionen benötigt notwendig:Was ist die beste Möglichkeit, CUDA-Kernel zu kapseln?

  1. Die Methode, die durch die aufgerufen wird Objekt.
  2. A __ __ global Funktion, die eine __ __ Gerät Methode dieses struct nennen.
  3. Ein __ Gerät __ Methode innerhalb der Struktur.

Ich gebe Ihnen ein Beispiel. Nehmen wir an, ich muss eine Methode implementieren, um einen Puffer in einer Struktur zu initialisieren. Es wäre sieht aus wie etwas wie folgt aus:

struct Foo 
{ 
    float *buffer; 
    short2 buffer_resolution_; 
    short2 block_size_; 
    __device__ initBuffer() 
    { 
     int x = blockIdx.x * blockDim.x + threadIdx.x; 
     int y = blockIdx.y * blockDim.y + threadIdx.y; 
     int plain_index = (y * buffer_resolution.x) + x; 
     if(plain_index < buffer_size) 
     buffer[plain_index] = 0; 
    } 
    void init(const short2 &buffer_resolution, const short2 &block_size) 
    { 
     buffer_resolution_ = buffer_resolution; 
     block_size_ = block_size; 
     //EDIT1 - Added the cudaMalloc 
     cudaMalloc((void **)&buffer_, buffer_resolution.x * buffer_resolution.y); 
     dim3 threadsPerBlock(block_size.x, block_size.y); 
     dim3 blocksPerGrid(buffer_resolution.x/threadsPerBlock.x, buffer_resolution.y/threadsPerBlock.y) 
     initFooKernel<<<blocksPerGrid, threadsPerBlock>>>(this); 
    } 
} 

__global__ initFooKernel(Foo *foo) 
{ 
    foo->initBuffer(); 
} 

Ich brauche das zu tun, weil aussieht, dass ich kippe ein __ global __ innerhalb der Struktur erklären. Ich habe diesen Weg anhand einiger Opensource-Projekte kennengelernt, aber es ist sehr schwierig, drei Funktionen zur Implementierung jeder gekapselten GPU-Methode zu implementieren. Also, meine Frage ist: Ist das der beste/einzige Ansatz möglich? Ist das überhaupt ein GÜLTIGER Ansatz?

EDIT1: Ich habe vergessen, den cudaMalloc vor dem Aufruf von initFooKernel den Puffer zuzuordnen. Behoben.

+0

CUDA unterstützt nur interne Verbindungen, daher bin ich mir nicht sicher, welchen Vorteil Sie mit dieser Art von Design erwarten. – talonmies

+0

Nun, ich möchte in der Lage sein, Foo-Methoden aufzurufen, auch wenn sie jeden Kernel als Standard-C++ aufrufen müssen. In diesem Fall wäre ich in der Lage, Foo f zu nennen; f.init (res, Größe); Außerdem kann ich die Strukturattribute innerhalb der __device__ Methoden verwenden. –

+0

Ich würde gerne ein vollständiges funktionierendes Beispiel sehen, das auf dem von Ihnen geposteten Pseudocode basiert, weil ich nicht sehe, wie es funktionieren könnte. – talonmies

Antwort

3

Ist das Ziel, Klassen zu erstellen, die CUDA verwenden, während sie wie normale Klassen von außen aussehen?

Wenn ja, um zu erweitern, was O'Conbhui sagte, können Sie einfach C-Stil-Aufrufe für die CUDA-Funktionalität erstellen und dann eine Klasse erstellen, die diese Aufrufe umschließt.

In einer .cu-Datei würden Sie also Definitionen für Texturreferenzen, Kernel, C-Style-Funktionen, die die Kernel aufrufen, und C-Style-Funktionen setzen, die GPU-Speicher zuordnen und freigeben. In Ihrem Beispiel würde dies eine Funktion beinhalten, die einen Kernel aufruft, der den GPU-Speicher initialisiert.

Anschließend importieren Sie in einer entsprechenden CPP-Datei eine Kopfzeile mit Deklarationen für die Funktionen in der .cu-Datei, und Sie definieren Ihre Klasse. Im Konstruktor rufen Sie die .cu-Funktion auf, die CUDA-Speicher zuweist und andere CUDA-Ressourcen wie z. B. Texturen einrichtet, einschließlich Ihrer eigenen Speicherinitialisierungsfunktion. Im Destruktor rufen Sie die Funktionen auf, die die CUDA-Ressourcen freigeben. In Ihren Member-Funktionen rufen Sie die Funktionen auf, die Kernel aufrufen.

Verwandte Themen