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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.05 13:00:50