【端智能】MNN CPU性能优化年度小结

【端智能】MNN CPU性能优化年度小结_第1张图片

简介


2020年5月,MNN发布了1.0.0版本,作为移动端/服务端/PC均适用的推理引擎,在通用性与高性能方面处于业界领先水平。

这之后,我们并没有停止脚步,而是继续在 CPU/GPU/NPU 持续发力。其中,CPU 作为最普适易用的计算资源,我们在多种架构,多种精度模式下继续进行优化,使 MNN 整体的CPU性能进一步提升:AVX2 架构下性能提升 70%-100%,ARM / ARMv8.2 架构下提升约 10-20%,新增了对 Intel Xeon 处理器的 AVX512 指令集的支持,新建对中低端移动手机的 BF16 优化,新增低比特量化计算支持(Int7 / OAQ / Winograd-Aware)。

  成果概述如下

【端智能】MNN CPU性能优化年度小结_第2张图片

【注:GPU 部分优化成果参见《谈谈MNN GPU性能优化策略》一文】

架构改造

所谓磨刀不误砍柴工,为了支持更多指令集架构与更多精度选择,我们先进行了架构改造,以便于减少后续优化成本。

  几何计算

几何计算是我们为了适配各类硬件所提出一种简化算子的方案,其核心思想是从原始算子里面分离坐标映射部分,降解为更基础的算子。

【端智能】MNN CPU性能优化年度小结_第3张图片

通过几何计算机制,一些原本在CPU上优化得不充分的算子,如 Slice-TF / Pack / Unpack / StridedSlice 等自然消除,相应的业务模型也得到了加速。

但由于各硬件的内存设计不一样,目前几何计算在处理坐标映射时只能比较保守地生成内存拷贝算子而不是直接引用,在处理复杂算子如卷积、反卷积等会因引入额外的性能损耗而无法拆解。

对于CPU,不论是各架构还是各类精度(以下简称分支),内存设计是完全一样的,我们可以在几何计算的基础上,对各分支做复杂算子实现的统一。

  算子统一

卷积、反卷积、矩阵乘等算子会有多种实现,以卷积为例有如下实现:

  • Slide-Window

  • Im2Col+GEMM

  • Winograd-GEMM

它们在不同的输入条件下各有优势,MNN 会通过 cost 计算,选择最优实现,保证各类模型都能达到最优性能。

如果针对各分支分别写这些实现,工作量无疑是巨大的。


【端智能】MNN CPU性能优化年度小结_第4张图片

因此,基于CPU内存同构的特性,我们把繁杂而并不耗时的内存管理、地址计算、预处理、分块并行等复杂逻辑统一实现,每个分支实现核心计算函数。

【端智能】MNN CPU性能优化年度小结_第5张图片

经过这番改造后,我们算子实现上的优化,可以较低成本同步到各个分支上。

算子优化

  矩阵乘实现改进

MNN卷积最初的实现为滑窗算法,为了方便进行SIMD优化,采用NC4HW4 的内存布局,即:


维度上c上对齐到4然后拆分,c的坐标j变换为

Im2Col-GEMM / Winograd-GEMM 算法的实现中,我们会根据这个NC4HW4布局,实现 

的矩阵乘汇编,其中X为分块大小,受寄存器数N的限制2X+4≤N,在ARMv8 上为 14 ,然后每次拷贝/计算出大小的计算,经过矩阵乘计算后填到对应的输出位置。

这样实现默认在C方向上强制做了4对齐,两个输入每次都需要以SIMD单位去读,理论读取内存量为:

可并发的FMLA指令数为X,有如下缺陷:

  • 可并行的FMLA指令不足,在中低端CPU上不能完全隐藏掉计算延迟

  • 内存读取量不够小

  • 不利于其他SIMD架构实现(比如AVX2并行单位为8)

为此,我们修正了矩阵乘算法,采用ep,1hp的分块模式,ep,hp由各架构的核心函数确定,并增加一个把 NC4HW4 转成ep,1的Pack过程。这样理论读取内存量为:,可并发的FMLA指令数为(n为SIMD一次计算数)

【端智能】MNN CPU性能优化年度小结_第6张图片

具体到 ARMv8 架构-浮点分支上,ep=12,hp=8,n=4 ,读取内存量 ,并发数为12∗8/4=24>14

虽然额外增加了Pack过程,但总体而言减少了内存读写量,增加了并发数,能达到理论极限性能。

  卷积实现改进

在卷积算子的实现中,上一节增加的 Pack 过程可以与 Im2Col 过程合并,仅在Im2Col过程中增加一些转置指令,不影响内存读写的瓶颈耗时。

首先我们看原始的实现,以 w=4,h=2,c=4,n=1,kx=3,ky=1 为例,我们需要先基于NC4HW4布局进行Im2Col,再把Im2Col的结果转换到c,ep的内存布局。

【端智能】MNN CPU性能优化年度小结_第7张图片

为了对Im2Col和Pack进行合并,我们注意到在w和c的方向上,内存的搬运是有连续性的,因此可以先计算出一个包含一系列矩形框的“骨架”(最多含有),每个矩阵框包含源地址、目标偏移、矩形大小等信息,然后再根据这些矩形框,逐个连续从输入源取值并转置到目标位置上。

示例流程如下图:

【端智能】MNN CPU性能优化年度小结_第8张图片

经过这个优化之后,我们和Google 提出的 的 Indirect Convolution Algorithm (集成在 XNNPack)进行了对比测试,由下表数据可见,在汇编都进行了深度优化的基础上,MNN 的 Im2Col-Pack Fuse - GEMM 卷积算法比XNNPack略优,此外,在非 1x1 卷积(矩阵乘即可,不需要额外处理)较多的模型,综合了 Winograd 算法的 MNN 则明显快于 Tflite-XNNPack 。

A76 上测试数据:

引擎 Mobilenet v1/ms Squeezenet v1.0 /ms InceptionV3 / ms

Tflite-XNNPack

33.696

54.563

342.066

MNN-(限定Im2Col-GEMM)

31.618

49.406

325.549

MNN

31.997

35.463

240.169

硬件相关优化

  ARM 调优

在算子优化的基础上,我们对ARM汇编做了进一步的精细调优,包括但不限于:

  • 矩阵乘/packing等广泛存在的存储指令ld* 优化为stp,读取指令选取合适的优化为ldp。

  • 部分合适的代码优化为读写双pipeline并行,

  • 部分简单指令例如 sub add指令hide到耗时长指令之内


  x64-AVX2

主流PC/服务器均支持AVX2的SIMD计算,它有16个256位的向量寄存器,一次可计算8个浮点数。

基于之前的算子优化,我们将 AVX2 的矩阵乘定为24x1x4,并编写汇编深度调优,提升了70%-100%的性能,使AVX2上MNN多数模型运行性能接近或超过理论浮点峰值(注:部分模型用Winograd算法加速,为了和训练框架的统计保证一致,模型计算量仍按滑窗计算)。

【端智能】MNN CPU性能优化年度小结_第9张图片


  x64-AVX512

Intel出的Xeon处理器增加了AVX512指令集,支持512位的向量寄存器,一次可计算16个浮点数,更新的AVX512-VNNI指令集追加了uint8-int8的dot指令,可以一次性计算32个整型乘加。

dot指令-vpdpbusd

FOR j := 0 to 7
    tmp1.word := Signed(ZeroExtend16(a.byte[4*j]) * SignExtend16(b.byte[4*j]))
    tmp2.word := Signed(ZeroExtend16(a.byte[4*j+1]) * SignExtend16(b.byte[4*j+1]))
    tmp3.word := Signed(ZeroExtend16(a.byte[4*j+2]) * SignExtend16(b.byte[4*j+2]))
    tmp4.word := Signed(ZeroExtend16(a.byte[4*j+3]) * SignExtend16(b.byte[4*j+3]))
    dst.dword[j] := src.dword[j] + tmp1 + tmp2 + tmp3 + tmp4
ENDFOR
dst[MAX:256] := 0

在Intel同事的支持下,我们借助AVX512的16单位浮点乘加指令与dot量化计算指令,在AVX2优化的基础上,使浮点矩阵乘加速 60%(1024x1024x1024矩阵由24ms下降到15ms),量化计算加速200%(单测用例31.53ms下降到10.15ms)。

低精度计算

  半精度浮点

采用16位浮点替代浮点计算,一般对精度影响不大,不但能加速,还可以减少一半的内存占用。

2018年之后的新手机大都支持 ARMv8.2 指令集,它支持了FP16的SIMD计算,可以达到浮点的两倍性能。

MNN在2020年即已支持这一功能,在算子统一的基础之上,我们重新设计并实现了ARMv8.2的矩阵分块方案与相应汇编代码,取得了进一步的性能提升。此外,为了满足部分应用使用32位架构部署的需求(减少包大小),我们也把FP16计算相关汇编同步编写了一份32位的汇编,支持了32位架构的FP16加速。

对于老的机器,不支持FP16计算的情况,我们实现了介于 Int8 - FP32 的一种优化方案 —— BF16,以减少内存,提升性能。这个方案的原理是以少量的转换指令(BF16与FP32可以简单的移位指令互转),减少读写内存的损耗。

实测在低端机红米4上,BF16 有 10%-20% 的加速效果,在中端机荣耀10上,大部分模型也有一定性能优势。

红米4 单核性能

模型 FP32 / ms BF16 /ms

Moblienet v2

140.801

131.472

Squeezenet v1.0

246.344

212.08

Mobilenet v1

219.629

203.085

Inception v3

1737.672

1516.181

Resnet v2-50

1044.753

779.895

荣耀10 单核性能

模型 FP32 / ms BF16 /ms

Moblienet v2

140.801

131.472

Squeezenet v1.0

120.563

96.106

Mobilenet v1

90.800

92.711

Inception v3

710.116

669.424

Resnet v2-50

470.768

435.611

打开 MNN_SUPPORT_BF16 编译宏,设置 precision = Precision_Low 即可使用。


  低比特量化计算

为了进一步提升量化模型计算的性能,我们需要在训练时加一些限定条件,使在特定架构下能用相关指令加速。

MNN支持了OAQ量化计算,7Bit下的Winograd量化计算与AVX2优化,在在PAI平台相应的模型压缩能力支持下,可以在原有量化模型的基础上提升 30% 左右的性能。

简述如下表:

低比特量化计算类型 限定条件 适配架构 加速原理

Overflow-Aware

矩阵乘数值范围小于等于 16bit

ARMv7a/ARMv8

vmlal.s8 替代 vmull.s8+vpadal.s16

Winograd-Aware

Winograd特征变换数值范围小于等于 8bit 或 特征与权重数值范围均小于等于7bit

ARMv7a/ARMv8

Winograd 算法 F(2, 3)减少运算量

7Bit

特征或权重数值范围小于等于7bit

AVX2

vpmaddubsw + vpmaddwd 替代 vpmovsxbw *2 + vpmaddwd + vpaddd


小结

  纵向对比

经过这一年优化之后,MNN在ARM/ARMv8.2上有10%-20%左右性能提升,而在 AVX2 上有70%-100%的提升。

【端智能】MNN CPU性能优化年度小结_第10张图片

Mate30 单核耗时/ms

【端智能】MNN CPU性能优化年度小结_第11张图片

Mac Retina, 15-inch, Mid 2015 单核耗时/ms

  横向对比

过去一年业界推理框架发展很快,有不少的优秀开源框架涌现,TNN / Mindspore-lite / Bolt 都宣称自己的性能业界第一,老将Tflite在集成 XNNPack 后性能也有了质的飞跃。MNN经过这一年优化,在通用性(算子数、训练框架支持,异构计算支持)有明显优势的基础上,性能保持业界领先,如下是和业界开源框架TNN/Bolt/Tengine/Tflite/Mindspore-lite 对比,可见 MNN 整体CPU性能最优:

【端智能】MNN CPU性能优化年度小结_第12张图片

Mate30-A76-FP32单核耗时/ms

【端智能】MNN CPU性能优化年度小结_第13张图片

Mate30-A76-FP16单核耗时/ms

【端智能】MNN CPU性能优化年度小结_第14张图片

小米6-A73-FP32单核耗时/ms

相关开源框架版本选取如下:

  • Bolt : 测试时使用master分支, 版本号>r1.1,  commit-id: e951118fb28f5fead39c6e56cba16caef4583a99

  • TNN : 测试时使用master分支: commit-id: 98003d6a9ce3c917ccf7522bf24de3a4b43e3824

  • Mindspore-lite: 取release 1.1版本. git clone  [https://github.com/mindspore-ai/mindspore](https://github.com/mindspore-ai/mindspore) -b r1.1

  • TFlite : 测试时使用master分支 commit-id:ee6fa8155e966654f158dad7da06f0b708e9a650

随着新架构、新指令、新算法的涌现,性能优化之路永无止境。MNN将紧随时代潮流,以通用性为基础,适配新硬件特性、新的压缩算法,将推理性能优化到极致,持续帮算法同学解决推理部署的问题。

除了 MNN 性能大幅度提升以外,我们也基于 MNN 工作台 + MNN 模型市场构建了面向全人群的 AI 低门槛部署能力,让大家能够更顺滑的体验 MNN。

不少用户通过这套系统积极参与到 MNN 的生态建设中,让 MNN 在短短一个多月的时间内新增了 4 项开箱即用的模型能力,其中包括视频风格迁移 StyleFilter, 目标检测 YoloV5, 图像能力 SuperPixel 以及人体姿态检测 MobilePose。 至此, MNN 模型市场已经具有 9 项开箱即用能力,所有上述的模型都可以在 MNN 工作台中体验,而这些示例模型,也可以帮助大家更好的上手 MNN 使用。

正是感受到了大家对 MNN 的热情,所以我们今天正式推出全新的 MNN 积分商场。通过 MNN 积分商场,我们真诚邀请更多开发者参与到 MNN 的演进中来,任何在 MNN 模型市场上贡献模型(无论是原创抑或是开源模型改造优化)的开发者都能够获得 MNN 模型市场上的积分。MNN 模型市场上的积分不仅可以用来下载模型市场上的模型资源, 还可以兑换 MNN 模型市场积分商城上的礼品,更有 MNN 团队内推面试直通车机会!!!

还在等什么?赶紧来体验 MNN 吧!

相关链接:www.mnn.zone

‍‍

✿  拓展阅读

【端智能】MNN CPU性能优化年度小结_第15张图片

【端智能】MNN CPU性能优化年度小结_第16张图片

【端智能】MNN CPU性能优化年度小结_第17张图片

【端智能】MNN CPU性能优化年度小结_第18张图片

作者|霞影

编辑|橙子君

出品|阿里巴巴新零售淘系技术

【端智能】MNN CPU性能优化年度小结_第19张图片

【端智能】MNN CPU性能优化年度小结_第20张图片

你可能感兴趣的:(卷积,人工智能,分布式存储,深度学习,大数据)