Comment empêcher tensorflow d'allouer la totalité d'une mémoire GPU?

283

Je travaille dans un environnement dans lequel les ressources de calcul sont partagées, c'est-à-dire que nous avons quelques machines serveurs équipées de quelques GPU Nvidia Titan X chacune.

Pour les modèles de petite à moyenne taille, les 12 Go du Titan X sont généralement suffisants pour que 2 à 3 personnes puissent exécuter la formation simultanément sur le même GPU. Si les modèles sont suffisamment petits pour qu'un seul modèle ne tire pas pleinement parti de toutes les unités de calcul du GPU, cela peut en fait entraîner une accélération par rapport à l'exécution d'un processus de formation après l'autre. Même dans les cas où l'accès simultané au GPU ralentit le temps de formation individuel, il est toujours agréable d'avoir la flexibilité d'avoir plusieurs utilisateurs simultanément formés sur le GPU.

Le problème avec TensorFlow est que, par défaut, il alloue la quantité totale de mémoire GPU disponible lors de son lancement. Même pour un petit réseau neuronal à deux couches, je constate que les 12 Go de mémoire GPU sont utilisés.

Existe-t-il un moyen de faire en sorte que TensorFlow n'alloue que, disons, 4 Go de mémoire GPU, si l'on sait que cela suffit pour un modèle donné?

Fabien C.
la source

Réponses:

292

Vous pouvez définir la fraction de mémoire GPU à allouer lorsque vous construisez un tf.Sessionen passant un tf.GPUOptionsdans le cadre de l' configargument facultatif :

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

Les per_process_gpu_memory_fractionagit comme un disque limite supérieure de la quantité de mémoire de GPU qui sera utilisé par le processus sur chaque GPU sur la même machine. Actuellement, cette fraction est appliquée uniformément à tous les GPU sur la même machine; il n'y a aucun moyen de définir cela sur une base par GPU.

mrry
la source
3
Merci beaucoup. Cette information est assez cachée dans le document actuel. Je ne l'aurais jamais trouvé par moi-même :-) Si vous pouvez répondre, j'aimerais demander deux infos supplémentaires: 1- Est-ce que cela limite la quantité de mémoire jamais utilisée, ou juste la mémoire initialement allouée? (c.-à-d., allouera-t-il encore plus de mémoire si le graphe de calcul en a besoin) 2- Existe-t-il un moyen de régler cela sur une base par GPU?
Fabien C.
15
Remarque connexe: la configuration de CUDA_VISIBLE_DEVICES pour limiter TensorFlow à un seul GPU fonctionne pour moi. Voir acceleware.com/blog/cudavisibledevices-masking-gpus
rd11
2
il semble que l'allocation de mémoire dépasse un peu la demande, e..g j'ai demandé per_process_gpu_memory_fraction = 0.0909 sur un gpu 24443MiB et a obtenu des processus prenant 2627MiB
jeremy_rutman
2
Je n'arrive pas à faire fonctionner cela dans unMonitoredTrainingSession
Anjum Sayed
2
@jeremy_rutman Je pense que cela est dû à l'initialisation du contexte cudnn et cublas. Cela n'est pertinent que si vous exécutez des noyaux qui utilisent ces bibliothèques.
Daniel
187
config = tf.ConfigProto()
config.gpu_options.allow_growth=True
sess = tf.Session(config=config)

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

Sergey Demyanov
la source
13
Celui-ci est exactement ce que je veux car dans un environnement multi-utilisateur, il est très gênant de spécifier la quantité exacte de mémoire GPU à réserver dans le code lui-même.
xuancong84
4
De plus, si vous utilisez Keras avec un backend TF, vous pouvez l'utiliser et l'exécuter from keras import backend as Ket K.set_session(sess)pour éviter les limitations de mémoire
Oliver
50

Voici un extrait du livre Deep Learning with TensorFlow

Dans certains cas, il est souhaitable que le processus n'alloue qu'un sous-ensemble de la mémoire disponible ou n'augmente l'utilisation de la mémoire que lorsque le processus en a besoin. TensorFlow fournit deux options de configuration sur la session pour contrôler cela. La première est l' allow_growthoption, qui tente d'allouer uniquement autant de mémoire GPU en fonction des allocations d'exécution, elle commence par allouer très peu de mémoire, et au fur et à mesure que les sessions s'exécutent et que davantage de mémoire GPU est nécessaire, nous étendons la zone de mémoire GPU requise par le TensorFlow processus.

1) Permettre la croissance: (plus flexible)

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

La deuxième méthode est l' per_process_gpu_memory_fractionoption, qui détermine la fraction de la quantité totale de mémoire que le eachGPU visible doit être alloué. Remarque: Aucune libération de mémoire n'est nécessaire, cela peut même aggraver la fragmentation de la mémoire une fois terminé.

2) Allouer de la mémoire fixe :

Pour allouer uniquement 40%la mémoire totale de chaque GPU par:

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

Remarque: Cela n'est utile que si vous voulez vraiment lier la quantité de mémoire GPU disponible sur le processus TensorFlow.

user1767754
la source
En ce qui concerne votre question, l'option 2 pourrait vous être utile. En général, si vous n'avez pas plusieurs applications en cours d'exécution sur le GPU et les réseaux dynamiques, il est judicieux d'utiliser l'option «Autoriser la croissance».
aniket
19

Toutes les réponses ci-dessus supposent l'exécution avec un sess.run()appel, ce qui devient l'exception plutôt que la règle dans les versions récentes de TensorFlow.

Lorsque vous utilisez le tf.Estimatorframework (TensorFlow 1.4 et supérieur), le moyen de transmettre la fraction à la création implicite MonitoredTrainingSessionest,

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)

De même en mode Désireux (TensorFlow 1.5 et supérieur),

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

Edit: 11-04-2018 Par exemple, si vous devez utiliser tf.contrib.gan.train, vous pouvez utiliser quelque chose de similaire à ci-dessous:

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

Pour Tensorflow versions 2.0 et 2.1, utilisez l'extrait de code suivant :

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

Pour les versions précédentes , l'extrait suivant fonctionnait pour moi:

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

Tensorflow 2.0 Beta et (probablement) au-delà

L'API a de nouveau changé. Il se trouve maintenant dans:

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

Alias:

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

Références:

Voir aussi: Tensorflow - Utilisez un GPU : https://www.tensorflow.org/guide/gpu

pour Tensorflow 2.0 Alpha voir: cette réponse

mx_muc
la source
9

Vous pouvez utiliser

TF_FORCE_GPU_ALLOW_GROWTH=true

dans vos variables d'environnement.

Dans le code 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
la source
5

Prise sans vergogne: si vous installez le Tensorflow pris en charge par le GPU, la session allouera d'abord tous les GPU, que vous le configuriez pour n'utiliser que le CPU ou le GPU. Je peux ajouter mon conseil que même si vous définissez le graphique pour utiliser uniquement le CPU, vous devez définir la même configuration (comme indiqué ci-dessus :)) pour éviter l'occupation indésirable du GPU.

Et dans une interface interactive comme IPython, vous devez également définir cette configuration, sinon elle allouera toute la mémoire et n'en laissera presque aucune pour les autres. C'est parfois difficile à remarquer.

Lerner Zhang
la source
3

Pour Tensorflow 2.0, cette solution a fonctionné pour moi. (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
la source
1
J'utilise TF-GPU 2.0, Ubuntu 16.04.6, Tesla K80.
azar
@azar - Merci pour le partage. C'est intéressant le même problème sur Ubuntu et Windows. D'une certaine manière, je pense toujours que les problèmes sont différents lorsque l'on se rapproche du matériel. Peut-être que cela diminue avec le temps - peut-être une bonne chose.
Sunsetquest
3

Si vous utilisez Tensorflow 2, essayez ce qui suit:

config = tf.compat.v1.ConfigProto()
config.gpu_options.allow_growth = True
session = tf.compat.v1.Session(config=config)
Plume d'orignal
la source
travailler pour Tensorflow 2
mobin alhassan
1

j'ai essayé de former unet sur le jeu de données voc mais à cause de la taille énorme de l'image, la mémoire se termine. J'ai essayé tous les conseils ci-dessus, même essayé avec une taille de lot == 1, mais sans amélioration. parfois, la version TensorFlow provoque également des problèmes de mémoire. essayez en utilisant

pip install tensorflow-gpu == 1.8.0

Khan
la source
1

Eh bien, je suis nouveau sur tensorflow, j'ai Geforce 740m ou quelque chose de GPU avec 2 Go de RAM, je courais un genre d'exemple manuscrit pour une langue maternelle avec des données de formation contenant 38700 images et 4300 images de test et essayais d'obtenir la précision, rappelez-vous, F1 utilisant le code suivant comme sklearn ne me donnait pas de réponses précises. une fois que j'ai ajouté cela à mon code existant, j'ai commencé à obtenir des erreurs 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)

De plus, mon modèle était lourd, je suppose, j'obtenais une erreur de mémoire après 147, 148 époques, puis j'ai pensé pourquoi ne pas créer de fonctions pour les tâches, donc je ne sais pas si cela fonctionne de cette façon dans Tensrorflow, mais je me suis demandé si une variable locale était utilisé et lorsqu'il est hors de portée, il peut libérer de la mémoire et j'ai défini les éléments ci-dessus pour la formation et les tests dans les modules, j'ai pu atteindre 10000 époques sans aucun problème, j'espère que cela vous aidera.

Imran Ud Din
la source
Je suis étonné de l'utilité de TF mais aussi de son utilisation de la mémoire. Sur le python CPU allouant 30 Go environ pour un travail de formation sur le jeu de données flowers utilisé dans les exemples TF de mai. Insensé.
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
la source
La réponse fournie a été signalée pour examen en tant que publication de faible qualité. Voici quelques lignes directrices pour Comment écrire une bonne réponse? . Cette réponse fournie peut être correcte, mais elle pourrait bénéficier d'une explication. Les réponses codées uniquement ne sont pas considérées comme de «bonnes» réponses. De l' examen .
Trenton McKinney