本章探讨 GPU 的内存系统。 GPU 计算内核通过加载和存储指令与内存系统交互。 传统图形应用程序与多个内存空间交互,例如纹理存储器、常量存储器和渲染表面存储器。 虽然在 CUDA 等 GPGPU 编程 API 中可以访问这些内存空间,但我们将在本章重点介绍 GPGPU 编程中使用的内存空间,尤其是实现它们所需的微架构支持。
CPU 通常包括两个独立的内存空间:寄存器文件和内存。 现代 GPU 在逻辑上将内存进一步细分为本地和全局内存空间。 本地内存空间是每个线程私有的,通常用于寄存器溢出,而全局内存用于在多个线程之间共享的数据结构。 此外,现代 GPU 通常会实现一个由程序员管理的暂存器内存,并在协作线程组中一起执行的线程之间共享访问。 包含共享地址空间的一个动机是,在许多应用程序中,程序员知道在计算的给定步骤需要访问哪些数据。 通过一次将所有这些数据加载到共享内存中,它们可以重叠长时间延迟的片外内存访问,并避免在对这些数据执行计算时对内存进行长延迟访问。 更重要的是,在给定时间内(DRAM 带宽)在 GPU 和片外内存之间传输的字节数相对于在相同时间内可执行的指令数而言是很小的。 此外,在片外存储器和 GPU 之间传输数据所消耗的能量比从片上存储器访问数据所消耗的能量高几个数量级。 因此,从片上存储器访问数据可以提高性能并节省功耗。
我们将对内存系统的讨论分为两部分,以反映内存分为驻留在 GPU 内核内的部分和连接到片外 DRAM 芯片的内存分区内的部分。