Multi GPU in keras


33

Come si può programmare nella libreria keras (o tensorflow) per partizionare l'allenamento su più GPU? Diciamo che ti trovi in ​​un'istanza di Amazon ec2 con 8 GPU e vorresti usarli tutti per allenarti più velocemente, ma il tuo codice è solo per una singola CPU o GPU.


3
hai controllato il documento Tensorflow?
ntk

@ sb0709: ho iniziato a leggere stamattina ma mi chiedevo come farlo in keras
Hector Blandin,

1
non lo so in keras ma per tensorflow: tf utilizzerà GPU per impostazione predefinita per il calcolo anche se è per CPU (se è presente GPU supportata). quindi puoi semplicemente fare un ciclo for: "for d in ['/ gpu: 1', '/ gpu: 2', '/ gpu: 3' ... '/ gpu: 8',]:" e nel "tf.device (d)" dovrebbe includere tutte le risorse della tua GPU di istanza. Quindi verrà effettivamente utilizzato tf.device ().
ntk

Come questo ?? per d in ['/ gpu: 1', '/ gpu: 2', '/ gpu: 3' ... '/ gpu: 8',]: tf.device (d) e cioè? Proverò così :)
Hector Blandin,

1
per quanto ne so sì, puoi fare qualsiasi operazione su un dispositivo diverso.
n.

Risposte:


37

Dalle domande frequenti su Keras:

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

Di seguito è riportato il codice incollato per abilitare il "parallelismo dei dati". Vale a dire che ciascuna delle GPU elabora un sottoinsieme diverso dei dati in modo indipendente.

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)

Si noti che questo sembra essere valido solo per il backend Tensorflow al momento della scrittura.

Aggiornamento (febbraio 2018) :

Keras ora accetta la selezione automatica di gpu usando multi_gpu_model, quindi non è più necessario codificare il numero di gpus. Dettagli in questa richiesta pull . In altre parole, questo abilita un codice simile al seguente:

try:
    model = multi_gpu_model(model)
except:
    pass

Ma per essere più espliciti , puoi rimanere con qualcosa del tipo:

parallel_model = multi_gpu_model(model, gpus=None)

Bonus :

Per verificare se stai davvero utilizzando tutte le tue GPU, in particolare quelle NVIDIA, puoi monitorare il tuo utilizzo nel terminale usando:

watch -n0.5 nvidia-smi

Riferimenti:


Funziona multi_gpu_model(model, gpus=None)nel caso in cui vi sia solo 1 GPU? Sarebbe bello se si adattasse automaticamente al numero di GPU disponibili.
CMCDragonkai,

Sì, penso che funzioni con 1 GPU, vedi github.com/keras-team/keras/pull/9226#issuecomment-361692460 , ma potresti aver bisogno di fare attenzione che il tuo codice sia adattato per funzionare su un multi_gpu_model invece di un modello semplice . Nella maggior parte dei casi, probabilmente non importerebbe, ma se hai intenzione di fare qualcosa come prendere l'output di un livello intermedio, dovrai codificare di conseguenza.
weiji14,

Hai qualche riferimento alle differenze del modello multi gpu?
CMCDragonkai,


Quel riferimento è stato fantastico @ weiji14. Tuttavia sono anche interessato a come funziona per deduzione. Le telecamere in qualche modo dividono i lotti equamente o pianificano round robin su repliche di modelli disponibili?
CMCDragonkai,

4
  1. Per TensorFlow:

TensorFlow utilizzando GPU

Ecco il codice di esempio su come viene utilizzato, quindi per ogni attività viene specificato l'elenco con dispositivi / dispositivo:

# 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 utilizzerà GPU per impostazione predefinita per il calcolo anche se è per CPU (se è presente GPU supportata). quindi puoi semplicemente fare un ciclo for: "for d in ['/ gpu: 1', '/ gpu: 2', '/ gpu: 3' ... '/ gpu: 8',]:" e nel "tf.device (d)" dovrebbe includere tutte le risorse della tua GPU di istanza. Quindi verrà effettivamente utilizzato tf.device ().

Scalare la formazione del modello Keras su più GPU

  1. Keras

Per Keras utilizzando Mxnet di args.num_gpus , dove num_gpus è l'elenco delle GPU richieste.

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

In cima a Uber di recente, Horovod è stato aperto di recente e penso che sia fantastico:

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)

2

Fondamentalmente, puoi prendere un esempio del seguente esempio. Tutto ciò che serve è specificare i valori di consumo di CPU e GPU dopo l'importazione di keras.

import keras

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

Successivamente, si adatterebbe il modello.

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

Infine, puoi ridurre i valori di consumo e non il lavoro sui limiti superiori.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.