CUDA二维数组拷贝仅成功第一行,求问题排查与解决
问题分析与修正
你的代码存在三个关键错误,导致仅第一行数据拷贝成功:
1. GPU内存访问逻辑错误
cudaMallocPitch分配的GPU内存是按行对齐的,每行实际占用的字节数是返回的pitch值(通常大于N*sizeof(double),用于满足硬件对齐要求)。你在kernel中用连续索引d_A[i]遍历,只会访问到第一行的有效数据,后续地址属于未拷贝的对齐填充区域,因此显示为0。
正确的访问方式应该是通过行偏移+列偏移计算地址:
// 第y行第x列元素的索引计算 int idx = y * (pitch / sizeof(double)) + x; double val = d_A[idx];
2. 代码拼写与语法错误
- kernel参数
N缺少类型声明,应为__global__ void kernel_print(double* d_A, int N, size_t pitch) - 变量名拼写错误:
kernal_print应为kernel_print,blocknum应为blocksnum - kernel中定义的
xIdx和yIdx未被使用,属于冗余代码
3. 缺少设备同步
调用kernel后未执行cudaDeviceSynchronize(),主机可能在GPU完成printf输出前就结束程序,导致输出不完整或异常。
修正后的完整代码
#include <stdio.h> #define N 3 void function(){ double A[N][N] = {{1,2,3}, {4,5,6}, {7,8,9}}; double* d_A; size_t pitch; cudaMallocPitch(&d_A, &pitch, N * sizeof(double), N); cudaMemcpy2D(d_A, pitch, A, N * sizeof(double), N * sizeof(double), N, cudaMemcpyHostToDevice); int threadnum = 1; int blocksnum = 1; kernel_print<<<blocksnum, threadnum>>>(d_A, N, pitch); // 同步设备,确保printf输出完成 cudaDeviceSynchronize(); cudaFree(d_A); } __global__ void kernel_print(double* d_A, int N, size_t pitch){ printf("\n"); for(int y = 0; y < N; y++){ for(int x = 0; x < N; x++){ int idx = y * (pitch / sizeof(double)) + x; printf("%f, ", d_A[idx]); } } printf("\n"); } int main(){ function(); return 0; }
关键注意事项
- 必须将
pitch传递给kernel,用于计算每行的实际元素数量 - 访问GPU数组时,严格按照
行索引 * 每行元素数 + 列索引的规则计算地址 - 调用CUDA kernel后,建议使用
cudaDeviceSynchronize()同步主机与设备,确保输出或后续操作的正确性 - 调试时可检查CUDA API的返回值(如
cudaMallocPitch、cudaMemcpy2D的返回值),快速定位内存分配或拷贝错误
内容的提问来源于stack exchange,提问作者TBB
相关产品推荐
相关产品推荐

