【2023 · CANN訓(xùn)練營(yíng)第一季】模型的遷移和調(diào)優(yōu)學(xué)習(xí)筆記
【2023 · CANN訓(xùn)練營(yíng)第一季】模型的遷移和調(diào)優(yōu)學(xué)習(xí)筆記
一、在線對(duì)接適配方案的優(yōu)點(diǎn)介紹
1.最大限度的繼承PyTorch框架動(dòng)態(tài)圖的特性。
2.最大限度的繼承原生PyTorch上的使用方式,能夠使用戶在移植時(shí)做到代碼修改少等優(yōu)點(diǎn)。
3.最大限度的繼承PyTorch原生的體系結(jié)構(gòu),像pytorch的自動(dòng)微分等功能都是保留了的。
4.擴(kuò)展性好。對(duì)于新增的網(wǎng)絡(luò)類型或結(jié)構(gòu),只需涉及相關(guān)計(jì)算類算子的開發(fā)和實(shí)現(xiàn)??蚣茴愃阕?,反向圖建立和實(shí)現(xiàn)機(jī)制等結(jié)構(gòu)可保持復(fù)用。
二、達(dá)芬奇框架簡(jiǎn)介
1.Cube: 負(fù)責(zé)矩陣運(yùn)算的單元,每次運(yùn)算可以計(jì)算一個(gè)fp16(16位浮點(diǎn)數(shù))的兩個(gè)16*16矩陣乘。
2.Vector: 向量運(yùn)算單元,可以運(yùn)算多種計(jì)算類型,如fp32,int32等
3.Scalar: Scalar,負(fù)責(zé)各類型的標(biāo)量數(shù)據(jù)運(yùn)算和程序的流程控制,功能上可以看做一個(gè)小CPU。
三、遷移方法
1.手工遷移
-分布式
原始代碼中,如果使用了DP(DataParallel):使用一個(gè)進(jìn)程來(lái)進(jìn)行參數(shù)計(jì)算,把每個(gè)批處理的數(shù)據(jù)分發(fā)到每個(gè)GPU,然后每個(gè)GPU計(jì)算各自的梯度,然后匯總到GPU0中進(jìn)行求平均,由GPU0進(jìn)行反向傳播更新參數(shù),然后再把模型的參數(shù)由GPU0傳播給其他的GPU,GPU利用率通常很低。如下圖:?

那么需要把DP改為DDP進(jìn)行使用。DDP(DistributedDataParallel):數(shù)據(jù)并行的分布式,是同時(shí)使用多個(gè)進(jìn)程,每個(gè)GPU上一個(gè)進(jìn)程,數(shù)據(jù)也是被進(jìn)程數(shù)等分,相當(dāng)于每個(gè)GPU上都跑了一份代碼,前向之后再經(jīng)過(guò)allreduce的處理,再經(jīng)過(guò)梯度反向傳播,更新參數(shù)。如下圖:?

-混合精度
由于NPU天然的混合精度的屬性,需要使用apex對(duì)代碼進(jìn)行修改 eg:
model = model.cuda()?
optimizer = torch.optim.SGD(model.parameters(), Ir=0.1)
#新增部分
model, optimizer =amp.initialize(model, optimizer,opt level="O2",loss_scale=128.0)
#把loss.backward()修改為
with ampscale loss(loss, optimizer) as scaled loss:
? ?
????scaled loss.backward()
部分參數(shù)解釋:?

-單卡模型遷移
因?yàn)槲覀兡P椭饕窃贕PU上運(yùn)行的,也就是cuda,而昇騰310是在的npu上運(yùn)行的。因此,我們需要將設(shè)備由cuda(gpu)切換到npu,torch.cuda->torch.npu eg:
#####轉(zhuǎn)換前的原生代碼CALCULATE DEVICE = "cuda:0"torch.cuda.set_device(CALCULATE DEVICE)
model = model.cuda()
#####轉(zhuǎn)換后的代碼CALCULATE DEVICE = "npu:0"torch.npu.set_device(CALCULATE DEVICE)
model = model.npu()
-多卡模型遷移
多卡遷移和單卡遷移的理念是一樣的,都是從GPU(英偉達(dá)顯卡)->NPU(華為昇騰) 因此,多卡主要是將backend(使用的通信庫(kù))參數(shù)?
從?
nccl(英偉達(dá)集合通信庫(kù)NVIDIA Collective Communication Library)?
轉(zhuǎn)換成?
hccl(華為集合通信庫(kù)Huawei Collective Communication Library)
eg:
#轉(zhuǎn)換前dist.init_process_group(backend='nccl',init_method=“tcp://127.0.0.1:29688",world_size=args.world_size, rank=args.rank)?
?#轉(zhuǎn)換后
dist.init_process_group(backend='hccl',init_method=“tcp://127.0.0.1:29688",world_size=args.world_size, rank=args.rank)
這里老師講解了幾個(gè)多卡啟動(dòng)的方式:?

?這里的高性能的啟動(dòng)模式用到了taskset命令 其用于在SMP場(chǎng)景下(一個(gè)計(jì)算機(jī)集成多個(gè)CPU)。 使用
yum install util-linux -y
復(fù)制
命令可以安裝此功能,其用法為:
語(yǔ)法格式:taskset [options] -p [mask] pid
參數(shù)選項(xiàng):
-a, --all-tasks 操作所有的任務(wù)線程
-p, --pid 操作已存在的pid
-c, --cpu-list 通過(guò)列表顯示方式設(shè)置CPU(逗號(hào)相隔)
-V, --version 輸出版本信息
-排查報(bào)錯(cuò)手段
1.使用流同步打點(diǎn)
print(torch.npu.synchronize(),"打點(diǎn)")
2.使用hook(網(wǎng)絡(luò)拓?fù)? 使用hook對(duì)每個(gè)model上的每個(gè)module進(jìn)行hook注冊(cè),看運(yùn)行斷在哪里?

3.查看Host日志

2.腳本轉(zhuǎn)換工具遷移
note:
原腳本需要在GPU上并且python3.7及以上可以跑通
腳本轉(zhuǎn)換前后邏輯一致
當(dāng)前此腳本工具只支持Pytorch1.5.0和1.8.1的訓(xùn)練腳本轉(zhuǎn)換
轉(zhuǎn)換方式:?

3.自動(dòng)遷移(推薦)
note:僅可以在pytorch1.8.1版本及以上使用。
只需要在訓(xùn)練腳本中引入代碼庫(kù)并且只需要增加一行:
import torch
import torch_npu?
......
from torch_npu.contrib import transfer_to_npu
四、樣例
在https://gitee.com/ascend/ModelZoo-PyTorch?網(wǎng)址下可以獲得昇騰的許多樣例進(jìn)行學(xué)習(xí)
ps:該文僅是為了記錄CANN訓(xùn)練營(yíng)的學(xué)習(xí)過(guò)程所用,不參與任何商業(yè)用途