赞
踩
V100显卡
实验模型:排序模型(基于ernie1.0)
镜像准备:原始镜像(tensorrt 7):nvcr.io/nvidia/tensorrt:21.06-py3
所有模型转换都在该容器中执行。
使用镜像:hub.yun.paic.com.cn/pib-core-dev/train-env:tensorrt7
构建这个docker的Dockerfile:
- FROM hub.yun.paic.com.cn/pib-core-dev/train-env:tensorrt-21.06-py3
- RUN mkdir /root/.pip
- COPY pip.conf /root/.pip/
- RUN pip install tf2onnx
- RUN pip install tensorflow-gpu
- CMD ["sleep", "infinity"]
启动容器:
docker run -d --rm --name tensorrt --gpus all -v /disk2/tensorrt/BERT:/workspace/BERT hub.yun.paic.com.cn/pib-core-dev/train-env:tensorrt7
--gpus all 代表将机器的所有显卡都载入
(注意:载入不代表抢占,机器的其他进程和容器仍然可以使用这些显卡)
实验的所有模型都放在:/disk2/tensorrt/BERT/models
(由于自制的镜像的CMD为 sleep infinity,所以启动容器后,容器不会退出,随时可以登入)
进入容器:
docker exec -it tensorrt bash
tf2onnx GitHub - onnx/tensorflow-onnx: Convert TensorFlow, Keras, Tensorflow.js and Tflite models to ONNX
- cd BERT/models
-
- python -m tf2onnx.convert --saved-model saved_models/shansou_rank/ --output onnx/shansou_rank.onnx --opset 13
tensorflow模型支持saved_model, graphdef, checkpoint,推荐使用saved_model,因为会自动发现和继承原模型的input、output名字。
--opset是onnx的算子版本,版本越高支持的算子数量越多,实测triton server里的onnxruntime最高支持opset 13,因此这里设置13
(建议为13 或是 12 )
(测试时的库版本信息:tensorflow=2.5.0, onnx=1.10.1, tf2onnx=1.9.1)
下面这个方法不能使用jit编译后的pt文件。
对于sbert而言
由于只加载了0_Transformer,转换的模型只有bert的标准输出,无池化结果(将sequence转为平均向量),需要在模型输出之后,额外增加池化函数。
(TODO:如何做到也将1_Pooling加进去?加载父文件夹已测试不通)
- from pathlib import Path
- from transformers.convert_graph_to_onnx import convert
-
- # Handles all the above steps for you
- convert(framework="pt", model="./models/sbert/ernie_3w_lcqmc_50/0_Transformer", output=Path("onnx/sbert.onnx"), opset=12)
由于tensorrt的engine是不可移植,因此开发环境V100的做成的tensorrt engine是无法用在线上环境T4的机器上的。
这里采用triton的onnx的tensorrt执行加速器(execution_accelerator)思路
目前已经测试成功的只有triton server 21.06版本(21.05和21.07都失败,nvidia的release notes多处互相矛盾!!打老王2巴掌!)
在onnx的config里添加
- optimization { execution_accelerators {
- gpu_execution_accelerator : [ {
- name : "tensorrt"
- }]
- }}
则,triton会使用tensorrt加速器对onnx模型进行加速。
(实测这种方式甚至比trtexec转engine的推理速度略快)
1.FAIL : TensorRT input: 1597 has no shape specified,用下面的脚本可以解决
python symbolic_shape_infer.py --input repository/shansou_sbert_onnx/1/model.onnx --output repository/shansou_sbert_onnx/1/model.onnx
2.onnx runtime error 6: Exception during initialization: Attribute not found: axes
通过tf2onnx的opset从13改为12解决掉。
注意:这个方案必须在实际推理相同的GPU型号上执行,例如,必须在T4显卡上执行,生成的engine才能在线上的T4机器用。
另外,batch的范围越大,转换时间越长,远不如triton集成tensorrt加速器的方案快。
使用tensorrt镜像里自带的trtexec工具
trtexec --onnx=onnx/shansou_rank.onnx --saveEngine=engines/shansou_rank.engine --minShapes=input_word_ids:1x128,input_mask:1x128,segment_ids:1x128 --optShapes=input_word_ids:50x128,input_mask:50x128,segment_ids:50x128 --maxShapes=input_word_ids:50x128,input_mask:50x128,segment_ids:50x128 --workspace=1280
--onnx为输入的onnx模型
--saveEngine为输出的tensorrt模型(注意:engine文件和triton里使用的model.plan为同一文件,重命名即可)
--minShapes,--maxShapes 如果不加,则转换出来的模型只能接收固定batch的输入,会让使用很不方便。
上面指令代表,batch的范围为1-50 (注意:这个范围越大,转换的耗时越长,因为tensorrt会根据batch做特定的性能优化)
(测试发现max batch为100时,triton启动会报cuda out of memory,因此这里保守设置为50)
--optShapes 代表实际推理中的典型值,tensorrt会重点优化这个batch数值的性能,这里取排序常用的50
--workspace=1280 原workspace很小,转换过程中会提示提高这个值,以便于有更高的性能。 (发现这个值等于显存的消耗,待确认,因此这里先删除)
如果需要有损的模型,加--fp16或--best(全部精度)即可。
模型运行在V100显卡,tensorrt的转换和运行要求在同一种显卡中的triton服务中,triton服务版本:21.05(集成 tensorrt 7)(hub.yun.paic.com.cn/pib-core/ibudda-triton:tritonserver-21.05-py3)
tensorrt的转换和运行版本也要求一致,否则报错,因此,转换和运行,都在tensorrt7中
(21.06是tensorrt7的最后一个版本,21.07是tensorrt8的第一个版本)
仅需要修改:platform: "tensorrt_plan" 即可
模型名称改为model.plan
仅需要修改:platform: "onnxruntime_onnx" 即可
模型名称改为model.onnx
建议打开tensorrt加速器
- optimization { execution_accelerators {
- gpu_execution_accelerator : [ {
- name : "tensorrt"
- }]
- }}
- optimization { execution_accelerators {
- gpu_execution_accelerator : [
- { name : "auto_mixed_precision" }
- ]
- }}
triton的TFTRT(没有推理优化效果,即使是FP16),不能和混合精度一起用
- optimization { execution_accelerators {
- gpu_execution_accelerator : [ {
- name : "tensorrt"
- parameters { key: "precision_mode" value: "FP16" }}]
- }}
原shansou_rank的tensorflow模型性能为:
batch 1: 35 infer/sec
batch 50: 340 infer/sec
batch 100: 400 infer/sec
打开混合精度:
batch 1: 同上
batch 50: 720 infer/sec
batch 100: 960 infer/sec
triton的TFTRT:
batch 1 : 38
batch 50: 370
转为onnx模型的性能为:
batch 1: 48 infer/sec
batch 50: 320 infer/sec
转为onnx模型+tensorrt execution_accelerator的性能为:
batch 1: 81 infer/sec
batch 50: 470 infer/sec
batch 100: 480 infer/sec
转为tensorrt模型(FP32)的性能为:
batch 1: 181 75 infer/sec
batch 50: 460 infer/sec
pytorch 1.6
batch 1: 97.8
batch 50: 220
pytorch 1.9
batch 1: 87.4
batch 50: 150
onnx
batch 1: 138
batch 50: 230
onnx(dynamic sequence)
当sequence为3时
batch 1: 354
batch 50: 10510
batch 100: 12560
当sequence为7时(输入文字为5个字)
batch 1: 306
batch 50: 6300
batch 100: 7140
sequence 128
batch 1: 245
batch 50: 470
batch 100: 500
当sequence为512时
batch 1: 82
batch 50: 100
batch 100: -(爆显存)
onnx (without pooling)(transformers convert函数)
batch 1:183
batch 50: 310
onnx (without pooling)(tensorRT)(transformers convert函数)
batch 1:153.4
batch 50: 310
pytorch
batch 1:93
batch 50: 450
batch 100: 460
onnx (do_constant_folding=True/False 都是一样的性能,ops=11/12也一样性能)
batch 1: 211
(打开dynamic axes)
batch 1: 238
batch 50: 480
batch 100: 520
onnx(tensorRT)
batch 1: 182
batch 50: 470
batch 100: 480
pytorch 1.9的性能不如1.6
onnx可以指定inputname和outputname,相比pytorch的input_0, output_1具有更好的表达力。
使用tensorRT加速器无法提高性能,反而会下降。
bert的batch性能和最大长度有关,和句子相似度或分类任务无太多关系。
128长度的bert
batch 1时,onnx相比pytorch可以提升150%
batch 50时,onnx只能提高6%,几乎一样
采用动态sequence在处理短输入时,效果非常明显,大批量时可以提升10倍以上的性能
使用triton sdk中的perf_analyzer
batch为50时的示例:
docker run --rm --net=host hub.yun.paic.com.cn/pib-core/ibudda-triton:tritonserver-21.06-py3-sdk perf_analyzer -m shansou_rank_tensorrt --percentile=95 -u localhost:8010 -b 50 -a --concurrency-range 1:4
(-b 是batch,-a是异步,防止超时失败)
--concurrency-range 1:4是从并发线程1到并发线程4的依次测试,等价于--concurrency-range 1:4:1(最后一个为step)
原模型:0.889
FP32:0.889
BEST模式(使能所有精度):0.806
FP16: 0.804
onnx转trt时,会提示一些node无法解析,导致转换trt失败。
triton 21.07无法使能TF的混合精度(TODO:需要再次确认)
这个builder是针对squad bert模型,无法通用,分类模型都无法转换成功,需要学习tensorrt的API函数,通用性不强。
build.py的使用可以部分参考:基于tensorRT的BERT服务部署---填坑记 - 知乎
tensorflow默认集成tensorrt,可用代码将模型转换为tensorrt。
但是实际发现,在TF2官方镜像里,执行这个过程无法成功,提示cudnn的问题,生成了很多tensorrt的过程文件,但是没有最后的单一engine文件,无法使用。
参考:Accelerating Inference in TensorFlow with TensorRT User Guide - NVIDIA Docs
这个功能,在官方的release notes中的21.05提到具有该功能,实际21.05中根本没有效果(浪费了很多时间在onnxruntime集成tensorrt的编译上,操操操)
在21.07中,官方的release notes还张扬的提到tensorrt加速器具有FP16的设置能力,文档也配套了这个功能,实际在一个known issues角落提到,由于tensorrt8的兼容问题,tensorrt加速器的功能拿掉了!(我砍死nvidia的文档团队!)
目前只有21.06中可以打开这个功能
perf_analyzer默认的input-data为random,在测试pytorch时,会出现random的值超过token_type_ids(vocab.txt)的定义范围,导致越界。
一旦出现这个问题,还必须重启triton,否则triton无法正常提供服务。
测试pytorch,需要添加:--input-data zero
代表输入都是0,就能正常测试性能了。
perf_analyzer加-v,可以更详细的看到报错信息。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。