Cuda 如何使用short或char类型的元素(假设每个元素有一个线程)正确地将全局内存中的读取合并到共享内存中?

Cuda 如何使用short或char类型的元素(假设每个元素有一个线程)正确地将全局内存中的读取合并到共享内存中?,cuda,gpu,nvidia,Cuda,Gpu,Nvidia,我有一个关于CUDA中合并的全局内存负载的问题。目前,我需要能够在具有CUDA 1.1或1.3计算能力的CUDA设备上执行 我正在编写一个CUDA内核函数,它将一个T型数组从全局内存读入共享内存,进行一些计算,然后将一个T型数组写回全局内存。我之所以使用共享内存,是因为每个输出元素的计算实际上不仅取决于相应的输入元素,还取决于附近的输入元素。我只想加载每个输入元素一次,因此我想将输入元素缓存在共享内存中 我的计划是让每个线程将一个元素读入共享内存,然后在开始计算之前uu syncthreads(

我有一个关于CUDA中合并的全局内存负载的问题。目前,我需要能够在具有CUDA 1.1或1.3计算能力的CUDA设备上执行

我正在编写一个CUDA内核函数,它将一个T型数组从全局内存读入共享内存,进行一些计算,然后将一个T型数组写回全局内存。我之所以使用共享内存,是因为每个输出元素的计算实际上不仅取决于相应的输入元素,还取决于附近的输入元素。我只想加载每个输入元素一次,因此我想将输入元素缓存在共享内存中

我的计划是让每个线程将一个元素读入共享内存,然后在开始计算之前uu syncthreads()。在此场景中,每个线程加载、计算和存储一个元素(尽管计算取决于其他线程加载到共享内存中的元素)

对于这个问题,我想重点讨论从全局内存到共享内存的读取

假设数组中有N个元素,我将CUDA配置为总共执行N个线程。对于sizeof(T)==4的情况,根据我对CUDA的理解,这应该很好地结合起来,因为线程K将读取单词K(其中K是线程索引)

但是,在
sizeof(T)<4
的情况下,例如,如果T=unsigned char或T=short,则我认为可能存在问题。在这种情况下,我的(天真的)计划是:

  • 计算numElementsPerWord=4/sizeof(T)
  • 如果(K%numElementsPerWord==0),则read让线程K读取下一个完整的32位字
  • 将32位字存储在共享内存中
  • 在共享内存被填充后,(并调用了_syncthreads()),每个线程K都可以处理计算输出元素K的工作
我担心的是它不会合并,因为(例如,在T=short的情况下)

  • 线程0从全局内存读取字0
  • 线程1不读取
  • 线程2从全局内存读取字1
  • 线程3不读取
  • 等等
换句话说,线程K读取单词(K/sizeof(T))。这似乎没有正确地结合在一起

我考虑的另一种方法是:

  • 启动时线程数=(N+3)/4,这样每个线程将负责加载和处理(4/sizeof(T))元素(每个线程处理一个32位字-可能是1、2或4个元素,具体取决于sizeof(T))。然而,我担心这种方法不会尽可能快,因为每个线程必须完成两倍(如果T=short)甚至四倍(如果T=unsigned char)的处理量
有人能告诉我我对我的计划的假设是否正确吗:即:它不会正确地结合在一起

你能评论一下我的替代方法吗


你能推荐一种更合适的合并方法吗?

你是正确的,你必须进行至少32位大小的加载才能实现合并,而你描述的方案(让每个其他线程进行加载)将不会合并。只需将偏移量右移2位,让每个线程执行一个连续的32位加载,并使用条件代码禁止在超出范围的地址上运行的线程执行

由于您的目标是SM 1.x,还请注意1)为了进行合并,给定扭曲(32个线程的集合)的线程0必须分别为4、8和16字节操作数的64、128或256字节对齐,2)一旦数据在共享内存中,您可能希望将循环展开2倍(简称)或4倍(字符)所以相邻线程引用相邻的32位字,以避免共享内存库冲突