关键词

Python api构建tensorrt加速模型的步骤详解

Python API 构建 TensorRT 加速模型的步骤详解

TensorRT(TensorRT是一种高性能神经网络推理(模型推断)引擎,主要用于在生产环境中部署深度学习模型。)是NVIDIA深度学习SDK中的一部分,是一种高效的深度学习推断加速库。TensorRT 可以将深度学习推理模型构建成一个高度优化的计算图形,用于部署到不同的 NVIDIA GPU 设备上,从而实现比原始模型更快、更小、更加节能的运行效果。

Python API 是基于TensorRT C++ API的一个封装,可以极大的简化TensorRT模型构建的流程。本文将详细介绍如何利用Python API构建TensorRT模型。

步骤

TensorRT模型构建的主要流程如下:

  1. 定义网络结构
  2. 加载训练好的模型
  3. 创建推理引擎
  4. 序列化引擎
  5. 反序列化引擎

定义网络结构

定义网络结构主要是用来在TensorRT中构建计算图。TensorRT采用了Caffe的模型概念来定义网络结构。在Python API中,可以使用caffe_pb2模块中定义的网络相关类来定义网络结构。

例如,下面的代码定义了一个简单的网络结构:

import tensorrt as trt
import numpy as np
import os

# Define network
G_LOGGER = trt.infer.ConsoleLogger(trt.infer.LogSeverity.ERROR)
builder = trt.Builder(G_LOGGER)
network = builder.create_network()

data = network.add_input(name="data", dtype=trt.float32, shape=(3, 224, 224))

fc1_w = np.random.rand(4096, 25088).astype(np.float32)
fc1_b = np.random.rand(4096).astype(np.float32)
fc1_layer = network.add_fully_connected(data, 4096, fc1_w, fc1_b)
relu1_layer = network.add_activation(fc1_layer.get_output(0), trt.infer.ActivationType.RELU)

fc2_w = np.random.rand(4096, 4096).astype(np.float32)
fc2_b = np.random.rand(4096).astype(np.float32)
fc2_layer = network.add_fully_connected(relu1_layer.get_output(0), 4096, fc2_w, fc2_b)
relu2_layer = network.add_activation(fc2_layer.get_output(0), trt.infer.ActivationType.RELU)

fc3_w = np.random.rand(1000, 4096).astype(np.float32)
fc3_b = np.random.rand(1000).astype(np.float32)
fc3_layer = network.add_fully_connected(relu2_layer.get_output(0), 1000, fc3_w, fc3_b)

softmax = network.add_softmax(fc3_layer.get_output(0))
softmax.get_output(0).set_name("prob")
network.mark_output(tensor=softmax.get_output(0))

加载训练好的模型

加载训练好的模型是指将训练好的模型导入到TensorRT中。目前,TensorRT支持Caffe和UFF(Universal Framework Format)格式的模型。下面的示例中,我们将使用Caffe格式的模型(.prototxt 文件和 .caffemodel文件)。

import tensorrt as trt
import numpy as np
import os

# Define network
G_LOGGER = trt.infer.ConsoleLogger(trt.infer.LogSeverity.ERROR)
builder = trt.Builder(G_LOGGER)
network = builder.create_network()

# Load trained model
model_path = "/path/to/model"
deploy_file = os.path.join(model_path, "deploy.prototxt")
model_file = os.path.join(model_path, "model.caffemodel")

parser = trt.CaffeParser()
parser.set_plugin_factory_ext(my_plugin_factory)
blob_name_to_tensor = parser.parse(deploy_file, model_file, network, trt.DataType.FLOAT)

# Set input and output
data = blob_name_to_tensor["data"]
network.mark_input(data.name)

在上述示例中,我们使用了CaffeParser类来解析Caffe格式的模型,并将模型导入到TensorRT网络中。parse()函数的第一个参数是.prototxt文件的路径,第二个参数是.caffemodel文件的路径。在将模型导入到网络中后,我们需要定义输入和输出张量。

创建推理引擎

创建推理引擎是TensorRT模型构建的核心步骤。推理引擎是一个高度优化的计算图形,用于快速推断神经网络模型。在Python API中,可以使用ICudaEngine类来创建推理引擎。

import tensorrt as trt
import numpy as np
import os

# Define network
G_LOGGER = trt.infer.ConsoleLogger(trt.infer.LogSeverity.ERROR)
builder = trt.Builder(G_LOGGER)
network = builder.create_network()

# Load trained model
model_path = "/path/to/model"
deploy_file = os.path.join(model_path, "deploy.prototxt")
model_file = os.path.join(model_path, "model.caffemodel")

parser = trt.CaffeParser()
parser.set_plugin_factory_ext(my_plugin_factory)
blob_name_to_tensor = parser.parse(deploy_file, model_file, network, trt.DataType.FLOAT)

# Set input and output
data = blob_name_to_tensor["data"]
network.mark_input(data.name)

# Create engine
builder.max_batch_size = 16
builder.max_workspace_size = 2 << 30
engine = builder.build_cuda_engine(network)

在上述示例中,我们使用Builder类来创建推理引擎。在构建推理引擎时,我们需要指定最大批处理大小和最大的工作空间大小。

序列化引擎

序列化是将推理引擎保存到磁盘上的过程。保存后,我们可以在不需要重新构建网络的情况下重复使用推理引擎。在Python API中,可以使用ICudaEngine类的serialize()函数来序列化推理引擎。

import tensorrt as trt
import numpy as np
import os

# Define network
G_LOGGER = trt.infer.ConsoleLogger(trt.infer.LogSeverity.ERROR)
builder = trt.Builder(G_LOGGER)
network = builder.create_network()

# Load trained model
model_path = "/path/to/model"
deploy_file = os.path.join(model_path, "deploy.prototxt")
model_file = os.path.join(model_path, "model.caffemodel")

parser = trt.CaffeParser()
parser.set_plugin_factory_ext(my_plugin_factory)
blob_name_to_tensor = parser.parse(deploy_file, model_file, network, trt.DataType.FLOAT)

# Set input and output
data = blob_name_to_tensor["data"]
network.mark_input(data.name)

# Create engine
builder.max_batch_size = 16
builder.max_workspace_size = 2 << 30
engine = builder.build_cuda_engine(network)

# Serialize engine
engine_path = "/path/to/engine"
serialized_engine = engine.serialize()
f = open(engine_path, "wb")
f.write(serialized_engine)
f.close()

在上述示例中,我们将序列化后的推理引擎保存到了/engine目录下。

反序列化引擎

反序列化是将已序列化的推理引擎重新构建成推理引擎对象的过程。在Python API中,可以使用ICudaEngine类的deserialize()函数来反序列化推理引擎。

import tensorrt as trt

# Deserialize engine
engine_path = "/path/to/engine"
f = open(engine_path, "rb")
serialized_engine = f.read()
f.close()

runtime = trt.infer.create_infer_runtime(G_LOGGER)
engine = runtime.deserialize_cuda_engine(serialized_engine)

在上述示例中,我们使用反序列化函数deserialize_cuda_engine()来反序列化推理引擎。

示例

以下是一个简单的示例,演示如何使用TensorRT Python API构建一个简单的卷积神经网络模型。这个模型包含一个卷积层、一个池化层和一个全连接层,用于对MNIST手写数字进行识别。

import tensorrt as trt
import numpy as np

G_LOGGER = trt.infer.ConsoleLogger(trt.infer.LogSeverity.ERROR)

def add_conv_layer(network, input, out_channels, kernel_size):
    conv_w = np.ones((out_channels, kernel_size, kernel_size)).astype(np.float32)
    conv_b = np.zeros((out_channels,)).astype(np.float32)
    conv_layer = network.add_convolution(input, out_channels, (kernel_size, kernel_size), conv_w, conv_b)
    return conv_layer

def add_pool_layer(network, input, pool_type, window_size):
    pool_layer = network.add_pooling(input, pool_type, (window_size, window_size))
    return pool_layer

def add_fc_layer(network, input, out_features):
    fc_w = np.ones((input.get_output(0).shape[-1], out_features)).astype(np.float32)
    fc_b = np.zeros((out_features,)).astype(np.float32)
    fc_layer = network.add_fully_connected(input, out_features, fc_w, fc_b)
    return fc_layer

def build_network():
    builder = trt.Builder(G_LOGGER)
    network = builder.create_network()

    input_tensor = network.add_input(name="input", dtype=trt.float32, shape=(1, 28, 28))
    conv_layer = add_conv_layer(network, input_tensor, out_channels=32, kernel_size=5)
    pool_layer = add_pool_layer(network, conv_layer.get_output(0), trt.PoolingType.AVERAGE, 2)
    relu_layer = network.add_activation(pool_layer.get_output(0), trt.infer.ActivationType.RELU)
    fc_layer = add_fc_layer(network, relu_layer.get_output(0), out_features=10)
    softmax_layer = network.add_softmax(fc_layer.get_output(0))

    output_tensor = softmax_layer.get_output(0)
    output_tensor.set_name("output")
    network.mark_output(output_tensor)

    return builder, network

def build_engine():
    builder, network = build_network()
    builder.max_batch_size = 1
    builder.max_workspace_size = 2 << 30
    engine = builder.build_cuda_engine(network)
    return engine

def main():
    engine = build_engine()

    runtime = trt.infer.create_infer_runtime(G_LOGGER)
    context = engine.create_execution_context()

    # Generate random input
    input_data = np.random.rand(1, 28, 28).astype(np.float32)

    # Allocate device memory
    input_shape = engine.get_binding_shape(0)
    input_size = trt.volume(input_shape) * engine.max_batch_size * np.dtype(np.float32).itemsize
    d_input = cuda.mem_alloc(input_size)

    # Copy input data to device
    cuda.memcpy_htod(d_input, input_data)

    # Allocate output memory
    output_shape = engine.get_binding_shape(1)
    output_size = trt.volume(output_shape) * engine.max_batch_size * np.dtype(np.float32).itemsize
    d_output = cuda.mem_alloc(output_size)

    # Run inference
    bindings = [int(d_input), int(d_output)]
    context.execute_async_v2(bindings=bindings)

    # Copy output data from device
    output_data = np.empty_like(output_data)
    cuda.memcpy_dtoh(output_data, d_output)

    # Print output
    print(output_data)

if __name__ == "__main__":
    main()

在上述示例中,我们构建了一个简单的卷积神经网络模型,用于对MNIST手写数字进行识别。模型中包含一个卷积层、一个池化层和一个全连接层。我们使用Builder类来构建引擎,使用create_execution_context()函数来创建执行上下文,使用execute_async_v2()函数来运行推断,最后从设备上复制输出数据到主机并打印。

总结

在本文中,我们详细介绍了如何使用TensorRT Python API构建一个模型,包括定义网络结构、加载训练好的模型、创建推理引擎、序列化引擎和反序列化引擎等步骤。我们还提供了一个简单的示例,演示了如何使用TensorRT Python API构建一个简单的卷积神经网络模型。

本文链接:http://task.lmcjl.com/news/16799.html

展开阅读全文