4

当我意识到即使我在for循环中关闭当前会话时,我只是在尝试一些四元数神经网络的东西,但我的程序大量减速,并且由于ops正在构建而导致内存泄漏。这是我的代码:Tensorflow:甚至在关闭会话时发生内存泄漏?

for step in xrange(0,200):#num_epochs * train_size // BATCH_SIZE): 
338 
339   with tf.Session() as sess: 
340 
341    offset = (BATCH_SIZE) % train_size 
342    #print "Offset : %d" % offset 
343 
344    batch_data = [] 
345    batch_labels = [] 
346    batch_data.append(qtrain[0][offset:(offset + BATCH_SIZE)]) 
347    batch_labels.append(qtrain_labels[0][offset:(offset + BATCH_SIZE)] 
352    retour = sess.run(test, feed_dict={x: batch_data}) 
357 
358    test2 = feedForwardStep(retour, W_to_output,b_output) 
367    #sess.close() 

问题似乎来自test2 = feedForward(..)。我需要在执行retour一次后声明这些操作,因为retour不能作为占位符(我需要遍历它)。没有这条线,程序运行得非常好,速度快,没​​有内存泄漏。我不明白为什么看起来TensorFlow正试图“拯救” test2即使我关闭会话...

回答

8

TL; DR:关闭会话不会在你的Python程序释放tf.Graph数据结构,并且如果循环的每次迭代都将节点添加到图中,则会发生泄漏。

由于您的功能feedForwardStep创造了新的TensorFlow操作,你把它叫做for循环内,则有在你的代码—泄漏虽然是一个微妙的。

除非另有说明(使用with tf.Graph().as_default():块),否则所有TensorFlow操作都会添加到全局默认图形中。这意味着每次调用tf.constant(),tf.matmul(),tf.Variable()等都会将对象添加到全局数据结构中。有两种方法来避免这种情况:

  1. 结构程序,让您建立图一次,然后用tf.placeholder() OPS不同的值养活在每个迭代。你在你的问题中提到这可能是不可能的。

  2. 在每个for循环中显式创建一个新图。如果图的结构取决于当前迭代中可用的数据,这可能是必需的。

    for step in xrange(200): 
        with tf.Graph().as_default(), tf.Session() as sess: 
         # Remainder of loop body goes here. 
    

    注意,在这个版本中,您不能使用TensorOperation对象从以前的迭代:您可以按如下做到这一点。 (例如,从您的代码片段中不清楚哪里来自test)。

+0

谢谢!我会尝试你的第二个命题,测试是一个我可以在for循环之外定义的操作(就像你在1点建议的那样)。 –

+0

不幸的是,我得到了一个很好的“会话图是空的,在调用run()之前向图中添加操作”使用tf.Graph.as_default() –

+0

我的好像似乎工作!非常感谢 ! –