【发布时间】:2018-06-04 00:29:15
【问题描述】:
我有一个内核,它使用大量寄存器并将它们大量溢出到本地内存中。
4688 bytes stack frame, 4688 bytes spill stores, 11068 bytes spill loads
ptxas info : Used 255 registers, 348 bytes cmem[0], 56 bytes cmem[2]
由于溢出看起来相当高,我相信它会超过 L1 甚至 L2 缓存。由于本地内存对每个线程都是私有的,编译器如何合并对本地内存的访问?该内存是否像全局内存一样以 128 字节事务读取?有了这么多的溢出,我的内存带宽利用率很低(50%)。我有类似的内核,没有溢出,可以获得高达 80% 的峰值内存带宽。
编辑
我使用nvprof 工具提取了更多指标。如果我很好地理解了here 提到的技术,那么由于寄存器溢出(4 * l1 命中和未命中/L2 的 4 个扇区的所有写入的总和 = (4 * (45936 + 4278911)) / (5425005 + 5430832 + 5442361 + 5429185) = 79.6%),我有大量的内存流量。有人可以验证我是否在这里吗?
Invocations Event Name Min Max Avg
Device "Tesla K40c (0)"
Kernel: mulgg(double const *, double*, int, int, int)
30 l2_subp0_total_read_sector_queries 5419871 5429821 5425005
30 l2_subp1_total_read_sector_queries 5426715 5435344 5430832
30 l2_subp2_total_read_sector_queries 5438339 5446012 5442361
30 l2_subp3_total_read_sector_queries 5425556 5434009 5429185
30 l2_subp0_total_write_sector_queries 2748989 2749159 2749093
30 l2_subp1_total_write_sector_queries 2748424 2748562 2748487
30 l2_subp2_total_write_sector_queries 2750131 2750287 2750205
30 l2_subp3_total_write_sector_queries 2749187 2749389 2749278
30 l1_local_load_hit 45718 46097 45936
30 l1_local_load_miss 4278748 4279071 4278911
30 l1_local_store_hit 0 1 0
30 l1_local_store_miss 1830664 1830664 1830664
编辑
我意识到这是 128 字节,而不是我想的位事务。
【问题讨论】:
-
全局内存不在 128 位事务中读取。从全局内存加载的 L2 高速缓存线由 32 个字节组成。一个 L1 缓存线加载由 128 个字节组成。
-
@RobertCrovella 我想我当时的意思是设备内存。为了实现高内存带宽,需要利用这些 128 位事务(warp 中的线程以对齐的方式访问全局内存)。全局负载不会缓存在 L1 中,而是在 L2 中,并且由于 L2 一次提供 256 位,因此效果很好。溢出的寄存器会发生什么?当所有线程都请求已写入 dram 的溢出值时,是否使用这些 128 位事务提供服务?还是比合并的全局内存读取慢?
-
来自本地的 l2 负载流量百分比 = (4 * l1_local_load_miss) / (4 * SUM(l2_sub*_total_read_sector_queries)。您不必计算点击次数。
-
本地内存是 32 位交错的,用于 warp 中的线程。如果所有线程都访问同一个堆栈变量,则访问是完全合并的(默认情况)。全局和本地内存访问都经过 L1 并且具有相同的性能。带宽的减少可能是由于扭曲停止读取本地内存。使用 255 个寄存器/线程,您的理论占用率将
-
@GregSmith (1) 为什么要将 L2 的读取总和乘以 4? (2) 通过对使用的寄存器数量(127)施加限制,我能够使占用率增加一倍,但这会减慢内核速度。增加的溢出似乎具有主导作用。 (3) 如果本地内存是32位交错的,双精度浮点数的情况如何处理?我认为这仍然会合并?
标签: memory cuda gpu-local-memory