CUDA核计算矩阵行积分图时输出结果异常问题咨询
问题原因分析
- 核心原因:8位无符号整数溢出
你使用uchar(即8位无符号整数,取值范围仅为0~255)存储积分计算结果,测试矩阵所有元素均为1,当行内累加值超过255时,无符号整数会自动触发模256的溢出规则,直接截断高位,因此输出会出现1到255的循环序列。核函数中sum变量虽然用了int类型存储中间值,但赋值给uchar类型的res时仍会发生隐式类型转换截断,导致溢出。 - 次要问题:核函数设计冗余
你原本设计为每行分配1个线程,执行配置的x维度总线程数为1(threadsPerBlock.x=1、numBlocks.x=1),所有线程的x索引固定为0,核函数中关于x的计算逻辑完全冗余,没有实际作用。
修复方案
- 修改结果矩阵的数据类型
积分图的结果最大值等于矩阵宽高的乘积,3840*2160的矩阵最大值可达800万以上,需要至少32位整数存储:- 核函数中
res的参数类型从uchar*改为uint32_t*或者int* - 主机端创建结果
cv::Mat时,类型从CV_8UC1改为CV_32SC1
- 核函数中
- 简化核函数逻辑(适配单线程处理一行的设计)
调整后的核函数可简化为:__global__ void IntegrateRows(const uchar* img, int* res) { int y = blockIdx.y * blockDim.y + threadIdx.y; if (y >= Height) return; int sum = 0; int row_offset = y * Width; for (int x = 0; x < Width; ++x) { sum += img[row_offset + x]; res[row_offset + x] = sum; } } - 动态计算执行配置(可选,适配任意分辨率)
你当前的执行配置y方向总线程数为256*16=4096,足以覆盖2160行的需求,如果要适配更大分辨率,可按如下方式动态计算块数:dim3 threadsPerBlock(1, 256); dim3 numBlocks(1, (Height + threadsPerBlock.y - 1) / threadsPerBlock.y); IntegrateRows<<<numBlocks, threadsPerBlock >>>(img, res);
内容的提问来源于stack exchange,提问作者vlado_sl
相关产品推荐
相关产品推荐

