我正在尝试根据 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% 之前所做的任何事情,但显然我一定是误解了一些事情要么是全局存储效率的含义,要么是全局存储合并的条件。
谢谢,
编辑 :
这是一个例子:如果我使用这段代码(只是在输入上添加一个“round”操作),全局存储效率从 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;
}