存储器在实现FDTD方程时合并

时间:2013-02-11 11:01:43

标签: cuda

我试图在GPU上实现FDTD方程。我最初 已经实现了使用全局内存的内核。记忆 合并并不是那么好。因此我实现了另一个内核 它使用共享内存来加载值。我在网格上工作 1024x1024

代码在

之下
__global__ void update_Hx(float *Hx, float *Ez, float *coef1, float* coef2){
    int x = threadIdx.x + blockIdx.x * blockDim.x;
    int y = threadIdx.y + blockIdx.y * blockDim.y;
    int offset = x + y * blockDim.x * gridDim.x;
    __shared__ float  Ez_shared[BLOCKSIZE_HX][BLOCKSIZE_HY + 1];
    /*int top = offset + x_index_dim;*/
    if(threadIdx.y == (blockDim.y - 1)){
        Ez_shared[threadIdx.x][threadIdx.y] = Ez[offset];
        Ez_shared[threadIdx.x][threadIdx.y + 1] = Ez[offset + x_index_dim];
   }
    else{
        Ez_shared[threadIdx.x][threadIdx.y] = Ez[offset];
    }
}

常量BLOCKSIZE_HX = 16BLOCKSIZE_HY = 16

当我运行可视化分析器时,它仍然表示内存未合并。

编辑: 我正在使用GT 520显卡,cuda计算能力为2.1。 我的全局L2交易/访问权限= 7.5,即有245 760个L2交易 32768执行该行 Ez_shared[threadIdx.x][threadIdx.y] = Ez[offset];

Global memory load efficiency50%

Global memory load efficiency = 100 * gld_requested_throughput/ gld_throughput

我无法弄清楚为什么有这么多内存访问,尽管我的线程正在查看16个连续值。有人能指出我做错了吗?

编辑:感谢您的帮助。

1 个答案:

答案 0 :(得分:1)

您的内存访问模式是此处的问题。您获得的效率仅为50%(对于L1和L2),因为您正在访问16个浮点数的连续区域,即64个字节,但L1事务大小为128个字节。这意味着对于所请求的每64个字节,必须将128个字节加载到L1中(并且因此也加载到L2中)。

您也遇到共享内存库冲突问题,但目前这并未对您的全局内存负载效率产生负面影响。

您可以通过多种方式解决负载效率问题。最简单的方法是将x维块大小更改为32.如果这不是一个选项,您可以更改全局内存数据布局,以便每两个连续的blockIdx.y([0,1],[2,3]等。 )值将映射到连续的内存块。如果即使这不是一个选项,你只需要加载全局数据一次,你可以使用非缓存的全局内存加载绕过L1 - 这将有所帮助,因为L2使用32字节事务,所以你的64字节将被加载到两个L2没有开销的交易。