第7章. GPU内存访问模式的分析 与优化
本作品已使用人工智能进行翻译。欢迎您提供反馈和意见:translation-feedback@oreilly.com
随着AI模型规模与复杂度的增长,GPU内存系统常成为理论计算能力与实际性能之间的瓶颈。正如第六章所述,现代NVIDIA GPU融合了数千个简单的高吞吐量优化核心与专用张量核心。其架构还包含高带宽内存(HBM)、CPU-GPU统一内存地址空间(如Grace Blackwell超级芯片)、片上共享内存、缓存,以及张量内存加速器(TMA)等专用直接内存访问(DMA)引擎。
本章将展示多种CUDA C++与PyTorch优化技术,包括:调整数据结构以实现高效内存访问、消除冗余数据加载、利用硬件实现数据传输与计算的重叠处理。
通过矩阵乘法、张量运算等具体案例的前后对比,您将看到内存访问模式、分块策略和异步数据传输的细微调整如何减少带宽浪费、提升运算效率,并使内核从内存瓶颈转变为计算瓶颈。
本章结束时,您将掌握如何编写能充分利用GPU内存层次结构和硬件优化数据传输引擎的CUDA内核。
合并式与非合并式全局内存访问
代码的内存访问模式 会显著影响性能。当波段内线程访问连续内存地址时,全局内存访问速度最快——硬件可将这些请求合并为更少的大型事务。若线程访问分散或错位地址,设备无法将请求合并为最小缓存行事务(现代GPU中为128字节行,由四个32字节扇区组成),导致大量内存事务检索未使用数据,迅速耗尽带宽。
在Blackwell GPU上,单设备HBM3e带宽可达8 TB/s。在Grace Blackwell GB200和GB300(双GPU超级芯片)中,跨GPU总带宽提升至16 TB/s。若采用未合并的内存访问方式,过多的内存交易和停滞将导致大部分带宽闲置。
在非合并访问场景下,每个线程从分散地址加载数据,导致大量独立内存事务。即使线程访问连续地址,若起始地址未对齐128字节边界,该线程请求仍会跨越两个128字节缓存行。
例如,若波段首个线程起始地址未对齐128字节,其内存请求将跨越缓存行边界,通常导致两个128字节事务而非一个。此时,该Warp可能在最佳的四个扇区之外额外获取一个扇区,导致跨两条缓存线的总扇区数达到五个。这会造成带宽浪费。对于未对齐但连续的128字节Warp加载操作,其访问的扇区数是5×32字节还是8×32字节取决于起始偏移量。而对齐访问则始终保持在4×32字节扇区范围内。
但在合并访问场景中,多个线程会将连续地址的加载操作合并为单次宽交易。图7-1对比了合并与非合并内存访问模式。
图7-1. 融合式与非融合式内存访问模式对比
在内核代码中,此问题通常表现为步进索引或不规则索引( ),导致各线程访问不同缓存行。当内核线程使用步进索引或不规则索引获取数据时,GPU会发出大量未合并的全球内存小交易,而非少数全宽加载操作。
在Nsight Compute中,当存在未合并模式时,内存负载分析部分将显示全局内存加载效率降低、DRAM扇区读取次数增加,且平均每次请求扇区数超过4.0。这是因为读取的扇区数量超过了合理合并的内存访问模式,表明您正因读取大量未使用字节而浪费带宽。此时DRAM吞吐量百分比将持续远低于峰值。这证实您的warp周期正因内存阻塞而非ALU运算而空转。
要突破这种内存有界状态,可重组数据结构使每个波束的32个线程加载连续元素。具体方法包括:采用索引数组 ...
Become an O’Reilly member and get unlimited access to this title plus top books and audiobooks from O’Reilly and nearly 200 top publishers, thousands of courses curated by job role, 150+ live events each month,
and much more.
Read now
Unlock full access