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 build与python 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
安装
如果下载预编译包, onnxruntime 与 onnxruntime-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?