Multi GPU w kamerach

33

W jaki sposób można zaprogramować w bibliotece keras (lub tensorflow) szkolenie partycjonowania na wielu GPU? Powiedzmy, że jesteś w instancji Amazon ec2, która ma 8 procesorów graficznych i chciałbyś wykorzystać je wszystkie, aby trenować szybciej, ale twój kod dotyczy tylko jednego procesora lub karty graficznej.

Hector Blandin
źródło
3
sprawdziłeś dokument tensorflow?
n1tk
@ sb0709: Zacząłem czytać dziś rano, ale zastanawiałem się, jak to zrobić w keras
Hector Blandin,
1
nie wiem w keras, ale dla tensorflow: tf domyślnie użyje GPU do obliczeń, nawet jeśli dotyczy CPU (jeśli jest obsługiwany procesor graficzny). więc możesz po prostu zrobić pętlę for: „for d in ['/ gpu: 1', '/ gpu: 2', '/ gpu: 3' ... '/ gpu: 8',]:” oraz w „tf.device (d)” powinien obejmować wszystkie zasoby GPU instancji. Tak więc tf.device () będzie faktycznie używane.
n1tk
Lubię to ?? dla d w ['/ gpu: 1', '/ gpu: 2', '/ gpu: 3' ... '/ gpu: 8',]: tf.device (d) i to jest? Spróbuję tak :)
Hector Blandin
1
o ile wiem tak, możesz wykonać dowolne zadanie na innym urządzeniu.
n1tk

Odpowiedzi:

37

Z najczęściej zadawanych pytań dotyczących Keras:

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

Poniżej znajduje się wklejony kod, aby umożliwić „równoległość danych”. Oznacza to, że każdy z twoich układów GPU przetwarza niezależnie inny podzbiór twoich danych.

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)

Zauważ, że wydaje się, że jest to poprawne tylko dla backendu Tensorflow w momencie pisania.

Aktualizacja (luty 2018) :

Keras teraz akceptuje automatyczny wybór GPU za pomocą multi_gpu_model, więc nie musisz już kodować liczby gpus. Szczegóły w tym żądaniu Pull . Innymi słowy, włącza to kod, który wygląda następująco:

try:
    model = multi_gpu_model(model)
except:
    pass

Ale mówiąc bardziej precyzyjnie , możesz trzymać się czegoś takiego:

parallel_model = multi_gpu_model(model, gpus=None)

Bonus :

Aby sprawdzić, czy naprawdę używasz wszystkich swoich układów GPU, szczególnie NVIDIA, możesz monitorować swoje użycie w terminalu, używając:

watch -n0.5 nvidia-smi

Referencje:

weiji14
źródło
Czy multi_gpu_model(model, gpus=None)działa w przypadku, gdy jest tylko 1 GPU? Byłoby fajnie, gdyby automatycznie dostosowywał się do liczby dostępnych GPU.
CMCDragonkai
Tak, myślę, że działa z 1 kartą graficzną, patrz github.com/keras-team/keras/pull/9226#issuecomment-361692460 , ale może być konieczne zachowanie ostrożności w dostosowaniu kodu do działania na modelu multi_gpu_model zamiast prostego modelu . W większości przypadków prawdopodobnie nie miałoby to znaczenia, ale jeśli zamierzasz zrobić coś takiego, jak pobrać dane wyjściowe z warstwy pośredniej, musisz odpowiednio kodować.
weiji14
Czy masz jakieś odniesienia do różnic w modelach wielu GPU?
CMCDragonkai
Masz na myśli coś takiego jak github.com/rossumai/keras-multi-gpu/blob/master/blog/docs/… ?
weiji14,
To odniesienie było świetne @ weiji14. Jednak jestem również zainteresowany tym, jak to działa w celu wnioskowania. Czy aparaty w jakiś sposób dzielą partie jednakowo, czy też harmonogram rundy robin na dostępne repliki modeli?
CMCDragonkai,
4
  1. W przypadku TensorFlow:

TensorFlow za pomocą procesorów graficznych

Oto przykładowy kod, w jaki sposób jest używany, więc dla każdego zadania określona jest lista z urządzeniami / urządzeniami:

# 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 będzie domyślnie używał GPU do obliczeń, nawet jeśli dotyczy CPU (jeśli jest obecny obsługiwany GPU). więc możesz po prostu zrobić pętlę for: „for d in ['/ gpu: 1', '/ gpu: 2', '/ gpu: 3' ... '/ gpu: 8',]:” oraz w „tf.device (d)” powinien obejmować wszystkie zasoby GPU instancji. Tak więc tf.device () będzie faktycznie używane.

Skalowanie szkolenia modelu Keras do wielu procesorów graficznych

  1. Keras

W przypadku Keras za pomocą Mxnet niż args.num_gpus , gdzie num_gpus jest listą wymaganych GPU.

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

Poza tym ostatnio Horovod z otwartym źródłem Uber i myślę, że jest świetny:

Horowod

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
źródło
2

Zasadniczo możesz wziąć przykład z następującego przykładu. Wystarczy zaimportować keras, aby określić wartości zużycia procesora i GPU.

import keras

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

Następnie pasowałbyś do modelu.

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

Wreszcie, możesz zmniejszyć wartości zużycia, a nie pracę na górnych granicach.

johncasey
źródło