Как помешать тензорному потоку выделить всю память GPU?

283

Я работаю в среде, в которой вычислительные ресурсы используются совместно, то есть у нас есть несколько серверных машин, оснащенных несколькими графическими процессорами Nvidia Titan X на каждой.

Для моделей малого и среднего размера 12 ГБ Titan X обычно достаточно, чтобы 2-3 человека могли одновременно тренироваться на одном и том же графическом процессоре. Если модели достаточно малы, чтобы одна модель не в полной мере использовала все вычислительные единицы графического процессора, это может фактически привести к ускорению по сравнению с запуском одного учебного процесса за другим. Даже в тех случаях, когда одновременный доступ к графическому процессору замедляет индивидуальное время обучения, все же приятно иметь возможность одновременной тренировки нескольких пользователей на графическом процессоре.

Проблема с TensorFlow заключается в том, что по умолчанию он выделяет полный объем доступной памяти GPU при запуске. Даже для небольшой двухслойной нейронной сети я вижу, что все 12 ГБ памяти GPU израсходованы.

Есть ли способ заставить TensorFlow выделять, скажем, 4 ГБ памяти GPU, если известно, что этого достаточно для данной модели?

Фабьен С.
источник

Ответы:

292

Вы можете установить долю памяти GPU, которая будет выделяться при создании a tf.Session, передавая tf.GPUOptionsкак часть необязательного 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))

В per_process_gpu_memory_fractionдействует как жесткий верхняя граница объема памяти GPU , которая будет использоваться в процессе на каждом GPU на той же машине. В настоящее время эта фракция применяется равномерно ко всем графическим процессорам на одном компьютере; нет способа установить это для каждого графического процессора.

mrry
источник
3
Большое спасибо. Эта информация довольно скрыта в текущем документе. Я бы никогда не нашел его сам :-) Если вы можете ответить, я хотел бы попросить две дополнительные информации: 1- Ограничивает ли это когда-либо объем используемой памяти или только изначально выделенную память? (т. е. будет ли он выделять больше памяти, если это потребуется графиком вычислений) 2- Есть ли способ установить это для каждого графического процессора?
Фабьен К.
15
Примечание по теме: настройка CUDA_VISIBLE_DEVICES для ограничения TensorFlow одним GPU работает для меня. См. Acceleware.com/blog/cudavisibledevices-masking-gpus
rd11
2
кажется, что выделение памяти идет немного по запросу, например, я запросил per_process_gpu_memory_fraction = 0.0909 для 24443 МБ графического процессора и получил процессы, принимающие 2627 МБ
jeremy_rutman
2
Я не могу показаться , чтобы получить эту работу вMonitoredTrainingSession
Анжум Сайед
2
@jeremy_rutman Я считаю, что это связано с инициализацией контекста cudnn и cublas. Это актуально, только если вы запускаете ядра, которые используют эти библиотеки.
Даниил
187
config = tf.ConfigProto()
config.gpu_options.allow_growth=True
sess = tf.Session(config=config)

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

Сергей Демьянов
источник
13
Это именно то, что я хочу, потому что в многопользовательской среде очень неудобно указывать точный объем памяти графического процессора для резервирования в самом коде.
xuancong84
4
Кроме того , если вы используете Keras с бекендом TF, вы можете использовать это и запустить from keras import backend as Kи K.set_session(sess)ограничения памяти , остерегайтесь
Oliver
50

Вот выдержка из Книги Deep Learning with TensorFlow

В некоторых случаях желательно, чтобы процесс выделял только подмножество доступной памяти или увеличивал использование памяти только по мере необходимости процесса. TensorFlow предоставляет два параметра конфигурации в сеансе для управления этим. Первая - это allow_growthопция, которая пытается выделить только столько памяти GPU на основе выделения времени выполнения, она начинает выделять очень мало памяти, и когда сеансы запускаются и требуется больше памяти GPU, мы расширяем область памяти GPU, необходимую для TensorFlow. обработать.

1) Разрешить рост: (более гибкий)

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

Второй метод - это per_process_gpu_memory_fractionопция, которая определяет долю общего объема памяти, которая eachдолжна быть выделена видимому графическому процессору. Примечание: освобождение памяти не требуется, это может даже ухудшить фрагментацию памяти, когда закончите.

2) Выделите фиксированную память :

Распределение 40%общей памяти каждого графического процессора только:

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

Примечание. Это полезно только в том случае, если вы действительно хотите связать объем памяти GPU, доступной в процессе TensorFlow.

user1767754
источник
Что касается вашего вопроса, вариант 2 может быть полезен для вас. В общем, если у вас нет нескольких приложений, работающих на GPU и в динамических сетях, то имеет смысл использовать опцию «Разрешить рост».
Аникет
19

Все ответы выше предполагают выполнение с sess.run()вызовом, который становится исключением, а не правилом в последних версиях TensorFlow.

При использовании tf.Estimatorфреймворка (TensorFlow 1.4 и выше) способ передать дробь неявно созданному 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)

Аналогично в режиме Eager (TensorFlow 1.5 и выше),

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

Редактировать: 11-04-2018 Например, если вы хотите использовать tf.contrib.gan.train, то вы можете использовать что-то похожее на ниже:

tf.contrib.gan.gan_train(........, config=conf)
Урс
источник
16

Для Tensorflow версии 2.0 и 2.1 используйте следующий фрагмент :

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

Для предыдущих версий у меня работал следующий фрагмент:

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 и (возможно) вне

API снова изменился. Теперь его можно найти в:

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

Псевдонимы:

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

Ссылки:

Смотрите также: Tensorflow - используйте графический процессор : https://www.tensorflow.org/guide/gpu

для Tensorflow 2.0 Alpha см .: этот ответ

mx_muc
источник
9

Ты можешь использовать

TF_FORCE_GPU_ALLOW_GROWTH=true

в переменных вашего окружения.

В тензорном коде:

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

Бесстыдный плагин: если вы устанавливаете Tensorflow, поддерживаемый графическим процессором, сеанс сначала выделяет все графические процессоры, независимо от того, настроены ли вы на использование только центрального процессора или графического процессора. Я могу добавить мой совет, что даже если вы настроите график для использования только процессора, вы должны установить ту же конфигурацию (как ответ выше :)), чтобы предотвратить нежелательное использование графического процессора.

И в интерактивном интерфейсе, таком как IPython, вы также должны установить эту конфигурацию, в противном случае она выделит всю память и почти не оставит ее для других. Это иногда трудно заметить.

Лернер Чжан
источник
3

Для Tensorflow 2.0 это решение работало для меня. (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
источник
1
Я использую TF-GPU 2.0, Ubuntu 16.04.6, Tesla K80.
азаром
@azar - Спасибо, что поделились. Это интересная проблема в Ubuntu и Windows. Почему-то я всегда думаю, что проблемы разные при приближении к аппаратному обеспечению. Может быть, с течением времени этого становится все меньше, может быть, это хорошо.
Sunsetquest
3

Если вы используете Tensorflow 2, попробуйте следующее:

config = tf.compat.v1.ConfigProto()
config.gpu_options.allow_growth = True
session = tf.compat.v1.Session(config=config)
Moosefeather
источник
работа для Tensorflow 2
Мобин Альхассан
1

я пытался обучить unet на наборе данных вокала, но из-за огромного размера изображения память заканчивалась. Я попробовал все вышеупомянутые советы, даже попробовал с размером партии == 1, но без улучшения. иногда версия TensorFlow также вызывает проблемы с памятью. попробуйте с помощью

pip install tenorflow-gpu == 1.8.0

хан
источник
1

Ну, я новичок в tenorflow, у меня есть Geforce 740m или что-то вроде GPU с 2 Гб оперативной памяти, я запускал рукописный пример mnist для родного языка с обучающими данными, содержащими 38700 изображений и 4300 тестовых изображений, и пытался получить точность, вспомним, F1, использующий следующий код в качестве sklearn, не давал мне точных результатов. как только я добавил это в свой существующий код, я начал получать ошибки графического процессора.

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)

Кроме того, моя модель была тяжелой, я думаю, я получал ошибку памяти после 147, 148 эпох, а затем я подумал, почему бы не создать функции для задач, поэтому я не знаю, работает ли он таким образом в tensrorflow, но я подумал, если локальная переменная использовался, и когда он выходит из области видимости, он может освободить память, и я определил вышеупомянутые элементы для обучения и тестирования в модулях, я смог достичь 10000 эпох без каких-либо проблем, я надеюсь, что это поможет ..

Имран Уд Дин
источник
Я поражен утилитой TF, а также ее использованием памяти. На питоне ЦП выделяется 30 ГБ или около того для учебной работы с набором данных цветов, использованным в майских примерах TF. Безумный.
Эрик М
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
источник
Предоставленный ответ был помечен для просмотра как сообщение низкого качества. Вот несколько рекомендаций о том, как мне написать хороший ответ? , Этот предоставленный ответ может быть правильным, но это могло бы извлечь выгоду из объяснения. Ответы только кода не считаются "хорошими" ответами. Из обзора .
Трентон МакКинни