背景:本文是《AI 编译器开发指南》一书的学习笔记。
AI模型在专用加速卡上性能分析大概流程:
1)先计算模型本身的计算访存比,得到模型理论算力带宽需求。
2)根据处理器本身支持的操作字节比(算力,带宽),确认模型在该处理器上的性能表现类型。
3)根据专用加速器内部架构的内存和计算并行性的设计,分析AI模型运行时的schedule,估算得到模型在加速卡上的执行周期。
名词定义
- 指令级并行性(Instruction-level Parallelism,ILP)
- 线程级并行(Thread-level Parallelism, TLP)
- 内存级并行性(Memory-level Parallelism, MLP)
- 内存线程束并行性(Memory Warp Parallelism, MWP)
- 计算线程束并行性(Computation Warp Parallelism, CWP)
就GPU而言,如果线程束调度器在每次指令发射时,从同一线程束中选择独立指令,则表现为ILP;如果线程束调度器在每次发射指令时,从不同线程束选择独立指令,则表现为TLP。GPU主要通过提高TLP来最大限度地利用其功能单元,SM占用率作为GPU程序TLP的定量分析指标,对GPU整体性能有重要影响。
一、AI模型在处理器的性能影响因素
计算并行性和存储访问效率是硬件架构决定AI模型性能的两个最重要因素。相应的,GPU和专用硬件架构为AI模型进行性能优化的方式也围绕着如何提高并行计算能力和高效利用片上存储资源展开。
从影响计算性能角度出发,GPU或者专用硬件架构运行AI模型性能的约束类型分为:内存带宽受限型, 计算速度受限型,延迟受限型。
内存受限:内存受限型AI模型性能取决于硬件内存带宽。当AI模型的计算密度较小时候(如激活函数,池化,和批量归一化算子),几乎都可能成为内存受限模型。即数据传输速度跟不上计算速度。
计算受限:当具有较多的如矩阵乘等大量计算的算子时候,这时候模型可能会成为计算受限模型。即计算速度跟不上数据传输速度。
延迟受限:在执行AI模型时,GPU设备上的线程束调度器选择就绪指令,并将其发射到线程束的活跃线程,SM准备执行线程束下一条指令所需的时钟周期数即为延迟。如果延迟是由寄存器相关性引起的,即某些输入操作数是由尚未执行完成的前一指令写入的,这时,延迟等于前一指令的执行时间,线程束调度器必须在这段时间内调度其他活跃线程束的指令以隐藏延迟。延迟受限型的AI模型则是由于没有足够的工作负载和相应的活跃线程束,无法隐藏线程束等待切换的延迟而导致性能下降。
二、计算访存比指标
确定模型时计算受限型或者访存受限型时,应首先分析模型在具体场景下的计算访存比,即计算吞吐量和访存吞吐量的比值。
以AI模型中常用的GEMM为例,分析访存比的计算。规定矩阵A,B, C的大小分别是MK, K
N,M
N。优化GEMM的一个方案是将C进行分片处理。分片大小分别是
,
,
每个C分片的访存吞吐量是()
K,计算吞吐量是2
K, 常数2是乘法和加法两次计算,计算访存比是(2
)/(
),为了使GEMM计算充分利用GPU的峰值计算能力,希望计算访存比越大越好,也就是
和
越大越好。但是共享内存中的元素需要提前加载到寄存器,并且
和
的取值受到线程块的共享内存容量和寄存器文件大小的限制。
三、算术强度和操作字节比的定义
定义AI模型访存占用时间为,计算占用时间为
,模型访问字节数为#bytes, 模型运算次数为#ops, 处理器内存带宽
,计算带宽
。
= #bytes /
,
=#ops /
计算受限模型是>
, 反之是内存受限型。
如下公式可以推导出算术强度和操作字节比的定义。算术强度可以理解为每从内存读写一个字节需要执行的操作数。操作字节比则与模型无关,只与给定处理的带宽参数有关。
>
=》 #ops /
> #bytes /
=>
#ops / #bytes > /
算术强度= #ops / #bytes
操作字节比 = /
不同AI模型的算术强度变化范围很大,因此没有一种通用的加速器,比如卷积神经网络一般认为是计算密集型,而机器翻译和自然语言处理模型通常由全连接层组成,权重重用少,需要消耗较多的存储空间,所以AI模型的计算结构和规模决定其算术强度,进而决定其对特定硬件架构的适用性。
以V100 GPU执行GEMM为例,V100的FP16峰值计算性能是125TFLOPS,片外存储带宽约为900GB/s, 片上L2带宽为3.1TB/s
- 如果输入数据来自片外存储器,操作字节比约为125/0.9≈138.9
- 如果输入数据来自片上存储器,操作字节比约为125/3.1≈40
对于MK
N的GEMM来说,算术强度 =
=
, 分子的2是指FMA的乘法和加法, 分母的乘法是指FP16类型的2byte。
当GEMM的形状是8192128
8192,算术强度是124.1,低于V100的操作字节比138.9,该操作为内存受限型
当GEMM的形状是81928192
8192,算术强度是2730,远高于V100的操作字节比138.9,该操作是计算受限型。
判断AI模型时内存受限还是计算受限型的前提是模型的工作负载足够大,足以令处理器的算术或存储流水线一直处于饱和工作状态。如果AI模型的工作负载不够大,不能提供足够的并行性,处理器无法充分利用,此模型则既不属于计算受限也不属于内存受限,而是属于延迟受限型。
在评估模型性能首先类型时,开发者应该首先通过评估AI模型工作负载需要消耗的线程块数量和大小,确定工作负载是否足够的并行性使GPU资源达到饱和。通过如果AI模型消耗的线程块数量达到SM的4倍,则可以认为,AI模型的工作负载有足够的并行性,不属于延迟受限型。
综上,对于GEMM计算
- 1)当K很小时,即M≈N >> K, GEMM为延迟受限型
- 2)当M或N很小时,即N≈K >> M, 或M≈K >> N,GEMM为内存受限型
- 3)当M,N,K都很大时,GEMM为计算受限型。
优化AI模型性能的另一个关键因素是提高全局内存访问效率。全局内存驻留在设备内存中,设备内存可通过128字节,64字节或32字节内存事务访问。这些内存事务只能读取或写入与其大小对其的设备内存的128字节,64字节或32字节。根据GPU的计算能力或运行时配置,当某个线程束执行一条访问全局内存的指令时,如果线程束中各线程的全局内存访问地址落入相同的128字节,64字节或32字节地址段,则这些全局内存访问可以合并为128字节,64字节或32字节内存事务。如果不采用合并访问方式,而是发散访问,则需要发射额外的内存事务。发散访问的方式会导致全局内存吞吐量降幅非常显著。
比如为每个线程4字节访问生成一个32字节的内存事务,每个内存事务包含28字节无用数据,导致全局内存吞吐量降低32/4=8倍,如果采用128字节内存事务,则全局内存吞吐量降低32倍。因此发散访问导致线程束吞吐量下降比由此导致的线程束延迟增加严重的多。为了最大化内存吞吐量,优化全局内存访问尤为重要,因为与片上存储器带宽和算术指令吞吐量相比,全局内存带宽较低,因此全局内存访问通常对性能有重要影响。
四、内存级并行性和线程级并行性指标
内存线程束并行性(MWP)用于刻画系统内存并行性,其表示从SM处理器开始执行某个线程束的内存指令后,到同一线程束的所有内存请求得到服务为止的时间段内,每个SM可以同时访问内存的最大线程束数量。
计算线程束并行性(CWP)用于刻画模型特征,表示SM处理器在一个内存线程束等待期间可以执行的线程束数量加1,加1是为了包括等待内存值的线程束本身。CWP与算术强度有相似之处和不同之处,相似之处在与两者都表示访存操作与运算操作的比例关系,不同之处在于,算术强度不具有时序信息,而CWP重点考虑内存等待周期内的时序信息,并可用于确定代码段总执行时间是由计算占用时间决定,还是由访存占用时间决定。内存等待周期表示系统处理内存请求的时间段。
如上图,白色方框表示计算指令占用的计算周期,彩色方框表示访存指令占用的内存等待周期,方框中的标识表示线程束序号。图6-2中所有的计算周期和内存等待周期来自第i-i+7个不同的线程束。从图上可以看出1个内存等待周期是计算周期的2倍,所以CWP=2+1=3。图6-2的左图假设系统可以同时处理两个内存线程束,即MWP=2。图6-2的有图假设系统可以同时处理8个内存线程束,所以MWP=8。
可以发现左图CWP>MWP, SM中由足够多的线程束等待内存值,所以内存访问周期可以被计算周期隐藏。代码段总执行时间为2个计算周期+4个内存等待周期之和。而右图CWP<MWP,代码段总执行时间为8个计算周期+1个内存访问周期之和。
综上,当CWP大于MWP时,执行成本主要由访存占用时间决定;当CWP小于MWP时,执行成本主要由计算占用时间决定。
基于MWP和CWP指标建立GPU性能模型通过评估每个SM在一个内存等待周期内可以同时访问的线程束数量,以及可以在同一时间段内完成计算的线程束数量,进而离线估算得到模型执行的时钟周期数,而不需要实际执行模型。