GPU也能高效跑視覺(jué)模型)
做了兩年多AI視覺(jué)項(xiàng)目后臺(tái)幾乎天天有人問(wèn)我同一個(gè)問(wèn)題做推理部署不買(mǎi)GPU行不行。說(shuō)實(shí)話被顯卡的價(jià)格和貨期折磨過(guò)的人都懂很多時(shí)候只是為了跑個(gè)YOLO檢測(cè)硬上好幾千甚至上萬(wàn)的GPU總覺(jué)得肉疼。后來(lái)我把目光轉(zhuǎn)到昇騰的Atlas系列上尤其是Atlas 300V 24G這張卡認(rèn)認(rèn)真真在它上面部署了一整套YOLO流程。今天就把這段時(shí)間的實(shí)測(cè)經(jīng)驗(yàn)寫(xiě)清楚聊聊這張卡到底是什么、能不能跑YOLO、該怎么部署、會(huì)遇到哪些坑。先說(shuō)結(jié)論Atlas 300V 24G是一張地地道道的AI推理加速卡不是訓(xùn)練卡也不是普通顯卡。它沒(méi)有顯示輸出接口不能接顯示器專(zhuān)為服務(wù)器端的推理任務(wù)設(shè)計(jì)。你問(wèn)它能不能部署YOLO答案是不僅能在視頻流處理、多模型常駐這類(lèi)場(chǎng)景里反而比同價(jià)位GPU更合適。這篇文章既解答你的硬件疑問(wèn)也附完整部署流程和踩坑記錄照著做就能把YOLO跑起來(lái)。1. Atlas 300V 24G到底是一張什么樣的卡1.1 先分清推理卡和訓(xùn)練卡這兩個(gè)物種很多人一聽(tīng)到AI加速卡下意識(shí)就把它當(dāng)成另一個(gè)品牌的顯卡然后拿訓(xùn)練卡的標(biāo)準(zhǔn)去衡量它這樣很容易得出錯(cuò)誤結(jié)論。實(shí)際上推理卡和訓(xùn)練卡是兩個(gè)方向的東西可以打個(gè)比方訓(xùn)練卡是重型卡車(chē)能拉幾十噸貨運(yùn)費(fèi)高、油耗大推理卡是城市配送的小面包車(chē)單趟拉不了那么多但便宜、靈活、停車(chē)方便專(zhuān)門(mén)解決最后一公里配送。具體到Atlas 300V 24G它隸屬于昇騰310P系列推理芯片核心設(shè)計(jì)目標(biāo)是用盡量低的功耗換取盡可能高的INT8推理吞吐。理論上做訓(xùn)練不是不行但效率遠(yuǎn)不如專(zhuān)業(yè)訓(xùn)練卡官方定位也一直是推理加速。所以如果你手頭有訓(xùn)練任務(wù)不要指望靠它解決但如果是把訓(xùn)練好的模型部署上線這張卡的性?xún)r(jià)比優(yōu)勢(shì)就很明顯了。我查過(guò)一些評(píng)測(cè)和官方資料這款卡整卡功耗大概在幾十瓦級(jí)別半高半長(zhǎng)的單槽設(shè)計(jì)不需要外接供電插到服務(wù)器的PCIe槽位上就能用。對(duì)機(jī)房密集部署來(lái)說(shuō)這種形態(tài)比動(dòng)輒兩三百瓦、需要獨(dú)立供電的大卡友好太多。1.2 24GB大內(nèi)存到底意味著什么關(guān)于這個(gè)卡被問(wèn)最多的就是24G是顯存嗎。準(zhǔn)確地說(shuō)它使用的主存儲(chǔ)器是板載DDR內(nèi)存不是GPU常用的GDDR顯存。這句話不是摳字眼而是理解這張卡性能特征的關(guān)鍵。DDR內(nèi)存的特點(diǎn)是容量大、成本低但對(duì)高帶寬訪問(wèn)任務(wù)支持不如HBM、GDDR。因此Atlas 300V 24G真正的強(qiáng)項(xiàng)不是單請(qǐng)求跑到極低延遲而是把大量模型、大批batch塞進(jìn)24GB里跑高并發(fā)推理。我實(shí)測(cè)下來(lái)如果你把batch size提高NPU的利用率和總吞吐會(huì)明顯好看相反強(qiáng)行要求單張圖片的極致延遲它跟高端GPU比并不占優(yōu)勢(shì)。24GB大內(nèi)存還有個(gè)很實(shí)際的用法同時(shí)常駐多個(gè)模型。比如項(xiàng)目中既要跑YOLOv8做行人檢測(cè)又要跑一個(gè)OCR模型識(shí)別車(chē)牌還要跑一個(gè)文本分類(lèi)模型做屬性標(biāo)簽這種多模型常駐的場(chǎng)景特別適合大內(nèi)存推理卡。換到普通12GB或16GB顯卡上要么得做顯存換入換出要么把幾個(gè)模型壓短batch跑整體吞吐會(huì)掉很多。1.3 硬件形態(tài)和使用環(huán)境Atlas 300V 24G是PCIe接口的標(biāo)準(zhǔn)加速卡市面上常見(jiàn)的是半高半長(zhǎng)版插在機(jī)架式服務(wù)器里非常合適。裝好驅(qū)動(dòng)后用npu-smi工具可以看到芯片狀態(tài)、算力使用率、內(nèi)存占用和功耗類(lèi)似GPU場(chǎng)景里的nvidia-smi。有一點(diǎn)要提前說(shuō)清楚很多人第一次拿到卡以為能像顯卡一樣裝進(jìn)家里臺(tái)式機(jī)接顯示器、跑個(gè)游戲這是不行的。Atlas 300V的運(yùn)行環(huán)境是服務(wù)器或工作站需要有UEFI或BIOS支持PCIe設(shè)備枚舉主流的x86服務(wù)器和部分ARM服務(wù)器都能正常識(shí)別。開(kāi)發(fā)調(diào)試時(shí)通過(guò)SSH遠(yuǎn)程操作推理結(jié)果以代碼輸出的形式返回全程沒(méi)有視頻輸出畫(huà)面。2. 在Atlas 300V上部署YOLO的完整流程2.1 環(huán)境準(zhǔn)備與CANN安裝部署環(huán)境我使用的是Ubuntu 22.04操作系統(tǒng)配一張Atlas 300V 24G加速卡。系統(tǒng)本身的要求并不高一套雙核CPU、8GB內(nèi)存以上的x86服務(wù)器就夠起步。整條軟件棧分兩個(gè)層次底層是驅(qū)動(dòng)和固件負(fù)責(zé)讓操作系統(tǒng)識(shí)別NPU設(shè)備上層是CANN昇騰計(jì)算語(yǔ)言提供模型轉(zhuǎn)換工具ATC和推理運(yùn)行時(shí)ACL。我安裝的是8.0版本的CANN Toolkit驅(qū)動(dòng)版本與CANN版本需要匹配。具體版本對(duì)照可以去昇騰技術(shù)支持頁(yè)面下載時(shí)核對(duì)比照官方release note是最靠譜的。安裝完成后可以用一條命令驗(yàn)證設(shè)備是否就緒npu-smi info如果能看到一個(gè)NPU設(shè)備、顯存容量顯示24GB、溫度功耗正常說(shuō)明驅(qū)動(dòng)部分沒(méi)問(wèn)題。接下來(lái)確認(rèn)CANN環(huán)境變量是否加載運(yùn)行source /usr/local/Ascend/ascend-toolkit/set_env.sh然后檢查ATC工具是否可用atc --help能正常打印幫助信息說(shuō)明軟件棧就緒可以進(jìn)行模型轉(zhuǎn)換了。2.2 導(dǎo)出ONNX中間模型昇騰的模型工具鏈不直接吃PyTorch的.pt權(quán)重也不能像CUDA生態(tài)那樣直接用torchscript標(biāo)準(zhǔn)流程是先導(dǎo)出ONNX再轉(zhuǎn)成昇騰的OM格式。以YOLOv5s為例假設(shè)你已經(jīng)有一個(gè)訓(xùn)練好的.pt權(quán)重官方倉(cāng)庫(kù)自帶了導(dǎo)出腳本python export.py --weights yolov5s.pt --include onnx --opset 12如果是YOLOv8或YOLO11Ultralytics倉(cāng)庫(kù)里也有導(dǎo)出格式運(yùn)行yolo export modelyolov8s.pt formatonnx opset12導(dǎo)出ONNX時(shí)有幾個(gè)細(xì)節(jié)會(huì)直接影響后續(xù)轉(zhuǎn)換成功率。第一opset版本建議固定在11到13之間太新的算子格式昇騰那邊可能還沒(méi)完全適配第二YOLOv8/v5默認(rèn)輸出是動(dòng)態(tài)shape建議在導(dǎo)出時(shí)就固定成靜態(tài)shape例如1x3x640x640后續(xù)ATC轉(zhuǎn)換省心很多第三如果網(wǎng)絡(luò)里有自定義算子導(dǎo)出ONNX后先用onnxruntime跑一遍推理確認(rèn)沒(méi)問(wèn)題再進(jìn)ATC環(huán)節(jié)。2.3 ATC轉(zhuǎn)OM模型——核心中的核心拿到ONNX模型后用ATC工具把它轉(zhuǎn)成昇騰專(zhuān)屬的OM格式。這個(gè)過(guò)程類(lèi)似CUDA生態(tài)里把TensorRT的.engineONNX轉(zhuǎn)OM不只是格式轉(zhuǎn)換還包含圖優(yōu)化、算子映射、內(nèi)存規(guī)劃等動(dòng)作直接影響最終推理性能。我給YOLOv5s執(zhí)行過(guò)的一條基礎(chǔ)轉(zhuǎn)換命令如下atc --modelyolov5s.onnx \ --framework5 \ --outputyolov5s_bs1 \ --input_shapeimages:1,3,640,640 \ --soc_versionAscend310P3 \ --loginfo參數(shù)含義逐一說(shuō)明--framework5表示輸入是ONNX模型這個(gè)值不能寫(xiě)錯(cuò)否則ATC會(huì)按照錯(cuò)誤格式解析文件。--input_shape把輸入的NHW各維度固定下來(lái)名字images必須和ONNX輸入名一致可以用Netron打開(kāi)模型確認(rèn)。--soc_version是目標(biāo)芯片的型號(hào)標(biāo)識(shí)必須和你的物理卡一致。查看方法是在裝有NPU驅(qū)動(dòng)的機(jī)器上執(zhí)行npu-smi info從輸出的芯片型號(hào)推斷常見(jiàn)的310P系列要寫(xiě)成Ascend310P3這樣的格式具體映射關(guān)系看當(dāng)前CANN版本的幫助文檔。--loginfo用于排查問(wèn)題轉(zhuǎn)換成功后可以改成error級(jí)別減少日志干擾。轉(zhuǎn)換成功后會(huì)生成yolov5s_bs1.om文件。如果轉(zhuǎn)換過(guò)程中報(bào)算子不支持先別急著重裝環(huán)境常見(jiàn)的解決辦法是調(diào)整ONNX的opset版本或者把核心算子的實(shí)現(xiàn)方式換成昇騰友好的形式比如把SiLU激活函數(shù)在前處理中展開(kāi)具體問(wèn)題我放到第3節(jié)排查部分細(xì)說(shuō)。2.4 寫(xiě)推理代碼pyACL從入門(mén)到能跑OM模型轉(zhuǎn)換好之后推理側(cè)常用的編程接口是pyACL也就是AscendCL的Python綁定。整體流程和CUDA編程高度類(lèi)似初始化設(shè)備、加載模型、準(zhǔn)備輸入輸出內(nèi)存、執(zhí)行推理、釋放資源。給一段簡(jiǎn)化但能跑通核心邏輯的示例框架import acl import numpy as np # 1. 初始化 acl.init() ret acl.rt.set_device(0) context, ret acl.rt.create_context(0) # 2. 加載OM模型 model_id, ret acl.mdl.load_from_file(yolov5s_bs1.om) # 3. 查詢(xún)輸入輸出信息 input_desc acl.mdl.get_input_desc(model_id) input_size acl.mdl.get_input_size_by_index(model_id, 0) output_desc acl.mdl.get_output_desc(model_id) output_size acl.mdl.get_output_size_by_index(model_id, 1) # 4. 準(zhǔn)備輸入數(shù)據(jù)假設(shè)input_np已經(jīng)是letterbox預(yù)處理好的640x640歸一化tensor input_np np.ascontiguousarray(input_np, dtypenp.float32) input_ptr acl.util.np_to_ptr(input_np) # 5. 申請(qǐng)輸出內(nèi)存 output_np np.zeros(output_size, dtypenp.uint8) output_ptr acl.util.np_to_ptr(output_np) # 6. 執(zhí)行推理 ret acl.mdl.execute(model_id, input_ptr, output_ptr) # 7. 輸出轉(zhuǎn)為numpy output_data np.array(output_np).reshape((1, 25200, 85)) # 后續(xù)做閾值過(guò)濾、NMS后處理代碼里有個(gè)關(guān)鍵點(diǎn)acl.util.np_to_ptr這類(lèi)API在部分版本里要求輸入數(shù)據(jù)在內(nèi)存中連續(xù)所以先做np.ascontiguousarray是很有必要的。另外預(yù)處理的細(xì)節(jié)直接決定檢測(cè)效果YOLOv5在線推理時(shí)要保證letterbox縮放比例和模型訓(xùn)練時(shí)一致縮放填充的灰度值也要對(duì)齊。如果用自己的代碼做預(yù)處理建議把YOLOv5原倉(cāng)庫(kù)中l(wèi)etterbox的邏輯原樣搬過(guò)來(lái)不要自己改。更進(jìn)階的玩法是使用AIPPAI Preprocessing配置把圖像縮放、減均值、歸一化等操作下沉到硬件里執(zhí)行減少CPU層面的反復(fù)拷貝。這樣做的好處是推理吞吐會(huì)提升但配置項(xiàng)較復(fù)雜適合把性能壓到極限的場(chǎng)合。第一次上手建議先用Python做預(yù)處理跑通全流程再考慮優(yōu)化。3. 部署過(guò)程中最容易踩的5個(gè)坑3.1 ATC轉(zhuǎn)換期的算子不支持問(wèn)題這是所有初次接觸昇騰的人都會(huì)遇到的第一道坎YOLOv5老版本、YOLOv8的某些模塊在特定CANN版本下都可能出現(xiàn)算子不支持。典型報(bào)錯(cuò)是E10016之類(lèi)的錯(cuò)誤碼后面跟著一個(gè)算子名。碰上這種情況我的排查順序比較固定先把ONNX的opset調(diào)到12甚至11很多算子報(bào)錯(cuò)跟新版opset引入的變形有關(guān)然后用Netron打開(kāi)模型找報(bào)錯(cuò)算子附近的子圖看看是不是可以用等價(jià)變換替換比如把SiLU換成ReLU需重新訓(xùn)練或接受小幅精度損失或者用--op_precision_mode讓ATC用兼容模式處理最后再考慮升級(jí)CANN版本新版本算子覆蓋度通常更高。實(shí)測(cè)下來(lái)超過(guò)一半的算子報(bào)錯(cuò)都能靠調(diào)整opset解決。3.2 預(yù)處理格式不一致導(dǎo)致檢測(cè)精度崩掉跑通了模型結(jié)果檢測(cè)精度和GPU上差了一大截這十有八九是預(yù)處理沒(méi)對(duì)齊。我犯過(guò)的錯(cuò)誤是把RGB圖像當(dāng)BGR輸進(jìn)去結(jié)果模型把天空檢測(cè)成行人的情況都有。昇騰側(cè)本身不會(huì)校驗(yàn)輸入的通道順序它只是忠實(shí)執(zhí)行模型的計(jì)算邏輯。解決辦法是把預(yù)處理代碼統(tǒng)一封裝成函數(shù)嚴(yán)格按模型訓(xùn)練時(shí)的順序處理從讀圖到letterbox、顏色通道、歸一化、layout維度每一步都用固定函數(shù)??缭O(shè)備對(duì)比精度時(shí)先用一張固定圖片在GPU端和NPU端分別輸出原生態(tài)的tensor再逐位對(duì)比這樣定位問(wèn)題非常有效率。3.3 內(nèi)存不足與多次加載模型問(wèn)題有24GB內(nèi)存按說(shuō)跑一個(gè)YOLOv5綽綽有余但碰到跑多路視頻流時(shí)仍然可能報(bào)memory too small。我遇到過(guò)一個(gè)具體的坑在循環(huán)里反復(fù)調(diào)用acl.mdl.load_from_file加載同一個(gè)OM文件舊模型沒(méi)有卸載最后內(nèi)存被耗光。正確做法是模型加載一次放進(jìn)全局變量整個(gè)進(jìn)程生命周期內(nèi)復(fù)用結(jié)束時(shí)再acl.mdl.unload。另外ATC轉(zhuǎn)換時(shí)加上--memory_init1參數(shù)可以讓模型在加載時(shí)做一次內(nèi)存初始化避免某些模型首次推理時(shí)因部分內(nèi)存未初始化而觸發(fā)異常。這個(gè)參數(shù)不解決所有問(wèn)題但對(duì)某些FP16模型確實(shí)有效可以加入默認(rèn)轉(zhuǎn)換命令中。3.4 單batch延遲不理想問(wèn)題出在用法上如果只看單張圖、batch為1的推理延遲Atlas 300V的數(shù)值不一定比同價(jià)位GPU漂亮這容易勸退一部分人。但把batch加大到8或16后每張圖的平均處理時(shí)間會(huì)明顯下降總吞吐大幅增加。這跟算力結(jié)構(gòu)和內(nèi)存帶寬的特點(diǎn)有關(guān)該卡的設(shè)計(jì)目標(biāo)是高通量場(chǎng)景而不是低延遲極限。實(shí)際項(xiàng)目中部署YOLO建議優(yōu)先把推理請(qǐng)求積攢到一個(gè)緩沖隊(duì)列里湊滿(mǎn)一個(gè)batch再提交給NPU。視頻流場(chǎng)景天然適合這樣做延遲增加幾十毫秒換來(lái)整機(jī)吞吐翻倍很劃算。3.5 驅(qū)動(dòng)、固件與CANN版本不匹配昇騰軟件棧對(duì)版本匹配要求十分嚴(yán)格驅(qū)動(dòng)、固件、CANN三者版本有一項(xiàng)對(duì)不上就可能出現(xiàn)設(shè)備無(wú)法初始化、npu-smi顯示異常、ATC莫名其妙崩潰等情況。我調(diào)試環(huán)境時(shí)曾經(jīng)因?yàn)轵?qū)動(dòng)是新的、CANN是舊的導(dǎo)致PYTHON API import階段直接段錯(cuò)誤。解決辦法嚴(yán)格按照官方版本配套關(guān)系表安裝安裝順序先固件再驅(qū)動(dòng)最后CANN Toolkit。如果之前裝過(guò)其他版本執(zhí)行官方腳本做徹底卸載不要手動(dòng)刪文件不然殘留的庫(kù)文件會(huì)導(dǎo)致后續(xù)安裝各種詭異問(wèn)題。下面把這個(gè)坑整理成速查表方便你核對(duì)問(wèn)題現(xiàn)象可能原因解決辦法npu-smi看不到NPU驅(qū)動(dòng)未裝好或固件不匹配重裝匹配版本的驅(qū)動(dòng)和固件ATC報(bào)算子不支持ONNX opset過(guò)高或算子不在支持列表調(diào)整opset、替換子圖、升級(jí)CANN檢測(cè)精度大幅下降預(yù)處理與訓(xùn)練時(shí)不一致對(duì)齊RGB順序、letterbox、歸一化報(bào)memory too small模型重復(fù)加載未釋放全局復(fù)用model_id顯式unload多batch吞吐偏低數(shù)據(jù)拷貝或CPU預(yù)處理成瓶頸用Python多線程預(yù)處理、嘗試AIPP下沉4. 性能實(shí)測(cè)與選型建議4.1 這張卡適合什么任務(wù)我在跑YOLOv8s整條流程時(shí)單batch實(shí)測(cè)純推理延遲在十幾毫秒這個(gè)量級(jí)加大batch后吞吐能明顯增加板載24GB內(nèi)存常駐多個(gè)模型完全沒(méi)壓力。這里強(qiáng)調(diào)的是純推理延遲機(jī)器吞吐受CPU預(yù)處理、數(shù)據(jù)拷貝、后處理的影響很大項(xiàng)目落地需要全鏈路優(yōu)化。如果從硬件定位出發(fā)給出選型建議這張卡適合這些場(chǎng)景中大規(guī)模視頻流分析比如智慧園區(qū)、明廚亮灶、工業(yè)質(zhì)檢等每路視頻獨(dú)立推理天然是批處理模式。多模型常駐服務(wù)把檢測(cè)、分類(lèi)、OCR等模型都丟進(jìn)24GB里按需路由省去動(dòng)態(tài)加載模型的開(kāi)銷(xiāo)。低功耗、高密度的邊緣或私有化服務(wù)器一張卡幾十瓦的功耗對(duì)機(jī)房電費(fèi)和散熱壓力非常友好而且不占CPU資源。4.2 和GPU相比的客觀優(yōu)劣不能一味說(shuō)Atlas 300V比GPU好這是不客觀的。和同價(jià)位的消費(fèi)級(jí)或?qū)I(yè)級(jí)GPU比它的優(yōu)勢(shì)是功耗低、大內(nèi)存、無(wú)獨(dú)立供電需求而且原生支持國(guó)產(chǎn)化軟硬件棧在合規(guī)性要求高的項(xiàng)目里優(yōu)勢(shì)明顯。劣勢(shì)是生態(tài)成熟度不如CUDA調(diào)試工具、第三方庫(kù)、網(wǎng)上案例都少一大截很多在GPU上隨手可用的功能需要自己摸索或者去昇騰社區(qū)翻文檔。另一層差異是數(shù)據(jù)格式和部署工具鏈。在GPU上Triton、TensorRT這些生態(tài)已經(jīng)非常成熟昇騰側(cè)有MindIE、MindSpore Lite這些工具但整體成熟度和社區(qū)活躍度仍在追趕階段。如果你帶一個(gè)熟悉CUDA的團(tuán)隊(duì)轉(zhuǎn)型到昇騰前兩周的適應(yīng)成本是繞不開(kāi)的。4.3 什么情況下不要買(mǎi)它有一些場(chǎng)景Atlas 300V并不合適。如果你的核心任務(wù)是模型訓(xùn)練直接放棄這張卡訓(xùn)練性能完全發(fā)揮不出來(lái)如果你的業(yè)務(wù)里全是小batch、低延遲、高并發(fā)的交互式請(qǐng)求比如在線鑒黃、實(shí)時(shí)人臉閘機(jī)那么GPU的延遲優(yōu)勢(shì)更明顯如果你特別依賴(lài)某個(gè)GPU專(zhuān)屬框架或算子且昇騰側(cè)沒(méi)有對(duì)應(yīng)適配遷移成本可能超過(guò)省下的硬件費(fèi)用這種情況也慎重。我的建議是先梳理清楚自己的核心負(fù)載是高通量離線/準(zhǔn)實(shí)時(shí)推理還是低延遲實(shí)時(shí)交互前者可以放心選擇Atlas 300V后者先用廠商提供的性能工具做一輪benchmark再?zèng)Q定。另外提一句選配置時(shí)的實(shí)際體驗(yàn)24G版本和8G版本價(jià)格差不少如果你的目標(biāo)只是跑一兩個(gè)輕量YOLO模型8G夠用但如果打算常駐多個(gè)模型或跑量化后的大模型24G版本能讓你少很多內(nèi)存不足的焦慮。別因?yàn)槭☆A(yù)算硬上小內(nèi)存后期項(xiàng)目擴(kuò)展時(shí)你會(huì)后悔。5. 聊聊我折騰期間的心里話從最初對(duì)國(guó)產(chǎn)加速卡半信半疑到一步步把YOLOv8跑通并壓榨到可用狀態(tài)這個(gè)過(guò)程中最大的體會(huì)是硬件本身的能力被很多人低估但生態(tài)成熟度的差距也是客觀存在的。Atlas 300V 24G不是萬(wàn)能的GPU生態(tài)積累的優(yōu)勢(shì)也不是靠一塊卡就能追平的但如果你手頭的任務(wù)恰好是視頻流推理、多模型常駐、低功耗部署這類(lèi)高通量場(chǎng)景它確實(shí)能花更少的錢(qián)辦同樣的事。最后再給一個(gè)實(shí)操建議不管用哪張卡先把基礎(chǔ)環(huán)境搞干凈嚴(yán)格按官方文檔匹配驅(qū)動(dòng)和CANN版本然后跑通一個(gè)小模型驗(yàn)證全鏈路再上你的主力模型。等把坑都踩過(guò)一遍后續(xù)工作就順了。