2020-10-29 Pytorch 程序單卡到多卡

在多卡上訓(xùn)練的過程為先將模型和數(shù)據(jù)加載到第一張卡上,然后copy至其他卡。batchsize最好設(shè)為卡的整數(shù)倍,比如兩張卡,bs為2, 那么每張卡分別計(jì)算bs=1的結(jié)果,在model.forward之后將不同卡上返回的結(jié)果合并傳回再做下一步計(jì)算。

下面是踩坑后總結(jié)的需要注意的一些點(diǎn)。

1. 關(guān)于cuda與to(device)

  • model 與 data 全部采用 to(device)方法來遷移至顯存中,其中model.to(device)中的device, 默認(rèn)是cuda:0就可以。 但是在網(wǎng)絡(luò)計(jì)算過程中的中間數(shù)據(jù),要放到哪個(gè)設(shè)備上是要根據(jù)當(dāng)時(shí)在哪一塊卡上計(jì)算決定的,因此,應(yīng)將device設(shè)置為當(dāng)前相關(guān)數(shù)據(jù)在的卡,x.to(related_data.device)。

2. 關(guān)于model與model.module

  • 在調(diào)用model內(nèi)部定義的變量或函數(shù)時(shí),由于已經(jīng)使用 model = nn.DataParallel(model)包裹,因此必須要寫做model.module才能正常調(diào)用。 但是,調(diào)用model.forward()時(shí)必須要直接用model本身,否則無法使用多卡

3. 關(guān)于多卡計(jì)算結(jié)果合并

  • 必須確保forward最后return的均為tensor, 不能使用其他數(shù)據(jù)結(jié)構(gòu)包裹,也不能返回標(biāo)量,多個(gè)tensor分別返回。

4. 關(guān)于nn.ParameterList()不能用于多卡的問題

  • 多卡不支持復(fù)制屬性為List的參數(shù),代碼中定義的nn.ParameterList()會(huì)在多卡計(jì)算中無法復(fù)制到其他卡上,導(dǎo)致計(jì)算時(shí)參數(shù)為空的問題。需要寫成module.register_parameter()的形式才能隨module一起成功復(fù)制。示例如下
 for k in range(len(self.filters) + 1):
            # Weights
            H_init = np.log(np.expm1(1 / scale / filters[k + 1]))
            H_k = nn.Parameter(torch.ones((n_channels, filters[k + 1], filters[k])))  # apply softmax for non-negativity
            torch.nn.init.constant_(H_k, H_init)
            self.register_parameter('H_{}'.format(k), H_k)

            # Scale factors
            a_k = nn.Parameter(torch.zeros((n_channels, filters[k + 1], 1)))
            self.register_parameter('a_{}'.format(k), a_k)

            # Biases
            b_k = nn.Parameter(torch.zeros((n_channels, filters[k + 1], 1)))
            torch.nn.init.uniform_(b_k, -0.5, 0.5)
            self.register_parameter('b_{}'.format(k), b_k)

5. 其他

  • 關(guān)于loss的計(jì)算部分不能放在model里,不然會(huì)產(chǎn)生不在同一張卡無法計(jì)算的問題
  • 返回的tensor如果在原有網(wǎng)絡(luò)中是按batch做了某種運(yùn)算才返回的,這部分也需要加在model外另外做,因?yàn)槎嗫ㄓ?jì)算返回的是單獨(dú)計(jì)算的結(jié)果。

更改為DistributedDataParallel

注意幾個(gè)點(diǎn):

  • 模型和數(shù)據(jù)在兩張卡上是一模一樣的,相當(dāng)于分別在兩張卡上啟動(dòng)了兩個(gè)python程序
    python -m torch.distributed.launch --nproc_per_node=2 腳本 其他命令行參數(shù)
  • 一定要確保當(dāng)前的模型和數(shù)據(jù)都設(shè)置了CUDA,在包裹為module之后一定還要加一句model.cuda()。全局可以寫一個(gè)或者torch.cuda.set_device(local_rank)
            self.model=nn.parallel.DistributedDataParallel(
                self.model,
                device_ids=[opt.local_rank],
                output_device=opt.local_rank,
                broadcast_buffers=False,
            )
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容