Jak zapobiec alokacji przez tensorflow całości pamięci GPU?

282

Pracuję w środowisku, w którym zasoby obliczeniowe są współużytkowane, tj. Mamy kilka maszyn serwerowych wyposażonych w kilka procesorów graficznych Nvidia Titan X.

W przypadku modeli o małych i średnich rozmiarach 12 GB Titan X zwykle wystarcza, aby 2-3 osoby mogły jednocześnie trenować na tym samym GPU. Jeśli modele są na tyle małe, że jeden model nie wykorzystuje w pełni wszystkich jednostek obliczeniowych GPU, może to faktycznie spowodować przyspieszenie w porównaniu z uruchomieniem jednego procesu szkoleniowego po drugim. Nawet w przypadkach, gdy równoczesny dostęp do GPU spowalnia indywidualny czas szkolenia, nadal miło jest mieć możliwość jednoczesnego trenowania wielu użytkowników na GPU.

Problem z TensorFlow polega na tym, że domyślnie przy uruchamianiu przydziela pełną ilość dostępnej pamięci GPU. Nawet w przypadku małej dwuwarstwowej sieci neuronowej widzę, że wszystkie 12 GB pamięci GPU jest zużyte.

Czy istnieje sposób, aby TensorFlow przydzielał tylko powiedzmy 4 GB pamięci GPU, jeśli wiadomo, że to wystarczy dla danego modelu?

Fabien C.
źródło

Odpowiedzi:

292

Możesz ustawić ułamek pamięci GPU do przydzielenia podczas konstruowania a tf.Session, przekazując tf.GPUOptionsjako część opcjonalnego configargumentu:

# 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))

W per_process_gpu_memory_fractiondziała jak twarde górną granicę ilości pamięci procesora graficznego, który zostanie użyty w procesie na procesorach w tym samym urządzeniu. Obecnie ta część jest stosowana równomiernie do wszystkich GPU na tej samej maszynie; nie ma możliwości ustawienia tego dla poszczególnych GPU.

mrry
źródło
3
Dziękuję Ci bardzo. Te informacje są dość ukryte w bieżącym dokumencie. Nigdy bym tego nie znalazła :-) Jeśli możesz odpowiedzieć, chciałbym poprosić o dwa dodatkowe informacje: 1- Czy to ogranicza ilość pamięci kiedykolwiek używanej, czy tylko pamięć początkowo przydzieloną? (tj. czy nadal przydzieli więcej pamięci, jeśli zajdzie taka potrzeba na wykresie obliczeniowym) 2- Czy istnieje sposób, aby ustawić to dla poszczególnych GPU?
Fabien C.,
15
Powiązana uwaga: dla mnie działa ustawienie CUDA_VISIBLE_DEVICES, aby ograniczyć TensorFlow do jednego GPU. Zobacz acceleware.com/blog/cudavisibledevices-masking-gpus
rd11
2
wygląda na to, że alokacja pamięci jest nieco większa niż w żądaniu, np. poprosiłem o frakcję per_process_gpu_memory_fraction = 0,0909 na GPU 24443MiB i otrzymałem procesy przyjmujące 2627MiB
jeremy_rutman
2
Nie mogę tego zmusić doMonitoredTrainingSession
Anjum Sayed
2
@jeremy_rutman Myślę, że jest to spowodowane inicjalizacją kontekstu cudnn i cublas. Jest to istotne tylko wtedy, gdy wykonujesz jądra korzystające z tych bibliotek.
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
źródło
13
Ten jest dokładnie tym, czego chcę, ponieważ w środowisku dla wielu użytkowników bardzo niewygodne jest określenie dokładnej ilości pamięci GPU do zarezerwowania w samym kodzie.
xuancong84
4
Ponadto, jeśli używasz Keras z backend TF, można to wykorzystać i biegać from keras import backend as Ki K.set_session(sess)ograniczeń pamięciowych uniknąć
Oliver
50

Oto fragment Księgi Deep Learning with TensorFlow

W niektórych przypadkach pożądane jest, aby proces alokował tylko podzbiór dostępnej pamięci lub zwiększał wykorzystanie pamięci tylko w sposób wymagany przez proces. TensorFlow zapewnia dwie opcje konfiguracji w sesji, aby to kontrolować. Pierwszą jest allow_growthopcja, która próbuje przydzielić tylko tyle pamięci GPU na podstawie przydziałów środowiska uruchomieniowego, zaczyna przydzielać bardzo mało pamięci, a gdy sesje się uruchamiają i potrzeba więcej pamięci GPU, rozszerzamy obszar pamięci GPU wymagany przez TensorFlow proces.

1) Pozwól na wzrost: (bardziej elastyczny)

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

Druga metoda to per_process_gpu_memory_fractionopcja, która określa ułamek ogólnej ilości pamięci, którą eachpowinien przydzielić widoczny GPU. Uwaga: zwolnienie pamięci nie jest konieczne, może nawet pogorszyć fragmentację pamięci po zakończeniu.

2) Przydziel stałą pamięć :

Aby przydzielić 40%całkowitą pamięć każdego GPU tylko:

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

Uwaga: Jest to przydatne tylko, jeśli naprawdę chcesz powiązać ilość pamięci GPU dostępnej w procesie TensorFlow.

użytkownik1767754
źródło
Jeśli chodzi o twoje pytanie, opcja 2 może być dla ciebie przydatna. Ogólnie rzecz biorąc, jeśli nie masz wielu aplikacji działających na GPU i sieciach dynamicznych, warto skorzystać z opcji „Zezwalaj na wzrost”.
aniket
19

Wszystkie powyższe odpowiedzi zakładają wykonanie z sess.run()wywołaniem, które staje się wyjątkiem, a nie regułą w najnowszych wersjach TensorFlow.

Podczas korzystania z tf.Estimatorframeworka (TensorFlow 1.4 i wyżej) sposobem na przekazanie frakcji do niejawnie utworzonego MonitoredTrainingSessionjest:

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)

Podobnie w trybie Eager (TensorFlow 1.5 i nowszy),

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

Edycja: 11-04-2018 Na przykład, jeśli chcesz użyć tf.contrib.gan.train, możesz użyć czegoś podobnego do poniższego:

tf.contrib.gan.gan_train(........, config=conf)
Urs
źródło
16

W przypadku Tensorflow w wersji 2.0 i 2.1 użyj następującego fragmentu kodu :

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

W poprzednich wersjach dla mnie działał następujący fragment kodu:

import tensorflow as tf
tf_config=tf.ConfigProto()
tf_config.gpu_options.allow_growth=True
sess = tf.Session(config=tf_config)
Anurag
źródło
10

Tensorflow 2.0 Beta i (prawdopodobnie) poza nią

Interfejs API zmienił się ponownie. Można go teraz znaleźć w:

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

Skróty:

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

Bibliografia:

Zobacz także: Tensorflow - Użyj procesora graficznego : https://www.tensorflow.org/guide/gpu

dla Tensorflow 2.0 Alpha patrz: ta odpowiedź

mx_muc
źródło
9

Możesz użyć

TF_FORCE_GPU_ALLOW_GROWTH=true

w zmiennych środowiskowych.

W kodzie tensorflow :

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

Bezwstydna wtyczka: Jeśli zainstalujesz Tensorflow obsługiwany przez GPU, sesja najpierw przydzieli wszystkie GPU, niezależnie od tego, czy ustawisz, aby korzystało tylko z CPU czy GPU. Mogę dodać moją wskazówkę, że nawet jeśli ustawisz wykres tak, aby korzystał tylko z procesora, powinieneś ustawić tę samą konfigurację (zgodnie z odpowiedzią powyżej :)), aby zapobiec niepożądanemu zajęciu GPU.

A w interaktywnym interfejsie, takim jak IPython, powinieneś również ustawić tę konfigurację, w przeciwnym razie przydzieli ona całą pamięć i pozostawi prawie żadną dla innych. Czasami trudno to zauważyć.

Lerner Zhang
źródło
3

Dla Tensorflow 2.0 to rozwiązanie to pracował dla mnie. (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
źródło
1
Używam TF-GPU 2.0, Ubuntu 16.04.6, Tesla K80.
Azar
@azar - Dziękujemy za udostępnienie. To interesujące, ten sam problem zarówno w Ubuntu, jak i Windows. Jakoś zawsze myślę, że problemy są różne, gdy zbliżamy się do sprzętu. Może z czasem staje się coraz mniej, więc może to dobra rzecz.
Sunsetquest
3

Jeśli używasz Tensorflow 2, spróbuj wykonać następujące czynności:

config = tf.compat.v1.ConfigProto()
config.gpu_options.allow_growth = True
session = tf.compat.v1.Session(config=config)
Moosefeather
źródło
praca dla Tensorflow 2
mobin alhassan
1

Próbowałem trenować unet na zestawie danych wok, ale z powodu ogromnego rozmiaru obrazu pamięć kończy się. wypróbowałem wszystkie powyższe wskazówki, nawet próbowałem z rozmiarem partii == 1, ale bez poprawy. czasami wersja TensorFlow powoduje również problemy z pamięcią. spróbuj za pomocą

pip install tensorflow-gpu == 1.8.0

Chan
źródło
1

Cóż, jestem nowy w tensorflow, mam Geforce 740m lub coś z GPU z 2 GB pamięci RAM, prowadziłem odręczny przykład odręcznego przykładu dla języka ojczystego z danymi szkoleniowymi zawierającymi 38700 obrazów i 4300 zdjęć testowych i starałem się uzyskać precyzję, przypominać, F1 używając następującego kodu jako sklearn nie dawało mi precyzyjnych wyników. po dodaniu tego do mojego istniejącego kodu zacząłem otrzymywać błędy GPU.

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)

plus mój model był chyba ciężki, otrzymywałem błąd pamięci po 147, 148 epokach, a potem pomyślałem, dlaczego nie tworzyć funkcji dla zadań, więc nie wiem, czy działa w ten sposób w tensrorflow, ale pomyślałem, że jeśli zmienna lokalna jest używane i kiedy poza zakresem może zwolnić pamięć i zdefiniowałem powyższe elementy do szkolenia i testowania w modułach, byłem w stanie osiągnąć 10000 epok bez żadnych problemów, mam nadzieję, że to pomoże ..

Imran Ud Din
źródło
Zadziwia mnie użyteczność TF, ale także wykorzystanie pamięci. Na pytonie CPU przeznaczającym około 30 GB na zadanie szkoleniowe w zestawie danych kwiatów używanych w przykładach TF. Szalony.
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
źródło
Podana odpowiedź została oznaczona do oceny jako post niskiej jakości. Oto kilka wskazówek, jak napisać dobrą odpowiedź? . Ta podana odpowiedź może być poprawna, ale może przydać się wyjaśnienie. Odpowiedzi tylko w kodzie nie są uważane za „dobre”. Z przeglądu .
Trenton McKinney,