Sehr niedrige GPU-Auslastung während der Ausbildung in Tensorflow
Ich versuche zu trainieren, eine einfache multi-layer-perzeptron für ein 10-Klasse Bild-Klassifizierung Aufgabe, die einen Teil des Auftrages für die Udacity Deep-Learning-Kurs. Um genauer zu sein, ist die Aufgabe zu klassifizieren Buchstaben gerendert aus verschiedenen Schriftarten (dataset aufgerufen wird notMNIST).
Den code landete ich mit sieht ziemlich einfach, aber egal was ich auch immer sehr niedrige GPU-Auslastung während des Trainings. Ich Messen die Last mit GPU-Z und es zeigt nur 25-30%.
Hier ist mein Derzeitiger code:
graph = tf.Graph()
with graph.as_default():
tf.set_random_seed(52)
# dataset definition
dataset = Dataset.from_tensor_slices({'x': train_data, 'y': train_labels})
dataset = dataset.shuffle(buffer_size=20000)
dataset = dataset.batch(128)
iterator = dataset.make_initializable_iterator()
sample = iterator.get_next()
x = sample['x']
y = sample['y']
# actual computation graph
keep_prob = tf.placeholder(tf.float32)
is_training = tf.placeholder(tf.bool, name='is_training')
fc1 = dense_batch_relu_dropout(x, 1024, is_training, keep_prob, 'fc1')
fc2 = dense_batch_relu_dropout(fc1, 300, is_training, keep_prob, 'fc2')
fc3 = dense_batch_relu_dropout(fc2, 50, is_training, keep_prob, 'fc3')
logits = dense(fc3, NUM_CLASSES, 'logits')
with tf.name_scope('accuracy'):
accuracy = tf.reduce_mean(
tf.cast(tf.equal(tf.argmax(y, 1), tf.argmax(logits, 1)), tf.float32),
)
accuracy_percent = 100 * accuracy
with tf.name_scope('loss'):
loss = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(logits=logits, labels=y))
update_ops = tf.get_collection(tf.GraphKeys.UPDATE_OPS)
with tf.control_dependencies(update_ops):
# ensures that we execute the update_ops before performing the train_op
# needed for batch normalization (apparently)
train_op = tf.train.AdamOptimizer(learning_rate=1e-3, epsilon=1e-3).minimize(loss)
with tf.Session(graph=graph) as sess:
tf.global_variables_initializer().run()
step = 0
epoch = 0
while True:
sess.run(iterator.initializer, feed_dict={})
while True:
step += 1
try:
sess.run(train_op, feed_dict={keep_prob: 0.5, is_training: True})
except tf.errors.OutOfRangeError:
logger.info('End of epoch #%d', epoch)
break
# end of epoch
train_l, train_ac = sess.run(
[loss, accuracy_percent],
feed_dict={x: train_data, y: train_labels, keep_prob: 1, is_training: False},
)
test_l, test_ac = sess.run(
[loss, accuracy_percent],
feed_dict={x: test_data, y: test_labels, keep_prob: 1, is_training: False},
)
logger.info('Train loss: %f, train accuracy: %.2f%%', train_l, train_ac)
logger.info('Test loss: %f, test accuracy: %.2f%%', test_l, test_ac)
epoch += 1
Hier ist, was ich bisher ausprobiert:
-
Änderte ich die Eingabe-pipeline, die von einfachen
feed_dict
zutensorflow.contrib.data.Dataset
. Soweit ich verstanden habe, soll Sie kümmern sich um die Effizienz der Eingabe, z.B. das laden der Daten in einem separaten thread. So sollte es keinerlei Engpass, verbunden mit dem Eingang. -
Sammelte ich die Spuren, wie hier vorgeschlagen: https://github.com/tensorflow/tensorflow/issues/1824#issuecomment-225754659
Jedoch, diese Spuren nicht wirklich etwas Interessantes. >90% des Zuges Schritt ist matmul Operationen. -
Geändert batch-Größe. Wenn ich es ändern von 128 bis 512 die Belastung steigt von ~30% auf ~38%, wenn ich erhöhen, es weiter zu 2048, der load geht auf ~45%. Ich habe 6 GB GPU-Speicher und dataset ist single-channel-28x28 Bilder. Bin ich wirklich verwenden sollte, solch eine große batch-Größe? Soll ich erhöhen es weiter?
Allgemein, sollte ich mir sorgen über die niedrige Belastung ist es wirklich ein Zeichen, dass ich am training ineffizient?
Hier der GPU-Z-screenshots mit 128 Bildern im Stapel. Sie können finden Sie unter geringer Last mit gelegentlichen Spitzen bis 100%, wenn ich Messen Genauigkeit auf den gesamten Datenbestand nach jeder Epoche.
InformationsquelleAutor Alexey Petrenko | 2017-09-11
Du musst angemeldet sein, um einen Kommentar abzugeben.
MNIST Größe Netzwerke sind klein und es ist schwer, um eine hohe GPU (oder CPU -) Effizienz für Sie, ich denke, 30% ist nicht ungewöhnlich für Ihre Anwendung. Erhalten Sie höhere rechnerische Effizienz mit größeren batch-Größe, was bedeutet, Sie verarbeiten kann mehr Beispiele pro Sekunde, aber Sie erhalten auch geringere statistische Effizienz, das heißt, Sie brauchen mehr Beispiele, die Summe zu bekommen, um Ziel-Genauigkeit. Es ist also ein trade-off. Für kleine Charakter-Modelle wie das Ihre, die statistische Effizienz sinkt sehr schnell ab, nach 100, so ist es wohl nicht Wert, versucht zu wachsen, die batch-Größe für training. Für die Ableitung verwenden, sollten Sie die größten batch-Größe, die Sie können.
Ja, es gibt nicht genug berechnen, um zu sättigen die Kerne. Auch Dinge, die ineffizient sind, wenn die Höhe der Berechnung ist klein im Verhältnis zu den erforderlichen Speicher-Bandbreite, oder der Aufwand der kernel startet. Weitere wichtige Sache zu achten, ist die Effizienz eher als GPU-Auslastung. TitanX großen matmul bekommt 10 T ops/Sekunde, aber in vielen Anwendungen Netze unter 1 T op/Sekunde, also weniger als 10% der peak-Effizienz
Bulatov, Sofern es freie CUDA-Kerne, warum kann nicht TensorFlow double up das Netzwerk, führen Sie es zweimal parallel zu verwenden, mehr Kerne, und wählen zwischen den zwei für den besten Parametersatz in einer iteration?
InformationsquelleAutor Yaroslav Bulatov
Auf meine nVidia GTX 1080, wenn ich ein convolutional neural network auf der MNIST-Datenbank, die GPU-Last ~68%.
Wenn ich wechseln, um eine einfache, nicht-convolutional network, dann ist die GPU-Last von ~20%.
Repliziert werden können diese Ergebnisse durch die Gebäude sukzessive mehr fortgeschrittene Modelle in der tutorial Gebäude Autoencoders in Keras von Francis Chollet.
InformationsquelleAutor Contango