CUDA 5.0内存对齐和合并访问

时间:2013-05-30 22:42:04

标签: memory-management cuda

我有一个包含10行和96列的2D主机阵列。我将此数组线性加载到我的cuda设备全局内存中,即row1,row2,row3 ... row10。

数组的类型为float。在我的内核中,每个线程都从设备全局内存中访问一个浮点值。

 The BLOCK_SIZE I use is = 96
 The GRID_DIM I use is = 10

现在我从“Cuda C编程指南”中了解到合并访问,我使用的模式是正确的,通过warp连续访问内存位置。但是有一个关于内存128字节内存对齐的条款。我不明白。

Q1)128字节内存对齐;这是否意味着warp中的每个线程应该从地址0x00(例如)到0x80开始访问4个字节?

Q2)所以在这种情况下,我是否会进行未加密的访问?

我的理解是:一个线程应该使一个内存访问应该是4个字节,从地址范围,如从0x00到0x80。如果来自warp的线程访问其外部的位置,则其为未解析的访问。

1 个答案:

答案 0 :(得分:8)

来自全局内存的加载通常以128字节的块完成,在128字节边界上对齐。合并内存访问意味着您将warp的所有访问保留为128字节的一个块。 (在较旧的卡中,必须按线程ID的顺序访问内存,但较新的卡不再具有此要求。)

如果warp中的32个线程都读取了一个浮点数,那么您将从全局内存中读取总共128个字节。如果内存正确对齐,则所有读取都来自同一个块。如果对齐关闭,则需要两次读取。如果您执行a[32*i]之类的操作,那么每次访问都将来自全局内存中不同的128字节块,这将非常慢。

只要warp中的所有线程访问同一个块,访问哪个块都无关紧要。

如果你有一个包含96个浮点数的数组,那么如果你的warp中索引为i的每个线程访问a[i],那么它将是一个合并读数。与a[i+32]a[i+64]相同。

因此,Q1的答案是所有线程都需要保持在128字节边界上对齐的128字节长度内。

Q2的答案是,如果您的阵列正确对齐,并且您的访问的格式为a[32*x+i] i,则线程ID和x任何相同的整数对于所有线程,您的访问将被合并。

根据编程指南的第5.3.2.1.1节,内存始终在至少256字节边界上对齐,因此使用cudaMalloc创建的数组始终正确对齐。