「RuntimeError: CUDA メモリ不足」問題の解決方法

ニティン・キショア著

編集:栄淮陽

ガイド

「RuntimeError: CUDA Out of Memory」を解決するために試せるいくつかの解決策。

2f2d2cc4d51d94f3f4caff22206d8b04.png

この問題が発生した場合は、コード変更の昇順に次の提案を試してください。

  1. 「batch_size」を減らす

  2. 精度を下げる

  3. エラーの内容を実行します

  4. キャッシュの消去

  5. モデル/トレーニングを変更する

これらのオプションのうち、事前トレーニング済みモデルを使用している場合、最も簡単で問題を解決できる可能性が最も高いのは最初のオプションです。

バッチサイズを変更する

既製のコードまたはモデルを実行している場合、最善の策はバッチサイズを減らすことです。半分にし、エラーがなくなるまで半分にし続けます。

4284b11a44dd303a73b16575789c84aa.jpeg

ただし、途中でバッチサイズを 1 に設定しても問題が解決しない場合は、何か他の問題があり、それを修正できれば、モデル トレーニングはより大きなバッチサイズでも機能するようになります。

精度を下げる

Pytorch-Lightning を使用している場合は、精度を「float16」に変更してみることもできます。これにより、予想される Double テンソルと Float テンソルの間の不一致などの問題が発生する可能性がありますが、多くのメモリが節約され、パフォーマンスのトレードオフが非常にわずかであるため、実行可能なオプションになります。

この 3 番目のオプションは、

エラーメッセージに従ってください

これは次のコマンドで実行できます。Windows コンピュータを使用している場合は、exportの代わりにsetを使用できます。

export PYTORCH_CUDA_ALLOC_CONF=garbage_collection_threshold:0.6,max_split_size_mb:128

Jupyter または Colab ノートブックを使用している場合は、 を発見した後RuntimeError: CUDA out of memoryカーネルを再起動する必要があります。

マルチ GPU システムを使用する場合は、CUDA_VISIBLE_DEVICES環境変数を使用して使用する GPU を選択することをお勧めします。

$ export CUDA_VISIBLE_DEVICES=0  (OR)
$ export CUDA_VISIBLE_DEVICES=1  (OR) 
$ export CUDA_VISIBLE_DEVICES=2,4,6  (OR)# This will make the cuda visible with 0-indexing so you get cuda:0 even if you run the second one.

または、Python コードで設定します。

import os
os.environ['CUDA_VISIBLE_DEVICES']='2, 3'

一部のスタック オーバーフロー投稿では、コードに次の行を追加してみる必要があります。

キャッシュの解放

モデルが cuda でどれだけのメモリを使用しているかを確認するには、次のことを試してください。

import gc
def report_gpu():
   print(torch.cuda.list_gpu_processes())
   gc.collect()
   torch.cuda.empty_cache()

Python のガベージ コレクションを呼び出し、pytorch の空のキャッシュを呼び出すと、基本的に GPU がクリーンな状態に戻り、必要以上のメモリを使用せず、次のモデル カーネルのトレーニングを開始するときに再起動する必要がなくなります。

import gc
gc.collect()
torch.cuda.empty_cache()

torch.cuda.empty_cache()または はCUDA メモリを解放できますgc.collect()、明らかに解放されていないメモリは Python に返されます。したがって、これらのスクリプトに期待を抱かないでください。この方法は、JupyterLab または Colab で機能します。これらのコードの使用例を次に示します。

c5d948e598abad215339d21fc12dcd31.png

すぐに .detach() と .cpu() を見てみましょう。

f83654695deade830570b590639fc3a5.png

これは通常、ノートブックと ipython でのみ機能します

これらの代替案を見てみましょう

koila Python パッケージを使用する

koila の使用例は次のとおりです。

pip install koila
# Wrap the input tensor and label tensor.
# If a batch argument is provided, that dimension of the tensor would be treated as the batch.
# In this case, the first dimension (dim=0) is used as batch's dimension.

(input, label) = lazy(input, label, batch=0)

これらのどれも役に立たない場合、問題を解決する唯一の方法は次のことを調べることです。

メモリを使用しているのは何ですか?

d29f974964753a551eeec6c9f7e64084.jpeg

一般に信じられていることに反して、より大きなモデルをトレーニングするためにより大きな GPU は必要ありません。勾配累積を使用するだけで済みます。これについては後で説明します。通常、エラー メッセージは良いヒントになるため、エラー メッセージを詳しく分析してみましょう。

7aef6f2923833252e0f041bcbc4e6ce6.png

このメッセージは、合計 15.78G の GPU メモリがあることを示します。したがって、データとモデルを GPU に移動する必要があるため、そのサイズを確認できます。合計容量を超えると、そのマシンでは実行されなくなり、データを分割して CPU と GPU の間で移動し続ける必要があります。

7c6f669462d194c253451d239c2f367c.jpeg

画像サイズを減らすことも役立ちます。使用可能なメモリが少ししかないために x MiB を使用できないという場合は、他のプロセスが GPU を使用していることを調べて、そのスペースを解放してください。以下を実行して、Python プロセスの PID を見つけます。

nvidia-smi

殺す

sudo kill -9 pid

モデル/トレーニング ループを変更する

現在は最終段階に入っています。すべてを試しましたが、GPU メモリを使用しているものは何もありません。おそらく、作成したコードは多くのものを GPU にプッシュしていると思われます。大規模な行列の乗算にはこれが必要ですが、メトリクスの計算ロギングなどの単純な処理の場合は、CPU 上で行うことができます。したがって、それらを GPU から削除します。

2241135c19ace19beda6c18d806f2892.png

損失、Pres、ターゲット

テンソル全体を保存するのではなく、エポックの終わりに損失を要約する必要がある場合に使用してくださいloss.item()

preds.detach().cpu()GPU から予測とターゲットを削除するために使用します。これらは重い商品です。ログ記録用にのみ保存する場合は、メモリに保存する必要はありません。

ここで注意してください。損失がエポック全体で一定であることがわかった場合、それはおそらく、計算グラフの一部を分離しており、バックプロパゲーションが更新された値を返す方法がないことが原因です。したがって、コードのどの時点で上記 2 つのステップを実行できるかを考えてください。

別のトリックについて話しましょう。

勾配累積

バッチ サイズを減らすことはメモリの問題を回避する 1 つの方法ですが、バッチ サイズが小さいほど、バッチ間の変動性が大きくなります。したがって、トレーニングのダイナミクスは異なります。異なるバッチサイズの構造体に対して異なるハイパーパラメーターのセットを検索し続ける必要はありません。

accumと呼ばれる別のパラメータを使用して、蓄積するグラデーション バッチの数を定義することにより、「グラデーションを蓄積」できます。これらの勾配を累積バッチに追加するため、batch_size を同じ数値で除算します。

batch_size//accum

コールバックを使用して蓄積GradientAccumulationを行うことができます

batch_size = 64
accum=2
# Data loader , change the batchsize parmeter to  bs = 64//accum
cbs = GradientAccumulation(64) if accum else []

私たちにできることは、32 個のデータを実行しながら、一度に 64 個のデータのように動作させる方法を見つけることです。通常のトレーニング ループでは、 を実行する前にloss.backward()勾配をゼロにする必要があります。勾配をゼロにしないと、勾配が累積します。

したがって、勾配をゼロにせずに 2 つのハーフバッチのトレーニングを実行すると、それらの勾配が蓄積され、最終的にターゲットの有効バッチ サイズで同じ勾配になります。トレーニング ループでは、事前に設定されたターゲットに達したら、小さなバッチサイズに従って更新するためにカウンターを使用する必要があります。その時点で勾配がゼロになります。それまでは、ただloss.backward()蓄積し続けるだけです。

英文原文:https://medium.com/@snk.nitin/how-to-solve-cuda-out-of-memory-error-850bb247cfb2

推奨読書:

私の2022年のインターネットスクール募集の共有

私の2021年のまとめ

アルゴリズムポストと開発ポストの違いについての話

インターネットスクール採用・研究開発・給与概要

2022年のネット就活状況、もうすぐ金9銀10が銅9鉄10になります!

公開番号:AIカタツムリカー

謙虚さを保ち、規律を保ち、改善し続ける

0681527134a9d5e4062b3fae28132c05.jpeg

【カタツムリ】を送って「ハンズオンAIプロジェクト」(AIカタツムリカー著)を入手

[1222] を送信して、適切な leetcode ブラッシングノートを入手してください

[AI Four Classics] を送信する 4 つの古典的な AI 電子書籍を入手する

おすすめ

転載: blog.csdn.net/qq_33431368/article/details/132703128
おすすめ