Kopieren eine struct mit Zeigern auf CUDA-Gerät

Arbeite ich an einem Projekt, wo ich mein CUDA-Gerät, um Berechnungen auf eine struct mit Zeigern.

typedef struct StructA {
    int* arr;
} StructA;

Wenn ich Speicher für das struct und dann kopieren Sie Sie auf das Gerät, wird es kopiert nur die Struktur und nicht der Inhalt der pointer. Jetzt arbeite ich, um dieses durch die Zuweisung der Zeiger zuerst, dann legen Sie die host-Struktur zu verwenden, dass die neuen Zeiger (die sich auf die GPU). Das folgende Codebeispiel beschreibt diesen Ansatz mit der struct von oben:

#define N 10

int main() {

    int h_arr[N] = {1,2,3,4,5,6,7,8,9,10};
    StructA *h_a = (StructA*)malloc(sizeof(StructA));
    StructA *d_a;
    int *d_arr;

    //1. Allocate device struct.
    cudaMalloc((void**) &d_a, sizeof(StructA));

    //2. Allocate device pointer.
    cudaMalloc((void**) &(d_arr), sizeof(int)*N);

    //3. Copy pointer content from host to device.
    cudaMemcpy(d_arr, h_arr, sizeof(int)*N, cudaMemcpyHostToDevice);

    //4. Point to device pointer in host struct.
    h_a->arr = d_arr;

    //5. Copy struct from host to device.
    cudaMemcpy(d_a, h_a, sizeof(StructA), cudaMemcpyHostToDevice);

    //6. Call kernel.
    kernel<<<N,1>>>(d_a);

    //7. Copy struct from device to host.
    cudaMemcpy(h_a, d_a, sizeof(StructA), cudaMemcpyDeviceToHost);

    //8. Copy pointer from device to host.
    cudaMemcpy(h_arr, d_arr, sizeof(int)*N, cudaMemcpyDeviceToHost);

    //9. Point to host pointer in host struct.
    h_a->arr = h_arr;
}

Meine Frage ist: Ist dies der Weg, es zu tun?

Es scheint wie eine Menge Arbeit, und ich erinnere Sie daran, dass dies eine sehr einfache Struktur. Wenn mein struct enthalten eine Menge von Zeigern oder Strukturen mit dem Pointer selbst, der code für die Zuweisung und Kopie ist Recht umfangreich und verwirrend.

Die Schritte 7 und 9 sind überflüssig, aber sonst ist ziemlich viel, wie es ist. Als Antwort unten sagt, Sie sind am besten gedient, durch die Vermeidung von komplexen, Zeiger-basierte Datenstrukturen auf der GPU. Die Leistung auf der GPU ist schlimmer, und die APIs sind wirklich nicht dafür geeignet.
Ich kann sehen, dass der Schritt 7 ist überflüssig, aber warum Schritt 9?
gut h_a ist (oder sollte sein) ein "Bild" der device-Struktur gehalten, die in dem host-Speicher. Die Zuordnung zu halten, einen Zeiger in dem host-Speicher ist wahrscheinlich eine Kombination von schlechte Praxis/falsch/device memory-leak-je nachdem, was Ihre wahren Absichten sind. Nachdem Sie kopiert den Inhalt d_a zurück h_a Sie haben "der Kreis" und sind wieder dort wo Sie begann.
Aber um die Kopie der struct korrekt an das Gerät muss ich den Zeiger von h_a zu d_arr (Schritt 4). Also, wenn ich kopieren Sie die Daten zurück, auch ich habe die Zeiger in h_a dem array habe ich nur kopiert. Ich bin damit einverstanden, dass der Schritt 7 ist überflüssig in meinem Beispiel oben, weil es keine anderen Daten in der Struktur, aber wenn es war, dass Schritt würde nicht überflüssig sein.. Oder bin ich komplett Irre?
Danke, tahatmat, für die Bereitstellung von uns mit diesem Muster kopieren von Strukturen über host-und device-Erinnerungen hin und her. Aber ich glaube, es ist nur erwähnenswert, einen zweiten Weg, der scheint etwas konsequenter und hilft zu vermeiden, die Umsetzung Schritt 9. Die spezifische Funktion cudaMemcpy() erlaubt tatsächlich die Dereferenzierung Gerät Zeiger in einen host-Codepunkt in einer solchen Art und Weise: Sie Schritt 4 überspringen und nach dem kopieren h_a zu d_a auf Schritt 5 kopieren Sie manuell jedes Gerät pointer-Adresse in d_a, wie diese: cudaMemcpy(&(d_a->arr) &(d_arr), sizeof(int*), cudaMemcpyHostToDevice). Wieder, "d_a->arr" legit ist

InformationsquelleAutor Thorkil Holm-Jacobsen | 2012-02-16

Schreibe einen Kommentar