TensorRT Developer Guide

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安裝文件

image

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)絡定義吸占。

  1. Create the TensorRT builder and network.
IBuilder* builder = createInferBuilder(gLogger);
nvinfer1::INetworkDefinition* network = builder->createNetwork();
  1. 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);
  1. Build engine
ICudaEngine* engine = builder->buildCudaEngine(*network);
  1. Serialize engine
IHostMemory *serializedModel = engine->serialize();
// store model to disk
// <…>
serializedModel->destroy();

Performing Inference In C++

  1. 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();
  1. 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);
  1. 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));
  1. 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

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末悦即,一起剝皮案震驚了整個濱河市吮成,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌辜梳,老刑警劉巖粱甫,帶你破解...
    沈念sama閱讀 206,602評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異冗美,居然都是意外死亡魔种,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,442評論 2 382
  • 文/潘曉璐 我一進店門粉洼,熙熙樓的掌柜王于貴愁眉苦臉地迎上來节预,“玉大人,你說我怎么就攤上這事属韧“材猓” “怎么了?”我有些...
    開封第一講書人閱讀 152,878評論 0 344
  • 文/不壞的土叔 我叫張陵宵喂,是天一觀的道長糠赦。 經(jīng)常有香客問我,道長锅棕,這世上最難降的妖魔是什么拙泽? 我笑而不...
    開封第一講書人閱讀 55,306評論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮裸燎,結(jié)果婚禮上顾瞻,老公的妹妹穿的比我還像新娘。我一直安慰自己德绿,他們只是感情好荷荤,可當我...
    茶點故事閱讀 64,330評論 5 373
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著移稳,像睡著了一般蕴纳。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上个粱,一...
    開封第一講書人閱讀 49,071評論 1 285
  • 那天古毛,我揣著相機與錄音,去河邊找鬼都许。 笑死稻薇,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的梭稚。 我是一名探鬼主播颖低,決...
    沈念sama閱讀 38,382評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼弧烤!你這毒婦竟也來了忱屑?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,006評論 0 259
  • 序言:老撾萬榮一對情侶失蹤暇昂,失蹤者是張志新(化名)和其女友劉穎莺戒,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體急波,經(jīng)...
    沈念sama閱讀 43,512評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡从铲,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 35,965評論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了澄暮。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片名段。...
    茶點故事閱讀 38,094評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡阱扬,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出伸辟,到底是詐尸還是另有隱情麻惶,我是刑警寧澤,帶...
    沈念sama閱讀 33,732評論 4 323
  • 正文 年R本政府宣布信夫,位于F島的核電站窃蹋,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏静稻。R本人自食惡果不足惜警没,卻給世界環(huán)境...
    茶點故事閱讀 39,283評論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望振湾。 院中可真熱鬧杀迹,春花似錦、人聲如沸恰梢。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,286評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽嵌言。三九已至嗅回,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間摧茴,已是汗流浹背绵载。 一陣腳步聲響...
    開封第一講書人閱讀 31,512評論 1 262
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留苛白,地道東北人娃豹。 一個月前我還...
    沈念sama閱讀 45,536評論 2 354
  • 正文 我出身青樓,卻偏偏與公主長得像购裙,于是被迫代替她去往敵國和親懂版。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 42,828評論 2 345

推薦閱讀更多精彩內(nèi)容