模型执行后清除Tensorflow GPU内存

时间:2016-09-28 21:38:35

标签: python tensorflow gpu

我已经训练了3个模型,现在正在运行代码,按顺序加载3个检查点中的每一个并使用它们运行预测。我正在使用GPU。

当加载第一个模型时,它预先分配整个GPU内存(我想要通过第一批数据)。但是当它完成时它不会卸载内存。当加载第二个模型时,同时使用tf.reset_default_graph()with tf.Graph().as_default(),GPU内存仍然会从第一个模型中完全消耗,然后第二个模型将缺乏内存。

有没有办法解决这个问题,除了使用Python子进程或多处理来解决问题(我通过谷歌搜索找到的唯一解决方案)?

6 个答案:

答案 0 :(得分:12)

2016年6月发出的git问题(https://github.com/tensorflow/tensorflow/issues/1727)表明存在以下问题:

  

目前GPUDevice中的Allocator属于ProcessState,   这本质上是一个全球性的单身人士。第一个会话使用GPU   初始化它,并在进程关闭时释放自己。

因此,唯一的解决方法是使用进程并在计算后关闭它们。

示例代码:

import tensorflow as tf
import multiprocessing
import numpy as np

def run_tensorflow():

    n_input = 10000
    n_classes = 1000

    # Create model
    def multilayer_perceptron(x, weight):
        # Hidden layer with RELU activation
        layer_1 = tf.matmul(x, weight)
        return layer_1

    # Store layers weight & bias
    weights = tf.Variable(tf.random_normal([n_input, n_classes]))


    x = tf.placeholder("float", [None, n_input])
    y = tf.placeholder("float", [None, n_classes])
    pred = multilayer_perceptron(x, weights)

    cost = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(logits=pred, labels=y))
    optimizer = tf.train.AdamOptimizer(learning_rate=0.001).minimize(cost)

    init = tf.global_variables_initializer()

    with tf.Session() as sess:
        sess.run(init)

        for i in range(100):
            batch_x = np.random.rand(10, 10000)
            batch_y = np.random.rand(10, 1000)
            sess.run([optimizer, cost], feed_dict={x: batch_x, y: batch_y})

    print "finished doing stuff with tensorflow!"


if __name__ == "__main__":

    # option 1: execute code with extra process
    p = multiprocessing.Process(target=run_tensorflow)
    p.start()
    p.join()

    # wait until user presses enter key
    raw_input()

    # option 2: just execute the function
    run_tensorflow()

    # wait until user presses enter key
    raw_input()

因此,如果您在创建的进程中调用函数run_tensorflow()并关闭进程(选项1),则释放内存。如果只运行run_tensorflow()(选项2),则在函数调用后不会释放内存。

答案 1 :(得分:7)

您可以使用numba库释放所有gpu内存

pip install numba 
from numba import cuda 
device = cuda.get_current_device()
device.reset()

这将释放所有内存

答案 2 :(得分:2)

只要不再需要张量(在.run调用终止之前),就会释放由张量分配的GPU内存(回到TensorFlow内存池)。为变量分配的GPU内存在变量容器被销毁时释放。对于DirectSession(即sess = tf.Session(“”)),会话关闭或显式重置(在62c159ff中添加)

答案 3 :(得分:2)

我使用numba释放gpu,使用tensorflow我找不到效果方法。

import tensorflow as tf
from numba import cuda

a = tf.constant([1.0,2.0,3.0],shape=[3],name='a')
b = tf.constant([1.0,2.0,3.0],shape=[3],name='b')
with tf.device('/gpu:1'):
    c = a+b

TF_CONFIG = tf.ConfigProto(
gpu_options=tf.GPUOptions(per_process_gpu_memory_fraction=0.1),
  allow_soft_placement=True)

sess = tf.Session(config=TF_CONFIG)
sess.run(tf.global_variables_initializer())
i=1
while(i<1000):
        i=i+1
        print(sess.run(c))

sess.close() # if don't use numba,the gpu can't be released
cuda.select_device(1)
cuda.close()
with tf.device('/gpu:1'):
    c = a+b

TF_CONFIG = tf.ConfigProto(
gpu_options=tf.GPUOptions(per_process_gpu_memory_fraction=0.5),
  allow_soft_placement=True)

sess = tf.Session(config=TF_CONFIG)

sess.run(tf.global_variables_initializer())
while(1):
        print(sess.run(c))

答案 4 :(得分:1)

我正在寻找Jupyter Notebook中哪个选项更好。即使深度学习应用程序完成,Jupyter Notebook也会永久占用GPU内存。通常会引起GPU风扇错误,这是一个令人头疼的问题。在这种情况下,我必须重置nvidia_uvm并定期重新启动linux系统。我总结出以下两个选项可以消除GPU风扇错误的困扰,但想知道哪个更好。

环境:

  • CUDA 11.0
  • cuDNN 8.0.1
  • TensorFlow 2.2
  • Keras 2.4.3
  • Jupyter Notebook 6.0.3
  • Miniconda 4.8.3
  • Ubuntu 18.04 LTS

第一个选项

将以下代码放在单元格的末尾。内核在应用程序运行时完成后立即结束。但这并不优雅。 Juputer将弹出一条消息,提示已死亡的内核。

import os
 
pid = os.getpid()
!kill -9 $pid

部分选项

以下代码也可以使用Jupyter Notebook结束内核。我不知道numba是否安全。 Nvidia更喜欢“ 0” GPU,它是个人开发人员(而非服务器人员)使用最多的GPU。但是,Neil G和mradul dubey都做出了回应:这使GPU处于不良状态。

from numba import cuda

cuda.select_device(0)
cuda.close()

第二个选项似乎更优雅。有人可以确认哪个是最佳选择吗?

注意:

通过直接执行“ $ python abc.py”在Anaconda环境中自动释放GPU内存并不是这样的问题。但是,有时我需要使用Jyputer Notebook来处理.ipynb应用程序。

答案 5 :(得分:0)

现在似乎有两种方法可以解决迭代训练模型,或者如果您使用将来的多进程池来服务于模型训练,则如果将来完成,池中的进程将不会被杀死。您可以在训练过程中应用两种方法来释放GPU内存,同时希望保留主过程。

  1. 调用一个子流程来运行模型训练。一阶段训练完成后,子流程将退出并释放内存。返回值很容易。
  2. 调用multiprocessing.Process(p)来运行模型训练(p.start),而p.join将指示进程退出和可用内存。

这是一个使用multiprocess.Process的辅助函数,它可以打开一个新进程来运行您的python编写的函数和reture值,而不是使用Subprocess,

# open a new process to run function
def process_run(func, *args):
    def wrapper_func(queue, *args):
        try:
            logger.info('run with process id: {}'.format(os.getpid()))
            result = func(*args)
            error = None
        except Exception:
            result = None
            ex_type, ex_value, tb = sys.exc_info()
            error = ex_type, ex_value,''.join(traceback.format_tb(tb))
        queue.put((result, error))

    def process(*args):
        queue = Queue()
        p = Process(target = wrapper_func, args = [queue] + list(args))
        p.start()
        result, error = queue.get()
        p.join()
        return result, error  

    result, error = process(*args)
    return result, error