戰(zhàn):從環(huán)境配置到性能調(diào)優(yōu))
拿到這塊卡的第一周我基本處于反復(fù)裝驅(qū)動(dòng)、反復(fù)重啟、反復(fù)看npu-smi info的狀態(tài)。Atlas 300V 24G在網(wǎng)上資料不算少但雜且版本之間差異很大。直到把一個(gè)YOLOv5模型跑起來、延時(shí)打點(diǎn)穩(wěn)定在個(gè)位數(shù)毫秒級(jí)才覺得這卡真正可用了。這篇東西就按我實(shí)際走通的路子來寫先回答熱搜里那個(gè)Atlas 300V 24G是不是運(yùn)算加速卡的問題再講我在這張卡上部署YOLO的完整鏈路——從環(huán)境準(zhǔn)備、模型轉(zhuǎn)換、推理代碼到性能調(diào)優(yōu)最后是那些不翻文檔根本不知道的坑。如果你是第一次拿昇騰推理卡干活照著走能省不少時(shí)間。1. 先拆熱搜Atlas 300V 24G到底算不算運(yùn)算加速卡1.1 這塊卡的家族定位與關(guān)鍵參數(shù)Atlas 300V Pro 24G屬于華為昇騰推理卡系列核心芯片是昇騰310P24GB LPDDR4X顯存單槽半高半長75W功耗通過PCIe接口插在服務(wù)器上被動(dòng)散熱需要機(jī)箱風(fēng)道。這些參數(shù)本身已經(jīng)說明問題它是一張推理加速卡不是用來練模型的訓(xùn)練卡。我手上這張卡在npu-smi info里能看到完整的設(shè)備信息芯片型號(hào)310P顯存24GB溫度、功耗、算力占用都能實(shí)時(shí)監(jiān)控。官方標(biāo)稱的INT8算力在140 TOPS量級(jí)FP16算力在16 TFLOPS量級(jí)。單看INT8數(shù)字確實(shí)唬人但別拿它跟A100去比訓(xùn)練性能兩個(gè)東西壓根不是一個(gè)賽道。注意Atlas 300V系列還有雙芯片版本比如Atlas 300V Duo配置和單芯片版本不同部署時(shí)soc_version參數(shù)也對(duì)應(yīng)不同。買卡之前先確認(rèn)自己手里的型號(hào)不要照著單芯片的教程硬套。1.2 它和訓(xùn)練GPU的差別為什么說它是推理加速器很多人容易犯一個(gè)概念錯(cuò)誤以為只要是GPU或者加速卡就能同時(shí)兼顧訓(xùn)練和推理。實(shí)際上昇騰310P這顆芯片的設(shè)計(jì)思路非常聚焦——它就是干推理的。芯片內(nèi)部大量資源用在算子加速、內(nèi)存帶寬、多路視頻解碼上而通用計(jì)算的靈活性遠(yuǎn)不如NVIDIA的GPU。從實(shí)用角度講它適合三件事訓(xùn)練好的模型做批量離線推理比如把幾十萬張圖片跑一遍分類或檢測(cè)在線服務(wù)場(chǎng)景下的低延時(shí)推理比如視頻流里逐幀檢測(cè)只要模型和芯片匹配延時(shí)能壓得很低邊緣服務(wù)器上同時(shí)跑多路視頻分析310P的視頻編解碼單元能硬解多路H.264/H.265流CPU完全不用參與。它不適合的事也明確不適合拿來做訓(xùn)練不適合跑需要復(fù)雜動(dòng)態(tài)shape的模型還不適合依賴大量自定義算子的人——昇騰的算子生態(tài)在快速補(bǔ)齊但和CUDA生態(tài)比還是差著量級(jí)。所以如果你手頭只有一張Atlas 300V 24G最好把它當(dāng)高吞吐推理引擎來用而不是小GPU來用。2. 部署YOLO的第一步驅(qū)動(dòng)、固件與CANN環(huán)境搭建2.1 npu-smi裝完驅(qū)動(dòng)先看這張卡安裝順序是固件再驅(qū)動(dòng)或者直接裝包含固件的驅(qū)動(dòng)包。裝完之后別急著跑模型先敲一句命令npu-smi info如果能正常列出卡的溫度、功耗、芯片和多卡拓?fù)湔f明驅(qū)動(dòng)基本OK。常見的問題是驅(qū)動(dòng)裝了但固件沒刷明明npu-smi info能看到卡一跑ACL就報(bào)初始化失敗概率極大。驅(qū)動(dòng)和固件的版本配對(duì)非常講究。昇騰的驅(qū)動(dòng)、固件、CANN工具包三者存在嚴(yán)格的兼容矩陣版本對(duì)不上輕則報(bào)E10042這類初始化錯(cuò)誤重則直接黑屏。我的經(jīng)驗(yàn)是先確定操作系統(tǒng)版本再根據(jù)操作系統(tǒng)找對(duì)應(yīng)版本的CANN最后按CANN要求的配套驅(qū)動(dòng)和固件版本一步步裝上去。安裝CANN時(shí)我實(shí)際用的是社區(qū)版工具包./Ascend-cann-toolkit_7.0.RC1_x86_64-linux.run --install安裝到/usr/local/Ascend下然后必須把這幾個(gè)路徑加進(jìn)環(huán)境變量source /usr/local/Ascend/ascend-toolkit/set_env.sh export LD_LIBRARY_PATH/usr/local/Ascend/ascend-toolkit/latest/lib64:$LD_LIBRARY_PATH2.2 CANN安裝與環(huán)境變量環(huán)境配錯(cuò)后面全白干CANN是整個(gè)昇騰軟件棧的核心它提供ACLAscend Computing Language推理接口、ATC模型轉(zhuǎn)換工具、算子庫這些運(yùn)行時(shí)依賴。沒有CANN驅(qū)動(dòng)裝得再好也調(diào)不起模型。環(huán)境變量設(shè)置是這里最容易翻車的一環(huán)——set_env.sh沒有source后面跑Python腳本時(shí)就會(huì)報(bào)找不到libascendcl.so。這類問題排查起來也很快先確認(rèn)環(huán)境變量到底有沒有生效echo $ASCEND_HOME_PATH ldconfig -p | grep ascend我踩過一次比較隱蔽的坑同時(shí)裝了多個(gè)CANN版本LD_LIBRARY_PATH指到了舊版本的lib目錄結(jié)果新轉(zhuǎn)換的OM模型加載時(shí)提示算子不兼容。所以如果你的服務(wù)器上同時(shí)存在多個(gè)CANN路徑一定要用ll確認(rèn)一下/usr/local/Ascend/ascend-toolkit/latest到底指向的是哪個(gè)版本。提示安裝完成后跑官方自帶的樣例sample做個(gè)冒煙測(cè)試比直接上自己的YOLO模型穩(wěn)得多。樣例跑通說明環(huán)境基本沒問題后面模型報(bào)錯(cuò)可以聚焦到模型側(cè)樣例跑不通就老老實(shí)實(shí)回來查驅(qū)動(dòng)固件和CANN的版本配對(duì)。3. 模型轉(zhuǎn)換鏈路PyTorch → ONNX → OM3.1 導(dǎo)出ONNX時(shí)先決定shape策略Atlas推理卡不像GPU那樣能隨手接受PyTorch的動(dòng)態(tài)圖它需要先把PyTorch的state_dict固化成計(jì)算圖描述ONNX是其中最常見的中間格式。整個(gè)鏈路是YOLOv5的.pt權(quán)重 → onnx模型 → ATC工具轉(zhuǎn)換成.om模型然后ACL或者M(jìn)indX SDK去加載這個(gè).om文件。YOLOv5官方倉庫自帶export.py可以直接導(dǎo)出ONNXpython export.py --weights yolov5s.pt --include onnx --opset 11 --batch-size 1導(dǎo)出時(shí)有一個(gè)必須想清楚的決策shape是固定還是動(dòng)態(tài)。固定shape例如1,3,640,640轉(zhuǎn)換出來的OM在推理時(shí)效率最高ATC能針對(duì)固定shape做充分的算子融合和內(nèi)存復(fù)用動(dòng)態(tài)shape-1,3,-1,-1意味著輸入尺寸可以任意變但性能會(huì)打折部分算子可能走fallback而且ATC轉(zhuǎn)換時(shí)必須設(shè)置動(dòng)態(tài)維度范圍否則直接報(bào)錯(cuò)。我的建議是業(yè)務(wù)輸入尺寸固定就老老實(shí)實(shí)固定shape。YOLO這類檢測(cè)模型的輸入通常都是正方形640x640最常見把模型固定成NCHW 1,3,640,640省心又高效。如果一定要支持多種分辨率寧可轉(zhuǎn)換多個(gè)OM模型按分辨率去加載也不要去搞動(dòng)態(tài)shape省下的那點(diǎn)顯存不值得。3.2 ATC轉(zhuǎn)換參數(shù)、輸出節(jié)點(diǎn)與常見坑導(dǎo)出ONNX之后用ATC工具把ONNX轉(zhuǎn)成昇騰的OM格式。核心命令大概是這樣atc --modelyolov5s.onnx \ --framework5 \ --outputyolov5s_bs1 \ --input_formatNCHW \ --input_shapeimages:1,3,640,640 \ --soc_versionAscend310P3 \ --output_typeFP16 \ --logerror逐個(gè)說下參數(shù)的含義--framework55代表ONNX1代表MindSpore2代表TensorFlow別記混。--input_shape需要和導(dǎo)出的ONNX輸入節(jié)點(diǎn)名字、順序完全對(duì)應(yīng)。YOLOv5導(dǎo)出的輸入名是images如果你的模型輸入名不一樣先看ONNX圖確認(rèn)。--soc_version芯片型號(hào)310P填A(yù)scend310P3。不確定的話參考npu-smi info里的芯片型號(hào)或者去查CANN文檔里的SoC版本列表。--output_typeFP16把模型轉(zhuǎn)成半精度推理。YOLOv5量化敏感度不高FP16精度損失可忽略推理速度比FP32快不少。這里有兩個(gè)高頻坑。第一個(gè)是ONNX里存在ATC不支持的算子。這是做昇騰部署最常見的卡點(diǎn)。解決辦法不是硬寫算子而是先去昇騰社區(qū)查一下支持算子清單然后繞開。比如YOLOv5的Detect頭里有大量grid生成、sigmoid、exp組合運(yùn)算我建議導(dǎo)出ONNX時(shí)把檢測(cè)頭去掉只保留backboneneck輸出的三個(gè)特征層8,16,32三個(gè)stride的特征圖后處理放到Python或者M(jìn)indX SDK的插件里做。這樣模型結(jié)構(gòu)簡(jiǎn)單ATC轉(zhuǎn)換失敗率會(huì)大幅下降。第二個(gè)坑是轉(zhuǎn)換時(shí)沒注意輸出節(jié)點(diǎn)。如果ONNX的檢測(cè)頭還在ATC會(huì)把整個(gè)計(jì)算圖都固化進(jìn)OM后處理的一部分計(jì)算也被算進(jìn)OM里表面上省了CPU開銷實(shí)際上對(duì)動(dòng)態(tài)shape的支持和精度控制都很受限。所以我的固定做法是ONNX只出特征圖后處理全部留在外面用Python處理后面調(diào)精度、調(diào)NMS閾值都方便。4. 用pyACL寫一版完整的YOLOv5推理4.1 初始化、加載模型、讀入tensor模型轉(zhuǎn)換好了接下來就是寫推理程序。昇騰PyTorch生態(tài)里有幾種方式我只說我驗(yàn)證過最直接好用的一條Python pyACL。pyACL是C語言ACL的Python綁定接口風(fēng)格是命令式逐級(jí)初始化acl.init初始化整個(gè)運(yùn)行時(shí)rt.set_device指定設(shè)備mdl.load_from_file加載OM模型。整個(gè)流程和CUDA的上下文模式有點(diǎn)像只要順著接口順序走邏輯并不復(fù)雜。核心初始化代碼import acl acl.init() ret acl.rt.set_device(0) # 設(shè)備IDnpu-smi里看到的邏輯ID context, ret acl.rt.create_context(0) model_path yolov5s_bs1.om model_id, ret acl.mdl.load_from_file(model_path) model_desc acl.mdl.create_desc() acl.mdl.get_desc(model_desc, model_id)加載模型之后需要從model_desc里分別取出輸入和輸出的buffer大小然后申請(qǐng)device側(cè)的內(nèi)存。這一步不能省ACL推理要求把輸入數(shù)據(jù)放到顯存里這和GPU的習(xí)慣類似input_size acl.mdl.get_input_size_by_index(model_desc, 0) output_size acl.mdl.get_output_size_by_index(model_desc, 0) input_data, ret acl.rt.malloc(input_size, ACL_MEM_MALLOC_NORMAL_ONLY) output_data, ret acl.rt.malloc(output_size, ACL_MEM_MALLOC_NORMAL_ONLY)注意ACL里的malloc返回的地址是一個(gè)int類型的指針值后續(xù)用acl.rt.memcpy把numpy數(shù)組拷進(jìn)去時(shí)需要先把numpy數(shù)組轉(zhuǎn)成字節(jié)串再通過acl.util.bytes_to_ptr拿到指針。字節(jié)串和指針之間的轉(zhuǎn)換是pyACL里最容易寫出內(nèi)存問題的地方建議封裝成函數(shù)統(tǒng)一處理。4.2 推理與后處理銜接的代碼框架模型推理本身只占整個(gè)部署工作量的三成剩下七成是后處理。YOLOv5的原始輸出是三個(gè)尺度的特征圖(1, 255, 80, 80)、(1, 255, 40, 40)、(1, 255, 20, 20)以640輸入為例2553個(gè)anchor×(clsxywhobj)。如果你按我前面的建議只導(dǎo)出到特征層輸出就是這些。在推理代碼里整個(gè)流程是import numpy as np import cv2 # 假設(shè)已經(jīng)是ndarrayshape(1,3,640,640)RGB0~255 img_bytes img.tobytes() acl.rt.memcpy(input_data, input_size, acl.util.bytes_to_ptr(img_bytes), input_size, ACL_MEMCPY_DEVICE_TO_DEVICE) stream acl.rt.create_stream() acl.mdl.execute_async(model_id, [input_data], [output_data], stream) acl.rt.synchronize_stream(stream) # 把輸出拷回內(nèi)存 out_bytes acl.util.ptr_to_bytes(output_data, output_size) output np.frombuffer(out_bytes, dtypenp.float16).reshape((1, 255, 80, 80))這里有幾個(gè)關(guān)鍵點(diǎn)輸入buffer的排布必須是連續(xù)的NCHW數(shù)據(jù)tobytes()本身就是按內(nèi)存順序序列化所以只要你的numpy數(shù)組是(1,3,640,640)且元素順序正確memcpy過去就行。如果轉(zhuǎn)換時(shí)指定了--output_typeFP16輸出數(shù)據(jù)是float16讀取時(shí)一定要指定dtypenp.float16否則解析出來的全是亂碼。如果輸出是(1, 255, 80, 80)這樣的C-first格式CHW后處理需要先transpose成(1, 80, 80, 255)再解析anchor這個(gè)維度順序直接對(duì)應(yīng)原YOLOv5代碼里的[bs, na, ny, nx, no]結(jié)構(gòu)處理錯(cuò)了結(jié)果全錯(cuò)。后處理部分就是標(biāo)準(zhǔn)YOLOv5了先做anchor解碼把特征圖映射到原圖坐標(biāo)再做conf閾值過濾和NMS。昇騰的社區(qū)樣例基本都是這么寫你可以直接參考。唯一要提醒的是NMS在CPU上做務(wù)必用向量化寫法不要用Python循環(huán)否則模型推理只要幾毫秒后處理能給你拖到幾十毫秒性能全毀。5. 性能打點(diǎn)與優(yōu)化方向從FP16到INT8、多batch、AIPP5.1 一版基準(zhǔn)性能數(shù)據(jù)環(huán)境跑通后我做的第一件事就是打性能基準(zhǔn)。YOLOv5s640x640輸入FP16推理不包含后處理純粹測(cè)ACL的推理耗時(shí)。測(cè)出來的數(shù)據(jù)大概是配置單幀推理耗時(shí)備注FP16, batch18-10 ms不含圖片decode和后處理FP16, batch4平均單幀約5-6 ms總耗時(shí)約22msINT8, batch15-7 ms需要先量化INT8, batch4平均單幀約3-4 ms總耗時(shí)約14ms這個(gè)數(shù)據(jù)是基于我當(dāng)時(shí)的CANN版本實(shí)測(cè)的不同版本可能有偏差但量級(jí)可以參考。如果是更小的模型比如YOLOv5n單幀可以壓到3-5ms如果換成YOLOv8m這類大模型單幀會(huì)到20ms以上。先弄清楚自己的模型在什么量級(jí)再?zèng)Q定要不要上優(yōu)化手段。5.2 從FP16到INT8量化精度與收益想進(jìn)一步壓推理延時(shí)最有效的方向是轉(zhuǎn)INT8。昇騰的INT8量化不是像TensorRT那樣一個(gè)命令自動(dòng)搞定中間要過一把AMCT工具做模型校準(zhǔn)PTQ。流程大致是準(zhǔn)備幾百張有代表性的校準(zhǔn)圖片用AMCT跑一遍校準(zhǔn)腳本產(chǎn)出量化后的ONNX模型用ATC把量化后的ONNX轉(zhuǎn)成INT8的OM推理時(shí)驗(yàn)證精度。精度方面目標(biāo)檢測(cè)模型普遍比分類模型對(duì)量化更敏感。YOLOv5s轉(zhuǎn)INT8之后mAP一般會(huì)掉0.5到1個(gè)點(diǎn)左右視覺上基本看不出差異。但如果校準(zhǔn)集選得不好比如全是白天場(chǎng)景、沒有夜間樣本掉點(diǎn)可能超過3個(gè)點(diǎn)這時(shí)候就得擴(kuò)充校準(zhǔn)集或者在AMCT配置里給敏感層配置更高的量化精度。提示INT8量化不是必然選擇。如果FP16已經(jīng)能滿足實(shí)時(shí)性要求比如單路視頻25FPS就沒有必要冒精度損失的風(fēng)險(xiǎn)去量化。量化是性能不夠時(shí)的最后一招不是上來就要做的事。5.3 多batch與多流真正吃滿這張卡單batch的延時(shí)達(dá)標(biāo)了接著就要考慮吞吐。Atlas 300V 24G顯存24GBYOLOv5s一個(gè)batch的顯存占用大約幾百M(fèi)B意味著顯存幾乎不成為限制限制在算力上。要提升吞吐兩個(gè)方向多batch和多流。多batch最直接轉(zhuǎn)換OM的時(shí)候把輸出batch設(shè)為4推理時(shí)一次丟4張圖進(jìn)去算力利用率會(huì)明顯上升。但注意--input_shape一旦固定成4,3,640,640就不能再拿單張圖去跑了需要把輸入buffer填滿4張圖的tensor。對(duì)在線服務(wù)來說需要自己做一個(gè)batch湊集器把多路請(qǐng)求攢成一批再送進(jìn)去實(shí)現(xiàn)復(fù)雜度略高。多流是昇騰特有的優(yōu)化思路一個(gè)設(shè)備可以創(chuàng)建多個(gè)context每個(gè)context獨(dú)立跑一個(gè)推理任務(wù)相當(dāng)于把310P的多個(gè)計(jì)算單元分開調(diào)度。多流的好處是單幀延時(shí)不會(huì)因?yàn)闇恇atch而變大適合對(duì)延時(shí)敏感的場(chǎng)景。我的經(jīng)驗(yàn)數(shù)據(jù)是4流并發(fā)的時(shí)候整體吞吐基本是單流的2.5-3倍而且單幀延時(shí)只增加10%左右。實(shí)際做視頻分析的場(chǎng)景里我推薦多路視頻各自解碼多流推理的組合比如8路視頻流每路50%計(jì)算量讓310P的編解碼單元去硬解CPU只負(fù)責(zé)后處理這樣既吃滿硬件又不拖累實(shí)時(shí)性。6. 我踩過的那些坑版本、精度、后處理6.1 版本不匹配很多玄學(xué)問題的元兇說一個(gè)我印象最深的詭異問題模型轉(zhuǎn)換成功、加載成功、單次推理也能出結(jié)果但結(jié)果和GPU上跑出來的完全不同不是差一點(diǎn)點(diǎn)是框的位置完全對(duì)不上。排查了整整一天最后發(fā)現(xiàn)是驅(qū)動(dòng)版本太舊CANN 7.0的功能集沒能完全發(fā)揮需要升級(jí)驅(qū)動(dòng)。這類問題在昇騰社區(qū)基本能占掉一半帖子。它表現(xiàn)為各種詭異狀態(tài)推理結(jié)果偶爾正常偶爾錯(cuò)誤、顯存申請(qǐng)偶爾失敗、算子執(zhí)行報(bào)ACL_ERROR_RT_PARAM_INVALID。原因往往是驅(qū)動(dòng)、固件、CANN三者版本不匹配。我的經(jīng)驗(yàn)是每次安裝前先去昇騰官方文檔查版本配套表看CANN版本支持的驅(qū)動(dòng)和固件最低版本是多少再檢查自己機(jī)器的固件版本。用好這個(gè)命令排查cat /usr/local/Ascend/driver/version.info如果版本不對(duì)不要猶豫該升級(jí)驅(qū)動(dòng)就升級(jí)。這個(gè)環(huán)節(jié)偷懶后面省下的時(shí)間全都會(huì)加倍還回去。6.2 精度對(duì)不上一步步排查模型能跑但精度不對(duì)這種問題也很常見。GPU上用原版PyTorch跑出來精度正常到了Atlas上mAP掉很多或者框的位置偏移通常先從三個(gè)方向排查第一輸入預(yù)處理方式。YOLOv5的訓(xùn)練腳本里輸入是RGB還是BGR歸一化是除以255還是減均值再乘方差這些邏輯每個(gè)版本都可能有差異。ATC和AIPP的配置里默認(rèn)了RGB歸一化方式如果和你的模型訓(xùn)練邏輯不一致推理結(jié)果必然漂移。我建議不要依賴AIPP的預(yù)處理在Python端自己做預(yù)處理確保和PyTorch訓(xùn)練時(shí)完全一致排查時(shí)少一個(gè)變量。第二模型輸入layout。PyTorch默認(rèn)NCHWONNX導(dǎo)出也是NCHW但ATC轉(zhuǎn)換時(shí)如果指定了NHWC要么轉(zhuǎn)換報(bào)錯(cuò)要么結(jié)果異常。確認(rèn)多個(gè)環(huán)節(jié)的輸入格式一致能減少很多詭異問題。第三輸出數(shù)據(jù)解析。如前面提到的FP16和FP32解析方式不一樣維度順序如果沒轉(zhuǎn)成(batch, anchors, grid_h, grid_w, attributes)后處理結(jié)果也全是錯(cuò)的。遇到精度問題我建議先不跑完整模型構(gòu)造一個(gè)只有第一層算子的最小ONNX或直接用單張圖、單層算子在GPU和Atlas上對(duì)比輸出逐步縮小范圍。這個(gè)過程可能比較枯燥但比瞎猜瞎改快得多。6.3 后處理成了瓶頸一次性能優(yōu)化親歷頭一回測(cè)性能我在FP16單batch推理已經(jīng)跑到8ms的情況下整個(gè)流程居然還要30ms多。用profile一打發(fā)現(xiàn)18ms都花在了后處理的NMS上——我最初是照著YOLOv5原版的循環(huán)實(shí)現(xiàn)寫的在GPU上循環(huán)幾萬個(gè)框沒什么感覺但在CPU上跑640x640輸出三萬多候選框的循環(huán)NMS簡(jiǎn)直災(zāi)難。優(yōu)化方法很簡(jiǎn)單用numpy的向量化操作替代循環(huán)candidate篩選、iou計(jì)算、nms抑制全部用矩陣運(yùn)算實(shí)現(xiàn)。這一步做完后處理從18ms降到了2ms左右。再進(jìn)一步如果batch不是1后處理也做batch處理總吞吐還能再漲一截。后來我干脆用MindX SDK的mxVision流水線來做推理后處理。它自帶一些檢測(cè)模型的后處理插件算子級(jí)融合已經(jīng)優(yōu)化過不需要自己寫numpy代碼。如果你對(duì)pyACL已經(jīng)足夠熟悉純手寫也沒問題但如果追求省事和極致性能上MindX SDK是更劃算的選擇。整體來說Atlas 300V 24G是一張性價(jià)比很高的推理卡尤其適合YOLO系列的部署。我自己的經(jīng)驗(yàn)是模型結(jié)構(gòu)盡量裁剪ONNX只保留特征提取部分后處理放在外面做環(huán)境版本嚴(yán)格配套轉(zhuǎn)換shape固定先跑通再優(yōu)化性能優(yōu)化按FP16單幀→多batch→多流→INT8量化的順序推進(jìn)不要一上來就上最激進(jìn)的方案。照著這個(gè)思路從零到跑通一張卡的YOLO部署兩個(gè)工作日之內(nèi)是可以做到的。