CUDA共享内存效率为50%?

CUDA共享内存效率为50%?,cuda,shared-memory,bank-conflict,Cuda,Shared Memory,Bank Conflict,下面的代码使用共享内存执行平铺矩阵转置以提高性能。共享内存用1列填充,以避免32x32线程块的内存组冲突 __global__ void transpose_tiled_padded(float *A, float *B, int n) { int i_in = blockDim.x*blockIdx.x + threadIdx.x; int j_in = blockDim.y*blockIdx.y + threadIdx.y; int i_out = blockDim.

下面的代码使用共享内存执行平铺矩阵转置以提高性能。共享内存用1列填充,以避免32x32线程块的内存组冲突

__global__ void transpose_tiled_padded(float *A, float *B, int n)
{
    int i_in = blockDim.x*blockIdx.x + threadIdx.x;
    int j_in = blockDim.y*blockIdx.y + threadIdx.y;
    int i_out = blockDim.x*blockIdx.y + threadIdx.x;
    int j_out = blockDim.y*blockIdx.x + threadIdx.y;

    extern __shared__ float tile[];

    // coalesced read of A rows to (padded) shared tile column (transpose)
    tile[threadIdx.y + threadIdx.x*(blockDim.y+1)] = A[i_in + j_in*n];
    __syncthreads();

    // coalesced write from (padded) shared tile column to B rows
    B[i_out + j_out*n] = tile[threadIdx.x + threadIdx.y*(blockDim.x+1)];
}

运行这个代码,我在英伟达可视化剖析器中获得100%的共享内存效率,正如我所期望的。但是,当我使用16x16线程块运行它时,我只能获得50%的效率。为什么呢?据我所知,在这种布局下,经纱中没有一条线是从同一个库读取的。还是我错了?

是的,你错了

考虑到16x16块中扭曲0的这种(读取)访问:

tile[threadIdx.x + threadIdx.y*(blockDim.x+1)];
     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
                     "index"
以下是经纱中每条线的相关计算:

warp lane:    0  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 23 25 26 27 28 29 30 31
threadIdx.x:  0  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15  0  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15
threadIdx.y:  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  1  1  1  1  1  1  1  1  1  1  1  1  1  1  1  1
"index":      0  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
bank:         0  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31  0

所以我们看到,对于这个扭曲,第一个和最后一个线程都从组0读取。这将导致双向库冲突、双向序列化和50%的效率。

是的,您错了

考虑到16x16块中扭曲0的这种(读取)访问:

tile[threadIdx.x + threadIdx.y*(blockDim.x+1)];
     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
                     "index"
以下是经纱中每条线的相关计算:

warp lane:    0  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 23 25 26 27 28 29 30 31
threadIdx.x:  0  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15  0  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15
threadIdx.y:  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  1  1  1  1  1  1  1  1  1  1  1  1  1  1  1  1
"index":      0  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
bank:         0  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31  0

所以我们看到,对于这个扭曲,第一个和最后一个线程都从组0读取。这会导致双向库冲突、双向序列化和50%的效率。

我明白了。那么,是否有一种系统的方法来计算填充宽度,以确保特定块维度不会发生排列冲突?线程x,y=[0,1]的索引不应该是16吗?这意味着在曲速车道上没有银行冲突,因此,冲突必须存在于其他地方。不,这是不正确的。应该是17岁
blockDim.x
为16。再加上一个就等于17了。研究代码。@RobertCrovella您完全正确。我没有注意到这一点,这是我的错。谢谢你的回复。我明白了。那么,是否有一种系统的方法来计算填充宽度,以确保特定块维度不会发生排列冲突?线程x,y=[0,1]的索引不应该是16吗?这意味着在曲速车道上没有银行冲突,因此,冲突必须存在于其他地方。不,这是不正确的。应该是17岁
blockDim.x
为16。再加上一个就等于17了。研究代码。@RobertCrovella您完全正确。我没有注意到这一点,这是我的错。谢谢你的回复。