2016-06-27 8 views
0

Ich verwende die CUDA API/cuFFT API. Um Daten vom Host zur GPU zu übertragen, verwende ich die cudaMemcpy-Funktionen. Ich benutze es wie unten. len ist die Anzahl der Elemente in dataReal und dataImag.Zeiger Arithmetik auf void * Zeiger

void foo(const double* dataReal, const double* dataImag, size_t len) 
{ 
    cufftDoubleComplex* inputData; 
    size_t allocSizeInput = sizeof(cufftDoubleComplex)*len; 
    cudaError_t allocResult = cudaMalloc((void**)&inputData, allocSizeInput); 

    if (allocResult != cudaSuccess) return; 

    cudaError_t copyResult; 

    coypResult = cudaMemcpy2D(static_cast<void*>(inputData), 
           2 * sizeof (double), 
           static_cast<const void*>(dataReal), 
           sizeof(double), 
           sizeof(double), 
           len, 
           cudaMemcpyHostToDevice); 

    coypResult &= cudaMemcpy2D(static_cast<void*>(inputData) + sizeof(double), 
           2 * sizeof (double), 
           static_cast<const void*>(dataImag), 
           sizeof(double), 
           sizeof(double), 
           len, 
           cudaMemcpyHostToDevice); 

    //and so on. 
} 

Ich bin mir bewusst, dass Zeigerarithmetik auf void Zeiger ist eigentlich nicht möglich. das zweite cudaMemcpy2D funktioniert aber trotzdem. Ich bekomme immer noch eine Warnung vom Compiler, aber es funktioniert richtig.

Ich habe versucht mit static_cast < char *> aber das funktioniert nicht, da cammleDoubleComplex * kann nicht statisch auf Char * gegossen werden.

Ich bin ein wenig verwirrt, warum die zweite cudaMemcpy mit dem Zeiger Arithmetik auf void funktioniert, wie ich es verstehe, sollte nicht. Nimmt der Compiler implizit an, dass der hinter void * stehende Datentyp ein Byte lang ist?

Sollte ich da etwas ändern? Verwenden Sie eine reinterpret_cast < char *> (inputData) zum Beispiel?

Auch während der Zuweisung verwende ich die alten C-Stil (void **) Cast. Ich mache das, weil ich einen "ungültigen static_cast von cummttDoubleComplex ** zu void **" bekomme. Gibt es eine andere Möglichkeit, dies richtig zu machen?

FYI: Link to cudaMemcpy2D Doc

Link to cudaMalloc Doc

+1

Try 'static_cast (& (inputData-> y)) '(anstelle von' + ... ') und benutze' sizeof (cammtDoubleComplex) 'anstelle von' 2 * sizeof (cammtDoubleComplex) '(auch wenn es der gleiche Wert ist, ist der erste allgemeiner)). – Holt

+0

Es ist nicht klar, warum du das Gefühl hast, etwas zu werfen. 'cudaMalloc' verlangt nicht, dass du auf' void ** 'wirfst und nie braucht' cudaMemcpy2D', dass du auf 'void *' wirfst. –

+0

cudaMalloc erwartet eine Lücke ** und cudaMemcpy2D erwartet eine Lücke *. Ich weiß in der Tat, dass beide an Bytes und nicht an Typen arbeiten. Eigentlich hätte ich gerne ein Char *, aber das will ich nicht von der CUDA-API. – FreddyKay

Antwort

1

Sie nicht arithmetische Operationen auf void* tun können, da arithmetische Operationen auf Zeiger auf die Größe der spitzen Gegenständen basiert (und sizeof(void) nicht wirklich etwas bedeuten).

Ihr Code kompiliert wahrscheinlich dank einer Compiler-Erweiterung, die arithmetische Operationen auf void* als arithmetische Operation auf char* behandelt.

In Ihrem Fall, werden Sie wahrscheinlich nicht arithmetische Operationen benötigen, sollte die folgende Arbeit (und robuster sein): einfach

coypResult &= cudaMemcpy2D(static_cast<void*>(&inputData->y), 
          sizeof (cufftDoubleComplex), 

Seit cufftDoubleComplex ist:

struct __device_builtin__ __builtin_align__(16) double2 
{ 
    double x, y; 
}; 
+0

Danke für deinen Vorschlag. Ich hätte das auch sehen können, aber ich war es nicht ;-). Versuchen Sie dies so schnell wie möglich und markieren Sie Ihre Antwort als die Antwort, wenn es funktioniert. Prost! – FreddyKay