Wie kann verhindert werden, dass Tensorflow die Gesamtheit eines GPU-Speichers zuweist?

282

Ich arbeite in einer Umgebung, in der Rechenressourcen gemeinsam genutzt werden, dh wir haben einige Server-Computer, die jeweils mit einigen Nvidia Titan X-GPUs ausgestattet sind.

Bei kleinen bis mittelgroßen Modellen reichen die 12 GB des Titan X normalerweise aus, damit 2 bis 3 Personen gleichzeitig auf derselben GPU trainieren können. Wenn die Modelle klein genug sind, dass ein einzelnes Modell nicht alle Recheneinheiten der GPU voll ausnutzt, kann dies tatsächlich zu einer Beschleunigung führen, verglichen mit dem Ausführen eines Trainingsprozesses nach dem anderen. Selbst in Fällen, in denen der gleichzeitige Zugriff auf die GPU die individuelle Trainingszeit verlangsamt, ist es immer noch schön, die Flexibilität zu haben, mehrere Benutzer gleichzeitig auf der GPU trainieren zu lassen.

Das Problem mit TensorFlow besteht darin, dass beim Start standardmäßig die gesamte Menge des verfügbaren GPU-Speichers zugewiesen wird. Selbst für ein kleines zweischichtiges neuronales Netzwerk sehe ich, dass alle 12 GB des GPU-Speichers verbraucht sind.

Gibt es eine Möglichkeit, TensorFlow dazu zu bringen, beispielsweise nur 4 GB GPU-Speicher zuzuweisen, wenn man weiß, dass dies für ein bestimmtes Modell ausreicht?

Fabien C.
quelle

Antworten:

292

Sie können den Anteil des GPU-Speichers festlegen, der beim Erstellen von a zugewiesen werden soll, indem Sie tf.Sessiona tf.GPUOptionsals Teil des optionalen configArguments übergeben:

# Assume that you have 12GB of GPU memory and want to allocate ~4GB:
gpu_options = tf.GPUOptions(per_process_gpu_memory_fraction=0.333)

sess = tf.Session(config=tf.ConfigProto(gpu_options=gpu_options))

Dies per_process_gpu_memory_fractionfungiert als harte Obergrenze für die Menge an GPU-Speicher, die vom Prozess auf jeder GPU auf demselben Computer verwendet wird. Derzeit wird dieser Anteil einheitlich auf alle GPUs auf derselben Maschine angewendet. Es gibt keine Möglichkeit, dies pro GPU festzulegen.

mrry
quelle
3
Vielen Dank. Diese Informationen sind im aktuellen Dokument ziemlich versteckt. Ich hätte es selbst nie gefunden :-) Wenn Sie antworten können, möchte ich Sie um zwei zusätzliche Informationen bitten: 1- Begrenzt dies die Menge des jemals verwendeten Speichers oder nur den ursprünglich zugewiesenen Speicher? (dh wird immer noch mehr Speicher zugewiesen, wenn dies im Berechnungsdiagramm erforderlich ist?) 2- Gibt es eine Möglichkeit, dies auf GPU-Basis festzulegen?
Fabien C.
15
Zugehöriger Hinweis: Das Festlegen von CUDA_VISIBLE_DEVICES, um TensorFlow auf eine einzelne GPU zu beschränken, funktioniert für mich. Siehe acceleware.com/blog/cudavisibledevices-masking-gpus
rd11
2
Es scheint, dass die Speicherzuweisung ein wenig über die Anforderung hinausgeht, z. B. habe ich per_process_gpu_memory_fraction = 0.0909 auf einer 24443MiB-GPU angefordert und Prozesse erhalten, die 2627MiB
jeremy_rutman
2
Ich kann nicht scheinen, dass dies in einemMonitoredTrainingSession
Anjum Sayed
2
@jeremy_rutman Ich glaube, das liegt an der Kontextinitialisierung von cudnn und cublas. Dies ist nur relevant, wenn Sie Kernel ausführen, die diese Bibliotheken verwenden.
Daniel
186
config = tf.ConfigProto()
config.gpu_options.allow_growth=True
sess = tf.Session(config=config)

https://github.com/tensorflow/tensorflow/issues/1578

Sergey Demyanov
quelle
13
Dies ist genau das, was ich möchte, da es in einer Mehrbenutzerumgebung sehr unpraktisch ist, die genaue Menge an GPU-Speicher anzugeben, die im Code selbst reserviert werden soll.
Xuancong84
4
Auch, wenn Sie verwenden Keras mit einem TF - Backend, können Sie diese verwenden , und führen Sie from keras import backend as Kund K.set_session(sess)zu vermeiden Speicherbeschränkungen
Oliver
50

Hier ist ein Auszug aus dem Buch Deep Learning with TensorFlow

In einigen Fällen ist es wünschenswert, dass der Prozess nur eine Teilmenge des verfügbaren Speichers zuweist oder die Speichernutzung nur so erhöht, wie es vom Prozess benötigt wird. TensorFlow bietet zwei Konfigurationsoptionen für die Sitzung, um dies zu steuern. Die erste allow_growthOption ist die Option, bei der versucht wird, basierend auf der Laufzeitzuweisung nur so viel GPU-Speicher zuzuweisen. Zunächst wird nur sehr wenig Speicher zugewiesen. Wenn Sitzungen ausgeführt werden und mehr GPU-Speicher benötigt wird, erweitern wir den vom TensorFlow benötigten GPU-Speicherbereich Prozess.

1) Wachstum zulassen: (flexibler)

config = tf.ConfigProto()
config.gpu_options.allow_growth = True
session = tf.Session(config=config, ...)

Die zweite Methode ist die per_process_gpu_memory_fractionOption, mit der der Anteil der eachsichtbaren GPU an der Gesamtspeichermenge bestimmt wird. Hinweis: Es ist keine Speicherfreigabe erforderlich. Wenn dies abgeschlossen ist, kann sich die Speicherfragmentierung sogar verschlechtern.

2) Festen Speicher zuweisen :

So weisen Sie nur 40%den Gesamtspeicher jeder GPU zu:

config = tf.ConfigProto()
config.gpu_options.per_process_gpu_memory_fraction = 0.4
session = tf.Session(config=config, ...)

Hinweis: Dies ist jedoch nur dann nützlich, wenn Sie die Menge des im TensorFlow-Prozess verfügbaren GPU-Speichers wirklich binden möchten.

user1767754
quelle
Für Ihre Frage kann Option 2 hilfreich sein. Wenn in GPU und dynamischen Netzwerken nicht mehrere Anwendungen ausgeführt werden, ist es im Allgemeinen sinnvoll, die Option "Wachstum zulassen" zu verwenden.
Aniket
19

Alle obigen Antworten setzen die Ausführung mit einem sess.run()Aufruf voraus , was in neueren Versionen von TensorFlow eher zur Ausnahme als zur Regel wird.

Wenn Sie das tf.EstimatorFramework (TensorFlow 1.4 und höher) verwenden, können Sie den Bruch an den implizit erstellten übergeben MonitoredTrainingSession:

opts = tf.GPUOptions(per_process_gpu_memory_fraction=0.333)
conf = tf.ConfigProto(gpu_options=opts)
trainingConfig = tf.estimator.RunConfig(session_config=conf, ...)
tf.estimator.Estimator(model_fn=..., 
                       config=trainingConfig)

Ähnlich im Eager-Modus (TensorFlow 1.5 und höher),

opts = tf.GPUOptions(per_process_gpu_memory_fraction=0.333)
conf = tf.ConfigProto(gpu_options=opts)
tfe.enable_eager_execution(config=conf)

Bearbeiten: 11-04-2018 Wenn Sie beispielsweise ein Beispiel verwenden möchtentf.contrib.gan.train , können Sie etwas Ähnliches wie unten verwenden:

tf.contrib.gan.gan_train(........, config=conf)
Urs
quelle
16

Verwenden Sie für Tensorflow Version 2.0 und 2.1 das folgende Snippet :

 import tensorflow as tf
 gpu_devices = tf.config.experimental.list_physical_devices('GPU')
 tf.config.experimental.set_memory_growth(gpu_devices[0], True)

In früheren Versionen funktionierte das folgende Snippet für mich:

import tensorflow as tf
tf_config=tf.ConfigProto()
tf_config.gpu_options.allow_growth=True
sess = tf.Session(config=tf_config)
Anurag
quelle
10

Tensorflow 2.0 Beta und (wahrscheinlich) darüber hinaus

Die API wurde erneut geändert. Es kann jetzt gefunden werden in:

tf.config.experimental.set_memory_growth(
    device,
    enable
)

Aliase:

  • tf.compat.v1.config.experimental.set_memory_growth
  • tf.compat.v2.config.experimental.set_memory_growth

Verweise:

Siehe auch: Tensorflow - Verwenden Sie eine GPU : https://www.tensorflow.org/guide/gpu

Für Tensorflow 2.0 Alpha siehe: diese Antwort

mx_muc
quelle
8

Sie können verwenden

TF_FORCE_GPU_ALLOW_GROWTH=true

in Ihren Umgebungsvariablen.

Im Tensorflow- Code:

bool GPUBFCAllocator::GetAllowGrowthValue(const GPUOptions& gpu_options) {
  const char* force_allow_growth_string =
      std::getenv("TF_FORCE_GPU_ALLOW_GROWTH");
  if (force_allow_growth_string == nullptr) {
    return gpu_options.allow_growth();
}
Mey Khalili
quelle
5

Schamloser Stecker: Wenn Sie den von der GPU unterstützten Tensorflow installieren, weist die Sitzung zunächst alle GPUs zu, unabhängig davon, ob Sie nur CPU oder GPU verwenden. Ich kann meinen Tipp hinzufügen, dass selbst wenn Sie das Diagramm so einstellen, dass nur die CPU verwendet wird, Sie dieselbe Konfiguration festlegen sollten (wie oben beantwortet :)), um die unerwünschte GPU-Belegung zu verhindern.

Und in einer interaktiven Oberfläche wie IPython sollten Sie auch diese Konfiguration festlegen, da sonst der gesamte Speicher zugewiesen wird und fast keiner für andere übrig bleibt. Dies ist manchmal schwer zu bemerken.

Lerner Zhang
quelle
3

Für Tensorflow 2.0 dies diese Lösung für mich gearbeitet. (TF-GPU 2.0, Windows 10, GeForce RTX 2070)

physical_devices = tf.config.experimental.list_physical_devices('GPU')
assert len(physical_devices) > 0, "Not enough GPU hardware devices available"
tf.config.experimental.set_memory_growth(physical_devices[0], True)
Sunsetquest
quelle
1
Ich benutze TF-GPU 2.0, Ubuntu 16.04.6, Tesla K80.
Azar
@azar - Danke fürs Teilen. Das ist das gleiche Problem sowohl unter Ubuntu als auch unter Windows. Irgendwie denke ich immer, dass die Probleme anders sind, wenn man sich der Hardware nähert. Vielleicht wird dies mit der Zeit immer weniger - vielleicht eine gute Sache.
Sunsetquest
3

Wenn Sie Tensorflow 2 verwenden, versuchen Sie Folgendes:

config = tf.compat.v1.ConfigProto()
config.gpu_options.allow_growth = True
session = tf.compat.v1.Session(config=config)
Elchfeder
quelle
Arbeit für Tensorflow 2
Mobin Alhassan vor
1

Ich habe versucht, Unet auf Voc-Datensatz zu trainieren, aber wegen der großen Bildgröße wird der Speicher beendet. Ich habe alle oben genannten Tipps ausprobiert, sogar mit der Chargengröße == 1, aber ohne Verbesserung. Manchmal verursacht die TensorFlow-Version auch Speicherprobleme. versuchen Sie es mit

pip install tensorflow-gpu == 1.8.0

Khan
quelle
1

Nun, ich bin neu in Tensorflow, ich habe Geforce 740m oder eine GPU mit 2 GB RAM, ich habe ein mnistisches handgeschriebenes Beispiel für eine Muttersprache mit Trainingsdaten ausgeführt, die 38700 Bilder und 4300 Testbilder enthalten, und versucht, Präzision zu erhalten. F1 mit folgendem Code als sklearn gab mir keine genauen Ergebnisse. Nachdem ich dies zu meinem vorhandenen Code hinzugefügt hatte, bekam ich GPU-Fehler.

TP = tf.count_nonzero(predicted * actual)
TN = tf.count_nonzero((predicted - 1) * (actual - 1))
FP = tf.count_nonzero(predicted * (actual - 1))
FN = tf.count_nonzero((predicted - 1) * actual)

prec = TP / (TP + FP)
recall = TP / (TP + FN)
f1 = 2 * prec * recall / (prec + recall)

Außerdem war mein Modell schwer, ich glaube, ich bekam nach 147, 148 Epochen einen Speicherfehler, und dann dachte ich mir, warum ich keine Funktionen für die Aufgaben erstellen sollte, damit ich nicht weiß, ob es im Tensrorflow so funktioniert, aber ich dachte, ob es eine lokale Variable ist verwendet und wenn es außerhalb des Bereichs liegt, kann es Speicher freigeben und ich definierte die oben genannten Elemente für das Training und Testen in Modulen. Ich konnte 10000 Epochen ohne Probleme erreichen. Ich hoffe, dies wird helfen.

Imran Ud Din
quelle
Ich bin erstaunt über das Dienstprogramm von TF, aber auch über die Speichernutzung. Auf der CPU-Python, die ungefähr 30 GB für einen Schulungsjob für den in Mai-TF-Beispiel verwendeten Blumendatensatz zuweist. Wahnsinnig.
Eric M
1
# allocate 60% of GPU memory 
from keras.backend.tensorflow_backend import set_session
import tensorflow as tf 
config = tf.ConfigProto()
config.gpu_options.per_process_gpu_memory_fraction = 0.6
set_session(tf.Session(config=config))
DSBLR
quelle
Die bereitgestellte Antwort wurde zur Überprüfung als Beitrag von geringer Qualität gekennzeichnet. Hier sind einige Richtlinien für Wie schreibe ich eine gute Antwort? . Diese Antwort mag richtig sein, könnte aber von einer Erklärung profitieren. Nur-Code-Antworten gelten nicht als "gute" Antworten. Aus der Überprüfung .
Trenton McKinney