Zapisz datę! Google I / O powraca w dniach 18-20 maja Zarejestruj się teraz
Ta strona została przetłumaczona przez Cloud Translation API.
Switch to English

Użyj GPU

Zobacz na TensorFlow.org Uruchom w Google Colab Wyświetl źródło w serwisie GitHub Pobierz notatnik

Kod TensorFlow i modele tf.keras będą działać w sposób niewidoczny na jednym GPU bez konieczności wprowadzania zmian w kodzie.

Najprostszym sposobem uruchamiania na wielu procesorach graficznych, na jednym lub wielu komputerach, jest użycie strategii dystrybucji .

Ten przewodnik jest przeznaczony dla użytkowników, którzy wypróbowali te metody i stwierdzili, że potrzebują szczegółowej kontroli nad sposobem korzystania z GPU przez TensorFlow. Aby dowiedzieć się, jak debugować problemy z wydajnością w scenariuszach z jednym i wieloma GPU, zobacz przewodnik Optymalizacja wydajności GPU TensorFlow .

Ustawiać

Upewnij się, że masz zainstalowaną najnowszą wersję procesora graficznego TensorFlow.

import tensorflow as tf
print("Num GPUs Available: ", len(tf.config.list_physical_devices('GPU')))
Num GPUs Available:  2

Przegląd

TensorFlow obsługuje wykonywanie obliczeń na różnych typach urządzeń, w tym na CPU i GPU. Są reprezentowane przez identyfikatory ciągów, na przykład:

  • "/device:CPU:0" : Procesor twojego komputera.
  • "/GPU:0" : notacja krótka wskazująca na pierwszy procesor graficzny w komputerze, który jest widoczny dla TensorFlow.
  • "/job:localhost/replica:0/task:0/device:GPU:1" : W pełni kwalifikowana nazwa drugiego procesora graficznego Twojej maszyny, która jest widoczna dla TensorFlow.

Jeśli operacja TensorFlow ma implementację zarówno procesora, jak i GPU, domyślnie urządzenia GPU będą miały priorytet, gdy operacja zostanie przypisana do urządzenia. Na przykład tf.matmul zawiera jądra procesora i GPU. W systemie z urządzeniami CPU:0 i GPU:0 , urządzenie GPU:0 zostanie wybrane do uruchomienia tf.matmul chyba że wyraźnie zażądasz uruchomienia go na innym urządzeniu.

Rejestrowanie rozmieszczenia urządzeń

Aby dowiedzieć się, do jakich urządzeń są przypisane twoje operacje i tensory, umieść tf.debugging.set_log_device_placement(True) jako pierwszą instrukcję programu. Włączenie rejestrowania rozmieszczenia urządzeń powoduje wydrukowanie wszelkich alokacji lub operacji Tensora.

tf.debugging.set_log_device_placement(True)

# Create some tensors
a = tf.constant([[1.0, 2.0, 3.0], [4.0, 5.0, 6.0]])
b = tf.constant([[1.0, 2.0], [3.0, 4.0], [5.0, 6.0]])
c = tf.matmul(a, b)

print(c)
Executing op MatMul in device /job:localhost/replica:0/task:0/device:GPU:0
tf.Tensor(
[[22. 28.]
 [49. 64.]], shape=(2, 2), dtype=float32)

Powyższy kod wypisze wskazanie, że MatMul została wykonana na GPU:0 .

Ręczne umieszczanie urządzenia

Jeśli chcesz, aby dana operacja była wykonywana na wybranym urządzeniu, a nie na tym, co jest wybierane automatycznie, możesz użyć with tf.device do utworzenia kontekstu urządzenia, a wszystkie operacje w tym kontekście będą wykonywane na tym samym wyznaczonym urządzeniu .

tf.debugging.set_log_device_placement(True)

# Place tensors on the CPU
with tf.device('/CPU:0'):
  a = tf.constant([[1.0, 2.0, 3.0], [4.0, 5.0, 6.0]])
  b = tf.constant([[1.0, 2.0], [3.0, 4.0], [5.0, 6.0]])

# Run on the GPU
c = tf.matmul(a, b)
print(c)
Executing op MatMul in device /job:localhost/replica:0/task:0/device:GPU:0
tf.Tensor(
[[22. 28.]
 [49. 64.]], shape=(2, 2), dtype=float32)

Zobaczysz, że teraz a i b są przypisane do CPU:0 . Ponieważ urządzenie nie zostało wyraźnie określone dla MatMul pracy, środowisko wykonawcze TensorFlow wybiorą jedną opartą na pracy i dostępnych urządzeń ( GPU:0 w tym przykładzie) i automatycznie kopiować tensory pomiędzy urządzeniami w razie potrzeby.

Ograniczanie wzrostu pamięci GPU

Domyślnie TensorFlow mapuje prawie całą pamięć GPU wszystkich GPU (z zastrzeżeniem CUDA_VISIBLE_DEVICES ) widocznych dla procesu. Ma to na celu bardziej efektywne wykorzystanie stosunkowo cennych zasobów pamięci GPU na urządzeniach poprzez zmniejszenie fragmentacji pamięci. Aby ograniczyć TensorFlow do określonego zestawu procesorów graficznych, używamy metody tf.config.experimental.set_visible_devices .

gpus = tf.config.list_physical_devices('GPU')
if gpus:
  # Restrict TensorFlow to only use the first GPU
  try:
    tf.config.experimental.set_visible_devices(gpus[0], 'GPU')
    logical_gpus = tf.config.experimental.list_logical_devices('GPU')
    print(len(gpus), "Physical GPUs,", len(logical_gpus), "Logical GPU")
  except RuntimeError as e:
    # Visible devices must be set before GPUs have been initialized
    print(e)
2 Physical GPUs, 1 Logical GPU

W niektórych przypadkach pożądane jest, aby proces przydzielił tylko podzbiór dostępnej pamięci lub tylko zwiększył użycie pamięci w zależności od potrzeb. TensorFlow udostępnia dwie metody kontrolowania tego.

Pierwszą opcją jest włączenie przyrostu pamięci przez wywołanie tf.config.experimental.set_memory_growth , które próbuje przydzielić tylko tyle pamięci GPU, ile potrzeba do alokacji środowiska wykonawczego: zaczyna przydzielać bardzo mało pamięci, a gdy program jest uruchamiany i potrzeba więcej pamięci GPU, rozszerzamy obszar pamięci GPU przydzielony procesowi TensorFlow. Pamiętaj, że nie zwalniamy pamięci, ponieważ może to prowadzić do fragmentacji pamięci. Aby włączyć zwiększanie pamięci dla określonego GPU, użyj następującego kodu przed przydzieleniem jakichkolwiek tensorów lub wykonaniem jakichkolwiek operacji.

gpus = tf.config.list_physical_devices('GPU')
if gpus:
  try:
    # Currently, memory growth needs to be the same across GPUs
    for gpu in gpus:
      tf.config.experimental.set_memory_growth(gpu, True)
    logical_gpus = tf.config.experimental.list_logical_devices('GPU')
    print(len(gpus), "Physical GPUs,", len(logical_gpus), "Logical GPUs")
  except RuntimeError as e:
    # Memory growth must be set before GPUs have been initialized
    print(e)
2 Physical GPUs, 2 Logical GPUs

Innym sposobem włączenia tej opcji jest ustawienie zmiennej środowiskowej TF_FORCE_GPU_ALLOW_GROWTH na wartość true . Ta konfiguracja jest specyficzna dla platformy.

Druga metoda polega na skonfigurowaniu wirtualnego urządzenia GPU za pomocą tf.config.experimental.set_virtual_device_configuration i ustawieniu tf.config.experimental.set_virtual_device_configuration limitu całkowitej pamięci do przydzielenia na GPU.

gpus = tf.config.list_physical_devices('GPU')
if gpus:
  # Restrict TensorFlow to only allocate 1GB of memory on the first GPU
  try:
    tf.config.experimental.set_virtual_device_configuration(
        gpus[0],
        [tf.config.experimental.VirtualDeviceConfiguration(memory_limit=1024)])
    logical_gpus = tf.config.experimental.list_logical_devices('GPU')
    print(len(gpus), "Physical GPUs,", len(logical_gpus), "Logical GPUs")
  except RuntimeError as e:
    # Virtual devices must be set before GPUs have been initialized
    print(e)
2 Physical GPUs, 2 Logical GPUs

Jest to przydatne, jeśli chcesz naprawdę ograniczyć ilość pamięci GPU dostępnej dla procesu TensorFlow. Jest to powszechna praktyka w programowaniu lokalnym, gdy procesor GPU jest współdzielony z innymi aplikacjami, takimi jak graficzny interfejs użytkownika stacji roboczej.

Korzystanie z jednego GPU w systemie z wieloma GPU

Jeśli masz więcej niż jeden GPU w swoim systemie, domyślnie zostanie wybrany GPU o najniższym identyfikatorze. Jeśli chcesz działać na innym GPU, musisz wyraźnie określić preferencję:

tf.debugging.set_log_device_placement(True)

try:
  # Specify an invalid GPU device
  with tf.device('/device:GPU:2'):
    a = tf.constant([[1.0, 2.0, 3.0], [4.0, 5.0, 6.0]])
    b = tf.constant([[1.0, 2.0], [3.0, 4.0], [5.0, 6.0]])
    c = tf.matmul(a, b)
except RuntimeError as e:
  print(e)
/job:localhost/replica:0/task:0/device:GPU:2 unknown device.

Jeśli określone urządzenie nie istnieje, zostanie wyświetlony RuntimeError : .../device:GPU:2 unknown device .

Jeśli chcesz, aby TensorFlow automatycznie wybierał istniejące i obsługiwane urządzenie do wykonywania operacji w przypadku, gdy określone urządzenie nie istnieje, możesz wywołać tf.config.set_soft_device_placement(True) .

tf.config.set_soft_device_placement(True)
tf.debugging.set_log_device_placement(True)

# Creates some tensors
a = tf.constant([[1.0, 2.0, 3.0], [4.0, 5.0, 6.0]])
b = tf.constant([[1.0, 2.0], [3.0, 4.0], [5.0, 6.0]])
c = tf.matmul(a, b)

print(c)
Executing op MatMul in device /job:localhost/replica:0/task:0/device:GPU:0
tf.Tensor(
[[22. 28.]
 [49. 64.]], shape=(2, 2), dtype=float32)

Korzystanie z wielu procesorów graficznych

Opracowanie dla wielu procesorów graficznych umożliwi skalowanie modelu przy użyciu dodatkowych zasobów. W przypadku programowania w systemie z pojedynczym procesorem graficznym możemy symulować wiele procesorów graficznych za pomocą urządzeń wirtualnych. Umożliwia to łatwe testowanie konfiguracji z wieloma GPU bez konieczności posiadania dodatkowych zasobów.

gpus = tf.config.list_physical_devices('GPU')
if gpus:
  # Create 2 virtual GPUs with 1GB memory each
  try:
    tf.config.experimental.set_virtual_device_configuration(
        gpus[0],
        [tf.config.experimental.VirtualDeviceConfiguration(memory_limit=1024),
         tf.config.experimental.VirtualDeviceConfiguration(memory_limit=1024)])
    logical_gpus = tf.config.experimental.list_logical_devices('GPU')
    print(len(gpus), "Physical GPU,", len(logical_gpus), "Logical GPUs")
  except RuntimeError as e:
    # Virtual devices must be set before GPUs have been initialized
    print(e)
2 Physical GPU, 3 Logical GPUs

Gdy mamy już wiele logicznych procesorów graficznych dostępnych dla środowiska wykonawczego, możemy wykorzystać wiele procesorów graficznych z tf.distribute.Strategy lub z ręcznym umieszczaniem.

Dzięki tf.distribute.Strategy

Najlepszą praktyką w przypadku korzystania z wielu procesorów graficznych jest użycie tf.distribute.Strategy . Oto prosty przykład:

tf.debugging.set_log_device_placement(True)

strategy = tf.distribute.MirroredStrategy()
with strategy.scope():
  inputs = tf.keras.layers.Input(shape=(1,))
  predictions = tf.keras.layers.Dense(1)(inputs)
  model = tf.keras.models.Model(inputs=inputs, outputs=predictions)
  model.compile(loss='mse',
                optimizer=tf.keras.optimizers.SGD(learning_rate=0.2))
Executing op RandomUniform in device /job:localhost/replica:0/task:0/device:GPU:0
Executing op Sub in device /job:localhost/replica:0/task:0/device:GPU:0
Executing op Mul in device /job:localhost/replica:0/task:0/device:GPU:0
Executing op Add in device /job:localhost/replica:0/task:0/device:GPU:0
Executing op VarHandleOp in device /job:localhost/replica:0/task:0/device:GPU:0
Executing op VarIsInitializedOp in device /job:localhost/replica:0/task:0/device:GPU:0
Executing op LogicalNot in device /job:localhost/replica:0/task:0/device:GPU:0
Executing op Assert in device /job:localhost/replica:0/task:0/device:GPU:0
Executing op AssignVariableOp in device /job:localhost/replica:0/task:0/device:GPU:0
Executing op ReadVariableOp in device /job:localhost/replica:0/task:0/device:GPU:0
Executing op Identity in device /job:localhost/replica:0/task:0/device:GPU:1
Executing op VarHandleOp in device /job:localhost/replica:0/task:0/device:GPU:1
Executing op VarIsInitializedOp in device /job:localhost/replica:0/task:0/device:GPU:1
Executing op LogicalNot in device /job:localhost/replica:0/task:0/device:GPU:1
Executing op Assert in device /job:localhost/replica:0/task:0/device:GPU:1
Executing op AssignVariableOp in device /job:localhost/replica:0/task:0/device:GPU:1
Executing op Reshape in device /job:localhost/replica:0/task:0/device:GPU:0
Executing op VarHandleOp in device /job:localhost/replica:0/task:0/device:GPU:0
Executing op VarHandleOp in device /job:localhost/replica:0/task:0/device:GPU:1

Ten program uruchomi kopię Twojego modelu na każdym GPU, dzieląc między nimi dane wejściowe, co jest również określane jako „ równoległość danych ”.

Aby uzyskać więcej informacji na temat strategii dystrybucji, zapoznaj się z przewodnikiem tutaj .

Ręczne umieszczanie

tf.distribute.Strategy działa pod maską, replikując obliczenia na różnych urządzeniach. Możesz ręcznie wdrożyć replikację, konstruując model na każdym GPU. Na przykład:

tf.debugging.set_log_device_placement(True)

gpus = tf.config.experimental.list_logical_devices('GPU')
if gpus:
  # Replicate your computation on multiple GPUs
  c = []
  for gpu in gpus:
    with tf.device(gpu.name):
      a = tf.constant([[1.0, 2.0, 3.0], [4.0, 5.0, 6.0]])
      b = tf.constant([[1.0, 2.0], [3.0, 4.0], [5.0, 6.0]])
      c.append(tf.matmul(a, b))

  with tf.device('/CPU:0'):
    matmul_sum = tf.add_n(c)

  print(matmul_sum)
Executing op MatMul in device /job:localhost/replica:0/task:0/device:GPU:0
Executing op MatMul in device /job:localhost/replica:0/task:0/device:GPU:1
Executing op AddN in device /job:localhost/replica:0/task:0/device:CPU:0
tf.Tensor(
[[ 44.  56.]
 [ 98. 128.]], shape=(2, 2), dtype=float32)