Python API vs C++ API of TensorRT
本质上,C++ API和Python API应该在支持您的需求方面接近相同。pythonapi的主要优点是数据预处理和后处理都很容易使用,因为您可以使用各种库,如NumPy和SciPy。 在安全性很重要的情况下,例如,在汽车中,C++ API应该被使用。有关C++ API的更多信息,请参见使用C++ API。
有关如何使用Python优化性能的更多信息,请参阅how Do I optimize My Python performance?来自TensorRT最佳实践指南。
import tensorrt as trt
TRT_LOGGER = trt.Logger(trt.Logger.WARNING)
使用TensorRT执行推理的第一步是从模型创建一个TensorRT网络。
实现这一点的最简单方法是使用TensorRT解析器库导入模型, (see Importing A Model Using A Parser In Python, Importing From Caffe Using Python, Importing From TensorFlow Using Python, and Importing From ONNX Using Python), which supports serialized models in the following formats:
An alternative is to define the model directly using the TensorRT Network API, (see Creating A Network Definition From Scratch Using The Python API). This requires you to make a small number of API calls to define each layer in the network graph and to implement your own import mechanism for the model’s trained parameters.
下面的步骤说明了如何使用OnnxParser和pythonapi直接导入ONNX模型。 关于这个任务
有关更多信息,请参阅使用Python(introductive_parser_samples)示例将Caffe、TensorFlow和ONNX模型导入TensorRT的简介。
注:
一般来说,较新版本的OnnxParser设计为向后兼容,因此,遇到由早期版本的ONNX导出器生成的模型文件不会引起问题。当更改不向后兼容时,可能会出现一些异常。在本例中,将早期的ONNX模型文件转换为更高版本的支持版本。有关此主题的详细信息,请参阅ONNX Model Opset Version Converter。
用户模型也有可能是由一个支持比TensorRT附带的ONNX解析器支持的操作集更新的导出工具生成的。在这种情况下,检查发布到GitHub的TensorRT的最新版本onnx-tensorrt是否支持所需的版本。有关更多信息,请参阅Python中使用Object Detection With The ONNX TensorRT Backend In Python (yolov3_onnx)示例。
支持的版本由onnx_trt中的BACKEND_optset_version变量定义_后端.cpp. 从GitHub下载并构建最新版本的ONNXTensorRT解析器。可以在这里找到构建说明:用于TensorRT backend for ONNX后端。
在tensorrt7.0中,ONNX解析器只支持全维模式,这意味着必须使用explicitBatch标志集创建网络定义。有关详细信息,请参见使用动态形状Working With Dynamic Shapes。
builder的功能之一是搜索其CUDA内核目录,以获得最快的实现,因此有必要使用相同的GPU来构建优化引擎将运行的GPU。
关于这个任务
IBuilderConfig有许多属性,您可以设置这些属性来控制诸如网络运行的精度,以及自动调整参数,例如在确定哪个内核最快时,TensorRT应该为每个内核计时多少次(迭代次数越多,运行时间越长,但是对噪声的敏感度较低。)您还可以查询构建器,以找出硬件本机支持哪些混合精度类型。
一个特别重要的属性是最大工作空间大小。
层算法通常需要临时工作空间。此参数限制网络中任何层可以使用的最大大小。如果提供的划痕不足,则可能是TensorRT无法找到给定层的实现。
有关用Python构建引擎的更多信息,请参阅使用Python(introductive_parser_samples)示例将Caffe、TensorFlow和ONNX模型导入TensorRT的简介。
Procedure
with trt.Builder(TRT_LOGGER) as builder, builder.create_builder_config() as config:
config.max_workspace_size = 1 << 20 # This determines the amount of memory available to the builder when building an optimized engine and should generally be set as high as possible.
with builder.build_engine(network, config) as engine:
# Do inference here.
When the engine is built, TensorRT makes copies of the weights.
从这里开始,您可以序列化引擎,也可以直接使用引擎进行推断。在使用模型进行推理之前,序列化和反序列化模型是可选的步骤—如果需要,可以直接使用引擎对象进行推理。
关于这个任务
序列化时,您正在将引擎转换为一种格式,以便存储并在以后用于推断。要用于推断,只需对引擎进行反序列化。序列化和反序列化是可选的。由于从网络定义创建引擎可能很耗时,因此可以避免每次应用程序重新运行时重新生成引擎,方法是序列化一次引擎并在推断时反序列化它。因此,在构建引擎之后,用户通常希望序列化它以备以后使用。
注意:序列化引擎不能跨平台或TensorRT版本移植。引擎是特定于确切的GPU模型,他们是建立在(除了平台和TensorRT版本)。
serialized_engine = engine.serialize()
with trt.Runtime(TRT_LOGGER) as runtime: engine = runtime.deserialize_cuda_engine(serialized_engine)
It is also possible to save a serialized engine to a file, and read it back from the file:
Serialize the engine and write to a file:
with open(“sample.engine”, “wb”) as f:
f.write(engine.serialize())
Read the engine from the file and deserialize:
with open(“sample.engine”, “rb”) as f, trt.Runtime(TRT_LOGGER) as runtime:
engine = runtime.deserialize_cuda_engine(f.read())
下面的步骤说明了如何在Python中执行推理,现在您有了一个引擎。
Procedure
为输入和输出分配一些主机和设备缓冲区。本例假设context.all_binding_dimensions == True,并且引擎在binding_index=0时有一个输入,在binding_index=1时有一个输出:
# Determine dimensions and create page-locked memory buffers (i.e. won't be swapped to disk) to hold host inputs/outputs.
h_input = cuda.pagelocked_empty(trt.volume(context.get_binding_shape(0)), dtype=np.float32)
h_output = cuda.pagelocked_empty(trt.volume(context.get_binding_shape(1)), dtype=np.float32)
# Allocate device memory for inputs and outputs.
d_input = cuda.mem_alloc(h_input.nbytes)
d_output = cuda.mem_alloc(h_output.nbytes)
# Create a stream in which to copy inputs/outputs and run inference.
stream = cuda.Stream()
创建一些空间来存储中间激活值。由于引擎保存网络定义和训练参数,因此需要额外的空间。这些在执行上下文中保存:
with engine.create_execution_context() as context:
# Transfer input data to the GPU.
cuda.memcpy_htod_async(d_input, h_input, stream)
# Run inference.
context.execute_async_v2(bindings=[int(d_input), int(d_output)], stream_handle=stream.handle)
# Transfer predictions back from the GPU.
cuda.memcpy_dtoh_async(h_output, d_output, stream)
# Synchronize the stream
stream.synchronize()
# Return the host output.
return h_output
一个引擎可以有多个执行上下文,允许一组权重用于多个重叠的推理任务。例如,您可以使用一个引擎和每个流一个上下文来处理并行CUDA流中的图像。每个上下文都将在与引擎相同的GPU上创建。
手机扫一扫
移动阅读更方便
你可能感兴趣的文章