CUDA 使用 cudaMemcpy2D 将数组从设备复制到主机
CUDA copying array from device to host using cudaMemcpy2D
cudaMemcpy2D
没有按照我的预期复制。在阅读有关 cudaMallocPitch 的手册后,我尝试编写一些代码来了解发生了什么。但是,好吧,我遇到了一个问题。
我做了这样一个简单的程序:
int main()
{
double *d_A;
size_t d_pitch;
cudaMallocPitch((void**)&d_A, &d_pitch, sizeof(double) * SIZE, SIZE);
dim3 blocks(4, 4);
dim3 threads(16, 16);
doStuff<<<blocks, threads>>>(d_A, d_pitch);
double *A;
size_t pitch = sizeof(double) * SIZE;
A = (double*)malloc(sizeof(double) * SIZE * SIZE);
cudaMemcpy2D(A, pitch, d_A, d_pitch, sizeof(double) * SIZE, SIZE, cudaMemcpyDeviceToHost);
for (int i = 0; i < SIZE; i++) {
for (int j = 0; j < SIZE; j++) printf("%f ", A[sizeof(double) * i + j]);
printf("\n");
}
}
和doStuff
是:
__global__ void doStuff(double *d_A, size_t d_pitch)
{
unsigned int i = blockIdx.x * blockDim.x + threadIdx.x;
unsigned int j = blockIdx.y * blockDim.y + threadIdx.y;
double *target = ( (double*)(((char*)d_A) + (d_pitch * i)) ) + j;
if (i < SIZE && j < SIZE)
*target = (i + 1) * (j + 1) + 0.0;
}
因此 doStuff
与 d_A[i][j] = (i+1)*(j+1)
相同。如果 SIZE
是 5,我期望的是:
1 2 3 4 5
2 4 6 8 10
3 6 9 12 15
4 8 12 16 20
5 10 15 20 25
双精度。但是,当我编译 运行 时,我得到:
1 2 3 4 5
8 10 3 6 9
8 12 16 20 5
25 0 0 0 0
0 0 0 0 0
似乎对于每一行,cudaMemcpy2D
都会覆盖以前的数据。我试图找到改变间距和宽度的问题,但我找不到。
那么我的代码是怎么回事?
错误在这一行:
for (int j = 0; j < SIZE; j++) printf("%f ", A[sizeof(double) * i + j]);
应该是:
for (int j = 0; j < SIZE; j++) printf("%f ", A[SIZE * i + j]);
您想按行的元素大小(而不是元素的字节大小)缩放行索引 (i
)。
这当然和CUDA无关
cudaMemcpy2D
没有按照我的预期复制。在阅读有关 cudaMallocPitch 的手册后,我尝试编写一些代码来了解发生了什么。但是,好吧,我遇到了一个问题。
我做了这样一个简单的程序:
int main()
{
double *d_A;
size_t d_pitch;
cudaMallocPitch((void**)&d_A, &d_pitch, sizeof(double) * SIZE, SIZE);
dim3 blocks(4, 4);
dim3 threads(16, 16);
doStuff<<<blocks, threads>>>(d_A, d_pitch);
double *A;
size_t pitch = sizeof(double) * SIZE;
A = (double*)malloc(sizeof(double) * SIZE * SIZE);
cudaMemcpy2D(A, pitch, d_A, d_pitch, sizeof(double) * SIZE, SIZE, cudaMemcpyDeviceToHost);
for (int i = 0; i < SIZE; i++) {
for (int j = 0; j < SIZE; j++) printf("%f ", A[sizeof(double) * i + j]);
printf("\n");
}
}
和doStuff
是:
__global__ void doStuff(double *d_A, size_t d_pitch)
{
unsigned int i = blockIdx.x * blockDim.x + threadIdx.x;
unsigned int j = blockIdx.y * blockDim.y + threadIdx.y;
double *target = ( (double*)(((char*)d_A) + (d_pitch * i)) ) + j;
if (i < SIZE && j < SIZE)
*target = (i + 1) * (j + 1) + 0.0;
}
因此 doStuff
与 d_A[i][j] = (i+1)*(j+1)
相同。如果 SIZE
是 5,我期望的是:
1 2 3 4 5
2 4 6 8 10
3 6 9 12 15
4 8 12 16 20
5 10 15 20 25
双精度。但是,当我编译 运行 时,我得到:
1 2 3 4 5
8 10 3 6 9
8 12 16 20 5
25 0 0 0 0
0 0 0 0 0
似乎对于每一行,cudaMemcpy2D
都会覆盖以前的数据。我试图找到改变间距和宽度的问题,但我找不到。
那么我的代码是怎么回事?
错误在这一行:
for (int j = 0; j < SIZE; j++) printf("%f ", A[sizeof(double) * i + j]);
应该是:
for (int j = 0; j < SIZE; j++) printf("%f ", A[SIZE * i + j]);
您想按行的元素大小(而不是元素的字节大小)缩放行索引 (i
)。
这当然和CUDA无关