tensorRT学*笔记

发布时间:2021-09-19 05:10:26

tensorRT学*笔记 C++version


1.1 初始化tensorRT的方式



有两种方式初始化TensorRT:
1、创建IBuilder对象去优化网络
2、创建IRuntime对象执行一个被优化的网络


这两种方式,你都需要先实现一个logging interface(日志接口),TensorRT会通过这个接口进行报错、警告和消息提示


class Logger : public ILogger
{
void log(Severity severity, const char* msg) override
{
//不提示INFO信息,只显示警告和错误
if (severity != Severity::kINFO)
{
std::cout << msg << std::endl;
}
}
}gLogger;

注意:你可能会创建很多的IBuilder和IRuntime,但是logger是一个单例!!!




1.2 在C++中创建一个网络定义



使用tensorRT的第一步就是从你的model中创建一个tensorRT的网络定义
可以从别的深度学*框架中进行导入,现在支持:
1、Caffe(both BVLC)
2、ONNX
3、UFF(used for tensorflow)
同样也可以使用TensorRT API直接构造模型,但是需要在网络层中使用少量API定义每一层,并且实现自己导入参数机制,来导入已经训练完毕的模型参数


在以上的方式你必须明确告诉tensorRT哪些张量是输出,因为被确定为输出的张量不会因为采取加速而被builder进行优化。


输入和输出张量都需要进行命名(使用ITensor::setName())


同时推理的时候,需要为引擎提供输入和输出的buff缓存指针


还有对于tensorRT网络定义很重要的一个方面,就是包含指向模型权重的指针,它会被builder拷贝到优化引擎里


注意:如果网络定义是从语法中创建的,解析器占用权重的内存,因此解析器在builder运行前都不能被删除




1.3 在C++使用解析器导入一个模型



使用C++解析器导入你需要遵循以下的步骤:
1、创建TensorRT的builder和network
2、为特殊的格式创建TensorRT的解析器
3、使用解析器解析导入的模型并填充网络


注意:builder必须在network之前创建,因为builder是network的工厂;不同的解析器有不同的机制来标记网络输出。



1.3.1 导入caffe模型



//1、创建builder和network
IBuilder* builder = createInferBuilder(gLogger);
INetworkDefinition* network = builder->createNetwork();
//2、创建caffe的解析器
ICaffeParser* parser = createCaffeParser();
//3、使用解析器导入模型
const IBlobNameToTensor* blobNameToTensor = parser->parse("deploy_file" ,"modelFile", *network, DataType::kFLOAT);
//4、指定模型的输出
for (auto& s : outputs)
network->markOutput(*blobNameToTensor->find(s.c_str()));

注意:
最后的参数表示解析器会生成一个32位浮点数的网络,使用DataType::kHALF表示会生成16位浮点数的模型网络(原文如下:The final argument instructs the parser to generate a network whose weights are 32-bit floats. Using DataType::kHALF would generate a model with 16-bit weights instead)


除了填充网络定义之外,解析器返回一个字典,该字典从Caffe blob名称映射到TensorRT张量,与Caffe不同的是,TensorRT网络定义不存在in-place操作的概念。当一个Caffe模型使用一个in-place操作时,字典中返回的TensorRT张量对应于最后一个写入的blob。举个例子,如果一个卷积写进一个blob后面跟着一个in-place的ReLU,这个blob的名字会映射到TensorRT张量这是ReLU的输出



1.3.2 使用UFF导入tensorflow模型



和caffe一样4个步骤:


//1、创建builder和network
IBuilder* builder = createInferBuilder(gLogger);
INetworkDefinition* network = builder->createNetwork();
//2、创建Uff的解析器
IUFFParser* parser = createUffParser();
//3、指定模型输入和输出
parser->registerInput("Input_0", DimsCHW(1, 28, 28), UffInputOrder::kNCHW);
parser->registerOutput("Binary_3");
//4、使用解析器导入模型
parser->parse(uffFile, *network, nvinfer1::DataType::kFLOAT);

ONNX模型导入就不做介绍了,基本流程一样



1.4 创建一个Network



这一节主要是介绍怎么使用C++API自己构造一个网络


//1、同样创造一个builder和netword
IBuilder* builder = createInferBuilder(gLogger);
INetworkDefinition* network = builder->createNetwork();
//2、为network添加输入层,带上输入的维度,一个network可以有多个输入,尽管例子中只有一个
auto data = network->addInput(INPUT_BLOB_NAME, dt, Dims3{1, INPUT_H,INPUT_W});
//3、添加一个卷积层
layerName->getOutput(0)
auto conv1 = network->addConvolution(*data->getOutput(0), 20, DimsHW{5, 5},weightMap["conv1filter"], weightMap["conv1bias"]);
conv1->setStride(DimsHW{1, 1});
//4、添加池化层
auto pool1 = network->addPooling(*conv1->getOutput(0), PoolingType::kMAX,DimsHW{2, 2});
pool1->setStride(DimsHW{2, 2});
//5、添加全连接和激活函数
auto ip1 = network->addFullyConnected(*pool1->getOutput(0), 500,weightMap["ip1filter"], weightMap["ip1bias"]);
auto relu1 = network->addActivation(*ip1->getOutput(0),ActivationType::kRELU);
//6、添加SoftMax层计算最后的概率并将其设置为输出
auto prob = network->addSoftMax(*relu1->getOutput(0));
prob->getOutput(0)->setName(OUTPUT_BLOB_NAME);
network->markOutput(*prob->getOutput(0));


1.5 构建引擎



下一步是调用TensorRT builder来创建一个优化的runtime,构建器的功能之一是搜索CUDA内核的目录,以获得最快的实现,因此需要使用相同的GPU来构建优化引擎。


builder有很多属性可以去设置,这些属性可以控制网络运行的精度,以及自动调优参数。


您还可以查询建造器来找出哪些降低精度类型是被硬件原生支持的。


两个最主要的参数是maximum batch size (最大的批处理数量)和 maximum workspace size(最大的工作空间)
1、最大批处理大小指定TensorRT将优化的批处理的数量,在运行时,更小的批处理数量可能被选择
2、每层的算法通常需要临时工作空间,这个参数限制了网络的任一层的最大空间。如果没有划分足够的空间,会导致一个被给定的层无法实现


//使用builder创建引擎
builder->setMaxBatchSize(maxBatchSize);
builder->setMaxWorkspaceSize(1 << 20);
ICudaEngine* engine = builder->buildCudaEngine(*network);

当引擎被创建,TensorRT会拷贝权重



1.6 序列化模型



引擎构建需要一些时间,你可以将引擎序列化,可以减少以后运行的时间。序列化后的引擎不能移植,因为其生成是根据现在特定版本的TensorRT和GPU的。


//序列化
IHostMemory *serializedModel = engine->serialize();
// store model to disk
// <…>
serializedModel->destroy();
//反序列化
IRuntime* runtime = createInferRuntime(gLogger);
ICudaEngine* engine = runtime->deserializeCudaEngine(modelData, modelSize,nullptr);


1.7 进行推断



一旦你有了一个引擎,你就可以执行推断:


//1、创建一个上下文,主要用来存储中间值
IExecutionContext *context = engine->createExecutionContext();
//2、使用输入和输出blob名称来获得相应的输入和输出索引
int inputIndex = engine.getBindingIndex(INPUT_BLOB_NAME);
int outputIndex = engine.getBindingIndex(OUTPUT_BLOB_NAME);
//3、使用这些索引,设置一个缓冲数组,指向GPU上的输入和输出缓冲区
void* buffers[2];
buffers[inputIndex] = inputbuffer;
buffers[outputIndex] = outputBuffer;
//TensorRT的执行通常是异步的,因此将核加入队列放在CUDA流上
context.enqueue(batchSize, buffers, stream, nullptr);


1.8 内存管理



TensorRT提供了两种机制,允许应用程序对设备内存进行更多的控制


默认情况下,在创建IExecutionContext时,会分配持久设备内存来保存激活数据。


为了避免这种分配可以使用createExecutionContextWithoutDeviceMemory这个函数。然后,应用程序的职责就是调用IExecutionContext::setDeviceMemory()来提供运行网络所需的内存。可以通过ICudaEngine::getDeviceMemorySize()获取内存块的大小


此外,应用程序还可以通过实现IGpuAllocator接口,提供在构建和运行时使用的自定义分配器。一旦接口实现,调用setGpuAllocator(&allocator);在IBuilder或IRuntime接口上。所有的设备内存都将通过这个接口分配和释放



2.1 深度学*框架与TensorRT



并不支持所有的caffe和TensorFlow的操作:
1、caffe的支持操作:



? Convolution
? Pooling
? InnerProduct
? SoftMax
? ReLU, TanH, Sigmoid
? LRN
? Power
? ElementWise
? Concatenation
? Deconvolution
? BatchNormalization
? Scale
? Crop
? Reduction
? Reshape
? Permute
?Dropout



2、TensorFlow的支持操作:



? Placeholder
? Const
? Add, Sub, Mul, Div, Minimum and Maximum
?BiasAdd
? Negative, Abs, Sqrt, Rsqrt, Pow, Exp and Log
?FusedBatchNorm
? ReLU, TanH, Sigmoid
? SoftMax
? Mean
? ConcatV2
? Reshape
? Transpose
? Conv2D
? DepthwiseConv2dNative
? ConvTranspose2D
? MaxPool ? AvgPool
? Pad is supported if followed by one of these TensorFlow layers:Conv2D,DepthwiseConv2dNative, MaxPool, and AvgPool


相关文档

  • 同等责任保险公司如何赔付
  • 一年又没挣到钱说说朋友圈图片一年到头没挣到钱句子搞笑2018
  • 2020年Java实习面试总结回顾:从面试连跪到收割offer(10家大厂面经)
  • AES加密算法的数学基础
  • 打包失败,Gradle构建失败问题良心解决,看完这个一定让你轻松
  • 哪位参加过普通话考试呀有笔试没有需要注意什么呀
  • SQL优化工作, 不能太激动。记录失败的优化经历,优化从 70分钟优化到 30秒, 再到1s但还是失败了
  • 新员工转正通用申请书
  • 幼教培训学习的心得体会
  • 忍不住地要发笑用什么成语表示
  • 呼吸困难是哮喘病吗
  • 90后式30岁是什么意思
  • 一个创业公司成员的总结
  • 2020年江西导游证考试时间、考试科目及考试大纲11月14日起
  • 西瓜遭了殃还有玉米记叙文阅读原文附答案
  • 关于快开学了日记范文
  • 有关工作自我鉴定集锦9篇
  • ipad摔了一下黑屏了怎么办
  • 基于ConcurrentHashMap实现带时限的缓存
  • 加拿大留学就业形势如何
  • 我当了一次英雄作文600字
  • 数组指针 与 二维数组的区别
  • 忽闻花语散文
  • “再学习、再讨论、再调研、再落实”心得体会
  • 治愈系晚安朋友圈问候语摘录
  • 学习在IDEA中使用SpringBoot(三)Spring Boot 与日志
  • 辽宁人民我们感谢您们
  • 美丽的小树林作文
  • 2019成都工业职业技术学院各省录取分数线是多少
  • 走失在纳西文字中阅读答案
  • 猜你喜欢

  • 2019六年级下册数学教案23圆锥体积苏教版语文
  • 人教版 三年级数学 上册 同步课堂练*题作业 第6单元 多位数乘一位数 第2.2课时 笔算乘法(不连续进位)
  • 加拿大留学行李准备(一)
  • 【医院工作计划】20XX年医院护理人员工作计划
  • 关于我身边的小能人400字
  • 兼职家教的简历怎么写
  • 有哲理的伤感说说句子
  • 植物甾醇酯的研究进展
  • Mysql中查看和设置表使用的存储引擎
  • 中煤财务比率分析分析
  • 牛肉的功效与作用和营养价值
  • 东莞市润田农资有限公司企业信息报告-天眼查
  • 有关宪法日的手抄报
  • 标养室温度湿度记录
  • 2014-2015高中历史 第12课 文艺复兴巨匠的人文风采智能提升 岳麓版必修3
  • 【推荐下载】六一儿童节黑板报内容word版本 (1页)
  • 沙市区仙果林精品水果销售中心(企业信用报告)- 天眼查
  • 初一作文写人:做人不能太贪心
  • 科学实验室使用管理制度
  • 厨房美食菜谱:香辣口蘑煲的做法
  • 汽车维修技术工作总结报告(二篇)
  • 人大法硕考研需要使用哪些参考书
  • 酒店员工仪表培训和基本礼仪培训
  • 行政秘书年终总结范文
  • 办公室5S实施方法培训
  • 霸王花鸡脚猪骨汤【精品做菜教程】
  • 初中八年级下册语文部编版《大自然的语言》课件
  • 国内电商现状_图文.ppt 11页PPT文档
  • 兴化市顾庄学区2016年秋学期九年级物理期末试卷及答案
  • 麦玲玲2013蛇年运程
  • 有哲理的话语人生感悟短句
  • 海阔天空弹奏教学钢琴谱
  • 《科学研究方法与学术论文写作》作业
  • 教师个人校本培训总结范文汇总6篇
  • 少儿舞蹈游子吟
  • 监测监控系统维护保养及检修制度
  • 2019秋华师大版九年级数学上册课件:第21章 21.2.4 一元二次方程的根与系数的关系
  • 福州市融和纸品有限公司(企业信用报告)- 天眼查
  • 《圆的周长》探究型教学设计 常州市丁堰中心小学 刘健
  • 关于旅游精选作文4篇
  • 教你^_^打领带
  • 初中毕业生学业考试英语模拟题(广州广东)
  • 电脑版