如何在CUDA中正确添加全局内存?
我试图在CUDA中为家庭作业实现绝对差异之和,但在获得正确结果时遇到了困难。 我得到一个Blocksize,它表示要比较的图像的正方形部分的X和Y大小(以像素为单位)。我还得到了两张YUV格式的图片。下面是我必须实现的程序部分:计算SAD的内核和网格/线程块大小的设置。程序的其余部分已提供,可以假定是正确的 这里我得到了当前线程的x和y索引,并使用它们来获得我在当前线程中处理的图像数组中的像素。然后我计算绝对差,等待所有线程完成计算,然后如果当前线程在我们关心的图像块内,则使用atomicAdd将绝对差添加到全局内存中的总和,以避免写入期间发生冲突如何在CUDA中正确添加全局内存?,cuda,Cuda,我试图在CUDA中为家庭作业实现绝对差异之和,但在获得正确结果时遇到了困难。 我得到一个Blocksize,它表示要比较的图像的正方形部分的X和Y大小(以像素为单位)。我还得到了两张YUV格式的图片。下面是我必须实现的程序部分:计算SAD的内核和网格/线程块大小的设置。程序的其余部分已提供,可以假定是正确的 这里我得到了当前线程的x和y索引,并使用它们来获得我在当前线程中处理的图像数组中的像素。然后我计算绝对差,等待所有线程完成计算,然后如果当前线程在我们关心的图像块内,则使用atomicAdd
__global__ void gpuCounterKernel(pixel* cuda_curBlock, pixel* cuda_refBlock, uint32* cuda_SAD, uint32 cuda_Blocksize)
{
int idx = blockIdx.x * blockDim.x + threadIdx.x;
int idy = blockIdx.y * blockDim.y + threadIdx.y;
int id = idx * cuda_Blocksize + idy;
int AD = abs( cuda_curBlock[id] - cuda_refBlock[id] );
__syncthreads();
if( idx < cuda_Blocksize && idy < cuda_Blocksize ) {
atomicAdd( cuda_SAD, AD );
}
}
给定的程序也计算CPU上的SAD,并将我们从GPU得到的结果与该结果进行比较,以检查正确性。图像中的有效块大小为1-1000。我上面的解决方案是从10-91得到正确的结果,但是91以上的任何值都只返回0作为总和。我做错了什么?您真的应该显示所有代码并识别您正在运行的GPU。至少是调用内核并为GPU使用分配数据的部分
- 您在所有CUDAAPI调用和内核调用上都做得正确吗
- 可能您的内核根本没有运行,因为
参数总共超过512个线程。您指出在threadsInBlock
=92及以上时,情况不正常。让我们来计算一下:Blocksize
92/4 = 23 threads in X and Y dimensions 23 * 23 = 529 total threads requested per threadblock
如果您进行了正确的cuda错误检查,错误报告会将您的注意力集中在cuda内核启动失败上,因为启动参数不正确。您的网格和块大小设置看起来很奇怪 通常我们对图像像素使用如下类似的设置
int imageROISize=1000;
dim3 threadInBlock(16,16);
dim3 blocksInGrid((imageROISize+15)/16, (imageROISize+15)/16);
有关如何将工作负载分配给cuda线程的更多信息,请参阅cuda编程指南中的以下部分
Blcoksize和BLOCKSU size有什么区别?命名看起来很混乱。一个是CUDA线程块的大小,另一个是图像ROI的大小?啊,是的,对不起。这些是我们的教授在框架实现中提供的名称。Blocksize是指我们在输入图像中求和的像素方盒的X/Y大小。Blocksize*Blocksize是我们计算的盒子的大小。block_size指CUDA线程块的大小。也许您应该给出完整的代码。我认为您必须检查您的块和线程配置。例如,对于100x100的图像,假设Blocksize=100,grid_-sizeX=grid_-sizeY=50,block_-sizeX=block_-sizeY=25,总线程数为25*25*50*50=156500(不等于100x100)。是的,情况就是这样。我修改了块和网格的大小,现在它对所有输入都运行良好。非常感谢。我肯定会进一步研究错误检查。程序中没有其他位置的原因是,我们被指示不要修改提供给我们的代码的任何其他部分。我的教授没有在代码中包含错误检查。好的,我改成了这个,它现在可以很好地用于不同ROI的所有输入。你能解释一下你在这里选择的维度背后的逻辑吗?我仍在努力学习如何选择好的维度来设置它。谢谢大家!@这将是一个很长的故事。我在回答中为你添加了一个链接。
int imageROISize=1000;
dim3 threadInBlock(16,16);
dim3 blocksInGrid((imageROISize+15)/16, (imageROISize+15)/16);