tensorflow
TensorFlowでメモリリークをデバッグする方法
サーチ…
Graph.finalize()を使用して、ノードをグラフに追加する
TensorFlowを使用する最も一般的なモードは、第一のようなTensorFlow演算子(のデータフローグラフの構築を伴うtf.constant()
およびtf.matmul()
次に呼び出すことによって、 手順を実行する 、 tf.Session.run()
ループ内の方法(例えば、Aをトレーニングループ)。
メモリリークの一般的な原因は、トレーニングループにノードをグラフに追加する呼び出しが含まれており、これらの呼び出しがすべての繰り返しで実行されるため、グラフが大きくなります。これらは明らかであるかもしれません(例えば、 tf.square()
ようなTensorFlow演算子への呼び出し)、暗黙の(例えば、 tf.train.Saver()
ような演算子を生成するTensorFlowライブラリ関数への呼び出し)、または微妙な暗黙的にtf.convert_to_tensor()
を呼び出し、新しいtf.constant()
をグラフに追加する、 tf.Tensor
とNumPy配列のオーバーロードされた演算子です。
tf.Graph.finalize()
メソッドは、次のようなリークを捕捉するのに役立ちます:グラフを読み取り専用としてマークし、何かがグラフに追加された場合に例外を発生させます。例えば:
loss = ...
train_op = tf.train.GradientDescentOptimizer(0.01).minimize(loss)
init = tf.initialize_all_variables()
with tf.Session() as sess:
sess.run(init)
sess.graph.finalize() # Graph is read-only after this statement.
for _ in range(1000000):
sess.run(train_op)
loss_sq = tf.square(loss) # Exception will be thrown here.
sess.run(loss_sq)
この場合、オーバーロードされた*
演算子は新しいノードをグラフに追加しようとします:
loss = ...
# ...
with tf.Session() as sess:
# ...
sess.graph.finalize() # Graph is read-only after this statement.
# ...
dbl_loss = loss * 2.0 # Exception will be thrown here.
tcmallocアロケータを使用する
メモリ割り当てのパフォーマンスを向上させるために、多くのTensorFlowユーザーは、大規模オブジェクト(多数のテンソルなど)を割り当てたり割り当てを解除したりするとき、 tcmalloc
断片化が少ないため、デフォルトのmalloc()
実装の代わりにtcmalloc
を使用します。メモリーを大量に消費するTensorFlowプログラムの中には、 ヒープ・アドレス空間を (それらが使用する個々のオブジェクトをすべて解放しながら)デフォルトのmalloc()
でリークすることが知られていましたが、 tcmalloc
に切り替えた後、さらに、 tcmalloc
にはヒーププロファイラーが含まれているため、残ったリークがどこで発生したかを追跡することができます。
tcmalloc
のインストールはお使いのオペレーティングシステムによって異なりますが、以下はUbuntu 14.04(trusty)で動作します( script.py
はTensorFlow Pythonプログラムの名前です)。
$ sudo apt-get install google-perftools4
$ LD_PRELOAD=/usr/lib/libtcmalloc.so.4 python script.py ...
上記のように、単にtcmalloc
切り替えるだけで、多くの明らかなリークを修正できます。ただし、メモリ使用量が増加している場合は、次のようにヒーププロファイラーを使用できます。
$ LD_PRELOAD=/usr/lib/libtcmalloc.so.4 HEAPPROFILE=/tmp/profile python script.py ...
上記のコマンドを実行すると、プログラムはプロファイルをファイルシステムに定期的に書き込みます。プロファイルの順序は次のようになります。
-
/tmp/profile.0000.heap
-
/tmp/profile.0001.heap
-
/tmp/profile.0002.heap
- ...
google-pprof
ツールを使用してプロファイルを読むことができます(たとえば、Ubuntu 14.04で) google-perftools
パッケージの一部としてインストールできます。たとえば、上記で収集した3番目のスナップショットを見るには:
$ google-pprof --gv `which python` /tmp/profile.0002.heap
上のコマンドを実行するとGraphVizウィンドウがポップアップし、プロファイル情報が有向グラフとして表示されます。