Multi GPU in Keras

33

Wie können Sie in der Keras-Bibliothek (oder im Tensorflow) programmieren, um das Training auf mehrere GPUs aufzuteilen? Angenommen, Sie befinden sich in einer Amazon ec2-Instanz mit 8 GPUs und möchten alle verwenden, um schneller zu trainieren. Ihr Code ist jedoch nur für eine einzelne CPU oder GPU bestimmt.

Hector Blandin
quelle
3
Haben Sie das Tensorflow-Dokument überprüft?
n1tk
@ sb0709: Ich habe heute Morgen angefangen zu lesen, aber ich habe mich gefragt, wie ich es in Keras machen soll
Hector Blandin,
1
Ich weiß nicht in Keras, aber für Tensorflow: tf verwendet standardmäßig die GPU für die Berechnung, auch wenn es sich um eine CPU handelt (sofern eine unterstützte GPU vorhanden ist). Sie können also einfach eine for - Schleife ausführen: "für d in ['/ gpu: 1', '/ gpu: 2', '/ gpu: 3' ... '/ gpu: 8',]:" und in der "tf.device (d)" sollte alle GPU-Ressourcen Ihrer Instanz enthalten. Tf.device () wird also tatsächlich verwendet.
Freitag,
So was ?? für d in ['/ gpu: 1', '/ gpu: 2', '/ gpu: 3' ... '/ gpu: 8',]: tf.device (d) und das ist? Ich werde es so versuchen :)
Hector Blandin
1
soweit ich weiß kann man ja jede aufgabe auf verschiedenen geräten erledigen.
Freitag,

Antworten:

37

Aus den Keras-FAQs:

https://keras.io/getting-started/faq/#how-can-i-run-a-keras-model-on-multiple-gpus

Unten finden Sie kopierten Code, um die Datenparallelität zu aktivieren. Das heißt, dass jede Ihrer GPUs eine andere Teilmenge Ihrer Daten unabhängig verarbeitet.

from keras.utils import multi_gpu_model

# Replicates `model` on 8 GPUs.
# This assumes that your machine has 8 available GPUs.
parallel_model = multi_gpu_model(model, gpus=8)
parallel_model.compile(loss='categorical_crossentropy',
                       optimizer='rmsprop')

# This `fit` call will be distributed on 8 GPUs.
# Since the batch size is 256, each GPU will process 32 samples.
parallel_model.fit(x, y, epochs=20, batch_size=256)

Beachten Sie, dass dies zum Zeitpunkt des Schreibens nur für das Tensorflow-Backend gültig zu sein scheint.

Aktualisierung (Februar 2018) :

Keras akzeptiert jetzt die automatische GPU-Auswahl mit multi_gpu_model, sodass Sie die Anzahl der GPUS nicht mehr fest codieren müssen. Details in dieser Pull-Anfrage . Mit anderen Worten, dies aktiviert Code, der so aussieht:

try:
    model = multi_gpu_model(model)
except:
    pass

Aber um mehr explizit , können Sie mit etwas kleben wie:

parallel_model = multi_gpu_model(model, gpus=None)

Bonus :

Um zu überprüfen, ob Sie wirklich alle Ihre GPUs, insbesondere die von NVIDIA, verwenden, können Sie Ihre Nutzung im Terminal überwachen.

watch -n0.5 nvidia-smi

Verweise:

weiji14
quelle
Funktioniert das multi_gpu_model(model, gpus=None)bei nur 1 GPU? Es wäre cool, wenn es sich automatisch an die Anzahl der verfügbaren GPUs anpassen würde.
CMCDragonkai
Ja, ich denke, es funktioniert mit 1 GPU, siehe github.com/keras-team/keras/pull/9226#issuecomment-361692460 , aber Sie müssen möglicherweise darauf achten, dass Ihr Code für die Ausführung auf einem multi_gpu_model anstelle eines einfachen Modells angepasst ist . In den meisten Fällen spielt es wahrscheinlich keine Rolle, aber wenn Sie die Ausgabe einer Zwischenebene übernehmen möchten, müssen Sie entsprechend codieren.
Weiji14
Haben Sie Referenzen zu Multi-GPU-Modellunterschieden?
CMCDragonkai
Diese Referenz war großartig @ weiji14. Ich bin aber auch daran interessiert, wie das funktioniert. Teilt Keras die Chargen in Bezug auf die verfügbaren Modellrepliken gleich oder nach dem Round-Robin-Schema auf?
CMCDragonkai
4
  1. Für TensorFlow:

TensorFlow Verwenden von GPUs

Hier ist der Beispielcode für die Verwendung, sodass für jede Aufgabe die Liste mit Geräten / Geräten angegeben wird:

# Creates a graph.
c = []
for d in ['/gpu:2', '/gpu:3']:
  with tf.device(d):
    a = tf.constant([1.0, 2.0, 3.0, 4.0, 5.0, 6.0], shape=[2, 3])
    b = tf.constant([1.0, 2.0, 3.0, 4.0, 5.0, 6.0], shape=[3, 2])
    c.append(tf.matmul(a, b))
with tf.device('/cpu:0'):
  sum = tf.add_n(c)
# Creates a session with log_device_placement set to True.
sess = tf.Session(config=tf.ConfigProto(log_device_placement=True))
# Runs the op.
print(sess.run(sum))

tf verwendet standardmäßig GPU für die Berechnung, auch wenn es sich um eine CPU handelt (sofern eine unterstützte GPU vorhanden ist). Sie können also einfach eine for - Schleife ausführen: "für d in ['/ gpu: 1', '/ gpu: 2', '/ gpu: 3' ... '/ gpu: 8',]:" und in der "tf.device (d)" sollte alle GPU-Ressourcen Ihrer Instanz enthalten. Tf.device () wird also tatsächlich verwendet.

Skalieren des Keras-Modelltrainings auf mehrere GPUs

  1. Keras

Für Keras mit Mxnet als args.num_gpus , wobei num_gpus die Liste Ihrer erforderlichen GPUs ist.

def backend_agnostic_compile(model, loss, optimizer, metrics, args):
  if keras.backend._backend == 'mxnet':
      gpu_list = ["gpu(%d)" % i for i in range(args.num_gpus)]
      model.compile(loss=loss,
          optimizer=optimizer,
          metrics=metrics, 
          context = gpu_list)
  else:
      if args.num_gpus > 1:
          print("Warning: num_gpus > 1 but not using MxNet backend")
      model.compile(loss=loss,
          optimizer=optimizer,
          metrics=metrics)
  1. horovod.tensorflow

Vor allem Uber Open Source Horovod vor kurzem und ich denke, ist toll:

Horovod

import tensorflow as tf
import horovod.tensorflow as hvd

# Initialize Horovod
hvd.init()

# Pin GPU to be used to process local rank (one GPU per process)
config = tf.ConfigProto()
config.gpu_options.visible_device_list = str(hvd.local_rank())

# Build model…
loss = 
opt = tf.train.AdagradOptimizer(0.01)

# Add Horovod Distributed Optimizer
opt = hvd.DistributedOptimizer(opt)

# Add hook to broadcast variables from rank 0 to all other processes during
# initialization.
hooks = [hvd.BroadcastGlobalVariablesHook(0)]

# Make training operation
train_op = opt.minimize(loss)

# The MonitoredTrainingSession takes care of session initialization,
# restoring from a checkpoint, saving to a checkpoint, and closing when done
# or an error occurs.
with tf.train.MonitoredTrainingSession(checkpoint_dir=“/tmp/train_logs”,
                                      config=config,
                                      hooks=hooks) as mon_sess:
 while not mon_sess.should_stop():
   # Perform synchronous training.
   mon_sess.run(train_op)
n1tk
quelle
2

Grundsätzlich können Sie das folgende Beispiel nehmen. Alles, was Sie brauchen, ist die Angabe der CPU- und GPU-Verbrauchswerte nach dem Import von Keras.

import keras

config = tf.ConfigProto( device_count = {'GPU': 1 , 'CPU': 56} )
sess = tf.Session(config=config) 
keras.backend.set_session(sess)

Danach würden Sie das Modell passen.

model.fit(x_train, y_train, epochs=epochs, validation_data=(x_test, y_test))

Schließlich können Sie die Verbrauchswerte verringern, nicht die Arbeit an den Obergrenzen.

Johncasey
quelle