Tensorrt笔记(一) C++ API

这个系列需要注意可读性,便于以后迭代阅读。

框架必须明晰

参考:Developer Guide :: NVIDIA Deep Learning TensorRT Documentation

1 须知

  • 接口类以字母"I"作为前缀,例如ILogger、IBuilder等等;
  • TensorRT在第一次调用CUDA时会自动创建一个CUDA上下文,所以,首次调用TensorRT之前自己创建和配置CUDA上下文。
  • 为了说明对象的生命周期,本章代码不使用智能指针;然而,建议在使用TensorRT接口时使用智能指针。

2 构建阶段

ILogger

class Logger : public ILogger           
{
    void log(Severity severity, const char* msg) noexcept override
    {
        // suppress info-level messages
        if (severity <= Severity::kWARNING)
            std::cout << msg << std::endl;
    }
} logger;

// 创建推理引擎
IBuilder* builder = createInferBuilder(logger);

2.1 创建网络定义

网络创建选项是通过组合多个标志位(flags)进行“或”运算(OR-d)来指定的。

  • ONNX:kEXPLICIT_BATCH
  • 是否使用强类型:NetworkDefinitionCreationFlag::kSTRONGLY_TYPED
INetworkDefinition* network = builder->createNetworkV2(flag);

2.2 导入ONNX文件

ONNX解析器API位于文件NvOnnxParser.h中,解析器位于nvonnxparser C++命名空间中。

#include “NvOnnxParser.h”

using namespace nvonnxparser;

创建ONNX parser并读取模型文件

IParser* parser = createParser(*network, logger);

parser->parseFromFile(modelFile, 
    static_cast<int32_t>(ILogger::Severity::kWARNING));
for (int32_t i = 0; i < parser->getNbErrors(); ++i)
{
std::cout << parser->getError(i)->desc() << std::endl;
}

它包含指向模型权重的指针,这些权重会被构建器复制到优化后的引擎中。由于网络是使用解析器创建的,所以解析器拥有权重所占用的内存,因此在构建器运行完成之前,不应该删除解析器对象。

2.3 构造引擎

创建构造参数。

IBuilderConfig* config = builder->createBuilderConfig();

可以设置:最大工作区域尺寸,限制了任何层可用的最大工作空间大小。一般为给定设备的全局内存大小。除非多个引擎一起构建

config->setMemoryPoolLimit(MemoryPoolType::kWORKSPACE, 1U << 20);

另一个重要的考虑因素是CUDA后端实现的最大共享内存分配。在需要与其他应用程序共存的场景中,这个分配变得尤为关键。

config->setMemoryPoolLimit(MemoryPoolType::kTACTIC_SHARED_MEMORY, 48 << 10);

开始构造引擎

IHostMemory* serializedModel = builder->buildSerializedNetwork(*network, *config);

构造完了,保存引擎,删掉不用的

delete parser;
delete network;
delete config;
delete builder;

delete serializedModel

至此,转化完毕,接下来推理。

2.4 逆序列化一个引擎

runtime时间,可以吃logger参数,也可以把缓存的model读入

IRuntime* runtime = createInferRuntime(logger);

ICudaEngine* engine = 
  runtime->deserializeCudaEngine(modelData, modelSize);

2.5 进行推理

要执行推理,你必须管理中间激活的额外状态

IExecutionContext *context = engine->createExecutionContext();

一个引擎有多个执行上下文,一组权重进行多个推理任务。(例外是使用动态形状时,除非指定了预览功能kPROFILE_SHARING_0806。)

必须为输入和输出传递TensorRT缓冲区,TensorRT要求你通过调用setTensorAddress来指定,这个函数需要传入张量的名称和缓冲区的地址。你可以使用你为输入和输出张量提供的名称来查询引擎。

context->setTensorAddress(INPUT_NAME, inputBuffer);
context->setTensorAddress(OUTPUT_NAME, outputBuffer);

动态尺寸就得指定输入尺寸

context->setInputShape(INPUT_NAME, inputDims);

用流开始推理

context->enqueueV3(stream);

可能同步的情况:

  1. 数据依赖的形状
  2. DLA(深度学习加速器)的使用
  3. 循环
  4. 同步插件
  • 39
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值