一、简介
MMDeploy 是一个开源的深度学习模型部署工具集,是OpenMMLab项目的一部分。能更轻松的将 OpenMMLab 下的算法部署到各种设备与平台上。
主要提供以下功能:
- 中间表示 ONNX 的定义标准。
- PyTorch 模型转换到 ONNX 模型的方法。
- 推理引擎 ONNX Runtime、TensorRT 的使用方法。
- 部署流水线 PyTorch - ONNX - ONNX Runtime/TensorRT 的示例及常见部署问题的解决方法。
- MMDeploy C/C++ 推理 SDK。
1.MMDeploy 模型部署流程
- Model Converter
- 能将 PyTorch 模型转换为 ONNX、TorchScript 等和设备无关的 IR 模型;也能将 ONNX 模型转换为推理后端模型。
- 通过Model Converter python推理API对onnx模型或trt模型进行推理【在线推理】。
- MMDeploy Model
- 是模型转换结果的集合。不仅包括后端模型,还包括模型的元信息。
- Inference SDK
- 封装了模型的前处理、网络推理和后处理过程。对外提供多语言的模型推理接口。
- 通过mmdeploy-runtime可以对MMDeploy Model进行推理。
- SDK 本质是设计了一套计算图的抽象,把多个模型的预处理、推理和后处理 调度起来,同时提供多种语言的 ffi。
MMDeploy v1.0.0 是 MMDeploy 1.x 的第一个正式发布版本,是 OpenMMLab 2.0 项目的一部分。截至发布时,MMDeploy 1.x 支持基于 OpenMMLab 2.0 的项目:MMCls 1.x、MMDet 3.x、MMDet3d 1.x、MMSeg 1.x、MMEdit 1.x、MMOCR 1.x、MMPose 1.x、 MMAction2 1.x.、MMRotate 1.x、MMYOLO。
2.OpenMMLab常用框架
1)MMDetection
MMDetection 是一个目标检测工具箱,包含了丰富的目标检测、实例分割、全景分割算法以及相关的组件和模块, 主分支代码目前支持 PyTorch 1.6 以上的版本。
MMDetection由 7 个主要部分组成,apis、structures、datasets、models、engine、evaluation 和 visualization。
- apis 为模型推理提供高级 API。
- structures 提供 bbox、mask 和 DetDataSample 等数据结构。
-
datasets 支持用于目标检测、实例分割和全景分割的各种数据集。
- transforms 包含各种数据增强变换。
- samplers 定义了不同的数据加载器采样策略。
-
models 是检测器最重要的部分,包含检测器的不同组件。
- detectors 定义所有检测模型类。
- data_preprocessors 用于预处理模型的输入数据。
- backbones 包含各种骨干网络。
- necks 包含各种模型颈部组件。
- dense_heads 包含执行密集预测的各种检测头。
- roi_heads 包含从 RoI 预测的各种检测头。
- seg_heads 包含各种分割头。
- losses 包含各种损失函数。
- task_modules 为检测任务提供模块,例如 assigners、samplers、box coders 和 prior generators。
- layers 提供了一些基本的神经网络层。
-
engine 是运行时组件的一部分。
- runner 为 MMEngine 的执行器提供扩展。
- schedulers 提供用于调整优化超参数的调度程序。
- optimizers 提供优化器和优化器封装。
- hooks 提供执行器的各种钩子。
- evaluation 为评估模型性能提供不同的指标。
- visualization 用于可视化检测结果。
模型支持列表参考此处。
2)MMSegmentation
MMSegmentation 是一个基于 PyTorch 的语义分割开源工具箱,是 OpenMMLab 项目的一部分,目前支持 PyTorch 1.6 以上的版本。
3)MMOCR
MMOCR 是基于 PyTorch 和 mmdetection 的开源工具箱,专注于文本检测,文本识别以及相应的下游任务,如关键信息提取。 它是 OpenMMLab 项目的一部分。主分支目前支持 PyTorch 1.6 以上的版本。
二、MMDeploy安装
- MMDeploy Converter 依赖
- torch>=1.8.0
- mmcv
- MMDeploy SDK 依赖
- OpenCV (>=3.0)
- pplcv:openPPL 开发的高性能图像处理库
mim 是 OpenMMLab 项目的包管理工具,会自动检查 CUDA 和 PyTorch 环境并尽量帮我们安装和环境匹配的预编译版本的 MMCV-full,从而省去编译的耗时。
pip install -U openmim
mim install mmengine
mim install mmcv-full
1.使用pypi预编译包安装【仅python可用】
请根据目标软硬件平台,从这里 选择最新版本下载并安装自定义算子库。
# 1. 安装 MMDeploy Model Converter(含trt/ort自定义算子)
pip install mmdeploy==1.0.0 -i http://pypi.douban.com/simple --trusted-host pypi.douban.com
# 2. 安装 MMDeploy Inference SDK(仅pypi 预编译包,c++包需要编译安装)
# 根据是否需要GPU推理可任选其一进行下载安装
# pip install mmdeploy-runtime==1.0.0 # 支持 onnxruntime 推理
pip install mmdeploy-runtime-gpu==1.0.0 # 支持 onnxruntime-gpu tensorrt 推理
# 3. 安装推理引擎【基于python binding】
# 3.1 安装推理引擎 TensorRT
pip install TensorRT-8.2.3.0/python/tensorrt-8.2.3.0-cp38-none-linux_x86_64.whl
pip install pycuda
export TENSORRT_DIR=$(pwd)/TensorRT-8.2.3.0
export LD_LIBRARY_PATH=${TENSORRT_DIR}/lib:$LD_LIBRARY_PATH
# !!! 另外还需要从 NVIDIA 官网下载 cuDNN 8.2.1 CUDA 11.x 安装包并解压到当前目录
export CUDNN_DIR=$(pwd)/cuda
export LD_LIBRARY_PATH=$CUDNN_DIR/lib64:$LD_LIBRARY_PATH
# 3.2 安装推理引擎 ONNX Runtime 【可选】
# 3.2.1 onnxruntime
wget https://github.com/microsoft/onnxruntime/releases/download/v1.8.1/onnxruntime-linux-x64-1.8.1.tgz
tar -zxvf onnxruntime-linux-x64-1.8.1.tgz
export ONNXRUNTIME_DIR=$(pwd)/onnxruntime-linux-x64-1.8.1
export LD_LIBRARY_PATH=$ONNXRUNTIME_DIR/lib:$LD_LIBRARY_PATH
# 3.2.2 onnxruntime-gpu
pip install onnxruntime-gpu==1.8.1
wget https://github.com/microsoft/onnxruntime/releases/download/v1.8.1/onnxruntime-linux-x64-gpu-1.8.1.tgz
tar -zxvf onnxruntime-linux-x64-gpu-1.8.1.tgz
export ONNXRUNTIME_DIR=$(pwd)/onnxruntime-linux-x64-gpu-1.8.1
export LD_LIBRARY_PATH=$ONNXRUNTIME_DIR/lib:$LD_LIBRARY_PATH
2.使用 Docker 镜像
1)使用dockerfile 构建
2)现成镜像
https://hub.docker.com/r/openmmlab/mmdeploy/tags
sudo docker pull openmmlab/mmdeploy:ubuntu20.04-cuda11.3-mmdeploy1.0.0
sudo docker run --gpus all -it openmmlab/mmdeploy:ubuntu20.04-cuda11.3-mmdeploy1.0.0
3.编译码源安装
Inference SDK 的 c/cpp 库可从这里 选择版本下载并安装。
目录结构
# 获取码源
$ git clone -b 1.x https://github.com/open-mmlab/mmdeploy.git --recursive
$ tree -L 1 mmdeploy
├── CMakeLists.txt # 编译模型转换自定义算子和 SDK 的 cmake 配置
├── configs # 模型转换要用的算法库配置
├── csrc # SDK 和自定义算子
├── demo # 各语言的 ffi 接口应用实例,如 csharp、java、python 等
├── docker # docker build
├── mmdeploy # 用于模型转换的 python 包
├── requirements # python 包安装依赖
├── service # 有些小板子不能跑 python,模型转换用的 C/S 模式。这个目录放 Server
├── tests # 单元测试
├── third_party # SDK 和 ffi 要的第三方依赖
└── tools # 工具,也是一切功能的入口。除了 deploy.py 还有 onnx2xx.py、profiler.py 和 test.py
-
csrc/mmdeploy 目录结构:
├── apis # Csharp、java、go、Rust 等 ffi 接口 ├── backend_ops # 各推理框架的自定义算子 ├── CMakeLists.txt ├── codebase # 各 mm 算法框架偏好的结果类型,例如检测任务多用 bbox ├── core # 脚手架,对图、算子、设备的抽象 ├── device # CPU/GPU device 抽象的实现 ├── execution # 对 exec 抽象的实现 ├── graph # 对图抽象的实现 ├── model # 实现 zip 压缩和非压缩两种工作目录 ├── net # net 的具体实现,例如封装了 ncnn forward C 接口 ├── preprocess # 预处理的实现 └── utils # OCV 工具类
1)一键式脚本安装
cd mmdeploy
python3 tools/scripts/ build_ubuntu_x64_ort.py
# 或
# bash tools/scripts/build_linux_nvidia.sh
2)手动编译安装【推荐】
通过预编译包只能安装特定版本的mmdeploy python库,且没有c++库,如果需要特定推理后端版本且支持c++ api的mmdeploy,则需要手动编译。
安装依赖
-
编译工具链依赖
# 保证 cmake的版本 >= 3.14.0 wget https://github.com/Kitware/CMake/releases/download/v3.20.0/cmake-3.20.0-linux-x86_64.tar.gz tar -xzvf cmake-3.20.0-linux-x86_64.tar.gz sudo ln -sf $(pwd)/cmake-3.20.0-linux-x86_64/bin/* /usr/bin/ # MMDeploy SDK 使用了 C++17 特性,因此需要安装gcc 7+以上的版本。 # 如果 Ubuntu 版本 < 18.04,需要加入仓库 sudo add-apt-repository ppa:ubuntu-toolchain-r/test sudo apt-get update sudo apt-get install gcc-7 sudo apt-get install g++-7
编译MMDeploy 后端自定义算子库
git clone -b 1.x git@github.com:open-mmlab/mmdeploy.git --recursive
cd mmdeploy
export MMDEPLOY_DIR=$(pwd)
# get onnxruntime
ONNXRUNTIME_VERSION=1.11.1
wget https://github.com/microsoft/onnxruntime/releases/download/v${ONNXRUNTIME_VERSION}/onnxruntime-linux-x64-${ONNXRUNTIME_VERSION}.tgz
tar -zxvf onnxruntime-linux-x64-${ONNXRUNTIME_VERSION}.tgz
export ONNXRUNTIME_DIR=$(pwd)/onnxruntime-linux-x64-${ONNXRUNTIME_VERSION}
# get tensorrt
tar -zxvf TensorRT-8.2.1.8.Linux.x86_64-gnu.cuda-11.4.cudnn8.2.tar.gz
pip install TensorRT-8.2.1.8/python/tensorrt-8.2.1.8-cp38-none-linux_x86_64.whl
export TENSORRT_DIR=$(pwd)/TensorRT-8.2.1.8
export LD_LIBRARY_PATH=$TENSORRT_DIR/lib:$LD_LIBRARY_PATH
pip install pycuda
# 单独编译trt后端对应的自定义算子库
mkdir -p build && cd build
cmake \
-DMMDEPLOY_TARGET_BACKENDS=trt \
-DTENSORRT_DIR=${TENSORRT_DIR} ..
make -j$(nproc) && make install
# 编译ONNXRuntime后端对应的自定义算子库
rm -rf ./*
cmake \
-DMMDEPLOY_TARGET_BACKENDS=ort \
-DONNXRUNTIME_DIR=${ONNXRUNTIME_DIR} ..
make -j$(nproc) && make install
# 固定安装到 ${MMDEPLOY_DIR}/mmdeploy/lib/
$ cd - && ls mmdeploy/lib/
libmmdeploy_onnxruntime_ops.so libmmdeploy_tensorrt_ops.so
# 安装 Model Converter
$ mim install -e .
$ pip list|grep mm
mmcv-full 1.6.0
mmdeploy 1.0.0rc3 /home/share/mmdeploy
mmengine 0.7.3
- DMMDEPLOY_TARGET_BACKENDS支持 ort、trt、ncnn和torchscript等。
- 自定义后端算子查看此处。
编译Inference SDK C++及python库
# 编译ppl.cv
cd /workspace
git clone https://github.com/openppl-public/ppl.cv.git
cd ppl.cv
export PPLCV_DIR=$(pwd)
git checkout tags/v0.7.0 -b v0.7.0
./build.sh cuda
# 获取文件 cuda-build/install/lib/cmake/ppl
export PLLCV_DIR=$(pwd)/cuda-build/install/lib/cmake/ppl
# 编译Inference sdk
cd ${MMDEPLOY_DIR}
rm -rf build/*
mkdir -p build && cd build
cmake .. \
-DMMDEPLOY_BUILD_SDK=ON \
-DMMDEPLOY_BUILD_EXAMPLES=ON \
-DCMAKE_CXX_COMPILER=g++ \
-Dpplcv_DIR=${PLLCV_DIR} \
-DTENSORRT_DIR=${TENSORRT_DIR} \
-DONNXRUNTIME_DIR=${ONNXRUNTIME_DIR} \
-DMMDEPLOY_BUILD_SDK_PYTHON_API=ON \
-DMMDEPLOY_TARGET_DEVICES="cuda;cpu" \
-DMMDEPLOY_TARGET_BACKENDS="ort;trt" \
-DMMDEPLOY_CODEBASES=all
make -j$(nproc) && make install
# 默认安装到 install目录
$ ls install
bin example include lib
cd -
export LD_LIBRARY_PATH=$(pwd)/build/lib:${LD_LIBRARY_PATH}
- 编译Inference sdk也会重新编译自定义算子库
三、模型转换
1.tools/deploy.py
使用 MMDeploy 中的工具 tools/deploy.py
,将 OpenMMLab 的 PyTorch 模型转换成推理后端支持的格式。
- 现在已支持的后端包括 ONNXRuntime ,TensorRT ,ncnn ,PPLNN ,OpenVINO。
- 现在已支持的代码库包括 MMPretrain ,MMDetection ,MMSegmentation ,MMOCR ,MMEditing。
python ./tools/deploy.py \
${DEPLOY_CFG_PATH} \
${MODEL_CFG_PATH} \
${MODEL_CHECKPOINT_PATH} \
${INPUT_IMG} \
--test-img ${TEST_IMG} \
--work-dir ${WORK_DIR} \
--calib-dataset-cfg ${CALIB_DATA_CFG} \
--device ${DEVICE} \
--log-level INFO \
--show \
--dump-info
-
deploy_cfg
: mmdeploy 针对此模型的部署配置,包含推理框架类型、是否量化、输入 shape 是否动态等。配置文件之间可能有引用关系。 -
model_cfg
: mm 算法库的模型配置,例如mmpretrain/configs/vision_transformer/vit-base-p32_ft-64xb64_in1k-384.py
。 -
checkpoint
: torch 模型路径。可以 http/https 开头。 -
img
: 模型转换时,用做测试的图像或点云文件路径。 -
--test-img
: 用于测试模型的图像文件路径。默认设置成None
。 -
--work-dir
: 工作目录,用来保存日志和模型文件。 -
--calib-dataset-cfg
: 此参数只有int8模式下生效,用于校准数据集配置文件。若在int8模式下未传入参数,则会自动使用模型配置文件中的'val'数据集进行校准。 -
--device
: 用于模型转换的设备。 默认是cpu
,对于 trt 可使用cuda:0
这种形式。 -
--log-level
: 设置日记的等级,选项包括'CRITICAL', 'FATAL', 'ERROR', 'WARN', 'WARNING', 'INFO', 'DEBUG', 'NOTSET'
。 默认是INFO
。 -
--show
: 是否显示检测的结果。 -
--dump-info
: 是否输出 SDK 信息
转换过程
- forward 重写
- 加载自定义算子
- 转换和测试
示例
# 克隆 mmdeploy 仓库。转换时,需要使用 mmdeploy 仓库中的配置文件,建立转换流水线, `--recursive` 不是必须的
git clone -b main --recursive https://github.com/open-mmlab/mmdeploy.git
# 以 MMDetection 中的 Faster R-CNN 为例,将 PyTorch 模型转换为 TenorRT 模型
# 安装 mmdetection。转换时,需要使用 mmdetection 仓库中的模型配置文件,构建 PyTorch nn module
git clone -b 3.x https://github.com/open-mmlab/mmdetection.git
cd mmdetection && mim install -v -e . && cd -
# 执行转换命令,实现端到端的转换
python mmdeploy/tools/deploy.py \
mmdeploy/configs/mmdet/detection/detection_tensorrt_dynamic-320x320-1344x1344.py \
mmdetection/configs/faster_rcnn/faster-rcnn_r50_fpn_1x_coco.py \
checkpoints/faster_rcnn_r50_fpn_1x_coco_20200130-047c8118.pth \
mmdetection/demo/demo.jpg \
--work-dir mmdeploy_model/faster-rcnn \
--device cuda \
--dump-info
2.其他工具
https://github.com/open-mmlab/mmdeploy/blob/main/docs/zh_cn/02-how-to-run/useful_tools.md
1)tools/torch2onnx.py
把 OpenMMLab 模型转 onnx 格式
python tools/torch2onnx.py \
${DEPLOY_CFG} \
${MODEL_CFG} \
${CHECKPOINT} \
${INPUT_IMG} \
--work-dir ${WORK_DIR} \
--device cpu \
--log-level INFO
2)tools/onnx2tensorrt.py
把 onnx 转成 trt .engine 格式
python tools/onnx2tensorrt.py \
${DEPLOY_CFG} \
${ONNX_PATH} \
${OUTPUT} \
--device-id 0 \
--log-level INFO \
--calib-file /path/to/file
四、模型推理
在转换完成后,既可以使用 Model Converter 进行推理,也可以使用 Inference SDK。
1.使用 Model Converter 的Python API推理
from mmdeploy.apis import inference_model
result = inference_model(
model_cfg='mmdetection/configs/faster_rcnn/faster_rcnn_r50_fpn_1x_coco.py',
deploy_cfg='mmdeploy/configs/mmdet/detection/detection_tensorrt_dynamic-320x320-1344x1344.py',
backend_files=['mmdeploy_model/faster-rcnn/end2end.engine'],
img='mmdetection/demo/demo.jpg',
device='cuda:0')
2.使用Inference SDK
可以直接运行预编译包中的 demo 程序,输入 mmdeploy_model和图像,进行推理,并查看推理结果。
wget https://github.com/open-mmlab/mmdeploy/releases/download/v1.0.0/mmdeploy-1.0.0-linux-x86_64-cuda11.3.tar.gz
tar xf mmdeploy-1.0.0-linux-x86_64-cuda11.3
cd mmdeploy-1.0.0-linux-x86_64-cuda11.3
# 运行 python demo
python example/python/object_detection.py cuda ../mmdeploy_model/faster-rcnn ../mmdetection/demo/demo.jpg
# 运行 C/C++ demo
# 根据文件夹内的 README.md 进行编译
./bin/object_detection cuda ../mmdeploy_model/faster-rcnn ../mmdetection/demo/demo.jpg
1)Python API
from mmdeploy_runtime import Detector
import cv2
# 读取图片
img = cv2.imread('mmdetection/demo/demo.jpg')
# 创建检测器
detector = Detector(model_path='mmdeploy_models/faster-rcnn', device_name='cuda', device_id=0)
# 执行推理
bboxes, labels, _ = detector(img)
# 使用阈值过滤推理结果,并绘制到原图中
indices = [i for i in range(len(bboxes))]
for index, bbox, label_id in zip(indices, bboxes, labels):
[left, top, right, bottom], score = bbox[0:4].astype(int), bbox[4]
if score < 0.3:
continue
cv2.rectangle(img, (left, top), (right, bottom), (0, 255, 0))
cv2.imwrite('output_detection.png', img)
2)C++ API
#include <cstdlib>
#include <opencv2/opencv.hpp>
#include "mmdeploy/detector.hpp"
int main() {
const char* device_name = "cuda";
int device_id = 0;
// mmdeploy SDK model,以转出的 faster r-cnn 模型为例
std::string model_path = "mmdeploy_model/faster-rcnn";
std::string image_path = "mmdetection/demo/demo.jpg";
// 1. 读取模型
mmdeploy::Model model(model_path);
// 2. 创建预测器
mmdeploy::Detector detector(model, mmdeploy::Device{device_name, device_id});
// 3. 读取图像
cv::Mat img = cv::imread(image_path);
// 4. 应用预测器推理
auto dets = detector.Apply(img);
// 5. 处理推理结果: 此处我们选择可视化推理结果
for (int i = 0; i < dets.size(); ++i) {
const auto& box = dets[i].bbox;
fprintf(stdout, "box %d, left=%.2f, top=%.2f, right=%.2f, bottom=%.2f, label=%d, score=%.4f\n",
i, box.left, box.top, box.right, box.bottom, dets[i].label_id, dets[i].score);
if (bboxes[i].score < 0.3) {
continue;
}
cv::rectangle(img, cv::Point{(int)box.left, (int)box.top},
cv::Point{(int)box.right, (int)box.bottom}, cv::Scalar{0, 255, 0});
}
cv::imwrite("output_detection.png", img);
return 0;
}
CMakeLists
find_package(MMDeploy REQUIRED)
target_link_libraries(${name} PRIVATE mmdeploy ${OpenCV_LIBS})