TensorRT Developer Guide
Overview
NVIDIA TensorRT?是一個C ++庫艰争,可以幫助NVIDIA圖形處理器(GPU)進行高性能推理。
TensorRT通過合并張量和圖層突硝,轉(zhuǎn)換權(quán)重,選擇高效的中間數(shù)據(jù)格式,并根據(jù)圖層參數(shù)和
測量的性能從大型內(nèi)核目錄中進行選擇域慷,從而對網(wǎng)絡進行定義并對其進行優(yōu)化严就。
TensorRT包含導入方法总寻,可幫助您為TensorRT表達訓練有素的深度學習模型以優(yōu)化和運行。 它是一種優(yōu)化工具梢为,可以應用圖形優(yōu)化和圖層融合渐行,并利用各種高度優(yōu)化的內(nèi)核集合找到該模
型的最快實現(xiàn),以及可用于在推理上下文中執(zhí)行此網(wǎng)絡的運行時方法铸董。
install
c++簡易安裝
1,首先從官網(wǎng) 下載TensorRT安裝文件
2, 解壓縮文件
$ tar -xzvf TensorRT-4.0.0.3.Ubuntu-16.04.4.x86_64-gnu.cuda-9.0.cudnn7.0.tar.gz
3, 添加環(huán)境變量
$ vim ~/.bashrc
$ export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:~/TensorRT-4.0.0.3/lib
$ source ~/.bashrc
Working With TensorRT Using The C++ API
Instantiating TensorRT Objects in C++
首先殊轴,您都必須實現(xiàn)一個日志記錄接口,TensorRT通過該接口打印錯誤袒炉,警告和信息性消息旁理。
日志記錄接口可用于創(chuàng)建多個運行時和構(gòu)建器實例,但是日志記錄接口是一個單例(整個應用程序
中只有一個類實例且這個實例所占資源在整個應用程序中是共享的)我磁,所以你必須為每個對象使用
同一個日志記錄實例孽文。
class Logger : public ILogger
{
void log(Severity severity, const char* msg) override
{
// suppress info-level messages
if (severity != Severity::kINFO)
std::cout << msg << std::endl;
}
} gLogger;
Creating A Network Definition In C++
使用TensorRT進行inference的第一步是從您的模型創(chuàng)建TensorRT網(wǎng)絡。實現(xiàn)此目的的最簡單方法是使用
TensorRT解析器庫導入模型夺艰,該解析器庫支持以下格式的序列化模型:
sampleMNIST(BVLC和NVCaffe)
sampleOnnxMNIST 1.0和1.1芋哭,以及
sampleUffMNIST(用于TensorFlow)
另一種方法是使用TensorRT API直接定義模型。這要求您進行少量API調(diào)用以定義網(wǎng)絡圖中的每個層郁副,并為模型的訓練參數(shù)實現(xiàn)自己的導入機制减牺。
在任何一種情況下,您都明確需要告訴TensorRT需要哪些tensors作為inference的輸出存谎。未標記為輸出的tensors被認為是可被優(yōu)化的瞬態(tài)值拔疚。輸出tensors的數(shù)量沒有限制,但是既荚,將tensors標記為輸出可能會禁止對tensors進行一些優(yōu)化稚失。在推理時,您將為引擎提供一個指向輸入和輸出緩沖區(qū)的指針數(shù)組恰聘。
現(xiàn)在我們只討論如何基于一個caffe模型句各,導出網(wǎng)絡定義吸占。
- Create the TensorRT builder and network.
IBuilder* builder = createInferBuilder(gLogger);
nvinfer1::INetworkDefinition* network = builder->createNetwork();
- Parse caffe model to populate network, then set the outputs
std::vector<std::string> outputs{"prob"};
ICaffeParser* parser = createCaffeParser();
const IBlobNameToTensor* blobNameToTensor = parser->parse(deployFile,
modelFile,
*network,
DataType::kFLOAT);
for (auto& s : outputs)
network->markOutput(*blobNameToTensor->find(s.c_str()));
builder->setMaxBatchSize(maxBatchSize);
builder->setMaxWorkspaceSize(1 << 20);
- Build engine
ICudaEngine* engine = builder->buildCudaEngine(*network);
- Serialize engine
IHostMemory *serializedModel = engine->serialize();
// store model to disk
// <…>
serializedModel->destroy();
Performing Inference In C++
- Deserialize engine we serialized earlier
IRuntime* runtime = createInferRuntime(gLogger);
//get model from disk or hostMemory
ICudaEngine* engine = runtime->deserializeCudaEngine(trtModelStream->data(), trtModelStream->size(), nullptr);
IExecutionContext* context = engine->createExecutionContext();
- Use the input and output blob names to get the corresponding input and output index
int inputIndex = engine.getBindingIndex(INPUT_BLOB_NAME);
int outputIndex = engine.getBindingIndex(OUTPUT_BLOB_NAME);
- allocate GPU buffers
Dims3 inputDims = static_cast<Dims3&&>(engine->getBindingDimensions(inputIndex));
outputDims = static_cast<Dims3&&>(engine->getBindingDimensions(outputIndex));
size_t inputSize = batchSize * inputDims.d[0] * inputDims.d[1] * inputDims.d[2] * sizeof(float);
size_t outputSize = batchSize * outputDims.d[0] * outputDims.d[1] * outputDims.d[2] * sizeof(float);
void* buffers[2];
cudaMalloc(&buffers[inputIndex], inputSize);
cudaMalloc(&buffers[outputIndex], outputSize)
//copy dato to gpu
cudaMemcpy(buffers[inputIndex], input, batchSize * INPUT_H * INPUT_W * sizeof(float));
- do interence and get output
context->execute(batchSize, buffers);
cudaMemcpy(output.data(), buffers[outputIndex], output_size_, cudaMemcpyDeviceToHost);
請閱讀官方demo/sampleMNIST,demo路徑為TensorRT-4.0.1.6/samples/sampleMNIST
Working With Mixed Precision
混合精度是在計算方法中組合使用不同的數(shù)值精度。 TensorRT可以存儲權(quán)重和激活凿宾,并以32位浮點矾屯,16位浮點或量化的8位整數(shù)執(zhí)行層。
使用低于FP32的精度可減少內(nèi)存使用初厚,允許部署更大的網(wǎng)絡件蚕。 數(shù)據(jù)傳輸花費的時間更少,計算性能也會提高惧所,尤其是在Tensor Core支持該精度的GPU上骤坐。
默認情況下,TensorRT使用FP32推理下愈,但它也支持FP16和INT8纽绍。 在運行FP16推理時,它會自動將FP32權(quán)重轉(zhuǎn)換為FP16權(quán)重势似。
注意:指定網(wǎng)絡的精度定義應用程序的最低可接受精度拌夏。 如果對于某些特定的內(nèi)核參數(shù)集更快,或者如果不存在低精度內(nèi)核履因,則可以選擇更高精度的內(nèi)核障簿。
bool useFp16 = builder->platformHasFastFp16();
DataType modelDataType = useFp16 ? DataType::kHALF : DataType::kFLOAT; // create a 16-bit model if it's natively supported
const IBlobNameToTensor *blobNameToTensor =
parser->parse(locateFile(deployFile).c_str(), // caffe deploy file
locateFile(modelFile).c_str(), // caffe model file
*network, // network definition that the parser will populate
modelDataType);
// set up the network for paired-fp16 format if available
if(useFp16)
builder->setFp16Mode(true);
customer layer
These are the operations that are supported in a Caffe framework:
Convolution
Pooling
InnerProduct
SoftMax
ReLU, TanH, and Sigmoid
LRN
Power
ElementWise
Concatenation
Deconvolution
BatchNormalization
Scale
Crop
Reduction
Reshape
Permute
Dropout
可能存在支持的層不滿足模型的特定需求。 在這種情況下栅迄,用戶可以通過使用C++ API實現(xiàn)自定義層來擴展TensorRT功能站故。 自定義層(通常稱為插件)由應用程序?qū)崿F(xiàn)和實例化,它們必須跨越TensorRT引擎的生命周期毅舆。
要在C++中添加自定義圖層西篓,請實現(xiàn)IPluginExt類。 對于基于Caffe的網(wǎng)絡憋活,如果使用TensorRT Caffe Parser岂津,您還將實現(xiàn)nvcaffeparser1 :: IPluginFactoryExt和nvinfer1 :: IPluginFactory類。
具體流程請參考demo/samplePlugin ,路徑為/TensorRT-4.0.1.6/samples/samplePlugin