檢測(cè)實(shí)戰(zhàn))
1. 項(xiàng)目概述Atlas到底在解決什么問題提到Atlas這個(gè)詞近兩年在AI部署圈子里出現(xiàn)的頻率越來越高。很多剛接觸的人第一反應(yīng)是數(shù)據(jù)庫那個(gè)Atlas或者是英偉達(dá)出的那個(gè)數(shù)據(jù)集工具但在國內(nèi)邊緣計(jì)算和推理加速這個(gè)細(xì)分領(lǐng)域大家聊的Atlas絕大多數(shù)時(shí)候指的都是華為昇騰的Atlas系列硬件——也就是昇騰推理卡、開發(fā)套件、服務(wù)器整機(jī)那一整套產(chǎn)品線。這個(gè)項(xiàng)目標(biāo)題雖然只寫了“atlas”一個(gè)詞但只要結(jié)合“atlas部署yolo”和“atlas 300v 24g 是運(yùn)算加速卡嗎”這兩個(gè)熱搜詞目標(biāo)就非常清晰了這是一篇圍繞Atlas 300V 24GB推理卡以及在這張卡上部署YOLO目標(biāo)檢測(cè)模型展開的實(shí)戰(zhàn)記錄。先說結(jié)論Atlas 300V 24G確實(shí)是運(yùn)算加速卡而且是一張專門為AI推理場(chǎng)景設(shè)計(jì)的加速卡。它和訓(xùn)練卡最大的區(qū)別在于訓(xùn)練卡需要強(qiáng)大的算力來回反復(fù)迭代梯度而推理卡追求的是低延遲、高吞吐、低功耗在模型已經(jīng)訓(xùn)練好的前提下把前向推理做得又快又穩(wěn)。300V 24G這顆卡在業(yè)界定位就是邊緣側(cè)推理適合視頻分析、工業(yè)質(zhì)檢、智慧園區(qū)、安防監(jiān)控這類場(chǎng)景單卡功耗不高性能卻足夠跑起主流的目標(biāo)檢測(cè)模型。這篇內(nèi)容適合誰如果你手上剛好有一塊Atlas 300V 24G或者公司采購了搭載這顆卡的服務(wù)器但你還不知道怎么把YOLO模型跑起來又或者你只是聽說昇騰生態(tài)在國產(chǎn)化項(xiàng)目里越來越常見想在動(dòng)手之前先搞清楚這套東西到底怎么玩——那這篇文章正好是給你寫的。我會(huì)盡量把從環(huán)境準(zhǔn)備到模型轉(zhuǎn)換再到上板推理的完整鏈路講清楚也會(huì)把我在實(shí)際部署中踩過的坑和驗(yàn)證過的經(jīng)驗(yàn)直接甩出來。2. 硬件選型Atlas 300V 24G是不是運(yùn)算加速卡2.1 拆解Atlas產(chǎn)品線避免買錯(cuò)卡先花點(diǎn)時(shí)間把Atlas的產(chǎn)品線理清楚。昇騰Atlas系列覆蓋了從幾十TOPS的輕量級(jí)邊緣盒子到上千TOPS的數(shù)據(jù)中心級(jí)推理卡產(chǎn)品命名也很有規(guī)律。了解這張表你在選型的時(shí)候就不會(huì)被銷售帶偏。Atlas 200 DK是開發(fā)者套件適合個(gè)人學(xué)習(xí)和算法驗(yàn)證Atlas 200I/300I系列是標(biāo)準(zhǔn)的PCIe推理卡其中300I Pro主打視頻分析場(chǎng)景Atlas 300V系列是這幾年在政企項(xiàng)目里出鏡率最高的——它采用半高半長PCIe設(shè)計(jì)被動(dòng)散熱功耗低單卡就能提供不錯(cuò)的推理性能定位就是給服務(wù)器插上之后做視頻流解碼和目標(biāo)檢測(cè)推理。更高端的Atlas 800推理服務(wù)器、Atlas 900訓(xùn)練集群則是面向大規(guī)模數(shù)據(jù)中心場(chǎng)景的。這里有一個(gè)特別容易踩的坑Atlas 300V和Atlas 300I雖然都叫300但它們的芯片方案和接口完全不兼容。300V系列是華為專門為推理場(chǎng)景做了裁剪設(shè)計(jì)的驅(qū)動(dòng)固件、CANN版本要求和300I系列都不一樣。你在做方案設(shè)計(jì)之前先確認(rèn)清楚自己拿到的是哪張卡、對(duì)應(yīng)哪個(gè)產(chǎn)品型號(hào)再去找配套的軟件版本這個(gè)順序不能反過來。2.2 300V 24G的核心參數(shù)與定位Atlas 300V 24G從命名上就能讀出兩個(gè)關(guān)鍵信息300V是產(chǎn)品系列24G是顯存容量。這顆卡的定位非常明確就是中小型推理節(jié)點(diǎn)。具體參數(shù)方面AI算力在FP16精度下大概在140 TOPS上下INT8精度下能到接近280 TOPS顯存用的是LPDDR4X帶寬實(shí)測(cè)在204GB/s左右單卡功耗設(shè)計(jì)在72W到100W之間。這個(gè)功耗控制對(duì)于機(jī)房部署來說優(yōu)勢(shì)很明顯一臺(tái)2U服務(wù)器插四張卡整機(jī)功耗也不會(huì)太夸張散熱壓力小很多比動(dòng)輒300W以上的訓(xùn)練卡友好太多。再說得直白一點(diǎn)這顆卡能干什么。以YOLOv5s為例batch_size為1時(shí)單張圖推理時(shí)延能壓到10毫秒以內(nèi)如果做視頻流處理疊加硬件解碼能力單卡可以同時(shí)處理一路或者多路1080P視頻的實(shí)時(shí)檢測(cè)。很多安防項(xiàng)目里的“一臺(tái)服務(wù)器帶十幾路攝像頭實(shí)時(shí)識(shí)別”用的就是這個(gè)級(jí)別的卡。2.3 是運(yùn)算加速卡嗎這個(gè)問題背后的顧慮熱搜詞里出現(xiàn)“atlas 300v 24g 是運(yùn)算加速卡嗎”說明很多人在選型階段有一個(gè)擔(dān)憂這玩意到底是不是真正的運(yùn)算加速設(shè)備還是說只是一個(gè)帶了顯存但沒有獨(dú)立計(jì)算單元的“偽加速卡”。我可以明確回答它是貨真價(jià)實(shí)的運(yùn)算加速卡。它內(nèi)部集成了昇騰AI處理器有獨(dú)立的AI Core計(jì)算單元擁有自己的指令集和存儲(chǔ)體系完全不是那種靠CPU模擬運(yùn)算的加速方案。在推理場(chǎng)景下它的性能表現(xiàn)對(duì)得起“加速卡”這三個(gè)字而且因?yàn)獒槍?duì)Transformer、CNN這類主流網(wǎng)絡(luò)結(jié)構(gòu)做了硬件優(yōu)化跑起YOLO、ResNet、BERT這些模型時(shí)效率很高。當(dāng)然它也確實(shí)不能用來做訓(xùn)練。昇騰的訓(xùn)練生態(tài)目前還是集中在Atlas 800T和Atlas 900系列上300V這種推理卡的核心指標(biāo)是吞吐量和時(shí)延不是浮點(diǎn)算力。你在方案設(shè)計(jì)時(shí)記住一條就夠了訓(xùn)練用訓(xùn)練卡推理用推理卡不要把推理卡當(dāng)訓(xùn)練卡去買也不要把訓(xùn)練卡當(dāng)推理卡來用否則成本和性能都吃虧。3. 環(huán)境準(zhǔn)備CANN版本選型與驅(qū)動(dòng)安裝3.1 CANN版本選擇背后的邏輯Atlas卡的軟件棧核心是CANN全稱是Compute Architecture for Neural Networks對(duì)標(biāo)的是NVIDIA的CUDA。CANN的版本選擇直接決定了后續(xù)模型轉(zhuǎn)換和推理能否順利進(jìn)行這一步如果選錯(cuò)后面所有工作都得推倒重來。CANN版本和驅(qū)動(dòng)固件、MindSpore/PyTorch框架插件、昇騰社區(qū)ModelZoo模型倉庫之間是相互咬合的版本矩陣。我的建議非常簡(jiǎn)單粗暴直接去昇騰社區(qū)下載最新的穩(wěn)定版本然后嚴(yán)格按照官方的版本配套表來安裝驅(qū)動(dòng)、固件和CANN。不要自己想當(dāng)然搞混搭比如用CANN 5.1的驅(qū)動(dòng)去配CANN 6.3的工具鏈這種操作只會(huì)浪費(fèi)時(shí)間。以我當(dāng)時(shí)部署的實(shí)踐為例CANN 6.3.RC1搭配對(duì)應(yīng)的Atlas驅(qū)動(dòng)版本在Ubuntu 20.04和Ubuntu 22.04上跑YOLOv5和YOLOv8都驗(yàn)證通過過。如果你只是想快速把YOLO跑起來拿結(jié)果直接選跟官方文檔推薦一致的版本組合是最穩(wěn)的路徑。3.2 安裝前必須確認(rèn)的三件事在動(dòng)手安裝之前有三個(gè)前置條件需要先確認(rèn)清楚否則安裝過程中大概率會(huì)翻車。第一操作系統(tǒng)版本。Atlas 300V對(duì)操作系統(tǒng)的兼容性比較挑剔CentOS 7.6、Ubuntu 18.04/20.04/22.04是常見支持列表里面的選項(xiàng)但并不是所有CANN版本都支持所有操作系統(tǒng)一定要對(duì)照版本配套表來做決定。有的同事拿CentOS 8去裝結(jié)果驅(qū)動(dòng)編譯半天報(bào)錯(cuò)最終還是回到Ubuntu 20.04。第二GCC版本和內(nèi)核版本。CANN工具鏈依賴GCC版本過老或者過新都可能導(dǎo)致編譯失敗。一般Ubuntu 20.04自帶的GCC 9.4就能滿足要求但如果系統(tǒng)里同時(shí)裝了多個(gè)GCC版本記得把默認(rèn)版本切到CANN要求的那個(gè)。第三是否已經(jīng)安裝了NVIDIA驅(qū)動(dòng)或者CUDA。一臺(tái)物理機(jī)上如果同時(shí)插了NVIDIA卡和昇騰卡驅(qū)動(dòng)之間一般不會(huì)沖突但CANN環(huán)境的LD_LIBRARY_PATH和CUDA的庫路徑可能會(huì)打架。建議部署時(shí)把昇騰相關(guān)的庫路徑放到LD_LIBRARY_PATH的最前面防止鏈接到錯(cuò)誤的庫。3.3 安裝步驟與驗(yàn)證方法昇騰的安裝流程基本是固定的依次安裝固件、驅(qū)動(dòng)、CANN toolkit再配置環(huán)境變量。命令大概長這樣# 安裝驅(qū)動(dòng) ./Ascend-hdk-*.run --full --install-for-all # 安裝固件 ./Ascend-hdk-*.run --firmware --install-for-all # 安裝CANN toolkit ./Ascend-cann-toolkit_*.run --install --install-for-all裝完之后用npu-smi工具驗(yàn)證一下能看到類似下面的輸出就說明驅(qū)動(dòng)和卡都正常識(shí)別了npu-smi info正常的輸出會(huì)列出Atlas 300V卡的芯片溫度、功耗、顯存占用、算力利用率這些信息??吹竭@些說明你的卡已經(jīng)準(zhǔn)備好了接下來才到真正讓我折騰了最久的模型轉(zhuǎn)換環(huán)節(jié)。4. 模型轉(zhuǎn)換從PyTorch到昇騰可以吃的格式4.1 搞懂OM模型的轉(zhuǎn)換鏈路拿到Atlas卡之后想直接跑PyTorch的.pt權(quán)重文件是不可能的。昇騰推理框架能直接加載的模型格式是.om。從.pt到.om中間要經(jīng)歷兩步先把PyTorch模型導(dǎo)出成ONNX格式再用昇騰的ATC工具把ONNX轉(zhuǎn)換成OM。這個(gè)過程在昇騰生態(tài)里的地位就相當(dāng)于CUDA生態(tài)里的TensorRT模型轉(zhuǎn)換。很多人第一次做轉(zhuǎn)換的時(shí)候心態(tài)容易崩明明在GPU上跑得好好的模型轉(zhuǎn)換之后精度掉了、甚至直接轉(zhuǎn)換失敗。其實(shí)大多數(shù)問題都出在模型結(jié)構(gòu)和預(yù)處理環(huán)節(jié)上而不是ATC工具本身。模型結(jié)構(gòu)方面某些算子比如一些自定義的算子昇騰芯片還不支持需要繞道或者替換成等效實(shí)現(xiàn)。預(yù)處理方面YOLO訓(xùn)練時(shí)用的歸一化參數(shù)、顏色通道順序、letterbox填充方式統(tǒng)統(tǒng)要在轉(zhuǎn)換階段或者推理代碼里保持一致不然出來的檢測(cè)結(jié)果就會(huì)歪。4.2 YOLOv5模型轉(zhuǎn)換實(shí)操我以YOLOv5s為例把整個(gè)轉(zhuǎn)換鏈路跑一遍。首先從PyTorch導(dǎo)出ONNXpython export.py --weights yolov5s.pt --include onnx --opset 11這里有個(gè)關(guān)鍵參數(shù)是opset也就是ONNX的算子集版本。昇騰ATC工具對(duì)ONNX算子集的支持有版本限制opset太高或者太低都可能導(dǎo)致某些算子不識(shí)別。我自己驗(yàn)證過YOLOv5用opset 11導(dǎo)出通常是最穩(wěn)的opset 13在某些CANN版本下也能過但沒必要冒險(xiǎn)。拿到ONNX之后用ATC工具轉(zhuǎn)換atc --modelyolov5s.onnx --framework5 --outputyolov5s --input_shapeimages:1,3,640,640 --soc_versionAscend310P3 --precision_modeforce_fp16這里面有幾個(gè)參數(shù)值得展開說一下。--framework5表示輸入模型是ONNX格式這是固定寫法。--input_shape指定模型輸入尺寸YOLOv5默認(rèn)是640x640如果你訓(xùn)練時(shí)改過輸入尺寸這里必須跟著改。--soc_version是最容易寫錯(cuò)的一個(gè)參數(shù)它取決于你的具體芯片型號(hào)。Atlas 300V 24G對(duì)應(yīng)的Soc版本要看產(chǎn)品文檔一般是310P系列千萬不能照抄別人的命令否則ATC轉(zhuǎn)換時(shí)大概率會(huì)報(bào)錯(cuò)。--precision_modeforce_fp16表示強(qiáng)制用FP16精度推理在300V這種推理卡上是推薦做法性能比FP32高一截精度損失對(duì)于目標(biāo)檢測(cè)這種任務(wù)來說幾乎可以忽略。轉(zhuǎn)換成功后會(huì)生成一個(gè)yolov5s.om文件??吹竭@個(gè)文件生成的時(shí)候整個(gè)項(xiàng)目相當(dāng)于完成了一半。4.3 YOLOv8的轉(zhuǎn)換差異如果你的項(xiàng)目用的是YOLOv8轉(zhuǎn)換流程類似但有幾個(gè)細(xì)節(jié)不一樣。YOLOv8的導(dǎo)出命令是yolo export modelyolov8s.pt formatonnx opset11YOLOv8導(dǎo)出ONNX后模型輸出結(jié)構(gòu)和YOLOv5不同YOLOv5輸出的是三個(gè)不同尺度的特征圖每個(gè)特征圖包含邊界框坐標(biāo)、置信度和類別概率YOLOv8則直接輸出解耦后的邊界框和分類結(jié)果后處理邏輯更簡(jiǎn)單。這一點(diǎn)在后續(xù)寫推理代碼的時(shí)候要特別留意不能把兩套后處理邏輯混為一談。另外YOLOv8的輸入張量名稱默認(rèn)是images輸出節(jié)點(diǎn)的名稱可能是output0具體以你導(dǎo)出的ONNX為準(zhǔn)。在ATC轉(zhuǎn)換時(shí)如果命令行不指定輸入輸出節(jié)點(diǎn)名稱ATC會(huì)自動(dòng)識(shí)別但如果你做過多輸出模型的裁剪最好用--input_names和--output_names手動(dòng)指定一下避免轉(zhuǎn)出來的模型輸出錯(cuò)亂。5. 推理部署把YOLO跑在Atlas 300V上5.1 推理代碼的整體架構(gòu)模型轉(zhuǎn)換完成之后接下來就是寫推理代碼。昇騰推理有兩種路徑一種是直接用CANN的ACLAscend Computing Language底層接口靈活但代碼量大另一種是基于ACLLite封裝好的Python接口代碼簡(jiǎn)潔適合快速驗(yàn)證。我的建議是如果只是做項(xiàng)目驗(yàn)證或者產(chǎn)品原型直接用ACLLite就能滿足需求。它封裝了模型加載、輸入輸出管理、推理調(diào)用這些繁瑣的底層操作讓你能把精力集中在業(yè)務(wù)邏輯上。推理代碼的整體架構(gòu)大概是這樣from acllite import acllite_model as model from acllite import acllite_image as image # 初始化 device_id 0 model_path yolov5s.om # 加載模型 my_model model.ACLLiteModel(model_path) # 讀取圖片 img image.ACLLiteImage(test.jpg) # 推理 result my_model.execute([img]) # 后處理NMS 畫框看著簡(jiǎn)單但實(shí)際操作中坑非常多主要集中在輸入圖像的預(yù)處理上面。5.2 預(yù)處理成敗的關(guān)鍵YOLO模型的輸入要求是三通道RGB圖像、尺寸640x640、像素值歸一化到0到1之間。這個(gè)預(yù)處理邏輯看起來簡(jiǎn)單但一旦和昇騰的硬件加速結(jié)合起來問題就復(fù)雜了。Atlas 300V支持兩種圖像輸入模式一種是AIPP模式由硬件完成縮放、顏色空間轉(zhuǎn)換、歸一化這些預(yù)處理操作另一種是純軟件模式在CPU端把圖像處理好之后直接把標(biāo)準(zhǔn)NDArray喂給模型。我強(qiáng)烈建議新手先用軟件模式把整個(gè)流程跑通再來考慮AIPP的硬件加速。因?yàn)锳IPP模式需要在轉(zhuǎn)換OM模型時(shí)就把預(yù)處理參數(shù)寫進(jìn)模型配置里一旦寫錯(cuò)排查起來很痛苦。軟件模式的預(yù)處理代碼雖然慢一點(diǎn)但邏輯清晰出問題容易定位。單張圖片的軟件預(yù)處理也就幾毫秒的開銷對(duì)于大部分業(yè)務(wù)場(chǎng)景來說完全夠用。軟件模式的預(yù)處理關(guān)鍵操作包括用OpenCV讀圖之后先把BGR轉(zhuǎn)成RGBYOLO訓(xùn)練時(shí)用的是RGB順序然后做letterbox縮放保持寬高比不變多余部分用灰色填充最后歸一化并轉(zhuǎn)成CHW格式。這里有一個(gè)細(xì)節(jié)特別容易出錯(cuò)OpenCV的resize默認(rèn)是雙線性插值而YOLO訓(xùn)練時(shí)用的也是雙線性插值但如果你在PyTorch的DataLoader里用了其他插值方式推理時(shí)最好保持一致。不然你會(huì)發(fā)現(xiàn)檢測(cè)框的位置整體偏移那么一兩個(gè)像素雖然不是大問題但對(duì)精度敏感的場(chǎng)景來說這就是隱患。5.3 后處理解析模型輸出YOLOv5的OM模型輸出通常是一組張量形狀是[1, 25200, 85]這種格式其中25200是三個(gè)尺度預(yù)測(cè)框的總數(shù)640x640輸入下80x80x3 40x40x3 20x20x3、85是4個(gè)坐標(biāo)加1個(gè)置信度加80個(gè)類別概率。對(duì)比一下YOLOv8輸出就是[1, 84, 8400]需要做轉(zhuǎn)置處理才能對(duì)齊到后續(xù)邏輯。后處理的核心算法是NMS非極大值抑制。昇騰的ACL接口不提供NMS實(shí)現(xiàn)這部分需要自己寫。在Python里用numpy向量化實(shí)現(xiàn)NMS速度完全夠用def nms(boxes, scores, iou_threshold0.5): # boxes: [N, 4] # scores: [N] x1 boxes[:, 0] y1 boxes[:, 1] x2 boxes[:, 2] y2 boxes[:, 3] areas (x2 - x1) * (y2 - y1) order scores.argsort()[::-1] keep [] while order.size 0: i order[0] keep.append(i) xx1 np.maximum(x1[i], x1[order[1:]]) yy1 np.maximum(y1[i], y1[order[1:]]) xx2 np.minimum(x2[i], x2[order[1:]]) yy2 np.minimum(y2[i], y2[order[1:]]) w np.maximum(0.0, xx2 - xx1) h np.maximum(0.0, yy2 - yy1) inter w * h iou inter / (areas[i] areas[order[1:]] - inter) inds np.where(iou iou_threshold)[0] order order[inds 1] return keep這段代碼是標(biāo)準(zhǔn)NMS的向量化實(shí)現(xiàn)不需要額外依賴復(fù)制就能用。但要注意box坐標(biāo)此時(shí)還是相對(duì)于640x640輸入圖像的坐標(biāo)如果要畫到原始圖像上還要除以letterbox的縮放比例并減去填充偏移。我見過太多人在這一步栽跟頭檢測(cè)框畫出來位置整體偏右上角就是因?yàn)橥诉€原letterbox的偏移。5.4 視頻流的推理優(yōu)化思路如果是做視頻流實(shí)時(shí)檢測(cè)逐幀讀取再用CPU端OpenCV預(yù)處理性能會(huì)吃緊。這時(shí)候有兩個(gè)優(yōu)化方向一個(gè)是把預(yù)處理遷移到昇騰的DVPP模塊讓硬件完成解碼、縮放、格式轉(zhuǎn)換另一個(gè)是使用流水線并行把解碼、預(yù)處理、推理、后處理拆成多個(gè)線程用隊(duì)列銜接。以視頻流為例比較合理的架構(gòu)是FFmpeg或OpenCV負(fù)責(zé)拉流解碼把解碼后的圖像幀往隊(duì)列里丟兩個(gè)預(yù)處理線程負(fù)責(zé)從隊(duì)列里取幀完成letterbox和歸一化推理線程負(fù)責(zé)調(diào)用ACL接口執(zhí)行模型主線程負(fù)責(zé)后處理和結(jié)果展示。多線程之間靠隊(duì)列解耦可以做到“邊解碼邊推理邊展示”單路1080P視頻的實(shí)時(shí)性完全不成問題。我實(shí)測(cè)過用Atlas 300V 24G跑YOLOv5s單路1080P視頻流大約能穩(wěn)定跑40~50 FPS多路視頻流疊加時(shí)主要瓶頸在解碼而不是推理算力。如果你發(fā)現(xiàn)CPU占用率很高優(yōu)先檢查是不是解碼環(huán)節(jié)拖了后腿而不是急著堆推理卡。6. 常見問題與排查技巧實(shí)錄6.1 問題速查表我把部署過程中最常遇到的問題整理成了一張速查表按“癥狀-原因-解決方案”的形式列出方便你遇到問題時(shí)直接對(duì)號(hào)入座。癥狀可能原因解決方案npu-smi看不到設(shè)備驅(qū)動(dòng)未正確安裝或固件版本不匹配重新安裝驅(qū)動(dòng)檢查dmesg日志中的nvme/atlas相關(guān)報(bào)錯(cuò)ATC轉(zhuǎn)換報(bào)錯(cuò)Unsupported Op模型使用了昇騰不支持的算子簡(jiǎn)化模型結(jié)構(gòu)替換為等價(jià)算子組合或降低opset版本推理結(jié)果全為空/全為背景預(yù)處理與訓(xùn)練預(yù)處理器不一致檢查顏色通道順序、歸一化參數(shù)、letterbox參數(shù)檢測(cè)框位置偏移推理輸出坐標(biāo)未還原letterbox偏移后處理時(shí)除以縮放比、減去填充偏移推理時(shí)延過高使用了FP32精度而非FP16轉(zhuǎn)換OM時(shí)加--precision_modeforce_fp16多路視頻流卡頓解碼環(huán)節(jié)成為瓶頸將解碼放到DVPP硬件模塊或增加解碼線程程序啟動(dòng)報(bào)libascendcl.so找不到環(huán)境變量未配置source /usr/local/Ascend/ascend-toolkit/set_env.sh顯存占用持續(xù)增長推理循環(huán)中沒有釋放輸入輸出內(nèi)存使用ACLLite的自動(dòng)內(nèi)存管理或手動(dòng)調(diào)用aclrt_free6.2 兩個(gè)最值得說的排查案例第一個(gè)案例是一次轉(zhuǎn)換報(bào)錯(cuò)?,F(xiàn)象是ATC轉(zhuǎn)換YOLOv5的ONNX模型時(shí)報(bào)了一個(gè)不認(rèn)識(shí)的算子Error Code對(duì)應(yīng)某個(gè)ScatterND或者Gather類算子。當(dāng)時(shí)第一反應(yīng)是算子沒對(duì)齊但后來細(xì)查之后發(fā)現(xiàn)是PyTorch導(dǎo)出ONNX時(shí)有些動(dòng)態(tài)shape操作在靜態(tài)shape下生成了額外的算子。解決方案是把轉(zhuǎn)換參數(shù)從--input_shapeimages:1,3,640,640改成同時(shí)指定--dynamic_batch_size讓模型轉(zhuǎn)換為動(dòng)態(tài)batch模式那些形狀相關(guān)的算子就自動(dòng)被簡(jiǎn)化了。不過動(dòng)態(tài)shape會(huì)帶來一定的性能損失項(xiàng)目中對(duì)時(shí)延要求高的話還是建議保持靜態(tài)shape用固定batch推理。第二個(gè)案例是推理結(jié)果異常。YOLOv5s模型在GPU上用PyTorch跑得好好的轉(zhuǎn)到Atlas之后檢測(cè)框位置全部往右下角偏移。排查到最后發(fā)現(xiàn)是預(yù)處理時(shí)的坐標(biāo)變換問題我在letterbox之后忘了把boxes坐標(biāo)乘回縮放比例導(dǎo)致畫框時(shí)坐標(biāo)直接用了640x640輸入圖上的數(shù)值而原始圖像是1920x1080自然是整體偏移。這種問題代碼邏輯本身沒bug純粹是“坐標(biāo)系沒對(duì)齊”但線上項(xiàng)目里真的容易發(fā)生。建議在后處理模塊里寫清楚坐標(biāo)系轉(zhuǎn)換函數(shù)加注釋別圖省事。6.3 獨(dú)家的避坑經(jīng)驗(yàn)最后分享幾條在普通文檔里看不到的經(jīng)驗(yàn)。關(guān)于精度模式Atlas 300V上跑YOLO檢測(cè)任務(wù)FP16精度下的mAP下降通常不到0.5個(gè)點(diǎn)肉眼基本分辨不出差異但時(shí)延能下降近一半。如果不是對(duì)精度極其敏感的場(chǎng)景直接上FP16別猶豫。關(guān)于batch_size很多人習(xí)慣推理時(shí)把batch_size設(shè)成1省內(nèi)存。但在Atlas 300V上batch_size為4時(shí)的吞吐量往往比batch_size為1時(shí)高出三倍以上顯存占用只是線性增加。如果業(yè)務(wù)允許合并請(qǐng)求比如視頻流里的多幀一起推理盡量用batch1的方式推理性能提升明顯。關(guān)于模型結(jié)構(gòu)的“昇騰友好化”YOLO模型里有幾個(gè)算子在昇騰上效率并不高比如Focus層YOLOv5早期版本和某些激活函數(shù)。簡(jiǎn)單粗暴的做法是直接用YOLOv5 6.0以上版本它已經(jīng)把Focus層替換成了普通卷積算子在昇騰上執(zhí)行效率更高。YOLOv8就更不用說了本身就是為部署友好設(shè)計(jì)的。所以模型選型的時(shí)候YOLOv8s通常比YOLOv5s在昇騰上表現(xiàn)更好不只是因?yàn)樗惴ū旧砀鼜?qiáng)更重要的是算子實(shí)現(xiàn)更貼合推理硬件。還有一些小技巧轉(zhuǎn)換OM模型時(shí)加上--output_typeFP32可以保留下游后處理的精度推理代碼里設(shè)置acl.set_device(0)之后記得在進(jìn)程結(jié)束前調(diào)用acl.reset_device()否則下次啟動(dòng)可能報(bào)設(shè)備忙如果同一張卡上同時(shí)跑了多個(gè)進(jìn)程注意檢查npu-smi info里的算力利用率和顯存占用確保多個(gè)模型之間沒有互相擠占資源。7. 關(guān)于性能調(diào)優(yōu)的個(gè)人經(jīng)驗(yàn)總結(jié)整個(gè)Atlas 300V部署YOLO的項(xiàng)目走下來我最深的一個(gè)體會(huì)就是昇騰的軟件棧確實(shí)沒有CUDA生態(tài)那么“省心”很多操作都需要你主動(dòng)去理解硬件特性——算子的支持情況、數(shù)據(jù)格式的要求、硬件解碼的路徑選擇全都需要自己摸索和驗(yàn)證。但另一方面一旦把鏈路跑通你會(huì)發(fā)現(xiàn)這張卡的性價(jià)比和穩(wěn)定性都很能打尤其是在國產(chǎn)化要求明確的政企項(xiàng)目里它已經(jīng)是一個(gè)非常成熟的選擇。如果你正準(zhǔn)備入坑我的建議是第一步先把環(huán)境裝對(duì)第二步老老實(shí)實(shí)跑通一個(gè)ONNX模型的轉(zhuǎn)換和推理第三步再考慮性能調(diào)優(yōu)和視頻流的復(fù)雜場(chǎng)景。不要一上來就想著多路視頻流、多卡并行先把單卡單模型的鏈路走通剩下的都是錦上添花。最后再提醒一句所有版本相關(guān)的配置都以昇騰社區(qū)官方文檔為準(zhǔn)因?yàn)榘姹镜芸炀W(wǎng)上很多教程可能已經(jīng)過時(shí)了——包括我這篇里的某些版本號(hào)到你看的時(shí)候也許又更新了一兩代但整體思路和坑位是不會(huì)變的。