如何在CUDA中正确添加全局内存?

如何在CUDA中正确添加全局内存?,cuda,Cuda,我试图在CUDA中为家庭作业实现绝对差异之和,但在获得正确结果时遇到了困难。 我得到一个Blocksize,它表示要比较的图像的正方形部分的X和Y大小(以像素为单位)。我还得到了两张YUV格式的图片。下面是我必须实现的程序部分:计算SAD的内核和网格/线程块大小的设置。程序的其余部分已提供,可以假定是正确的 这里我得到了当前线程的x和y索引,并使用它们来获得我在当前线程中处理的图像数组中的像素。然后我计算绝对差,等待所有线程完成计算,然后如果当前线程在我们关心的图像块内,则使用atomicAdd

我试图在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调用和内核调用上都做得正确吗
  • 可能您的内核根本没有运行,因为
    threadsInBlock
    参数总共超过512个线程。您指出在
    Blocksize
    =92及以上时,情况不正常。让我们来计算一下:

    92/4 = 23 threads in X and Y dimensions
    23 * 23 = 529 total threads requested per threadblock
    
529超过了512,这是cc 1.x设备的限制,因此我猜您正在cc 1.x设备上运行,因此内核启动失败,内核没有运行,因此您没有得到计算结果(即0)。请注意,在X和Y尺寸为91/4=22个螺纹时,您需要总共484个螺纹


如果您进行了正确的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);