【问题标题】:Segmentation fault in CUDACUDA 中的分段错误
【发布时间】:2021-12-17 04:58:03
【问题描述】:

我在运行此代码时收到分段错误(核心转储)

我知道 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**)&a,SIZE *sizeof(int));
    cudaMalloc((void**)&b, SIZE *sizeof(int));
    cudaMalloc((void**)&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;
}

【问题讨论】:

  • 使用cudaMalloc 创建的分配不能直接从主机代码中引用,正如您在此处尝试所做的那样:a[i]=i;。有一个名为 vectorAdd 的 CUDA 示例代码,它提供了一种典型的处理方法。你看过那个示例代码吗?
  • 发布的代码也无法在最后打印出c[] 值。
  • 如果你想使用普通代码来初始化你的数组,并使用普通代码来打印总和(正如你在这里尝试的那样),你将不得不:(a)分配常规内存和 Cuda 内存(对于常规内存,您可以使用普通数组,或调用 malloc); (b) 初始化您的主机阵列,(c) 使用cudaMemcpy 从主机复制到设备,(d) 调用您的内核进行添加,(e) 再次使用cudaMemcpy 从设备内存复制回主机内存,以及最后 (f) 打印出结果。
  • 感谢您的回答。我会研究示例代码。

标签: cuda


【解决方案1】:

正如 cmets 已经建议的那样,您必须在主机上初始化数组 ab 的值,将它们复制到设备数组,一旦计算完成,您必须将数据从 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**)&a,SIZE *sizeof(int));
    cudaMalloc((void**)&b, SIZE *sizeof(int));
    cudaMalloc((void**)&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 for 循环!如果这是不小心出错了,我已经修复了!

  • cudaMemcpy 总是在主机和设备之间执行同步。所以,cudaDeviceSynchronize() 在内核调用后就不需要了。

  • 为避免显式处理分离的主机和设备数据,您可以使用cudaMallocManaged 而不是cudaMalloc

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-05-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-04-19
    • 2019-01-03
    • 1970-01-01
    相关资源
    最近更新 更多