ホームページ >バックエンド開発 >Python チュートリアル >コンテキスト デコレータを使用した Pytorch のメモリ リーク問題のデバッグ
デコレーターは、Python コンテキスト マネージャーの特定の実装です。この記事では、pytorch GPU デバッグの例を通じてそれらの使用方法を説明します。すべての状況で機能するとは限りませんが、非常に便利であることがわかりました。
メモリ リークをデバッグするには、さまざまな方法があります。この記事では、コード内で問題のある行を特定するための便利な方法を紹介します。この方法は、特定の場所を簡潔な方法で見つけるのに役立ちます。
問題が発生した場合、一般的に使用される古典的な方法は、次の例のように、デバッガーを使用して行ごとにチェックすることです。
def memleak_wrapper(func): def wrap(*args, **kwargs): print("num tensors start is ...") out = func(*args, **kwargs) print("num tensors end is ...") return out return wrap@memleak_wrapper def function_to_debug(x): print(f"put line(s) of code here. Input is {x}") out = x + 10 return outout = function_to_debug(x=1000) print(f"out is {out}") #输入类似这样 #num tensors start is ... #put line(s) of code here. Input is 1000 #num tensors end is ... #outis 1010このコードを実行するには、チェックしたいコード行を関数 (function_to_debug) に入れる必要があります。ただし、依然として多くのコードを手動で挿入する必要があるため、これは最良の方法ではありません。もう 1 つは、コード ブロックが複数の変数を生成する場合、これらの下流変数を使用するための追加のソリューションを見つける必要があることです。 コンテキスト デコレーター上記の問題を解決するには、関数デコレーターの代わりにコンテキスト マネージャーを使用できます。コンテキスト マネージャーの最も広く使用されている例は、with ステートメントを使用してコンテキストをインスタンス化することです。以前は最も一般的なものは次のとおりでした。
with open("file") as f: …Python の contextlib ライブラリを使用すると、Python ユーザーは独自のコンテキスト マネージャーを簡単に作成できます。したがって、この記事では、ContextDecorator を使用して、上記のデコレータを使用しようとした作業を完了します。その理由は、開発と使用が簡単であるためです。
from contextlib import ContextDecorator class check_memory_leak_context(ContextDecorator): def __enter__(self): print('Starting') return self def __exit__(self, *exc): print('Finishing') return FalseContextDecorator には、コンテキストに入るときまたはコンテキストから出るときに呼び出される、enter() と exit() という 2 つのメソッドがあります。 __exit__ の *exc パラメータは、受信した例外を表します。 ここで、これを使用して上記の問題を解決します。 ContextDecorator を使用してメモリ リークを見つけるテンソルの総数を計算する必要があるため、計算プロセスを関数 get_n_tensors() にカプセル化して、テンソルを次の時点で計算できるようにします。コンテキストの始まりと終わり 数量:
class check_memory_leak_context(ContextDecorator): def __enter__(self): self.start = get_n_tensors() return self def __exit__(self, *exc): self.end = get_n_tensors() increase = self.end — self.start if increase > 0: print(f”num tensors increased with" f"{self.end — self.start} !”) else: print(”no added tensors”) return False増加がある場合は、コンソールに出力します。 get_n_tensor() はガベージ コレクター (gc) を使用し、pytorch 用にカスタマイズされていますが、他のライブラリ用に簡単に変更できます:
import gc def get_n_tensors(): tensors= [] for obj in gc.get_objects(): try: if (torch.is_tensor(obj) or (hasattr(obj, ‘data’) and torch.is_tensor(obj.data))): tensors.append(obj) except: pass return len(tensors)これは現在使用でき、次の目的で使用できます。 any コードの行 (またはブロック) は次のコンテキストを使用します:
x = arbitrary_operation(x) ... with check_memory_leak_context(): y = x[0].permute(1, 2, 0).cpu().detach().numpy() x = some_harmless_operation() ... x = another_arbitrary_operation(x)新しいテンソルがコンテキスト デコレーターによってラップされた行内で作成された場合、それが出力されます。 概要これは、開発中に別のファイルに配置できる非常に優れたコード スニペットです。この記事の完全なコードは次のとおりです: https:// gist.github.com/MarkTension/4783697ebd5212ba500cdd829b364338最後に、この小さな記事が、コンテキスト マネージャーとは何か、コンテキスト デコレーターの使用方法、コンテキスト デコレーターを pytorch のデバッグに適用する方法を理解するのに役立つことを願っています。
以上がコンテキスト デコレータを使用した Pytorch のメモリ リーク問題のデバッグの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。