AMD的GCN架构在向NVIDIA Fermi靠拢,其在硬件架构上做出了巨大的改进,比之前的VLIW4和VLIW5更适合通用计算。本节介绍AMD GCN架构中和性能优化相关的部分。
1.处理器层次结构
为了满足不同的消费者的要求,GPU厂商通常采用模块化设计,通过增加或减少模块的数目来满足不同层次的需求。为了与OpenCL抽象一致,AMD将其GCN GPU模块化为3个层次:设备、CU和ALU。AMD GCN GPU第一代基于GCN架构的显卡Radeon HD7970,具有32个CU,每个CU具有64个流核心,故总共有2048个核心。每个CU具有独立的局部存储器、一级缓存和常量缓存。所有的32个核心共享统一的二级缓存,二级缓存通过交叉总线(CrossBar)连接到显存控制器。
2.CU
GCN架构中的CU除了具有4组向量核心以外,还有一个标量核心。每组向量核心包含16个标量ALU,每组向量核心每次执行一条wavefront指令。CU中的标量核心用于计算分支、常量缓存访问和其他以wavefront为单位的操作。GCN中每个CU具有64 KB局部存储器,但是每个工作组最多只可使用32 KB。GCN架构中没有单独用于超越函数计算的单元。图1-5所示为HD7970 CU结构图。
CU中计算单元主要是4个向量核心,每个核心可同时处理16个32位浮点乘加运算,这意味着CU每周期的计算能力为16×4×2=128个操作。
3.存储器层次
AMD GCN GPU的存储器和处理器一样也呈现出层次结构,这种结构通常表现出缓存的关系,比如局部存储器和二级缓存会缓存全局存储器的数据,一级缓存会缓存二级缓存中的数据。

全局存储器就是显存,它能够被整个索引空间内任何一个工作项读写,并且在多个内核的调用间持久(除非显式释放),其延迟非常大,常用来缓存主机端的大容量数据,以避免多次传输。目前常用的显存采用GDDR5技术,容量从2 GB到12 GB不等。在满足合并访问的条件下,能够获得更大的带宽。
AMD GCN GPU的存储器信息如表1-4所示,其中的吞吐量表示每时钟周期每个CU最多能够提供的带宽。
CU对全局存储器和图形存储器的访问都会通过二级缓存,二级缓存由索引空间内的所有工作项共享,HD 7970具有768 KB二级缓存。对于GPU来说,二级缓存存在的主要目的是减少访存不对齐的影响,增大带宽,而不是减少延迟,因此其容量大小远小于对应的X86 CPU。
常量存储器是只读的,索引空间内所有工作项都可以读取,且在多个内核间持久。常量存储器具有高性能、独立的缓存,为了更好地利用缓存,AMD GCN架构限制软件开发人员声明的大小为16 KB。笔者测试发现,在AMD S10000 GPU上,常量缓存的带宽为每CU每周期32字节。由于现代的GPU都具有缓存,因此常量存储器已经不那么重要,但是在某些情况下还是能够显著提升程序性能。
局部存储器只能被同一个工作组的工作项读写,且只在工作项的生存期内有效,一旦工作组执行完成即不可再用,使用时需要注意并行访问时的竞写问题。局部存储器类似于用户可控制的缓存,软件开发人员必须显式地使用。GCN架构上每个CU具有64 KB局部存储器,但是运行在CU上的每个工作组最多只能使用32 KB。GCN的局部存储器也划分为32个存储体,每个存储体宽度为4字节。局部存储器常用于通用并行计算时的共享数据和工作组通信,但是由于采用的是片上存储器,其速度极快,因此也被用于优化程序性能。笔者测试发现:在AMD S10000 GPU上,局部存储器的最大带宽为每周期每CU 128字节,但是大多数程序只能发挥64字节带宽。局部存储器的使用需要注意存储体冲突的问题。
GCN架构上每个CU具有16KB一级缓存,它们被用于缓存对全局存储器的访问。
GCN架构具有标量和向量寄存器,向量寄存器大小为256 KB,每个寄存器大小为32位,故总共有64K个寄存器。如果数据大小是64位,则会使用相邻的两个寄存器。GCN架构限制每个工作项最多可使用的向量寄存器数目为255。