CUDA调用OpenCV图像处理核函数遇非法内存访问错误求助
问题原因及修复方案
你代码的核心错误出在核函数参数使用了引用类型,不符合CUDA核函数的参数传递规则。
错误原因
CUDA核函数的所有参数默认会拷贝到设备端的专属参数内存中,若将参数声明为引用类型,实际传递给核函数的是主机侧变量的内存地址:
- 你传入的
dimage是主机栈上存储的设备指针变量,unsigned char *&pimage相当于引用主机侧的dimage变量本身 const int &cn、const size_t &total同理,引用的是主机栈上的cn、total变量
设备代码没有权限访问主机端的虚拟地址空间,所以内核一启动就触发非法内存访问,直接执行失败,这也是你看不到内核printf输出、后续cudaMemcpy、cudaFree操作都跟着报错的原因。
修复方案
把核函数的所有参数改为值传递即可,修改后的核函数代码如下:
__global__ void makeGrey( unsigned char *pimage, const int cn, const size_t total) { unsigned i = blockDim.x * blockIdx.x + threadIdx.x; unsigned icn = i * cn; printf("%u\n", i); if (i < total) { float result = pimage[icn + 0] * .114 + pimage[icn + 1] * .587 + pimage[icn + 2] * .299; pimage[icn + 0] = result; //B pimage[icn + 1] = result; //G pimage[icn + 2] = result; //R // pimage[icn + 3] *= result; //A 4通道图像可取消该注释 } }
额外注意事项
- 如果输入图像是带alpha通道的4通道图,记得取消alpha通道赋值的注释,避免alpha通道保留原值导致输出图像和预期不符
- CUDA核函数仅支持传入设备侧变量的引用,主机侧变量一律使用值传递,或者先把变量拷贝到设备内存再传设备指针
内容的提问来源于stack exchange,提问作者Hakan Demir
相关产品推荐
相关产品推荐

