每次启动都重复运行CUDA内核

CUDA Kernel running repeatedly for each launch

本文关键字:运行 CUDA 内核 启动      更新时间:2023-10-16

我有一个非常奇怪的bug与CUDA (v5.0)代码。基本上,我正在尝试使用设备内存为需要取一堆像素平均值的程序积累值。为了做到这一点,我有两个内核,一个在浮点数组中累加一个和,sum_mask,另一个在最后进行除法,avg_mask。奇怪的是两个核函数都做了我想让它们做的操作,乘以14。我怀疑这是某种同步或网格/块模糊问题,但我已经检查了又检查了所有内容,无法弄清楚。如有任何帮助,不胜感激。

编辑1,问题陈述:运行一个CUDA内核,做任何累积过程,如果每个像素由14个线程连续运行,我将得到我所期望的结果。给我带来麻烦的具体输入是宽度=1280,高度=720

编辑2:删除代码片段中一些看似与问题无关的代码。 内核:

__global__ void sum_mask(uint16_t * pic_d, float * mask_d,uint16_t width, uint16_t height)
{
unsigned short col = blockIdx.x*blockDim.x + threadIdx.x;
unsigned short row = blockIdx.y*blockDim.y + threadIdx.y;
unsigned short offset = col + row*width;
mask_d[offset] = mask_d[offset] + 1.0f; //This ends up incrementing by 14
//mask_d[offset] = mask_d[offset] + __uint2float_rd(pic_d[offset]); //This would increment by 14*pic_d[offset]
}

调用kernel:

uint32_t dark_subtraction_filter::update_mask_collection(uint16_t * pic_in)
{
// Synchronous
HANDLE_ERROR(cudaSetDevice(DSF_DEVICE_NUM));
HANDLE_ERROR(cudaMemcpy(pic_in_host,pic_in,width*height*sizeof(uint16_t),cudaMemcpyHostToHost));
averaged_samples++;
HANDLE_ERROR(cudaMemcpyAsync(pic_out_host,mask_device,width*height*sizeof(uint16_t),cudaMemcpyDeviceToHost,dsf_stream));
/* This part is for testing */
HANDLE_ERROR(cudaStreamSynchronize(dsf_stream));
        std::cout << "#samples: " << averaged_samples << std::endl;
        std::cout << "pic_in_host: " << pic_in_host[9300] << "maskval: " << pic_out_host[9300] <<std::endl;
//Asynchronous
HANDLE_ERROR(cudaMemcpyAsync(picture_device,pic_in_host,width*height*sizeof(uint16_t),cudaMemcpyHostToDevice,dsf_stream));
sum_mask<<< gridDims, blockDims,0,dsf_stream>>>(picture_device, mask_device,width,height);

return averaged_samples;
}
构造函数:

dark_subtraction_filter::dark_subtraction_filter(int nWidth, int nHeight)
{
HANDLE_ERROR(cudaSetDevice(DSF_DEVICE_NUM));
width=nWidth;
height=nHeight;
blockDims = dim3(20,20,1);
gridDims = dim3(width/20, height/20,1);
HANDLE_ERROR(cudaStreamCreate(&dsf_stream));
HANDLE_ERROR(cudaHostAlloc( (void **)&pic_in_host,width*height*sizeof(uint16_t),cudaHostAllocPortable)); //cudaHostAllocPortable??
HANDLE_ERROR(cudaHostAlloc( (void **)&pic_out_host,width*height*sizeof(float),cudaHostAllocPortable)); //cudaHostAllocPortable??
HANDLE_ERROR(cudaMalloc( (void **)&picture_device, width*height*sizeof(uint16_t)));
HANDLE_ERROR(cudaMalloc( (void **)&mask_device, width*height*sizeof(float)));
HANDLE_ERROR(cudaPeekAtLastError());
}

变量offset被声明为unsigned short类型。偏移量计算溢出了16位存储类。如果width = height = 1000,这将导致大约14个溢出,从而导致所观察到的行为。

参数传递和偏移量计算在unsigned short/uint16_t上执行。如果数据类型和计算是int类型,计算可能会更快。