Como impedir que o fluxo tensor aloque a totalidade da memória da GPU?


282

Trabalho em um ambiente em que os recursos computacionais são compartilhados, ou seja, temos algumas máquinas servidoras equipadas com algumas GPUs Nvidia Titan X cada.

Para modelos de tamanho pequeno a moderado, os 12 GB do Titan X geralmente são suficientes para 2-3 pessoas executar treinamento simultaneamente na mesma GPU. Se os modelos forem pequenos o suficiente para que um único modelo não tire o máximo proveito de todas as unidades computacionais da GPU, isso poderá resultar em uma aceleração em comparação à execução de um processo de treinamento após o outro. Mesmo nos casos em que o acesso simultâneo à GPU diminui o tempo de treinamento individual, ainda é bom ter a flexibilidade de ter vários usuários treinando simultaneamente na GPU.

O problema com o TensorFlow é que, por padrão, ele aloca a quantidade total de memória disponível da GPU quando é iniciada. Mesmo para uma pequena rede neural de duas camadas, vejo que todos os 12 GB de memória da GPU estão esgotados.

Existe uma maneira de fazer o TensorFlow alocar apenas, digamos, 4 GB de memória GPU, se alguém souber que isso é suficiente para um determinado modelo?

Respostas:


292

Você pode definir a fração da memória da GPU a ser alocada ao construir a tf.Sessionpassando a tf.GPUOptionscomo parte do 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))

Ele per_process_gpu_memory_fractionatua como um limite superior rígido da quantidade de memória da GPU que será usada pelo processo em cada GPU na mesma máquina. Atualmente, essa fração é aplicada uniformemente a todas as GPUs na mesma máquina; não há como definir isso em uma base por GPU.


3
Muito obrigado. Esta informação está bastante oculta no documento atual. Eu nunca teria encontrado isso sozinho :-) Se você puder responder, gostaria de pedir duas informações adicionais: 1- Isso limita a quantidade de memória já utilizada ou apenas a memória inicialmente alocada? (isto é, ele ainda alocará mais memória se houver necessidade pelo gráfico de computação) 2- Existe uma maneira de definir isso em uma base por GPU?
— Fabien C.

15
Nota relacionada: configurar CUDA_VISIBLE_DEVICES para limitar o TensorFlow a uma única GPU funciona para mim. Veja acceleware.com/blog/cudavisibledevices-masking-gpus
— rd11

2
parece que a alocação de memória vai um pouco sobre o pedido, e..g I solicitado per_process_gpu_memory_fraction = 0,0909 em um gpu 24443MiB e processos tenho de tomar 2627MiB
— jeremy_rutman

2
Parece que não consigo fazer isso funcionar em umMonitoredTrainingSession
— Anjum Sayed

2
@jeremy_rutman Acredito que isso se deva à inicialização do contexto cudnn e cublas. Isso é relevante apenas se você estiver executando kernels que usam essas bibliotecas.
— Daniel

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

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


13
Este é exatamente o que eu quero, porque em um ambiente multiusuário, é muito inconveniente especificar a quantidade exata de memória da GPU a ser reservada no próprio código.
— precisa saber é o seguinte

4
Além disso, se você estiver usando Keras com um backend TF, você pode usar este e executar from keras import backend as Ke K.set_session(sess)a limitações de memória Evitar
— Oliver

50

Aqui está um trecho do livro Deep Learning with TensorFlow

Em alguns casos, é desejável que o processo aloque apenas um subconjunto da memória disponível ou aumente apenas o uso de memória conforme necessário pelo processo. O TensorFlow fornece duas opções de configuração na sessão para controlar isso. A primeira é a allow_growthopção, que tenta alocar apenas a quantidade de memória da GPU com base nas alocações de tempo de execução, começa a alocar muito pouca memória e, à medida que as sessões são executadas e é necessária mais memória da GPU, estendemos a região de memória da GPU necessária pelo TensorFlow processo.

1) Permitir crescimento: (mais flexível)

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

O segundo método é a per_process_gpu_memory_fractionopção, que determina a fração da quantidade geral de memória que a eachGPU visível deve ser alocada. Nota: Não é necessária nenhuma liberação de memória; ele pode até piorar a fragmentação da memória quando concluído.

2) Aloque memória fixa :

Para alocar apenas 40%a memória total de cada GPU por:

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

Nota: Isso só é útil se você realmente deseja vincular a quantidade de memória da GPU disponível no processo do TensorFlow.


No que diz respeito à sua pergunta, a opção 2 pode ser útil para você. Em geral, se você não possui vários aplicativos em execução na GPU e nas redes dinâmicas, faz sentido usar a opção 'Permitir crescimento'.
— aniket 31/01


19

Todas as respostas acima assumem a execução com uma sess.run()chamada, que está se tornando a exceção e não a regra nas versões recentes do TensorFlow.

Ao usar a tf.Estimatorestrutura (TensorFlow 1.4 e superior), a maneira de passar a fração para o implicitamente criado 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)

Da mesma forma, no modo Ansioso (TensorFlow 1.5 e superior),

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 Como exemplo, se você for usar tf.contrib.gan.train, poderá usar algo semelhante ao abaixo:

tf.contrib.gan.gan_train(........, config=conf)

16

Para o Tensorflow versão 2.0 e 2.1, use o seguinte trecho :

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

Para versões anteriores , o seguinte snippet costumava funcionar para mim:

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

10

Tensorflow 2.0 Beta e (provavelmente) além

A API mudou novamente. Agora pode ser encontrado em:

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

Apelido:

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

Referências:

Consulte também: Tensorflow - Use uma GPU : https://www.tensorflow.org/guide/gpu

para Tensorflow 2.0 Alpha, consulte: esta resposta


8

Você pode usar

TF_FORCE_GPU_ALLOW_GROWTH=true

nas suas variáveis ​​de ambiente.

No código do 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();
}

5

Plugue descarado: Se você instalar o Tensorflow suportado pela GPU, a sessão primeiro alocará toda a GPU, independentemente de você a configurar para usar apenas CPU ou GPU. Posso acrescentar minha dica de que, mesmo que você defina o gráfico para usar apenas a CPU, defina a mesma configuração (conforme respondida acima :)) para evitar a ocupação indesejada da GPU.

E na interface interativa como o IPython, você também deve definir esse configure, caso contrário, ele alocará toda a memória e deixará quase nenhuma para os outros. Às vezes é difícil perceber.


3

Para o Tensorflow 2.0, esta solução funcionou para mim. (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)

1
Estou usando o TF-GPU 2.0, Ubuntu 16.04.6, Tesla K80.
— Azar

@azar - Obrigado por compartilhar. É interessante o mesmo problema no Ubuntu e no Windows. De alguma forma, sempre penso que os problemas são diferentes ao se aproximar do hardware. Talvez isso esteja diminuindo com o passar do tempo - talvez seja uma coisa boa.
— Sunsetquest

3

Se você estiver usando o Tensorflow 2, tente o seguinte:

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

trabalhar para Tensorflow 2
— mobin alhassan

1

Eu tentei treinar unet no conjunto de dados vocais, mas devido ao enorme tamanho da imagem, a memória termina. Eu tentei todas as dicas acima, mesmo tentei com o tamanho do lote == 1, mas sem melhorias. Às vezes, a versão TensorFlow também causa problemas de memória. tente usando

pip instala tensorflow-gpu == 1.8.0


1

Bem, eu sou novo no tensorflow, tenho Geforce 740m ou algo como GPU com 2 GB de RAM, estava executando o mnist tipo de exemplo manuscrito para um idioma nativo com dados de treinamento contendo 38700 imagens e 4300 imagens de teste e estava tentando obter precisão, recall, F1 usando o código a seguir como sklearn não estava me dando resultados precisos. Depois que adicionei isso ao meu código existente, comecei a receber erros 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)

Além disso, meu modelo era pesado, eu acho, estava recebendo erro de memória após 147, 148 épocas, e então pensei por que não criar funções para as tarefas, então não sei se funciona dessa maneira no tensrorflow, mas pensei que se uma variável local fosse usado e quando fora do escopo ele pode liberar memória e eu defini os elementos acima para treinamento e teste em módulos, consegui atingir 10000 épocas sem problemas, espero que isso ajude.


Estou impressionado com a utilidade do TF, mas também com o uso de memória. No python da CPU, alocando 30 GB ou mais para um trabalho de treinamento no conjunto de dados de flores usado em alguns exemplos 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))

A resposta fornecida foi sinalizada para revisão como uma publicação de baixa qualidade. Aqui estão algumas diretrizes para Como redigir uma boa resposta? . Esta resposta fornecida pode estar correta, mas pode se beneficiar de uma explicação. As respostas apenas de código não são consideradas "boas". Da revisão .
— Trenton McKinney
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.