【问题标题】:GPU coalesced global memory access vs using shared memoryGPU 合并全局内存访问与使用共享内存
【发布时间】:2013-06-11 01:08:18
【问题描述】:

如果一个线程正在访问全局内存,为什么它要访问一个大块?这个大块存储在哪里?

如果您以合并的方式从全局内存中读取,将全局内存的公共块复制到共享内存中是否有益,或者不会有任何改进。

ie:如果每个线程正在读取接下来的 5 个或 10 个或 100 个内存位置,并将它们取平均值,如果您可以将全局内存中的一大块 X 点放入共享内存中,您是否可以不写一个 if 语句说如果您寻找这些内存值之一,从共享内存而不是全局读取?我假设翘曲发散惩罚会小于每次从全局内存中读取。

【问题讨论】:

    标签: cuda


    【解决方案1】:

    当你从全局内存中读取数据时,首先在 L1 缓存中搜索数据(高带宽,Fermi 上为 1.600GB/s,但大小有限,Fermi 上为 48KB),然后,如果 L1 中不存在,它们是在 L2 中搜索(带宽较低,但大于 L1,在 Fermi 上为 768KB),最后,如果 L2 中不存在,则从全局内存中加载它们*。

    当发生全局内存加载时,数据会先移到 L2,然后再移到 L1,以便下次需要读取全局内存时能够以更快的方式访问它们。

    这些数据可能会被后续的全局内存负载清除,也可能不会。因此,原则上,如果您正在读取“小”数据块,则不必强制数据位于共享内存中以便下次快速访问它们。

    考虑到,在 Fermi 和 Kepler 上,共享内存是由 L1 缓存的相同电路构成的。然后,您可以将共享内存视为受控的 L1 缓存

    然后,您应该强制数据驻留在共享内存中,以确保它们驻留在“最快的可用缓存”上,并且在您需要多次访问这些相同数据时执行此操作。

    请注意,以上是全局内存传输背后的一般理念。实现细节可能因底层架构而异。

    *Il 应该注意,L1 高速缓存行可以被编译器选项禁用。这在随机访问数据模式的性能方面很有用。

    【讨论】:

    • 我相信从全局读取是从 L1 缓存中读取的只有如果 L1 启用并带有编译标志。所以你在第一段中所说的并不完全正确。
    • 引用 Rob Farber,CUDA 应用程序设计和开发,第 113 页,“所有数据加载和存储都通过 L2 缓存”。在完全随机内存访问的情况下,您通常会禁用 L1 缓存,请参阅CUDA programming - L1 and L2 caches
    • 当然。我说你的第一段并不完全/不一定是真的。
    • 我编辑了答案以考虑禁用 L1 缓存行的可能性。
    • 对于计算能力 2.* 设备默认缓存全局内存。标志 -dlcm=cg 可用于仅在 L2 中缓存。对于计算能力 3.* 设备,全局内存仅缓存在 L2 中。在计算能力 3.5 设备上,可以使用 LDG 指令通过纹理访问全局内存。如果您对每个 warp 的所有 32 个线程进行移动平均,则使用共享内存可能会更快,因为共享内存每次访问只需要 1 个问题,而 L1 将需要 2 个问题,因为数据将跨越 2 个缓存行,5 个中有 4 个访问。
    猜你喜欢
    • 1970-01-01
    • 2011-09-29
    • 1970-01-01
    • 2020-04-06
    • 1970-01-01
    • 2012-05-06
    • 1970-01-01
    • 2016-10-28
    • 1970-01-01
    相关资源
    最近更新 更多