¿Cómo evitar que tensorflow asigne la totalidad de una memoria de GPU?

282

Trabajo en un entorno en el que se comparten recursos computacionales, es decir, tenemos algunas máquinas de servidor equipadas con algunas GPU Nvidia Titan X cada una.

Para modelos de tamaño pequeño a moderado, los 12 GB del Titan X suelen ser suficientes para que 2–3 personas realicen un entrenamiento al mismo tiempo en la misma GPU. Si los modelos son lo suficientemente pequeños como para que un solo modelo no aproveche al máximo todas las unidades computacionales de la GPU, esto puede resultar en una aceleración en comparación con la ejecución de un proceso de entrenamiento después del otro. Incluso en los casos en que el acceso concurrente a la GPU ralentiza el tiempo de entrenamiento individual, es bueno tener la flexibilidad de tener múltiples usuarios entrenándose simultáneamente en la GPU.

El problema con TensorFlow es que, de forma predeterminada, asigna la cantidad total de memoria de GPU disponible cuando se inicia. Incluso para una pequeña red neuronal de dos capas, veo que los 12 GB de memoria de la GPU están agotados.

¿Hay alguna manera de hacer que TensorFlow solo asigne, por ejemplo, 4 GB de memoria de GPU, si se sabe que esto es suficiente para un modelo dado?

Fabien C.
fuente

Respuestas:

292

Puede configurar la fracción de memoria de GPU que se asignará cuando construya un tf.Sessionpasando un tf.GPUOptionscomo parte del configargumento opcional :

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

Los per_process_gpu_memory_fractionactúa como una fuerza límite superior de la cantidad de memoria de la GPU que será utilizado por el proceso en cada GPU en la misma máquina. Actualmente, esta fracción se aplica de manera uniforme a todas las GPU en la misma máquina; no hay forma de configurar esto por GPU.

señor
fuente
3
Muchas gracias. Esta información está bastante oculta en el documento actual. Nunca lo habría encontrado por mí mismo :-) Si puede responder, me gustaría pedir dos informaciones adicionales: 1- ¿Limita esto la cantidad de memoria utilizada alguna vez, o solo la memoria inicialmente asignada? (es decir, seguirá asignando más memoria si es necesario por el gráfico de cálculo) 2- ¿Hay alguna manera de configurar esto por GPU?
Fabien C.
15
Nota relacionada: configurar CUDA_VISIBLE_DEVICES para limitar TensorFlow a una sola GPU me funciona. Ver acceleware.com/blog/cudavisibledevices-masking-gpus
rd11
2
parece que la asignación de memoria va un poco por encima de la solicitud, por ejemplo, solicité per_process_gpu_memory_fraction = 0.0909 en una gpu de 24443MiB y obtuve procesos que toman 2627MiB
jeremy_rutman el
2
Parece que no puedo hacer que esto funcione en unMonitoredTrainingSession
Anjum Sayed
2
@jeremy_rutman Creo que esto se debe a la inicialización del contexto cudnn y cublas. Sin embargo, eso solo es relevante si está ejecutando núcleos que usan esas bibliotecas.
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
fuente
13
Esto es exactamente lo que quiero porque en un entorno multiusuario, es muy inconveniente especificar la cantidad exacta de memoria de GPU que se reserva en el código mismo.
xuancong84
44
Además, si usted está utilizando Keras con un backend TF, puede utilizar esto y correr from keras import backend as Ky K.set_session(sess)a las limitaciones de memoria Evita
Oliver
50

Aquí hay un extracto del libro. Deep Learning with TensorFlow

En algunos casos, es deseable que el proceso solo asigne un subconjunto de la memoria disponible o que solo aumente el uso de la memoria según lo necesite el proceso. TensorFlow proporciona dos opciones de configuración en la sesión para controlar esto. La primera es la allow_growthopción, que intenta asignar solo la cantidad de memoria de GPU basada en asignaciones de tiempo de ejecución, comienza asignando muy poca memoria y, a medida que se ejecutan las sesiones y se necesita más memoria de GPU, ampliamos la región de memoria de GPU que necesita TensorFlow proceso.

1) Permitir crecimiento: (más flexible)

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

El segundo método es la per_process_gpu_memory_fractionopción, que determina la fracción de la cantidad total de memoria que se eachdebe asignar a la GPU visible. Nota: No se necesita liberar memoria, incluso puede empeorar la fragmentación de la memoria cuando se hace.

2) Asignar memoria fija :

Para asignar solo 40%la memoria total de cada GPU por:

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

Nota: Eso solo es útil si realmente desea vincular la cantidad de memoria de GPU disponible en el proceso TensorFlow.

usuario1767754
fuente
En lo que respecta a su pregunta, la opción 2 podría serle útil. En general, si no tiene múltiples aplicaciones ejecutándose en GPU y redes dinámicas, entonces tiene sentido usar la opción 'Permitir crecimiento'.
Aniket
19

Todas las respuestas anteriores suponen la ejecución con una sess.run()llamada, que se está convirtiendo en la excepción en lugar de la regla en las versiones recientes de TensorFlow.

Al usar el tf.Estimatormarco (TensorFlow 1.4 y superior), la forma de pasar la fracción a lo creado implícitamenteMonitoredTrainingSession es,

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)

Del mismo modo, en el modo Eager (TensorFlow 1.5 y superior),

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

Editar: 11-04-2018 Como ejemplo, si va a usar tf.contrib.gan.train, puede usar algo similar a lo siguiente:

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

Para Tensorflow versión 2.0 y 2.1, use el siguiente fragmento :

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

Para versiones anteriores , el siguiente fragmento solía funcionar para mí:

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

Tensorflow 2.0 Beta y (probablemente) más allá

La API cambió de nuevo. Ahora se puede encontrar en:

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

Referencias

Consulte también: Tensorflow: use una GPU : https://www.tensorflow.org/guide/gpu

para Tensorflow 2.0 Alpha ver: esta respuesta

mx_muc
fuente
8

Puedes usar

TF_FORCE_GPU_ALLOW_GROWTH=true

en sus variables de entorno

En el código de 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
fuente
5

Enchufe desvergonzado: si instala el Tensorflow compatible con GPU, la sesión primero asignará todas las GPU, ya sea que configure que use solo CPU o GPU. Puedo agregar mi consejo de que incluso si configura el gráfico para usar CPU solo debe establecer la misma configuración (como se respondió anteriormente :)) para evitar la ocupación de GPU no deseada.

Y en una interfaz interactiva como IPython, también debe configurar esa configuración, de lo contrario, asignará toda la memoria y dejará casi ninguna para los demás. Esto a veces es difícil de notar.

Lerner Zhang
fuente
3

Para Tensorflow 2.0, esta solución funcionó para mí. (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
fuente
1
Estoy usando TF-GPU 2.0, Ubuntu 16.04.6, Tesla K80.
azar
@azar - Gracias por compartir. Es interesante el mismo problema tanto en Ubuntu como en Windows. De alguna manera, siempre pienso que los problemas son diferentes cuando nos acercamos al hardware. Tal vez esto sea cada vez menos a medida que pase el tiempo, tal vez sea algo bueno.
Sunsetquest
3

Si está utilizando Tensorflow 2 intente lo siguiente:

config = tf.compat.v1.ConfigProto()
config.gpu_options.allow_growth = True
session = tf.compat.v1.Session(config=config)
Pluma de alce
fuente
trabajo para Tensorflow 2
mobin alhassan hace
1

Traté de entrenar unet en el conjunto de datos voc pero debido al gran tamaño de la imagen, la memoria termina. Probé todos los consejos anteriores, incluso probé con el tamaño del lote == 1, pero no obtuve ninguna mejora. a veces la versión TensorFlow también causa problemas de memoria intente usando

pip install tensorflow-gpu == 1.8.0

Kan
fuente
1

Bueno, soy nuevo en tensorflow, tengo Geforce 740m o algo GPU con 2GB de RAM, estaba ejecutando un ejemplo escrito a mano mnist para un idioma nativo con datos de entrenamiento que contienen 38700 imágenes y 4300 imágenes de prueba y estaba tratando de obtener precisión, recordar, F1 usando el siguiente código como sklearn no me estaba dando resultados precisos. Una vez que agregué esto a mi código existente, comencé a recibir errores 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)

Además, supongo que mi modelo era pesado, estaba recibiendo un error de memoria después de 147, 148 épocas, y luego pensé por qué no crear funciones para las tareas, así que no sé si funciona de esta manera en el flujo de tensión, pero pensé si una variable local es utilizado y cuando está fuera del alcance puede liberar memoria y definí los elementos anteriores para la capacitación y las pruebas en los módulos, pude lograr 10000 épocas sin ningún problema, espero que esto ayude.

Imran Ud Din
fuente
Estoy sorprendido por la utilidad de TF pero también por su uso de memoria. En la CPU, Python asigna 30 GB más o menos para un trabajo de capacitación sobre el conjunto de datos de flores utilizado en muchos ejemplos de TF. Insano.
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
fuente
La respuesta proporcionada se marcó para su revisión como Publicación de baja calidad. Aquí hay algunas pautas para ¿Cómo escribo una buena respuesta? . Esta respuesta proporcionada puede ser correcta, pero podría beneficiarse de una explicación. Las respuestas de solo código no se consideran respuestas "buenas". De la revisión .
Trenton McKinney