女人自慰AV免费观看内涵网,日韩国产剧情在线观看网址,神马电影网特片网,最新一级电影欧美,在线观看亚洲欧美日韩,黄色视频在线播放免费观看,ABO涨奶期羡澄,第一导航fulione,美女主播操b

0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

DataParallel里為什么會(huì)顯存不均勻以及如何解決

深度學(xué)習(xí)自然語言處理 ? 來源:深度學(xué)習(xí)自然語言處理 ? 作者:臺(tái)運(yùn)鵬 ? 2022-12-14 10:36 ? 次閱讀

鑒于網(wǎng)上此類教程有不少模糊不清,對(duì)原理不得其法,代碼也難跑通,故而花了幾天細(xì)究了一下相關(guān)原理和實(shí)現(xiàn),歡迎批評(píng)指正!

關(guān)于此部分的代碼,可以去https://github.com/sherlcok314159/dl-tools查看

「在開始前,我需要特別致謝一下一位摯友,他送了我雙顯卡的機(jī)器來贊助我做個(gè)人研究,否則多卡的相關(guān)實(shí)驗(yàn)就得付費(fèi)在云平臺(tái)上跑了,感謝好朋友一路以來的支持,這份恩情值得一輩子銘記!這篇文章作為禮物贈(zèng)與摯友?!?/strong>

Why Parallel

我們?cè)趦煞N情況下進(jìn)行并行化訓(xùn)練[1]:

「模型一張卡放不下」:我們需要將模型不同的結(jié)構(gòu)放置到不同的GPU上運(yùn)行,這種情況叫ModelParallel(MP)

「一張卡的batch size(bs)過小」:有些時(shí)候數(shù)據(jù)的最大長度調(diào)的比較高(e.g., 512),可用的bs就很小,較小的bs會(huì)導(dǎo)致收斂不穩(wěn)定,因而將數(shù)據(jù)分發(fā)到多個(gè)GPU上進(jìn)行并行訓(xùn)練,這種情況叫DataParallel(DP)。當(dāng)然,DP肯定還可以加速訓(xùn)練,常見于大模型的訓(xùn)練中

這里只講一下DP在pytorch中的原理和相關(guān)實(shí)現(xiàn),即DataParallel和DistributedParallel

Data Parallel

實(shí)現(xiàn)原理

實(shí)現(xiàn)就是循環(huán)往復(fù)一個(gè)過程:數(shù)據(jù)分發(fā),模型復(fù)制,各自前向傳播,匯聚輸出,計(jì)算損失,梯度回傳,梯度匯聚更新,可以參見下圖[2]:

b84b1762-7acd-11ed-8abf-dac502259ad0.png

pytorch中部分關(guān)鍵源碼[3]截取如下:

defdata_parallel(
module,
input,
device_ids,
output_device=None
):
ifnotdevice_ids:
returnmodule(input)

ifoutput_deviceisNone:
output_device=device_ids[0]

#復(fù)制模型
replicas=nn.parallel.replicate(module,device_ids)
#拆分?jǐn)?shù)據(jù)
inputs=nn.parallel.scatter(input,device_ids)
replicas=replicas[:len(inputs)]
#各自前向傳播
outputs=nn.parallel.parallel_apply(replicas,inputs)
#匯聚輸出
returnnn.parallel.gather(outputs,output_device)

代碼使用

因?yàn)檫\(yùn)行時(shí)會(huì)將數(shù)據(jù)平均拆分到GPU上,所以我們準(zhǔn)備數(shù)據(jù)的時(shí)候, batch size = per_gpu_batch_size * n_gpus

同時(shí),需要注意主GPU需要進(jìn)行匯聚等操作,因而需要比單卡運(yùn)行時(shí)多留出一些空間

importtorch.nnasnn
#device_ids默認(rèn)所有可使用的設(shè)備
#output_device默認(rèn)cuda:0
net=nn.DataParallel(model,device_ids=[0,1,2],
output_device=None,dim=0)
#input_varcanbeonanydevice,includingCPU
output=net(input_var)

接下來看個(gè)更詳細(xì)的例子[4],需要注意的是被DP包裹之后涉及到模型相關(guān)的,需要調(diào)用DP.module,比如加載模型

classModel(nn.Module):
#Ourmodel
def__init__(self,input_size,output_size):
super(Model,self).__init__()
#forconvenience
self.fc=nn.Linear(input_size,output_size)

defforward(self,input):
output=self.fc(input)
print("	InModel:inputsize",input.size(),
"outputsize",output.size())
returnoutput

bs,input_size,output_size=6,8,10
#defineinputs
inputs=torch.randn((bs,input_size)).cuda()
model=Model(input_size,output_size)
iftorch.cuda.device_count()>1:
print("Let'suse",torch.cuda.device_count(),"GPUs!")
#dim=0[6,xxx]->[2,...],[2,...],[2,...]on3GPUs
model=nn.DataParallel(model)
#先DataParallel,再cuda
model=model.cuda()
outputs=model(inputs)
print("Outside:inputsize",inputs.size(),
"output_size",outputs.size())
#assume2GPUSareavailable
#Let'suse2GPUs!
#InModel:inputsizetorch.Size([3,8])outputsizetorch.Size([3,10])
#InModel:inputsizetorch.Size([3,8])outputsizetorch.Size([3,10])
#Outside:inputsizetorch.Size([6,8])output_sizetorch.Size([6,10])

#savethemodel
torch.save(model.module.state_dict(),PATH)
#loadagain
model.module.load_state_dict(torch.load(PATH))
#doanythingyouwant

如果經(jīng)常使用huggingface,這里有兩個(gè)誤區(qū)需要小心:

#dataparallelobjecthasnosave_pretrained
model=xxx.from_pretrained(PATH)
model=nn.DataParallel(model).cuda()
model.save_pretrained(NEW_PATH)#error
#因?yàn)閙odel被DPwrap了,得先取出模型#
model.module.save_pretrained(NEW_PATH)
#HF實(shí)現(xiàn)貌似是返回N個(gè)loss(N為GPU數(shù)量)
#然后對(duì)N個(gè)loss取mean
outputs=model(**inputs)
loss,logits=outputs.loss,outputs.logits
loss=loss.mean()
loss.backward()

#返回的logits是匯聚后的
#HF實(shí)現(xiàn)和我們手動(dòng)算loss有細(xì)微差異
#手動(dòng)算略好于HF
loss2=loss_fct(logits,labels)
assertloss!=loss2
True

顯存不均勻

了解前面的原理后,就會(huì)明白為什么會(huì)顯存不均勻。因?yàn)镚PU0比其他GPU多了匯聚的工作,得留一些顯存,而其他GPU顯然是不需要的。那么,解決方案就是讓其他GPU的batch size開大點(diǎn),GPU0維持原狀,即不按照默認(rèn)實(shí)現(xiàn)的平分?jǐn)?shù)據(jù)

首先我們繼承原來的DataParallel(此處參考[5])),這里我們給定第一個(gè)GPU的bs就可以,這個(gè)是實(shí)際的bs而不是乘上梯度后的。假如你想要總的bs為64,梯度累積為2,一共2張GPU,而一張最多只能18,那么保險(xiǎn)一點(diǎn)GPU0設(shè)置為14,GPU1是18,也就是說你DataLoader每個(gè)batch大小是32,gpu0_bsz=14

classBalancedDataParallel(DataParallel):
def__init__(self,gpu0_bsz,*args,**kwargs):
self.gpu0_bsz=gpu0_bsz
super().__init__(*args,**kwargs)

核心代碼就在于我們重新分配chunk_sizes,實(shí)現(xiàn)思路就是將總的減去第一個(gè)GPU的再除以剩下的設(shè)備,源碼的話有些死板,用的時(shí)候不妨參考我的[6]

defscatter(self,inputs,kwargs,device_ids):
#不同于源碼,獲取batchsize更加靈活
#支持只有kwargs的情況,如model(**inputs)
iflen(inputs)>0:
bsz=inputs[0].size(self.dim)
elifkwargs:
bsz=list(kwargs.values())[0].size(self.dim)
else:
raiseValueError("Youmustpassinputstothemodel!")

num_dev=len(self.device_ids)
gpu0_bsz=self.gpu0_bsz
#除第一塊之外每塊GPU的bsz
bsz_unit=(bsz-gpu0_bsz)//(num_dev-1)
ifgpu0_bszbsz_0=16,bsz_1=bsz_2=18
#總的=53=>bsz_0=16,bsz_1=19,bsz_2=18
foriinrange(delta):
chunk_sizes[i+1]+=1
ifgpu0_bsz==0:
chunk_sizes=chunk_sizes[1:]
else:
returnsuper().scatter(inputs,kwargs,device_ids)

returnscatter_kwargs(inputs,kwargs,device_ids,chunk_sizes,dim=self.dim)

優(yōu)缺點(diǎn)

優(yōu)點(diǎn):便于操作,理解簡單

缺點(diǎn):GPU分配不均勻;每次更新完都得銷毀「線程」(運(yùn)行程序后會(huì)有一個(gè)進(jìn)程,一個(gè)進(jìn)程可以有很多個(gè)線程)重新復(fù)制模型,因而速度慢

審核編輯:湯梓紅

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
  • gpu
    gpu
    +關(guān)注

    關(guān)注

    28

    文章

    4898

    瀏覽量

    130552
  • 顯卡
    +關(guān)注

    關(guān)注

    16

    文章

    2498

    瀏覽量

    69130
  • pytorch
    +關(guān)注

    關(guān)注

    2

    文章

    809

    瀏覽量

    13737

原文標(biāo)題:DataParallel里為什么會(huì)顯存不均勻以及如何解決

文章出處:【微信號(hào):zenRRan,微信公眾號(hào):深度學(xué)習(xí)自然語言處理】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。

收藏 人收藏

    評(píng)論

    相關(guān)推薦
    熱點(diǎn)推薦

    不均勻性的定義 PPT學(xué)習(xí)資料

    不均勻性的定義可以這樣說:組成系統(tǒng)是由傳輸線+功能電路,這中間會(huì)遇到大量的不均勻性或者說不連續(xù)性。對(duì)于不均性的研究有兩個(gè)方面,不均勻性分析方
    發(fā)表于 11-02 17:13

    矩陣式LED的顯示亮度不均勻

    亮的效果(比如點(diǎn)亮LED2 LED 4 LED6 LED8 LED11 LED12)刷新6次;然后,發(fā)現(xiàn)亮度不夠,并且顯示起來亮度不均勻,然后又嘗試了行列式點(diǎn)亮,也是亮度不均勻,其實(shí)單獨(dú)做個(gè)LED顯示
    發(fā)表于 12-17 08:41

    在同步設(shè)計(jì)中使用占空比不均勻的時(shí)鐘是否可行

    喜 在同步設(shè)計(jì)中使用占空比不均勻的時(shí)鐘是否可行,我使用這些時(shí)鐘在上升沿和下降沿執(zhí)行操作。我使用這些脈沖作為總是塊的時(shí)鐘。請(qǐng)建議。謝謝,維沙爾以上來自于谷歌翻譯以下為原文hi
    發(fā)表于 01-30 08:03

    VHDL小源程序平均頻率輸出不均勻

    一.積分分頻(小數(shù)分頻)注:只是對(duì)平均頻率,輸出不均勻。library ieee; use ieee.std_logic_1164.all; use
    發(fā)表于 02-20 06:35

    何解決厚銅PCB電路板銅厚度不均勻的問題呢?

    何解決厚銅PCB電路板銅厚度不均勻的問題呢?
    發(fā)表于 04-11 14:31

    基于不均勻密度的自動(dòng)聚類算法

    針對(duì)基于密度的聚類算法不能自動(dòng)處理密度分布不均勻的數(shù)據(jù)問題,提出一種基于不均勻密度的自動(dòng)聚類算法。該算法既保持了一般基于密度算法的優(yōu)點(diǎn),也能有效地處理分布不均
    發(fā)表于 04-09 09:39 ?16次下載

    照度不均勻圖像的自動(dòng)Gamma灰度校正

    照度不均勻圖片分辨率較差,許多信息被掩蓋,為了較好地去除光照影響,真實(shí)再現(xiàn)原場景,本文提出了一種改進(jìn)的Gamma非線性灰度矯正函數(shù),實(shí)現(xiàn)了對(duì)不同像素進(jìn)行不同程度的灰度修正,另
    發(fā)表于 03-01 14:31 ?26次下載

    為什么數(shù)碼管亮度不均勻

    為什么數(shù)碼管亮度不均勻?  關(guān)于亮度一致性的問題是一個(gè)行業(yè)內(nèi)的常見問題。  有二個(gè)大的因素影響到亮度一致性?! ∫皇鞘褂迷牧闲酒倪x
    發(fā)表于 11-06 11:44 ?6590次閱讀

    RTC 計(jì)秒不均勻

    STM32F103RCT6的RTC 計(jì)秒不均勻
    發(fā)表于 12-07 18:13 ?0次下載

    抑制永磁體局部溫升最高點(diǎn)的不均勻軸向分段技術(shù)

    抑制永磁體局部溫升最高點(diǎn)的不均勻軸向分段技術(shù)_陳萍
    發(fā)表于 01-07 18:12 ?0次下載

    簡單分析光纖激光打標(biāo)機(jī)打標(biāo)效果不均勻的原因

    光纖激光打標(biāo)機(jī)打標(biāo)效果不均勻的原因分析。
    的頭像 發(fā)表于 12-25 13:15 ?995次閱讀

    機(jī)器人靜電噴涂不均勻的原因有哪些

    因種種原因機(jī)器人靜電噴涂有時(shí)候也有噴涂不均勻的情況,下面分享一下機(jī)器人靜電噴涂不均勻的原因。
    發(fā)表于 12-26 08:27 ?944次閱讀

    立磨磨輥磨損不均勻及磨輥與輥皮間隙變大了怎么解決

    立磨磨輥磨損不均勻怎么修補(bǔ)?磨輥與輥皮間隙變大了怎么辦?
    發(fā)表于 09-19 15:50 ?0次下載

    淺談連接器電鍍不均勻的原因

    很多連接器都需要電鍍,但是有些連接器電鍍后會(huì)出現(xiàn)電鍍不均勻的情況。我們來看看原因。
    的頭像 發(fā)表于 12-07 14:18 ?1777次閱讀

    錫膏點(diǎn)膠時(shí)拉絲不均勻,如何解決?

    時(shí)就出現(xiàn)拉絲不均勻,那么如何解決呢?接下來深圳佳金源錫膏廠家為大家講解一下:在點(diǎn)膠的過程中比較容易出現(xiàn)的問題就是拉絲,可以采取以下幾種措施:1、設(shè)置開膠延時(shí)。由于膠嘴
    的頭像 發(fā)表于 04-20 16:03 ?622次閱讀
    錫膏點(diǎn)膠時(shí)拉絲<b class='flag-5'>不均勻</b>,如<b class='flag-5'>何解</b>決?