2010-11-14 15 views
11

Jestem nowy w CUDA C i próbuję przekazać strukturę jądra do jądra. Moja metoda działała bez zarzutu, gdy próbowałem ją ze strukturą zawierającą tylko ints, ale kiedy przełączam się na zmiennoprzecinkowe, otrzymuję bez znaczenia liczby jako wyniki. Zakładam, że ma to związek z wyrównaniem i próbowałem dołączyć __align__ wraz z deklaracją mojego typu, ale bezskutecznie. Czy ktoś może mi podać przykład tego, jak to się robi, lub podać alternatywne podejście? Próbuję skonfigurować go tak, aby można było łatwo dodawać lub usuwać pola bez zmiany niczego poza strukturą i jądrem. Mój kod:Przekazywanie struktur do jądra CUDA

typedef struct __align__(8) 
{ 
    float a, b; 
} point; 

__global__ void testKernel(point *p) 
{ 
    int i = blockIdx.x * blockDim.x + threadIdx.x; 
    p[i].a = 1.1; 
    p[i].b = 2.2; 
} 

int main(void) 
{ 
     // set number of points 
    int numPoints = 16, 
     gpuBlockSize = 4, 
     pointSize = sizeof(point), 
     numBytes  = numPoints * pointSize, 
     gpuGridSize = numPoints/gpuBlockSize; 

     // allocate memory 
    point *cpuPointArray = new point[numPoints], 
      *gpuPointArray = new point[numPoints]; 
    cpuPointArray = (point*)malloc(numBytes); 
    cudaMalloc((void**)&gpuPointArray, numBytes); 

     // launch kernel 
    testKernel<<<gpuGridSize,gpuBlockSize>>>(gpuPointArray); 

     // retrieve the results 
    cudaMemcpy(cpuPointArray, gpuPointArray, numBytes, cudaMemcpyDeviceToHost); 
    printf("testKernel results:\n"); 
    for(int i = 0; i < numPoints; ++i) 
    { 
     printf("point.a: %d, point.b: %d\n",cpuPointArray[i].a,cpuPointArray[i].b); 
    } 

     // deallocate memory 
    free(cpuPointArray); 
    cudaFree(gpuPointArray); 

    return 0; 
} 
+0

punkt * gpuPointArray = new ... wydaje mi się nie tak? Przydzielasz na hoście, a potem robi cudaMalloc na urządzeniu ... – Bart

+0

Czy nie muszę przydzielać pamięci przed przekazaniem jej jako argumentu do jądra? Pozostawienie linii cudaMalloc daje "nieokreśloną awarię uruchamiania". Mogłabym również ustawić wartość parametru gpuPointArray na NULL, ale nie zmienia to oryginalnego wyniku. – Paul

+3

Absolutnie. Potrzebujesz cudaMalloc. Nie potrzebujesz jednak "nowego". To samo dotyczy cpuPointArray. Użyj malloc i free (programujesz C) i nie używaj nowego tutaj. (Nigdy nie mieszaj nowych usunięć malloc i darmowych) – Bart

Odpowiedz

3

Zapraszamy do obejrzenia jak to się robi w nagłówku vector_types.h który przychodzi w CUDA to katalog. To powinno już dać ci kilka wskazówek.

Jednak głównym problemem jest tutaj %d w twoich połączeniach printf. Próbujesz wydrukować teraz pływaki, a nie liczby całkowite. Tak więc ci naprawdę powinni używać zamiast tego %f.

+0

Ok, obejrzałem vector_types.h, i próbowałem zrobić to, co zrobili: 'typedef struct __align __ (2 * sizeof (float)) point {' ..., but nadal daje taki sam wynik. Czy jest coś jeszcze, co powinienem zobaczyć? – Paul

+2

Nawiasem mówiąc, zmień swój printf, aby używał% f zamiast% d ... czy to coś zmieni? Próbujesz teraz drukować pływaki, nie int ... – Bart

+1

Ha! Tak to się stało, dzięki. Czasami oczywiste jest najłatwiejsze do przeoczenia ... – Paul

15

Ponieważ wydaje się, że nie ma przyzwoitej dokumentacji, jak to zrobić, pomyślałem, że opublikuję tutaj ostateczny, poprawiony kod. Okazuje się, że część __align__ również była niepotrzebna, a problemem było użycie% d w printf podczas próby drukowania float.

#include <stdlib.h> 
#include <stdio.h> 

typedef struct 
{ 
    float a, b; 
} point; 

__global__ void testKernel(point *p) 
{ 
    int i = blockIdx.x * blockDim.x + threadIdx.x; 
    p[i].a = 1.1; 
    p[i].b = 2.2; 
} 

int main(void) 
{ 
     // set number of points 
    int numPoints = 16, 
     gpuBlockSize = 4, 
     pointSize = sizeof(point), 
     numBytes  = numPoints * pointSize, 
     gpuGridSize = numPoints/gpuBlockSize; 

     // allocate memory 
    point *cpuPointArray, 
      *gpuPointArray; 
    cpuPointArray = (point*)malloc(numBytes); 
    cudaMalloc((void**)&gpuPointArray, numBytes); 

     // launch kernel 
    testKernel<<<gpuGridSize,gpuBlockSize>>>(gpuPointArray); 

     // retrieve the results 
    cudaMemcpy(cpuPointArray, gpuPointArray, numBytes, cudaMemcpyDeviceToHost); 
    printf("testKernel results:\n"); 
    for(int i = 0; i < numPoints; ++i) 
    { 
     printf("point.a: %f, point.b: %f\n",cpuPointArray[i].a,cpuPointArray[i].b); 
    } 

     // deallocate memory 
    free(cpuPointArray); 
    cudaFree(gpuPointArray); 

    return 0; 
} 
Powiązane problemy