Skip to main content

resnet18 并行推理

线程安全的本地推理

为了方便,假设将tensorrt推理功能封装为名称为 TensorrtTensor计算后端。由于计算发生在gpu设备上,我们加上SyncTensor 表示gpu上的流同步操作。

配置项参数说明
backend"SyncTensor[TensorrtTensor]"计算后端和tensorrt推理本身一样,不是线程安全的。
max4模型支持的最大batchsize,用于模型转换(onnx->tensorrt)

如果可以从多个线程中同时调用某个函数,则该函数是线程安全的。提供线程安全的接口将极大的方便使用者。

torchpipe默认会在此计算后端上包裹一层可扩展的单节点调度后端,实现以下三个基本能力:

  • 前向接口线程安全性
  • 多实例并行

    配置项默认值说明
    instance_num1多个模型实例并行执行推理任务。
  • Batching

    对于resnet18, 模型本身输入为-1x3x224x224, batchsize越大,单位硬件资源所完成的任务越多。 batchsize 从计算后端(TensorrtTensor)读取。

    配置项默认值说明
    batching_timeout0单位为毫秒,在此时间内如果没有接收到 batchsize 个数目的请求,则放弃等待。

性能调优技巧

汇总以上步骤,我们获得推理resnet18在torchpipe下的必要参数:

import torchpipe as tp
import torch
config = {
# 单节点调度器参数:
"instance_num":2,
"batching_timeout":5,
# 计算后端:
"backend":"SyncTensor[TensorrtTensor]",
# 计算后端参数:
"model":"resnet18_-1x3x224x224.onnx",
"max":4
}

# 初始化
models = tp.pipe(config)
data = torch.ones(1,3,224,224).cuda()

## 前向
input = {"data":data}
models(input) # <== 可多线程调用
result: torch.Tensor = input["result"] # 失败则 "result" 不存在

假设我们想要支持最多10路的客户端/并发请求, instance_num 一般设置2,以便最多有处理 instance_num*max = 8 路的能力。

性能取舍

请注意,我们的加速做了如下假设:

cpu到cpu,单张显卡内部gpu到gpu的数据拷贝)速度快,消耗资源少,整体上可忽略不计。

提示

相对于异构设备间的数据拷贝以及其他的计算,这条假设是没问题的。后面我们将看到,在一些特殊场景,这条假设可能不成立,需要相应的规避手段。

小结

从接口层面,我们实现了所有的预定目标:

  • 使用tensorrt等框架进行模型针对性加速
  • 避免频繁显存申请 : 透过pytorch的显存池完成
  • 多实例,batching : 透过单节点调度后端完成
  • 优化数据传输: 透过将torch.Tensor作为输入输出载体实现。