3つのモデルをトレーニングし、3つのチェックポイントを順番に読み込み、それらを使用して予測を実行するコードを実行しています。 GPUを使用しています。
最初のモデルが読み込まれると、GPUメモリ全体が事前に割り当てられます(データの最初のバッチを処理するために必要です)。ただし、終了してもメモリはアンロードされません。 tf.reset_default_graph()
とwith tf.Graph().as_default()
の両方を使用して2番目のモデルがロードされると、GPUメモリはまだ最初のモデルから完全に消費され、2番目のモデルはメモリ不足になります。
Pythonサブプロセスまたはマルチプロセッシングを使用して問題を回避する以外に、これを解決する方法はありますか(Google検索で見つけた唯一の解決策)?
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)を実行しただけでは、関数呼び出し後にメモリは解放されません。
私は 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))
テンソルが不要になったらすぐに(.run呼び出しが終了する前に)、テンソルによって割り当てられたGPUメモリが解放されます(TensorFlowメモリプールに戻ります)。変数に割り当てられたGPUメモリは、変数コンテナーが破棄されると解放されます。 DirectSession(つまり、sess = tf.Session( ""))の場合、セッションが閉じられるか、明示的にリセットされます( 62c159ff に追加されます)
反復トレーニングモデルを解決する方法と、将来のマルチプロセスプールを使用してモデルトレーニングを提供する場合、将来が終了してもプール内のプロセスが強制終了されない2つの方法があるようです。メインプロセスを保持したい場合、トレーニングプロセスで2つの方法を適用してGPUメモリを解放できます。
次に、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