在CUDA中,什么是记忆聚合,它是如何实现的?

在CUDA中,什么是记忆聚合,它是如何实现的?,cuda,definition,memory-access,Cuda,Definition,Memory Access,CUDA全局内存事务中的“合并”是什么?我看了我的CUDA指南也不明白。怎么做?在CUDA编程指南矩阵示例中,逐行访问矩阵称为“合并”或列。。上校。。被称为联合? 哪个是正确的?为什么?这些信息可能只适用于计算能力1.x或cuda 2.0。更新的体系结构和CUDA3.0具有更复杂的全局内存访问,事实上,这些芯片甚至没有描述“合并的全局负载” 此外,此逻辑可应用于共享内存,以避免银行冲突 合并内存事务是半扭曲中的所有线程同时访问全局内存的事务。这太简单了,但正确的方法是让连续的线程访问连续的内存

CUDA全局内存事务中的“合并”是什么?我看了我的CUDA指南也不明白。怎么做?在CUDA编程指南矩阵示例中,逐行访问矩阵称为“合并”或列。。上校。。被称为联合? 哪个是正确的?为什么?

这些信息可能只适用于计算能力1.x或cuda 2.0。更新的体系结构和CUDA3.0具有更复杂的全局内存访问,事实上,这些芯片甚至没有描述“合并的全局负载”

此外,此逻辑可应用于共享内存,以避免银行冲突


合并内存事务是半扭曲中的所有线程同时访问全局内存的事务。这太简单了,但正确的方法是让连续的线程访问连续的内存地址

因此,如果线程0、1、2和3读取全局内存0x0、0x4、0x8和0xc,那么它应该是联合读取

在矩阵示例中,请记住,您希望矩阵线性驻留在内存中。您可以按照自己的意愿执行此操作,并且您的内存访问应该反映矩阵的布局方式。下面是3x4矩阵

0 1 2 3
4 5 6 7
8 9 a b
可以像这样一行接一行地进行,这样(r,c)映射到内存(r*4+c)

假设您需要访问元素一次,并假设您有四个线程。哪个线程将用于哪个元素?也许是吧

thread 0:  0, 1, 2
thread 1:  3, 4, 5
thread 2:  6, 7, 8
thread 3:  9, a, b

哪个更好?哪些将导致合并读取,哪些不会

无论哪种方式,每个线程都进行三次访问。让我们看看第一次访问,看看线程是否连续访问内存。在第一个选项中,第一个访问是0、3、6、9。不是连续的,不是联合的。第二个选项是0,1,2,3。连续的联合起来!耶


最好的方法可能是编写内核,然后对其进行概要分析,以查看是否有未合并的全局加载和存储。

如果块中的线程正在访问连续的全局内存位置,则所有访问都会被硬件合并成单个请求(或合并)。在矩阵示例中,行中的矩阵元素线性排列,然后是下一行,依此类推。 例如,对于一个块中的2x2矩阵和2个线程,内存位置的排列如下:

(0,0)(0,1)(1,0)(1,1)

在行访问中,thread1访问无法合并的(0,0)和(1,0)。
在列访问中,thread1访问(0,0)和(0,1),因为它们相邻,所以可以合并。

合并的标准在第G.3.2节中有很好的说明。简短的版本如下:warp中的线程必须按顺序访问内存,被访问的字应>=32位。此外,对于32位、64位和128位访问,warp访问的基址应分别为64、128或256字节对齐

Tesla2和Fermi硬件在合并8位和16位访问方面做得很好,但如果您想要峰值带宽,最好避免使用它们


请注意,尽管Tesla2和费米硬件有所改进,但合并绝不是过时的。即使在Tesla2或Fermi类硬件上,未能合并全局内存事务也可能导致性能下降2倍。(在费米级硬件上,这似乎只有在启用ECC时才是正确的。连续但未恢复的内存事务在费米上的命中率约为20%)

内存合并是一种允许优化使用全局内存带宽的技术。 也就是说,当运行相同指令的并行线程访问全局内存中的连续位置时,将实现最有利的访问模式

上图中的示例有助于解释合并安排:

在图(a)中,长度为m的n个向量以线性方式存储。向量j的元素i用v j i表示。GPU内核中的每个线程都分配给一个m长度向量。CUDA中的线程按块数组分组,GPU中的每个线程都有一个唯一的id,可以定义为
indx=bd*bx+tx
,其中
bd
表示块维度,
bx
表示块索引,
tx
是每个块中的线程索引

垂直箭头显示并行线程访问每个向量的第一个组件的情况,即地址0、m、2m。。。记忆的一部分。如图(a)所示,在这种情况下,存储器访问不是连续的。通过将这些地址之间的间隙归零(上图中显示的红色箭头),内存访问变得一致

然而,这里的问题有点棘手,因为每个GPU块允许的驻留线程大小限制为
bd
。因此,可以通过以连续顺序存储第一bd向量的第一元素,然后是第二bd向量的第一元素,依此类推,来完成合并数据排列。其余的向量元素以类似的方式存储,如图(b)所示。如果n(向量数)不是
bd
的一个因子,则需要将最后一个块中的剩余数据填入一些小值,例如0

在图(a)中的线性数据存储器中,分量i(0≤ 向量indx的im×indx+i寻址;同一组分在聚结的 图(b)中的存储模式寻址为

(m×bd)ixC+bd×ixB+ixA

其中
ixC=floor[(m.indx+j)/(m.bd)]=bx
ixB=j
ixA=mod(indx,bd)=tx

总之,在存储多个大小为m的向量的示例中,线性索引映射到合并索引,根据:

m.indx+i−→ m、 bd.bx+i.bd+tx

这种数据重排可以显著提高GPU全局内存的内存带宽


资料来源:“基于GPU的非线性计算加速
thread 0:  0, 1, 2
thread 1:  3, 4, 5
thread 2:  6, 7, 8
thread 3:  9, a, b
thread 0:  0, 4, 8
thread 1:  1, 5, 9
thread 2:  2, 6, a
thread 3:  3, 7, b