Int8量化算子在移动端CPU的性能优化

news2024/11/17 21:56:00

2757a9f044c6fc26cd2d8be31dec079f.gif

本文介绍了Depthwise Convolution 的Int8算子在移动端CPU上的性能优化方案。ARM架构的升级和相应指令集的更新不断提高移动端各算子的性能上限,结合数据重排和Sdot指令能给DepthwiseConv量化算子的性能带来较大提升。

58f1dd0a776e994a8b31670fc50dd0f3.png

背景

MNN对ConvolutionDepthwise Int8量化算子在ARM V8(64位)和ARM V8.2上的性能做了较大的优化,主要优化方法包括改变数据的排列方式以及使用Sdot指令。为了方便叙述,后文统一用DepthwiseConvInt8来表示ConvolutionDepthwiseInt8量化算子。在优化前在安卓手机上测得该量化算子的耗时比使用FP16推理多三倍,严重影响量化模型在端侧的性能。本文从ARM汇编算子的角度出发讲解DepthwiseConvInt8算子的优化方案。

e4d886e47febc1358e81a66d43c5ac90.png

性能瓶颈定位及优化方案

  ARM V8 优化数据排列方式
  • 方案介绍

MNN中DepthwiseConvInt8的输入数据格式是e12158cbca3e8f19493877bf12b6a7f4.png,后文简称这种数据排列数据方式为C4),即每4个Channel的数据排列在一起。同理,我们用C16表示每16个Channel的数据连续排列的数据排布方式。下图直观地描述了C4的数据排列方式,假设b9a3da19a62bd3319cb2490cde131abc.jpeg,图中每一个小正方形代表一个数据,四种颜色分别代表feature map上四个坐标点,正方形内的数字编号d39e03b6c6d4ddc63b09cd56c15e1614.png表示它们在内存中的排列次序。

1b0faf502bd434895f744c2a7ee60a0b.jpeg

一般地,我们会对da28bb200badf81d09d73fc2a5b23f04.png采取多线程计算,对8ddd783c4e21837f86e8f501fddd20bb.png采取ARM汇编并行计算。本文关注单线程时对c40f95a237b1bda0e40fe761e8ba5a20.png维度做性能优化。在ARM汇编中通常会同时计算输出的特征图上多个点的结果,这要求我们尽量能够同时读取输入特征图上的点数据。例如当Depthwise层的Stride参数等于1时,同时计算输出特征图中4个点坐标的数据(一共4(坐标点)*4(channel)=16个数据),我们需要读取上图中编号为ded67a97eecd1549f3374a0a867af552.png的正方形数据。当每个数据占4个字节(32位)时,4个输入数据正好填满一个向量寄存器。但是在Int8量化算子中,每个输入数据占8位(1个字节),如果仍然采取C4的数据排列,则4个数据填不满一个向量寄存器。特别地,当Depthwise层的Stride参数不是1时,采用C4的数据排列方式会导致feature map上多个数据时不能连续读取,进而导致性能损失。所以对于Int8类型的输入数据,在ARM平台上我们首先考虑将C4的数据排列方式改为C16的排列,这样保证可以连续地读取16个Int8类型数据来填满一个向量寄存器。我们用汇编代码来表示这两种数据读取方式的差异。

/* x0: source address, 读取feature map上的4个点 */
/* pack=4, stridex = 2, sizeof(inputData)=1 */
ld1 {v0.s}[0], [x0], #8
ld1 {v1.s}[0], [x0], #8
ld1 {v2.s}[0], [x0], #8
ld1 {v3.s}[0], [x0], #8
/* pack=16, stridex = 2, sizeof(inputData)=1 */
ld1 {v0.4s}, [x0], #32
ld1 {v1.4s}, [x0], #32
ld1 {v2.4s}, [x0], #32
ld1 {v3.4s}, [x0], #32

从代码中可以看到同样是使用4条指令读取数据,C16比C4多读取3倍的数据。所以对于ARM V8平台,我们将pack=4更改为pack=16,虽然该方案额外增加了推理时数据排布的转换时间,但是在ARM汇编内部更好地并行化带来的收益更大。

  • ARM V8 性能提升结果

本文中所有的性能数据均来源于美颜模型在华为Mate40 Pro上的测试结果。美颜模型中一共含有23个Convolution Depthwise算子,所有算子都是3x3 kernel,其中19个算子的stride=1,4个算子的stride=2. 表格中记录的算子耗时是美颜模型中所有23个convolution depthwise算子在一次推理中的耗时总和,单位:ms.

华为 Mate40 Pro ARM V8

优化前 C4数据排列

优化后 C16数据排列

Convolution Depthwise Int8 量化算子

4.46 ms

2.78 ms

改变数据排列方式的方案性能加速比是1.6.

  ARM V8.2 使用sdot指令提高性能
  • 为什么sdot指令能提高算子性能?

虽然在ARM V8平台上DepthwiseConvInt8算子的性能加速已经有明显效果,但ARM V8.2指令集为ARM平台上CPU算子的性能加速提供了更大的空间。与此同时,随着ARM V8.2指令集在旗舰型手机上的普及,浮点模型使用fp16推理极大地提高了移动端性能,量化模型想要保持竞争力也需要进一步优化。在DepthwiseConvInt8算子含有大量乘加计算,以3x3kernel为例,先进行9次乘法再进行1次加法,此时需要9条指令才能得到一个输出数据。ARM V8.2平台提供的sdot指令能实现3条指令即可得到1个输入数据。汇编代码能够直观展示两者差异:

// 3x3kernel 不使用sdot指令,进行9次循环
Loop_Kernel_H3:
  Loop_Kernel_W3:
    smlal v0.4s, v1.4h, v2.4s // 累加结果存储在v0中


// 3x3kernel 使用sdot指令
sdot v0.4s, v1.16b, v3.16b
sdot v0.4s, v2.16b, v4.16b
smlal v0.4s, v5.4h, v6.4h
  • 使用sdot指令会带来额外开销吗?

我们先关注sdot指令是如何加速若干个元素乘加操作的,下面的代码展示了sdot指令计算原理。

// v0.16b : [0,1,2,3, 4,5,6,7, 8,9,10,11, 12,13,14,15]
// v1.16b : [0,1,2,3, 4,5,6,7, 8,9,10,11, 12,13,14,15]


// v2.s[0]=v0.b[0]*v1.b[0]+v0.b[1]*v1.b[1]
//         +v0.b[2]*v1.b[2]+v0.b[3]*v1.b[3]
sdot v2.4s, v0.16b, v1.16b // v2.4s: [14,126,366,734]

由代码示例得知,进行累加的4个元素在内存中是连续排列的。上文中已经介绍了算子的输入数据排列是C4,同一个Kernel中的所有元素在内存中肯定不能连续读取。

sdot指令的使用之前需要重排数据才能得到正确的结果,注意此时的数据重排和ARM V8优化中的数据重排完全不同。上文中我们提到的ARM V8上的数据重排仅仅是在Channel维度将C4修改为C16,而ARM V8.2上sdot 指令之前的数据重排需要将一个kernel中的9个元素每4个连续排列在一起。我们用一张图来解释重排规则。不妨假设kernel size是3x3,后文中均采取此假设。

78aab95968d23433e6bd60ca10cfe240.jpeg

显然数据重排的时间会极大影响算子性能,高效地进行数据重排是ARM V8.2 DepthwiseConvInt8性能优化的关键步骤。

  • ARM V8.2 如何进行数据重排

思考重排问题时我们将问题简化,不需要写代码就能得到最高效的解决方案(前提是足够熟悉ARM汇编指令,因为指令集了解地越多,解决方法就越多)。我们把问题抽象为如何高效重排一个向量寄存器中的16个int8_t数据。重排前后的数据排列对比图如下:

830155cebddbddd7e60b2c3a1da7bd08.jpeg

从抽象问题回到对3x3 kernel中的数据进行重排,我们最终需要9个元素相乘再累加,所以我们对kernel中的每4个元素进行重排,剩下的1个再使用smlal指令累加结果即可。当然我们推理前就可以对权值矩阵进行对应元素的重排,不占用推理时间。跟ARM V8上的优化不同的是,ARM V8.2的重排是基于C4进行的而不是C16. 无论是C8还是C16都会给数据重排带来更多的开销,具体来说就是需要的重排指令条数更多,这里就不详细讲解C8和C16场景下的最优重排方案了。

因为数据重排这一步是必不可少的,所以在该算子中使用sdot指令的前提是kernel size是已知的。当前MNN对于DepthwiseConvInt8 在ARM V8.2平台上的优化仅支持3x3 kernel.

  • ARM V8.2 性能提升结果

华为 Mate40 Pro ARM V8

优化前 C4数据排列

ARM V8使用C16优化后

ARM V8 使用sdot指令优化后

Convolution Depthwise Int8 量化算子

4.46 ms

2.78 ms

1.75 ms

通过使用sdot 指令,算子性能加速比达到了2.55.

  ARM V8.2和ARM V8的优化方案差异总结

在ARM V8.2 上优化DepthwiseConvInt8算子性能的核心是重排输入数据以方便使用sdot指令进行累加。因为Depthwise算子的计算复杂度比Convolution低,所以数据重排的耗时对算子性能影响更大。经过稿纸推演和实际测试,我们确定了耗时最低的数据重排方案,即在输入数据是NC4HW4时,用tbl指令将与3x3kernel中9个数据分成3组,第一组和第二组分别有4个数据连续排列,最后一个数据单独排列。在ARM V8上的优化受限于指令种类数量,目前仅从减少数据读取时间角度优化算子性能。

  总结

ARM架构的升级和相应指令集的更新不断提高移动端各算子的性能上限,目前在ARM V8.2上对于Convolution depthwise Int8量化算子的性能已经接近最优,但受限于数据重排带来的额外负载,Int8量化算子的性能仍然无法超越半浮点精度推理性能。

e49ab99313a80c37ef3503114e7a2fb4.png

团队介绍

大淘宝技术Meta Team,负责面向消费场景的3D/XR基础技术建设和创新应用探索,通过技术和应用创新找到以手机及XR 新设备为载体的消费购物3D/XR新体验。团队在端智能、商品三维重建、3D引擎、XR引擎等方面有深厚的技术积累。先后发布端侧推理引擎MNN,端侧实时视觉算法库PixelAI,商品三维重建工具Object Drawer等技术。团队在OSDI、MLSys、CVPR、ICCV、NeurIPS、TPAMI等顶级学术会议和期刊上发表多篇论文。

¤ 拓展阅读 ¤

3DXR技术 | 终端技术 | 音视频技术

服务端技术 | 技术质量 | 数据算法

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1250243.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

计算机组成原理-固态硬盘SSD

文章目录 总览机械硬盘vs固态硬盘固态硬盘的结构固态硬盘与机械硬盘相比的特点磨损均衡技术例题 总览 机械硬盘vs固态硬盘 固态硬盘采用闪存技术,是电可擦除ROM 下图右边黑色的块块就是一块一块的闪存芯片 固态硬盘的结构 块大小16KB~512KB 页大小512B~4KB 对固…

ES6之class类

ES6提供了更接近传统语言的写法,引入了Class类这个概念,作为对象的模板。通过Class关键字,可以定义类,基本上,ES6的class可以看作只是一个语法糖,它的绝大部分功能,ES5都可以做到,新…

数据库的事务的基本特性,事务的隔离级别,事务隔离级别如何在java代码中使用,使用MySQL数据库演示不同隔离级别下的并发问题

文章目录 数据库的事务的基本特性事务的四大特性(ACID)4.1、原子性(Atomicity)4.2、一致性(Consistency)4.3、隔离性(Isolation)4.4、持久性(Durability) 事务的隔离级别5.1、事务不…

6.11左叶子之和(LC404-E)

用java定义树: public class TreeNode {int val;TreeNode left;TreeNode right; //一个空构造方法TreeNode(),用于初始化节点的默认值。TreeNode() {} //一个构造方法TreeNode(int val),用于初始化节点的值,并设置默认的左右子节…

算法笔记:OPTICS 聚类

1 基本介绍 OPTICS(Ordering points to identify the clustering structure)是一基于密度的聚类算法 OPTICS算法是DBSCAN的改进版本 在DBCSAN算法中需要输入两个参数: ϵ 和 MinPts ,选择不同的参数会导致最终聚类的结果千差万别,因此DBCSAN…

分布式篇---第六篇

系列文章目录 文章目录 系列文章目录前言一、说说什么是漏桶算法二、说说什么是令牌桶算法三、数据库如何处理海量数据?前言 前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。点击跳转到网站,这篇文章男女通用,看懂了就去分享给你的码…

可观测性建设实践之 - 日志分析的权衡取舍

指标、日志、链路是服务可观测性的三大支柱,在服务稳定性保障中,通常指标侧重于发现故障和问题,日志和链路分析侧重于定位和分析问题,其中日志实际上是串联这三大维度的一个良好桥梁。 但日志分析往往面临成本和效果之间的权衡问…

Spring Boot Actuator 2.2.5 基本使用

1. pom文件 &#xff0c;添加 Actuator 依赖 <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency> 2.application.properties 文件中添加以下配置 …

优秀软件设计特征与原则

1.摘要 一款软件产品好不好用, 除了拥有丰富的功能和人性化的界面设计之外, 还有其深厚的底层基础, 而设计模式和算法是构建这个底层基础的基石。好的设计模式能够让产品开发快速迭代且稳定可靠, 迅速抢占市场先机&#xff1b;而好的算法能够让产品具有核心价值, 例如字节跳动…

2、用命令行编译Qt程序生成可执行文件exe

一、创建源文件 1、新建一个文件夹&#xff0c;并创建一个txt文件 2、重命名为main.cpp 3、在main.cpp中添加如下代码 #include <QApplication> #include <QDialog> #include <QLabel> int main(int argc, char *argv[]) { QApplication a(argc, argv); QDi…

深入浅出 Linux 中的 ARM IOMMU SMMU II

SMMU 驱动中的系统 I/O 设备探测 要使系统 I/O 设备的 DMA 内存访问能通过 IOMMU&#xff0c;需要将系统 I/O 设备和 IOMMU 设备绑定起来&#xff0c;也就是执行 SMMU 驱动中的系统 I/O 设备探测。总线发现系统 I/O 设备并和对应的驱动程序绑定&#xff0c;与 IOMMU 设备驱动程…

设备管理系统-设备管理软件

一、为什么要使用设备管理系统 1.企业扩张快&#xff0c;设备配置多&#xff0c;管理混乱。 2.设备数量多&#xff0c;存放地点多&#xff0c;查找麻烦。 3.同类设备单独管理, 困难。 4.设备较多时相关信息统计容易出错&#xff0c;错误后修改困难。 二、凡尔码设备管理软件的…

EEG脑电信号处理合集(1):功率谱中常见artifacts

通常EEG脑电信号采集完成以后&#xff0c;我们可以绘制出功率谱&#xff0c;一个正常的功率谱如下图所示&#xff1a; 在10H在处有个明显的突起&#xff0c;在后方通道中&#xff0c;这是我们所期望看到的。每个通道功率谱曲线都有一个负斜率&#xff0c;这是因为较高的频率通…

使用 HTML、CSS 和 JavaScript 创建图像滑块

使用 HTML、CSS 和 JavaScript 创建轮播图 在本文中&#xff0c;我们将讨论如何使用 HTML、CSS 和 JavaScript 构建轮播图。我们将演示两种不同的创建滑块的方法&#xff0c;一种是基于opacity的滑块&#xff0c;另一种是基于transform的。 创建 HTML 我们首先从 HTML 代码开…

NB-IoT BC260Y Open CPU平台篇②AEP物联网平台天翼物联CWing

NB-IoT BC260Y Open CPU平台篇②AEP物联网平台天翼物联CWing 1、注册账号2、创建属于自己项目的产品3、协议解析:4、添加设备5、设备模拟测试:6、设备调试:最近做了几个项目,都是将终端产品连接到天翼物联Cwing平台和Onenet平台,个人感觉这2个平台功能还是挺全的比较好用。…

Linux 常见命令篇

history 获取执行的指令记录 语法格式: history [参数] 常用参数&#xff1a; -a 写入命令记录 -c 清空命令记录 -d 删除指定序号的命令记录 -n 读取命令记录 -r 读取命令记录到缓冲区 -s 将指定的命令添加到缓冲区 -w 将缓冲区信息写入到历史文件 history#获取最近的三条…

Jquery ajax 进行网络请求,同步阻塞引起的UI线程阻塞 (loading图片不显示 )

jax重新获取数据刷新页面功能&#xff0c;因为ajax属于耗时操作&#xff0c;想在获取数据且加载页面时显示加载遮罩层&#xff0c;结果发现了ajax的好多坑。 ajax 执行http网络请示时时&#xff0c;让遮罩层显示&#xff0c;ajax加载完毕后遮罩层消失。 因为我想让loadChart()…

机器学习第13天:模型性能评估指标

☁️主页 Nowl &#x1f525;专栏《机器学习实战》 《机器学习》 &#x1f4d1;君子坐而论道&#xff0c;少年起而行之 文章目录 交叉验证 保留交叉验证 k-折交叉验证 留一交叉验证 混淆矩阵 精度与召回率 介绍 精度 召回率 区别 使用代码 偏差与方差 介绍 区…

【阿里云】图像识别 智能分类识别 项目开发(一)

语音模块和阿里云图像识别结合 环境准备 代码实现 编译运行 写个shell脚本用于杀死运行的进程 语音模块和阿里云图像识别结合 使用语音模块和摄像头在香橙派上做垃圾智能分类识别 语音控制摄像下载上传阿里云解析功能点实现 环境准备 将语音模块接在UART5的位置 在orange…

AMEYA360:村田首款1608M尺寸/100V静电容量1µF的MLCC实现商品化

株式会社村田制作所成功开发了用于基站、服务器和数据中心48V线路的多层陶瓷电容器“GRM188D72A105KE01”并已量产。该产品在1608M(1.60.8mm)尺寸、100V的额定电压下可实现1μF的超大静电容量(村田调查数据&#xff0c;截至2023年11月20日)。目前可向村田申请免费样品。 随着5G…