我对CUDA中合并的全局内存负载有疑问。目前,我需要能够在具有计算能力CUDA 1.1或1.3的CUDA设备上执行。
我正在编写一个CUDA内核函数,它将类型为T的数组从全局内存读入共享内存,进行一些计算,然后将类型T的数组写回全局内存。我正在使用共享内存,因为每个输出元素的计算实际上不仅取决于相应的输入元素,还取决于附近的输入元素。我只想加载每个输入元素一次,因此我想将输入元素缓存在共享内存中。
我的计划是让每个线程在开始计算之前将一个元素读入共享内存,然后__syncthreads()。在这种情况下,每个线程加载,计算和存储一个元素(尽管计算依赖于其他线程加载到共享内存中的元素)。
对于这个问题,我想集中讨论从全局内存到共享内存的读取。
假设数组中有N个元素,我已配置CUDA以执行总共N个线程。对于sizeof(T)== 4的情况,根据我对CUDA的理解,这应该很好地合并,因为线程K将读取单词K(其中K是线程索引)。
但是,在sizeof(T) < 4
的情况下,例如如果T = unsigned char或T = short,那么我认为可能存在问题。在这种情况下,我的(天真)计划是:
我担心的是它不会合并,因为(例如,在T =短的情况下)
换句话说,线程K读取字(K / sizeof(T))。这似乎没有正确地合并。
我考虑的另一种方法是:
有人可以告诉我,我对我的计划的假设是否正确:即:它不能正常合并?
请您评论我的替代方法吗?
您能推荐一种能够正确合并的更佳方法吗?
答案 0 :(得分:3)
你是对的,你必须做至少32位的加载才能合并,你描述的方案(让其他所有线程都加载)将不会合并。只需将偏移量右移2位,让每个线程执行连续的32位加载,并使用条件代码禁止执行将在超出范围的地址上运行的线程。
由于您的目标是SM 1.x,请注意1)为了进行合并,给定warp的线程0(32个线程的集合)必须为64,128或256字节对齐4 - ,分别为8和16字节操作数,以及2)一旦您的数据在共享内存中,您可能希望将循环展开2x(简称)或4x(对于char),因此相邻的线程引用相邻的32位单词,以避免共享内存库冲突。