TRT8系列—— 版本差异注意事项

        TRT8 一个大版本,8.4-、 8.5、 8.6(包含预览功能)却有很多变动,一不注意就发现很混乱,特备注此贴。建议具体case可以参考这个合集,真心安利:https://github.com/NVIDIA/trt-samples-for-hackathon-cn/tree/master/cookbook

版本差异概述

1)当前使用了8.4;
2)8.5版本废弃了binding, 导致开内存代码不同;
3)8.6版本以后支持dynamic shape统一个profile 用于不同的context。不再支持Pascal (P40),但完全改变了原来TRT engine必须绑定硬件和版本的要求, 现在可以解耦出来,但是有如下限制:

1、binding 改变

1)8.5前需要使用biding 接口

    对应dynamic batch 多个profile 需要计算偏置。偏置或者说index 是针对profile (同一个engine)的不是针对context的。下图是一个engine里有3个profile,模型有4个输入1个输出,那么就有(4+1)*3 =15个binding。
engine.num_bindings 获取binding 总数
engine.binding_is_input 计算出input数量(每个profile里 算一个, engine.binding_is_inpu // nProfile 才是模型的输入个数)
context.set_binding_shape 设置输入输出的维度,如上面表格需要计算出pad和对应输入输出的顺序index
contex.get_binding_shape 获得对应profile 的输出的维度
context.execute_async_v2 执行推理,这里传入的第一个参数为输出输出GPU显存的地址,并且需要填满如上的表格,不用的位置填0。
 
logger = trt.Logger(trt.Logger.ERROR)
engine = trt.Runtime(logger).deserialize_cuda_engine(engineString) # engineString 是二进制 open engine文件
nIO = engine.num_bindings
nInput = np.sum([engine.binding_is_input(i) for i in range(engine.num_bindings)])
nOutput = nIO - nInput
nIO, nInput, nOutput = nIO // nProfile, nInput // nProfile, nOutput // nProfile
context = engine.create_execution_context()
context.set_optimization_profile_async(index, stream)
bindingPad = nIO * index_profile  # 计算binding 的偏置
context.set_binding_shape(bindingPad + 0, inputShape) # 第一个输入
outputShape = contex.get_binding_shape(bindingPad + nInput + 0) # 第一个输出
bufferList = [int(0) for b in bufferD[:bindingPad]] + \
             [int(b) for b in bufferD[bindingPad:(bindingPad + nInput + nOutput)]] + \
             [int(0) for b in bufferD[(bindingPad + nInput + nOutput):]]
context.execute_async_v2(bufferList, stream)

2)8.5 之后废弃binding

    使用范例如下
engine.num_io_tensors  获取输入输出总个数
engine.get_tensor_name  获得对应的输入输出名字
engine.get_tensor_mode 判断是输入还是输出(trt.TensorIOMode.INPUT 、trt.TensorIOMode.OUTPUT)
context.set_input_shape 直接设置对应的形状,不再需要计算偏置
context.get_tensor_shape 直接获得输入输出(需要先设置输入自动计算)形状
context.set_tensor_address 绑定TRT 输入输出和 开辟的显存
context.execute_async_v3 来执行推理
logger = trt.Logger(trt.Logger.ERROR)
engine = trt.Runtime(logger).deserialize_cuda_engine(engineString) # engineString 是二进制 open engine文件
nIO = engine.num_io_tensors
lTensorName = [engine.get_tensor_name(i) for i in range(nIO)]
nInput = [engine.get_tensor_mode(lTensorName[i]) for i in range(nIO)].count(trt.TensorIOMode.INPUT)
context = engine.create_execution_context()
context.set_optimization_profile_async(index, stream)
context.set_input_shape(lTensorName[0], inputShape)
outputShape = context.get_tensor_shape(lTensorName[1])
context.set_tensor_address(lTensorName[0], int(cudart.cudaMalloc(nbytes)[1]))
context.execute_async_v3(0)

2、dynamic shape 性能

如果跨度较大建议使用多个配置文件,可以明显提升推理性能
参考:
    获得真实推理形状(假设真实为(3,150,150)),要使用 context.get_tensor_shape(0) (返回 (3, 150, 250)),而不是 engine.get_tensor_shape("foo”)  (返回  (3, -1, -1)  。

3、engine、 context、stream、profile(动态batch的配置文件)

一个engine 可以拥有多个context,共享一个权重。
可以将不同的context 放到不同的stream 中,实现并行。
一个context可以拥有多个profile(至少一个),但是8.6 0805预览特性前,一个profile 只能绑定一个context(context 和profile 需要错开使用)。
参考:
  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

TigerZ*

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值