Ich habe einen Datensatz, der auf der CPU auf der Fliege generiert wird. Samples werden in Python durch eine Funktion make_sample
berechnet, die ziemlich komplex ist und kann nicht in Tensorflow ops übersetzt werden. Da die Erstellung von Beispielen zeitraubend ist, möchte ich die Funktion aus mehreren Threads aufrufen, um eine Eingabewarteschlange zu füllen.Tensorflow langsamer bei Verwendung mehrerer Threads während der Vorverarbeitung auf der CPU
begann ich aus dem example given in the documentation und kam zu folgendem Spielzeug Beispiel:
import numpy as np
import tensorflow as tf
import time
def make_sample():
# something that takes time and needs to be on CPU w/o tf ops
p = 1
for n in range(1000000):
p = (p + np.random.random()) * np.random.random()
return np.float32(p)
read_threads = 1
with tf.device('/cpu:0'):
example_list = [tf.py_func(make_sample, [], [tf.float32]) for _ in range(read_threads)]
for ex in example_list:
ex[0].set_shape(())
batch_size = 3
capacity = 30
batch = tf.train.batch_join(example_list, batch_size=batch_size, capacity=capacity)
with tf.Session().as_default() as sess:
tf.global_variables_initializer().run()
coord = tf.train.Coordinator()
threads = tf.train.start_queue_runners(sess=sess, coord=coord)
try:
# dry run, left out of timing
sess.run(batch)
start_time = time.time()
for it in range(5):
print(sess.run(batch))
finally:
duration = time.time() - start_time
print('duration: {0:4.2f}s'.format(duration))
coord.request_stop()
coord.join(threads)
Was mich wundert ist, dass, wenn read_threads
zunimmt, nie die CPU-Auslastung von über 50% hinausgeht. Was noch schlimmer ist, die Rechenzeit sinkt: auf meinem Computer,
read_threads=1
→duration: 12s
read_threads=2
→duration: 46s
read_threads=4
→duration: 68s
read_threads=8
→duration: 112s
Gibt es eine Erklärung, und vor allem eine Lösung, um einen effizienten Multithr zu erhalten eaded Datengenerierung mit benutzerdefinierten Python-Funktion auf Tensorflow?