如何处理GPU训练显存不足[memory isnapos;t enough][alloc failed][out of memory]
【現象描述】
GPU上網絡運行過程中出現OOM(顯存不足),報錯日志中有如下信息:
cudaMalloc failed, ret[2], out of memory
或者:
memory isn't enough and alloc failed
【原因分析】
網絡訓練過錯中出現顯存不足的原因很多,后續遇到我會持續補充,當前遇到的一些原因如下:
1.卡被占用,導致可用顯存變小了。
2.網絡訓練batchsize過大。
3.輸入數據的shape是變化的(輸入數據動態shape)。
4.輸出結果的tensor保存起來了。
5.網絡中的算子里出現顯存泄漏(算子里每次launch都申請顯存,并且不釋放)。
【排查步驟和解決方法】
步驟1:執行前使用命令nvidia-smi查看卡的使用狀態,是否有被占用以及被占用的大小,剩下可用顯存有多大。
步驟2:排查訓練的batchsize是否過大,可以逐步縮小batch,如果覺得batch不夠大,還是出現OOM,則排除這個原因。
步驟3:確認輸入數據是否是動態shape,當前動態shape還不支持輸入shape可變,因為針對這種場景,每次step訓練都會編譯新圖,導致顯存不斷申請最后OOM,可以通過圖的個數是不是不斷増長來判斷。(context.set_context(save_graphs=True),然后觀察*_validate*.ir這一類ir是不是一直在增多)
步驟4:輸出tensor里會掛接device上的地址,方便print時同步device數據輸出,在tensor析構的時候會釋放device地址,因此如果每次step訓練都把輸出tensor保存起來的話,導致tensor不會析構,隨著訓練step的增加則會OOM。
案例代碼:
losses=[] for i in range(steps):loss = train_network()losses.append(loss)該案例代碼將圖的執行結果loss放到全局losses中存儲,因此每次循環都會保存loss的device地址,隨著訓練次數的增加可能會導致OOM。如果有存儲圖輸出結果的訴求,可以轉化成asnumpy后保存,改成loss = train_network().asnumpy(),loss經過asnumpy后拷貝device到host后會釋放掉device的地址。
步驟5:前面步驟確認都沒有問題的話,則有可能是算子實現bug,這塊需要對算子實現有一定的基礎了解,可以排查下是否有新增算子,算子里是否有申請顯存的操作導致顯存泄漏。
案例代碼:
bool Launch(const std::vector<AddressPtr> &inputs, const std::vector<AddressPtr> &workspace,const std::vector<AddressPtr> &outputs, void *stream_ptr) override {T *input = GetDeviceAddress<T>(inputs, 0);S *indices = GetDeviceAddress<S>(inputs, 1);T *updates = GetDeviceAddress<T>(inputs, 2);T *output = GetDeviceAddress<T>(outputs, 0);const size_t indices_len = sizeof(S) * out_strides_.size();void *indices_stride_work =?device::gpu::GPUMemoryAllocator::GetInstance().AllocTensorMem(indices_len);if (indices_stride_work == nullptr) {MS_LOG(EXCEPTION) << "Failed to alloc indices_stride_work, size: " << indices_len;}每次launch都調用內存池接口AllocTensorMem申請內存,導致隨著訓練step增加出現OOM,可以搜索代碼查看算子的Launch中是否有調用AllocTensorMem函數。
步驟6:前面的幾種可能原因都排查沒有問題的話,需要MindSpore開發人員詳細分析了,context.set_context(save_graphs=True)同時export GLOG_v=1保存執行日志,將保存的圖和日志打包發給開發人員排查確認。
【建議與總結】
1.輸出tensor一般不建議保存起來,如果需要保存,可以保存asnumpy后的對象,tensor經過asnumpy后拷貝device到host后會釋放掉device的地址。
2.算子實現邏輯不應該出現申請顯存的邏輯,一般都可以通過workspace來實現臨時device地址存儲的目的。上面的案例修改方案參考:https://gitee.com/mindspore/mindspore/pulls/25633
總結
以上是生活随笔為你收集整理的如何处理GPU训练显存不足[memory isnapos;t enough][alloc failed][out of memory]的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: tensorflow出现显存不足的提示
- 下一篇: 技术至简-3:简述无线通信系统中的数字调