如何計算顯存的佔用,預防out of memory?
最近一次組會上,師兄點評一篇文章顯存佔用過多,突然發現還不知道如何具體的計算顯存,只好去學習一下。
顯存類似於內存,可以存放模型數據,參數等等;顯存越大,所能運行的網絡也就越大
torch.FatalError: cuda runtime error (2) : out of memory at /opt/conda/.......
out of memory: 顯存裝不下你那麼多的模型權重還有中間變量
GPU計算單元用來進行數值計算,衡量計算量的單位是flop,浮點數先乘後加算一個flop計算能力越強大,速度越快。衡量計算能力的單位是 flops: 每秒能執行的 flop數量。
2*2+2 :1個flop
2*2+3*3+4*4 : 3個flop
1、 存儲指標
1 Byte = 8 bit 1 K = 1024 Byte 1 M = 1024 K 1 G = 1024 M
除此之外,
1 Byte = 8 bit 1 KB = 1000 Byte 1 MB = 1000 KB 1 GB = 1000 MB 1TB = 1000 GB
常用的數值類型:
若一張256*256的RGB圖片存儲在顯存中佔有顯存爲(float):
3*256*256*4=0.75M,若batchsize=100,也就佔用75M,顯存,顯然,佔用顯存較大的不是輸入圖片數據,那會是什麼呢?
什麼佔用了顯存?
首先,瞭解神經網絡的構成,我們當然知道神經網絡只是一種類似神經的架構,主要由構成網絡層的各種參數構成,以及神經網絡的各種中間輸出。
網絡模型的參數:
看一個例子:
- 模型權重:各種網絡層的參數
- 卷積層,通常的conv2d
- 全連接層,也就是Linear層
- BatchNorm層
- Embedding層
- 中間變量:各種網絡層的輸出
而不佔用顯存的則是:
- 剛纔說到的激活層Relu等
- 池化層
- Dropout層
具體計算方式:
- Conv2d(Cin, Cout, K): 參數數目:Cin × Cout × K × K
- Linear(M->N): 參數數目:M×N
- BatchNorm(N): 參數數目: 2N
- Embedding(N,W): 參數數目: N × W
參數佔用顯存:
參數佔用顯存 = 參數數目×n
n = 4 :float32 n = 2 : float16 n = 8 : double64
優化器的顯存佔用:
例如SGD優化器:
除了保存W之外還要保存參數對應的梯度,因此顯存佔用等於參數佔用的顯存的2倍。
Momentum-SGD:保存參數、梯度、動量------3倍
Adam:------------------------------------------4倍
輸入輸出的顯存佔用:
特點:
- 需要計算每一層的feature map的形狀(多維數組的形狀)
- 模型輸出的顯存佔用與 batch size 成正比
- 需要保存輸出對應的梯度用以反向傳播(鏈式法則)
- 模型輸出不需要存儲相應的動量信息(因爲不需要執行優化)
具體計算:
顯存佔用 = 模型顯存佔用 + batch_size × 每個樣本的顯存佔用
注意 : 輸入數據不用計算梯度;激活函數不用保存輸入;
如何減小顯存佔用?出現out of memory如何處理?
- 儘量不使用全連接層
- 下采樣
- 減小batchsize
最簡單處理方法,也是最常用的方法
減小batchsize
一般模型參數與batchsize成一定的不嚴格的正比關係。
參考資料:https://blog.csdn.net/liusandian/article/details/79069926