1

我在 CUDA 中编写了以下代码

__global__ void test(int *b_dev)
{
  int index=blockDim.x*blockIdx.x+threadIdx.x;
  b_dev[index]=1;
 }

 int main()
 {
   int **a;
   int *b_dev;
   a=(int**)malloc(sizeof(int*)*4);
   for(i=0;i<4;i++)
     a[i]=(int*)malloc(sizeof(int)*4);

   //initialise array a here with 0

   cudaMalloc((void**)&b_dev,sizeof(int)*16);
   cudaMemcpy(b_dev,a,sizeof(int)*16,cudaMemcpyHostToDevice);
   test<<<4,4>>>(dev_b);
   cudaMemcpy(a,b_dev,sizeof(int)*16,cudaMemcpyDeviceToHost);
   for(i=0;i<4;i++)
     for(j=0;j<4;j++)
        cout<<a[i][j];
  }

我在主机中有这个二维数组,我将它展平为一维数组并在 gpu 中处理,但是当我尝试在主机中打印数组 a 时,这段代码会产生分段错误,但是当我在内核中注释掉该行时b_dev[valindex]=1,它会打印a具有初始化零的数组。可视化 c++ 调试器表明

CXX0030:无法评估错误表达式。

请引导我

4

1 回答 1

2

当您以您的方式分配数组时,您无法保证每个数组在内存中都是连续的。更具体地说,在您的示例中,您有一个int**数组a,它由 4 个int*数组、a[0]a[1]a[2]和组成a[3]。在每个数组 a[i] (其中 i 是二维数组的数组索引)内,内存将是连续的。但是,不能保证数组的内存和数组a[i]的内存a[i+1]是。也就是说,在您对 的调用之间malloc,分配的内存可以来自您的免费存储中的任何位置,并且它们是否连续取决于malloc. (顺便说一句,如果您在堆栈上分配内存,那么它将是连续的,或者在堆上作为一维数组)。

因此,您不能指望 1 次调用cudaMemcpy来复制所有数组。相反,您必须cudaMemcpy对每个一维数组执行多次调用才能复制所有数组,并对目标指针进行指针算术运算以确保将它们复制到正确的位置。

在处理连续的 2D 数据时,您可以使用cudaMemcpy2D具有签名的 :

cudaError_t cudaMemcpy2D ( void* dst, size_t dpitch, const void* src, size_t spitch, size_t width, size_t height, cudaMemcpyKind kind )

如果您知道源音高和目标音高,则可以使用它,并在使用数据时考虑音高。但是,此函数假定数据维度是连续的,因此在您的情况下它对您没有帮助。

当然,最简单的解决方案是选择数组维度协议并坚持使用它(例如,要么将所有内存都设为 2D 或全部 1D,但除非你有令人信服的理由,否则不要混合它们)。

如果我没有留下指向有关 cudaMemcpy 的相关 CUDA 文档的链接,我也会失职

于 2013-05-08T20:39:46.340 回答