Fermi及更高版本中共享内存冲突的相关性

3
根据CUDA文档所述,sm_20及更高版本的共享内存bank冲突并不重要,因为当同时请求时,值会被广播,从而防止任何序列化延迟。
文档如下:
“在计算能力为2.x的设备上,共享内存硬件得到了改进,支持多个广播字,并且对每个线程的8位、16位、64位或128位访问生成更少的bank冲突(第G.4.3节)。”
有人能够确认我的说法吗?
1个回答

16

不,它们并不是“无关紧要”的。

我认为你的困惑可能源自于一个常见误解,即银行冲突中的“bank”与“location”在某种程度上是相等的。虽然银行和位置之间存在联系,但它们不一定是相等的。

举个简单的例子,假设我们有4个银行(讨论仅限于32位事务,并且自然对齐32位存储,例如intfloat)。 银行和位置(intfloat索引“地址”)之间的关系如下:

address:  bank:
       0      0 <-----------------------Thread 0
       1      1
       2      2     ------Thread 1
       3      3    /
       4      0 <---------Thread 2
       5      1
       6      2 
       7      3
       8      0 <-----------------------Thread 3
...

例如,我们可以看到地址1和5在同一银行,但它们不是相同的位置。

无论何种架构,如果一个warp中的两个或多个线程由于特定的事务(例如从共享内存读取)而尝试访问与另一个线程相同的bank中的数据,都可能会出现银行冲突。

在Fermi之前的情况下,即使多个线程从相同的location(也就是地址)读取,这也是一种银行冲突,因为这些线程正在从同一银行读取。

在cc2.x或更高版本的情况下,引入了一个broadcast机制。这个机制对于银行冲突的一般情况没有影响,除了一个特定的情况。当多个线程从same location读取时,这不再是一个银行冲突,所有从该位置读取的线程将在一个特定的周期内接收到数据,而不需要序列化。

然而,在任何情况下,如果多个线程从位于同一bank的不同位置读取,那么这就是一个银行冲突,无论在当前的GPU架构下还是以后的任何版本下。

在上面的图片中,如果Thread 0从地址0读取,Thread 3从地址8读取,这将始终是当前任何架构上的银行冲突(假设这只是一个有4个银行的简化示例)。如果Thread 1和Thread 2都从地址4读取,那就是Fermi之前的银行冲突,但在所有Fermi设备及以后的设备上不是。

对于32个银行的配置,这是一种实际的银行配置,共享内存中任何位置的bank由该位置的索引或偏移量的低5位给出,无论该位置是否属于一个intfloat数组。


一个"float"的低5位?我想你可能是指"float"的整数部分,也许!除此之外,我"假设"低5位是用来确定线程ID的warp的相同掩码。但我不确定。 - Drout
1
intfloat偏移量的5个低位是指该位置的偏移量的5个位,无论它是一个int数组还是一个float数组,即数组索引,其本身不是一个float数量。重新措辞。 - Robert Crovella

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接