網(wǎng)站首頁 編程語言 正文
Pytorch訓練模型時如何釋放GPU顯存 torch.cuda.empty_cache()內(nèi)存釋放以及cuda的顯存機制探索
作者:白馬金羈俠少年 更新時間: 2022-10-29 編程語言前言
訓練模型時,一般我們會把模型model,數(shù)據(jù)data和標簽label放到GPU顯存中進行加速。
但有的時候GPU Memory會增加,有的時候會保持不變,以及我們要怎么清理掉一些用完的變量呢?
下面讓我們一起來探究下原理吧!
一、pytorch訓練模型
只要你把任何東西(無論是多小的tensor)放到GPU顯存中,那么你至少會棧1000MiB左右的顯存(根據(jù)cuda版本,會略有不同)。這部分顯存是cuda running時固有配件必須要占掉的顯存,你先訓練過程匯總也是無法釋放的。
import torch
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
# 把一個很小的tensor加到GPU顯存中(大約2MiB)
x = torch.randn((2, 3), device=device)
現(xiàn)在我再放入一個比較大的tensor,GPU顯存升到了1919MiB
y = torch.randn((200, 300, 200, 20), device=device)
也就是說當你有個新的東西加進去時,GPU顯存會不斷擴大。
二、batch訓練模型時,GPU顯存的容量會保持不變?
但是為什么我們像下面這樣拿出一個個batch訓練模型時,GPU顯存的容量會保持不變的呢?
batch_loss = []
for epoch in range(self.epoch):
pbar = enumerate(tqdm(self.train_dataloader, desc="Training Bar"), 0)
for i, (inputs, labels) in pbar:
inputs = inputs.to(self.device) # 放到GPU顯存中
labels = labels.to(self.device) # 放到GPU顯存中
optimizer.zero_grad()
outputs = model(inputs)
loss = criterion(outputs, labels)
batch_loss.append(loss)
loss.backward()
optimizer.step()
這實際上跟cuda的內(nèi)存管理有關(guān),但你的一塊內(nèi)存不再由引用它的變量時,他就不再是Active memory。他會殘留在一個隊列中,如果下一次有新的東西進來,那就會把他擠出隊列(FIFO),當然如果新進來的東西和你那部分空間的大小差不多,那么出去一塊空間,又進來一塊空間,那么看上去你的GPU顯存就不會有增加,看上去是一直不變。這就解釋了一個個batch訓練模型時GPU顯存不變的原因。
當然如果新加進來的東西很多,就是那些unactivate的memory全部被擠出還是放不下新的東西,那GPU的顯存就會增加了。(有點類似C++中的capacity增加的情況)
實際運行中,我們會發(fā)現(xiàn)這個隊列capacity會有個閾值(這個閾值好像不是固定的),當你還沒到達這個閾值時不會觸發(fā)垃圾回收機制(即清理unactivate memeory的空間)
也就是說我不斷運行下面代碼
y = torch.randn((200, 300, 200, 20), device=device)
GPU顯存會增加到9247MiB
這時再加入y,容量不再增加,會把原來unactivate的memory擠掉。
三、如何釋放GPU顯存空間
那么我們要怎么樣釋放掉空間呢
我們上面很多空間原來是被y指向的,后來y指向新的地方,那這些空間都是殘留的,我們可以用下面命令繼續(xù)釋放(如果你想釋放的話)
torch.cuda.empty_cache()
上述命令可能要運行多次才會釋放空間,我運行了大概5次吧
殘留內(nèi)存成功被釋放
現(xiàn)在這里面GPU顯存 = 基礎(chǔ)配置(1001MiB) + y(918MiB) + x(忽略不計)
最后我們再來把y這部分釋放掉
令 y = 2
,那么原來y所指的那部分顯存空間就會變成unactivate,我們可以使用torch.cuda.empty_cache()
把這部分空間釋放掉
最終只剩下基礎(chǔ)配置的GPU顯存占用(這部分已經(jīng)無法釋放了)
四、torch.cuda.memory_summary()查看顯存信息
使用print(torch.cuda.memory_summary())
可以看到更多關(guān)于cuda顯存的信息
五、寫在最后
經(jīng)過上面的摸索,我感覺這部分內(nèi)容跟操作系統(tǒng)的內(nèi)存管理有點像,所以說計算機的那幾門基礎(chǔ)課真的很重要,大家都要好好學一學!
當然實際中cuda的顯存管理肯定沒有那么簡單,有興趣的同學可以繼續(xù)探究下。
原文鏈接:https://blog.csdn.net/qq_43827595/article/details/115722953
相關(guān)推薦
- 2022-11-14 Asp.net?Core項目配置HTTPS支持_實用技巧
- 2022-05-25 Python可變參數(shù)*args和**kwargs_python
- 2022-12-09 重學c/c++之數(shù)據(jù)存儲詳解(整數(shù)、浮點數(shù))_C 語言
- 2022-08-04 C++中純虛函數(shù)的實例詳解_C 語言
- 2022-04-28 C++實現(xiàn)班級成績管理系統(tǒng)_C 語言
- 2022-09-25 linux基礎(chǔ)入門1 vi/vim編輯器
- 2022-09-13 c++實現(xiàn)排序算法之希爾排序方式_C 語言
- 2023-03-22 Go語言實現(xiàn)猜謎小游戲_Golang
- 最近更新
-
- window11 系統(tǒng)安裝 yarn
- 超詳細win安裝深度學習環(huán)境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎(chǔ)操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區(qū)別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權(quán)
- redisson分布式鎖中waittime的設(shè)
- maven:解決release錯誤:Artif
- restTemplate使用總結(jié)
- Spring Security之安全異常處理
- MybatisPlus優(yōu)雅實現(xiàn)加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務(wù)發(fā)現(xiàn)-Nac
- Spring Security之基于HttpR
- Redis 底層數(shù)據(jù)結(jié)構(gòu)-簡單動態(tài)字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應(yīng)用詳解
- 聊聊消息隊列,發(fā)送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支