欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Pytorch中關(guān)于inplace的操作

 更新時(shí)間:2023年08月02日 16:13:44   作者:二十米  
這篇文章主要介紹了Pytorch中關(guān)于inplace的操作方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教

Pytorch中inplace操作

之前在寫(xiě)訓(xùn)練代碼時(shí),遇到了inplace operation導(dǎo)致的問(wèn)題,所以就了解了一下pytorch的inplace operation,記錄一下inplace操作的知識(shí)。

報(bào)錯(cuò)信息如下:

RuntimeError: one of the variables needed for gradient computation has been modified by an inplace operation.

Inplace操作概述

稍微了解過(guò)python的人應(yīng)該會(huì)知道python的變量名是一個(gè)類似索引的東西,其指向內(nèi)存中的一個(gè)對(duì)象。

而對(duì)該變量重新賦值,實(shí)際上是將該變量名指向內(nèi)存中的其它對(duì)象,原對(duì)象本身其實(shí)并未改變。而Inplace操作并非如此,該操作會(huì)直接改變?cè)瓕?duì)象的內(nèi)容,這樣能減少內(nèi)存的消耗,但也會(huì)帶來(lái)一些隱患。

非inplace操作如下圖所示,運(yùn)算操作先是開(kāi)辟了一塊新的內(nèi)存存放運(yùn)算后的結(jié)果,然后再將引用指向新內(nèi)存,而舊內(nèi)存的內(nèi)容保持不變。

而inplace操作則不同,運(yùn)算操作會(huì)直接在舊內(nèi)存上進(jìn)行更改,而并不會(huì)另外開(kāi)辟一個(gè)新內(nèi)存進(jìn)行運(yùn)算結(jié)果的存放。

inplace操作的優(yōu)缺點(diǎn)

要使用好inplace操作,首先肯定需要知道其存在的優(yōu)點(diǎn)以及缺點(diǎn)。根據(jù)inplace操作的原理,其實(shí)不難發(fā)現(xiàn)其優(yōu)點(diǎn)就在于節(jié)省內(nèi)存,尤其是在處理高維數(shù)據(jù)時(shí)能顯著減少額外的內(nèi)存開(kāi)銷,這在訓(xùn)練神經(jīng)網(wǎng)絡(luò)時(shí)是很有價(jià)值的一個(gè)特性。

但在節(jié)省內(nèi)存的同時(shí),inplace操作也帶來(lái)了一些隱患,pytorch的官方文檔是這樣說(shuō)的:

  • inplace操作可能會(huì)覆蓋計(jì)算梯度所需的值。
  • 每個(gè)inplace操作實(shí)際上都需要實(shí)現(xiàn)重寫(xiě)計(jì)算圖。Out-of-place版本只是簡(jiǎn)單地分配新對(duì)象并保持對(duì)舊圖的引用,而inplace操作則要求將所有輸入的創(chuàng)建者更改為表示該操作的函數(shù)。

也就是說(shuō),在Autograd中支持inplace操作很困難,有時(shí)候會(huì)在不經(jīng)意間導(dǎo)致自動(dòng)求導(dǎo)失敗,得到上文所提到的報(bào)錯(cuò)。同時(shí),Autograd積極的緩沖區(qū)釋放和重用使其非常高效,inplace操作實(shí)際上并不能降低太多內(nèi)存的消耗,因此在大多數(shù)情況下不鼓勵(lì)使用。除非在沉重的內(nèi)存壓力下運(yùn)行,否則可能永遠(yuǎn)不需要使用inplace操作。

PS:如果你使用了inplace操作而沒(méi)有報(bào)錯(cuò)的話,那么你可以確定你的梯度計(jì)算是正確的。但是,這僅僅表示Autograd計(jì)算梯度無(wú)誤,如果出現(xiàn)了該內(nèi)存被其他變量引用而未注意,依舊可能存在計(jì)算一致性的風(fēng)險(xiǎn)。

常見(jiàn)的inplace操作

inplace操作有優(yōu)點(diǎn)也有缺點(diǎn),但總體來(lái)說(shuō)還是弊大于利,所以如果顯存足夠的話,還是盡量少用inplace操作。那inplace操作有哪些呢?

  • 1.數(shù)值運(yùn)算,如x+=1屬于inplace操作,會(huì)直接對(duì)x的值進(jìn)行操作;而y=x+5則不屬于inplace操作(PS:x+=1雖然是inplace操作,但求導(dǎo)時(shí)其導(dǎo)數(shù)為1,導(dǎo)數(shù)值并不與x的值相關(guān),所以不會(huì)對(duì)反向傳播產(chǎn)生影響,故這種情況的影響不大)
  • 2.pytorch提供的一些inplace選項(xiàng),如nn.ReLU(inplace=True)nn.LeakyReLU(inplace=True),這些選項(xiàng)的安全性要高一些,但也需要注意中間變量后續(xù)是否需要,如果后面還需要使用中間變量,就應(yīng)當(dāng)設(shè)置inplace=False
  • 3.具有 _ 后綴的方法,如x.copy_(y)x.t_(),將直接改變x。同時(shí),一些常見(jiàn)的操作如x.add_(y)x.mul_(y)也會(huì)直接改變x,除非有特定需求,否則不建議使用這類inplace操作,隱患比前兩種情況高很多。

以上是常見(jiàn)的一些inplace操作,雖然不建議使用inplace操作,但還是需要了解一下,以免日后遇到問(wèn)題。

注意:

inplace操作會(huì)直接修改原內(nèi)存處的值,雖然會(huì)節(jié)省一些內(nèi)存,但也會(huì)帶來(lái)一些隱患,如自動(dòng)求導(dǎo)出錯(cuò)等。因此如果不是內(nèi)存十分緊缺,不建議使用inplace操作。

pytorch的inplace的問(wèn)題

最近將一個(gè)模型訓(xùn)練代碼從caffe平臺(tái)移植到pytorch平臺(tái)過(guò)程中遇到了一個(gè)詭異的inplace坑,特別記錄一下防止大家掉坑。

relu等激活函數(shù)的inplace

看到官方的relu入?yún)⑹侵衝n.ReLU(inplace=True)是inplace操作,我一想這不是能節(jié)省我的資源占用,毫不猶豫的選擇了True。

搭好模型運(yùn)行,結(jié)果是在backward計(jì)算導(dǎo)數(shù)的時(shí)候。表示inplace操作導(dǎo)致求導(dǎo)結(jié)果有問(wèn)題。

改為**nn.ReLU(inplace=False)**問(wèn)題在pytorch1.3和pytorch1.8解決了。

“+=”操作的默認(rèn)inplace

后來(lái)因?yàn)閾Q了pytorch1.10版本后又報(bào)錯(cuò)了。報(bào)錯(cuò)形式和上面一樣。

后來(lái)查了一下“+=”也是inplace操作,將工程中網(wǎng)絡(luò)的前向傳播方式中:x += feature16改為:“x = x + feature16” 。

問(wèn)題就消失了。

報(bào)錯(cuò)形式

RuntimeError: one of the variables needed for gradient computation has been modified by an inplace operation: [torch.cuda.HalfTensor [×,×,×,×]], which is output 0 of ReluBackward0, is at version 1; expected version 0 instead. Hint: enable anomaly detection to find the operation that failed to compute its gradient, with torch.autograd.set_detect_anomaly(True).

總結(jié)

以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。

相關(guān)文章

最新評(píng)論