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?

Fabien C.
fonte

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.

mrry
fonte
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

Sergey Demyanov
fonte
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.

user1767754
fonte
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)
Urs
fonte
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)
Anurag
fonte
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

mx_muc
fonte
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();
}
Mey Khalili
fonte
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.

Lerner Zhang
fonte
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)
Sunsetquest
fonte
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)
Moosefeather
fonte
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

Khan
fonte
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.

Imran Ud Din
fonte
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))
DSBLR
fonte
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