开源一年,阿里轻量级AI推理引擎MNN 1.0.0正式发布( 二 )


可以看出 , 在实现了73%模型尺寸压缩的情况下 , 量化模型的精度甚至要稍高于原始模型 。
开源一年,阿里轻量级AI推理引擎MNN 1.0.0正式发布
本文插图
异构性能
x86
在x86上 , 我们重点优化了矩阵乘法 。 在分析过AVX和Arm向量乘指令差异后 , 我们修改了AVX下的权重矩阵布局 , 降低了I/O布局 , 以充分利用CPU算力 。
此外 , 我们允许在支持FMA扩展的设备上 , 启用扩展 , 将乘法和加法合为一条指令 , 以进一步降低指令耗时 。
当前 , FMA扩展的启用开关还放置在CMakeLists.txt中 , 后续会在运行时判别 。
开源一年,阿里轻量级AI推理引擎MNN 1.0.0正式发布
本文插图
综合两项优化 , x86上有30%左右的性能优化 。
ARM64
在ARM64上 , 他们面向中低端设备 , 调整了矩阵乘法的分块策略 , 矩阵中每个元素的均摊I/O降低了22%;同时 , 将数据对齐从32字节调整为64字节 , 与ARM架构CPU下场景的L1 cacheline匹配;最后 , 优化了缓存预取 。 优化结果如下:
开源一年,阿里轻量级AI推理引擎MNN 1.0.0正式发布
本文插图
ARMv8.2
ARM在「Bringing Armv8.2 Instructions to Android Runtime」一文中 , 列举了可以在Android运行时中应用的ARMv8.2新特性 。 其中 , FP16 extensions和Dot Product可以分别应用于浮点计算加速和量化计算加速 。
FP16 extensions
开源一年,阿里轻量级AI推理引擎MNN 1.0.0正式发布
本文插图
亦记作asimdhp(Advanced SIMD Half Precision) , 是ARMv8.2架构的可选扩展 。 asimdhp可用时 , 可以使用相关SIMD指令实现float16的读写计算 。 float16将float32所需的位数降低了一半 , 因此在SIMD下 , 可以实现两倍的并发吞吐 , 从而优化性能 。 为此 , 我们在卷积中 , 采用[N,C/8,H,W,8]的数据布局 , 新增了部分卷积实现 , 效果如下:
开源一年,阿里轻量级AI推理引擎MNN 1.0.0正式发布
本文插图
精度上几乎没有下降 , 但是性能足足提升了一倍 。 搭配上MNN转换工具的--fp16输出选项 , 模型大小还能减小一半 。 一箭双雕 。
Dot Product
开源一年,阿里轻量级AI推理引擎MNN 1.0.0正式发布
本文插图
亦记作asimddp(Advanced SIMD Dot Product) , 是ARMv8.2架构的可选扩展 。 asimddp可用时 , 可以使用SDOT/UDOT指令实现int8/uint8的点积计算 。 SDOT/UDOT指令如上图所示 , 一次可以处理两个4x4 int8/uint8数据乘 , 并累加到4x1的int32/uint32的寄存器上 。 这样强大的硬件加速指令 , 还是双发射的 。
开源一年,阿里轻量级AI推理引擎MNN 1.0.0正式发布
本文插图
【开源一年,阿里轻量级AI推理引擎MNN 1.0.0正式发布】
实战表现效果也非常明显 , 在原先int8无法发挥效用的设备上 , ARMv8.2也成功实现了耗时减半 。
开源一年,阿里轻量级AI推理引擎MNN 1.0.0正式发布
本文插图
Python工具链
2019年的绿盟开发者大会上 , 我们发布了MNN的Python前端和Python版的转换、量化、可视化工具 。 而今 , Python又增加了对MNN Express (表达式)、模型训练的封装 , 累计新增超过150个接口 。
依然是前文的Express构图 , 使用Python改写的版本如下:
class Net(nn.Module): ''''''construct a lenet 5 model'''''' def __init__(self): super(Net, self).__init__ self.conv1 = nn.conv(1, 20, [5, 5]) self.conv2 = nn.conv(20, 50, [5, 5]) self.fc1 = nn.linear(800, 500) self.fc2 = nn.linear(500, 10) def forward(self, x): x = F.relu(self.conv1(x)) x = F.max_pool(x, [2, 2], [2, 2]) x = F.relu(self.conv2(x)) x = F.max_pool(x, [2, 2], [2, 2]) x = F.convert(x, F.NCHW) x = F.reshape(x, [0, -1]) x = F.relu(self.fc1(x)) x = self.fc2(x) x = F.softmax(x, 1) return x注:目前Python Express API处于BETA阶段 。 阿里会根据社区和内部的反馈持续改进Python API , 包含进行backward incompatible的改动 。