web-dev-qa-db-fra.com

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

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

Pour les modèles de taille petite à moyenne, les 12 Go du Titan X sont généralement suffisants pour que 2 à 3 personnes puissent s'entraîner simultanément sur le même processeur graphique. 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 Titan X, il peut en résulter une accélération par rapport à l’exécution d’un processus d’entraînement 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 possibilité de faire fonctionner plusieurs utilisateurs à la fois sur les GPU.

Le problème avec TensorFlow est que, par défaut, il alloue la totalité de la mémoire disponible sur le GPU lors de son lancement. Même pour un petit réseau de neurones à 2 couches, je constate que les 12 Go du Titan X sont épuisés.

Existe-t-il un moyen de faire en sorte que TensorFlow n'alloue que, par exemple, 4 Go de mémoire GPU, si l'on sait que cette quantité est suffisante pour un modèle donné?

193
Fabien C.

Vous pouvez définir la fraction de mémoire GPU à allouer lorsque vous construisez un tf.Session en passant un tf.GPUOptions dans le cadre de l’argument optionnel config:

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

Le per_process_gpu_memory_fraction agit comme une limite supérieure fixe sur la quantité de mémoire GPU qui sera utilisée par le processus sur chaque GPU sur le même ordinateur. Actuellement, cette fraction est appliquée uniformément à tous les GPU de la même machine. il n'y a aucun moyen de régler cela sur une base par GPU.

220
mrry
config = tf.ConfigProto()
config.gpu_options.allow_growth=True
sess = tf.Session(config=config)

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

142
Sergey Demyanov

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 si le processus en a besoin. TensorFlow fournit deux configurations options sur la session pour contrôler cela. La première est l’option allow_growth, qui tente d’allouer autant de mémoire GPU que d’allocations d’exécution, commence à allouer très peu de mémoire et, à mesure que les sessions sont exécutées et que la mémoire GPU est plus importante, nous étendons la région de Processus TensorFlow.

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'option per_process_gpu_memory_fraction, qui détermine la fraction de la quantité totale de mémoire que le GPU each visible doit être alloué. Remarque: Aucune libération de mémoire 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% de la mémoire totale de chaque GPU, procédez comme suit:

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 souhaitez vraiment lier la quantité de mémoire GPU disponible sur le processus TensorFlow.

28
user1767754

Mise à jour pour TensorFlow 2.0 Alpha et les versions ultérieures

Dans les documents Alpha 2.0, la réponse n’est plus qu’une ligne avant de faire quoi que ce soit avec TensorFlow:

import tensorflow as tf
tf.config.gpu.set_per_process_memory_growth(True)
10
Theo

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

Lorsque vous utilisez le framework tf.Estimator (TensorFlow 1.4 et supérieur), le moyen de transmettre la fraction à la variable implicite créée MonitoredTrainingSession est

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 Eager (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)
10
Urs

Prise sans scrupule: si vous installez le Tensorflow pris en charge par le GPU, la session allouera tout d'abord tous les GPU, que vous le configuriez pour utiliser uniquement le processeur ou le GPU. Je peux ajouter mon conseil: même si vous définissez le graphique pour utiliser uniquement le processeur, vous devez définir la même configuration (comme indiqué ci-dessus :)) afin d'empêcher l'occupation non souhaitée du processeur graphique. 

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. 

3
lerner

Tensorflow 2.0 Beta et (probablement) au-delà

L'API a encore changé. On peut le trouver 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
  • tf.config.experimental.set_memory_growth

https://www.tensorflow.org/versions/r2.0/api_docs/python/tf/config/experimental/set_memory_growthhttps://www.tensorflow.org/beta/guide/using_gpu#limiting_gpu_memory_growth

1
mx_muc

Vous pouvez utiliser

TF_FORCE_GPU_ALLOW_GROWTH=true

dans vos variables d'environnement.

Dans 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();
}
1
Mey Khalili

j'ai essayé de m'entraîner sur les données vocales, mais à cause de la taille énorme de l'image, la mémoire se termine. J'ai essayé tous les conseils ci-dessus, même avec une taille de lot == 1, mais aucune amélioration. Parfois, la version de TensorFlow provoque également des problèmes de mémoire. essayez en utilisant 

pip installer tensorflow-gpu == 1.8.0

0
Khan

Eh bien, je suis nouveau sur tensorflow, j’ai Geforce 740m ou un GPU avec 2 Go de RAM, j’exécutais le type d’exemple manuscrit mnist pour une langue maternelle avec des données de formation contenant 38700 images et 4300 images de test et je cherchais à obtenir de la précision F1 en utilisant le code suivant comme sklearn ne me donnait pas de résultats précis. Une fois que j'ai ajouté ceci à mon code existant, j'ai commencé à avoir des erreurs de 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, je commençais à avoir une erreur de mémoire après 147, 148 époques, puis je me suis dit pourquoi ne pas créer de fonctions pour les tâches afin que je ne sache pas si cela fonctionne de cette façon dans tensrorflow, mais je me suis demandé si une variable locale était utilisé et quand 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 été capable de réaliser 10000 époques sans aucun problème, j'espère que cela aidera.

0
Imran Ud Din