換到工程化推理)
最近有幾個(gè)做視覺的朋友問我Atlas 300V 24G到底是不是運(yùn)算加速卡能不能拿來部署YOLO。這個(gè)問題挺典型——Atlas在華為昇騰產(chǎn)品線里既指整機(jī)、也指板卡還經(jīng)常被拿來和GPU對(duì)比新手一聽就懵。我花了大約三天把YOLOv5完整部署到Atlas 300V Pro 24G上跑通中間經(jīng)歷了模型轉(zhuǎn)換、算子報(bào)錯(cuò)、結(jié)果全黑、顯存反復(fù)拉滿這些坑。這篇就把整個(gè)流程、參數(shù)選擇、排查經(jīng)驗(yàn)一次性寫清楚給準(zhǔn)備在Atlas類推理卡上做目標(biāo)檢測(cè)的同學(xué)當(dāng)參考。1. 先搞清楚Atlas 300V 24G到底是什么卡1.1 它不是顯卡是專用AI推理加速卡很多人聽到“24G顯存”第一反應(yīng)是這塊卡像RTX 3090一樣可以隨便訓(xùn)練模型。實(shí)際不是。Atlas 300V Pro 24G是華為昇騰系列里的AI推理加速卡核心是一個(gè)NPU神經(jīng)網(wǎng)絡(luò)處理器針對(duì)神經(jīng)網(wǎng)絡(luò)計(jì)算做了大量專用電路優(yōu)化擅長(zhǎng)干高吞吐的模型推理但它不是通用的可編程GPU很多CUDA生態(tài)里習(xí)以為常的操作在它上面并不直接支持。怎么理解這個(gè)區(qū)別可以類比GPU像一臺(tái)通用機(jī)床什么零件都能車NPU像一條專用流水線只加工你提前設(shè)計(jì)好的零件但加工速度極快。所以Atlas這張卡最適合的場(chǎng)景是模型已經(jīng)訓(xùn)練好、需要大規(guī)模部署推理的環(huán)節(jié)比如視頻監(jiān)控目標(biāo)檢測(cè)、工業(yè)質(zhì)檢、園區(qū)安防、智慧交通這些。你拿它去從頭訓(xùn)練YOLO那會(huì)很別扭但拿它來跑已經(jīng)訓(xùn)練好的YOLO模型尤其是多路視頻流同時(shí)做目標(biāo)檢測(cè)反而是它的主場(chǎng)。這張卡還有一個(gè)加分項(xiàng)板載了專屬的視頻編解碼模塊可以硬件解碼H.264/H.265視頻流不用CPU軟解做視頻分析類的項(xiàng)目非常省心。所以熱詞里“atlas 300v 24g是運(yùn)算加速卡嗎”答案是肯定的但更準(zhǔn)確的說法是它是一張偏推理、偏視頻處理場(chǎng)景的AI加速卡。1.2 為什么在Atlas上部署YOLO要先轉(zhuǎn)變思路在GPU上部署YOLO大家習(xí)慣把PyTorch模型直接加載到顯存里跑或者導(dǎo)出TensorRT引擎。Atlas這套生態(tài)的邏輯不太一樣它要求先把訓(xùn)練好的模型離線編譯成一種名為OMOffline Model的格式再通過CANN運(yùn)行時(shí)加載執(zhí)行。這個(gè)差異是整個(gè)部署流程里最需要扭轉(zhuǎn)思路的地方。OM模型是靜態(tài)編譯產(chǎn)物編譯時(shí)就要把輸入shape、算子類型、芯片型號(hào)這些信息都定好運(yùn)行時(shí)不支持動(dòng)態(tài)算子插拔。好處是運(yùn)行時(shí)開銷低、性能穩(wěn)定壞處是靈活性下降比如你想隨便改輸入分辨率就得重新編譯一次模型。理解了這個(gè)底層邏輯后面所有操作就順理成章了——先導(dǎo)出ONNX再用ATC工具轉(zhuǎn)成OM最后寫代碼加載OM做推理。這不是繞路而是NPU推理卡的標(biāo)準(zhǔn)工作流。2. 部署前準(zhǔn)備驅(qū)動(dòng)固件與CANN軟件棧2.1 裝機(jī)與配套版本檢查我踩過的第一個(gè)坑就是安裝順序和版本配套。Atlas這塊板卡到手后不是插上PCIe槽就能用還要裝三樣?xùn)|西NPU驅(qū)動(dòng)、固件、CANN工具包。這三者之間有嚴(yán)格的版本配套關(guān)系不能各裝各的。選版本時(shí)一定要去昇騰社區(qū)的“版本配套表”里查清楚驅(qū)動(dòng)版本對(duì)應(yīng)哪個(gè)固件版本對(duì)應(yīng)哪個(gè)CANN版本再對(duì)應(yīng)你打算用的PyTorch/ONNX算子版本。我一開始圖省事裝了最新驅(qū)動(dòng)結(jié)果CANN不認(rèn)npu-smi info能看見卡但跑ATC時(shí)直接報(bào)算子編譯失敗。折騰半天最后老老實(shí)實(shí)按照配套表重裝了一遍才正常。另外要注意硬件環(huán)境。Atlas 300V Pro 24G是PCIe接口的板卡服務(wù)器主板至少要留一個(gè)PCIe x16物理插槽功耗和散熱也要確認(rèn)電源功率夠、機(jī)箱風(fēng)道能帶走熱量。開發(fā)階段我用一臺(tái)塔式工作站插單卡完全不涉及多卡互聯(lián)環(huán)境簡(jiǎn)單很多。2.2 安裝順序和關(guān)鍵環(huán)境變量安裝順序建議嚴(yán)格按這個(gè)來先裝NPU驅(qū)動(dòng)再裝固件最后裝CANN Toolkit。驅(qū)動(dòng)和固件一般有對(duì)應(yīng)的run包或deb包執(zhí)行后會(huì)寫入/usr/local/Ascend/driver和/usr/local/Ascend/firmware。CANN Toolkit解壓后路徑通常在/usr/local/Ascend/ascend-toolkit。裝完CANN后最容易被忽略的是環(huán)境變量。每次開終端或?qū)懛?wù)腳本都要source一下source /usr/local/Ascend/ascend-toolkit/set_env.sh這個(gè)腳本會(huì)把LD_LIBRARY_PATH、PYTHONPATH、ASCEND_HOME_PATH等關(guān)鍵變量設(shè)置好。如果沒source你importacl庫(kù)時(shí)會(huì)直接報(bào)找不到動(dòng)態(tài)庫(kù)或者運(yùn)行時(shí)提示libascendcl.so: cannot open shared object file這類問題十有八九就是環(huán)境變量沒配對(duì)。強(qiáng)烈建議在系統(tǒng)級(jí)配置里寫上比如在/etc/profile.d/下新建一個(gè)腳本開機(jī)自動(dòng)source省得每次部署服務(wù)都要重新找路徑。2.3 用npu-smi確認(rèn)設(shè)備正常安裝完成后第一件事就是確認(rèn)設(shè)備狀態(tài)。npu-smi info類似NVIDIA的nvidia-smi能查看卡的工作狀態(tài)、溫度、顯存占用、驅(qū)動(dòng)版本。npu-smi info正常輸出里能看到Atlas 300V Pro 24G的信息芯片狀態(tài)應(yīng)該是“OK”。如果這里都看不到卡或者芯片狀態(tài)異常不要往下走先檢查驅(qū)動(dòng)是否加載成功、PCIe設(shè)備是否被識(shí)別必要時(shí)重新插拔板卡或引導(dǎo)驅(qū)動(dòng)模塊。驅(qū)動(dòng)加載可以看內(nèi)核模塊lsmod | grep drv_pcie如果驅(qū)動(dòng)模塊沒加載可以用npu-smi info的報(bào)錯(cuò)信息排查通常是版本不匹配或系統(tǒng)內(nèi)核頭文件缺失。我習(xí)慣在裝機(jī)階段就確認(rèn)好這一步因?yàn)樗鼪Q定了后面所有環(huán)節(jié)能不能進(jìn)行。3. YOLO模型轉(zhuǎn)換從PyTorch權(quán)重到OM模型3.1 為什么要轉(zhuǎn)OM前面說過Atlas推理卡運(yùn)行的是OM離線模型不是PyTorch權(quán)重。OM模型是ATC工具根據(jù)目標(biāo)芯片生成的靜態(tài)指令集有點(diǎn)像給NPU寫好的“機(jī)器碼”。運(yùn)行時(shí)按圖執(zhí)行調(diào)度開銷極低。轉(zhuǎn)換時(shí)ATC要做幾件事解析ONNX圖結(jié)構(gòu)把PyTorch里的動(dòng)態(tài)計(jì)算圖轉(zhuǎn)成靜態(tài)計(jì)算圖把ONNX算子映射成CANN算子做算子融合、內(nèi)存復(fù)用等優(yōu)化最終生成適配指定芯片型號(hào)的OM文件。所以O(shè)M模型和你手上的芯片型號(hào)強(qiáng)綁定。在Atlas 300V Pro上編譯的OM換到另一顆昇騰芯片上大概率跑不了需要重新轉(zhuǎn)換。3.2 ONNX導(dǎo)出要點(diǎn)我用的是YOLOv5sPyTorch權(quán)重先導(dǎo)出ONNX。YOLOv5官方倉(cāng)庫(kù)自帶導(dǎo)出腳本python export.py --weights yolov5s.pt --include onnx --opset 11這里有幾個(gè)細(xì)節(jié)要注意。第一--opset不建議設(shè)太高CANN對(duì)ONNX算子支持有版本邊界過高的opset可能引入CANN不認(rèn)識(shí)的算子。我實(shí)測(cè)opset 11比較穩(wěn)。第二導(dǎo)出前把模型輸入固定。YOLOv5默認(rèn)導(dǎo)出的是動(dòng)態(tài)batch版本輸入shape帶-1維度。ONNX動(dòng)態(tài)shape不是不能轉(zhuǎn)OM但會(huì)帶來額外的動(dòng)態(tài)shape處理初學(xué)者很容易在這里出錯(cuò)。更穩(wěn)的做法是在導(dǎo)出腳本里固定輸入尺寸比如imgsz640后面ATC轉(zhuǎn)換也固定成1,3,640,640鏈路最簡(jiǎn)單。第三不要在ONNX里導(dǎo)出NMS算子。YOLOv5原版導(dǎo)出的ONNX后處理部分是裸的候選框輸出NMS要自己做。某些倉(cāng)庫(kù)會(huì)集成NMS算子但在NPU上這些算子未必兼容而且整個(gè)NMS放硬件上做輸出形狀無(wú)法固定反而不利于性能優(yōu)化。我的習(xí)慣是模型只做主干推理NMS和后處理全部在CPU側(cè)完成。3.3 ATC轉(zhuǎn)換命令與參數(shù)說明拿到ONNX后用ATC工具轉(zhuǎn)換atc --modelyolov5s.onnx \ --framework5 \ --outputyolov5s_om \ --input_shapeimages:1,3,640,640 \ --soc_versionAscend310P3 \ --insert_op_confaipp.cfg \ --output_typeFP32 \ --logerror逐個(gè)解釋這些參數(shù)--model輸入的ONNX文件路徑。--framework5表示ONNX1表示MindSpore0表示TensorFlow我們這里用ONNX就是5。--input_shape固定輸入shape。images是ONNX輸入節(jié)點(diǎn)的名稱YOLOv5導(dǎo)出后一般叫images可以用Netron打開ONNX確認(rèn)。形狀寫1,3,640,640表示batch1、3通道、高640寬640。--soc_version目標(biāo)芯片型號(hào)字符串必須和你的卡對(duì)應(yīng)。這里的Ascend310P3只是示例Atlas 300V Pro到底是哪個(gè)字符串一定要去查你這張卡對(duì)應(yīng)CANN版本的《產(chǎn)品型號(hào)-昇騰軟件版本配套表》。填錯(cuò)會(huì)在編譯階段直接報(bào)錯(cuò)或者生成一個(gè)根本無(wú)法加載的OM。--insert_op_confAIPP配置文件路徑稍后詳細(xì)講。--output_type指定模型輸出數(shù)據(jù)類型。目標(biāo)檢測(cè)后處理一般用FP32精度夠用。--logerror日志級(jí)別只打印錯(cuò)誤信息。轉(zhuǎn)換失敗時(shí)再看debug日志。3.4 配置AIPP把預(yù)處理搬進(jìn)硬件AIPP是Atlas硬件圖像預(yù)處理模塊可以在推理前自動(dòng)完成縮放、裁剪、色域轉(zhuǎn)換、歸一化。YOLO的預(yù)處理需要在CPU端做resize、減均值除方差、RGB轉(zhuǎn)BGR這些如果全部在CPU做多路視頻時(shí)CPU容易成瓶頸。AIPP配置好后這些操作交給硬件CPU只負(fù)責(zé)讀圖。我用的aipp.cfg大致長(zhǎng)這樣aipp_op { aipp_mode: static input_format: RGB888_U8 src_image_size_w: 640 src_image_size_h: 640 csc_switch: true rbuv_swap_switch: false min_chn_0: 0 min_chn_1: 0 min_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表示輸入是RGB三通道、每個(gè)通道8bitvar_reci_chn_*是1/255即歸一化系數(shù)對(duì)應(yīng)YOLO訓(xùn)練時(shí)的歸一化到0-1操作。rbuv_swap_switch控制是否交換R和B通道如果你的PYTORCH訓(xùn)練代碼輸入是RGB順序而JPG讀進(jìn)來默認(rèn)是BGR就需要在這里控制換通道。這個(gè)細(xì)節(jié)很多人會(huì)漏結(jié)果推理結(jié)果出來坐標(biāo)對(duì)但類別全錯(cuò)。AIPP還有更大的作用——支持直接送原始分辨率大圖讓硬件完成等比縮放和居中填充這樣CPU端不需要自己實(shí)現(xiàn)letterbox。不過這樣配置稍微復(fù)雜我建議第一版還是CPU端把圖resize好喂給AIPP只做歸一化跑通再優(yōu)化。4. 用pyACL寫推理代碼跑通YOLO4.1 初始化和加載模型CANN的Python接口叫pyACL代碼風(fēng)格和CUDA的C接口很像都是先初始化、設(shè)置設(shè)備、創(chuàng)建stream再加載模型執(zhí)行。先看初始化這一段import acl def init(): ret acl.init() assert ret 0, acl.init failed ret acl.rt.set_device(0) # 使用第0張卡 ret acl.rt.set_context(0) # 創(chuàng)建上下文 context acl.rt.create_context(0) ret acl.rt.create_stream(0) # 創(chuàng)建stream這段代碼有幾個(gè)容易踩的坑acl.init()通常只需要調(diào)用一次進(jìn)程結(jié)束前要記得調(diào)用acl.finalize()釋放set_device(0)的設(shè)備編號(hào)要和npu-smi info里看到的卡序號(hào)對(duì)應(yīng)多卡時(shí)尤其注意。模型加載用acl.mdl.load_from_filemodel_id acl.mdl.load_from_file(yolov5s_om.om) model_desc acl.mdl.create_desc() acl.mdl.get_desc(model_desc, model_id)加載成功后必須拿到模型描述信息里面包含輸入、輸出的shape和大小。這些信息后面申請(qǐng)內(nèi)存時(shí)要用。4.2 準(zhǔn)備輸入數(shù)據(jù)與執(zhí)行推理輸入數(shù)據(jù)要先轉(zhuǎn)成numpy數(shù)組再拷貝到設(shè)備側(cè)內(nèi)存。YOLOv5預(yù)處理后的輸入是1,3,640,640、每個(gè)像素值范圍0-1的float32數(shù)組。import numpy as np input_data np.zeros((1, 3, 640, 640), dtypenp.float32) # 把resize后的圖像按HWC轉(zhuǎn)CHW、歸一化之后填入input_data _, input_size acl.mdl.get_input_size_by_index(model_id, 0) input_buffer, ret acl.rt.malloc(input_size, 2) # 設(shè)備側(cè)內(nèi)存2是ACL_MEM_MALLOC_NORMAL_ONLY acl.rt.memcpy(input_buffer, input_size, input_data.tobytes(), input_size, 1) # 1是H2D拷貝這一步最容易出問題的是input_size。它是bytes大小不是元素個(gè)數(shù)。YOLOv5s的輸入是1*3*640*640*4字節(jié)float32也就是4915200字節(jié)。不要想當(dāng)然寫死最好從get_input_size_by_index動(dòng)態(tài)獲取避免以后換模型就崩。執(zhí)行推理stream_id acl.rt.get_stream() ret acl.mdl.execute(stream_id, model_id, [input_buffer], [output_buffer])acl.mdl.execute是同步接口執(zhí)行完需要從輸出buffer拷回主機(jī)側(cè)。異步版本acl.mdl.execute_async后面做多路并發(fā)時(shí)再考慮。4.3 后處理坐標(biāo)解碼與NMSYOLOv5輸出形狀是1, 25200, 85表示有25200個(gè)候選框每個(gè)候選框85個(gè)值——前4個(gè)是坐標(biāo)(x, y, w, h)或(x1, y1, x2, y2)第5個(gè)是objectness置信度后面80個(gè)是COCO各類別概率。拿到原始輸出后要做三件事坐標(biāo)解碼、置信度過濾、NMS。坐標(biāo)解碼要看你導(dǎo)出的模型輸出格式。如果輸出是中心坐標(biāo)加寬高(xywh)要先轉(zhuǎn)成xyxy格式boxes[:, 0] cx - w / 2 boxes[:, 1] cy - h / 2 boxes[:, 2] cx w / 2 boxes[:, 3] cy h / 2然后再縮放回原始圖像尺寸。別忘了letterbox的padding要減掉否則框會(huì)整體偏移。置信度過濾一般把閾值設(shè)在0.3-0.5之間太低會(huì)有大量假陽(yáng)性。NMS我用最簡(jiǎn)單的torchvision.ops.nms或者OpenCV的cv2.dnn.NMSBoxes都行關(guān)鍵是NMS的IoU閾值YOLOv5默認(rèn)是0.45。這塊沒什么黑科技但性能調(diào)優(yōu)時(shí)要注意25200個(gè)候選框逐類別做NMS比較花CPU時(shí)間如果連續(xù)跑多路視頻后處理CPU占用會(huì)很高后面我會(huì)講怎么優(yōu)化。5. 工程化部署的提速與避坑5.1 固定shape優(yōu)先動(dòng)態(tài)batch謹(jǐn)慎使用ATC轉(zhuǎn)換時(shí)可以選擇固定一個(gè)輸入shape也可以用--dynamic_batch_size支持多個(gè)batch。動(dòng)態(tài)batch的代價(jià)是模型體積變大、推理啟動(dòng)時(shí)間變長(zhǎng)而且部分算子融合策略會(huì)被禁用。我的觀點(diǎn)很直接第一版項(xiàng)目一律固定shape。先讓整個(gè)鏈路跑通、結(jié)果正確再去折騰動(dòng)態(tài)shape。如果后續(xù)有多batch需求明確兩個(gè)batch就編譯兩個(gè)輸入shape的模型不要用過于寬泛的動(dòng)態(tài)范圍。實(shí)際上大多數(shù)邊緣推理場(chǎng)景都有固定的視頻路數(shù)和固定分辨率動(dòng)態(tài)shape的收益遠(yuǎn)小于它帶來的復(fù)雜度。5.2 多進(jìn)程多路并發(fā)怎么搭A(yù)tlas 300V Pro 24G有24GB顯存單路YOLOv5s推理占顯存約2-3GB理論上一張卡能跑多路。但千萬(wàn)不要把所有視頻流塞進(jìn)同一個(gè)進(jìn)程里串行推理。更合理的做法是一個(gè)進(jìn)程處理一路視頻或者把幀收集到隊(duì)列后按batch推理。實(shí)際項(xiàng)目中我用的是“一卡多進(jìn)程”模式每個(gè)視頻流一個(gè)進(jìn)程進(jìn)程內(nèi)做解碼、預(yù)處理、推理、后處理。顯存和NPU算力由驅(qū)動(dòng)做調(diào)度。這樣隔離性最好單路崩潰不影響其他路。如果希望高峰期吞吐更高再在一路視頻內(nèi)把多幀拼成一個(gè)batch用batch4的OM模型做批量推理。多進(jìn)程模式下要留意acl.init和set_device在每個(gè)進(jìn)程內(nèi)都要調(diào)用一次不要圖省事在父進(jìn)程初始化后fork子進(jìn)程否則子進(jìn)程的設(shè)備上下文狀態(tài)不可控容易出現(xiàn)推理超時(shí)。5.3 量化、DVPP和算子融合的提速空間部署穩(wěn)定之后性能優(yōu)化有幾條路第一INT8量化。YOLOv5s用FP16/FP32推理已經(jīng)不錯(cuò)但I(xiàn)NT8能把吞吐再提一截。CANN生態(tài)里有AMCT模型壓縮工具支持后訓(xùn)練量化用一批校準(zhǔn)圖片統(tǒng)計(jì)量化因子。量化后模型體積變小、推理速度接近翻倍代價(jià)是精度可能掉0.5-2個(gè)點(diǎn)。是否需要取決于你的業(yè)務(wù)精度底線。第二DVPP硬解碼。前面說的視頻編解碼模塊不是擺設(shè)。用dvpp接口直接解碼視頻流輸出YUV幀再做AIPP轉(zhuǎn)RGB能省掉CPU軟解和顏色空間轉(zhuǎn)換的開銷。實(shí)測(cè)下來8路1080P視頻流的解碼CPU占用能從60%降到10%以內(nèi)。不過DVPP對(duì)輸入格式和分辨率對(duì)齊有要求比如寬高要偶數(shù)對(duì)齊這些細(xì)節(jié)得翻CANN的DVPP文檔。第三算子融合。ATC編譯時(shí)默認(rèn)會(huì)做常見融合比如ConvBNReLU融合。如果發(fā)現(xiàn)某些算子在圖上單獨(dú)存在導(dǎo)致性能瓶頸可以看CANN提供的算子融合配置項(xiàng)但一般用默認(rèn)設(shè)置就夠了。不要為了優(yōu)化而優(yōu)化先量化再動(dòng)融合。6. 常見問題排查速查表下面這些是部署過程中高頻踩坑整理成速查表遇到類似報(bào)錯(cuò)直接按表查?,F(xiàn)象可能原因解決辦法acl.init失敗錯(cuò)誤碼507008驅(qū)動(dòng)/固件/CANN版本不匹配設(shè)備文件權(quán)限異常內(nèi)核模塊未加載檢查npu-smi info是否能正常顯示確認(rèn)驅(qū)動(dòng)和固件版本重新加載drv_pcie模塊按配套表重裝ATC報(bào)錯(cuò)EZ0101算子不支持ONNX算子無(wú)法映射到CANN算子降低opset版本升級(jí)CANN查看日志定位具體算子改網(wǎng)絡(luò)結(jié)構(gòu)或換成等價(jià)算子ATC報(bào)錯(cuò)SOC版本不匹配--soc_version填錯(cuò)查產(chǎn)品型號(hào)對(duì)應(yīng)表用npu-smi info確認(rèn)芯片類型推理結(jié)果全0或坐標(biāo)偏移輸入通道順序錯(cuò)誤、letterbox padding沒去掉、歸一化系數(shù)不對(duì)、輸出shape理解錯(cuò)打印輸入和輸出shape核對(duì)預(yù)處理鏈路每個(gè)環(huán)節(jié)用一張圖逐層對(duì)比輸出推理結(jié)果類別錯(cuò)亂但坐標(biāo)正確RGB/BGR通道交換配置錯(cuò)誤在AIPP配置或預(yù)處理中交換R和B通道保持訓(xùn)練時(shí)輸入一致設(shè)備顯存不足0x506010單卡顯存被多路進(jìn)程占滿顯存未釋放減小batch檢查是否有資源泄漏用npu-smi info監(jiān)控顯存占用DVPP解碼報(bào)錯(cuò)輸入分辨率或編碼格式不符合DVPP要求確認(rèn)寬高偶數(shù)對(duì)齊確認(rèn)輸入是H.264/H.265裸流或符合要求的封裝查文檔對(duì)齊要求模型加載失敗提示文件損壞或版本不符OM文件與目標(biāo)芯片型號(hào)不匹配用當(dāng)前芯片型號(hào)重新ATC編譯OM其中推理結(jié)果全0這個(gè)問題我調(diào)試了最久。最后發(fā)現(xiàn)是預(yù)處理代碼里np.transpose寫錯(cuò)了維度順序圖像從HWC轉(zhuǎn)CHW時(shí)通道順序變成了不入流的結(jié)果模型吃進(jìn)去的完全是噪聲。所以排查這個(gè)問題時(shí)建議先用一張純色圖跑推理如果輸出也和純色圖對(duì)不上說明預(yù)處理鏈路有硬傷先修預(yù)處理再看模型。環(huán)境類問題里最隱蔽的是“驅(qū)動(dòng)裝了、CANN裝了、但acl.init還是失敗”。我當(dāng)時(shí)查了半天才發(fā)現(xiàn)是用戶權(quán)限不夠設(shè)備節(jié)點(diǎn)只能root訪問。普通用戶跑推理前要給設(shè)備節(jié)點(diǎn)加訪問權(quán)限或者在服務(wù)里以合適用戶運(yùn)行。生產(chǎn)環(huán)境建議用昇騰容器鏡像鏡像里已經(jīng)配好權(quán)限和環(huán)境變量能少踩很多坑。7. 部署之外把Atlas當(dāng)成正式生產(chǎn)設(shè)備來管理項(xiàng)目跑通只是第一步真正把它放上生產(chǎn)再看還有一些管理層面的經(jīng)驗(yàn)值得記下來。首先是開機(jī)自檢和恢復(fù)。服務(wù)器重啟后驅(qū)動(dòng)不一定自動(dòng)加載npu-smi info可能暫時(shí)看不到卡。生產(chǎn)環(huán)境建議做啟動(dòng)后的設(shè)備自檢腳本檢測(cè)到設(shè)備異常就觸發(fā)告警而不是等推理服務(wù)超時(shí)了才發(fā)現(xiàn)。其次是顯存監(jiān)控。多路進(jìn)程共享一張卡時(shí)顯存分配不均衡會(huì)互相影響。我在實(shí)際部署中給每個(gè)進(jìn)程指定了顯存上限策略并在監(jiān)控面板上持續(xù)觀察每路占用的顯存曲線。一旦某一路異常上漲一般是圖像分辨率突變或模型加載了額外buffer及時(shí)重啟該路進(jìn)程不影響其他路。最后是容器化部署。昇騰提供了配套的CANN容器鏡像把驅(qū)動(dòng)、固件、CANN都封裝好宿主機(jī)只需要裝驅(qū)動(dòng)。我后來把推理服務(wù)打成鏡像內(nèi)部初始化時(shí)再source環(huán)境變量代碼統(tǒng)一管理?yè)Q機(jī)器部署時(shí)拉鏡像就能跑比手工裝環(huán)境省太多時(shí)間。唯一的注意點(diǎn)是容器要映射設(shè)備節(jié)點(diǎn)啟動(dòng)時(shí)加--device/dev/davinci0和對(duì)應(yīng)管控節(jié)點(diǎn)否則容器里看不到卡。整套流程走下來我最大的感受是Atlas這套東西不是拿來即用的即插即型生態(tài)它需要你花一兩天時(shí)間把環(huán)境、格式、參數(shù)這些基礎(chǔ)事情磨平。但只要鏈路通了它在多路推理場(chǎng)景下的穩(wěn)定性和性能是很能打的。給剛開始接觸的同學(xué)一個(gè)建議第一版不求多路、不求動(dòng)態(tài)、不求INT8只用固定shape、單路、FP32把全流程跑通。跑通了你對(duì)整個(gè)鏈路的理解就建立起來了后面加容器、加并發(fā)、加量化都是水到渠成的事。如果一上來就想直接跑一個(gè)復(fù)雜的多路動(dòng)態(tài)模型每個(gè)環(huán)節(jié)都在報(bào)錯(cuò)反而容易勸退。