Zendesk では機械学習 (ML) 製品の構築でかなり多くの Python を使用しています。 機械学習アプリケーションで遭遇する一般的なパフォーマンスの問題の 1 つは、メモリ リークとスパイクです。 Python コードは通常、Hadoop、Spark、AWS Batch などの分散処理フレームワークを介してコンテナ内で実行されます。 各コンテナには、固定量のメモリが割り当てられています。 コードの実行が指定されたメモリの制限を超えると、メモリ不足のエラーによりコンテナーが終了します。 しかし、これはリソースの浪費につながり、予測できないメモリスパイクのために製品の安定性に影響を与える可能性があります。 メモリ リークの原因としては、
- 解放されていない大きなオブジェクトのリング
- コード内の参照サイクル
- 基盤となるライブラリ/拡張機能のメモリ リーク
コードの空間効率と使用されている基盤パッケージについてより良く理解するために、アプリケーションのメモリ使用量をプロファイルすることは有用な作業と言えます。 この投稿では、以下をカバーします:
- profiling memory usage of the application across time
- how to inspect memory usage at specific part of the program
- tips for debugging memory issues
Python code using the memory-profile packageで実行中のメモリ使用量を時間と共に変えて見ることができるようになりました。
# install the required packages
pip install memory_profiler
pip install matplotlib# run the profiler to record the memory usage
# sample 0.1s by defaut
mprof run --include-children python fantastic_model_building_code.py# plot the recorded memory usage
mprof plot --output memory-profile.png
include-children オプションは、親プロセスから生成された子プロセスのメモリ使用量を含めます。 グラフAは、反復モデル学習プロセスを示しており、学習データのバッチ処理に伴い、メモリが周期的に増加することがわかります。 オブジェクトは、ガベージ コレクションが開始されると解放されます。
メモリ使用量が常に増加している場合、メモリ リークの問題が発生する可能性があります。 以下は、これを説明するためのダミーのサンプルスクリプトです。
pdb-mmem オプションを使用して、メモリ使用量が特定のしきい値を超えた時点でデバッガーのブレークポイントを設定することができ、トラブルシューティングの際に便利です。
ある時点でのメモリダンプ
プログラム内の大きなオブジェクトの予想数を理解することは重要で、それらが複製されたり異なるフォーマットに変換されるべきかどうかということを理解する必要があります。