tensorflow
Hur man felsöker ett minnesläckage i TensorFlow
Sök…
Använd Graph.finalize () för att fånga noder som läggs till i diagrammet
Det vanligaste sättet att använda TensorFlow innebär att man först bygger en dataflödesdiagram över TensorFlow-operatörer (som tf.constant()
och tf.matmul()
, sedan kör steg genom att anropa tf.Session.run()
i en slinga (t.ex. en träningsslinga).
En vanlig källa till minnesläckor är där träningsslingan innehåller samtal som lägger till noder i diagrammet, och dessa körs i varje iteration, vilket får grafen att växa. Dessa kan vara uppenbara (t.ex. ett samtal till en TensorFlow-operatör som tf.square()
), implicit (t.ex. ett samtal till en TensorFlow-biblioteksfunktion som skapar operatörer som tf.train.Saver()
) eller subtil (t.ex. ett samtal till en överbelastad operatör på en tf.Tensor
och en NumPy-matris, som implicit kallar tf.convert_to_tensor()
och lägger till en ny tf.constant()
till grafen).
tf.Graph.finalize()
kan hjälpa till att fånga läckor som denna: den markerar en graf som skrivskyddad och ger ett undantag om något läggs till i diagrammet. Till exempel:
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)
I det här fallet försöker den överbelastade *
operatören lägga till nya noder i diagrammet:
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.
Använd tcmalloc-tilldelaren
För att förbättra minnesallokeringsprestanda använder många TensorFlow-användare ofta tcmalloc
istället för standard- malloc()
, eftersom tcmalloc
lider mindre av fragmentering vid allokering och omfördelning av stora objekt (till exempel många tensorer). Vissa minnesintensiva TensorFlow-program har varit kända för att läcka heap-adressutrymme (medan de frigör alla enskilda objekt som de använder) med standard malloc()
, men fungerade bra efter att ha bytt till tcmalloc
. Dessutom innehåller tcmalloc
en högprofil , som gör det möjligt att spåra var eventuella återstående läckor kan ha inträffat.
Installationen för tcmalloc
beror på ditt operativsystem, men följande fungerar på Ubuntu 14.04 (pålitligt) (där script.py
är namnet på ditt TensorFlow Python-program):
$ sudo apt-get install google-perftools4
$ LD_PRELOAD=/usr/lib/libtcmalloc.so.4 python script.py ...
Som nämnts ovan kan helt enkelt byta till tcmalloc
fixa en hel del uppenbara läckor. Men om minnesanvändningen fortfarande växer kan du använda heap-profilen enligt följande:
$ LD_PRELOAD=/usr/lib/libtcmalloc.so.4 HEAPPROFILE=/tmp/profile python script.py ...
När du har kört ovanstående kommando skriver programmet periodiskt profiler till filsystemet. Profilsekvensen kommer att namnges:
-
/tmp/profile.0000.heap
-
/tmp/profile.0001.heap
-
/tmp/profile.0002.heap
- ...
Du kan läsa profilerna med verktyget google-pprof
, som (till exempel på Ubuntu 14.04) kan installeras som en del av paketet google-perftools
. Till exempel för att titta på den tredje ögonblicksbilden som samlas in ovan:
$ google-pprof --gv `which python` /tmp/profile.0002.heap
Om du kör ovanstående kommando visas ett GraphViz-fönster som visar profilinformationen som en riktad graf.