Ошибка сегментации в CUDA

#cuda

Вопрос:

Я получаю ошибку сегментации (сброс ядра) при запуске этого кода.

Я знаю, что проблема в cudaMalloc, но я понятия не имею, как ее решить. Я только начал изучать программирование на CUDA и не знаком с ним. Я работаю над wsl, если это имеет значение.

 #include<stdio.h>
#define SIZE 20
__global__ void VectorAdd(int *a,int *b,int *c,int n){
    int i = threadIdx.x;
    if(i<n)
        c[i]=a[i] b[i];
}
int main(){
    int *a,*b,*c;
    cudaMalloc((void**)amp;a,SIZE *sizeof(int));
    cudaMalloc((void**)amp;b, SIZE *sizeof(int));
    cudaMalloc((void**)amp;c,SIZE *sizeof(int));

    for (int i=1;i<SIZE;i  ){
        a[i]=i;
        b[i]=i;
        c[i]=0;
    }

    VectorAdd<<<1, SIZE>>>(a,b,c,SIZE);
    cudaDeviceSynchronize();

    for(int i=1;i<SIZE;i  ){
        printf("%d n",c[i]);
    }

    cudaFree(a);
    cudaFree(b);
    cudaFree(c);

    return 0;
}
 

Комментарии:

1. На распределение, созданное с использованием cudaMalloc , нельзя напрямую ссылаться из кода хоста, как вы пытаетесь сделать здесь: a[i]=i; . Существует пример кода CUDA, который называется vectorAdd и дает типичный способ справиться с этим. Вы смотрели этот пример кода?

2. Опубликованный код также не смог бы распечатать c[] значения в конце.

3. Если вы хотите использовать обычный код, чтобы инициализировать свои массивы, и обычный код, чтобы напечатать сумму обратно (как вы пытаетесь здесь), вы будете иметь, чтобы: (А) как выделить оперативную память и CUDA памяти (для регулярного памяти можно использовать простые массивы, либо позвонить malloc ); (б) инициализировать хост массивов (с) копирование с хоста на устройство, используя cudaMemcpy , (д) обратитесь к ядру, чтобы сделать дополнение, (Эл.) копировать с устройства памяти в хост-память через cudaMemcpy раз, и, наконец, (е) распечатывает результат.

4. Спасибо вам за ваши ответы. Я изучу пример кода.

Ответ №1:

Как уже предлагалось в комментариях, вам необходимо инициализировать значения для массивов a и b на хосте, скопировать их в массив устройств, а после завершения вычисления вам необходимо скопировать данные c обратно на хост.

 #include<stdio.h>
#define SIZE 20
__global__ void VectorAdd(int *a,int *b,int *c,int n){
    int i = threadIdx.x;
    if(i<n)
        c[i]=a[i] b[i];
}

int main(){

    int *a,*b,*c;
    int *h_a, *h_b, *h_c; /*declare pointers to host arrays*/

    cudaMalloc((void**)amp;a,SIZE *sizeof(int));
    cudaMalloc((void**)amp;b, SIZE *sizeof(int));
    cudaMalloc((void**)amp;c,SIZE *sizeof(int));

    /* allocate memory for host arrays */
    h_a = new int[SIZE];
    h_b = new int[SIZE];
    h_c = new int[SIZE];

    /* initialize values on host arrays */
    for (int i = 0; i < SIZE; i  ){
        h_a[i]=i;
        h_b[i]=i;
    }
    
    /*copy data from host to device */
    cudaMemcpy(a, h_a, SIZE*sizeof(int), cudaMemcpyHostToDevice);
    cudaMemcpy(b, h_b, SIZE*sizeof(int), cudaMemcpyHostToDevice);

    VectorAdd<<<1, SIZE>>>(a,b,c,SIZE);
    // cudaDeviceSynchronize(); /* this is not needed because cudaMemcpy implies sync. */
    
    /*copy results from device to host*/
    cudaMemcpy(h_c, c, SIZE*sizeof(int), cudaMemcpyDeviceToHost);

    for(int i = 0; i < SIZE; i  ){
        printf("%d n",h_c[i]);
    }

    cudaFree(a);
    cudaFree(b);
    cudaFree(c);

    /* free host memory */
    delete [] h_a;
    delete [] h_b;
    delete [] h_c;

    return 0;
}
 

Примечания

  • По какой-то причине вы начинаете итерацию с позиции 1 , а 0 не в вас для циклов! Если это случайно неправильно, я это исправил!
  • cudaMemcpy всегда выполняет синхронизацию между хостом и устройством. Таким образом, cudaDeviceSynchronize() нет необходимости после вызова ядра.
  • Чтобы избежать явной обработки отдельных данных хоста и устройства, вы можете использовать cudaMallocManaged вместо cudaMalloc .