TensorRT量化-FP16和INT8

FP16

  • FP16 :FP32 是指 Full Precise Float 32 ,FP 16 就是 float 16。更省內存空間,更節約推理時間。

  • Half2Mode :tensorRT 的一種執行模式(execution mode ),這種模式下 圖片上相鄰區域的 tensor 是 以16位 交叉存儲的方式 存在的。而且在 batchsize 大於 1的情況下,這種模式的運行速度是最快的。(Half2Mode is an execution mode where internal tensors interleave 16-bits from
    adjacent pairs of images, and is the fastest mode of operation for batch sizes greater
    than one.

    這是計算機組成原理中涉及到存儲方式的選擇,不是很懂。大概是下圖這樣的:

    以下分別是 2D和3D情況:
    在這裏插入圖片描述
    在這裏插入圖片描述

    參考這個 順序存儲和交叉存儲 ,這樣做可以提升存儲器帶寬。更多詳細內容參考文末參考資料。

2 具體做法

2.1 配置 builder

TensorRT3.0的官方文檔上說,如果只是使用 float 16 的數據精度代替 float-32 , 實際上並不會有多大的性能提升。真正提升性能的是 half2mode ,也就是上述使用了交叉存存儲方式的模式。

如何使用half2mode ?

  • 首先 使用float 16 精度的數據 來初始化 network 對象,主要做法就是 在調用NvCaffeParser 工具解析 caffe模型時,使用 DataType::kHALF 參數,如下:

    const IBlobNameToTensor *blobNameToTensor = 
    parser->parse(locateFile(deployFile).c_str(), 
    locateFile(modelFile).c_str(), 			
    *network, 				 
    DataType::kHALF);
    
  • 配置builder 使用 half2mode ,這個很簡單,就一個語句就完成了:

    builder->setHalf2Mode(true);
    

int8

定義網絡時,注意這個地方傳進去的dataType,如果使用FP16 inference 則傳進去的是FP16,也就是kHALF;但如果是使用INT8 inference的話,這個地方傳進去的是kFLOAT,也就是 FP32,這是因爲INT8 需要先用FP32的精度來確定轉換系數,TensorRT自己會在內部轉換成INT8。

const IBlobNameToTensor* blobNameToTensor =    
parser->parse(locateFile(deployFile).c_str(),  
locateFile(modelFile).c_str(),   
*network,                  
DataType::kFLOAT);

這個看起來就跟使用FP32是一樣的流程,INT8 MODE inference的輸入和輸出都是 FP32的。

配置build使用int8,

//設置int8模式
builder->setInt8Mode(dataType == DataType::kINT8);
//s設置int8標定
builder->setInt8Calibrator(calibrator);
//brief: Build a CUDA engine from a network definition.
//實際過程在buildCudaEngine時完成
engine = builder->buildCudaEngine(*network);

int8標定
官方文檔關於量化的敘述:

INT8 calibration provides an alternative to generate per activation tensor the dynamic range. This methods can be categorized as post training technique to generate the appropriate quantization scale. The process of determining these scale factors is called calibration, and requires the application to pass batches of representative input for the network (typically batches from the training set.) Experiments indicate that about 500 images is sufficient for calibrating ImageNet classification networks.

int8量化的調用接口爲 IInt8EntropyCalibrator

當build int8 engine時,執行以下步驟:
Builds a 32-bit engine, runs it on the calibration set, and records a histogram for each tensor of the distribution of activation values.
Builds a calibration table from the histograms.
Builds the INT8 engine from the calibration table and the network definition.

  • build一個32位engine,在標定集中運行,記錄每一個tensor的激活值分佈的直方圖
  • 根據直方圖創建一個標定表
  • 根據標定表和網絡定義生成int8 engine

標定表可以緩存。當多次build同一個網絡時,標定表緩存是非常必要的。當第一次build時,生成標定表,之後build時,直接讀取標定表,而不用再次標定。

build中配置int8標定
builder->setInt8Calibrator(calibrator);

使用 writeCalibrationCache() and readCalibrationCache() 函數緩存標定表。

參考

TensorRT(4)-Profiling and 16-bit:Inference https://arleyzhang.github.io/articles/fda11be6/

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章