GPGPU-CUDA:全球存储效率

GPGPU-CUDA:全球存储效率,cuda,gpgpu,coalescing,Cuda,Gpgpu,Coalescing,我试图根据NVidia的profiler的“全局存储效率””值(我使用的是Fermi GPU上的CUDA 5 toolkit预览版),计算出我的一个内核的全局内存写入访问结合得有多好 据我所知,该值是请求的内存事务与实际执行的事务nb的比率,因此反映了访问是否完全合并(100%效率) 现在,对于32的线程块宽度,并将浮点值作为输入和输出,下面的测试内核为全局加载和全局存储提供了100%的效率,正如预期的那样: __global__ void dummyKernel(float*output,fl

我试图根据NVidia的profiler的“全局存储效率””值(我使用的是Fermi GPU上的CUDA 5 toolkit预览版),计算出我的一个内核的全局内存写入访问结合得有多好

据我所知,该值是请求的内存事务与实际执行的事务nb的比率,因此反映了访问是否完全合并(100%效率)

现在,对于32的线程块宽度,并将浮点值作为输入和输出,下面的测试内核为全局加载和全局存储提供了100%的效率,正如预期的那样:

__global__ void dummyKernel(float*output,float* input,size_t pitch)
{
  unsigned int x = blockIdx.x * blockDim.x + threadIdx.x;
  unsigned int y = blockIdx.y * blockDim.y + threadIdx.y;
  int offset = y*pitch+x;
  float tmp = input[offset];
  output[offset] = tmp;
}
我不明白的是,为什么当我开始在输入读取和输出写入之间添加有用的代码时,全局存储效率开始下降,而我没有改变内存写入模式或线程块几何结构?不过,正如我预期的那样,全局负载保持在100%

有人能解释一下为什么会这样吗?我认为,由于给定warp中的所有32个线程同时执行输出存储指令(根据定义)并使用“聚合友好”模式,因此无论我之前做了什么,我都应该得到100%的结果,但显然我对全局存储效率的含义有所误解,或者全球门店合并的条件

Thx

编辑:

下面是一个例子:如果我使用这段代码(只需对输入添加一个“舍入”操作),全局存储效率将从100%下降到95%

__global__ void dummyKernel(float*output,float* input,size_t pitch)
{
  unsigned int x = blockIdx.x * blockDim.x + threadIdx.x;
  unsigned int y = blockIdx.y * blockDim.y + threadIdx.y;
  int offset = y*pitch+x;
  float tmp = round(input[offset]);
  output[offset] = tmp;
}

不确定是否是这种情况,但round可能会将其参数转换为double,如果存在寄存器溢出,则每个线程将访问8字节的内存,然后强制将其转换为4字节的tmp。访问8个字节会将合并减少到半扭曲


然而,我相信寄存器溢出不应该发生,因为内核中的局部变量数量很少。您可以使用nvcc--ptxas options=-v检查溢出情况。

好的,我很遗憾,我发现了问题:我在调试模式下分析了这个简单的测试代码,这为大多数指标提供了完全不确定的数字。在发布模式下重新分析给了我预期的结果:在这两种情况下都是100%的存储效率。

你说中间的
有用代码是什么意思?
?为什么你认为效率开始下降?这确实是个谜。正如你所做的那样,我不希望全球门店效率发生变化。我想你没有改变逻辑,只对一些线程进行存储?请提供完整的代码。否则,这里的任何回答或评论都只是猜测……我检查了一下以确保没有溢出(使用了21个寄存器)。即使有某种类型的双/浮点转换,我仍然不理解它如何影响最终写入,而最终写入在任何情况下都使用浮点。我将检查汇编代码,试图找出差异。。。