web-dev-qa-db-ja.com

モデル実行後のTensorflow GPUメモリのクリア

3つのモデルをトレーニングし、3つのチェックポイントを順番に読み込み、それらを使用して予測を実行するコードを実行しています。 GPUを使用しています。

最初のモデルが読み込まれると、GPUメモリ全体が事前に割り当てられます(データの最初のバッチを処理するために必要です)。ただし、終了してもメモリはアンロードされません。 tf.reset_default_graph()with tf.Graph().as_default()の両方を使用して2番目のモデルがロードされると、GPUメモリはまだ最初のモデルから完全に消費され、2番目のモデルはメモリ不足になります。

Pythonサブプロセスまたはマルチプロセッシングを使用して問題を回避する以外に、これを解決する方法はありますか(Google検索で見つけた唯一の解決策)?

17
David Parks

2016年6月のgitの問題( https://github.com/tensorflow/tensorflow/issues/1727 )は、次の問題があることを示しています。

現在、GPUDeviceのAllocatorはProcessStateに属します。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)を実行しただけでは、関数呼び出し後にメモリは解放されません。

14
Oliver Wilken

私は numpy を使用してgpuを解放しますが、テンソルフローでは効果メソッドが見つかりません。

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))
3
TanLingxiao

テンソルが不要になったらすぐに(.run呼び出しが終了する前に)、テンソルによって割り当てられたGPUメモリが解放されます(TensorFlowメモリプールに戻ります)。変数に割り当てられたGPUメモリは、変数コンテナーが破棄されると解放されます。 DirectSession(つまり、sess = tf.Session( ""))の場合、セッションが閉じられるか、明示的にリセットされます( 62c159ff に追加されます)

2

反復トレーニングモデルを解決する方法と、将来のマルチプロセスプールを使用してモデルトレーニングを提供する場合、将来が終了してもプール内のプロセスが強制終了されない2つの方法があるようです。メインプロセスを保持したい場合、トレーニングプロセスで2つの方法を適用してGPUメモリを解放できます。

  1. サブプロセスを呼び出してモデルトレーニングを実行します。 1段階のトレーニングが完了すると、サブプロセスが終了し、メモリが解放されます。戻り値を取得するのは簡単です。
  2. multiprocessing.Process(p)を呼び出してモデルトレーニング(p.start)を実行すると、p.joinはプロセスの終了とメモリの解放を示します。

次に、multiprocess.Processを使用したヘルパー関数を示します。これは、サブプロセスを使用する代わりに、新しいプロセスを開いてpython written function and reture valueを実行できます。

# 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
0
liviaerxin