不知道大家有没有以下这些疑问:
回答: 模型的推理速度主要看两个方面,一个是模型本身,另一个是模型在什么计算平台上跑(CPU/GPU/BPU/NPU),模型和计算平台的"默契程度"综合决定模型的实际表现(FPS)。例如最常见的:GPU对常规卷积加速更多,CPU对深度可分离卷积支持效果更好。
那“默契程度”又体现在什么地方呢?
常常听到的计算量、参数量、访存量、内存占用、ddr的访问带宽又和哪些因素有关系呢?
进入正题:Roofline Model 提出 Operational Intensity(计算强度)的概念,并给出模型在计算平台上所能达到理论计算性能上限公式。
计算平台的算力,又称为计算平台的性能上限,指的是:一个计算平台每秒钟最多能完成的浮点运算数。单位是 FLOPS or FLOP/s。
计算平台的带宽上限,指的是:一个计算平台每秒钟最多能完成的“内存”交换量。单位是Byte/s。
计算平台的计算强度上限指的是:计算平台上,单位“内存”交换 最多用来进行多少次计算,也就是用计算平台的算力除以计算平台的带宽。单位是FLOPs/Byte。
I m a x = π β I_{max} = \frac{\pi}{\beta} Imax=βπ
“内存”:CPU的内存、GPU的显存
计算量,又称为浮点运算量,表示网络前向传播时需要进行的加法操作和乘法操作的次数,也即模型的时间复杂度。单位是FLOPs。
参数量是指参数的个数。
深度卷积神经网络中绝大部分的计算量和参数量均集中在卷积层和全连接层。
卷积层的计算量为:
访存量是指输入一个样本,模型完成一次前向传播过程中所发生的内存交换总量,也即模型的空间复杂度。
访存量是指模型前向推理时所需访问存储单元的字节大小,反映了模型对存储单元带宽的需求。
在理想情况下(即不考虑片上缓存),模型的访存量就是模型各层权重参数的内存占用(Kernel Mem)与每层所输出的特征图的内存占用(Output Mem)之和。单位是Byte(或者 KB/MB/GB)。
由于数据类型通常为float32 ,因此需要乘以四。
卷积层的访存量为:
B c o n v = K 1 × K 2 × C i n × C o u t + H o u t × W o u t × C o u t B_{conv} = K_1 × K_2 × C_{in} × C_{out} + H_{out} × W_{out} × C_{out} Bconv=K1×K2×Cin×Cout+Hout×Wout×Cout
模型的计算强度,又称为计算访存比、计算密度:模型的计算量除以模型的访存量。表示模型在计算过程中,每Byte内存交换用于进行多少次浮点运算。单位是FLOPs/Byte。
I = F B I = \frac{F}{B} I=BF
模计算强度越大,其内存使用效率越高。
理论上,模型在计算平台上所能达到的每秒浮点运算次数。单位是 FLOPS or FLOP/s。使用Roof-line Model来衡量。
内存占用是指模型运行时,所占用的内存/显存大小。一般需要关注的是最大内存占用。注意,内存占用 ≠ 访存量。
内存占用大小除了受模型本身影响外,还受软件实现的影响。
例如,有的框架为了保证推理速度,会将模型中每一个 Tensor 所需的内存都提前分配好,因此内存占用为网络所有 Tensor 大小的总和。更多的框架会提供 lite 内存模式,即动态为 Tensor 分配内存,以最大程度节省内存占用(当然可能会牺牲一部分性能)。
内存占用不会直接影响推理速度,往往算作访存量的一部分。但在同一平台上有多个任务并发的环境下,如推理服务器、车载平台、手机 APP,往往要求内存占用可控。可控一方面是指内存/显存占用量,如果占用太多,其他任务就无法在平台上运行;另一方面是指内存/显存的占用量不会大幅波动,影响其他任务的可用性。
模型在一个计算平台的限制下,到底能达到多快的浮点计算速度。
具体来说:Roof-line Model模型解决的是:计算量为A且访存量为B的模型在算力为C且带宽为D的计算平台所能达到的理论性能上限E是多少的问题。
Roof-line,指的是由计算平台的算力和带宽上限这两个参数所决定的“屋顶”形态,如下图所示。
当模型的计算强度 I I I小于计算平台的计算强度上限 I m a x I_{max} Imax 时,此时模型位于“房檐”区间,模型理论性能 P P P的大小完全由计算平台的带宽上限 β \beta β(房檐的斜率)以及模型自身的计算强度 I I I所决定。
这时候就称模型处于 Memory-Bound 状态。
在模型处于带宽瓶颈区间的前提下,计算平台的带宽 β \beta β越大(斜率越大,房檐越陡),或者模型的计算强度 I I I越大,模型的理论性能 P P P可呈线性增长。
不管模型的计算强度 I I I 有多大,它的理论性能 P P P最大只能等于计算平台的算力 π \pi π。
当模型的计算强度 I I I 大于计算平台的计算强度上限 I m a x I_{max} Imax 时,模型在当前计算平台处于 Compute-Bound状态,即模型的理论性能 P P P 受到计算平台算力 π \pi π 的限制,无法与计算强度 I I I 成正比。
这并不是一件坏事,因为此时,模型已经充分利用了计算平台的全部算力。
可见,计算平台的算力 π \pi π 越高,模型进入计算瓶颈区域后的理论性能 P P P 也就越大。
VGG计算强度 I v g g I_{vgg} Ivgg很大,以VGG-16为例,一次前向传播的计算量达到 15 GFLOPs,如果包含反向传播,则需要再乘二。
访存量是 Kernel Memory 和 Output Memory 之和再乘以四,大约是 600MB。因此 VGG16 的计算强度就是 25 FLOPs/Byte。
MobileNet 由于使用了深度可分离卷积,其计算量约为 0.5 GFLOPs(VGG16 则是 15 GFLOPs),其访存量只有 74 MB(VGG16 则是约 600 MB)。
但是,由于计算量和访存量都下降了,而且相比之下计算量下降的更厉害,因此 MobileNet 的计算强度只有 7 FLOPs/Byte。
MobileNet 更适合运行在嵌入式平台之上。
嵌入式平台本身的计算强度上限就很低,可能比 MobileNet 的计算强度还要小,因此 MobileNet 运行在这类计算平台上时,它可能就不再位于 Memory-Bound 区域,而是进入了 Compute-Bound 区域。
此时 MobileNet 和 VGG16 一样可以充分利用计算平台的算力,自身的计算量与内存消耗又都更小,自然“占便宜”。
网络中的算子可以根据计算密度进行分类。一般而言,
Conv、FC、Deconv 算子属于计算密集型算子;
ReLU、EltWise Add(Elementwise:逐元素)、Concat(合并) 等属于访存密集型算子。
同一个算子也会因参数的不同而导致计算密度变化,甚至改变性质。
比如在其他参数不变的前提下,增大 Conv 的 group,或者减小 Conv 的 input channel 都会减小计算密度。
算子的计算密度越大,越有可能提升硬件的计算效率,充分发挥硬件性能。
注意: 不同的硬件平台峰值算力和内存带宽不同,导致同一个模型在平台 1 上可能是计算密集的,在平台 2 上可能就变成了访存密集的。
按照 RoofLine 模型,算子实际的执行时间如下:
对于访存密集型算子,推理时间跟访存量呈线性关系;
对于计算密集型算子,推理时间跟计算量呈线性关系。
全局上,计算量和推理时间并非具有线性关系。
计算量并不能单独用来评估模型的推理时间,还必须结合硬件特性(算力&带宽),以及访存量来进行综合评估。
RoofLine 模型可以用来评估程序的性能上界,但是实际能达到的性能还会受到硬件限制、系统环境、软件实现等诸多因素的影响,距离性能上界有一定距离。
更多内容,欢迎查看原文:深度学习模型大小与模型推理速度的探讨
==========================================================================================
再次感谢两位大佬!
https://zhuanlan.zhihu.com/p/411522457
https://zhuanlan.zhihu.com/p/34204282