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 na 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.

Ustawiać

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

 import tensorflow as tf
print("Num GPUs Available: ", len(tf.config.experimental.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 wydrukuje wskazanie, że MatMul została wykonana na GPU:0 .

Ręczne umieszczanie urządzenia

Jeśli chcesz, aby określona operacja została uruchomiona na wybranym urządzeniu zamiast na tym, co jest automatycznie wybrane, 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]])

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.

Ograniczenie wzrostu pamięci GPU

Domyślnie TensorFlow mapuje prawie całą pamięć GPU wszystkich procesorów graficznych (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 GPU, używamy metody tf.config.experimental.set_visible_devices .

 gpus = tf.config.experimental.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 wzrostu pamięci przez wywołanie tf.config.experimental.set_memory_growth , które próbuje przydzielić tylko tyle pamięci GPU, ile jest potrzebne do alokacji środowiska wykonawczego: zaczyna przydzielać bardzo mało pamięci, a gdy program jest uruchamiany i potrzeba więcej pamięci GPU, rozszerzamy region 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 ilości pamięci dla określonego GPU, użyj następującego kodu przed przydzieleniem jakichkolwiek tensorów lub wykonaniem jakichkolwiek operacji.

 gpus = tf.config.experimental.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.experimental.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

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

 gpus = tf.config.experimental.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

Kiedy już mamy 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 o strategiach 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)