Memory CUDA本地内存寄存器溢出开销

Memory CUDA本地内存寄存器溢出开销,memory,cuda,gpu-local-memory,Memory,Cuda,Gpu Local Memory,我有一个内核,它使用了很多寄存器,并将它们大量地溢出到本地内存中 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] 由于溢出似乎相当高,我相信它会通过一级缓存甚至二级缓存。由于本地内存对每个线程都是私有的,编译器如何合并对本地内存的访问?该内存是否像

我有一个内核,它使用了很多寄存器,并将它们大量地溢出到本地内存中

    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]
由于溢出似乎相当高,我相信它会通过一级缓存甚至二级缓存。由于本地内存对每个线程都是私有的,编译器如何合并对本地内存的访问?该内存是否像全局内存一样在128字节事务中读取?有了这些溢出量,我的内存带宽利用率很低(50%)。我有类似的内核,没有溢出,可以获得高达80%的峰值内存带宽

编辑 我使用
nvprof
工具从中提取了更多指标。如果我很了解上面提到的技术,那么由于寄存器溢出(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字节的,而不是我所想到的位事务。

根据 寄存器溢出对性能的影响不仅仅是编译时决定的合并;更重要的是:从二级缓存读/写已经非常昂贵,您希望避免这种情况

该演示文稿建议,使用探查器,您可以在运行时计算由于本地内存(LMEM)访问而产生的二级查询数,查看它们是否对所有二级查询的总数有重大影响,然后优化共享与一级查询的比率,以利于后者,例如,通过单个主机调用 cudaDeviceSetCacheConfig(cudaFuncCachePreferL1)


希望这有帮助。

128位事务中不会读取全局内存。从全局内存加载的L2缓存线由32个字节组成。L1缓存线加载由128字节组成。@RobertCrovella我想我当时指的是设备内存。为了获得高内存带宽,需要利用这些128位事务(warp中的线程以对齐方式访问全局内存)。全局加载不是缓存在L1中,而是缓存在L2中,因为L2一次提供256bit的数据,所以这样就可以了。溢出的寄存器会发生什么情况?当所有线程都请求已写入dram的溢出值时,是否使用这些128位事务提供服务?或者它比合并的全局内存读取慢?来自本地的l2加载流量百分比=(4*l1\u local\u load\u miss)/(4*SUM(l2\u sub*\u total\u read\u sector\u查询)。您不必计算命中率。本地内存对扭曲中的线程进行32位交织。如果所有线程访问同一堆栈变量,则访问完全合并(默认情况)。全局和本地内存访问都通过L1进行,并且具有相同的性能。带宽的减少可能是由于扭曲阻止读取本地内存。对于255个寄存器/线程,您的理论占用率将为@GregSmith(1)为什么将L2的读取总和乘以4?(2)我通过限制使用的寄存器数量(127个)使占用率翻了一番,但这减慢了内核的速度。增加的溢出似乎起到了主导作用如果本地内存是32位交错的,如何处理双精度浮点的情况?我假设这仍然会合并?谢谢。全局内存读取也会经过L2,因此我希望溢出内存的这些读取具有类似的延迟(不同的是跳过L1)。但是,我的warp中的所有线程都以合并的方式访问连续的内存位置,这意味着它们可以生成将数据放入寄存器所需的最小事务数。我想知道编译器是否足够聪明,可以对本地内存执行相同的操作。本地和全局请求都通过L1,并在相同的时间内完成ete假设事务的所有128字节都已使用。@GregSmith感谢您指出,我已经阅读了您对文章的评论,我将编辑上面的暂定答案,以删除有问题的行:)