You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.09 02:20:28