CUDA與TensorRT模型部署優(yōu)化:關(guān)鍵考慮與實(shí)踐策略
本文經(jīng)自動(dòng)駕駛之心公眾號(hào)授權(quán)轉(zhuǎn)載,轉(zhuǎn)載請(qǐng)聯(lián)系出處。
筆者的一點(diǎn)個(gè)人理解
模型部署與優(yōu)化是當(dāng)前許多自動(dòng)駕駛公司投入人力物力去做的模塊,如何將模型高效部署在特定的芯片上至關(guān)重要。深度學(xué)習(xí)模型的部署與優(yōu)化是一個(gè)綜合性的過程,涉及多個(gè)關(guān)鍵考慮因素。雖然工具如TensorRT為模型提供了強(qiáng)大的優(yōu)化,但其應(yīng)用并非無限,有時(shí)需要開發(fā)者手動(dòng)調(diào)整或補(bǔ)充。此外,選擇CUDA Cores還是Tensor Cores、考慮前后處理的效率,以及進(jìn)一步的性能分析和基準(zhǔn)測(cè)試,都是確保模型在特定硬件上達(dá)到最佳性能的關(guān)鍵步驟。今天我將會(huì)為大家分享下模型部署的關(guān)鍵考慮與實(shí)踐策略。
所有內(nèi)容出自:全搞定!基于TensorRT的CNN/Transformer/檢測(cè)/BEV模型四大部署代碼+CUDA加速教程!
1. FLOPS TOPS
首先,我們來解釋FLOPS和TOPS的含義:
FLOPS:是Floating Point Operations Per Second的縮寫,意思是每秒浮點(diǎn)運(yùn)算次數(shù)。它是衡量計(jì)算機(jī)或計(jì)算設(shè)備在每秒內(nèi)執(zhí)行的浮點(diǎn)運(yùn)算次數(shù)的指標(biāo)。通常用于表示處理器的計(jì)算性能。例如,1 TFLOPS表示每秒執(zhí)行1萬(wàn)億次浮點(diǎn)運(yùn)算。
TOPS:是Tera Operations Per Second的縮寫,意思是每秒運(yùn)算次數(shù)。它與FLOPS類似,但通常用于衡量整數(shù)運(yùn)算或混合型的運(yùn)算能力,而不僅僅是浮點(diǎn)運(yùn)算。
下面列出一個(gè)關(guān)于NVIDIA A100(基于發(fā)布時(shí)的公開資料)的性能參數(shù)表格。請(qǐng)注意,這些性能數(shù)字代表了理論上的峰值計(jì)算能力,實(shí)際應(yīng)用中的性能可能會(huì)因?yàn)楦鞣N因素而有所不同。
參數(shù) | 性能值 |
Peak FP64 (雙精度浮點(diǎn)性能) | 9.7 TFLOPS |
Peak FP32 (單精度浮點(diǎn)性能) | 19.5 TFLOPS |
Peak FP16 (半精度浮點(diǎn)性能) | 312 TFLOPS |
Tensor Performance (FP16) | 624 TOPS |
INT8 Performance | 1248 TOPS |
INT4 Performance | 2496 TOPS |
下面是Jetson Xavier AGX Volta的參數(shù)
參數(shù) | Jetson Xavier AGX (Volta) |
Core種類與數(shù)量 | |
CUDA cores | 512 |
Tensor cores | 64 |
SMs | 8 |
計(jì)算峰值 | |
FP32 | 1.4 TFLOPS |
FP16 | 11 TFLOPS |
INT8 | 22 TOPS |
帶寬 | 137 GB/s |
頻率 | 900MHz |
Tensor Performance (FP16): Tensor Core的半精度浮點(diǎn)性能,特別針對(duì)深度學(xué)習(xí)和AI應(yīng)用進(jìn)行了優(yōu)化。
INT8 Performance: 8位整數(shù)性能,常用于某些深度學(xué)習(xí)工作負(fù)載。
INT4 Performance: 4位整數(shù)性能,適用于需要更高吞吐量但可以接受較低精度的應(yīng)用。
這些數(shù)據(jù)提供了一個(gè)全面的視圖,顯示了A100在不同精度和數(shù)據(jù)類型下的性能。不同的應(yīng)用和任務(wù)可能會(huì)根據(jù)其對(duì)計(jì)算精度和速度的需求來選擇最適合的數(shù)據(jù)類型和運(yùn)算模式。
2. FLOPs
這個(gè)容易弄混淆,這個(gè)只是衡量模型大小的指標(biāo),下面展示YOLOV5跟Swin Transformer的FLOPs
參數(shù)/模型 | YOLOv5 (640x640) | Swin Transformer (224x224) |
Tiny/Small | YOLOv5s: ~3.5 GFLOPs | Swin Tiny: ~4.5 GFLOPs |
Medium | YOLOv5m: ~6.9 GFLOPs | Swin Small: ~8.7 GFLOPs |
Large | YOLOv5l: ~12.7 GFLOPs | Swin Base: ~17.3 GFLOPs |
Extra Large | YOLOv5x: ~17.4 GFLOPs | Swin Large: ~34.5 GFLOPs |
- 模型的規(guī)模與計(jì)算復(fù)雜性的關(guān)系:
- 對(duì)于每個(gè)模型系列(不論是YOLOv5還是Swin Transformer),當(dāng)模型規(guī)模增加(從Tiny到Extra Large)時(shí),計(jì)算復(fù)雜性(FLOPs)也相應(yīng)增加。這很容易理解,因?yàn)楦蟮哪P屯ǔ>哂懈嗟膶雍蛥?shù),因此需要更多的計(jì)算。
- 模型輸入尺寸的影響:
YOLOv5的輸入尺寸為640x640,而Swin Transformer的為224x224。即使如此,較小的Swin Transformer模型仍然具有相似或更高的FLOPs。這突顯了Transformer結(jié)構(gòu)相較于傳統(tǒng)的卷積網(wǎng)絡(luò)結(jié)構(gòu)在計(jì)算上的密集性。
模型類型的不同:
正如前面提到的,YOLOv5是一個(gè)目標(biāo)檢測(cè)模型,而Swin Transformer主要設(shè)計(jì)用于圖像分類。將這兩者進(jìn)行對(duì)比可能不完全公平,因?yàn)樗鼈兪菫椴煌娜蝿?wù)優(yōu)化的。不過,這個(gè)對(duì)比提供了一個(gè)關(guān)于不同模型和結(jié)構(gòu)計(jì)算復(fù)雜性的大致感覺。
FLOPs與性能的關(guān)系:
雖然FLOPs提供了關(guān)于模型計(jì)算復(fù)雜性的信息,但它并不直接等同于模型的實(shí)際運(yùn)行速度或效率。其他因素,如內(nèi)存訪問、優(yōu)化技術(shù)、硬件特性等,都會(huì)影響實(shí)際性能。
同樣,F(xiàn)LOPs也不直接等同于模型的準(zhǔn)確性。有時(shí),較小的模型經(jīng)過適當(dāng)?shù)挠?xùn)練和優(yōu)化可能會(huì)表現(xiàn)得相當(dāng)好。
總的來說,這個(gè)表格提供了一個(gè)視覺上的對(duì)比,展示了兩種不同模型結(jié)構(gòu)在不同規(guī)模下的計(jì)算復(fù)雜性。但解釋這些數(shù)據(jù)時(shí),要考慮到模型的具體用途、設(shè)計(jì)目標(biāo)和其他相關(guān)因素。
3. CUDA Core and Tensor Core
CUDA Core:
- 定義: CUDA Core 是 NVIDIA GPU 中用于執(zhí)行浮點(diǎn)和整數(shù)運(yùn)算的基本計(jì)算單元。
- 用途: CUDA Cores 主要用于通用的圖形和計(jì)算任務(wù),比如圖形渲染、物理模擬和其他數(shù)值計(jì)算等。
Tensor Core:
- 定義: Tensor Core 是 NVIDIA 的一些新架構(gòu)(如 Volta、Turing 和 Ampere)中引入的專門硬件單元,用于高效地執(zhí)行深度學(xué)習(xí)中的矩陣運(yùn)算。
- 用途: Tensor Cores 專門設(shè)計(jì)用于深度學(xué)習(xí)計(jì)算,尤其是進(jìn)行大規(guī)模的矩陣乘法和加法操作,這些操作是神經(jīng)網(wǎng)絡(luò)訓(xùn)練和推理的核心。
簡(jiǎn)而言之,CUDA Core 是 GPU 的通用計(jì)算工作馬,處理各種圖形和計(jì)算任務(wù),而 Tensor Core 則是為深度學(xué)習(xí)任務(wù)特別設(shè)計(jì)的高效計(jì)算單元。
A100 有 6912 個(gè) CUDA Core,而只有 432 個(gè) Tensor Core。盡管 Tensor Cores 的數(shù)量較少,但它們?cè)谔幚硖囟ǖ纳疃葘W(xué)習(xí)任務(wù)時(shí)非常高效。
設(shè)計(jì)目的:
CUDA Cores 是通用的計(jì)算單元,能夠處理各種任務(wù),包括圖形、物理模擬和通用數(shù)值計(jì)算等。Tensor Cores 則專門設(shè)計(jì)用于深度學(xué)習(xí)計(jì)算,尤其是矩陣乘法和累加操作。性能:
單一的 CUDA Core 能夠執(zhí)行基本的浮點(diǎn)和整數(shù)運(yùn)算。每個(gè) Tensor Core 能夠在一個(gè)周期內(nèi)處理一小塊矩陣的乘法和累加操作(例如 4x4 或 8x8)。這使得它們?cè)谔幚砩疃葘W(xué)習(xí)操作時(shí)非常高效。使用場(chǎng)景:
當(dāng)執(zhí)行圖形渲染或通用計(jì)算任務(wù)時(shí),主要使用 CUDA Core。當(dāng)執(zhí)行深度學(xué)習(xí)訓(xùn)練和推理任務(wù)時(shí),尤其是使用庫(kù)如 cuDNN 或 TensorRT 時(shí),Tensor Cores 會(huì)被積極利用,以實(shí)現(xiàn)最大的計(jì)算效率。使用 A100 作為例子,我們可以清楚地看到 NVIDIA 是如何通過結(jié)合 CUDA Cores 和 Tensor Cores 來提供高效的深度學(xué)習(xí)和通用計(jì)算性能的。
4. Roofline model
Roofline Model 是一個(gè)可視化工具,用于表征計(jì)算密集型應(yīng)用的性能。它提供了一個(gè)框架,通過該框架,開發(fā)者可以理解應(yīng)用的性能瓶頸,并與某個(gè)特定硬件的理論峰值性能進(jìn)行對(duì)比。Roofline 模型的主要目標(biāo)是提供對(duì)算法和硬件交互的深入了解,從而為優(yōu)化提供指導(dǎo)。
Roofline模型基本上是一個(gè)圖,其中:
- x軸: 計(jì)算與數(shù)據(jù)移動(dòng)的比率,通常用“浮點(diǎn)運(yùn)算次數(shù)/字節(jié)”表示。
- y軸: 性能,通常以“FLOPS”為單位。
在此圖上有兩個(gè)主要部分:
- Roof: 這代表了硬件的性能上限。這是兩部分組成的:
- 計(jì)算上限:這通常是以FLOPS為單位的峰值計(jì)算性能。
- 帶寬上限:這是數(shù)據(jù)從主存儲(chǔ)器移動(dòng)到計(jì)算單元的最大速率。
- Line:這表示應(yīng)用或算法的性能。它的斜率由內(nèi)存訪問和浮點(diǎn)計(jì)算的比率決定。
通過觀察算法在Roofline模型上的位置,開發(fā)者可以判斷算法是受計(jì)算能力限制還是受帶寬限制,并據(jù)此決定優(yōu)化策略。
案例一: RTX 3080
案例二: Jetson Xavier AGX Volta
參數(shù) | Jetson Xavier AGX (Volta) |
Core種類與數(shù)量 | |
CUDA cores | 512 |
Tensor cores | 64 |
SMs | 8 |
計(jì)算峰值 | |
FP32 | 1.4 TFLOPS |
FP16 | 11 TFLOPS |
INT8 | 22 TOPS |
帶寬 | 137 GB/s |
頻率 | 900MHz |
也可以從這兩個(gè)案例的對(duì)比看出來邊緣端跟服務(wù)器端的區(qū)別,所以TensorRT CUDA的掌握就很重要, 能夠使用這些SDK滿足客戶的需求也是我們求職的一個(gè)機(jī)會(huì)
5. 模型部署的一些誤區(qū)
模型性能與FLOPs
FLOPs, 即浮點(diǎn)運(yùn)算次數(shù), 通常被用來衡量模型的計(jì)算復(fù)雜性。然而,它并不足以完全描述模型的性能。盡管FLOPs反映了模型的計(jì)算負(fù)荷,但實(shí)際的推理速度和效率還受到其他因素影響。例如,訪問內(nèi)存、數(shù)據(jù)的轉(zhuǎn)換和重塑,以及其他與計(jì)算無關(guān)但與深度神經(jīng)網(wǎng)絡(luò)操作相關(guān)的部分。此外,像前后處理這樣的步驟,也可能占據(jù)顯著的時(shí)間,尤其是在一些輕量級(jí)模型中。
TensorRT的局限性
TensorRT是NVIDIA提供的一個(gè)強(qiáng)大的工具,可以對(duì)深度學(xué)習(xí)模型進(jìn)行優(yōu)化以獲得更好的推理性能。然而,它的優(yōu)化能力并非沒有局限。例如,某些低計(jì)算密度的操作,如1x1的conv,depthwise conv, 可能不會(huì)被TensorRT重構(gòu)。有些操作,如果GPU不能優(yōu)化,TensorRT可能會(huì)選擇在CPU上執(zhí)行。但開發(fā)者可以手動(dòng)調(diào)整代碼,使某些CPU操作轉(zhuǎn)移到GPU。此外,如果遇到TensorRT尚不支持的算子,可以通過編寫自定義插件來補(bǔ)充。
1x1 conv, depthwise conv 這些算子出現(xiàn)在mobileNet上面,Transformer的優(yōu)化也是把最后的FC層用這兩個(gè)算子去替換,他們雖然降低了參數(shù)量,但是減少了計(jì)算的密度。
CUDA Core與Tensor Core的選擇考量
NVIDIA的最新GPU通常配備了CUDA Cores和Tensor Cores。雖然Tensor Cores專門為深度學(xué)習(xí)操作優(yōu)化,但TensorRT不一定總是使用它們。實(shí)際上,TensorRT通過內(nèi)核自動(dòng)調(diào)優(yōu)選擇最優(yōu)的內(nèi)核執(zhí)行方式,這可能意味著某些情況下INT8的性能比FP16還差。要有效利用Tensor Cores,有時(shí)需要確保tensor的尺寸為8或16的倍數(shù)。
前后處理的時(shí)間開銷
在深度學(xué)習(xí)的應(yīng)用中,前處理(如圖像調(diào)整和歸一化)和后處理(如結(jié)果解釋)是不可或缺的步驟。然而,對(duì)于輕量級(jí)的模型,這些處理步驟可能比實(shí)際的DNN推理還要耗時(shí)。部分前后處理步驟由于其復(fù)雜邏輯不適合GPU并行化。但解決方案是將這些邏輯中的并行部分移至GPU或在CPU上使用優(yōu)化庫(kù)如Halide,這樣可以提高某些任務(wù),如模糊、縮放的效率。
很多時(shí)候在做YOLO的后處理的時(shí)候我們會(huì)喜歡把它放在GPU上面去做,這樣會(huì)給人一種很快的感覺,但是這種并不是必要的,第一,GPU沒有排序的功能,第二,YOLO系列我們使用閾值先過濾掉一大部分的時(shí)候剩下來的bbox已經(jīng)是很少的了,也不見得說會(huì)快很多。
并不是TRT跑通了就結(jié)束了
創(chuàng)建并使用TensorRT推理引擎僅僅是優(yōu)化流程的開始。為了確保模型達(dá)到最佳性能,開發(fā)者需要進(jìn)一步對(duì)其進(jìn)行基準(zhǔn)測(cè)試和性能分析。NVIDIA提供了如nsys, nvprof, dlprof, Nsight等工具,這些工具可以幫助開發(fā)者精確地確定性能瓶頸、尋找進(jìn)一步的優(yōu)化機(jī)會(huì)以及識(shí)別不必要的內(nèi)存訪問。
原文鏈接:https://mp.weixin.qq.com/s/OikQ9BUZi6_be8ul6L0F6g