Skip to content

Releases: alibaba/MNN

【LLM相关性能优化,形状缓存机制】2.9.0

15 May 02:15
6a22d17
Compare
Choose a tag to compare

MNN-LLM 正式合入

增加Transformer相关算子与对应图优化功能

  • 编译 MNN 时打开宏 MNN_LOW_MEMORY 和 MNN_SUPPORT_TRANSFORMER_FUSE ,增加在线权重反量化、动态量化和Transformer相关算子支持
    • -DMNN_SUPPORT_TRANSFORMER_FUSE=ON -DMNN_LOW_MEMORY=ON
  • 转换模型时加上 --transformerFuse=1 开启Transformer模型相关图优化

新增 LLM 模块

使用方法

构建 LLM 文件包

  • 下载模型,推荐使用魔搭
    • pip install modelscope
    • 执行脚本(以千问7b为例)
from modelscope import snapshot_download
from transformers import AutoModelForCausalLM, AutoTokenizer

# Downloading model checkpoint to a local dir model_dir
model_dir = snapshot_download('qwen/Qwen-7B-Chat')
#model_dir = snapshot_download("modelscope/Llama-2-7b-chat-ms", revision='v1.0.5',
                              ignore_file_pattern=[r'.+\.bin$'])
#model_dir = snapshot_download('qwen/Qwen-1_8B-Chat')
print(model_dir)
  • 使用 MNN 目录下面的 transformers/llm/export/llm_export.py 进行模型导出,把 torch 模型转换成 onnx
    • 示例
      • python3 llm_export.py --embed_bin --embed_bf16 --onnx_path onnx --type Qwen-7B-Chat --path /Users/xtjiang/.cache/modelscope/hub/qwen/Qwen-7B-Chat --export_embed --export_token --mnn_path mnn --export
    • 务必加 --embed_bin 参数,将 embeding 层导出成 bin 文件
    • 完成后会产出两个文件夹
      • onnx
        • llm.onnx
        • tokenizer.txt
        • 其他外置权重数据,不用关注
      • mnn
        • embeddings_bf16.bin
  • 使用 MNNConvert 转换 onnx 模型,并进行量化
    • ./MNNConvert -f ONNX --modelFile onnx/llm.onnx llm.mnn --weightQuantBits=4 --transformerFuse=1 --saveExternalData
    • 一般需要20-30 分钟,请耐心等待
    • 产出 llm.mnn 与 llm.mnn.weight
  • 建文件夹,组合上述步骤产出的文件,这里以千问7b为例
    • 文件夹名:qwen-7b-int4
    • 包含文件
      • embeddings_bf16.bin
      • llm.mnn
      • llm.mnn.weight
      • tokenizer.txt

编译LLM引擎并使用

  • 编译MNN打开 MNN_BUILD_LLM 宏,编译 transformers/llm/engine 目录,产出 libllm 和 llm_demo

  • 使用 llm_demo 运行 llm

    • 参数:
      • llm.mnn 文件路径
      • forwardtype :0 为 CPU ,3 为 OpenCL
      • Memory | Precision :Memory * 4 + Precision ,如果 memory 和 preicsion 都为 low ,即设为 10
    • 示例:
      • ./llm_demo ../../qwen-7b-int4/llm.mnn 0 10
        • 【然后进行对话】
      • ./llm_demo ../../qwen-7b-int4/llm.mnn 0 10 prompt.txt :使用预设的问题进行测试
  • CPU / GPU

性能测试

  • 8Gen1
    | model | CPU 4线程 | | OpenCL | |
    | --- | --- | --- | --- | --- |
    | | prefill | decode | prefill | decode |
    | qwen-1.8b | 207.56 | 35.58 | 28.58 | 20.40 |
    | qwen-7b | 25.86 | 7.5 | 7.95 | 7.70 |
    | llama3-8b | 22.09 | 5.59 | 内存不足 | 内存不足 |

  • 8Gen3
    | model | CPU 4线程 | | OpenCL | |
    | --- | --- | --- | --- | --- |
    | | prefill | decode | prefill | decode |
    | qwen-1.8b | 205.70 | 47.07 | 61.25 | 21.56 |
    | qwen-7b | 40.93 | 11.01 | 20.26 | 10.60 |
    | llama3-8b | 36.44 | 7.83 | 19.10 | 2.14 |

  • 注:暂未对 llama3-8b 结构支持 Transformer 相关图优化,因此GPU性能较差

形变缓存机制

背景

对于语音/文本类的模型,往往涉及张量某个维度的逐步变化,这种情况下每次都会进行几何计算、申请内存等操作,导致不可忽略的性能损耗。考虑到输入单个维度变化的情况下,网络中会存在部分算子形状不变,这部分计算是可以去除的。
为了对这种情况进行优化,MNN新增了形变缓存机制,使模型输入形状变化时,形状不变的算子跳过形变相关操作,以提升性能。

原理

  • MNN 通过两个状态去优化Resize过程,先在 Check 状态下寻找不变形状的算子,然后切换到 Fix 状态,分离易变形状与不变形状算子进行处理。对应于 Interpreter.hpp 里面增加两个 SessionMode
    • Session_Resize_Check
    • Session_Resize_Fix
  • Check 状态
    • 存储或检查输入的形状是否与上次一致,对应跳过几何计算阶段,但资源分配阶段不跳过
  • Fix 状态
    • 根据算子的形状不变标志,跳过几何计算与资源分配阶段

基于 Module API 使用

对应 API

  • **Module::**traceOrOptimize

示例

  • 网络输入为 speech ,输出为 out0 ,out1 ,输入大小为: 1,3,X
std::shared_ptr<MNN::Express::Module> net(MNN::Express::Module::load(fileName, {"speech"}, {"out0", "out1"}), MNN::Express::Module::destroy);
net->traceOrOptimize(MNN::Interpreter::Session_Resize_Check);
int validShape[] = {64, 112};
for (int i=0; i<2; ++i) {
    auto varp = MNN::Express::_Input({1, 3, validShape[i]}, MNN::Express::NCHW);
    varp->writeMap<float>();
    auto outputs = net->onForward({varp});
}
net->traceOrOptimize(MNN::Interpreter::Session_Resize_Fix);
// Forward and use output

基于 Intrepreter - Session API使用

相关API

  • Interpreter::setSessionMode

示例

  • 网络输入为 speech ,输出为 out0 ,out1 ,输入大小为: 1,3,X
std::shared_ptr<MNN::Interpreter> net(MNN::Interpreter::createFromFile(fileName), MNN::Interpreter::destroy);
MNN::ScheduleConfig config;
/*Set up config
......
*/
MNN::Session* session = net->createSession(config);
auto input = net->getSessionInput(session, "speech");
auto out0 = net->getSessionOutput(session, "out0");
auto out1 = net->getSessionOutput(session, "out1");
net->setSessionMode(Interpreter::Session_Resize_Check);
/*Resize Session for each valid size Begin*/
/*Demo: */
net->resizeTensor(input, {1, 3, 112});
net->resizeSession(session);
net->resizeTensor(input, {1, 3, 64});
net->resizeSession(session);
/*Resize Session for each valid size End*/
net->setSessionMode(Interpreter::Session_Resize_Fix);

/*Fill input and run session
......
*/

鸿蒙系统支持、功能完善与Github Issue 修正

功能完善

  • 支持华为鸿蒙系统上的编译与运行
    • 参考 MNN/project/harmony 下面的脚本进行编译
  • 增加 WinogradLevel 配置,支持用户设定较低的Winograd 输出计算尺寸 ,以节省内存
    • setSessionHint(WINOGRAD_MEMORY_LEVEL, 0) :使用最低计算尺寸
    • setSessionHint(WINOGRAD_MEMORY_LEVEL, 3) :使用默认计算尺寸
  • 修正 onnx onehot 算子在输入尺寸未知时转换出错问题
  • 修正 Sigmoid / Tanh 等算子量化后出错的问题
  • 优化 Tile 算子的几何计算分解,降低产出的Region数,以减少对应GPU后端的初始化耗时
  • 支持 LayerNorm RMS 模式及相应的图优化
  • 原生支持onnx-external data ,降低 Onnx 大模型转换所需要内存
  • Metal 后端 NC4HW4 布局模式修改为C4NHW4,以优化 batch > 1 的卷积性能
  • Metal 后端支持 BatchMatMul / Gather / GatherND 等对应生成的 Loop 算子
  • Metal 后端支持 GridSampler3D
  • Metal 后端支持可变精度设置
    • precision 为 low / normal 时使用 fp16 存储
    • precision 为 high 时使用 fp32 存储
    • 计算一律使用 fp32
  • CPU 后端修正权值在线反量化模式下,输入输出通道不对齐时出错的问题
  • OpenCL 后端优化 Pooling 算子在 KernelSize 很大时的性能问题
  • OpenCL 后端增加 Kernel 缓存机制,降低部分设备上 resize 耗时
  • 其他Bugfix与优化

相应 Issue 修正

2.8.1

29 Dec 08:08
d284430
Compare
Choose a tag to compare
2.8.1

2.8.0

05 Dec 08:50
1ea55f4
Compare
Choose a tag to compare

1. 新特性

  • MNN支持以JSON文件格式导入量化参数 (issue-2587)
  • 支持 MaxPooling with index (issue-2268)
  • MNN支持NNAPI中Deconvolution算子
  • MNNConvert支持 Onnx 中 dim < 2 的矩阵乘算子
  • TestConvert 增加测试非 CPU 后端的能力
  • Pymnn支持构建 MNN 训练模型,以支持离线训练模式
  • 优化MNNConvert,大幅降低大模型转换时的内存占用
  • OpenCL 支持 Loop 算子特殊形式,广播 Binary
  • 支持 Unary, Prelu 算子量化

2. 性能优化

  • ONNX ScatterND算子性能优化 (issue-2530)
  • CPUTopKV2算子性能优化,将tflite的实现修改为stl的实现;
  • ARM汇编实现MNNTranspose16Bit8x8, 提升fp16的转置性能;
  • ARM/X86使用动态量化方案优化权重量化的矩阵乘、卷积算子;llm模型推理性能大幅提升;

llm cpu性能测试

mnn-llm 在MNN 2.8.0版本的CPU性能如下,测试均使用4线程, 速度为prefill / decode单位为tok/s

model android(f16/32) macos (f32) linux (f32) windows (f32)
qwen-1.8b-int4 100.21 / 22.22 84.85 / 19.93 151.00 / 35.89 117.30 / 33.40
qwen-1.8b-int8 99.95 / 16.94 67.70 / 13.45 118.51 / 24.90 97.19 / 22.76
chatglm-6b-int4 17.37 / 6.69 19.79 / 6.10 34.05 / 10.82 30.73 / 10.63
chatglm2-6b-int4 26.41 / 8.21 20.78 / 6.70 36.99 / 11.50 33.25 / 11.47
chatglm3-6b-int4 26.24 / 7.94 19.67 / 6.67 37.33 / 11.92 33.61 / 11.21
qwen-7b-int4 14.60 / 6.96 19.79 / 6.06 33.55 / 10.20 29.05 / 9.62
baichuan2-7b-int4 13.87 / 6.08 17.21 / 6.10 30.11 / 10.87 26.31 / 9.84
llama-2-7b-int4 17.98 / 5.17 19.72 / 5.06 34.47 / 9.29 28.66 / 8.90

测试的系统和设备信息如下,

os device CPU Memory
android XiaoMi12 Snapdragon 8gen1 8 GB
macos MacBook Pro 2019 Intel(R) Core(TM) i7-9750H CPU 16 GB
linux PC Intel(R) Core(TM) i7-13700K 32GB
windows PC Intel(R) Core(TM) i7-13700K 32GB

3. Bugfix

3.1 关联 Github Issue 解决

  • 修复MNN2.5.3版本后量化模型不能得到正确结果 (issue-2614)
  • 修复tflite模型转换到MNN时重复算子检测卡死的问题 (issue-2573)
  • 支持Pytorch FX 量化而得的 ONNX 模型转换 (issue-2548)

3.2 其他 Bugfix 或优化

工具类:

  • 修复Defer Allocator 实际分配内存后未做成功与否的检查
  • 修复量化工具中由index=-1导致的crash问题
  • 修复模型转换工具在转大模型时会crash的问题
  • 修复模型转换工具在转换ONNX模型的Clip算子时不能正确处理 int32_t数据的问题
  • 修复使用OpenCL训练时的内存泄露问题
  • OpenCL单测错误问题修复

编译兼容性问题:

  • 修复在X86_x64下SSE指令不兼容导致的编译错误
  • 修复IOS 工程文件中由于局部变量在线程函数外导致的编译错误
  • 修复一些ARM编译器无法识别 "vmov.f16 q0, #5.0"导致的编译错误

结果错误(crash)类问题:

  • 修复C++版本下Binary函数中(<=,<,>=,>,==)的返回值类型导致的结果错误
  • 修复 1x1 Strassen矩阵在Low Memory时crash问题
  • 修复coreML在deconvolution算子padding!=0时crash问题
  • 修复 ModuleAPI在运行时使用 Defer Allocator来申请内存的问题

2.7.2

04 Dec 08:21
6edd12f
Compare
Choose a tag to compare
Merge pull request #2618 from alibaba/feature/sync

[MNN:Sync] Sync Internal 2.7.2

2.7.1

28 Sep 07:41
94e1212
Compare
Choose a tag to compare
MNN 2.7.1

【内存分配优化、性能优化、Bugfix】2.7.0

04 Sep 08:37
9e3cc72
Compare
Choose a tag to compare

1. 新特性

  • 新增LayerNorm int8量化算子支持:
  • CUDA 后端 新增 TopKV2 算子支持
  • 新增 DeferAllocator ,支持延迟分配内存,默认在 CPU Backend 中启用,内部模型测试平均降低内存占用 19.13%
  • OpenCL Buffer 模式新增Range/Select/Cast/ArgMax 等算子支持
  • OpenCL支持用户设置platform_id/device_id/platform_num接口,以选择显卡核心,并支持默认优先选用独显(NVIDIA/AMD独显)
  • 优化 OpenCL 后端内存分配逻辑,降低ChatGLM模型的内存占用

2. 性能优化

  • OpenCL优化Mali-GPU计算量大的卷积运算(image/buffer存储混用)。性能提升10%-20%。

  • CPU浮点模型优化Winograd卷积的准入条件、1x1Strassen算法。性能提高3%~18%。

  • CPU量化模型优化WinogradInt8、DepthwiseInt8。性能提高4%~22%。

  • CUDA优化广播Binary算子性能、Blit算子性能。

  • CUDA支持编译CodeGen功能,针对Unary/Raster/Binary算子进行算子在线融合,整体性能提升5%-10%。

3. Bugfix

3.1 关联 Github Issue 解决

  • Tflite FC + Relu 情况下模型转换到 MNN 未正确解析 Relu #2332
  • Onnx 模型中FP16 常量 转换到 MNN 时不支持#2477
  • Onnx 新的 LayerNorm 算子不支持(目前采用效率较低的算子组合实现)#2509
  • Vulkan Image 模式部分情形下计算错误#2433
  • Yolov8 MNN CUDA 推理出错 #2428
  • OpenCL Codegen 部分 case 下出现编译错误 #2523

3.2 其他 Bugfix 或优化

  • 修正 Vulkan Buffer 模式单元测试 convolution3d 出错的问题
  • 修正 ScatterND 算子在 update tensor 长度为空的计算错误问题
  • 修正 Onnx EinSum 算子在部分情况下转换到 MNN 出错的问题
  • 修正 Onnx Split 算子转换问题
  • 支持 Onnx 的 GEMM + Relu 算子的合并

2.6.3

28 Sep 07:42
c442ff3
Compare
Choose a tag to compare
Merge pull request #2550 from alibaba/feature/sync

[MNN:Sync] Sync Internal 2.6.3

【新增Int8 量化算子,OpenCL后端适配 recordable queue】2.6.0

05 Jul 08:11
c293f9e
Compare
Choose a tag to compare

1. 新特性

  • 新增int8量化算子支持:
    • Softmax
    • Interp
    • Binary
    • Unary
    • Scale
  • OpenCL 支持 Loop 算子特定情形;
    • BatchMatMul
    • Gather
  • x86_64支持Gelu-bf16;
  • CUDA支持bf16模型推理;
  • benchmark 工具支持直接测试模型量化后的性能(不需要先用量化工具量化模型)
  • Pymnn Tensor/Var使用Tuple创建时支持混合类型数据;
  • 权值量化模型支持低内存推理模式,计算时反量化;
    • 支持ChatGLM-6B模型推理内存占用3G;
    • 支持构建了ChatGLM-MNN Android app;

2. 优化

  • OpenCL支持高通reocrd queue ,以降低创建 GPU Command Buffer 所需的时间;

Oneplus 9 机型 Benchmark 测试结果如下

Model unrecord record
resnet-v2-50.mnn 21.254 20.160
MobileNetV2_224.mnn 4.853 4.186
mobilenet-v1-1.0.mnn 6.424 5.315
nasnet.mnn 46.751 20.260
SqueezeNetV1.0.mnn 7.35 6.832
squeezenetv1.1.mnn 3.936 3.693
mobilenetV3.mnn 14.201 6.743
inception-v3.mnn 33.111 32.032
  • 稀疏卷积内存优化,降低内存占用;
  • 减少异构(CPU低精度/GPU)运行 MNN 模型时的常量内存占用;
  • CUDA优化int8算子性能;
  • 减少Permute几何计算产生的region数量;
  • 重新调整ConvolutionInt8及im2col在AVX512-VNNI下的分块大小,提升性能20%-30%;
  • X86新增bilinear/nearest sample的SIMD实现,提升ImageProcess性能 50% 左右;

3. Bugfix

3.1 关联 Github Issue 解决

  • 修复CUDA Raster错误导致输出为0的问题;issue-2333
  • 修复OpenCL Gather算子出错的问题;issue-2424
  • 修复ImageProcess出错的问题;issue-2386
  • OpenCL支持用户选择device id; issue-2343

3.2 其他 Bugfix

  • CUDA CMakeList对未支持架构增加报错信息;
  • testMNNFromOnnx脚本在模型测试正确时不启用DEBUG模式;
  • load_module_from_file中的shape_mutable默认改为True(存在子图的模型无法在False情形下运行);
  • MNNConvert使用keepInputFormat选项时,也同时将输出Tensor的format转换为原始格式
  • 修复log记录时设备为空时Crash的情况;
  • 修复BinaryOp单元测试在Windows下无法编译的问题;
  • 修复MNN_SUPPORT_DEPRECATED_OP宏不控制OptimizedComputer的问题;
  • 修复fp16多线程且分块方向为channel时convolution计算出错的问题;
  • 修复deconvolutionInt8访存越界的问题;
  • 修复TensorArrayWrite几何计算产生zero region的问题;
  • 修复CUDA depthwise conv出错的问题;
  • 修复一些文档格式、内容的错误;
  • 修复多线程下createRuntime和setGlobalConfig出错的问题;
  • 修复Vec.hpp中无用代码导致的编译失败问题;
  • 修复OpenCL对gpuDevice的assert失败的问题;
  • 修复OpenCL bianry mod出错的问题;
  • 修复CUDA argmax出错的问题;
  • 修复pymnn/example/mnn_numpy_cv_demo.py中形状不对的问题;

2.5.0

27 Apr 09:09
d7d1efe
Compare
Choose a tag to compare

1. 新特性

  • MNN OpenCV新增算子:
    • erode
    • convertMaps
    • remap
    • adaptiveThreshold
    • bilateralFilter
    • solve (MNN numpy新增solve)
    • normalize
    • split
    • merge
    • addWeight
  • 支持Tflite int8量化模型转换到MNN模型;
  • ARM CPU支持GELU-bf16
  • CUDA 新增算子:
    • GridSampler
    • Multi-Input Convolution
    • Multi-Input Deconvolution
  • CUDA针对多卡推理,支持用户设置运行device_id
  • 支持Deconvolution-int8
  • runSession/runSessionWithCallBack函数加锁,避免多线程调用出错
  • 支持非拓扑序ONNX模型转换
  • 支持ONNX多版本Softmax转换

2. 重构/优化

  • 优化内存分配与回收时机,新增Session
  • 简化ONNX Slice算子模型转换
  • Cuda性能优化
    • Argmax针对dim size较大的情况性能优化
    • Softmax在channel较大时性能优化
    • MatMul算子预重排逻辑优化
    • 优化后ChatGLM模型在A10显卡上性能优于Pytorch 2.0
  • OpenCL优化,resnet测试优于OpenVINO
    • 使用intel subgroup扩展优化winogard算子,调整数据排布格式与准入条件
    • 根据输入尺寸调整conv2d算子的数据排布格式,使用intel subgroup扩展优化
    • 优化后ResNet18模型在intel UHD Graphics 630显卡上性能优于OpenVINO
  • GELU-bf16实现后性能提升

3. Bugfix

3.1 关联 Github Issue 解决

  • 修复CPURaster 的 singleConvert 部分情况出错 issue-2264
  • 修复atan2计算错误的问题
  • 修复ONNX dynamic shape转换出错的问题 issue-2276
  • 修复i8mm时Im2col出错的问题
  • 修复CPUConvolutionDepthwise错误的问题 issue-2291
  • 修复CUDA int8编译失败的问题 issue-2321
  • 修复Onnx Loop 算子的 M 和 cond 为optional 时,转换失败的问题 issue-2267
  • 修复Raster中fastblit 中turnPackRegion 部分情况下出错的问题 issue-2337

3.2 其他 Bugfix

  • 修复 onnx 子图中 identity 被优化导致 输出数和原始子图不一致的问题
  • 修复 Onnx sequense 相关算子转换问题
  • 修复 TensorArrayConcat 计算 newAxis = 1 时的问题(此时为 stack)
  • 修复 TensorArray 计算 eleSize 时,axis < 0 时计算出错的问题
  • 修复低精度计算或者 GPU 无法运行 mnn 训练模型的问题

2.4.0 NNAPI后端/CUDA后端支持量化模型

01 Mar 02:34
dcb080c
Compare
Choose a tag to compare

一、新特性

  • NNAPI 支持int8 量化模型;
  • MNN OpenCL/Metal支持算子在线Fuse与代码生成;
  • 支持使用cibuildwheel构建Python Wheel包;
  • Github Action支持自动化构建多端库与Whl包;
  • (测试中)CUDA后端支持量化模型运行

二、重构/优化

  • CUDA优化Softmax/DepthwiseConv算子
  • 优化 KernelSize = 3x3 的 OpenCL 卷积算子性能
  • 优化了MaxPool/AvgPool的int8量化计算;
  • 移除原来的LLVMJit, C等Codegen后端;
  • 更新MNN.podspec, MNNBridge.podspec;
  • 增加GELU模块Fuse为GELU算子的功能,Vulkan 和 OpenCL 后端支持 GELU 算子
  • NetModule析构函数中增加gc函降低内存占用;
  • OpenCL支持设置推理低优先级配置;
  • OpenCL updateCache支持异步,降低阻塞时间;
  • fastTestOnnx.py / fastTestTf.py / fastTestTflite.py / fastTestTorch.py 分别更名为 testMNNFromOnnx.py / testMNNFromTf.py / testMNNFromTflite.py / testMNNFromTorch.py
  • Android Demo新增使用README文档;

三、Bugfix

  • 修复Android Demo运行Crash的问题;
  • 修复Metal中的onSync的Bug;
  • 修复Metal多段模型推理的Bug;
  • 修复在Windows下MNN Train的编译问题;
  • 修复perm值非法时的Crash问题;
  • 修复Pad的输入参数为负数时(此时等效为Crop),计算出错的问题
  • 修正 Relu Int8 不支持非对称量化的问题
  • 修正部分AVX2架构的机器上运行量化模型crash的问题
  • 修正Module API 运行静态模型crash的问题
  • 修正Winograd量化过程未使用相同变换矩阵的问题
  • 修正Winograd量化计算多Batch输入错误的问题
  • 修正 OpenCL Relu 算子在 AMD GPU 上段错误的问题
  • 修正 OpenCL ROIPooling 算子实现错误