tensorrt加速推理整到一半還沒整明白。因為另一個項目緊急,寫了個簡單的進展匯報給同事,由同事接着做下去。等以后有空了完全弄明白tensorrt,再回來修改這篇文章。
TensorRT當前進展
(本文前4節為已做工作總結,可直接跳過,看“5 當前進展”,並開展下一步工作!)
1 TensorRT的基本功能
TensorRT是NVIDIA開發的一個可以在NVIDIA旗下的GPU上進行高性能推理的C++庫,是一個高性能推理優化引擎。
其核心庫是使用c++去加速NVIDIA生產的GPU,具有python API。它可以加速的框架模型有:tensorflow、Caffe、Pytorch、MXNet等。
它可以吸收在這些流行框架上受過訓練的神經網絡,優化神經網絡計算,生成一個輕量級的運行時引擎,然后它將在這些GPU平台上最大限度地提高吞吐量、延遲和性能。
1.1 工作原理
主要的優化模型工作集中在:
1)分析圖結構中沒有用到的輸出layer,對網絡層進行合並。
2)融合卷積操作、bias和ReLU操作。
3)把有相似參數的操作和有相同輸入源的tensor聚合。
4)通過直接將layer的輸出對應到最終的destination,這樣融合了級聯層。
1.2 官方指導
https://docs.nvidia.com/deeplearning/sdk/tensorrt-developer-guide/。
2 需要的庫
2.1 tensorflow、tensorrt
已安裝
2.2 pycuda
已安裝
2.3 uff、graphsurgeon
已安裝
3 准備工作
3.1 pb文件
以keras訓練出的yolov3_tiny.h5為例,在Nano中/Documents/1tensorrt_pb_uff文件夾下,運行first_step_freeze_model.py進行轉換:
python3 first_step_freeze_model.py --model=“yolov3_tiny.h5” —output=“yolov3_tiny.pb”
(這個好像只能對yolo_tiny轉.pb文件,yolo不行)
3.2 pb文件轉uff文件
使用自帶的convert_to_uff工具轉uff文件:
python3 /usr/lib/python3.6/dist-packages/uff/bin/convert_to_uff.py --input-file yolov3_tiny.pb
4 tensorrt基本流程
4.1 導入模型
4.1.1創造builder和network。
IBuilder* builder=createInferBuilder(gLogger);
nvinfer1::INetworkDefinition* network=builder->createNetwork();
4.1.2創造parse
使用parse導入模型填充網絡。
parser->parse(args);
4.1.3導入caffe和tensorflow、ONNX模型,可以參考官網的指導。
https://docs.nvidia.com/deeplearning/sdk/tensorrt-developer-guide/index.html#create_network_c
4.1.4創造engine
有了網絡結構后可以創造engine了。builder有兩個重要的屬性,分別是batchsize和worksize。
2 使用builder object建立引擎。
1、builder->setMaxBatchSize(maxBatchSize);
2、builder->setMaxWorkspaceSize(1 << 20);
3、ICudaEngine* engine = builder->buildCudaEngine(*network);
釋放空間:
engine->destroy();
network->destroy();
builder->destroy();
4.3序列化模型
序列化和反序列化是可以自由選擇的,使用序列化模型的主要原因是使用讀取模型定義網絡再創造engine是很耗時的操作,序列化后可以避免每次 都需要重新建立engine。
當engine建立了之后,可以將其序列化保存下來為以后使用。
注意:序列化的模型在不同的模型和tensorRT的版本之間是不能夠相互使用的。
序列化:
IHostMemory *serializedModel=engine->serialize();
serializedModel->destroy();
反序列化:
IRuntime* runtime = createInferRuntime(glogger);
ICudaEngine* engine = runtime->deserializeCudaEngin(modelData,modelSize, nullptr)
4.3進行預測
1、IExecutionContext *context = engine->createExecutionContext();
2、int inputIndex = engine.getBindingIndex(INPUT_BLOB_NAME);
int outputIndex = engine.getBindingIndex(OUTPUT_BLOB_NAME);
3、void* buffers[2];
buffers[inputIndex] = inputbuffer;
buffers[outputIndex] = outputBuffer;
4、context.enqueue(batchSize, buffers, stream, nullptr);
5 當前進展
5.1 tensorRT_mnist_example-master代碼分析
代碼github地址為:https://github.com/junyu0704/tensorRT_mnist_example。運行前需要編譯(此步已完成,不需要再做)。
以下為代碼簡介。
5.1.1 mnist.py
訓練mnist,權重文件保存為mnist.pb。
5.1.2 mnist_pred.py
對mnist.py中訓練出的mnist.pb,進行tensorrt優化推理,然后再進行預測。
5.2 mnist_pred.py代碼分析
優化推理主要有三步:第一步,find_data查找數據,事實上就是一個參數解析函數;第二步,build_engine創建引擎;第三步,inference推理。
5.2.1 find_data查找數據
事實上就是一個參數解析函數,定義parser解析器。
5.2.2 build_engine創建引擎
創建推理引擎,對網絡進行推理解析
with trt.Builder(TRT_LOGGER) as builder, builder.create_network() as network, trt.UffParser() as parser:
5.2.3 inference推理
推理共5行代碼。
# 將數據移動到GPU
[cuda.memcpy_htod_async(inp.device, inp.host, stream) for inp in inputs]
# 執行inference.
context.execute_async(batch_size=batch_size,bindings=bindings, stream_handle=stream.handle)
# 將結果從 GPU寫回到host端
[cuda.memcpy_dtoh_async(out.host, out.device, stream) for out in outputs]
# 同步stream
stream.synchronize()
# 返回host端的輸出結果
return [out.host for out in outputs]
