银行冲突CUDA共享内存?

时间:2015-02-06 21:05:58

标签: cuda shared-memory bank-conflict

我在CUDA内核中遇到(我认为是)共享内存库冲突。代码本身相当复杂,但我在下面附带的简单示例中重现了它。

在这种情况下,它被简化为来自全球的简单副本 - >分享 - >全局内存,大小为16x16的2D数组,使用可能在右侧填充的共享内存数组(变量ng)。

如果我使用ng=0编译代码并使用NVVP检查共享内存访问模式,它会告诉我“没有问题”。用例如ng=2我在标有“NVVP警告”的行上获得“Shared Store Transactions / Access = 2,Ideal Transactions / Acces = 1”。我不明白为什么(或更具体:为什么填充会导致警告)。

编辑 如下面Greg Smith所述,在Kepler上有32个8字节宽的存储区(http://gpgpu.org/wp/wp-content/uploads/2013/09/08-opti-smem-instr.pdf,幻灯片18)。但我不知道这是如何改变这个问题的。

如果我理解正确,有32个银行(B1, B2, ..)的4个字节,则双倍(D01, D02, ..)存储为:

B1   B2   B3   B4   B5    ..   B31
----------------------------------
D01       D02       D03   ..   D15
D16       D17       D18   ..   D31
D32       D33       D34   ..   D47

没有填充,一半warp写入(as[ijs] = in[ij])到共享内存D01 .. D15D16 .. D31等。使用填充(大小为2),前半部分warp写入{{ 1}},填充到D01 .. D15之后的第二个,它仍然不应该导致银行冲突?

知道这里可能出现什么问题吗?

简化示例(使用cuda 6.5.14测试):

D18 .. D33

1 个答案:

答案 0 :(得分:3)

事实证明我没有正确理解Keppler架构。正如Greg Smith上面的一条评论所指出的,Keppler可以配置为具有8个字节的32个共享存储体。在这种情况下,使用cudaDeviceSetSharedMemConfig( cudaSharedMemBankSizeEightByte ),共享内存布局如下所示:

bank:  B0   B1   B2   B3   B4    ..   B31
       ----------------------------------
index: D00  D01  D02  D03  D04   ..   D31
       D32  D33  D34  D35  D36   ..   D63   

现在,对于我的简单示例(使用itot=16),写入/读取共享内存,例如前两行(threadIdx.y=0threadIdx.y=1)在一个warp内处理。这意味着threadIdx.y=0D00..D15存储在B0..B15中,然后存在两个双精度的填充,之后在D18..D33中存储相同的变形值B18..B31+B00..B01 1}},导致B00-B01上的银行冲突。如果没有填充(ng=0),第一行将写入D00..D15中的B00..B15D16..D31B16..B31中的第二行,因此不会发生银行冲突。

对于blockDim.x>=32的线程块,不应出现问题。例如,对于itot=32blockDim.x=32ng=2,第一行存储在存储区B00..B31中,然后存储两个单元格填充,B02..B31+B00..B01中的第二行等。