戰(zhàn):版本匹配與踩坑記錄)
1. 在16.04上做這件事前先想清楚三件事1.1 為什么Ubuntu 16.04折騰GLIBC和Python生態(tài)的年代差先說(shuō)個(gè)現(xiàn)實(shí)問題Ubuntu 16.04發(fā)布于2016年自帶GLIBC 2.23而mmdetection的現(xiàn)代版本和配套編譯工具鏈很多編譯產(chǎn)物都依賴更高的GLIBC版本。之前我在一臺(tái)老機(jī)器上直接照搬新教程結(jié)果在import torch那一步就報(bào)GLIBC_2.29 not found當(dāng)時(shí)整個(gè)人是懵的。這個(gè)報(bào)錯(cuò)的意思很直白你想用的PyTorch或mmcv編譯時(shí)是基于新版系統(tǒng)的動(dòng)態(tài)庫(kù)鏈接的GLIBC符號(hào)在你的系統(tǒng)里根本不存在。解決辦法不是去網(wǎng)上找一堆不安全的二進(jìn)制替換libc而是老老實(shí)實(shí)選擇一套和系統(tǒng)年代匹配的版本組合。同樣的問題也出現(xiàn)在Python層面。16.04系統(tǒng)自帶的Python 3.5已經(jīng)非常老了很多新版本的mmdet、mmcv都不再兼容Python 3.5。我在實(shí)際配置中把它鎖定在Python 3.7不追新原因后面會(huì)展開說(shuō)。所以入手16.04裝mmdetection的第一認(rèn)知就是不要試圖全上最新版本而是要構(gòu)建一套“古董但自洽”的版本矩陣。誰(shuí)先接受“老系統(tǒng)配老版本”這個(gè)現(xiàn)實(shí)誰(shuí)就能少踩三分之二的坑。適合看這篇內(nèi)容的人我總結(jié)一下手里正好有16.04的老機(jī)器、或者因?yàn)轱@卡驅(qū)動(dòng)原因只能留在16.04、再或者在某些工控設(shè)備上必須用老內(nèi)核的人。如果你的機(jī)器可以隨便裝20.04以上系統(tǒng)我建議你直接上新系統(tǒng)別回頭。1.2 顯卡、驅(qū)動(dòng)、CUDA三角約束先搞定在裝任何軟件之前先把顯卡型號(hào)確認(rèn)清楚。在16.04這種老系統(tǒng)上顯卡驅(qū)動(dòng)版本和CUDA版本是互相鎖死的順序不能亂。我當(dāng)時(shí)的做法是三步走。第一步用lspci | grep -i nvidia查看顯卡型號(hào)第二步去NVIDIA官網(wǎng)看該型號(hào)支持的最新驅(qū)動(dòng)版本第三步根據(jù)驅(qū)動(dòng)版本反推CUDA版本。實(shí)際中遇到過(guò)這樣一個(gè)例子一臺(tái)機(jī)器是GTX 1080 Ti驅(qū)動(dòng)版本390.xx這個(gè)驅(qū)動(dòng)最高只支持到CUDA 9.2左右。這意味著你最多也就用PyTorch 1.0左右的版本mmdetection基本沒法跑。這時(shí)候就得考慮升級(jí)驅(qū)動(dòng)到440以上才能用CUDA 10.2。顯卡驅(qū)動(dòng)版本可用的CUDA版本可搭配的PyTorch建議390.xxCUDA 9.2及以下PyTorch 1.0以下不推薦跑mmdetection418/430CUDA 10.1/10.2PyTorch 1.5~1.8450CUDA 11.0/11.3PyTorch 1.8~1.10這里額外提一句如果你連顯卡都沒有只想用CPU跑一跑示例那也請(qǐng)保持CPU版PyTorch的版本對(duì)應(yīng)關(guān)系不要混裝。1.3 是不是非16.04不可很多人的掙扎在于周圍教程都是18.04、20.04自己這臺(tái)機(jī)器偏偏是16.04。這時(shí)候我通常給出的建議排序是能上20.04就上20.04這是最優(yōu)解一套新版本組合隨便配。因?yàn)槔巷@卡或軟件依賴無(wú)法升級(jí)系統(tǒng)的選擇16.04 老版本組合也就是本文的主題。既不能換系統(tǒng)、又想用新功能——可以考慮用Docker容器在Docker里跑新版Ubuntu鏡像。但這對(duì)顯卡直通和nvidia-container-toolkit有要求而且16.04主機(jī)內(nèi)核老Docker的gpu參數(shù)兼容性需要專門測(cè)試我試下來(lái)反倒是裸裝更快。我個(gè)人的傾向是如果確定留在16.04就干脆把心氣放平把本文推薦的老版本組合當(dāng)標(biāo)準(zhǔn)答案不要再惦記mmdetection最新的3.0版本。2. 驅(qū)動(dòng)、CUDA與conda虛擬環(huán)境一鍋端式的準(zhǔn)備方案2.1 禁用nouveau安裝NVIDIA驅(qū)動(dòng)16.04自帶的nouveau開源驅(qū)動(dòng)和NVIDIA閉源驅(qū)動(dòng)之間的沖突是環(huán)境安裝的第一道坎。不把它禁掉裝完驅(qū)動(dòng)重啟后大概率出現(xiàn)黑屏或循環(huán)登錄。操作順序是這樣的編輯配置文件sudo vim /etc/modprobe.d/blacklist-nouveau.conf寫入下面兩行內(nèi)容blacklist nouveau options nouveau modeset0更新內(nèi)核配置并重啟sudo update-initramfs -u sudo reboot重啟后先確認(rèn)nouveau沒被加載lsmod | grep nouveau如果沒有任何輸出說(shuō)明禁用成功。接著去NVIDIA官網(wǎng)下載對(duì)應(yīng)顯卡的runfile安裝包直接.run文件安裝比apt源里的版本更可控特別是老環(huán)境。安裝命令chmod x NVIDIA-Linux-x86_64-450.142.run sudo ./NVIDIA-Linux-x86_64-450.142.run -no-x-check -no-nouveau-check裝完用nvidia-smi驗(yàn)證。如果顯示驅(qū)動(dòng)版本和顯存信息說(shuō)明驅(qū)動(dòng)沒問題。這一步看似基礎(chǔ)但我見過(guò)太多人跳過(guò)后在mmdet訓(xùn)練時(shí)報(bào)各種CUDA相關(guān)崩潰回頭查才發(fā)現(xiàn)是驅(qū)動(dòng)層的cuda版本根本不兼容。2.2 CUDA與cuDNN安裝盡量用runfile而不是deb包CUDA和cuDNN的安裝方式會(huì)影響后期mmcv編譯的順利程度。16.04上用deb包安裝有個(gè)問題它會(huì)把驅(qū)動(dòng)也一并更新掉導(dǎo)致你辛辛苦苦裝好的驅(qū)動(dòng)版本被覆蓋。所以我的方案是驅(qū)動(dòng)用runfile裝CUDA也用只裝工具庫(kù)的方式不動(dòng)驅(qū)動(dòng)。CUDA下載頁(yè)里選擇Linux、x86_64、Ubuntu 16.04版本對(duì)應(yīng)的runfile。假設(shè)我們選用CUDA 10.2wget https://developer.download.nvidia.com/compute/cuda/10.2/Prod/local_installers/cuda_10.2.89_440.33.01_linux.run sudo sh cuda_10.2.89_440.33.01_linux.run安裝時(shí)注意在提示是否安裝驅(qū)動(dòng)時(shí)選No只安裝CUDA Toolkit。然后設(shè)置環(huán)境變量把下面內(nèi)容加到~/.bashrcexport PATH/usr/local/cuda-10.2/bin:$PATH export LD_LIBRARY_PATH/usr/local/cuda-10.2/lib64:$LD_LIBRARY_PATHcuDNN的安裝更簡(jiǎn)單把下載的cudnn-10.2-linux-x64-v8.2.1.32.tgz解壓然后把文件內(nèi)容拷貝到CUDA目錄下tar -xzvf cudnn-10.2-linux-x64-v8.2.1.32.tgz sudo cp cuda/include/cudnn*.h /usr/local/cuda/include/ sudo cp cuda/lib64/libcudnn* /usr/local/cuda/lib64/這一步完成后記得同步一下軟鏈接否則編譯時(shí)可能出現(xiàn)libcudnn.so.8 not found。這是老系統(tǒng)上非常經(jīng)典的坑因?yàn)?6.04不太會(huì)主動(dòng)刷新動(dòng)態(tài)庫(kù)緩存。2.3 conda環(huán)境與Python 3.7給所有依賴建一個(gè)隔離區(qū)到這一步我強(qiáng)烈建議裝Anaconda或Miniconda絕對(duì)不要直接用系統(tǒng)Python。16.04自帶Python 3.5且很多系統(tǒng)工具鏈依賴它直接覆蓋會(huì)出大問題。Miniconda對(duì)老系統(tǒng)更友好安裝命令wget https://repo.anaconda.com/miniconda/Miniconda3-py37_4.12.0-Linux-x86_64.sh bash Miniconda3-py37_4.12.0-Linux-x86_64.sh安裝時(shí)一路yes最后初始化conda。創(chuàng)建虛擬環(huán)境conda create -n mmdet python3.7 -y conda activate mmdet為什么鎖Python 3.7因?yàn)閙mdetection 2.x時(shí)代的官方README和大量預(yù)編譯的mmcv wheel都明確支持Python 3.7而且3.7在AGES工具箱里兼容性最高。整個(gè)mmdet全家桶對(duì)這個(gè)Python版本支持得最穩(wěn)實(shí)際測(cè)試中3.8也可以但在16.04的GLIBC限制下3.7的輪子最聽話。3. mmcv與mmdetection的版本匹配系統(tǒng)成敗的分水嶺3.1 版本對(duì)應(yīng)關(guān)系別信任何單點(diǎn)教程mmcv和mmdetection的版本匹配關(guān)系極其嚴(yán)格不同大版本之間API有變化連配置字段都可能改過(guò)名。在16.04上我最終是裝成了mmdetection 2.25.1 mmcv-full 1.7.5 PyTorch 1.10.0 CUDA 10.2這一組合。這個(gè)搭配的思考邏輯是Python 3.7 PyTorch 1.10 CUDA 10.2在老驅(qū)動(dòng)能用、且版本不要太老之間取了平衡。mmcv-full 1.7.5這個(gè)版本提供豐富的預(yù)編譯包選項(xiàng)支持PyTorch 1.10。mmdetection 2.25.1是2.x系列的后期版本功能足夠且配置組織方式成熟。這里還需要看一個(gè)關(guān)鍵對(duì)應(yīng)表mmcv與mmdet官方支持關(guān)系mmdetection版本mmcv全版本2.25.1mmcv-full 1.5.1, 1.8.02.18.1mmcv-full 1.4.6, 1.7.02.10.0mmcv-full 1.3.8, 1.4.0別小看這些區(qū)間mmcv版本裝高了或裝低了輕則警告重則直接報(bào)AttributeError或KeyError比如mmdet里用到的某個(gè)函數(shù)在mmcv新版本里被改名了。3.2 安裝PyTorch與mmcv-full的完整命令先裝PyTorch 1.10.0對(duì)應(yīng)CUDA 10.2直接用conda安裝最省事conda install pytorch1.10.0 torchvision0.11.0 torchaudio0.10.0 cudatoolkit10.2 -c pytorch -y這里有個(gè)易錯(cuò)點(diǎn)如果你預(yù)先下載了本地wheel安裝必須保證wheel是CUDA 10.2編譯的。我曾經(jīng)貪快用了pip install torch1.10.0默認(rèn)源結(jié)果拉到了CPU版本訓(xùn)練時(shí)torch.cuda.is_available()一直返回False排查了半天才發(fā)現(xiàn)基礎(chǔ)裝錯(cuò)了。接著裝mmcv-full。有兩個(gè)選擇一是直接用官方預(yù)編譯wheel二是源碼編譯。在16.04上如果預(yù)編譯wheel能匹配到你的Python和CUDA版本那是最快路徑如果報(bào)找不到對(duì)應(yīng)的wheel就老老實(shí)實(shí)從源碼編譯。預(yù)編譯方式pip install mmcv-full1.7.5 -f https://download.openmmlab.com/mmcv/dist/cu102/torch1.10/index.html源碼編譯方式預(yù)編譯失敗時(shí)的備選git clone -b v1.7.5 https://github.com/open-mmlab/mmcv.git cd mmcv pip install -r requirements/optional.txt MMCV_WITH_OPS1 FORCE_CUDA1 pip install -e .注意源碼編譯時(shí)MMCV_WITH_OPS1這個(gè)環(huán)境變量不能省不然只會(huì)裝純Python版本后續(xù)運(yùn)行檢測(cè)時(shí)會(huì)報(bào)一些算子在自定義CUDA擴(kuò)展上缺失的錯(cuò)誤。3.3 驗(yàn)證安裝是否真的可用裝完后我建議不止做import測(cè)試而是直接跑一次簡(jiǎn)單測(cè)試看CUDA是否可用python -c import torch; print(torch.__version__, torch.cuda.is_available()) python -c import mmcv; print(mmcv.__version__) python -c import mmdet; print(mmdet.__version__)同時(shí)在Python里跑一個(gè)小算子import torch from mmcv.ops import nms boxes torch.tensor([[0, 0, 10, 10, 0.9]], dtypetorch.float32).cuda() keep nms(boxes, torch.tensor([0.5]).cuda(), 0.4) print(keep)如果這段輸出正常說(shuō)明整個(gè)CUDA編譯鏈路都是通的可以進(jìn)入數(shù)據(jù)準(zhǔn)備階段了。很多人在這一步直接卡住有的報(bào)torch.cuda.is_available() False有的報(bào)nms算子加載失敗。前者多半是PyTorch版本和CUDA不匹配后者多半是mmcv未安裝帶ops的版本。4. 數(shù)據(jù)集準(zhǔn)備與配置文件改動(dòng)訓(xùn)練前最后的硬骨頭4.1 COCO格式目錄結(jié)構(gòu)就是規(guī)則mmdetection默認(rèn)推薦COCO格式數(shù)據(jù)集。如果你手上是VOC或自建數(shù)據(jù)集推薦先轉(zhuǎn)成COCO格式因?yàn)楹罄m(xù)一切可視化腳本、評(píng)測(cè)接口都基于這個(gè)格式省得繞路。目錄組織如下data/ coco/ annotations/ instances_train2017.json instances_val2017.json train2017/ 000001.jpg 000002.jpg ... val2017/ 000001.jpg ...自建數(shù)據(jù)集時(shí)你需要寫一個(gè)腳本把標(biāo)注轉(zhuǎn)換為COCO json最少包含categories、images、annotations三個(gè)節(jié)點(diǎn)。提醒一句images里的id和annotations里的image_id必須一致否則訓(xùn)練時(shí)數(shù)據(jù)加載會(huì)直接報(bào)找不到圖片的index這個(gè)初學(xué)最容易漏。4.2 配置文件繼承體系從base到sub-configmmdetection的配置成熟度很高“拿來(lái)改”比“從零寫”靠譜太多。它的邏輯是先有基礎(chǔ)配置再逐層覆蓋字段。實(shí)際訓(xùn)練時(shí)主要改三個(gè)文件configs/_base_/datasets/coco_detection.py改數(shù)據(jù)路徑、訓(xùn)練圖片尺度、數(shù)據(jù)增強(qiáng)參數(shù)。configs/_base_/schedules/schedule_1x.py改學(xué)習(xí)率、step、總epoch數(shù)。configs/_base_/default_runtime.py改checkpoint保存間隔、日志配置、工作目錄。比如我們訓(xùn)練SSD或Faster R-CNN通常會(huì)創(chuàng)建一個(gè)新配置文件_base_ [ ../_base_/datasets/coco_detection.py, ../_base_/schedules/schedule_1x.py, ../_base_/default_runtime.py ] model dict( typeFasterRCNN, backbonedict(...), ... ) data dict( samples_per_gpu2, # 每個(gè)GPU的batch大小 workers_per_gpu2, # 每個(gè)GPU的DataLoader線程數(shù) ) optimizer dict(lr0.02/8) # 如果samples_per_gpu調(diào)整過(guò)學(xué)習(xí)率也要等比調(diào)整我當(dāng)時(shí)自作主張把samples_per_gpu調(diào)成4卻沒動(dòng)學(xué)習(xí)率結(jié)果損失直接NAN后來(lái)參照官方文檔里“l(fā)inear scaling rule”把學(xué)習(xí)率調(diào)小才恢復(fù)。4.3 數(shù)據(jù)增強(qiáng)與類別匹配中的隱藏要求模型頭和數(shù)據(jù)集類別數(shù)必須匹配。COCO默認(rèn)是80類如果你用自建數(shù)據(jù)集只有3個(gè)類別必須在配置里顯式覆蓋model dict( roi_headdict( bbox_headdict( num_classes3, )), ... )這個(gè)問題很隱蔽因?yàn)椴桓采w也不會(huì)報(bào)錯(cuò)默認(rèn)80類會(huì)和你的標(biāo)注id對(duì)不上導(dǎo)致所有框都往錯(cuò)誤的類別上套。我在某次實(shí)驗(yàn)里完全沒注意訓(xùn)練了很久mAP一直很低直到可視化檢測(cè)結(jié)果才發(fā)現(xiàn)類別全亂這屬于白跑幾個(gè)小時(shí)的經(jīng)典失誤。數(shù)據(jù)增強(qiáng)方面mmdet的默認(rèn)pipeline已經(jīng)包含隨機(jī)翻轉(zhuǎn)、隨機(jī)縮放、多尺度resize。在16.04老機(jī)器上如果顯存不寬裕建議把img_scale從(1333, 800)改成(1000, 600)訓(xùn)練速度會(huì)提升明顯mAP損失在接受范圍內(nèi)。5. 訓(xùn)練流程實(shí)操?gòu)拿钚械交謴?fù)斷點(diǎn)5.1 單卡訓(xùn)練命令與常見參數(shù)一切就緒后進(jìn)入訓(xùn)練conda activate mmdet cd /path/to/mmdetection python tools/train.py configs/faster_rcnn_r50_fpn_1x_coco.py --work-dir work_dirs/my_experiment參數(shù)說(shuō)明--work-dir保存日志和checkpoint的目錄不設(shè)置時(shí)會(huì)自動(dòng)生成在work_dirs/下。--cfg-options臨時(shí)修改配置比如--cfg-options optimizer.lr0.01適合做小實(shí)驗(yàn)時(shí)用。--resume-from從指定checkpoint恢復(fù)。--auto-resume自動(dòng)從最近一次中斷點(diǎn)恢復(fù)這個(gè)參數(shù)在2.x版本里很實(shí)用。啟動(dòng)后日志會(huì)輸出每個(gè)epoch的loss、bbox_mAP等指標(biāo)。這里有個(gè)小習(xí)慣啟動(dòng)訓(xùn)練后別急著離開先等兩三個(gè)iteration確認(rèn)loss在合理范圍比如0.5到2之間震蕩如果一開始loss就NAN立刻CtrlC回去查配置別心疼這幾分鐘。5.2 多卡訓(xùn)練與GPU選擇如果你的老機(jī)器插了多張顯卡可以用官方腳本bash tools/dist_train.sh configs/faster_rcnn_r50_fpn_1x_coco.py 2 --work-dir work_dirs/my_experiment其中2是GPU卡數(shù)。但是16.04機(jī)器多為老平臺(tái)PCIe帶寬和CPU都可能是瓶頸。實(shí)測(cè)下來(lái)雙卡加速往往達(dá)不到2倍甚至?xí)驗(yàn)橥ㄐ砰_銷拖慢。所以老機(jī)器上我反而推薦先單卡跑通再考慮分布式的test-time augmentation或推理加速。顯存不夠是另一個(gè)高頻問題。如果訓(xùn)練時(shí)報(bào)CUDA out of memory優(yōu)先做三件事把samples_per_gpu降到1。把img_scale進(jìn)一步縮小。開啟梯度累積在配置里使用optimizer_config dict(grad_clipNone, typeGradientCumulativeOptimizerHook, cumulative_iters4)。這個(gè)梯度累積技巧在顯存受限時(shí)堪稱救星等效增大batch size又不炸顯存。5.3 訓(xùn)練中途崩潰怎么續(xù)訓(xùn)練跑著跑著因?yàn)闄C(jī)房斷電、SSH斷開、顯存溢出被殺進(jìn)程是常態(tài)。mmdetection的斷點(diǎn)續(xù)訓(xùn)機(jī)制很完善做法是python tools/train.py configs/faster_rcnn_r50_fpn_1x_coco.py --resume-from work_dirs/my_experiment/epoch_10.pth它會(huì)從epoch 10繼續(xù)訓(xùn)練優(yōu)化器狀態(tài)、學(xué)習(xí)率調(diào)度都會(huì)一并恢復(fù)。如果不想手動(dòng)指定--auto-resume會(huì)自動(dòng)找最新的checkpoint。迭代過(guò)程中還建議定期把配置文件復(fù)制到work_dirs里留檔比如cp configs/faster_rcnn_r50_fpn_1x_coco.py work_dirs/my_experiment/否則后續(xù)想回溯當(dāng)時(shí)實(shí)驗(yàn)用的哪套參數(shù)會(huì)非常被動(dòng)。評(píng)測(cè)模型時(shí)用python tools/test.py configs/faster_rcnn_r50_fpn_1x_coco.py work_dirs/my_experiment/epoch_12.pth --eval bbox注意--eval bbox只評(píng)測(cè)檢測(cè)框如果要評(píng)測(cè)分割結(jié)果要改成segm參數(shù)用錯(cuò)了不會(huì)報(bào)錯(cuò)但輸出metric缺失容易誤判。6. 我在16.04上踩過(guò)的坑編譯、訓(xùn)練中的典型報(bào)錯(cuò)與排查鏈路6.1 編譯報(bào)錯(cuò)別只看最后一行要看完整日志源碼編譯mmcv時(shí)最常見的報(bào)錯(cuò)是error: command gcc failed with exit status 1這個(gè)錯(cuò)誤信息太籠統(tǒng)90%以上的人卡在這里。我當(dāng)時(shí)的排查思路是往上翻日志找到真正的根源。通常有幾種情況缺少python頭文件需要先conda install python-dev或conda install python3.7-dev。缺少CUDA頭文件確認(rèn)/usr/local/cuda/include/cuda.h存在。gcc版本太老如果CUDA 10.2自帶驅(qū)動(dòng)的約束官方要求gcc 5.4沒問題但如果升級(jí)到CUDA 115.4就不夠了需要gcc 7.5。說(shuō)到gcc16.04默認(rèn)gcc是5.4。解決辦法是apt安裝gcc-7sudo add-apt-repository ppa:ubuntu-toolchain-r/test sudo apt update sudo apt install gcc-7 g-7 sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-7 70 sudo update-alternatives --install /usr/bin/g g /usr/bin/g-7 70注意如果換gcc版本之前已經(jīng)編譯過(guò)的CUDA工具鏈不一定需要重裝但重新編譯mmcv時(shí)一定要確認(rèn)gcc --version是預(yù)期版本。6.2 訓(xùn)練中出現(xiàn)NAN的排查鏈路NAN是訓(xùn)練階段最常見的臟數(shù)據(jù)類問題在16.04老環(huán)境里還多了一個(gè)特殊性硬件穩(wěn)定性降低某個(gè)PCIe插槽接觸不良或電源供電不足也可能隨機(jī)產(chǎn)生NAN。我的排查順序是先排除數(shù)據(jù)如果隨機(jī)抽樣幾百?gòu)堯?yàn)證圖片loss都在合理范圍那數(shù)據(jù)本身沒問題。再看學(xué)習(xí)率線性縮放規(guī)則batch減半那么lr也要減半否則NAN概率極高。檢查BN層的num_batches_tracked低batch size下BN統(tǒng)計(jì)不穩(wěn)定可以在配置里norm_cfg dict(typeBN, requires_gradTrue)改成SyncBN或減小lr進(jìn)一步觀察。硬件層面查dmesg | grep -i error看有沒有GPU相關(guān)報(bào)錯(cuò)用nvidia-smi -pl 200給老卡降一點(diǎn)功耗墻訓(xùn)練穩(wěn)定性會(huì)好很多。這里強(qiáng)調(diào)一下環(huán)境越老越不能把NAN直接歸因到算法要按層、按數(shù)據(jù)、按硬件一步步隔離才能找到真兇。6.3 GPU利用率上不去、CPU爆滿的老機(jī)器優(yōu)化16.04老機(jī)器CPU核數(shù)普遍不多訓(xùn)練時(shí)GPU利用率經(jīng)常只在30%左右波動(dòng)這是因?yàn)镈ataLoader在瘋狂做圖像解碼和resizeCPU成了瓶頸。解法data dict( samples_per_gpu2, workers_per_gpu4, # 適當(dāng)調(diào)大worker數(shù) )workers_per_gpu從2調(diào)到4或6通常能讓GPU利用率明顯回升。但也不要盲目開太大worker太多會(huì)造成內(nèi)存占用飆升老機(jī)器內(nèi)存不夠時(shí)反而觸發(fā)swap速度暴跌。我的一般經(jīng)驗(yàn)是內(nèi)存16G配2~4個(gè)worker32G以上配8個(gè)也沒問題。還有一個(gè)容易被忽略的點(diǎn)可以用torch.backends.cudnn.benchmark True在輸入尺寸固定時(shí)開啟cudnn自動(dòng)調(diào)優(yōu)對(duì)小數(shù)據(jù)集訓(xùn)練有明顯加速效果。老機(jī)器上跑訓(xùn)練最忌諱看著GPU沒吃滿就著急換大batch很多時(shí)候瓶頸不在GPU而在數(shù)據(jù)管線和IO。先診斷再優(yōu)化才是正道。最后再分享一個(gè)實(shí)際操作中的體會(huì)Ubuntu 16.04 mmdetection這套配置如果你能接受“不追新、版本鎖死、一切按部就班”的心態(tài)其實(shí)是可以很穩(wěn)定地跑起來(lái)的。我多次在重裝環(huán)境后照著一份自制的版本清單裝基本半小時(shí)內(nèi)能恢復(fù)到昨天的工作狀態(tài)。建議你也把最終成功的版本組合和安裝命令寫成一份備忘而不是依賴記憶。老系統(tǒng)的容錯(cuò)率低但確定性高一次配好持續(xù)使用體驗(yàn)反而比每次升級(jí)都要折騰的人舒暢得多。