pytorch 運行一段時間後出現GPU OOM的問題
pytorch的dataloader會將數據傳到GPU上,這個過程GPU的mem占用會逐漸增加,為瞭避免GPUmen被無用的數據占用,可以在每個step後用del刪除一些變量,也可以使用torch.cuda.empty_cache()釋放顯存:
del targets, input_k, input_mask torch.cuda.empty_cache()
這時能觀察到GPU的顯存一直在動態變化。
但是上述方式不是一個根本的解決方案,因為他受到峰值的影響很大。比如某個batch的數據量明顯大於其他batch,可能模型處理該batch時顯存會不夠用,這也會導致OOM,雖然其他的batch都能順利執行。
顯存的占用跟這幾個因素相關:
模型參數量
batch size
一個batch的數據 size
通常我們不希望改變模型參數量,所以隻能通過動態調整batch-size,使得一個batch的數據 size不會導致顯存OOM:
ilen = int(sorted_data[start][1]['input'][0]['shape'][0]) olen = int(sorted_data[start][1]['output'][0]['shape'][0]) # if ilen = 1000 and max_length_in = 800 # then b = batchsize / 2 # and max(1, .) avoids batchsize = 0 # 太長的句子會被動態改變bsz,單獨成一個batch,否則padding的部分就太多瞭,數據量太大,OOM factor = max(int(ilen / max_length_in), int(olen / max_length_out)) b = max(1, int(batch_size / (1 + factor))) #b = batch_size end = min(len(sorted_data), start + b) minibatch.append(sorted_data[start:end]) if end == len(sorted_data): break start = end
此外,如何選擇一個合適的batchsize也是個很重要的問題,我們可以先對所有數據按照大小(長短)排好序(降序),不進行shuffle,按照64,32,16依次嘗試bsz,如果模型在執行第一個batch的時候沒出現OOM,那麼以後一定也不會出現OOM(因為降序排列瞭數據,所以前面的batch的數據size最大)。
還有以下問題
pytorch increasing cuda memory OOM 問題
改瞭點model 的計算方式,然後就 OOM 瞭,調小瞭 batch_size,然後發現發現是模型每次迭代都會動態增長 CUDA MEMORY, 在排除瞭 python code 中的潛在內存溢出問題之後,基本可以把問題定在 pytorch 的圖計算問題上瞭,說明每次迭代都重新生成瞭一張計算圖,然後都保存著在,就 OOM 瞭。
參考
CUDA memory continuously increases when net(images) called in every iteration
Understanding graphs and state
說是會生成多個計算圖:
loss = SomeLossFunction(out) + SomeLossFunction(out)
準備用 sum來避免多次生成計算圖的問題:
loss = Variable(torch.sum(torch.cat([loss1, loss2], 0)))
然而,調著調著就好瞭,和報錯前的 code 沒太大差別。估計的原因是在pycharm 遠程連接服務器的時候 code 的保存版本差異問題,這個也需要解決一下。
還有個多次迭代再計算梯度的問題,類似於 caffe中的iter_size,這個再仔細看看。
以上為個人經驗,希望能給大傢一個參考,也希望大傢多多支持WalkonNet。
推薦閱讀:
- Pytorch 如何加速Dataloader提升數據讀取速度
- PyTorch中的CUDA的操作方法
- 詳解pytorch的多GPU訓練的兩種方式
- pytorch 使用半精度模型部署的操作
- 對pytorch中不定長序列補齊的操作