合并访问与广播访问GPU上的全局内存位置

时间:2016-02-24 19:59:59

标签: caching cuda gpu kepler

我有一个应用程序,我需要在全局内存中向所有线程广播单个(非常量,只是普通旧数据)值。线程只需要读取值,而不是写入它。我无法明确告诉应用程序使用常量缓存(例如cudaMemcpyToSymbol),因为我使用的是一个内存包装库,它不会给我显式的低级控制。

我想知道这个广播是如何在幕后进行的,以及它如何与通常的访问模式不同,其中每个线程访问一个唯一的全局内存位置(为简单起见假设这"通常"访问模式是合并的)。我对广播案例中可能发生的任何隐式序列化特别感兴趣,以及这可能会受到不同架构的影响。

例如,对于Fermi,大概是第一个访问该值的线程将它拉到L2缓存,然后到它的SM的L1缓存,此时驻留在SM上的每个线程都会尝试抓取它来自L1缓存。当所有线程尝试访问相同的L1缓存值时,是否存在任何序列化惩罚?

对于Kepler,大概是第一个访问该值的线程会将其拉到L2缓存(然后可能会也可能不会将其拉到L1缓存,具体取决于是否启用了L1缓存)。当所有线程尝试访问L2中的相同值时,是否存在序列化惩罚?

另外,分区露营是一个问题吗?

我发现另一个couple questions来解决类似主题,但其细节水平不足以满足我的好奇心。

提前致谢!

1 个答案:

答案 0 :(得分:2)

  

我有一个应用程序,我需要在全局内存中向所有线程广播单个(非常量,只是普通旧数据)值。线程只需要读取值,而不是写入它。

顺便说一下,这几乎是常量数据的定义,因为它与CUDA内核的使用有关。您可能无法利用它,但这种访问被称为" uniform"访问,如果有类型的重复访问,对于读取的线程并且不写入的值,则__constant__内存是可以考虑的可能优化。 / p>

  

我想知道这个广播是如何在引擎盖下发生的

要清楚,广播和/或序列化只有在相同warp 中的线程正在访问特定数据项时才可用。当不同warp中的线程访问同一位置时,这些术语不适用;这些将由单独的warp读取请求提供服务。

  

当所有线程尝试访问相同的L1缓存值时,是否存在任何序列化损失?

没有序列化惩罚。同一个warp中的线程可以read the same location without additional cost;从同一位置读取的所有线程将在同一周期中进行服务("广播")。读取Fermi上相同位置的单独warp中的线程将由单独的读取请求提供服务,就像您对单独warp执行的任何指令所期望的那样。在这种情况下,也没有额外或不寻常的成本。

  

当所有线程尝试访问L2中的相同值时,是否存在序列化惩罚?

在这种情况下,上述L1的same statements适用于L2。

  

另外,分区露营是一个问题吗?

分区驻留与从L1或L2缓存中检索的值无关。分区驻留通常是指数据访问模式,其导致DRAM请求不成比例地由具有多个存储器分区的GPU上的一个分区处理。对于由多个线程/ warp读取的单个位置,缓存将为此提供服务。至多应该需要一个DRAM事务来为所有彼此足够接近的请求提供服务(即忽略缓存抖动的可能性),目标是单个位置。