CUDA内核每次启动都会反复运行

时间:2014-06-09 23:27:40

标签: c++ cuda gpgpu

我的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]
}

调用内核的代码:

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());
}

1 个答案:

答案 0 :(得分:1)

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

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