Multi GPU en keras

33

Comment pouvez-vous programmer dans la bibliothèque keras (ou tensorflow) pour partitionner la formation sur plusieurs GPU? Supposons que vous vous trouviez dans une instance Amazon ec2 comportant 8 GPU et que vous souhaitiez toutes les utiliser pour vous entraîner plus rapidement, mais que votre code ne concerne qu'un seul processeur ou GPU.

Hector Blandin
la source
3
Avez-vous vérifié le doc tensorflow?
n1tk
@ sb0709: J'ai commencé à lire ce matin mais je me demandais comment le faire à keras
Hector Blandin
1
je ne sais pas en keras mais pour tensorflow: tf utilisera GPU par défaut pour le calcul même si est pour CPU (si est présent pris en charge GPU). vous pouvez donc simplement créer une boucle for: "pour d dans ['/ gpu: 1', '/ gpu: 2', '/ gpu: 3' ... '/ gpu: 8',]:" et dans le "tf.device (d)" devrait inclure toutes vos ressources GPU d'instance. Donc tf.device () sera réellement utilisé.
n1tk
Comme ça ?? pour d dans ['/ gpu: 1', '/ gpu: 2', '/ gpu: 3' ... '/ gpu: 8',]: tf.device (d) et c’est? Je vais essayer comme ça :)
Hector Blandin
1
pour autant que je sache, vous pouvez effectuer n'importe quelle tâche sur différents appareils.
n1tk

Réponses:

37

De la FAQ de Keras:

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

Le code ci-dessous est copié-collé pour activer le «parallélisme des données». C'est-à-dire que chacun de vos GPU traite un sous-ensemble différent de vos données indépendamment.

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)

Notez que cela semble être valable uniquement pour le backend Tensorflow au moment de la rédaction.

Mise à jour (février 2018) :

Keras accepte maintenant la sélection automatique de gpu en utilisant multi_gpu_model, vous n'avez donc plus à coder en dur le nombre de gpus. Détails dans cette demande d'extraction . En d'autres termes, cela active un code qui ressemble à ceci:

try:
    model = multi_gpu_model(model)
except:
    pass

Mais pour être plus explicite , vous pouvez vous en tenir à quelque chose comme:

parallel_model = multi_gpu_model(model, gpus=None)

Prime :

Pour vérifier si vous utilisez réellement tous vos GPU, en particulier ceux de NVIDIA, vous pouvez surveiller votre utilisation dans le terminal en utilisant:

watch -n0.5 nvidia-smi

Les références:

weiji14
la source
Est-ce que le multi_gpu_model(model, gpus=None)travail fonctionne dans le cas où il y a seulement 1 GPU? Ce serait cool s'il s'adapte automatiquement au nombre de GPU disponibles.
CMCDragonkai
Oui, je pense que cela fonctionne avec 1 GPU, voir github.com/keras-team/keras/pull/9226#issuecomment-361692460 , mais vous devrez peut-être faire attention à ce que votre code soit adapté pour être utilisé sur un multi_gpu_model au lieu d'un modèle simple. . Dans la plupart des cas, cela n'aurait probablement pas d'importance, mais si vous voulez faire quelque chose comme prendre la sortie d'une couche intermédiaire, vous devrez coder en conséquence.
weiji14
Avez-vous des références aux différences de modèles multi-gpu?
CMCDragonkai
Vous voulez dire quelque chose comme github.com/rossumai/keras-multi-gpu/blob/master/blog/docs/… ?
weiji14
Cette référence était géniale @ weiji14. Cependant, je suis aussi intéressé par la façon dont cela fonctionne pour l'inférence. Est-ce que keras divise en quelque sorte les lots en parts égales ou en programme circulaire sur les répliques de modèles disponibles?
CMCDragonkai
4
  1. Pour TensorFlow:

TensorFlow Utilisation de GPU

Voici un exemple de code d'utilisation, ainsi pour chaque tâche est spécifiée la liste avec devices / device:

# 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 utilisera le GPU par défaut pour le calcul, même s’il s’agit d’un CPU (si le GPU supporté est présent). vous pouvez donc simplement créer une boucle for: "pour d dans ['/ gpu: 1', '/ gpu: 2', '/ gpu: 3' ... '/ gpu: 8',]:" et dans le "tf.device (d)" devrait inclure toutes vos ressources GPU d'instance. Donc tf.device () sera réellement utilisé.

Mise à l'échelle de Keras Model Training sur plusieurs GPU

  1. Keras

Pour Keras en utilisant Mxnet plutôt que args.num_gpus , où num_gpus est la liste de vos GPU requis.

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

En plus de tous les Horovod Uber à code source ouvert récemment et je trouve ça génial:

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
la source
2

Fondamentalement, vous pouvez prendre exemple de l'exemple suivant. Tout ce dont vous avez besoin est de spécifier les valeurs de consommation cpu et gpu après l'importation de keras.

import keras

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

Après cela, vous adapteriez le modèle.

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

Enfin, vous pouvez réduire les valeurs de consommation et non le travail sur les limites supérieures.

johncasey
la source