CUDA Driver API中cuLaunchKernel传参异常:重复指针与非法内存访问问题
问题原因分析与修复方案
核心问题根源
你的代码存在局部变量地址非法引用的问题,直接导致了参数值异常和非法内存访问错误。
1. 参数指针重复的原因
在遍历输入/输出的循环中,CUdeviceptr ptr是循环体内的局部变量,每次迭代结束后,该变量的栈内存会被回收。你错误地将&ptr(局部变量的栈地址)存入kernel_arguments,但:
- 循环中每次迭代的
ptr在栈上的位置大概率是同一个,所以kernel_arguments里的所有元素实际指向同一个栈地址 - 循环结束后,这个栈地址里残留的是最后一次循环分配的
ptr值(也就是存储b的设备缓冲区地址)
最终核函数拿到的前两个参数都是同一个设备地址,自然会打印出相同的指针和3.0的数据。
2. 非法内存访问的原因
输出缓冲区的参数传递犯了同样的错误:你传递的是局部变量ptr的栈地址,而非ptr本身存储的设备缓冲区地址。核函数尝试写入o_3[index]时,实际访问的是一个无效的设备内存地址(栈地址对应的设备空间根本不存在),因此触发非法内存访问错误。
修复方案
修改主机端代码,直接将ptr的值(设备缓冲区地址)转换为void*存入参数列表,而非局部变量的地址:
std::vector<void *> kernel_arguments; std::vector<float> a = {2}; std::vector<float> b = {3}; for (auto &input : {a, b}) { CUdeviceptr ptr; cuMemAlloc(&ptr, input.size()*sizeof(float)); cuMemcpyHtoD(ptr, input.data(), input.size()*sizeof(float)); // 直接传递设备指针的值,而非局部变量的地址 kernel_arguments.push_back(reinterpret_cast<void *>(ptr)); } std::vector<float> c(1); for (auto &output : {c}) { CUdeviceptr ptr; cuMemAlloc(&ptr, output.size()*sizeof(float)); // 同样传递设备指针的值 kernel_arguments.push_back(reinterpret_cast<void *>(ptr)); } // 后续核函数启动代码不变 CUresult result = cuLaunchKernel(function, 1, 1, 1, 1024, 1, 1, 0, stream, kernel_arguments.data(), NULL);
补充:结果拷贝与内存释放
核函数执行完成后,需要将结果从设备拷贝回主机,并释放设备内存:
// 同步流后拷贝结果 result = cuStreamSynchronize(stream); // 取出输出设备指针 CUdeviceptr output_ptr = reinterpret_cast<CUdeviceptr>(kernel_arguments[2]); cuMemcpyDtoH(c.data(), output_ptr, c.size()*sizeof(float)); std::cout << "计算结果:" << c[0] << std::endl; // 释放所有设备缓冲区 for (auto arg : kernel_arguments) { cuMemFree(reinterpret_cast<CUdeviceptr>(arg)); }
内容的提问来源于stack exchange,提问作者user1139069
相关产品推荐
相关产品推荐

