我正在使用cudaMallocPitch
和cudaMemcpy2D
来表示2D数组。即使我无法正确输出,我也不确定我的编码是否正确。有人可以帮忙吗?任何人都可以调试我的错误吗?提前致谢。
#include<stdio.h>
#include<cuda.h>
#define siz 4*sizeof(int)
__global__ void addmatrix(int *m1,int *m2,size_t pitch)
{
int r=threadIdx.x;
int *r1=m1+r*pitch;
int *r2=m2+r*pitch;
int c;
for(c=1;c<=4;c++)
{
r1[c]+=r2[c];
}
}
int main()
{
int i,j;
int **m1_c,**m2_c;
int *m1_d,*m2_d;
size_t pitch;
cudaError_t err;
m1_c=(int **)malloc(4*sizeof(int *));
for(i=1;i<=4;i++)
{
m1_c[i]=(int *)malloc(siz);
}
m2_c=(int **)malloc(4*sizeof(int *));
for(i=1;i<=4;i++)
{
m2_c[i]=(int *)malloc(siz);
}
for(i=1;i<=4;i++)
{
for(j=1;j<=4;j++)
{
m1_c[i][j]=rand()%10;
m2_c[i][j]=rand()%10;
}
}
for(i=1;i<=4;i++)
{
for(j=1;j<=4;j++)
{
printf("%d\t",m1_c[i][j]);
}
printf("\n");
}
printf("\n\n");
for(i=1;i<=4;i++)
{
for(j=1;j<=4;j++)
{
printf("%d\t",m2_c[i][j]);
}
printf("\n");
}
err=cudaMallocPitch((void **)&m1_d,&pitch,siz,siz);
err=cudaMallocPitch((void **)&m2_d,&pitch,siz,siz);
err=cudaMemcpy2D(m1_d,pitch,m1_c,siz,siz,4,cudaMemcpyHostToDevice);
err=cudaMemcpy2D(m2_d,pitch,m2_c,siz,siz,4,cudaMemcpyHostToDevice);
dim3 grid(1);
dim3 block(16);
addmatrix<<<grid,block>>>(m1_d,m2_d,siz);
cudaMemcpy2D(m1_c,siz,m1_d,pitch,siz,4,cudaMemcpyDeviceToHost);
for(i=1;i<=4;i++)
{
for(j=1;j<=4;j++)
{
printf("%d\t",m1_c[i][j]);
}
printf("\n");
}
err=cudaFree(m1_d);
err=cudaFree(m2_d);
err=cudaDeviceReset();
}
答案 0 :(得分:1)
因此这段代码存在一些问题。没有特别的顺序:
src
和dst
),这两个指针都指向内存中的线性数组。我意识到这是令人困惑的,因为2D出现在整个描述中,但是两个指针参数基本上都是相同的类型(指向内存的指针),并且你传递2种不同类型的指针(一个是指向内存的指针,另一个是是指向内存指针的指针。从cudaMemcpy2D的定义来看,你的用法是不正确的。关于如何使用cudaMemcpy2D的示例有很多已回答的问题,我建议您搜索并查看其中的一些。请注意,修复此问题可能会导致您从根本上重新考虑如何将数据存储在主机矩阵中。关于处理多维矩阵有很多问题,例如this one - 如果可能的话,你应该将它们弄平。请注意,在当前代码中,使用cudaMemcpy2D时出现此错误会破坏主机矩阵上的指针数组,这会在您尝试打印结果时导致seg错误。width
和height
参数,您传递的是siz
,即矩阵维,以字节为单位。但是您应该只传递width
参数的字节维度。对于height
参数,您应该传递行数,即在您的情况下为4。对cudaMemcpy2D的调用也有类似的要求,但是你就在那里。pitch
参数。但请记住,音调位于 bytes 中,对于指针算术索引,编译器希望参数位于元素中 - 它会根据您的转换为字节。数据类型。同样,这实际上是一个C问题,并不是特定于CUDA。您可以使用(pitch/sizeof(int))
在内核中使用pitch
的任何地方解决此问题。siz
传递给您的内核。你应该传递pitch
作为音高参数。 siz
实际上是主机数据存储上的“间距”,但pitch
是设备上存储的间距。内核正在设备存储上运行,因此需要正确的间距。以下是一些以某种方式解决上述所有问题的代码:
#include<stdio.h>
#define siz (4*sizeof(int))
#define cudaCheckErrors(msg) \
do { \
cudaError_t __err = cudaGetLastError(); \
if (__err != cudaSuccess) { \
fprintf(stderr, "Fatal error: %s (%s at %s:%d)\n", \
msg, cudaGetErrorString(__err), \
__FILE__, __LINE__); \
fprintf(stderr, "*** FAILED - ABORTING\n"); \
exit(1); \
} \
} while (0)
__global__ void addmatrix(int *m1,int *m2,size_t pitch)
{
int r=threadIdx.x;
int *r1=m1+r*(pitch/sizeof(int));
int *r2=m2+r*(pitch/sizeof(int));
int c;
for(c=0;c<4;c++)
{
r1[c]+=r2[c];
}
}
int main()
{
int i,j;
int *m1_c,*m2_c;
int *m1_d,*m2_d;
size_t pitch;
cudaError_t err;
m1_c=(int *)malloc(16*sizeof(int));
m2_c=(int *)malloc(16*sizeof(int));
for(i=0;i<4;i++)
{
for(j=0;j<4;j++)
{
m1_c[(i*4)+j]=rand()%10;
m2_c[(i*4)+j]=rand()%10;
}
}
for(i=0;i<4;i++)
{
for(j=0;j<4;j++)
{
printf("%d\t",m1_c[(i*4)+j]);
}
printf("\n");
}
printf("\n\n");
for(i=0;i<4;i++)
{
for(j=0;j<4;j++)
{
printf("%d\t",m2_c[(i*4)+j]);
}
printf("\n");
}
err=cudaMallocPitch((void **)&m1_d,&pitch,siz,4);
cudaCheckErrors("cm1");
err=cudaMallocPitch((void **)&m2_d,&pitch,siz,4);
cudaCheckErrors("cm2");
err=cudaMemcpy2D(m1_d,pitch,m1_c,siz,siz,4,cudaMemcpyHostToDevice);
cudaCheckErrors("cm3");
err=cudaMemcpy2D(m2_d,pitch,m2_c,siz,siz,4,cudaMemcpyHostToDevice);
cudaCheckErrors("cm4");
dim3 grid(1);
dim3 block(4);
addmatrix<<<grid,block>>>(m1_d,m2_d,pitch);
cudaMemcpy2D(m1_c,siz,m1_d,pitch,siz,4,cudaMemcpyDeviceToHost);
cudaCheckErrors("cm5");
for(i=0;i<4;i++)
{
for(j=0;j<4;j++)
{
printf("%d\t",m1_c[(i*4)+j]);
}
printf("\n");
}
err=cudaFree(m1_d);
err=cudaFree(m2_d);
err=cudaDeviceReset();
}