我在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];
}
我在主机中有这个2d数组,我将其作为1D数组展平并在gpu中处理但是当我尝试在主机中打印数组a时,此代码会产生分段错误,但是当我注释掉行{{1在kernal中,它使用初始化的零打印数组b_dev[valindex]=1
。 visual c ++调试器指示
CXX0030:无法评估错误表达。
请引导我
答案 0 :(得分:2)
当你以你的方式分配一个数组数组时,你没有保证每个数组在内存中都是连续的。更具体地说,在您的示例中,您有一个int**
数组a
,其中包含4个int*
数组,a[0]
,a[1]
,a[2]
,和a[3]
。在每个数组a [i](其中i是2D数组的数组索引)内,内存将是连续的。但是,没有保证数组a[i]
的内存和数组a[i+1]
的内存是。也就是说,在您对malloc
的调用之间,正在分配的内存可以来自您的免费商店中的任何位置,并且它们是否是连续的最多是malloc
。 (顺便说一句,如果你在堆栈上分配内存,那么它将是连续的,或者在堆上作为一维数组)。
因此,您不能指望1次调用cudaMemcpy
来复制所有数组。相反,您必须为每个1D数组执行多个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,但除非你有令人信服的理由,否则不要将它们混合在一起)。
的链接,我也会失职