1. 单位换算
1.1 内存
1GB =
2
10
2^{10}
210MB =
2
20
2^{20}
220 KB =
2
30
2^{30}
230 B = 1073741824 B
≈
\approx
≈ 1073741824 B
≈
\approx
≈ 10亿字节
模型里的一个参数精度为fp32,需要4个字节存储。
所以一个包含10亿个精度为fp32参数的模型,需要4GB内存来保存模型参数。
1.2 性能
TOPS 是Tera Operations Per Second的缩写,1TOPS代表处理器每秒钟可进行一万亿次( 1 0 12 10^{12} 1012)操作。
- 1 GOPS(Giga Operations Per Second)代表处理器每秒钟可进行十亿次( 1 0 9 10^{9} 109)操作,
- 1 MOPS(Million Operation Per Second)代表处理器每秒钟可进行一百万次( 1 0 6 10^{6} 106)操作。
FLOPS 是floating-point operations per second的缩写,意指每秒浮点运算次数(速度)。用来衡量硬件的性能。
- 1 MFLOPS(megaFLOPS)等于每秒一百万( 1 0 6 10^{6} 106)次的浮点运算,
- 1 GFLOPS(gigaFLOPS)等于每秒十亿( 1 0 9 10^{9} 109)次的浮点运算,
- 1 TFLOPS(teraFLOPS)等于每秒一万亿( 1 0 12 10^{12} 1012)次的浮点运算,(1太拉)
- 1 PFLOPS(petaFLOPS)等于每秒一千万亿( 1 0 15 10^{15} 1015)次的浮点运算。
FLOPs 是floating point of operations的缩写,是浮点运算次数(总量),常用来衡量算法/模型复杂度,表示模型完成一次前向推理(或者包含反向传播)的浮点运算次数,常用单位GFLOPs
。
2. 模型推理速度
我们常听说模型越轻量,包含的参数量/操作次数越少,推理速度就会越快,比如一般都会认为mobilenet运行速度比VGG16要快,如果我假设mobilenet模型计算量(操作次数)是VGG16的1/30, 那么前者的推理速度会是后者的30倍吗?
模型推理时间 = 模型计算量 / 硬件算力 。这里涉及两个相关对象:模型, 硬件。
很显然,如果答案不是30倍的话,那一定是二者的硬件算力有差异。
2.1 硬件-算法协同
参考文档看这里
内存里的一个小圆圈代表一个字节数据,处理器里一个矩形框代表一次操作,处理器性能越高,矩形框越多
当模型结构固定的前提下,影响模型推理速度的因素有哪些呢?
- 算力,即硬件的处理器每秒可进行操作(加减乘除等)的次数,单位
FLOP/s
。我们经常看到板子NPU有多少TOPS(Tera Operations Per Second,1TOPS代表处理器每秒钟可进行一万亿次( 1 0 12 10^{12} 1012)操作)。在上图中对应的就是处理单元中小房子的个数。 - 内存带宽,即单位时间内内存能够读取或写入的数据量,通常以字节每秒(Bytes Per Second,
Byte/s
)计量。在上图中对应的是箭头越宽,单位时间能通过的数据越多。
内存带宽是如何影响推理速度的?
当模型(算法)的运算强度不高时,内存带宽直接影响处理器性能 能否完全释放。
什么是算法的运算强度?
算法中平均每读入单位数据,能支持多少次运算操作,单位FLOP/Byte
。
算法的运算强度 = 计算量/数据量
举个例子:
假设输入数据大小为 64x64,输入和输出 feature的通道数都为 1,数据和卷积核都用单精度浮点数 2Byte。
- 对于步长为 1 的 3x3 卷积运算:
计算量为:62x62x3x3=34596(FLOP)(需要进行 62x62 次卷积运算,每次卷积需要做 3x3=9 次乘加运算)
数据量为:64x64x2(输入数据)+ 3x3x2(卷积核数据)= 8210 (Byte)
运算强度为:34596/8210=4.21 (FLOP/Byte)- 对于步长为 1 的1x1 卷积运算:
计算量为:64x64=4096 (FLOP)
数据量为:64x64x2 + 1x1x2=8194 (Byte)
运算强度为:4096/8194=0.5 (FLOP/Byte)
不同运算强度在处理器中的体现如下图:
左边代表3x3卷积,右边代表1x1卷积。左边只需要1个数据就可以将处理器的小房子填满,右边2个数据却只能填满一个小房子。也就是说,想让处理器的性能完全释放,算法的运算强度越弱,需要的带宽越大(即需要一次能通过的数据越多)。mobilenet与VGG的运算强度就不一致,故二者的硬件算力也有可能存在差异。
Roofline模型
Roofline模型是一种用于性能分析的可视化工具,它可以帮助我们理解计算任务在特定硬件上的性能表现,并识别可能的性能瓶颈。这个模型通过两个主要的硬件指标——算力(Peak Flops/sec)和带宽(Peak Memory Bandwidth)——来评估计算任务的潜在性能,并将其表示在图表上。
在Roofline模型中,"屋顶"的高度由计算平台的峰值算力决定,所有在该平台上运行的计算任务能够达到的性能都处于这个"屋顶"的下方。如果一个任务的运算强度(Operational Intensity,即运算量和访存量的比值)较低,它可能受限于内存带宽,位于"Memory-bound"区域;如果模型量化算强度较高,则可能受限于算力,位于"Compute-bound"区域。
横坐标表示算法的运算强度,纵坐标表示处理器的性能(算力)。可以看出,达到相同的处理器性能,内存带宽越宽,对算法运算强度要求越低。
当计算平台性能达不到峰值,一方面,我们可以认为计算平台的带宽限制导致计算平台的算力不能完全发挥;另一方面我们也可以认为,模型的计算强度太低,导致对单位内存访问时的计算量太小。
Roofline 模型讲的是程序在计算平台的算力和带宽这两个指标限制下,所能达到的理论性能上界,而不是实际达到的性能,因为实际计算过程中还有除算力和带宽之外的其他重要因素,它们也会影响模型的实际性能,这是 Roofline Model 未考虑到的。例如矩阵乘法,会因为 cache 大小的限制、GEMM 实现的优劣等其他限制,导致你几乎无法达到 Roofline 模型所定义的边界(屋顶)。
2.2 如何确定一个模型的运算强度, 以及衡量模型与硬件的适配性?
参考文档看这里,分析得非常棒,主要对比了VGG16和mobilenet这两个模型的运算强度,以及在1080Ti硬件上的表现。
数据量:指的是输入单个样本,模型完成一次前向传播过程中所发生的内存交换总量,也即模型的空间复杂度。在理想情况下(即不考虑片上缓存),模型的访存量就是模型各层权重参数的内存占用(Kernel Mem)与每层所输出的特征图的内存占用(Output Mem)之和。单位是Byte。由于数据类型通常为float32 ,一个数据需要4个字节来存放,故参数量需要乘以四。
模型 | 计算量(FLOPs) | 数据量(Byte) | 运算强度(FLOP/Byte) |
---|---|---|---|
VGG16 | 15,470,264,320 | 614,427,296 | 25.17 |
MobileNet | 568,740,352 | 77,975,008 | 7.29 |
硬件 | 算力(FLOPS) | 带宽(Byte/s) | 计算强度(FLOP/Byte) |
---|---|---|---|
1080Ti | 11.3T | 484G | 23.34 |
虽然 MobileNet 前向传播的计算量是VGG16 的三十分之一,但是由于计算平台的带宽限制,它不能像 VGG 那样完全利用 1080Ti 这个计算平台的全部算力,理论上计算出MobileNet运行速度大约只是VGG16的十倍,如下表所示。
模型 | 计算量(FLOPs) | 在1080Ti上能达到的算力(FLOPS) | 耗时(ms) |
---|---|---|---|
VGG16 | 15,470,264,320 | 11.3 T | 0.164 |
MobileNet | 568,740,352 | 3.3T | 1.327 |
因此MobileNet 这类小型网络更适合运行在嵌入式平台之上。由于这类计算平台本身的计算强度上限就很低,可能比 MobileNet 的计算强度还要小,因此 MobileNet 运行在这类计算平台上的时候,它就不再位于 Memory-Bound 区域,而是农奴翻身把歌唱的进入了 Compute-Bound 区域(是吗?那模型参数量化后,不就更加是在计算受限区吗?算力没法进一步提升呀,如何体现量化加速呢?答:主要还是利用整形运算速度快的优势),此时 MobileNet 和 VGG16 一样可以充分利用计算平台的算力,而且内存消耗和计算量都小了一两个数量级,同时分类准确率只下降了1%,所以大家才愿意用它。
给我的启发是:
在做模型部署的时候,在硬件平台确定的前提下,一定要计算一下模型位于内存受限区还是计算受限区.
如果位于内存受限区,可以替换数据复用率更高的模块,来提高模型计算强度,降低对内存带宽的需求,或者进行模型量化,变相扩充内存带宽。
如果已经位于计算受限区,还想近一步提速,可以考虑替换计算量更小的模块, 或者适当减小输入图片尺寸(模型参数量不便变,但计算量减少,注意缩小程度,不要使模型进入内存受限区)。
注意:无论做哪种优化操作,都需要在操作后重新计算新模型位于哪个区域,计算新的推理速度。
3. 模型量化
概论知识树可参考该文档
模型量化是将神经网络模型的权重和激活值映射到一组较小的离散值(通常为整数)上,以减小模型大小和计算复杂度,虽然会引入量化误差,但可显著降低模型内存占用和推理时间。
模型量化带来的好处
- 占用更少的内存空间。比如从fp32–>int8,理论上数据量会变为原来的1/4。
- 推理提速。
- 变相增加了内存带宽或提高了模型的运算强度。如果模型原本位于内存受限区,模型量化后就有可能进入计算受限区,从而提高了算力,推理速度也就提高了。
- 整形运算一般比浮点型运算速度更快。从指令周期缩短的角度分析可参考文档看这里。另外,在很多专门为神经网络部署设计的芯片上,往往会存在专门为整型运算设计的加速单元。
- 更低的能耗与占用面积。整形运算需要的晶体管更少。
如何实现模型量化
模型量化分类
QAT & PTQ
QAT->quantization aware training 量化感知训练
PTQ->post training quantization 训练后量化