原创作品,转载时请务必以超链接形式标明文章原始出处: http://www.dapalm.com/?p=199,作者:大数据,怕了么?
本手册为TensorRT 4.0.1.6 GA版英文手册翻译而来,博主英文水平一般般,主要作为备忘所用,分享出来以供更多开发者使用。TensorRT Developer Guide手册一共分为四个章节,主要内容在第二、三章,看懂这两章,写代码够用了。第一章为TensorRT综述,就是自吹有多牛逼。第四章为示例,介绍demo的代码结构及功能。开篇是目录,前三章每章为两到三篇,最后第四章示例,会拆分几个关键示例进行详细说明。
第二章,分别介绍了C++和Python两种语言接口下,TensorRT如何实现推理。下一篇文章再介绍Python接口如何实现推理。
第二章 TensorRT任务
本章主要内容是用户能使用TensorRT实现的目标和任务。假设已有训练好的模型,本章将覆盖使用TensorRT的必要步骤:
‣导入模型创建TensorRT网络定义
‣通过TensorRT网络定义调用TensorRT构建器来创建优化运行时引擎
‣通过序列化和反序列化引擎实现快速重新创建运行时引擎
‣喂数据到引擎并执行推理
在实际使用中更重要的主题是:
‣使用自定义层扩展TensorRT功能
‣混合精度
2.1 C++初始化TensorRT
TensorRT的两种初始化方法:
‣创建IBuilder对象去优化网络(创建后可生成序列化文件)
‣创建IRuntime对象去执行优化网络(从序列化文件导入)
在任何一种情况下,你都必须实现一个日志记录接口,TensorRT通过该接口报告错误,警告和信息性消息。 以下代码显示了如何实现日志记录接口。 在这种用例中,我们已经抑制了信息性消息,只报告警告和错误消息。
class Logger : public ILogger
{
void log(Severity severity, const char* msg) override
{
//不打印信息性消息
if (severity != Severity::kINFO)
std::cout << msg << std::endl;
}
} gLogger;
日志记录接口可用于创建多个运行时和构建器实例,但是日志记录接口是一个单件
(整个应用程序中只有一个类实例且这个实例所占资源在整个应用程序中是共享的),所以你必须为每个对象使用同一个日志记录实例。
创建构建器或运行时时,将创建线程关联的GPU上下文。 虽然默认上下文如果不存在,会自动创建它,但还是建议创建构建器或运行时实例之前,创建和配置CUDA上下文。
2.2 C++创建网络定义
使用TensorRT进行推理的第一步是导入你的模型并创建TensorRT网络。 实现此目的的最简单方法是使用TensorRT解析器库导入模型,目前支持以下格式的序列化模型:
‣Caffe
‣ONNX(Pytorch、Caffe2等)
‣UFF(TensorFlow)
另一种方法是使用TensorRT API直接定义模型。 这要求你进行少量(感觉应该是大量调用
)API调用以定义网络图中的每个层,并为模型的训练参数实现自己的导入机制。
在任何一种情况下,你都需要明确告诉TensorRT哪些张量是推理的输出。 未标记为输出的张量被认为是可由构建器优化的瞬态值。 输出张量的数量没有限制,但是将张量标记为输出可能会禁止对张量进行一些优化。 输入和输出张量必须给出名称(ITensor:: setName()
)。 在推理时,你需要为引擎提供一个指向输入和输出缓冲区的指针数组。 为了确定引擎对应的缓冲区指针顺序,你可以使用张量名称进行查询(ICudaEngine::getBindingIndex(const char* name)
)。
TensorRT网络定义的一个重要方面是它包含指向模型权重的指针,这些指针由构建器复制到优化引擎中。 如果网络是通过解析器创建的,则解析器将拥有权重内存的句柄,因此在构建器运行结束之前,不应删除解析器对