CUDA Kernel参数传递引发cudaMemcpy非法内存访问错误排查
可能的核心原因
内存分配/拷贝大小计算错误
当通过argv传入M、N后,若代码中计算内存大小存在失误(比如误将sizeof(half)写成sizeof(int),或M、N转换为整数时出错),会导致分配的内存空间不足以容纳所有数据,cudaMemcpy时触发越界访问。比如8192*8192的half数组需要128MB内存,若按int数组分配则仅64MB,拷贝必然越界。主机端half内存的对齐问题
CUDA的cudaMemcpy对主机端内存有对齐要求,若用普通malloc分配主机端half数组,可能无法满足half类型的对齐规范(通常至少2字节对齐,部分场景要求更高),从而触发非法访问。而int2half_I2H是在设备端完成int到half的转换,主机端存储的是对齐要求更低的int类型,因此规避了这个问题。主机端half数据操作错误
half是IEEE半精度浮点数类型,若在主机端直接对half数组进行赋值或内存操作(比如用int类型的值直接强转赋值),可能导致数据存储格式异常,间接引发cudaMemcpy时的内存访问错误。而int2half_I2H依赖设备端的硬件转换逻辑,不会出现这类格式问题。
排查步骤
验证M、N的正确性
在代码中添加打印:printf("M: %d, N: %d\n", M, N);,确认从argv转换后的数值确实是8192,排除字符串转整数的错误。检查内存分配与拷贝的字节数
打印内存大小:printf("Required memory: %zu bytes\n", M * N * sizeof(half));,确认cudaMalloc、主机端内存分配(如malloc或cudaMallocHost)的大小与计算值一致,同时检查cudaMemcpy的第四个参数是否为该字节数。替换主机端内存分配方式
将主机端half数组的malloc替换为cudaMallocHost,分配页锁定且满足对齐要求的内存,测试是否还会出现错误。示例:half* h_A; cudaMallocHost(&h_A, M * N * sizeof(half));添加CUDA错误检查
为所有CUDA操作添加错误码检测,获取更精准的错误信息:cudaError_t err = cudaMemcpy(d_A, h_A, M * N * sizeof(half), cudaMemcpyHostToDevice); if (err != cudaSuccess) { fprintf(stderr, "cudaMemcpy failed: %s\n", cudaGetErrorString(err)); return -1; }对比两种实现的代码差异
仔细对比使用cudaMemcpy拷贝half数组,与使用int2half_I2H转换的代码逻辑差异,重点关注主机端数据类型的定义、内存分配、赋值操作是否存在不一致,定位到具体的错误点。
内容的提问来源于stack exchange,提问作者hy pan

