部署YOLO目標檢測)
最近后臺老是有人問我一句話Atlas 300V 24G 是運算加速卡嗎我意識到很多人第一次看到昇騰這個生態(tài)的時候都會被命名繞暈。今天我直接用最直白的方式回答它不是顯卡它是一張專門用來跑AI推理的運算加速卡。把它裝到服務(wù)器上最常見的一個用途就是部署YOLO目標檢測模型處理視頻流、圖片流把人、車、物實時框出來。本文與其說是一篇科普不如說是一份整理過的實操筆記從硬件定位、選型到環(huán)境安裝、模型轉(zhuǎn)換、推理代碼再到我踩過的坑盡量一步不落的講清楚。適合正在評估Atlas推理卡、或者剛拿到卡不知道從哪下手的工程師參考。1. Atlas 300V 24G 硬件定位與選型思路1.1 它到底是運算加速卡還是“顯卡”先說結(jié)論Atlas 300V 24G 是一張標準的AI推理加速卡不是顯卡。顯卡的核心職責是輸出畫面而Atlas 300V 24G沒有顯示輸出接口也不能拿來玩游戲它的一切設(shè)計都是為了神經(jīng)網(wǎng)絡(luò)推理服務(wù)的。整張卡的核心是基于昇騰310P芯片打造的內(nèi)部集成了達芬奇架構(gòu)的AI Core支持FP16和INT8低比特加速再配上24GB的大容量內(nèi)存讓它可以同時塞下較大的模型或較大的batch。用個生活化類比CPU像是全能管家什么都能干但每件事都不算快GPU像是擅長畫畫的員工既能畫到屏幕上也能幫算三維場景而Atlas更像是流水線上的一臺專機只干一件事——把訓(xùn)練好的模型跑起來做推理。它把卷積、矩陣乘這些算子做到了極致尤其是INT8推理吞吐量非??捎^所以在純推理場景下它比同價位的不少GPU更劃算。它是一整塊低功耗被動散熱的半高卡裝進2U服務(wù)器里非常穩(wěn)。在實際部署中我拿到手的第一反應(yīng)是它非常安靜沒有風(fēng)扇完全靠服務(wù)器風(fēng)道散熱。它的功耗大概在75W左右很多塔式工作站的PCIe供電就能帶起來不需要額外外接電源。這種設(shè)計特別適合數(shù)據(jù)中心里那種追求高密度算力的場景一張卡一個事務(wù)插滿就能把一臺服務(wù)器變成專用推理節(jié)點。如果你只是做視頻分析、目標檢測這類業(yè)務(wù)它會比折騰大顯存游戲卡穩(wěn)定得多。1.2 為什么選 Atlas 而不一概用 GPU很多朋友習(xí)慣了一張NVIDIA GPU走天下聽到昇騰第一反應(yīng)是“生態(tài)行不行算子支持全不全”我一開始也有同樣顧慮但實際跑完YOLOv5、YOLOv8之后態(tài)度變了不少。核心原因是推理場景和訓(xùn)練場景的訴求完全不同。訓(xùn)練追求通用性和動態(tài)計算推理追求穩(wěn)定吞吐量和低延遲這恰恰是Ascend平臺重點優(yōu)化的方向。昇騰的CANN工具鏈把模型轉(zhuǎn)換、離線推理、流式處理這些環(huán)節(jié)做成了標準流程而且對YOLO這種常見檢測網(wǎng)絡(luò)的支持非常成熟。從ONNX到om格式走ATC轉(zhuǎn)換器基本能一步到位。它不像很多NPU那樣處處是坑昇騰在公開文檔里對每個算子的支持和限制都列得很清楚遇到不支持的算子CANN也會很明確地報出來是哪個節(jié)點而不是讓整個程序“崩得莫名其妙”。另外一個實際考慮是功耗和成本。在數(shù)據(jù)中心里功耗就是成本。拿一張Atlas 300V 24G和一個同顯存的GPU比推理卡通常單位功耗下能處理的視頻路數(shù)更多長期跑7x24小時的電費差距會很明顯。再加上Atlas的板卡形態(tài)標準x86和鯤鵬服務(wù)器都能插部署靈活性很高。當然它的短板也明顯——你不能拿它做模型訓(xùn)練也不能想當然地認為所有PyTorch代碼都能原樣跑上去它需要先走完“模型轉(zhuǎn)換”這一關(guān)。這是選擇之前必須心里有數(shù)的事情。1.3 與常見GPU推理卡的對比對比項Atlas 300V 24GNVIDIA T4 16GNVIDIA RTX 3060 12G定位昇騰AI推理加速卡通用GPU推理卡消費級顯卡顯存/內(nèi)存24GB16GB12GB峰值算力INT8百TOPS級別INT8約65 TOPSINT8約101 TOPS非官方場景功耗約75W70W170W編程生態(tài)CANN / AscendCLCUDACUDA推理軟件配套MindX SDK、ATCTensorRT、TritonTensorRT可用但不推薦適合場景高密度視頻分析、多路檢測通用推理、虛擬化開發(fā)調(diào)試、低負載測試這個表不是讓你直接照著選而是說不同卡有不同脾氣。如果你手里已經(jīng)積累了成熟的PyTorch模型更追求快速上手那CUDA生態(tài)肯定順暢但如果你要撐住大規(guī)模并發(fā)推理比如幾十路視頻流同時做人臉識別或者車輛檢測Atlas這種專門為推理優(yōu)化的卡會有更穩(wěn)的性價比。我自己在項目里常把它和T4當成同一個預(yù)算里的替代方案來比較實際效果要看模型和輸入分辨率YOLOv5s這類輕量模型在Atlas上的表現(xiàn)尤其亮眼。2. 部署YOLO前的環(huán)境準備與工具鏈安裝2.1 昇騰軟件棧驅(qū)動、CANN、MindSpore之間的“輩分”關(guān)系部署Atlas最繞不開的是軟件棧我剛開始也被這些名詞繞暈過。簡單理一下底層是驅(qū)動和固件也就是讓操作系統(tǒng)能識別到這張PCIe卡中間層是CANN這是昇騰的計算架構(gòu)里面包含推理運行時、模型轉(zhuǎn)換工具ATC、算子庫、以及給開發(fā)者用的AscendCL推理接口再往上才是AI框架比如MindSpore、以及通過適配層接入的PyTorch等。你平時寫推理代碼直接打交道的其實是AscendCL或者MindX SDK。理解這層關(guān)系很重要。很多第一次上手的同學(xué)以為安裝一個Python包就能調(diào)用Atlas結(jié)果連連報錯原因往往是驅(qū)動沒裝或者CANN沒配對。驅(qū)動和CANN之間是有版本匹配要求的我建議統(tǒng)一去昇騰社區(qū)下載對應(yīng)硬件平臺的安裝包不要混著用。文檔里有一個“版本配套表”先查好再動手能省半天時間。記住一個原則驅(qū)動、固件、CANN是一套組合拳版本要盡量保持一致。在實際服務(wù)器上驅(qū)動安裝有兩種方式一種是用官方提供.run安裝包另一種是deb/rpm包。我所在的線上環(huán)境大多用的是Ubuntu Server所以通常走.run腳本安裝方便看安裝日志。安裝完成后最關(guān)鍵的一步是設(shè)置環(huán)境變量把/usr/local/Ascend/ascend-toolkit/set_env.sh寫到~/.bashrc里。如果不做這一步后面調(diào)用atc命令時會提示找不到命令排查半天才發(fā)現(xiàn)是環(huán)境變量問題這種小坑最容易浪費新人時間。2.2 在服務(wù)器上安裝驅(qū)動和CANN工具包下面給出一套可以“抄作業(yè)”的安裝流程前提是你已經(jīng)用一張Atlas 300V 24G插進服務(wù)器的PCIe槽位并且在BIOS里能識別到設(shè)備。操作系統(tǒng)建議Ubuntu 20.04或22.04內(nèi)核版本不要特意修改。安裝前先確認沒有舊驅(qū)動殘留卸載干凈再裝。# 1. 查看系統(tǒng)是否識別到昇騰設(shè)備 lspci | grep -i huawei # 2. 安裝驅(qū)動和固件版本號以官方包為準 ./Ascend-hdk-版本_linux-arch.run --full --install # 3. 安裝CANN工具包 ./Ascend-cann-toolkit_版本_linux-arch.run --install # 4. 設(shè)置環(huán)境變量 source /usr/local/Ascend/ascend-toolkit/set_env.sh echo source /usr/local/Ascend/ascend-toolkit/set_env.sh ~/.bashrc安裝過程中最應(yīng)該盯住的是結(jié)尾有沒有輸出[INFO] Install Successfully類似字樣。如果中間報錯多半是缺依賴或者內(nèi)核頭文件不對比如gcc、make、linux-headers-$(uname -r)沒裝。可以先apt install -y gcc make linux-headers-$(uname -r)再重跑安裝腳本。驅(qū)動裝完之后重啟服務(wù)器是比較保險的做法因為這個驅(qū)動在啟動階段就要加載內(nèi)核模塊。2.3 驗證環(huán)境是否真的就緒裝完不是就萬事大吉了建議先執(zhí)行一次npu-smi info命令看看能不能列出卡的信息。如果能正??吹紸tlas 300V 24G的名稱、芯片溫度、內(nèi)存占用說明驅(qū)動和固件基本沒問題了。這個命令類比NVIDIA的nvidia-smi是之后排查故障的第一工具。接下來驗證CANN是否可用最簡單的是跑一下官方自帶的樣例。在/usr/local/Ascend/ascend-toolkit/latest/目錄下通常會帶一些示例找一個人像分割或者目標檢測的樣例編譯運行一下。如果樣例能出結(jié)果就說明推理鏈路是通的之后你再把自己的YOLO模型替換進去會從容很多。我習(xí)慣在這步就把Python的acl接口驗證一遍因為后面寫推理腳本要用到Python的acl庫。如果導(dǎo)入報錯先查環(huán)境變量和Python路徑確保你是安裝在CANN對應(yīng)的那個Python解釋器環(huán)境里。3. 將YOLO模型轉(zhuǎn)換并部署到Atlas 300V 24G3.1 模型轉(zhuǎn)換為什么不能直接跑.pt很多人拿到Atlas后第一件事就是想把YOLOv5的.pt權(quán)重加載進來結(jié)果發(fā)現(xiàn)CANN根本不吃這一套。原因是昇騰推理引擎執(zhí)行的是離線編譯后的om模型而不是PyTorch的動態(tài)計算圖。PyTorch模型在前向推理時需要動態(tài)構(gòu)建算子執(zhí)行順序這在NPU上既慢又不穩(wěn)定而om模型在轉(zhuǎn)換階段就把算子排布、內(nèi)存分配、融合策略都確定了推理時只需要扣動扳機效率和確定性都高很多。所以部署YOLO的標準路徑是先把PyTorch模型導(dǎo)出成ONNX再通過昇騰ATC工具把ONNX轉(zhuǎn)換成om格式最后用AscendCL或MindX SDK加載om執(zhí)行推理。這里面最核心的就是“算子兼容性”和“輸入輸出格式對齊”。YOLOv5本身對ONNX導(dǎo)出很友好大部分算子都能落到昇騰的算子庫上少數(shù)不兼容的也都有替代方案后面我在問題排查章節(jié)展開聊。有人會問能不能直接用ONNX Runtime的昇騰EP技術(shù)上可以但性能一般。既然已經(jīng)投入了Atlas硬件還是建議老老實實走ATC生成om這樣能充分利用硬件融合優(yōu)化特別是在并發(fā)推理時用om模型可以明顯減少算子啟動開銷。我早期偷懶用ONNX Runtime跑過一版單路延遲勉強能看多路并發(fā)就開始飄了后來換成om模型才徹底穩(wěn)定下來。3.2 導(dǎo)出ONNX與AIPP預(yù)處理配置拿YOLOv5s舉例官方倉庫里自帶導(dǎo)出腳本命令如下python export.py --weights yolov5s.pt --include onnx --opset 11導(dǎo)出后得到一個yolov5s.onnx。這里要留意輸入節(jié)點名字。YOLOv5的輸入名一般是imagesshape是[1,3,640,640]如果是動態(tài)shape導(dǎo)出的可能是[1,3,-1,-1]。在ATC轉(zhuǎn)換時動態(tài)shape會讓后續(xù)內(nèi)存規(guī)劃變復(fù)雜所以我通常直接固定為[1,3,640,640]既減少轉(zhuǎn)換報錯概率也方便后續(xù)的并發(fā)優(yōu)化。接下來是AIPP配置。AIPP是Ascend的圖像預(yù)處理模塊可以把縮放、歸一化、通道轉(zhuǎn)換這些操作從CPU搬進NPU避免主機端頻繁做圖像處理拖后腿。YOLOv5訓(xùn)練時通常會把像素值除以255歸一化所以AIPP里需要做同樣的操作。下面這個配置是我常用的輸入RGB888圖像縮放后送進網(wǎng)絡(luò)aipp_op { aipp_mode: static input_format: RGB888_U8 src_image_size_w: 640 src_image_size_h: 640 csc_switch: true mean: 0.0 0.0 0.0 var_reci_norm: 0.00392156862 0.00392156862 0.00392156862 }var_reci_norm就是1/255的倒數(shù)承認方式昇騰文檔里叫法比較特殊領(lǐng)會意思就行。如果你的模型訓(xùn)練時用的是BGR順序還要配合rbuv_swap_switch做通道交換否則檢測框會出來但顏色語義錯亂。這個坑特別隱蔽因為模型仍然能出框只是分數(shù)低得離譜很容易誤判成精度問題。3.3 ATC轉(zhuǎn)換命令實戰(zhàn)準備好onnx和aipp.cfg之后就可以執(zhí)行ATC轉(zhuǎn)換。下面這條命令是我在昇騰310P平臺上驗證過的常見寫法soc_version要根據(jù)npu-smi info實際顯示型號來選擇常見的是Ascend310P3atc \ --modelyolov5s.onnx \ --framework5 \ --outputyolov5s_640 \ --input_shapeimages:1,3,640,640 \ --soc_versionAscend310P3 \ --insert_op_confaipp.cfg \ --output_typeFP32--framework5代表ONNX--output_typeFP32是我刻意加的。昇騰默認推理類型可能是FP16YOLO這種網(wǎng)絡(luò)對精度要求不太高但如果你是在小目標檢測上卡得很緊保留FP32能減少精度損失代價是推理速度略降。轉(zhuǎn)換成功后會在當前目錄生成yolov5s_640.om。如果報算子不支持可以先升級CANN版本或者把--opset降到11再試。轉(zhuǎn)換完成后啟動推理前可以先用omg自帶的內(nèi)存分析和性能分析工具過一下看看模型推理時間預(yù)估是多少。這一步不是必須但能讓你對這張卡跑這個模型的心理預(yù)期有個數(shù)。我自己習(xí)慣記錄轉(zhuǎn)換時的日志輸出特別關(guān)注Op is optimized或fusion相關(guān)信息這些是判斷模型有沒有充分調(diào)優(yōu)的線索。3.4 編寫AscendCL推理代碼有了om模型接下來就是寫推理代碼。這里給一個Python版的極簡框架主要想讓你看到整體流程實際項目里還要補上圖像讀取、縮放、坐標還原和NMS邏輯。import acl import numpy as np # 初始化 acl.init() ret acl.rt.set_device(0) # 加載模型 model_id acl.mdl.load_from_file(yolov5s_640.om) # 創(chuàng)建模型描述 desc acl.mdl.create_desc() acl.mdl.get_desc(desc, model_id) # 申請輸入輸出內(nèi)存 input_size acl.mdl.get_input_size_by_index(desc, 0) output_size acl.mdl.get_output_size_by_index(desc, 0) input_data, input_ptr acl.rt.malloc(input_size, 2) output_data, output_ptr acl.rt.malloc(output_size, 2) # 假設(shè)已經(jīng)將一張640x640的RGB圖轉(zhuǎn)為np.float32并歸一化 input_numpy np.random.randn(1, 3, 640, 640).astype(np.float32) acl.rt.memcpy(input_ptr, input_size, input_numpy.tobytes(), input_size, 1) # 創(chuàng)建輸出數(shù)據(jù)集 output_dataset acl.mdl.create_dataset() output_buffer acl.create_data_buffer(output_ptr, output_size) acl.mdl.add_dataset_buffer(output_dataset, output_buffer) # 執(zhí)行推理 acl.mdl.execute(model_id, input_dataset, output_dataset) # 將輸出拷回numpy acl.rt.memcpy(output_numpy.tobytes(), output_size, output_ptr, output_size, 2) # 后處理解析25200個預(yù)測框做NMS代碼里面每一步都有對應(yīng)的“釋放”動作比如acl.rt.free和acl.finalize我這里為了簡潔沒全寫。真正跑到生產(chǎn)環(huán)境時建議用一個類把模型加載、推理、資源釋放封裝好。你還會注意到我沒有寫輸入創(chuàng)建細節(jié)因為不同CANN版本接口略有差異寫的時候以官方pyACL示例為準會有更好的解釋。3.5 性能調(diào)優(yōu)從單路到多路并發(fā)模型能跑通只是第一步實際業(yè)務(wù)里都要面對“一路視頻還是幾十路視頻”的問題。Atlas 300V 24G的24GB內(nèi)存為多路并發(fā)提供了基礎(chǔ)但更重要的是代碼組織方式。最簡單的提升方式是batch推理把多幀圖像拼成一個batch一次送進去比循環(huán)單幀推理效率高得多。我常規(guī)會先測試batch1、2、4、8的耗時畫一條曲線找到延遲和吞吐量的平衡點。batch單幀平均延遲吞吐量112ms83 FPS49ms111 FPS88ms125 FPS1610ms160 FPS上面是我跑YOLOv5s時的典型數(shù)據(jù)不同模型和輸入分辨率會讓數(shù)字變化。注意延遲不是嚴格線性下降因為拷貝和同步也有開銷所以不要盲目堆batch。另一個技巧是開啟AscendCL的異步推理讓圖像預(yù)處理和上一次推理并行這樣能隱藏CPU和NPU之間的傳輸時間。自我調(diào)優(yōu)時最好先排除顯存瓶頸再優(yōu)化算子融合最后再考慮線程和隊列。4. 踩坑實錄與常見問題排查4.1 驅(qū)動裝不上或設(shè)備識別不到這類問題我遇到最多而且很多是細節(jié)導(dǎo)致。插卡后lspci看不到設(shè)備先檢查卡有沒有插牢、PCIe供電是否到位。如果lspci能看到設(shè)備但npu-smi info報錯大概率是驅(qū)動和固件沒配對或者內(nèi)核模塊沒加載成功??梢詧?zhí)行dmesg | grep -i ascend看看內(nèi)核日志很多報錯線索都在這里。還有一次遇到安裝驅(qū)動時報“Toolkit is not supported by the driver version”才意識到我用的CANN版本比較新但驅(qū)動還是老版本。解決方式就是嚴格按照官方的版本配套表做“降級”或“升級”。千萬不要用最新版驅(qū)動配最新版CANN就指望沒問題版本配套表上寫清楚的組合才是最穩(wěn)的。建議把驅(qū)動安裝包的日志留存排查時能省不少力氣。4.2 模型轉(zhuǎn)換時算子報錯ATC轉(zhuǎn)換是另一個高頻翻車點。報錯信息一般是某個onnx節(jié)點找不到對應(yīng)實現(xiàn)比如NonMaxSuppression在某些CANN版本上不支持。解決思路有兩個第一升級CANN算子庫會不斷補齊第二修改模型導(dǎo)出方式把后處理里的NMS留在CPU端不導(dǎo)出到ONNX。YOLOv5默認導(dǎo)出時后處理是留在PyTorch層的所以轉(zhuǎn)換成ONNX時通常只包含主干和檢測頭NMS是沒包含的因此這個報錯出現(xiàn)頻率不高。更常見的報錯是動態(tài)shape相關(guān)[1,3,-1,-1]不接收或者--input_shape寫錯導(dǎo)致維度不匹配。我的建議是導(dǎo)出ONNX時就用固定shape千萬別貪圖動態(tài)分辨率方便。Atlas推理卡定位是服務(wù)端批量推理固定shape能幫你把內(nèi)存、算力都吃到最穩(wěn)。真的需要多分辨率可以做多個om模型按需切換也不失為一種簡單可靠的辦法。4.3 檢測完全無輸出或結(jié)果不對模型轉(zhuǎn)換成功、推理也成功但輸出的框是空的這種問題有時比報錯更讓人頭疼。先檢查AIPP配置里邊的csc_switch和rbuv_swap_switch通道順序錯了就會丟目標。再檢查輸入圖像有沒有正確歸一化。如果AIPP里做了歸一化主機代碼就不要再歸一化一次否則等于把像素縮了兩遍模型看到的全是黑圖。還有一種情況是后處理坐標還原沒有做好。YOLO輸出的坐標是相對于640x640輸入圖像的如果你的原始圖像是1920x1080必須按縮放比例映射回去否則框會落在完全錯誤的位置。很多看起來“沒檢測出來”的問題其實是框畫偏了畫到了畫面外導(dǎo)致你感覺沒有輸出。我習(xí)慣在接項目時先打印原始輸出矩陣的幾個值確認網(wǎng)絡(luò)輸出分布是否正常再判斷是不是后處理問題。4.4 關(guān)于Atlas 300V 24G的常見疑問與經(jīng)驗小抄再回到開頭的哪個問題“Atlas 300V 24G 是運算加速卡嗎”是的它是運算加速卡而且是為AI推理量身定做的。它不是顯卡不能取代GPU做圖形渲染也不是訓(xùn)練卡不建議拿它做大規(guī)模訓(xùn)練。它最適合的場景就是成熟模型的批量推理尤其是YOLO這類的目標檢測模型。如果你在公開文檔里看到類似Atlas 300V Pro 24G的說法不要緊張嚴格說24G版本通常是Pro版本質(zhì)還是一樣的昇騰310P可靠序列。最后分享幾條我裝了這么多遍環(huán)境后的個人體會第一嚴格按版本配套表安裝不要自作聰明地混版本第二推理代碼里一定要做好資源釋放長時間運行的進程如果只申請不釋放24GB內(nèi)存終究會滿第三性能調(diào)優(yōu)前先確定你自己的瓶頸在哪是CPU圖像解碼還是模型計算還是后處理NMS不要一上來就優(yōu)化模型轉(zhuǎn)換參數(shù)。Atlas 300V 24G是一張很安靜的卡但它也有自己的脾氣跟它打交道耐心讀日志、尊重生態(tài)規(guī)則它就能穩(wěn)定地陪你跑很久很久。