基于Jetson Xavier构建mmdeploy部署镜像流程

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启动效果。


image.png

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

你可能感兴趣的:(基于Jetson Xavier构建mmdeploy部署镜像流程)