tensorflow
Как отладить утечку памяти в TensorFlow
Поиск…
Используйте Graph.finalize (), чтобы уловить узлы, добавляемые на график
Наиболее распространенный способ использования TensorFlow включает сначала построение графика потока данных операторов tf.constant()
(например, tf.constant()
и tf.matmul()
, а затем выполнение шагов путем вызова tf.Session.run()
в цикле (например, тренировочный цикл).
Общим источником утечек памяти является то, где цикл обучения содержит вызовы, которые добавляют узлы в график, и они выполняются на каждой итерации, заставляя график расти. Они могут быть очевидны (например, вызов оператора tf.square()
например tf.square()
), неявный (например, вызов библиотеки tf.train.Saver()
которая создает такие операторы, как tf.train.Saver()
), или тонкий (например, вызов перегруженный оператор на tf.Tensor
и массив NumPy, который неявно вызывает tf.convert_to_tensor()
и добавляет новый tf.constant()
в график).
Метод 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
Чтобы улучшить производительность распределения памяти, многие пользователи tcmalloc
часто используют 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
. Например, чтобы посмотреть на третий снимок, полученный выше:
$ google-pprof --gv `which python` /tmp/profile.0002.heap
Запуск вышеуказанной команды откроет окно GraphViz, отображающее информацию профиля в виде ориентированного графика.