此为初稿,后续将继续完善。
目录
前言移动平台开发的基础原理与架构设计
基础 AI 与移动平台开发核心学习路径
掌握核心模型裁剪与优化的工程方法
基于优化的TensorFlow Lite的落地案例
移动平台包含的范围
移动电话
平板电脑
可穿戴设备
智能手环、智能手环、智能眼镜、智能腰带
嵌入式设备:树莓派
边缘计算节点
边缘计算
基本概念
- 在边缘测发起应用
- 就近提供服务
- 更快响应用户
- 实时、智能、安全与隐私
本质
- 在本地完成计算而不交给云端处理
- 确保处理稳定,降低云端的工作负载
面临的挑战
- 传输带宽
- 硬件性能与软件优化
5G
万物互联,参数了边缘计算。边缘测
边缘计算应用
- 消防与安全监控
- 环境控制
- 油、气远程监测
- 交通管理
- 自动驾驶
Machine learing on the go
云计算与边缘计算的区别
移动平台
内存 体系结构
计算问题
模型文件巨大,临时内存空间,计算过程中占据的内存空间。
tf pytoch
指令集加速
减小模型体积
TF-Lite 前向引擎,在移动平台。
速度越快,加剧负载。普遍性的优化。特定性的场景优化有时无能为力。
移动深度学习框架开发。
国内:
腾讯 NCNN
百度 PaddleLite
不能完全依赖框架
稀疏量化
有时牺牲精度,追求速度,平衡点。
总结:
在移动就是在移动平台运行。
云端: ws
实时本地运行技术, 尤为关键。自动驾驶,
降低功耗,提高性能和效率。
移动平台化
ARM体系结构、Neon指令集、Neon Intrinsics、线性倒数优化问题、卷积、池化、ARM Linux开发基地、ARM工具链、主流前向引擎和框架、架构、代码结构等、ARM内存模型、指令加速。
数据预处理
缺失值处理、去噪声、平滑、去均值、归一化、标准化、使用和掌握实时处理系统、编程实战等
二、移动端开发核心学习路径概述
- ARM体系结构时一种精简指令集计算(Reduced Instruction Set Commpution, RISC)体系结构。
- 内置大量通用寄存器。
- 体系结构设计采用了加载/存储模式,也就是所有的数据处理都是在寄存器中完成的,无法直接处理内存。
- 寻址模式简单,所有的加载/存储地址都来自寄存器内容和指令字段。
- ARM体系结构充分考虑了实现规模、架构性能和低功耗,这些特定使得其非常适用于具有不同要求的场景。
X86 复杂指令集计算。
执行模式
- AArch64,也就是64位执行模式,一般体系结构称之为aarch64。这种执行模式是ARMv8的新执行模型。
- AArch32,也就是32执行模式,一般体系结构称之为arm,这种执行模式是ARM v7a架构,同时也支持AArch64模式带来的一些增强特性。
性能优化模式
- SIMD指令
- 浮点指令集
v8向下兼容
CPU下的SIMD指令:单指令,多数据。
类似于pc和服务器端采用的:Gpu计算采用的模式
基础数据类型
- 整形:字节(Byte, 8位);半字(Halfword, 16位);字(word, 32位);双字(Doubleword, 64位);4字(Quadword, 128位)
- 浮点类型:半精度(16位);单精度(32位);双精度(64位);32位和64位的定点数表示
AArch64向量格式
在AArch64状态下,使用Vn表示SIMD和浮点数寄存器,其中n的取值范围是0~31,也就是一共32个寄存器。引用寄存器的方式为Vn*CM,SIMD和浮点寄存器提供了3种具体的数据格式,分别是:
- 单元素标量,也就是整个寄存器的最低部分。
- 64位向量
字节(Byte, 8位);半字(Halfword, 16位);字(word, 32位)
引用方式,Vn{.2S, .4H, .8B} - 128位向量
字节(Byte, 8位);半字(Halfword, 16位);字(word, 32位);双字(Doubleword, 64位)
引用方式:Vn{.2D, .4S, .8h, 16B}
AArch32向量格式
- 32位模式的ARM使用的向量寄存器类型描述方式与64位不同
- 64位在寄存器引用种说明了向量数据类型
- 32位模式则选择在指令中说明具体向量数据类型
比如向量乘法指令是VMUL,数据类型说明符是.F32,那么针对这种数据类型的向量赋值指令就是VMUL.F32。
- 数据类型说明符
Neon指令集
- Neon是由ARM提出的一种压缩SIMD技术
- Neon指令将寄存器看出相同数据类型的向量,并且支持多种数据类型
- Neon指令可以对所有支持的寄存器执行相同的操作
- 不同的数据类型支持不同的数量的操作指令
- 在新的ARM v8.2-A和ARM v8-A/R体系结构中,Neon甚至还能支持多指令并行,使得整体运算效率更上一层楼。
- ARM支持的数据类型表
Neon指令集处理模式
- 单指令单数据
- 每个指令指定单个数据源,处理多个数据时需要多条指令
- 速度慢
- 单指令多数据(向量模式)
- 使用同一条指令处理多个数据源(如果控制器寄存器的长度为N,那么一条向量可以执行N个运算)
- 多次运算操作时依次执行而不是同时执行的
- 速度快于单指令单数据
- 单指令多数据(组合数据模式)
- 将一个寄存器分为N个D位的独立运算部分;
- 各个部分独立运算(比如64位寄存器拆分为4个16位数据);
- N个部分运算不会互相产生影响;
-
速度最快,目前的主流模式。
ARM内存模式
ARMv8定义了多层次的存储系统
- 在主存和CPU之间设计了多层次的缓存(Cache),以平衡存储器大小和内存访问言辞
- ARM只是一个标准,各个厂家的具有实现可以不同
ARM加速方法
- 内存
- 内存对齐:访问非对齐内存的指令一般会消耗比较多的指令周期,因此在涉及大量数据计算时必须确保数据存储、数据访问尽量保持内存对齐。
- 缓存预加载:使用指令将自己后续一段时间希望使用的内存地址告知硬件的存储管理器,但处理器可以自行决定如何处理,因此具有不确定性。
- Neon指令集
- 开源库:如OpenBLAS, Eigen等
- 编译器的自动向量化特性
- Compiler intrinsics: ARM提供的编译器内联函数,可读性较好,编译器可以再次自动优化
- 汇编指令:可读性与维护性较差,AArch64不支持内联汇编,一般建议采用Compiler instinsics
Tensoflow Lite案例
Tensoflow Lite构建
Tensoflow Lite构建基于Bazel
- 多语言支持:Bazel支持Java、Objective-C和C/C++,可以扩展支持任务语言
- 高级别的构建语言:通过BUILD的DSL支持构建,可以简单描述复杂的构建任务
- 多平台支持:支持多平台构建
- 伸缩性:可以灵活采用多台服务器并行处理构建
Tensoflow Lite构建
Tensoflow Lite构建
- BUILD文件裁剪
- CPU体系结构
- 系统平台
- 裁剪操作
- 位置:kernel/mutable_op_resolver
- 处理内置函数:AddBuiltin
- 处理自定义函数:AddCustom
- 可以根据情况自行裁剪操作符
- 操作符扩展与优化
build可以删除不需要的平台支持,得到tf-lite的二进制文件会小的多,删除不需要的操作符。
删除操作符注册信息和源代码,这样可以大幅减小tf-lite编译出来的文件。
直接找到addBuilitin和AddCustom,然后针对某些操作进行改进,用到arm指令集的优化,做针对性的优化。
案例
语言识别
链接:https://github.com/tensorflow/examples/tree/master/lite/examples
提高预测性能和降低功耗。
其实,研发专有芯片,解决专有问题,软件优化加硬件优化,这才是最好的优化。