如何使用合并内存访问

时间:2011-07-03 13:51:25

标签: gpu shared-memory coalesce

我有'N'个线程同时在设备上执行,它们需要M * N从全局内存中浮动。访问全局内存合并的正确方法是什么?在这个问题上,共享内存如何帮助?

1 个答案:

答案 0 :(得分:15)

通常,当相邻线程访问内存中的相邻单元时,可以实现良好的合并访问。因此,如果tid包含您的线程的索引,那么访问:

  • arr[tid] ---给出完美的合并
  • arr[tid+5] ---几乎是完美的,可能未对齐
  • arr[tid*4] ---因为空白而不再那么好了
  • arr[random(0..N)] ---太可怕了!

我是从CUDA程序员的角度谈论的,但类似的规则也适用于其他地方,即使是在简单的CPU编程中,尽管影响并不大。


“但是我有这么多阵列,每个人都比我的线程数长2到3倍,使用像”arr [tid * 4]这样的模式是不可避免的。这可能是什么治疗方法?“

如果偏移是某个更高的2次幂(例如16 * x或32 * x)的倍数,则不是问题。因此,如果你必须在for循环中处理一个相当长的数组,你可以这样做:

for (size_t base=0; i<arraySize; i+=numberOfThreads)
    process(arr[base+threadIndex])

(以上假设数组大小是多个的线程数)

因此,如果线程数是32的倍数,那么内存访问就会很好。

再次注意:我是从CUDA程序员的角度谈论的。对于不同的GPU /环境,您可能需要更少或更多的线程来实现完美的内存访问合并,但类似的规则应该适用。


与经线大小相关的“32”是否与全局存储器并行访问?

虽然没有直接,但有一些联系。全局内存分为32,64和128字节的段,可通过半warp访问。您为给定的内存提取指令访问的段越多,它就越长。您可以在“CUDA编程指南”中详细了解更多详细信息,这一主题有一整章:“5.3。最大化内存吞吐量”。

另外,我听说了一些关于共享内存以本地化内存访问的内容。这对于内存合并是首选还是有其自身的困难? 共享内存在芯片上更快,但其大小有限。内存不像全局一样被分段,你可以几乎随机访问,无需花费。但是,存在宽度为4字节的存储体线(32位int的大小)。每个线程访问的内存地址应该是16(或32,取决于GPU)不同的模块。因此,地址[tid*4]将比[tid*5]慢得多,因为第一个只能访问0,4,8,12和后者0,5,10,15,4,9,14, ...(银行ID =地址模16)。

同样,您可以在CUDA编程指南中阅读更多内容。