GPGPU - CUDA:全球商店效率

时间:2012-06-22 07:09:35

标签: cuda gpgpu coalescing

基于NVidia分析器的“全局存储效率”值,我试图弄清楚我的某个内核的全局内存访问是如何合并的(我在Fermi GPU上使用CUDA 5工具包预览版)。

据我了解,此值是请求的内存事务与执行的实际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;
}

2 个答案:

答案 0 :(得分:0)

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

但是,我认为不应该发生寄存器溢出,因为内核中的局部变量数量很少。您可以使用nvcc --ptxas-options = -v查看泄漏。

答案 1 :(得分:0)

好吧,惭愧我,我发现了问题:我在调试模式下分析了这个简单的测试代码,它给出了大多数指标的完全数字。在发布模式下重新分析给出了预期的结果:两种情况下的存储效率均为100%。