×

签到

分享到微信

打开微信,使用扫一扫进入页面后,点击右上角菜单,

点击“发送给朋友”或“分享到朋友圈”完成分享

【CN-MM2】MagicMind 模型生成(框架解析) 小飞人2023-07-17 17:17:36 回复 查看 社区交流 干货资源
【CN-MM2】MagicMind 模型生成(框架解析)
分享到:

知乎链接:【CN-MM2MagicMind 模型生成(框架解析)

https://zhuanlan.zhihu.com/p/594256690

本文讲解 MagicMind 是如何具体实现框架解析的,在这里面该遵循什么样的流程,具体使用到什么样的 api,解析各个不同的开源框架有什么样的不同之处。最后介绍 MagicMind 将开源框架模型解析并转换为 MagicMind 模型的一个简单的工具。

1、MagicMind 模型生成原理

1 MagicMind 模型解析概览

MagicMind 首先会将诸如 TensorFlow,PyTorch 一类的开源框架的模型的解析为 network,然后通过builder 去优化和生成模型,当我们得到了 MagicMind 模型之后可以选择将其序列化保存为模型文件,供以后使用;或者选择直接将模型进行部署



2 MagicMind 统一计算图表示



MagicMind 基于 MLIR 定义了自己的中间表示,比如 TensorFlow的frozen pb,PyTorch trace出来的pt模型。这些是由一些基础运算组成的,包含了卷积,激活等算子,通过 Parser 可以将这些算子映射到MagicMind 的计算图中,如 mm.conv2d,mm.relu. 这一部分我们称其为 MagicMind 中间图表示,MMIR(MagicMind Intermediate Representation)。用户训练好的算法模型会统一转换为 MagicMind IR 表示的计算图,后续的模型优化和代码生成都基于该计算图完成)

说明:MLIR 中文含义是多级的中间表示,这是由 LLVM 团队开发和维护的一套编译器基础设施,它强调工具链的可重用性和可扩展性。

3 MagicMind 模型优化层



MagicMind 模型优化层,该层主要包含计算图高级别优化、计算图低级别优化和代码生成三部分:

  • 计算图高级别优化(HLO)的工作是完成与硬件无关的、算法层级的优化,包括但不限于算子融合、常量折叠、冗余分支消除等。

  • 计算图低级别优化(LLO)主要是完成硬件相关的优化,包括但不限于物理布局转换、前后融合等。

  • 代码生成部分是完成指令和模型对象生成。该部分支持自动代码生成和手写算子库匹配两种代码生成方式,最终将指令和权重数据打包,生成模型对象(可序列化到文件)。

4 MagicMind 模型优化及生成

在将开源框架模型解析为 MagicMind IR 表示的计算图后,MagicMind 会对该计算图进行优化和代码生成。



2、MagicMind 模型生成流程(框架解析)

1 MagicMind 开源框架模型的解析流程



主要流程如上图所示,其中说明两点:

  • 不同的框架会有不同的设置。设置完数据类型后需要调用 Parser 的 parse 方法导入开源框架的原始模型,比如 PyTorch 的 pt 模型。

  • 创建 builder 之后,可以选择是否需要需要创建 builderconfig 来配置模型生成选项,当不创建builderconfig 时,MagicMind 会使用默认参数生成模型,当选择创建 builderconfig 时,我们可以自己配置一些包括模型的设备选择,模型的优化等的参数

2 MagicMind Parser 支持的模型格式

大概了解模型解析的流程之后,我们需要首先了解 MagicMind Parser 支持的模型格式。



支持以上4种形式,其他两个如下:

  • 对于PyTorch 框架 MagicMind 支持 jit trace 模式生成的模型,该模型一般会以 .pt 作为后缀。

  • TensorFlow 目前有两个版本,分别是 TensorFlow1 和 TensorFlow2,MagicMind Parser 支持对TensorFlow1 的 graphdef 也就是 frozen pb 格式的模型和 saved model 格式的模型进行解析,支持对 TensorFlow2 的 saved model 格式模型进行解析。

MagicMind 的 PyTorch Parser 目前只支持解析 pt 格式(用JIT 模式生成)的 PyTorch 模型的示例:

input = torch.randn(1, 3, 224, 224)trace_model = torch.jit.trace(model, input)torch.jit.save(trace_model, "resnet50.pt")

3 MagicMind 模型解析参数设置



4 MagicMind 配置模型生成选项

配置 config 文件的两种方式:

1)通过json文件配置config

# 通过json文件配置configIBuilderConfig* config = CreateIBuilderConfig();config->ParseFromFile("user_config_path/build_config.json");{
    "opt_config": {
    "conv_scale_fold": true
    },}

2)通过字符串配置

# 通过字符串配置IBuilderConfig* config = CreateIBuilderConfig();std::string user_json_string = "xxx";config->ParseFromString(user_json_string);

其中的常见参数:

config 里的常用参数设置:

基本设置:
archs
graph_shape_mutable
computation_preference
优化设置:
type64to32_conversion
conv_scale_fold
精度设置:
precision_mode

5 MagicMind 模型解析 python 代码展示

pt_model = "sample.pt" builder = mm.Builder()sample_network = mm.Network()# 创建parserparser = Parser(mm.ModelKind.kPytorch)# 模型输入类型设置parser.set_model_param("pytorch-input-dtypes", [DataType.FLOAT32])# 解析PyTorch模型parser.parse(sample_network, pt_model)# 创建BuilderConfigconfig = BuilderConfig()# parse config文件config.parse_from_file("graph_dump.json")# 生成模型model = builder.build_model("sample_model", sample_network, config)offline_model_name = "sample_parse.mm"# 模型序列化model.serialize_to_file(offline_model_name)

3、MagicMind 模型生成工具简介

  1. 工具名称:mm_build

  2. 工具用途:解析开源框架模型并生成对应的 MagicMind 模型

  3. 工具位置:MagicMind 软件栈 /usr/local/neuware/samples/magicmind/mm_build/

  4. 使用步骤

1、进入到工具位置参照 readme 编译 tensorflow_build, pytorch_build, onnx_build, caffe_build 四个二进制文件

2、执行所需转换的模型对应的二进制文件,对模型进行转换

参数介绍:

build命令及参数解释pytorch_build                               \       –pytorch_pt model.pt            \       –pt_input_dtypes FLOAT           \       –mlu_arch mtp_372              \       –input_dims 1,3,224,224      \ 
       –precision force_float32       \       –build_config config.json



具体的更多参数细节:

Options:--precision<Str>[optional]:
        Allowed: force_float32/force_float16/qint16_mixed_float16/qint8_mixed_float16/qint16_mixed_float32/qint8_mixed_float32
        Mix precision mode.--calibration<Bool>[optional]:
        Allowed: 0/1/true/false(ignore capsules)
        Default: false
        To do calibration or not. Will use range [-1,1] and skip calibration if no file or range is set.--rpc_server<Str>[optional]:
        Set remote address for calibration.--calibration_algo<Str>[optional]:
        Allowed: linear/eqnm
        Default: linear
        Set quantization algorithm for calibration.--file_list<Vec<Str>>[optional]:
        Input file list path by order. For calibration only. MUST input with calibration_data_path.--calibration_data_path<Str>[optional]:
        Directory for calibration data. MUST input with file_list.--random_calib_range<Vec<Float>>[optional]:
        Set random range for calibration. Will override path and filelist.--batch_size<Vec<Int>>[optional]:
        Input batchsize by order, will override all highest dimensions for all inputs and not affect unrank/scalar inputs.--input_dims<Vec<Vec<Int>>>[optional]:
        Use '_' as empty vector;
        Input shapes by order. '_' represents scalar.--input_layout<Vec<Str>>[optional]:
        Allowed: NCHW/NHWC/NCT/NTC/NCDHW/NDHWC
        Convert input layouts from channel last to channel second (or the opposite) by order.--input_dtypes<Vec<Str>>[optional]:
        Allowed: INT8/INT16/INT32/UINT8/UINT16/UINT32/HALF/FLOAT/BOOL/QINT8/QINT16
        Input data types by order for inference (will not affect calibration).--dynamic_shape<Bool>[optional]:
        Allowed: 0/1/true/false(ignore capsules)
        Default: true
        To compile with dynamic shape or not.--vars<Vec<Vec<Float>>>[optional]:
        Use '_' as empty vector;
        Vars for inputs by order. MUST input with means.--means<Vec<Vec<Float>>>[optional]:
        Use '_' as empty vector;
        Means for inputs by order. MUST input with vars.--output_layout<Vec<Str>>[optional]:
        Allowed: NCHW/NHWC/NCT/NTC/NCDHW/NDHWC
        Convert output layouts from channel last to channel second (or the opposite) by order.--output_dtypes<Vec<Str>>[optional]:
        Allowed: INT8/INT16/INT32/UINT8/UINT16/UINT32/HALF/FLOAT/BOOL/QINT8/QINT16
        Output data types by order.--mlu_arch<Vec<Str>>[optional]:
        Allowed: mtp_220/mtp_270/mtp_290/mtp_372/tp_322
        Target arch for mlu dev. Unset means all.--plugin<Vec<Str>>[optional]:
        Plugin library paths to   with.--magicmind_model<Str>[optional]:
        Default: ./model
        File path for output serialization model file.--build_config<Str>[optional]:
        Additional json build config for build. Config json will override other arg params.--toolchain_path<Str>[optional]:
        Default: /usr/local/gcc-linaro-6.2.1-2016.11-x86_64_aarch64-linux-gnu/
        Cross compile toolchain path for tp_322 and mtp_220.--rgb2bgr<Bool>[optional]:
        Allowed: 0/1/true/false(ignore capsules)
        Default: false
        convert RGB to BGR for first  's Conv/BatchNorm/Scale of network--pytorch_pt<Str>[required]:
        PyTorch pt file path for PyTorch parser.--pt_input_dtypes<Vec<Str>>[optional]:
        Allowed: INT8/INT16/INT32/UINT8/UINT16/UINT32/HALF/FLOAT/BOOL/QINT8/QINT16
        Default: FLOAT
        Input data types by order for parsing PyTorch pt.


其他模型的参数选择:



4、实验

1 pytorch 解析 MagicMind 模型

使用官网下载的pytorch模型,并进行转行,运行如下:

# 1) 下载模型:wget https://download.pytorch.org/models/resnet50-19c8e357.pth# 2) 运行,先转换成对应的 pt 文件python convert_pt.py# 生成 MM 文件python pt_to_mm.py

其中:

convert_pt.py

import torchimport torchvisionmodel = torchvision.models.resnet50()model.load_state_dict(torch.load("./resnet50-19c8e357.pth"))model.eval()  # 使用trace之前,一定要执行model.eval(),以保证trace测试而不是训练的逻辑input = torch.randn(1, 3, 224, 224)trace_model = torch.jit.trace(model, input)torch.jit.save(trace_model, "resnet50_mm.pt")

pt_to_mm.py

import jsonimport torchimport numpy as npimport osimport magicmind.python.runtime as mmfrom magicmind.python.runtime.parser import Parserbatch_size = 1# 创建 Builderbuilder = mm.Builder()# 创建 MagicMind Networkresnet50_network = mm.Network()# 创建 MagicMind builder_configbuilder_config = mm.BuilderConfig()# 创建 MagicMind Parser (pytorch后端)parser = Parser(mm.ModelKind.kPytorch)# 获取 Network 的输入节点及其维度parser.set_model_param("pytorch-input-dtypes", [mm.DataType.FLOAT32])# 将 resnet50_mm.pt 与 MagicMind Network 绑定parser.parse(resnet50_network, "./resnet50_mm.pt")# 设置 MagicMind Network 参数:硬件平台、自动int64转int32、卷积折叠,可变输入开关等build_config = {
        "archs": ["mtp_372"],
        "graph_shape_mutable": True,
        "precision_config": {"precision_mode": "force_float32"},
        "opt_config": {"type64to32_conversion": True, "conv_scale_fold": True}}builder_config.parse_from_string(json.dumps(build_config)).ok()# 执行 MagicMind 模型生成model = builder.build_model("resnet50_parser.mm", resnet50_network, builder_config)# 保存 MagicMind 模型至本地assert model != Nonemodel.serialize_to_file("./resnet50_parser.mm")print("Generate model done, model save to %s" % "./resnet50_parser.mm")

2 mm_build 的使用演示

首先需要确认在/usr/local/neuware/samples/magicmind/mm_build下是否有编译好的可执行文件,若是没有,请先执行以下脚本:

make_build_tool.sh 脚本如下:

#!/bin/bashif [[ ! -f "/usr/local/neuware/samples/magicmind/mm_build/build/caffe_build" ]]; thenpushd /usr/local/neuware/samples/magicmind/mm_buildmkdir build cd buildcmake -DABI=0 ..make -j32popdelse
  echo "caffe_build exist !"fi

运行以下:

bash make_build_tool.sh

将会编译生成对应的工具如下:



运行以下脚本:

/usr/local/neuware/samples/magicmind/mm_build/build/pytorch_build \--pytorch_pt   ./resnet50_mm.pt \--pt_input_dtypes FLOAT \--mlu_arch mtp_372 \--magicmind_model ./resnet50_from_mm_build.mm

最终生成:

SyntaxHighlighter.all();

版权所有 © 2024 寒武纪 Cambricon.com 备案/许可证号:京ICP备17003415号-1