關注&置頂“Charlotte資料挖掘”
每日9:00,幹貨速遞!
不知道大家在訓練深度學習模型時有沒有遇見過這種情況:設定的batch_size明明不大,譬如32或者16,但是怎麼一跑模型,GPU的顯存就占滿了呢?原來我使用Tensorflow的訓練的時候發現是這樣,後來我使用PaddlePaddle的時候也是這樣,我以為是架構本身出了問題,但是仔細研究後才發現,其實這兩種架構都是在跑模型的時候,預設設定會把你的GPU顯存占滿,需要手動去調整。具體如何優化呢,我把兩個架構的優化方式都分享給大家~
Tensorflow的顯存設定
1.設定指定GPU運作
a)在外部設定
如果電腦有多個GPU,tensorflow預設全部使用。如果想隻使用部分GPU,可以設定CUDA_VISIBLE_DEVICES即可,如下:
CUDA_VISIBLE_DEVICES=1 python train.py
b)在python内部設定制定GPU
import osos.environ["CUDA_VISIBLE_DEVICES"] = "1"
2.設定Tensorflow使用的顯存大小
a)按固定比例設定
譬如我們設定配置設定給GPU的顯存大小是0.7,可以按如下方式設定:
gpu_options = tf.GPUOptions(per_process_gpu_memory_fraction=0.7)sess = tf.Session(config=tf.ConfigProto(gpu_options=gpu_options))
b)按需設定
除了設定固定比例,也可以調整allow-growth參數來按需配置設定:
gpu_options = tf.GPUOptions(allow_growth=True)sess = tf.Session(config=tf.ConfigProto(gpu_options=gpu_options))
PaddlePaddle的顯存優化
1.原生政策
在優化之前,先看看原生的PaddlePaddle的顯存配置設定政策:原生的CUDA系統調用 cudaMalloc 和 cudaFree 均是同步操作,非常耗時。為了加速顯存配置設定,飛槳采用了顯存預配置設定的政策,具體方式如下圖所示:
![](https://img.laitimes.com/img/__Qf2AjLwojIjJCLyojI0JCLicmbw5SO1EjYkZ2MxADMhNTYwQTNhRmMxIjY0ETZkBTOhljMx8CX0JXZ252bj91Ztl2Lc52YucWbp5GZzNmLn9Gbi1yZtl2Lc9CX6MHc0RHaiojIsJye.png)
在配置設定requested_size大小的顯存時,先定義一個顯存池的大小,記為chunk_size,chunk_size由環境變量 FLAGS_fraction_of_gpu_memory_to_use 确定,表征chunk_size在全部顯存的占比,預設值為0.92,即架構預先配置設定顯示卡92%的顯存。
設定固定比例的顯存
export FLAGS_fraction_of_gpu_memory_to_use=0.4 # 預先40%的GPU顯存
2.優化政策
除了我們剛剛提到的顯存預配置設定,Paddle還提供了多種通用顯存優化方法,使得同樣網絡模型及配置下的顯存占用盡可能小,進而可以支援更大batch size的訓練,來提升訓練效率,下面介紹最重要的兩種方法:分别是GC(Garbage Collection)政策和Inplace政策。
2.1 GC政策: 顯存垃圾及時回收
GC(GarbageCollection)的原理是在網絡運作階段及時釋放無用變量的顯存空間,達到節省顯存的目的。GC可生效于使用Executor,ParallelExecutor做模型訓練/預測時。GC政策由三個環境變量控制:
a). FLAGS_eager_delete_tensor_gb
建議預設設定為FLAGS_eager_delete_tensor_gb = 0
- 若 FLAGS_eager_delete_tensor_gb=0 ,則一旦有顯存垃圾則馬上回收,最為節省顯存。
- 若 FLAGS_eager_delete_tensor_gb=1 ,則顯存垃圾積攢到1G後才觸發回收。
- 若 FLAGS_eager_delete_tensor_gb<0 ,則GC政策關閉。
b).FLAGS_memory_fraction_of_eager_deletion
建議預設設定為FLAGS_memory_fraction_of_eager_deletion = 1
- 若 FLAGS_memory_fraction_of_eager_deletion=0.6 ,則表示僅回收顯存占用60%大的變量顯存。
- 若 FLAGS_memory_fraction_of_eager_deletion=0 ,則表示不回收任何變量的顯存,GC政策關閉。
- 若 FLAGS_memory_fraction_of_eager_deletion=1 ,則表示回收所有變量的顯存。
c).FLAGS_fast_eager_deletion_mode
建議預設設定為FLAGS_fast_eager_deletion_mode = 1
這是快速GC政策的開關,bool類型,預設值為True,表示使用快速GC政策。快速GC政策會不等待CUDAKernel結束直接釋放顯存。建議使用者維持預設值,即 FLAGS_fast_eager_deletion_mode=True 。
2.2 Inplace政策: Op内部的輸出複用輸入
Inplace政策的原理是Op的輸出複用Op輸入的顯存空間。例如,reshape操作的輸出和輸入可複用同一片顯存空間。
Inplace政策可生效于使用ParallelExecutor或CompiledProgram加with_data_parallel做模型訓練和預測,通過 BuildStrategy 設定。
具體方式為:
build_strategy = fluid.BuildStrategy()build_strategy.enable_inplace =True# 開啟Inplace政策compiled_program =fluid.CompiledProgram(train_program).with_data_parallel(loss_name=loss.name, build_strategy=build_strategy)
3. 最佳優化實踐
說了這麼多,大家在使用PaddlePaddle優化顯存的時候,可以建議大家從以下三個方面優化:
(1)設定預配置設定顯存池:
FLAGS_fraction_of_gpu_memory_to_use=0.92
(2)開啟GC政策:
FLAGS_eager_delete_tensor_gb=0 。FLAGS_memory_fraction_of_eager_deletion=1FLAGS_fast_eager_deletion_mode=True
(3)開啟Inplace政策:
build_strategy.enable_inplace= True ,fetch_list中的loss.persistable= Trueacc.persistable= True
大家在實際跑項目的時候可以參考本文的參數進行訓練,說不定有新的效果~也歡迎大家回報更優的方式^_^
參考文獻:
1.更快更簡單|飛槳PaddlePaddle顯存配置設定與優化最佳實踐
-點選右下角 告訴大家你“在看”-