戰(zhàn)指南)
做AI推理這幾年我手里經(jīng)手過不少加速卡GPU、NPU、FPGA都折騰過。前陣子因?yàn)轫椖啃枨笳J(rèn)真地把華為昇騰的Atlas 300V 24G摸了一遍還順手把YOLOv5/YOLOv8的模型完整部署了上去。之所以想寫這篇東西是因?yàn)槲野l(fā)現(xiàn)在社區(qū)里“atlas部署yolo”和“atlas 300v 24g 是運(yùn)算加速卡嗎”這類問題的搜索量特別高但真正把從硬件認(rèn)識、驅(qū)動環(huán)境、模型轉(zhuǎn)換到推理調(diào)優(yōu)整條鏈路講清楚的文章少之又少很多人卡在第一步就不動了。這篇文章我不想講太多PPT上的理論就從一個實(shí)際跑過項目的人角度把我踩過的坑、驗(yàn)證過的命令、試出來有效的配置全部攤開講給想做昇騰推理的同學(xué)一條能直接照著走的路。1. Atlas 300V 24G到底是個什么“加速卡”1.1 先回答熱搜它確實(shí)是運(yùn)算加速卡但和你想的可能不一樣先直接回答那個被問爛了的問題Atlas 300V 24G是運(yùn)算加速卡嗎答案是肯定的它是一張專門為AI推理設(shè)計的加速卡。但它和你印象里的“顯卡”完全是兩回事——它沒有顯示輸出接口你沒法給它接個顯示器打游戲它誕生出來的唯一目的就是把神經(jīng)網(wǎng)絡(luò)模型的計算跑得飛快。這顆卡的核心是昇騰310P系列處理器具體型號在部分文檔里也叫310P324G指的是板載內(nèi)存容量這個內(nèi)存不是用來存畫面的而是用來存放模型權(quán)重、中間特征圖和推理數(shù)據(jù)的。換算成大家熟悉的GPU語言它更像是“專門跑AI作業(yè)的協(xié)處理器”。在模型推理場景下它單卡能提供的INT8算力在百級TOPS左右具體數(shù)值跟頻率和功耗模式有關(guān)功耗卻控制得很低我記得標(biāo)稱大概在72W附近比動輒三四百瓦的GPU溫和太多。很多朋友第一次拿到這卡會犯迷糊因?yàn)樗L得太像一張顯卡了又帶散熱片又帶擋板。我在這里給你提個醒千萬別拿它當(dāng)顯卡用也別指望它能幫你做CUDA加速它的軟件棧是華為自己的一套CANN生態(tài)和CUDA不通用。想在上面跑東西所有的模型轉(zhuǎn)換、算子適配、推理調(diào)用都要圍繞昇騰的工具鏈來。1.2 它憑什么能跑YOLO硬件規(guī)格與算力定位部署YOLO這類目標(biāo)檢測模型本質(zhì)上就是把訓(xùn)練好的權(quán)重文件轉(zhuǎn)換成能在NPU上運(yùn)行的離線模型OM格式然后通過昇騰的推理接口調(diào)用硬件完成前向計算。Atlas 300V 24G在這個過程中的定位非常清晰它是一款高能效比的推理卡專攻“已經(jīng)訓(xùn)練好的模型”的加速而不是用來訓(xùn)練的。拿YOLOv5s舉例這個模型在GPU上用FP16跑一張圖大概也就幾毫秒到十幾毫秒在Atlas 300V上如果配置得當(dāng)單張圖的推理時間同樣可以做到個位數(shù)毫秒級別。你可能覺得這不就是“能跑”嘛沒什么稀奇。但真正讓它有價值的是批量處理能力和功耗比在視頻流分析場景里一路視頻按25幀算每秒需要處理25張圖一張卡同時處理8路、16路視頻流時它能穩(wěn)定壓住幀率而且整卡功耗遠(yuǎn)低于同規(guī)格GPU。這個優(yōu)勢在機(jī)房部署和邊緣服務(wù)器里非常值錢。另外要澄清一個概念A(yù)tlas 300V 24G這個“24G”并不是越大越好它主要用來容納更大的模型和更大的batch。比如你想一次推理塞進(jìn)去8張甚至16張圖或者跑YOLOv8x這種大模型內(nèi)存需求就會明顯上漲。實(shí)際項目中我建議先確認(rèn)模型大小和batch策略再決定要不要上24G版本。如果只是跑個YOLOv5s單batch推理其實(shí)8G甚至更小內(nèi)存的型號也能勝任沒必要為了“大內(nèi)存”多花錢。但如果你要做多路視頻流并發(fā)推理24G的余量會讓人從容很多。2. 部署YOLO前的準(zhǔn)備工作把環(huán)境一次配到位2.1 硬件安裝與驅(qū)動檢查拿到卡后第一件事Atlas 300V是一張PCIe插槽的卡安裝過程和裝顯卡基本一樣。但有幾個細(xì)節(jié)我提醒一下第一供電一定要接好。部分型號的300V除了PCIe插槽供電外還需要外接一個8pin或者6pin的輔助供電口。有些同學(xué)裝機(jī)時圖省事不接外電結(jié)果上電后系統(tǒng)死活識別不到卡查了半天發(fā)現(xiàn)是供電沒插。這問題我見過不止一次強(qiáng)烈建議你裝卡之前先看清楚卡上的供電接口類型。第二驅(qū)動和固件版本要匹配。從官網(wǎng)下載對應(yīng)型號的CANN工具包時里面通常會包含NPU驅(qū)動和固件。我踩過的坑是先裝了舊版驅(qū)動再裝新版CANN結(jié)果在推理初始化時報設(shè)備不支持的錯。后來老老實(shí)實(shí)按官方要求把固件、驅(qū)動、CANN三者版本對齊才解決。裝完驅(qū)動后可以用npu-smi info命令查看卡的狀態(tài)這個命令和NVIDIA的nvidia-smi很像能看到卡的溫度、內(nèi)存占用、算力利用率等關(guān)鍵信息。npu-smi info正常狀態(tài)下你能看到類似這樣的輸出里面有具體的芯片型號“Ascend 310P”和內(nèi)存大小如果這里顯示不出來說明驅(qū)動或硬件連接有問題先別急著往下走把環(huán)境整干凈再說。2.2 軟件棧選型CANN、MindSpore Lite還是自定義算子路徑Atlas卡上的軟件棧不像CUDA那樣只有一條路它其實(shí)給了你幾種選擇。我用過之后給你梳理一下CANN AscendCL這是最底層、最可控的方案。AscendCLACL是C語言/Python的推理接口類似CUDA的Runtime API。你直接調(diào)用aclrt_malloc、aclmdlExecute這類接口自己管理內(nèi)存、排隊、同步。優(yōu)點(diǎn)是靈活性最高性能潛力最大缺點(diǎn)是你得像寫CUDA一樣注意資源的管理。這是我最推薦的方式后面我也會重點(diǎn)講這條路徑。MindSpore Lite如果你訓(xùn)練模型用的是MindSpore框架轉(zhuǎn)換和部署會比較順滑。但如果你手里是PyTorch的權(quán)重反而多一層轉(zhuǎn)換步驟沒太大優(yōu)勢。第三方推理框架比如通過OpenCV的DNN模塊配合CANN后端或者用ONNX Runtime的昇騰EPExecution Provider。這種方式上手最快幾行代碼就能跑起來但對算子的控制力弱性能上限也有限。我建議生產(chǎn)環(huán)境還是走AscendCL。我在實(shí)際項目中選了CANN AscendCL原因很簡單部署YOLO這種模型后處理里NMS非極大值抑制和輸出解析占的時間不少如果全丟給框架的黑盒處理出了問題很難定位。自己用ACL把推理主鏈路管起來后處理在CPU上自己寫出了性能問題我能明確知道瓶頸在NPU還是在后處理排查起來清晰很多。提示第一次接觸昇騰的同學(xué)我建議先把CANN開發(fā)套件里的sample跑通一個比如官方自帶的resnet50推理樣例。先不管你的YOLO模型這一步是為了驗(yàn)證驅(qū)動、固件、CANN三方環(huán)境是好的。樣例能跑通再往上加復(fù)雜度。3. 模型遷移鏈路從PyTorch權(quán)重到OM離線模型3.1 導(dǎo)出ONNX的三個關(guān)鍵點(diǎn)在Atlas上跑YOLO最繞不開的一步就是模型轉(zhuǎn)換。昇騰的NPU不認(rèn)PyTorch的權(quán)重文件它只認(rèn)OM格式的離線模型。所以整個遷移鏈路通常是PyTorch權(quán)重 → ONNX → OM。這個過程中ONNX導(dǎo)出是第一個大坑。我基于YOLOv5和YOLOv8的實(shí)際經(jīng)驗(yàn)給你總結(jié)三個關(guān)鍵點(diǎn)第一輸入尺寸一定要固定。導(dǎo)出ONNX時建議把輸入尺寸定死在模型推理時實(shí)際使用的尺寸比如640x640。雖然ONNX協(xié)議支持動態(tài)尺寸但昇騰的ATC轉(zhuǎn)換對動態(tài)shape支持有限動態(tài)尺寸不僅會拉低性能還容易在轉(zhuǎn)換時報錯。我在項目里直接固定成1x3x640x640省了無數(shù)麻煩。如果你確實(shí)需要多尺寸推理你可以轉(zhuǎn)換多個不同尺寸的OM模型運(yùn)行時根據(jù)輸入圖尺寸動態(tài)選擇。第二后處理算子不要一股腦塞進(jìn)模型里。YOLO的檢測頭輸出通常包括目標(biāo)框坐標(biāo)、置信度、類別概率后續(xù)還要經(jīng)過解碼和NMS。有些同學(xué)圖省事把NMS也寫進(jìn)模型網(wǎng)絡(luò)里想著NPU能一并處理。但昇騰對NMS這類動態(tài)算子的支持很有限強(qiáng)行塞進(jìn)去輕則性能變差重則轉(zhuǎn)換失敗。我建議只保留模型主干和檢測頭的原始輸出把解碼和NMS放到模型外部的CPU后處理里。第三用torch.onnx.export時注意算子版本。我遇到過導(dǎo)出的ONNX里某些算子版本過新ATC不認(rèn)的情況。通常是設(shè)置opset_version11或12就夠用了沒必要追求最新版。另外導(dǎo)出后最好用onnxsim等工具對圖做一次簡化去掉一些冗余的Transpose、ReshapeATC轉(zhuǎn)換時成功率會明顯提高。下面是我導(dǎo)出YOLOv5 ONNX時常用的一段代碼關(guān)鍵部分import torch from models.experimental import attempt_load model attempt_load(yolov5s.pt, map_locationcpu) model.eval() dummy_input torch.randn(1, 3, 640, 640) torch.onnx.export( model, dummy_input, yolov5s.onnx, opset_version11, input_names[images], output_names[output], dynamic_axesNone ) print(export done)導(dǎo)出后我會立刻用onnxruntime跑一遍確認(rèn)輸出結(jié)果和PyTorch原始推理一致再進(jìn)入ATC轉(zhuǎn)換。這一步能提前暴露很多算子兼容性問題。3.2 ATC轉(zhuǎn)換實(shí)戰(zhàn)命令、AIPP配置與常見報錯拿到ONNX模型后下一步就是用ATC工具把它轉(zhuǎn)成OM。ATC工具在CANN安裝目錄下的/usr/local/Ascend/ascend-toolkit/latest/bin/atc第一次用要先確認(rèn)它在你系統(tǒng)的PATH里。我最常用的轉(zhuǎn)換命令長這樣atc --modelyolov5s.onnx \ --framework5 \ --outputyolov5s_bs1 \ --input_shapeimages:1,3,640,640 \ --soc_versionAscend310P3 \ --insert_op_confaipp.cfg \ --output_typeFP32這里幾個參數(shù)我逐個解釋--framework5表示輸入是ONNX格式這是ATC的固定寫法。--output是輸出OM文件的前綴名。--input_shape需要和你導(dǎo)出ONNX時完全一致不然會報維度不匹配。--soc_version要注意Atlas 300V對應(yīng)的是Ascend310P3別和Atlas 300I的Ascend310P1弄混了選錯會直接報錯。--insert_op_conf是AIPP配置文件這個非常關(guān)鍵我單獨(dú)說一下。AIPPAI Preprocessing是昇騰在硬件上做預(yù)處理的功能可以把圖像縮放、減均值、除方差、色域轉(zhuǎn)換這些操作從CPU挪到NPU上完成。很多人在轉(zhuǎn)換時忽略這一步把預(yù)處理全部留在CPU上用OpenCV做結(jié)果推理速度被CPU預(yù)處理拖慢不少。我建議把所有能下沉的預(yù)處理都配置進(jìn)AIPP。下面是一個YOLOv5彩色圖輸入的典型AIPP配置aipp_op { aipp_mode: static input_format: RGB888_U8 src_image_size_w: 640 src_image_size_h: 640 crop: false mean_chn_0: 0 mean_chn_1: 0 mean_chn_2: 0 var_reci_chn_0: 0.003921569 var_reci_chn_1: 0.003921569 var_reci_chn_2: 0.003921569 }這里input_format: RGB888_U8告訴AIPP輸入是RGB三通道8位圖模型訓(xùn)練時的預(yù)處理是標(biāo)準(zhǔn)化到0~1所以mean全為0var_reci是1/255約等于0.00392。如果你訓(xùn)練時用的是歸一化均值±標(biāo)準(zhǔn)差還需要按實(shí)際值配置。AIPP這個設(shè)計我覺得比GPU上手動寫預(yù)處理要優(yōu)雅不少一旦配好推理時輸入就可以直接丟原始圖像數(shù)據(jù)進(jìn)去NPU自己完成resize和歸一化。轉(zhuǎn)換成功后你會在輸出目錄里看到y(tǒng)olov5s_bs1.om文件??梢杂胦mg自帶的工具查看模型信息或者直接進(jìn)入下一步用一個小測試腳本來驗(yàn)證OM能不能正確推理。常見報錯我先列幾個E10001: Input shape is inconsistent輸入shape沒對齊檢查ATC參數(shù)里的--input_shape。E10002: Unsupported op type xxx模型里有ATC不支持的算子。這時優(yōu)先考慮回源頭修改模型把特殊算子替換成通用算子。E19999: Inner Error這種比較頭疼通常是CANN版本和模型算子兼容性問題可以先查CANN的版本日志再考慮升級或降級CANN版本。4. 基于AscendCL的推理部署寫一個能跑的YOLO推理程序4.1 初始化與資源管理模型轉(zhuǎn)換好了接下來就是寫推理程序。這里我走的是CANN AscendCL路徑Python版本用起來也很方便C語言適合性能極致要求的場景我開發(fā)時先用Python快速驗(yàn)證線上再優(yōu)化C。這里我介紹Python版本的流程因?yàn)槟闩芡ㄟ壿嫼笤俑某蒀只是API層面的替換。推理程序的第一步是初始化ACL環(huán)境import acl # 初始化 ret acl.init() assert ret 0 # 設(shè)置推理設(shè)備 ret acl.rt.set_device(0) assert ret 0 # 創(chuàng)建上下文 context, ret acl.rt.create_context(0) assert ret 0這里有幾個容易犯的錯誤第一每個進(jìn)程必須且只能調(diào)用一次acl.init()多次調(diào)用會報重復(fù)初始化的錯。第二acl.rt.set_device(0)里的0是設(shè)備ID如果你機(jī)器上插了多張Atlas卡要先確認(rèn)你的模型在哪張卡上跑。可以用npu-smi info查看卡的編號。第三上下文Context一定要創(chuàng)建并且后續(xù)所有推理調(diào)用都必須在同一個上下文中執(zhí)行。這就像CUDA里的context一樣搞錯了會莫名其妙地報空指針錯誤。初始化完成后加載OM模型model_path byolov5s_bs1.om # 加載模型 model_id, ret acl.mdl.load_from_file(model_path) assert ret 0 # 獲取模型描述 model_desc acl.mdl.create_desc() ret acl.mdl.get_desc(model_desc, model_id)模型加載成功后你就拿到了model_id后續(xù)所有推理執(zhí)行都靠它。同時我強(qiáng)烈建議你調(diào)用acl.mdl.get_desc獲取模型的輸入輸出信息它會告訴你模型期望的輸入大小、輸出Tensor數(shù)量、每個Tensor的shape和數(shù)據(jù)類型。這些信息在后處理階段非常重要。4.2 推理主流程拆解YOLO推理的完整流程是讀圖 → 預(yù)處理 → 拷貝到設(shè)備內(nèi)存 → 推理 → 從設(shè)備內(nèi)存取回輸出 → 后處理。在ACL環(huán)境下每一步都有對應(yīng)的API。讀圖和預(yù)處理我用OpenCV完成但注意因?yàn)锳IPP已經(jīng)把resize和歸一化下沉到NPU了所以CPU端只需要把圖像數(shù)據(jù)轉(zhuǎn)成RGB排列并resize到640x640不需要再做歸一化。然后申請設(shè)備內(nèi)存并拷貝數(shù)據(jù)# 假設(shè)image是resize后的RGB圖像連續(xù)內(nèi)存 image_bytes image.tobytes() # 申請設(shè)備內(nèi)存 device_data, ret acl.rt.malloc(640 * 640 * 3, 2) # 2是內(nèi)存對齊 # 從主機(jī)內(nèi)存拷貝到設(shè)備內(nèi)存 ret acl.rt.memcpy(device_data, 640 * 640 * 3, image_bytes, 640 * 640 * 3, acl.aclrt_memcpy_kind.aclrt_memcpy_kind_host_to_device)注意acl.rt.malloc的第二個參數(shù)是內(nèi)存對齊大小通常傳2即64字節(jié)對齊也可以傳32具體看官方要求。拷貝方式一定要是host_to_device方向反了你會在推理時得到一堆亂碼。執(zhí)行推理這一步很關(guān)鍵ACL支持同步和異步兩種方式。同步接口acl.mdl.execute簡單粗暴調(diào)用完就阻塞直到推理結(jié)束。異步接口acl.mdl.execute_async需要配合stream使用適合高吞吐場景。我開發(fā)階段先用同步接口驗(yàn)證正確性性能調(diào)優(yōu)時才切異步。# 同步推理 ret acl.mdl.execute(model_id, [device_data], # 輸入設(shè)備內(nèi)存指針列表 [output_size], # 輸出大小列表 [output_data], # 輸出設(shè)備內(nèi)存指針列表 [output_size]) # 輸出大小列表執(zhí)行完成后把輸出數(shù)據(jù)拷貝回主機(jī)內(nèi)存output_data_host, ret acl.rt.malloc_host(output_size) ret acl.rt.memcpy(output_data_host, output_size, output_data, output_size, acl.aclrt_memcpy_kind.aclrt_memcpy_kind_device_to_host)這里要提醒一個我踩過的坑輸出Tensor在設(shè)備內(nèi)存里是連續(xù)排列的但不是所有模型輸出順序都跟你想的一樣。一定要用前面get_desc拿到的輸出shape信息去解析數(shù)據(jù)別想當(dāng)然地認(rèn)為第一個輸出就是坐標(biāo)。我遇到過YOLOv8轉(zhuǎn)出來的ONNX輸出順序和YOLOv5不一樣結(jié)果解析錯亂畫出來的框五花八門。4.3 輸出解析與后處理輸出數(shù)據(jù)拷回主機(jī)內(nèi)存后就進(jìn)入CPU后處理階段。YOLOv5的原始輸出是[batch, 25200, 85]的Tensor其中25200是三個尺度80x80、40x40、20x20的anchor總數(shù)85是[cx, cy, w, h, obj_conf, class1_conf, class2_conf, ...]。而YOLOv8的輸出結(jié)構(gòu)稍有不同它用的是解耦頭shape通常是[batch, 84, 8400]你需要先做一次轉(zhuǎn)置才能按檢測框的方式解析。后處理的任務(wù)包括解碼把模型的原始輸出轉(zhuǎn)成檢測框坐標(biāo)和置信度。置信度過濾低于閾值的框直接丟棄。NMS對重疊的框做非極大值抑制。坐標(biāo)映射把640x640坐標(biāo)系映射回原始圖像的坐標(biāo)系。這部分我用純Python實(shí)現(xiàn)雖然效率比不上C但邏輯清晰方便調(diào)參。等確認(rèn)模型輸出正確、NMS閾值合理后再把這部分代碼改成C或者用numpy向量化加速。注意NMS的閾值conf_thres和iou_thres直接影響檢測效果。我經(jīng)驗(yàn)上建議置信度閾值設(shè)在0.25左右IOU閾值設(shè)在0.45左右這是YOLOv5倉庫的默認(rèn)配置在實(shí)際場景里平衡得比較好。如果誤檢多就調(diào)高置信度閾值如果漏檢多就調(diào)低。5. 性能調(diào)優(yōu)與踩坑實(shí)錄5.1 三個直接影響吞吐量的配置模型在Atlas上跑通只是第一步真正讓性能飛起來還得靠調(diào)優(yōu)。我實(shí)際調(diào)優(yōu)后發(fā)現(xiàn)下面這三個配置對吞吐量的影響最大第一Batch Size。ATC轉(zhuǎn)換時可以把--input_shape設(shè)成images:8,3,640,640一次推理同時處理8張圖。Batch越大NPU的利用率越高8路視頻并發(fā)推理時Batch8通常是性價比最高的選擇。但要注意Batch太大內(nèi)存會爆24G內(nèi)存在Batch16時建議先估算模型大小再決定。第二Stream與異步推理。acl.mdl.execute_async配合多Stream可以把“數(shù)據(jù)拷貝”和“NPU計算”重疊起來。我的經(jīng)驗(yàn)是先開2~4個Stream每個Stream內(nèi)循環(huán)推理即在一個Stream里前一個batch還在NPU上算GPU已經(jīng)可以拷貝下一個batch的數(shù)據(jù)了。這個流水線設(shè)計能讓卡一直處在“忙”的狀態(tài)而不是等數(shù)據(jù)拷完了才開始計算。第三AIPP盡量承接預(yù)處理。我在前面反復(fù)強(qiáng)調(diào)AIPP是因?yàn)閷?shí)測下來它的收益非常明顯。YOLO推理一張圖CPU預(yù)處理耗時約2~3毫秒而AIPP把resize和歸一化下沉到NPU后這部分時間幾乎可以忽略。如果你的部署場景是實(shí)時視頻流AIPP是必須打開的功能不然你的CPU會先被預(yù)處理拖垮。第四補(bǔ)充輸出內(nèi)存復(fù)用。不要頻繁申請釋放設(shè)備內(nèi)存。我的做法是在程序啟動時一次性申請好輸入輸出設(shè)備內(nèi)存整個生命周期里反復(fù)復(fù)用。內(nèi)存分配釋放是很貴的操作尤其在4K視頻流場景下申請釋放頻率一高性能立刻掉下去。5.2 常見報錯和排查思路我在部署過程中遇到不少問題挑幾個有代表性的整理成表格給后來的人一個排查方向現(xiàn)象可能原因排查與解決辦法acl.init返回非0驅(qū)動未安裝或CANN環(huán)境變量未配置檢查npu-smi info確認(rèn)/usr/local/Ascend路徑在當(dāng)前環(huán)境變量中acl.mdl.load_from_file報文件不存在OM模型路徑錯誤或模型未轉(zhuǎn)換成功確認(rèn)OM路徑用ls檢查文件重新跑ATC轉(zhuǎn)換推理結(jié)果全零或全錯輸入數(shù)據(jù)方向拷貝錯誤預(yù)處理與AIPP不一致檢查memcpy方向核對AIPP的input_format是否與輸入圖像一致推理時報內(nèi)存不足設(shè)備內(nèi)存申請過大batch過大減小batch用acl.rt.mem_info查看設(shè)備剩余內(nèi)存異步推理結(jié)果不刷新未調(diào)用acl.rt.synchronize_stream在execute_async后調(diào)用acl.rt.synchronize_stream(stream)同步ATC轉(zhuǎn)換報Unsupported opONNX中的算子超出支持范圍回源頭修改模型優(yōu)化ONNX圖適當(dāng)升級CANN版本memcpy數(shù)據(jù)錯位輸出shape判斷錯誤用acl.mdl.get_desc打印所有輸入輸出信息對比實(shí)際數(shù)據(jù)維度另外排查問題是還有一個經(jīng)驗(yàn)想分享CANN的日志系統(tǒng)默認(rèn)是關(guān)閉的但出問題時你真的需要它。在運(yùn)行推理程序前可以先設(shè)置環(huán)境變量ASCEND_GLOBAL_LOG_LEVEL1開啟info級日志ASCEND_SLOG_PRINT_TO_STDOUT1把日志打到終端。這樣能很直觀地看到ACL初始化、模型加載、每層推理的耗時和可能的報錯比瞎猜高效得多。調(diào)完后再把日志級別設(shè)回去因?yàn)槿罩颈旧硪矔下评硭俣取_€有一個小技巧用npu-smi info監(jiān)控卡的溫度和利用率。如果利用率一直上不去而CPU占用很高大概率是預(yù)處理或后處理在拖后腿如果利用率很高但吞吐量上不去可能是batch太小或者stream數(shù)量不夠。性能調(diào)優(yōu)本質(zhì)上就是在找系統(tǒng)的“瓶頸點(diǎn)”找到瓶頸再針對性優(yōu)化。最后的最后我再分享一點(diǎn)個人體會在Atlas上部署YOLO最容易被低估的其實(shí)是模型轉(zhuǎn)換這一步。很多人覺得PyTorch模型能跑就萬事大吉結(jié)果卡在ATC轉(zhuǎn)換報錯上反反復(fù)復(fù)修改模型結(jié)構(gòu)、算子版本反而花掉整個項目一半的時間。我的建議是轉(zhuǎn)換之前先小規(guī)模驗(yàn)證ONNX的算子兼容性把能簡化的結(jié)構(gòu)在導(dǎo)出階段就簡化掉不要在轉(zhuǎn)換報錯后再回頭改模型那樣效率太低了。Atlas這套工具鏈確實(shí)有它的學(xué)習(xí)門檻但一旦把環(huán)境配順、把鏈路跑通它的穩(wěn)定性、功耗和成本優(yōu)勢會非常突出。希望這篇文章能讓你少走一些彎路。