后面的不用看了,直接看最省事版本:
??????
?????????直接用CUDA_VISIBLE_DEVICES="2,3"指定多卡就可以,也可以給sh文件傳參進(jìn)去。但是,切記!切記!切記!sh文件里不能有空行,尤其是使用反斜杠 \ 連接多行的時(shí)候,我一開始嘗試指定多卡不起作用,就是因?yàn)閳D美觀手賤多了個(gè)空行,調(diào)試了好久。反面教材如下:
到這里就OK了,下面的正文不用看了。懶得刪了(╯︵╰)
?正文:
?????????今天做目標(biāo)檢測(cè)的多卡訓(xùn)練,想兩張卡并行跑一組參數(shù),希望在0號(hào)和1號(hào)顯卡上掛兩組實(shí)驗(yàn),在2號(hào)和3號(hào)顯卡上掛兩組實(shí)驗(yàn),他們都用兩張卡并行。為什么不用四張卡并行跑四個(gè)實(shí)驗(yàn)?zāi)??因?yàn)轱@存不夠。使用的命令是tools/dist_train.sh中的python -m torch.distributed.launch...
????????但是問題出現(xiàn)了:指定雙卡并行時(shí)每次總會(huì)是用0號(hào)和1號(hào)卡,不管我怎么設(shè)置gpu_ids,devices或者local_rank,都不會(huì)看23顯卡一眼,網(wǎng)上搜了半天,問了許多同學(xué),都未果,于是自己折騰一晚上,終于搞定了。
??????? 首先,原理:我猜測(cè)是雙卡時(shí),兩個(gè)進(jìn)程的序號(hào)也就是rank會(huì)是0和1,于是mmdet分布式訓(xùn)練時(shí)就直接用rank序號(hào)作為GPU序號(hào)。體現(xiàn)在mmdet/apis/train.py中如下部分:
if distributed:
find_unused_parameters = cfg.get('find_unused_parameters', False)
# Sets the `find_unused_parameters` parameter in
# torch.nn.parallel.DistributedDataParallel
model = build_ddp(
model,
cfg.device,
device_ids=[int(os.environ['LOCAL_RANK'])],
broadcast_buffers=False,
find_unused_parameters=find_unused_parameters)
else:
model = build_dp(model, cfg.device, device_ids=cfg.gpu_ids)
????????其中device_ids直接用的rank序號(hào),省時(shí)確實(shí)省時(shí),可把我折騰壞了。于是我稍作修改,當(dāng)前兩個(gè)進(jìn)程的rank是0和1,我需要用2和3,只需要給他們各自加2即可。于是可以改成
device_ids=[int(os.environ['LOCAL_RANK'])+2],
????????改完這一步后運(yùn)行,會(huì)報(bào)錯(cuò)Expected all tensors to be on the same device, but found at least two devices, cuda:2 and cuda:0! 經(jīng)過檢查,發(fā)現(xiàn)數(shù)據(jù)是放到2和3號(hào)卡上了,但是模型model還在0和1號(hào)卡上,定位到mmdet/utils/util_distribution.py的build_ddp()函數(shù),其中有一句
if device == 'cuda':
model = model.cuda()
這一句默認(rèn)是放到0號(hào)開頭的顯卡上,需要我們?cè)俅渭?,把model也放到2和3號(hào)卡上,如下:
if device == 'cuda':
from mmcv.runner import get_dist_info
rank, _ = get_dist_info()
model = model.cuda('cuda:{}'.format(rank+2))
????????到此為止,就可以成功的把mmdet程序放到2號(hào)和3號(hào)顯卡上訓(xùn)練了,實(shí)現(xiàn)過程的不足之處在于沒有用參數(shù)的形式指定,相當(dāng)于一個(gè)臨時(shí)措施,我考慮賦值os.environ['LOCAL_RANK']="2,3",但是這是多進(jìn)程,需要讓一個(gè)進(jìn)程看到2,另一個(gè)進(jìn)程看到3,而非兩個(gè)進(jìn)程都看到2和3,所以可能需要再次rank, _ = get_dist_info(),根據(jù)當(dāng)前進(jìn)程的序號(hào)改變os.environ['LOCAL_RANK']的值。另外,前面的device_ids=[int(os.environ['LOCAL_RANK'])+2],我后來沒有這樣做,而是在main.py中os.environ['LOCAL_RANK'] = str(int(os.environ['LOCAL_RANK']) + 2),因?yàn)槿绻竺婺承┑胤桨裠ata放大顯卡上時(shí)仍然直接用rank值,那后面就不需要再給data把rank+2一次。文章來源:http://www.zghlxwxcb.cn/news/detail-481874.html
??????? 從上面過程也能看出,多卡并行訓(xùn)練時(shí)用哪些卡,主要還是model.cuda()要指定設(shè)備號(hào),以及某些原作者圖省事直接使用LOCAL_RANK環(huán)境變量的地方需要改成自己需要的數(shù)字。對(duì)了,LOCAL_RANK應(yīng)該是pytorch自動(dòng)生成的,我們無法在外圍指定。文章來源地址http://www.zghlxwxcb.cn/news/detail-481874.html
到了這里,關(guān)于mmdetection使用指定的顯卡號(hào)并行分布式訓(xùn)練的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!