DL-deploy

  • Compiler:

    • 编译原理: B站华保健老师课程及作业

    • LLVM: GiantPandasCV B站视频

    • TVM: 陈天奇B站视频及讲义

    • pytorch: pytorch 2.0, torch.fx, torch.jit.trace, torch.jit.script

  • Inference Engine:

    • mmdeploy(优先级高): 官方文档

    • onnx(优先级高): 官方文档

    • tensorRT:

  • 追剧计划:

    • GiantPandasCV

    • mmlab

    • 李沐

  • 其他前置知识

    • cmake, make(优先级高)

    • pybind11(优先级高)

各个知识点之间的联系:

部署流程:

最终一般是用推理框架来完成的, 例如: tensorRT, ncnn, onnxruntime。这些框架都各自定义了一套模型存储格式, 根据这套存储格式适配一种或多种硬件做推理。而当前主流的训练框架有pytorch, tensorflow等, 他们各自定义了一套模型存储格式, 因此本质上需要:

因此可能需要 $m \times n$ 种转换, 因此 onnx 作为中间格式应运而生, 这样子只需要 $m+n$ 种转换:

注意: 可以看出, 实际上部署流程并非都得走 torch(.pth) -> onnx(.onnx) -> tensorRT(.engine) 这种流程, 能直接转成(.engine)格式实际就可以达到目的, 只是因为"生态"的原因, 通常会走两步转换的流程.

make, cmake, gcc/g++, llvm

参见个人笔记

pybind11

结论: 目前最为流行的方式是 pybind11, 许多开源项目一般将 pybind11 作为 git submodule 放在 third_party 文件夹中, 源码编译这些开源项目会用到 pybind11, 例如:

  • onnx: https://github.com/onnx/onnx/tree/main/third_party

  • pytorch: https://github.com/pytorch/pytorch/tree/master/third_party

  • tvm: 不确定是否使用 pybind11

  • tensorflow: 不确定是否使用 pybind11

  • mmdeploy: https://github.com/open-mmlab/mmdeploy/tree/master/third_party

  • mxnet: 不确定是否使用 pybind11

  • faiss: 似乎不是 pybind11, https://github.com/facebookresearch/faiss

  • SPTAG: 使用 SWIG, https://github.com/microsoft/SPTAG

cpython 原生的 C 拓展的方式为:

pybind11实际上是对这种拓展方式做了层层封装

存在其他的python调用C/C++扩展的方式:

  • ctypes

  • cython

  • swig

详细内容参见 个人博客

onnx

Protocol Buffer (Finished)

Google定义了一套用于代替xml,json的格式, 并提供了一套完整的库来解析, 序列化这种数据格式, onnx的序列化使用了这种格式

官方文档: https://developers.google.com/protocol-buffers/docs

安装步骤参考官方教程进行, 此处简单记一下,两项均需要安装:

  • 安装 protoc(任选其一):

    • 从官方 Github 的 Release 中下载关于 protoc 的压缩包,里面有预编译好的二进制 protoc 文件,并将它添加至 $PATH 变量中

    • 下载源码按官方教程编译出 protoc

  • 安装 protobuf runtime (此处仅记录python,以下方式任选其一)

    • pip install protobuf==xx.xx.xx

    • 从官方 Github 的 Release 中下载源代码, 进入python 文件夹后, 执行 python setup buildpython setup install

python 使用 protobuf 分为如下几步:

  • 定义数据规范: 即声明字段及字段的类型等(即定义结构体), 这种声明使用的是一种特殊的语法, 保存在一个 .proto 文件中

  • 使用 protoc 命令工具用 .proto 文件生成一个 .py 文件(自动生成代码)

  • import 这个生成的文件以创建 .proto 里声明的数据结构对象, 并可以使用相关方法将数据解析或保存到文件中

示例(来源于官方教程):

第一步: 定义"数据结构"

第二步: 根据"数据结构"自动生成代码

备注: 如果使用者直接拿到这个.py文件, 实际上就已经可以进行第三步

第三步: 利用生成的 .py 文件操作数据

onnx 概念

参考官方文档,此处仅简要列出:

  • node: 即张量op

    • attribute: 张量op的参数, 例如: Unsqueeze 算子(opset11版本) 中的 axes 就是 attribute, 构建计算图时就会确定好具体的取值

  • input: 即张量op的输入

    • initializer: 一种特殊的输入, 固定的权重

  • output: 即张量op的输出

  • domain: onnx用domain将op进行划分(即domain是一些op的集合), 官方只定义了如下几个domain:

    • ai.onnx: 包含 Add, Conv, Relu 等

    • ai.onnx.ml: 包含 TreeEnsembleRegressor, SVMRegressor 等

    • ai.onnx.preview.training: onnx v1.7.0 新特性, 包含 Adam 等

  • graph: 使用node, input, output搭建的图

  • opset version:

    • opset version: 可以通过以下方式查看当前版本的onnx的opset版本号

    • op version: 每个op都有自己的版本号, 例如: Add 操作有 1, 6, 7, 13, 14这几个版本号, 这代表 Add 操作随着 opset 更新的版本

    • 一个graph会为每个domain记录一个全局的opset版本号,graph内的所有node都会按照所在的domain的opset版本号决定其版本号, 例如一个graph里设定的的ai.onnx这个domain的opset版本号为8, 则 Add 操作的版本号为 7

  • proto: 上述概念实现上采用了Protocol Buffer, onnx 定义了如下的数据结构

    • 核心: TensorProto, TensorShapeProto, TypeProto, ValueInfoProto, AttributeProto, OperatorProto, FunctionProto, NodeProto, GraphProto, ModelProto, TrainingInfoProto

    • 其他: MapProto, OperatorSetIdProto, OperatorSetProto, OptionalProto, SequenceProto, SparseTensorProto, StringStringEntryProto,

下面是一个具体的例子:

首先参考例子使用 torch.onnx.export 转换模型得到一个 .onnx 格式的文件

然后读取并解析

d 的内容如下:

备注: "AACAPw==" 代表 32 位浮点数的原因可以参考这个issue

onnx Python API: (low level)

onnx定义模型的方式是使用 *Proto 的方式进行的:

源码安装解析

此处结合 make, cmake, pybind11, setup.py, protocol buffer 对 onnx 项目的安装过程以及一些使用时的调用栈进行分析

onnxruntime

安装

如果下载预编译包, onnxruntimeonnxruntime-gpu 不能同时安装

备注:

  • onnxruntime-gpu==1.6.0 Pypi 预编译包不带 TensorrtProvider

  • onnxruntime-gpu==1.10.0 Pypi 预编译包包含 TensorrtProvider

  • 无论哪种情况都要注意 onnxruntime/capi/_ld_preload.py

一个例子

本节主要对官方的示例代码

本质上干了两件事

源码安装解析

这里以 TensorRT (文档, Dockerfile) 举例。

这里结合官方Dockerfile简述一下 onnxruntime-gpu==1.6.0 的源码安装步骤, 官方的 Dockerfile 的内容简化为如下:

镜像的 build 命令为

首先对基础镜像 nvcr.io/nvidia/tensorrt:20.10-py3 (nvcr.io/nvidia/tensorrt:20.07.1-py3 应该类似) 做一些说明, 该基础镜像包含 CUDA、cuDNN、TensorRT, 相关信息如下:

默认动态链接库目录

gcc默认头文件目录

CUDA、cuDNN、TensorRT

源码安装的关键命令为

Last updated

Was this helpful?