模型执行后清除Tensorflow GPU内存

lhcgjxsq  于 2022-11-16  发布在  其他
关注(0)|答案(9)|浏览(276)

我已经训练了3个模型,现在正在运行代码,依次加载3个检查点中的每一个,并使用它们运行预测。
当第一个模型被加载时,它会预先分配整个GPU内存(我想用来处理第一批数据)。但是当它完成时,它不会卸载内存。当第二个模型被加载时,同时使用tf.reset_default_graph()with tf.Graph().as_default(),GPU内存仍然被第一个模型完全消耗掉,第二个模型会出现内存不足的情况。
除了使用Python子进程或多处理来解决这个问题(这是我通过谷歌搜索找到的唯一解决方案)之外,还有什么方法可以解决这个问题吗?

mkh04yzy

mkh04yzy1#

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),则在函数调用后不会释放内存。

rdlzhqv9

rdlzhqv92#

你可以使用numba库来释放所有的gpu内存
第一个
这将释放所有内存

vzgqcmou

vzgqcmou3#

我使用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))
mdfafbf1

mdfafbf14#

现在似乎有两种方法来解决迭代训练模型,或者如果你使用未来的多进程池来服务于模型训练,那么当未来完成时池中的进程不会被杀死,你可以在训练过程中使用两种方法来释放GPU内存,同时你希望保留主进程。
1.调用一个子进程运行模型训练,当一个阶段训练完成后,子进程退出并释放内存,很容易得到返回值。
1.调用multiprocessing.process(p)来运行模型训练(p.start),p.join将指示进程退出并释放内存。
这是一个使用multiprocess.process的帮助函数,它可以打开一个新的进程来运行你的python编写的函数并返回值,而不是使用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
7xzttuei

7xzttuei5#

我正在思考Jupyter笔记本电脑的哪个选项更好。Jupyter笔记本电脑即使完成了深度学习应用程序,也会永久占用GPU内存。它通常会引发GPU风扇错误,这是一个很大的头痛。在这种情况下,我不得不重置nvidia_uvm并定期重启linux系统。我总结了以下两个选项可以解决GPU风扇错误的头痛,但我想知道哪个更好。

环境:

  • CUDA 11.0计算基础架构
  • 铜脱氧核糖核酸8.0.1
  • 张力流2.2
  • 角速度2.4.3
  • Jupyter笔记本电脑6.0.3
  • 微型摄像机4.8.3
  • Ubuntu 18.04 LTS版本
    第一个选项

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

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

区段选项

下面的代码也可以用Jupyter Notebook结束内核,我不知道numba是否安全,英伟达更喜欢“0”GPU,这是个人开发者(而不是服务器家伙)最常用的GPU,不过,Neil G和mradul dubey都有过回应:这会使GPU处于不良状态。

from numba import cuda

cuda.select_device(0)
cuda.close()

似乎第二个选择更优雅,谁能确定哪一个是最好的选择?
备注:
通过直接执行“$ python www. example. com“在Anaconda的环境中自动释放GPU内存并不是这样的问题abc.py,但是,我有时需要使用Jyputer Notebook来处理.ipynb应用程序。

1bqhqjot

1bqhqjot6#

我刚才用垃圾收集器解决了一个OOM错误。

import gc
gc.collect()

model.evaluate(x1, y1)
gc.collect()

model.evaluate(x2, y2)
gc.collect()

等等。
根据Yaroslav Bulatov的回答(当对象被销毁时,tf会释放GPU内存),我推测可能是垃圾收集器还没有运行。强制它收集可以让我解脱,所以这可能是一个很好的方法。

jq6vz3qz

jq6vz3qz7#

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

svmlkihl

svmlkihl8#

当我在一个for循环中训练了120个不同参数的模型后,我得到了这个错误。之后,如果我不杀死内核,我甚至不能训练一个简单的模型。我可以通过在建立模型之前添加下面的行来解决这个问题:
tf.keras.backend.clear_session()
(see(第10页)

esbemjvw

esbemjvw9#

为了释放我的资源,我用途:

import os, signal

os.kill(os.getpid(), signal.SIGKILL)

相关问题