TensorRT
cuda
deployment
YOLOv7
Edge AI
Nvidia
Jetson
Pytorch > ONNX > TensorRT(include NMS)
.trt
and .pt
are averaged over a 1-minute video.engine
are tested with /usr/src/tensorrt/bin/trtexec --loadEngine=model.engine --verbose
(trtexec FPS)size
: 640model | NMS | batch tested |
precision | FPS | speedup | mAP |
---|---|---|---|---|---|---|
yolov7-tiny.pt | - | 1 | fp32 | 24.0 | baseline | 38.7% |
yolov7-tiny.trt | included | 1 | fp16 | 145.5 | 6.1x | to do |
yolov7-tiny.engine | - | 1 | fp16 | 166.8 | 7.0x | to do |
yolov7-tiny_qat.engine* | - | 1 | int8 | 183.1 | 7.6x | to do |
model | NMS | batch tested |
precision | FPS | speedup | mAP |
---|---|---|---|---|---|---|
yolov7.pt | - | 1 | fp32 | 14.8 | baseline | 51.4% |
yolov7.trt | included | 1 | fp16 | 40.2 | 2.7x | 51.2% |
yolov7.engine | - | 1 | fp16 | 40.8 | 2.7x | 51.2% |
yolov7_qat.engine* | - | 1 | int8 | 57.8 | 3.9x | 51.1% |
* qat表Quantization-aware training,見Model Quantization Note 模型量化筆記
測試環境:
Module: NVIDIA Jetson AGX Xavier (32 GB ram)
Python: 3.8.10
Pytorch: 1.12.0a0+2c916ef.nv22.3
Libraries
CUDA: 11.4.315
cuDNN: 8.6.0.166
TensorRT: 8.5.2
L4T: 35.2.1
Jetpack: 5.1
從系統角度分析部署過程中的優化加速方案,可分為模型優化與系統優化。本文以YOLOv7為例,記錄部署流程中,系統優化/推理引擎加速操作部分
(source:2022/02。Law-Yao。深度学习模型压缩与优化加速(Model Compression and Acceleration Overview))
根據官網TensorRT的運作流程包含:
將模型轉換為ONNX或TensorRT檔案有以下好處:
然而,將模型轉換為ONNX或TensorRT檔案也有一些缺點:
TensorRT缺點補充:
以YOLOv7為例,進行模型轉換。
使用Open Neural Network Exchange (ONNX)中轉
不使用 ONNX 格式中轉(待測試)
優缺點比較
路徑 | 優點 | 缺點 |
---|---|---|
Pytorch > TensorRT | 可以在不同平台之間實現模型的無縫轉換,例如在使用不同的硬件加速器時,如在NVidia GPU上使用TensorRT,在Intel處理器上使用OpenVINO,在Windows上使用DirectML,這樣就可以充分利用各種硬件的優勢。此外,ONNX Runtime提供了一系列的生產級優化和測試,並進行持續改進,使模型轉換更加高效。 | 由於存在ONNX的中間步驟,整個轉換路徑相比較於直接使用TensorRT而言,可能會增加一些額外的轉換時間和性能損失 |
Pytorch > ONNX >TensorRT | 可以避免額外的轉換時間和性能損失。此外,TensorRT本身具有很好的性能優化能力,可以大大加速深度學習模型的推理過程 | 由於直接使用TensorRT進行轉換,可能會存在一些平台兼容性的問題,不同平台的支持程度可能不同 |
另外要注意的是,TensorRT是針對特定硬體平台與環境做優化,所以在轉換.trt檔(TensorRT Engine)時,必須在欲部署的環境中進行。相對,PyTorch > ONNX則不限於特定平台
The generated plan files are not portable across platforms or TensorRT versions. Plans are specific to the exact GPU model they were built on (in addition to platforms and the TensorRT version) and must be re-targeted to the specific GPU in case you want to run them on a different GPU
TensorRT学习笔记–序列化(Serialize)和反序列化(Deserialize)
序列化和反序列化的概念
將某個對象的信息轉化成可以存儲或者傳輸的信息,這個過程稱為序列化;反序列化是序列化的相反過程,將信息還原為序列化前的狀態;
- 在Pytorch中,當序列化為torch.save()時,則反序列化可以是torch.load();
- 在Tensor RT中,為了能夠在interface的時候不需要重覆編譯engine,傾向於將模型序列化成一個能夠永久保存的engine;當 需要interface的時候,只需要通過簡單的反序列化就能夠快速加載序列化保存好的模型engine,節省部署開發的時間。
model.pt → model.onnx → model.trt
→ model.engine
.engine
與 model.trt
兩種
.engine
格式
model.trt
格式
import tensorrt as trt
import pycuda.autoinit
import pycuda.driver as cuda
trtexec
指令進行模型轉換trtexec
是NVIDIA TensorRT的命令行工具,用於執行和測試TensorRT推理引擎。TensorRT是NVIDIA的高性能深度學習推理優化庫,可用於在GPU上加速深度學習模型的推理過程。簡單的ONNX to TensorRT engine範例,以yolov7-tiny
為例
# use trtexec to convert ONNX to TensorRT engine
/usr/src/tensorrt/bin/trtexec --onnx=yolov7-tiny.onnx --saveEngine=yolov7-tiny-nms.trt --fp16
#install onnx-simplifier not listed in general yolov7 requirements.txt
pip3 install onnx-simplifier
# Pytorch Yolov7 -> ONNX with grid, EfficientNMS plugin and dynamic batch size
python export.py --weights ./yolov7.pt --grid --end2end --dynamic-batch --simplify --topk-all 100 --iou-thres 0.65 --conf-thres 0.35 --img-size 640 640
# ONNX -> TensorRT with trtexec and docker
docker run -it --rm --gpus=all nvcr.io/nvidia/tensorrt:22.06-py3
# Copy onnx -> container: docker cp yolov7.onnx <container-id>:/workspace/
# Export with FP16 precision, min batch 1, opt batch 8 and max batch 8
./tensorrt/bin/trtexec --onnx=yolov7.onnx --minShapes=images:1x3x640x640 --optShapes=images:8x3x640x640 --maxShapes=images:8x3x640x640 --fp16 --workspace=4096 --saveEngine=yolov7-fp16-1x8x8.engine --timingCacheFile=timing.cache
# Test engine
./tensorrt/bin/trtexec --loadEngine=yolov7-fp16-1x8x8.engine
# Copy engine -> host: docker cp <container-id>:/workspace/yolov7-fp16-1x8x8.engine .
--batch=
參數指定批次大小) [I] === Performance summary ===
[I] Throughput: 73.4985 qps
[I] Latency: min = 14.8578 ms, max = 15.8344 ms, mean = 15.07 ms, median = 15.0422 ms, percentile(99%) = 15.7443 ms
我的NVDIA Jetson部署環境
Platform
Machine: aarch64
Linux Ubuntu 20.04 focal
Release: 5.10.104-tegra
Python: 3.8.10
pytorch: 1.12.0a0+2c916ef.nv22.3
Libraries
CUDA: 11.4.315
cuDNN: 8.6.0.166
TensorRT: 5.1
VPI: 2.2.4
Vulkan: 1.3.204
OpenCV: 4.5.4 with CUDA: NO
Hardware
Model: Jetson-AGX
Module: NVIDIA Jetson AGX Xavier (32 GB ram)
L4T: 35.2.1
Jetpack: 5.1
ps: 使用 dpkg -l |grep -i tensor
檢視,我的TensoRT版本應該是8.5.2-1,jtop
可能誤抓到nvidia-tensorrt
的資訊
ii nvidia-tensorrt 5.1-b147 arm64 NVIDIA TensorRT Meta Package
ii python3-libnvinfer 8.5.2-1+cuda11.4 arm64 Python 3 bindings for TensorRT
ii tensorrt 8.5.2.2-1+cuda11.4 arm64 Meta package for TensorRT
ii tensorrt-libs 8.5.2.2-1+cuda11.4 arm64 Meta package for TensorRT runtime libraries
$ sudo apt update
$ sudo apt list --upgradable
$ sudo apt upgrade
$ sudo apt install nvidia-jetpack
參考資訊:How to use tensorrt in python of AGX Xavier JetPack5.1
目前Linux環境系統安裝的是TensorRT: 5.1與CUDA: 11.4.315,Python的TensorRT套件需要與系統環境一致,使用nvidia-pyindex
package 會自動幫你根據系統資訊抓取適合版本
pip install --upgrade setuptools pip --user
pip install nvidia-pyindex
pip install onnx_graphsurgeon
pip install onnx
pip install onnxruntime
pip install --ignore-installed PyYAML
pip install --upgrade nvidia-tensorrt
pip install pycuda
pip install protobuf<4.21.3
pip install onnxruntime
pip install onnx>=1.9.0
pip install onnx-simplifier>=0.3.6 --user
參考https://github.com/WongKinYiu/yolov7/YOLOv7TRT.ipynb
wget https://github.com/WongKinYiu/yolov7/releases/download/v0.1/yolov7-tiny.pt
python export.py --weights yolov7-tiny.pt --grid --include-nms
git clone https://github.com/Linaom1214/tensorrt-python.git
python ./tensorrt-python/export.py -o yolov7-tiny.onnx -e yolov7-tiny-nms.trt -p fp16
# Or use trtexec to convert ONNX to TensorRT engine
# /usr/src/tensorrt/bin/trtexec --onnx=yolov7-tiny.onnx \
--saveEngine=yolov7-tiny-nms.trt --fp16
# Download YOLOv7 code
git clone https://github.com/WongKinYiu/yolov7
cd yolov7
! Download trained weights
wget https://github.com/WongKinYiu/yolov7/releases/download/v0.1/yolov7-tiny.pt
--include-nms
--end2end
進行同樣操作
python3 export.py --weights ./yolov7-tiny.pt --grid --simplify --include-nms
cd ../
git clone https://github.com/Linaom1214/tensorrt-python.git
cd tensorrt-python
fp16
指定float16的精度python3 export.py -o /content/yolov7/yolov7-tiny.onnx -e ./yolov7-tiny-nms.trt -p fp16
或直接在terminal使用trtexec
指令
# Or use trtexec to convert ONNX to TensorRT engine
/usr/src/tensorrt/bin/trtexec --onnx=yolov7-tiny.onnx --saveEngine=yolov7-tiny-nms.trt --fp16
netron
檢視模型架構netron yolov7-tiny.onnx
batch
= 1,如果要加快推理速度進行批次處理,前面的步驟應該指定啟用動態批次 --dynamic-batch
參考原程式碼加上註解
class BaseEngine(object):
def __init__(self, engine_path, imgsz=(640,640)):
"""
初始化模型引擎。
:param engine_path: 模型引擎的路徑。
:param imgsz: 影像的大小,預設為 (640, 640)。
"""
self.
self.imgsz = imgsz
self.mean = None
self.std = None
# 目標類別的名稱列表。
self.class_names = [ 'person', 'bicycle', 'car', 'motorcycle', 'airplane', 'bus', 'train', 'truck', 'boat', 'traffic light',
'fire hydrant', 'stop sign', 'parking meter', 'bench', 'bird', 'cat', 'dog', 'horse', 'sheep', 'cow',
'elephant', 'bear', 'zebra', 'giraffe', 'backpack', 'umbrella', 'handbag', 'tie', 'suitcase', 'frisbee',
'skis', 'snowboard', 'sports ball', 'kite', 'baseball bat', 'baseball glove', 'skateboard', 'surfboard',
'tennis racket', 'bottle', 'wine glass', 'cup', 'fork', 'knife', 'spoon', 'bowl', 'banana', 'apple',
'sandwich', 'orange', 'broccoli', 'carrot', 'hot dog', 'pizza', 'donut', 'cake', 'chair', 'couch',
'potted plant', 'bed', 'dining table', 'toilet', 'tv', 'laptop', 'mouse', 'remote', 'keyboard', 'cell phone',
'microwave', 'oven', 'toaster', 'sink', 'refrigerator', 'book', 'clock', 'vase', 'scissors', 'teddy bear',
'hair drier', 'toothbrush' ]
logger = trt.Logger(trt.Logger.WARNING)
# 初始化 TensorRT 插件。
trt.init_libnvinfer_plugins(logger,'')
runtime = trt.Runtime(logger)
# 讀取模型引擎。
with open(engine_path, "rb") as f:
serialized_engine = f.read()
engine = runtime.deserialize_cuda_engine(serialized_engine)
self.context = engine.create_execution_context()
self.inputs, self.outputs, self.bindings = [], [], []
self.stream = cuda.Stream()
# 為每個 binding 創建 host 和 device 記憶體
for binding in engine:
size = trt.volume(engine.get_binding_shape(binding)) # 取得 binding 的尺寸
dtype = trt.nptype(engine.get_binding_dtype(binding)) # 取得 binding 的數據類型
host_mem = cuda.pagelocked_empty(size, dtype) # 建立用於主機記憶體的 Numpy 陣列
device_mem = cuda.mem_alloc(host_mem.nbytes) # 分配裝置記憶體
self.bindings.append(int(device_mem)) # 將裝置記憶體加入到 bindings 清單中
if engine.binding_is_input(binding): # 判斷 binding 是否是輸入
# 如果是輸入,將主機和裝置記憶體加入到 inputs 清單中
self.inputs.append({'host': host_mem, 'device': device_mem})
else: # 如果是輸出,將主機和裝置記憶體加入到 outputs 清單中
self.outputs.append({'host': host_mem, 'device': device_mem})
def infer(self, img): # 推理函式,接收一張圖片作為參數
self.inputs[0]['host'] = np.ravel(img) # 將圖片攤平後存入 inputs[0]['host'] 中
# 將資料傳輸到 GPU
for inp in self.inputs:
cuda.memcpy_htod_async(inp['device'], inp['host'], self.stream)
# 執行推理
self.context.execute_async_v2(
bindings=self.bindings,
stream_handle=self.stream.handle)
# 從 GPU 中取得輸出
for out in self.outputs:
cuda.memcpy_dtoh_async(out['host'], out['device'], self.stream)
# synchronize stream 等待傳輸完成
self.stream.synchronize()
# 將輸出資料放入 data 清單中並返回**
data = [out['host'] for out in self.outputs]
return data
def inference(self, img_path, conf=0.25):
origin_img = cv2.imread(img_path)
origin_img = cv2.cvtColor(origin_img, cv2.COLOR_BGR2RGB)
img, ratio = preproc(origin_img, self.imgsz, self.mean, self.std)
num, final_boxes, final_scores, final_cls_inds = self.infer(img)
final_boxes = np.reshape(final_boxes, (-1, 4))
num = num[0]
# 獲取物體個數
if num >0:
# 將檢測結果還原至原圖大小,截取前 num 個物體
final_boxes, final_scores, final_cls_inds = final_boxes[:num]/ratio, final_scores[:num], final_cls_inds[:num]
# 可視化檢測結果
origin_img = vis(origin_img, final_boxes, final_scores, final_cls_inds,
conf=conf, class_names=self.class_names)
origin_img = cv2.cvtColor(origin_img, cv2.COLOR_RGB2BGR)
return origin_img
def get_fps(self):
# warmup
import time
img = np.ones((1,3,self.imgsz[0], self.imgsz[1]))
img = np.ascontiguousarray(img, dtype=np.float32)
for _ in range(20):
_ = self.infer(img)
t1 = time.perf_counter()
_ = self.infer(img)
print(1/(time.perf_counter() - t1), 'FPS')
# 以下略
pred = BaseEngine(engine_path='/content/tensorrt-python/yolov7-tiny-nms.trt')
origin_img = pred.inference('/content/yolov7/inference/images/horses.jpg')
import matplotlib.pyplot as plt
plt.figure(figsize=(10,10))
plt.imshow(origin_img[:, :, ::-1])
Linaom1214/tensorrt-python/trt.py
python3 trt.py -e yourmodel.trt -i src/1.jpg -o 1-inference.jpg --end2end
如果沒有--end2end
指令,則需要在推理後self.postprocess
進行NMS的後處理,理論上將NMS納入模型結構中可以加速處理
class BaseEngine(object):
# ... 略 ...
def inference(self, img_path, conf=0.5, end2end=False):
origin_img = cv2.imread(img_path)
img, ratio = preproc(origin_img, self.imgsz, self.mean, self.std)
data = self.infer(img)
if end2end:
num, final_boxes, final_scores, final_cls_inds = data
final_boxes = np.reshape(final_boxes/ratio, (-1, 4))
dets = np.concatenate([final_boxes[:num[0]], np.array(final_scores)[:num[0]].reshape(-1, 1), np.array(final_cls_inds)[:num[0]].reshape(-1, 1)], axis=-1)
else:
predictions = np.reshape(data, (1, -1, int(5+self.n_classes)))[0]
dets = self.postprocess(predictions,ratio)
if dets is not None:
final_boxes, final_scores, final_cls_inds = dets[:, :4], dets[:, 4], dets[:, 5]
frame = vis(frame, final_boxes, final_scores, final_cls_inds,
conf=conf, class_names=self.class_names)
在部署模型TensorRT轉檔時,可以選擇使用Fixed batch或Dynamic batch。使用Fixed batch意味著將模型的輸入形狀固定為一個特定的batch大小,因此無法處理其他batch大小的輸入,而使用Dynamic batch可以適應不同大小的batch輸入。Dynamic batch具有以下幾個優點:
靈活性:使用Dynamic batch可以在不更改模型部署的情況下,輕鬆地支持不同大小的輸入,這對於實際應用非常有用,例如,當輸入大小不一致時,可以避免在重新編譯模型時浪費時間和資源。
效能:在TensorRT中,當使用Dynamic batch時,可以在編譯時動態生成更高效的計算圖,而不需要將計算圖固定為特定的batch大小。因此,可以在Dynamic batch下達到與Fixed batch相同甚至更好的效能,並在執行時更加高效。
如果輸入資料為多個攝影機的多串流MultiStream,那讓模型設定為動態批次是很有必要的,這部分也可以串接DeepStream的PipeLine
在轉換動態模型的時候需要額外指定三個維度即可(最小、最優、最大)。
/usr/src/tensorrt/bin/trtexec
--explicitBatch --onnx=demo.onnx \
--minShapes=input:1x3x256x256 \
--optShapes=input:8x3x256X256 \
--maxShapes=input:16x3x256X256\
--saveEngine=demo.trt
yolov7/export.py
參數解釋--dynamic-batch
參數用於啟用動態批處理的 ONNX 導出
--dynamic-batch
時,ONNX 導出將生成一個動態批處理的模型,適用於使用 TensorRT 或 ONNX-Runtime 運行時進行推理。動態批處理意味着模型可以接受不同大小的批次作為輸入,而不需要預先指定批處理大小。導出的模型將使用一個特殊的符號 batch 來表示批處理維度。--dynamic
參數用於啟用動態軸的 ONNX 導出
--end2end
选项,该参数将被忽略。--dynamic
時,ONNX 導出將生成一個動態軸的模型,適用於一些需要在運行時調整輸入形狀的場景。動態軸意味着模型可以處理不同大小的輸入圖像尺寸,而不需要預先指定固定的圖像尺寸。這對於一些需要運行時靈活調整輸入形狀的應用非常有用。需要注意的是,–dynamic 參數和 –dynamic-batch 參數是互斥的,不能同時使用。如果同時指定了這兩個參數,–dynamic 參數會被忽略,僅導出動態批處理的模型。根據你的需求,可以選擇使用適合的參數來導出相應的 ONNX 模型。
yolov7/export.py
opt.dynamic_batch
啟用時
dynamic_axes = None
if opt.dynamic:
dynamic_axes = {'images': {0: 'batch', 2: 'height', 3: 'width'}, # size(1,3,640,640)
'output': {0: 'batch', 2: 'y', 3: 'x'}}
if opt.dynamic_batch:
opt.batch_size = 'batch'
dynamic_axes = {
'images': {
0: 'batch',
}, }
if opt.end2end and opt.max_wh is None:
output_axes = {
'num_dets': {0: 'batch'},
'det_boxes': {0: 'batch'},
'det_scores': {0: 'batch'},
'det_classes': {0: 'batch'},
}
else:
output_axes = {
'output': {0: 'batch'},
}
dynamic_axes.update(output_axes)
netron
檢視轉出的.onnx檔dynamic_batch | fix_batch(b=1) |
---|---|
![]() |
![]() |
在部署階段的模型加速方案包括:1) 模型壓縮(Model Compression),包括模型剪枝(Model Pruning)、模型量化(Model Quantization)、模型蒸餾(Model Distillation)、低秩因式分解(Low-Rank Factorization)等方法
(source:2020。A comprehensive survey on model compression and acceleration)
以下針對在Nvidia平台提供的通用加速工具提供範例,包括:
型轉換階段(.pt > .trt)啟用啟用動態批次 Dynamic_batch
模型量化 Quantization
模型量化透過降低精度和簡化模型參數,大幅減少模型的體積和計算負擔,並提高模型在特定硬體上的效率。
訓練時,也需要採用arm64架構的平台,否則在 onnx轉TensorRT階段會報錯
[TRT] DLA requests all profiles have same min, max, and opt value. All dla layers are falling back to GPU
採用PTQ後再接QAT的yolov7(int8)模型,在多批次(batch=16)時,處理速度(FPS)比fp16可以再提升1.82x(264/145)
在將onnx模型格式轉換為TensorRT Engine時,如果需要設定動態批次,記得做以下更改,否則在DeepStream設定檔讀入"batch-size">1時,模型會無法載入
將以下指令(batch size預設為1)
# int8 QAT model, the onnx model with Q&DQ nodes
/usr/src/tensorrt/bin/trtexec --onnx=yolov7qat.onnx --saveEngine=yolov7QAT.engine --fp16 --int8
替換為(明確指定批次範圍):
# int8 QAT model, the onnx model with Q&DQ nodes and dynamic-batch
/usr/src/tensorrt/bin/trtexec --onnx=yolov7qat.onnx \
--minShapes=images:1x3x640x640 \
--optShapes=images:12x3x640x640 \
--maxShapes=images:16x3x640x640 \
--saveEngine=yolov7QAT.engine --fp16 --int8
在TensorRT8.5.2 + AGX Xavier(32G)實測
/usr/src/tensorrt/bin/trtexec --loadEngine=model.engine --verbose
precision | Latency (mean:ms) |
trtexec FPS | \(mAP^{val}_{0.5:0.95}\) |
---|---|---|---|
FPS16 | 24.90 | 40.76 | 0.5124 |
Int8(PTQ/QAT) | 17.87 | 57.82 | 0.5113 |
* network input resolution: 3x640x640
* \(mAP^{test}_{0.5:0.95}\) for yolov7.pt : 0.514
測試環境
TensorRT Version: 8.5.2
GPU Type: Jetson AGX Xavier(32G) 系統安裝在外接64G隨身碟
Nvidia Driver Version:
CUDA Version: 11.4.315
CUDNN Version: 8.6.0.166
目前中文最詳盡的介紹,作者有豐富完整的部署經驗、值得一讀
tensorRT
編譯時對batch的處理,若靜態batch則意味著無論你多少圖,都按照固定大小batch推理。耗時是固定的view
操作不能固定batch維度數值,通常寫-1
dynamic_axes
,實際上不指定也沒關系dynamic_axes
指定O
以外的維度為動態,這樣帶來的複雜度太高,並且存在有的layer不支持。這種需求也不常用,性能也很差TRT::compile
函數的inputsDimsSetup參數重定義輸入的shapeTRT::set_layer_hook_reshape
鉤子動態修改reshape
的參數實現適配tensor.view(tensor.size(0), -1)
這類操作,避免直接使用tensor.size的返回值,而是加上int轉換, tensor.view(int(tensor.size(0)),-1)
nn.Upsample
或nn.functional.interpolate
函數,使用scale_factor
指定倍率,而不是使用size參數指定大小torch.onnx.export
指定dynamic_axes
參數,並且只指定batch維度,不指定其他維度。我們只需要動態batch,相對動態的寬高有其他方案1、盡量使得GPU高密集度運行,避免出現CPU、GPU相互交換運行
2、盡可能使tensorRT運行多個batch 數據。與第一點相合
3、預處理盡量cuda化,例如圖像需要做normalize、reisze、warpaffine、
bgr2rgb等,在這裏,采用cuda核實現warpaffine+normalize等操作,集中
在一起性能好
4、後處理盡量cuda化,例如decode、nms等。在這裏用cuda核實現了
decode和nms
5、善於使用cudaStream,將操作加入流中,采用異步操作避免等待
6、內存覆用
1、如何實現盡可能讓單模型使用多batch,此時future、promise就是很好
的工具
2、時序圖要盡可能優化,分析並繪制出來,不必的等待應該消除,同樣
是promise、future帶來的好處
3、尤其是圖像讀取和模型推理最常用的場景下,可以分析時序圖,緩存
一幀的結果,即可實現幀率的大幅提升
沒有緩存的時序圖
有緩存的時序圖
簡單易懂,可以瞭解入門概念
型推理的圖編譯器(Graph Compilers )原理解釋與補充
圖編譯器壓縮和優化深度神經網絡,以實現更快和更有效的內存推理。它們是深度學習推理加速堆棧中軟件組件的一部分,同時還有低級別的庫和深度學習框架。圖編譯器與計算圖一起工作,它代表了神經網絡及其張量操作。 圖編譯器使用的優化技術包括圖重寫、操作融合以及將操作分配給硬件
DL Inference Acceleration Stack