tensorflow
Jak debugować wyciek pamięci w TensorFlow
Szukaj…
Użyj Graph.finalize (), aby złapać węzły dodawane do wykresu
Najczęstszy tryb korzystania z TensorFlow obejmuje najpierw zbudowanie wykresu przepływu danych operatorów TensorFlow (takich jak tf.constant()
i tf.matmul()
, a następnie uruchomienie kroków poprzez wywołanie metody tf.Session.run()
w pętli (np. pętla treningowa).
Częstym źródłem wycieków pamięci jest to, że pętla szkoleniowa zawiera wywołania, które dodają węzły do wykresu, i są one uruchamiane w każdej iteracji, powodując wzrost wykresu. Mogą być oczywiste (np. Wywołanie operatora TensorFlow, takiego jak tf.square()
), niejawne (np. Wywołanie funkcji bibliotecznej TensorFlow, która tworzy operatory takie jak tf.train.Saver()
) lub subtelne (np. Wywołanie przeciążony operator na tf.Tensor
i NumPy, który pośrednio wywołuje tf.convert_to_tensor()
i dodaje nowy tf.constant()
do wykresu).
Metoda tf.Graph.finalize()
może pomóc w tf.Graph.finalize()
takich przecieków: zaznacza wykres jako tylko do odczytu i podnosi wyjątek, jeśli coś zostanie dodane do wykresu. Na przykład:
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)
W tym przypadku przeciążony *
operator próbuje dodać nowe węzły do wykresu:
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.
Użyj alokatora tcmalloc
Aby poprawić wydajność alokacji pamięci, wielu użytkowników TensorFlow często używa tcmalloc
zamiast domyślnej implementacji malloc()
, ponieważ tcmalloc
cierpi mniej na fragmentację podczas przydzielania i zwalniania dużych obiektów (takich jak wiele tensorów). Wiadomo, że niektóre programy TensorFlow wymagające dużej ilości pamięci przeciekają przestrzeń adresową sterty (jednocześnie zwalniając wszystkie poszczególne obiekty, których używają) za pomocą domyślnej funkcji malloc()
, ale działały dobrze po przejściu na tcmalloc
. Ponadto tcmalloc
zawiera profiler sterty , który umożliwia śledzenie, gdzie mogły wystąpić pozostałe wycieki.
Instalacja tcmalloc
będzie zależeć od twojego systemu operacyjnego, ale następujące działania działają na Ubuntu 14.04 (trusty) (gdzie script.py
to nazwa twojego programu TensorFlow Python):
$ sudo apt-get install google-perftools4
$ LD_PRELOAD=/usr/lib/libtcmalloc.so.4 python script.py ...
Jak wspomniano powyżej, po prostu przejście na tcmalloc
może naprawić wiele widocznych wycieków. Jeśli jednak użycie pamięci wciąż rośnie, możesz użyć profilera sterty w następujący sposób:
$ LD_PRELOAD=/usr/lib/libtcmalloc.so.4 HEAPPROFILE=/tmp/profile python script.py ...
Po uruchomieniu powyższej komendy program okresowo zapisuje profile w systemie plików. Sekwencja profili zostanie nazwana:
-
/tmp/profile.0000.heap
-
/tmp/profile.0001.heap
-
/tmp/profile.0002.heap
- ...
Możesz czytać profile za pomocą narzędzia google-pprof
, które (na przykład na Ubuntu 14.04) można zainstalować jako część pakietu google-perftools
. Na przykład, aby spojrzeć na trzecią migawkę zebraną powyżej:
$ google-pprof --gv `which python` /tmp/profile.0002.heap
Uruchomienie powyższego polecenia spowoduje wyświetlenie okna GraphViz, pokazującego informacje o profilu w postaci ukierunkowanego wykresu.