1 目标
- 构建mmdeploy在Jetson Xavier的转换转换环境,方便直接将模型转换成tensort并执行推理;
- 转换后的模型能够在triton-serve加载并使用
- 支持图片分类、目标检测和实例分隔三种模型的转换;
2 环境
- 硬件:Jetson Xavier
- 系统:JetPack4.6
- 基础容器:nvcr.io/nvidia/l4t-ml:r32.6.1-py3
- Nvidia官方镜像仓库:https://catalog.ngc.nvidia.com/containers
3 基本问题
问:什么是JetPack?
答:Nvidia制作的Jetson上的系统包,需要下载再烧录到SD卡上
问:如何更新JetPack?
答:4.4之后的可以直接在线升级,之前的仍然需要烧录
问:如何烧录JetPack?
答:
- ① 下载JetPack SD Card Image:https://developer.nvidia.com/jetpack-sdk-44-archive
- ② 参考教程制作:https://developer.nvidia.com/embedded/learn/get-started-jetson-xavier-nx-devkit#prepare
- 下载SD Card Formatter,格式化SD卡
- 下载balenaEtcher-Setup-1.7.7,烧录镜像
- ③ 把SD卡拔出,插入到板子上即可
问:什么是L4T
答:L4T是Linux for Tegra的缩写,因为jetson系列用的是Tegra架构,因此L4T可以理解为jetson定制的Linux操作系统,具体的来说就是ubuntu定制款。
4 制作Jetson上的MMDeploy镜像
构建Jetson上的镜像探索了两种思路,
- 思路1:在x86架构的机器上交叉编译,然后制作成镜像。可以参考交叉编译,我尝试该方法后发现,在x86机器上的编译速度并不是很快,同时编译后不方便测试GPU是否能够使用起来,因此该方案没有进行深入探索。
- 思路2:直接在aarch64的机器上构建容器环境,一些包的编译相对较慢,但是只需编译一次就可以了。
本实验探索在nvcr.io/nvidia/l4t-ml:r32.6.1-py3镜像的基础上构建容器,所以需要先手动执行一遍,最后形成构建容器的Dockerfile。下面先介绍探索的过程以及探索过程中遇到的一些坑。
4.1 准备容器环境
注意:后续的操作都是在启动的容器中进行操作的。
docker run -d -it --runtime nvidia --name jetson-ml -v /opt/data/code/software:/software --network host nvcr.io/nvidia/l4t-ml:r32.6.1-py3 /bin/bash # 启动容器
docker exec -it jetson-ml /bin/bash # 进入容器
docker stop jetson-ml && docker rm jetson-ml # 停止并删除容器
注意启动参数中添加了--runtime nvidia,否则cuda相关的库会用无法使用。
nvcr.io/nvidia/l4t-ml:r32.6.1-py3镜像中已经自带了下列包,因此不需要安装。
- TensorFlow 1.15.5
- PyTorch v1.9.0
- torchvision v0.10.0
- torchaudio v0.9.0
- onnx 1.8.0
- CuPy 9.2.0
- numpy 1.19.5
- numba 0.53.1
- OpenCV 4.5.0 (with CUDA)
- pandas 1.1.5
- scipy 1.5.4
- scikit-learn 0.23.2
- JupyterLab 2.2.9
安装必要的包
apt update
apt install python3-tk unzip -y
pip3 install tkinter
4.2 升级cmake
cmake升级有两种方案,① 直接下载cmake源码,然后进行编译,编译时间大概1个小时左右。② 下载预编译好的cmake,直接下载cmake-3.21.6-linux-aarch64.sh。
方案1:下载源码并编译
apt-get remove cmake # 卸载系统自带的cmake
wget https://github.com/Kitware/CMake/archive/refs/tags/v3.22.1.tar.gz
tar zxvf v3.22.1.tar.gz
cd v3.22.1
./bootstrap && make && make install
方案2:下载预编译包
wget https://github.com/Kitware/CMake/releases/download/v3.21.6/cmake-3.21.6-linux-aarch64.sh
sh cmake-3.21.6-linux-aarch64.sh
export PATH=$PATH:/INSTALL_PATH/cmake-3.21.6-linux-aarch64/bin # 注意必须要导出安装路径
4.3 编译安装spdlog
spdlog一个开源的C++日志库,后续mmdeploy编译时需要。编译前需要在Cmakelists.txt中添加add_compile_options(-fPIC),否则后续mmdeploy编译会报错。
cd spdlog-1.9.2 && mkdir build && cd build && cmake .. && make -j$(nproc) && make install
4.4 编译安装ppl.cv
ppl.cv是openPPL的高性能图像处理库,后续mmdeploy编译时需要。
unzip ppl.cv-0.6.1.zip && mv ppl.cv-0.6.1 ppl.cv && cd ppl.cv && ./build.sh cuda
4.5 安装onnxruntime
onnxruntime在1.10.0版本之后,直接发布了aarch64的预编译版本onnxruntime-linux-aarch64-1.10.0.tgz,直接下载使用即可。
下载后执行解压、并导出对应的环境变量
tar zxvf onnxruntime-linux-aarch64-1.10.0.tgz -C /workspace
export ONNXRUNTIME_DIR=/workspace
安装onnxruntime-gpu
pip3 install onnxruntime-gpu==1.10.0
4.6 安装mmcv-full
pip3 install mmcv-full==1.4.5 -f https://download.openmmlab.com/mmcv/dist/cu102/torch1.9.0/index.html
首次使用的系统会自动编译,编译完成后可以从缓存中把编译的whl包保存下来,下次就不用编译了,首次编译时间大概也需要1个小时左右。获取到编译的包之后,直接pip3 install mmcv_full-1.4.5-cp36-cp36m-linux_aarch64.whl
即可。
4.7 安装mmdet/mmseg/mmcls
上述环境准备好之后,这三个包直接pip安装即可,命令如下:
pip3 install mmdet==2.21.0 mmcls==0.20.1 mmsegmentation==0.18.0
4.8 编译安装mmdeploy
下载mmdeploy,处理mmdeploy,还需要下载对应子模块的代码。
git clone https://github.com/open-mmlab/mmdeploy.git
cd mmdeploy
export MMDEPLOY_DIR=$(pwd) # 注意要导出MMDEPLOY_DIR后续编译需要用到。
git submodule update --init --recursive
编译onnruntime和tensorrt支持库
cd mmdeploy &&\
rm -rf build &&\
mkdir build &&\
cd build &&\
cmake -DMMDEPLOY_TARGET_BACKENDS=ort .. &&\
make -j$(nproc) &&\
cmake -DMMDEPLOY_TARGET_BACKENDS=trt .. &&\
make -j$(nproc) &&\
cd .. &&\
pip3 install -e .
编译sdk支持
cd mmdeploy &&\
rm -rf build/CM* &&\
mkdir -p build && cd build &&\
cmake .. \
-DMMDEPLOY_BUILD_SDK=ON \
-DCMAKE_CXX_COMPILER=aarch64-linux-gnu-g++ \
-Dpplcv_DIR=/software/ppl.cv/cuda-build/install/lib/cmake/ppl \
-DMMDEPLOY_BUILD_SDK_PYTHON_API=ON \
-DMMDEPLOY_TARGET_DEVICES="cuda;cpu" \
-DMMDEPLOY_TARGET_BACKENDS="trt" \
-DMMDEPLOY_CODEBASES=all &&\
cmake --build . -- -j$(nproc) && cmake --install . &&\
cd install/example && mkdir -p build && cd build &&\
cmake -DMMDeploy_DIR=/software/mmdeploy/build/install/lib/cmake/MMDeploy ..
编译完成后导出mmdeploy的库:
export LD_LIBRARY_PATH="DIR/mmdeploy/build/lib:${LD_LIBRARY_PATH}"
5 Dockerfile
FROM nvcr.io/nvidia/l4t-ml:r32.6.1-py3
ARG CUDA=10.2.460
ARG PYTHON_VERSION=3.6.9
ARG TORCH_VERSION=1.9.0
ARG TORCHVISION_VERSION=0.10.0
ARG ONNXRUNTIME_VERSION=1.10.0
ARG MMCV_VERSION=1.4.5
ENV WORK_DIR=/root/workspace
ENV DEBIAN_FRONTEND=noninteractive
ENV PATH="${PATH}:${WORK_DIR}/cmake-3.21.6-linux-aarch64/bin"
ENV LD_LIBRARY_PATH="${WORK_DIR}/mmdeploy/build/lib:${LD_LIBRARY_PATH}"
ENV ONNXRUNTIME_DIR="${WORK_DIR}/onnxruntime-linux-aarch64-1.10.0"
WORKDIR /root/workspace
### copy files
copy files $WORK_DIR
RUN cd $WORK_DIR && apt update && apt-get remove cmake -y && apt install python3-tk unzip -y &&\
sh -c '/bin/echo -e "\ny\ny" | sh cmake-3.21.6-linux-aarch64.sh'
RUN cd $WORK_DIR &&\
pip3 install onnxruntime_gpu-1.10.0-cp36-cp36m-linux_aarch64.whl &&\
pip3 install mmcv_full-1.4.5-cp36-cp36m-linux_aarch64.whl &&\
pip3 install mmdet==2.21.0 mmcls==0.20.1 mmsegmentation==0.18.0 &&\
tar zxvf onnxruntime-linux-aarch64-1.10.0.tgz
RUN cd $WORK_DIR/spdlog-1.9.2 && mkdir build && cd build && cmake .. && make -j$(nproc) && make install
RUN cd $WORK_DIR && unzip ppl.cv-0.6.1.zip && mv ppl.cv-0.6.1 ppl.cv &&\
cd ppl.cv && ./build.sh cuda
ENV MMDEPLOY_DIR="${WORK_DIR}/mmdeploy"
RUN cd $WORK_DIR/mmdeploy &&\
rm -rf build &&\
mkdir build &&\
cd build &&\
cmake -DMMDEPLOY_TARGET_BACKENDS=ort .. &&\
make -j$(nproc) &&\
cmake -DMMDEPLOY_TARGET_BACKENDS=trt .. &&\
make -j$(nproc) &&\
cd .. &&\
pip3 install -e .
RUN cd $WORK_DIR/mmdeploy &&\
rm -rf build/CM* &&\
mkdir -p build && cd build &&\
cmake .. \
-DMMDEPLOY_BUILD_SDK=ON \
-DCMAKE_CXX_COMPILER=aarch64-linux-gnu-g++ \
-Dpplcv_DIR=${WORK_DIR}/ppl.cv/cuda-build/install/lib/cmake/ppl \
-DMMDEPLOY_BUILD_SDK_PYTHON_API=ON \
-DMMDEPLOY_TARGET_DEVICES="cuda;cpu" \
-DMMDEPLOY_TARGET_BACKENDS="trt" \
-DMMDEPLOY_CODEBASES=all &&\
cmake --build . -- -j$(nproc) && cmake --install . &&\
cd install/example && mkdir -p build && cd build &&\
cmake -DMMDeploy_DIR=${WORK_DIR}/mmdeploy/build/install/lib/cmake/MMDeploy ..
RUN rm -f ${WORK_DIR}/*.gz && rm -f ${WORK_DIR}/*.tgz && rm -f ${WORK_DIR}/*.zip
适配Xavier JetPack4.6的Dockerfile以及对应的文件链接:https://pan.baidu.com/s/14WXskPdrS7BI_HcrXUY0LQ
提取码:r9z0
6 测试模型转换以及tritonserver的部署
用到的测试模型以及配置文件下载地址:
链接:https://pan.baidu.com/s/1uZ7pi2KszHkC2vkZ8UPi1A
提取码:cp1r
模型转换测试
docker run -it --rm -w /root/workspace/mmdeploy \
-v /root/software:/software --network host 172.18.18.222:5000/schinper/ai-train:schiper_deploy_xavier_v1.0 python3 tools/deploy.py /software/model/cls_139_1182/model_deploy_config.py \
/software/model/cls_139_1182/mmcls_model_config.py /software/model/cls_139_1182/latest.pth /software/model/cls_139_1182/demo.jpg \
--test-img /software/model/cls_139_1182/demo.jpg \
--work-dir /software/model/cls_139_1182/convert \
--device cuda:0 --log-level INFO --dump-info
tritonserver的配置文件
路径格式
- tritonserver
- 139_1182_resnet18_cls_tensorrt
- 1
- model.plan
- config.pbtxt
config.pbtxt配置
name: "139_1182_resnet18_cls_tensorrt"
platform: "tensorrt_plan"
max_batch_size : 0
input [
{
name: "input"
data_type: TYPE_FP32
format: FORMAT_NCHW
dims: [3, 224, 224]
reshape { shape: [1, 3, 224, 224] }
}
]
output [
{
name: "output"
data_type: TYPE_FP32
dims: [1000]
reshape { shape: [ 1, 1000] }
}
]
启动tritonserver【JetPack4.6中已经预装tritonserver2.19.0,直接使用即可】,需要指定与加载的TensorRT算子,具体操作参考下面的问题3。tritonserver启动效果。
7 遇到的坑
问题1:构建镜像时出现如下错误 CUDA_cublas_LIBRARY
CMake Error: The following variables are used in this project, but they are set to NOTFOUND.
Please set them or make sure they are set and tested correctly in the CMake files:
CUDA_cublas_LIBRARY (ADVANCED)
linked by target "mmdeploy_tensorrt_ops_obj" in directory /root/workspace/mmdeploy/csrc/backend_ops/tensorrt
-- Generating done
CMake Generate step failed. Build files cannot be regenerated correctly.
解决方法:需要将docker的runtime 默认设置为"default-runtime": "nvidia" ,在docker的daemon.json
中添加"default-runtime": "nvidia"
。示例如下:
{
"runtimes": {
"nvidia": {
"path": "nvidia-container-runtime",
"runtimeArgs": []
}
},
"insecure-registries": ["172.18.18.222:5000"],
"default-runtime": "nvidia"
}
问题2:mmdeploy在编译的时出现dangerous relocation: unsupported relocation错误
解决方法:出现这个问题主要是由于编译spdlog时,需要在spdlog的Cmakelists.txt中添加add_compile_options(-fPIC)
,否则会出现上述的链接定位错误。
问题3:加载模型是出现下面的错误
E0311 04:18:11.717970 28535 logging.cc:43] 1: [pluginV2Runner.cpp::load::290] Error Code 1: Serialization (Serialization assertion creator failed.Cannot deserialize plugin since corresponding IPluginCreator not found in Plugin Registry)
E0311 04:18:11.718220 28535 logging.cc:43] 4: [runtime.cpp::deserializeCudaEngine::50] Error Code 4: Internal Error (Engine deserialization failed.)
I0311 04:18:11.799840 28535 tensorrt.cc:5345] TRITONBACKEND_ModelInstanceFinalize: delete instance state
I0311 04:18:11.800085 28535 tensorrt.cc:5283] TRITONBACKEND_ModelFinalize: delete model state
E0311 04:18:11.801115 28535 model_repository_manager.cc:1152] failed to load '147_1297_retinanet_det_tensorrt' version 1: Internal: unable to create TensorRT engine
解决方法:出现该问题的原因是因为tensorrt中没有mmdeploy新增的算子,因此需要将构建镜像时编译生成的库,拷贝到tritonserver可以使用的地方。
# 启动一个容器
docker run -it --rm --name temp 172.18.18.222:5000/schinper/ai-train:schiper_deploy_xavier_v1.0 /bin/bash
# 在另外一个console下执行拷贝
docker cp /root/workspace/mmdeploy/build/install/lib /root/mmdeploy_lib
# 指定预加载库,并启动tritonserver
LD_PRELOAD=/root/mmdeploy_lib/libmmdeploy_tensorrt_ops.so ./tritonserver --model-repository=/root/models