Verwenden Sie eine GPU

Auf TensorFlow.org ansehen In Google Colab ausführen Quelle auf GitHub anzeigen Notizbuch herunterladen

TensorFlow Code und tf.keras Modelle werden auf einer einzelnen GPU ohne Code - Änderungen erforderlich transparent ausgeführt werden .

Die einfachste Art und Weise auf mehrere GPUs auf einem oder mehreren Rechnern laufen, wird unter Verwendung von Vertriebsstrategien .

Dieses Handbuch richtet sich an Benutzer, die diese Ansätze ausprobiert haben und festgestellt haben, dass sie eine detaillierte Kontrolle darüber benötigen, wie TensorFlow die GPU verwendet. Um zu erfahren , wie Performance - Probleme debuggen für Einzel- und Multi-GPU - Szenarien finden Sie in der Optimieren TensorFlow GPU Leistung Führung.

Einrichten

Stellen Sie sicher, dass Sie die neueste TensorFlow-GPU-Version installiert haben.

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

Überblick

TensorFlow unterstützt die Ausführung von Berechnungen auf einer Vielzahl von Gerätetypen, einschließlich CPU und GPU. Sie werden beispielsweise mit Zeichenfolgenbezeichnern dargestellt:

  • "/device:CPU:0" : Die CPU Ihrer Maschine.
  • "/GPU:0" : Kurzschreibweise für die erste GPU Ihrer Maschine, die auf TensorFlow sichtbar ist.
  • "/job:localhost/replica:0/task:0/device:GPU:1" : Die vollständig qualifizierter Name des zweiten GPU Ihrer Maschine, die auf TensorFlow sichtbar ist.

Wenn ein TensorFlow-Vorgang sowohl CPU- als auch GPU-Implementierungen aufweist, wird das GPU-Gerät standardmäßig priorisiert, wenn der Vorgang zugewiesen wird. Zum Beispiel tf.matmul hat sowohl CPU- und GPU - Kerne und auf einem System mit Geräten CPU:0 und GPU:0 , die GPU:0 Gerät ausgewählt laufen tf.matmul wenn Sie nicht ausdrücklich auf einem anderen Gerät ausgeführt werden fordern.

Wenn ein TensorFlow-Vorgang keine entsprechende GPU-Implementierung hat, fällt der Vorgang auf das CPU-Gerät zurück. Da zum Beispiel tf.cast nur einen CPU - Kern hat, auf einem System mit Geräten CPU:0 und GPU:0 , die CPU:0 Gerät zu laufen ausgewählt tf.cast , auch angefordert , wenn auf dem laufen GPU:0 Gerät .

Platzierung von Logging-Geräten

Um herauszufinden , welche Geräte Ihre Operationen und Tensoren zugeordnet sind, Put tf.debugging.set_log_device_placement(True) als erste Anweisung Ihres Programms. Wenn Sie die Protokollierung der Geräteplatzierung aktivieren, werden alle Tensor-Zuordnungen oder -Operationen gedruckt.

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 _EagerConst in device /job:localhost/replica:0/task:0/device:GPU:0
Executing op _EagerConst in device /job:localhost/replica:0/task:0/device:GPU:0
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)

Der obige Code wird eine Anzeige der Druck MatMul op wurde auf ausgeführt GPU:0 .

Manuelle Geräteplatzierung

Wenn Sie eine bestimmte Operation mögen auf einem Gerät Ihrer Wahl laufen statt , was für Sie automatisch ausgewählt ist, können Sie with tf.device einen Gerätekontext zu erstellen, und alle Operationen in diesem Zusammenhang auf demselben bezeichneten Gerät ausgeführt werden sollen .

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)

Sie werden das jetzt sehen a und b zugeordnet sind CPU:0 . Da ein Gerät nicht explizit für den angegebene wurde MatMul Betrieb wird die TensorFlow Laufzeit eines auf dem Betrieb und die verfügbaren Geräten (basierend wählen GPU:0 in diesem Beispiel) und automatisch Tensoren zwischen den Geräten zu kopieren , falls erforderlich.

Begrenzung des GPU-Speicherwachstums

Standardmäßig ordnet TensorFlow fast alle von der GPU - Speicher aller GPUs (je nach CUDA_VISIBLE_DEVICES ) sichtbar an den Prozess. Dies geschieht, um die relativ kostbaren GPU-Speicherressourcen auf den Geräten effizienter zu nutzen, indem die Speicherfragmentierung reduziert wird. TensorFlow auf eine bestimmte Gruppe von GPUs, verwenden Sie das begrenzen tf.config.experimental.set_visible_devices Methode.

gpus = tf.config.list_physical_devices('GPU')
if gpus:
  # Restrict TensorFlow to only use the first GPU
  try:
    tf.config.set_visible_devices(gpus[0], 'GPU')
    logical_gpus = tf.config.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)
1 Physical GPUs, 1 Logical GPU

In einigen Fällen ist es für den Prozess wünschenswert, nur eine Teilmenge des verfügbaren Speichers zuzuweisen oder die Speichernutzung nur so zu erhöhen, wie es der Prozess benötigt. TensorFlow bietet zwei Methoden, um dies zu kontrollieren.

Die erste Option ist durch den Aufruf auf Speicherwachstum drehen tf.config.experimental.set_memory_growth , die versucht , nur so viel GPU - Speicher zuzuweisen , wie für die Laufzeitzuweisungen erforderlich: es beginnt sehr wenig Zuweisen von Speicher, und wie das Programm wird ausgeführt und Wird mehr GPU-Speicher benötigt, wird der GPU-Speicherbereich für den TensorFlow-Prozess erweitert. Speicher wird nicht freigegeben, da dies zu einer Speicherfragmentierung führen kann. Um das Speicherwachstum für eine bestimmte GPU zu aktivieren, verwenden Sie den folgenden Code, bevor Sie Tensoren zuweisen oder Operationen ausführen.

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.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)
Physical devices cannot be modified after being initialized

Eine andere Möglichkeit , diese Option zu aktivieren ist , um die Umgebungsvariable setzen TF_FORCE_GPU_ALLOW_GROWTH zu true . Diese Konfiguration ist plattformspezifisch.

Die zweite Methode ist eine virtuelle Gerät mit GPU konfigurieren tf.config.experimental.set_virtual_device_configuration und eine harte Begrenzung der Gesamtspeicher auf der GPU zuzuteilen eingestellt.

gpus = tf.config.list_physical_devices('GPU')
if gpus:
  # Restrict TensorFlow to only allocate 1GB of memory on the first GPU
  try:
    tf.config.set_logical_device_configuration(
        gpus[0],
        [tf.config.LogicalDeviceConfiguration(memory_limit=1024)])
    logical_gpus = tf.config.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)
Virtual devices cannot be modified after being initialized

Dies ist nützlich, wenn Sie die Menge des für den TensorFlow-Prozess verfügbaren GPU-Speichers wirklich begrenzen möchten. Dies ist gängige Praxis für die lokale Entwicklung, wenn die GPU mit anderen Anwendungen wie einer Workstation-GUI geteilt wird.

Verwenden einer einzelnen GPU in einem Multi-GPU-System

Wenn Sie mehr als eine GPU in Ihrem System haben, wird standardmäßig die GPU mit der niedrigsten ID ausgewählt. Wenn Sie auf einer anderen GPU laufen möchten, müssen Sie die Voreinstellung explizit angeben:

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)
Executing op _EagerConst in device /job:localhost/replica:0/task:0/device:GPU:0
Executing op _EagerConst in device /job:localhost/replica:0/task:0/device:GPU:0
Executing op MatMul in device /job:localhost/replica:0/task:0/device:GPU:0

Wenn das Gerät von Ihnen angegebenen nicht vorhanden ist , erhalten Sie eine RuntimeError : .../device:GPU:2 unknown device .

Wenn Sie TensorFlow mögen automatisch ein bestehendes und unterstütztes Gerät wählen , um die Operationen auszuführen , falls die spezifizierte nicht existiert, können Sie rufen 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 _EagerConst in device /job:localhost/replica:0/task:0/device:GPU:0
Executing op _EagerConst in device /job:localhost/replica:0/task:0/device:GPU:0
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)

Verwenden mehrerer GPUs

Durch die Entwicklung für mehrere GPUs kann ein Modell mit den zusätzlichen Ressourcen skaliert werden. Wenn Sie auf einem System mit einer einzelnen GPU entwickeln, können Sie mehrere GPUs mit virtuellen Geräten simulieren. Dies ermöglicht ein einfaches Testen von Multi-GPU-Setups, ohne zusätzliche Ressourcen zu benötigen.

gpus = tf.config.list_physical_devices('GPU')
if gpus:
  # Create 2 virtual GPUs with 1GB memory each
  try:
    tf.config.set_logical_device_configuration(
        gpus[0],
        [tf.config.LogicalDeviceConfiguration(memory_limit=1024),
         tf.config.LogicalDeviceConfiguration(memory_limit=1024)])
    logical_gpus = tf.config.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)
Virtual devices cannot be modified after being initialized

Einmal gibt es mehrere logische GPUs zur Verfügung, die Laufzeit sind, können Sie die mehrere GPUs mit nutzen tf.distribute.Strategy oder mit manueller Platzierung.

mit tf.distribute.Strategy

Die beste Vorgehensweise mehrere GPUs für die Verwendung verwenden tf.distribute.Strategy . Hier ist ein einfaches Beispiel:

tf.debugging.set_log_device_placement(True)
gpus = tf.config.list_logical_devices('GPU')
strategy = tf.distribute.MirroredStrategy(gpus)
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 _EagerConst 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 AssignVariableOp in device /job:localhost/replica:0/task:0/device:GPU:0
INFO:tensorflow:Using MirroredStrategy with devices ('/job:localhost/replica:0/task:0/device:GPU:0',)
Executing op _EagerConst in device /job:localhost/replica:0/task:0/device:GPU:0
Executing op _EagerConst in device /job:localhost/replica:0/task:0/device:GPU:0
Executing op _EagerConst in device /job:localhost/replica:0/task:0/device:GPU:0
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 AddV2 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 AssignVariableOp in device /job:localhost/replica:0/task:0/device:GPU:0
Executing op NoOp 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: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:0
Executing op _EagerConst in device /job:localhost/replica:0/task:0/device:GPU:0
Executing op _EagerConst in device /job:localhost/replica:0/task:0/device:GPU:0
Executing op Fill 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 AssignVariableOp in device /job:localhost/replica:0/task:0/device:GPU:0
Executing op NoOp 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: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:0
Executing op _EagerConst 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 AssignVariableOp in device /job:localhost/replica:0/task:0/device:GPU:0
Executing op NoOp 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 AssignVariableOp in device /job:localhost/replica:0/task:0/device:GPU:0
Executing op NoOp 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 AssignVariableOp in device /job:localhost/replica:0/task:0/device:GPU:0
Executing op NoOp in device /job:localhost/replica:0/task:0/device:GPU:0
Executing op _EagerConst in device /job:localhost/replica:0/task:0/device:GPU:0
Executing op Fill 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 AssignVariableOp in device /job:localhost/replica:0/task:0/device:GPU:0
Executing op NoOp in device /job:localhost/replica:0/task:0/device:GPU:0
INFO:tensorflow:Reduce to /job:localhost/replica:0/task:0/device:CPU:0 then broadcast to ('/job:localhost/replica:0/task:0/device:CPU: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:CPU:0
INFO:tensorflow:Reduce to /job:localhost/replica:0/task:0/device:CPU:0 then broadcast to ('/job:localhost/replica:0/task:0/device:CPU: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:CPU:0
Executing op _EagerConst in device /job:localhost/replica:0/task:0/device:GPU:0
Executing op Fill 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 AssignVariableOp in device /job:localhost/replica:0/task:0/device:GPU:0
Executing op NoOp in device /job:localhost/replica:0/task:0/device:GPU:0
INFO:tensorflow:Reduce to /job:localhost/replica:0/task:0/device:CPU:0 then broadcast to ('/job:localhost/replica:0/task:0/device:CPU: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:CPU:0
INFO:tensorflow:Reduce to /job:localhost/replica:0/task:0/device:CPU:0 then broadcast to ('/job:localhost/replica:0/task:0/device:CPU: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:CPU:0
Executing op _EagerConst 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 AssignVariableOp in device /job:localhost/replica:0/task:0/device:GPU:0
Executing op NoOp in device /job:localhost/replica:0/task:0/device:GPU:0

Dieses Programm wird eine Kopie des Modells auf jeden GPU, Splitting die Eingangsdaten zwischen ihnen, auch bekannt als „run Datenparallelität “.

Weitere Informationen über Vertriebsstrategien, überprüfen Sie die Führung heraus hier .

Manuelle Platzierung

tf.distribute.Strategy arbeitet unter der Haube durch Berechnung auf verschiedene Geräte zu replizieren. Sie können die Replikation manuell implementieren, indem Sie Ihr Modell auf jeder GPU erstellen. Beispielsweise:

tf.debugging.set_log_device_placement(True)

gpus = tf.config.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 _EagerConst in device /job:localhost/replica:0/task:0/device:GPU:0
Executing op _EagerConst in device /job:localhost/replica:0/task:0/device:GPU:0
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)