Как помешать тензорному потоку выделить всю память GPU?
Я работаю в среде, в которой вычислительные ресурсы используются совместно, то есть у нас есть несколько серверных машин, на каждом из которых установлено несколько графических процессоров Nvidia Titan X.
Для моделей малого и среднего размера, 12 ГБ Titan X обычно достаточно, чтобы 2-3 человека могли одновременно тренироваться на одном и том же графическом процессоре. Если модели достаточно малы, чтобы одна модель не в полной мере использовала все вычислительные единицы Titan X, это может привести к ускорению по сравнению с запуском одного учебного процесса за другим. Даже в тех случаях, когда одновременный доступ к графическому процессору замедляет индивидуальное время обучения, по-прежнему приятно иметь гибкость, когда несколько пользователей одновременно запускают программы на графических процессорах.
Проблема с TensorFlow заключается в том, что по умолчанию он выделяет полный объем доступной памяти на GPU при запуске. Даже для небольшой двухслойной нейронной сети я вижу, что 12 ГБ Титана X израсходованы.
Есть ли способ заставить TensorFlow выделять, скажем, только 4 ГБ памяти графического процессора, если известно, что этого количества достаточно для данной модели?
6 ответов
Вы можете установить долю памяти GPU, которая будет выделена при создании 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
действует как жесткая верхняя граница объема памяти графического процессора, который будет использоваться процессом на каждом графическом процессоре на той же машине. В настоящее время эта фракция применяется равномерно ко всем графическим процессорам на одном компьютере; нет способа установить это для каждого графического процессора.
config = tf.ConfigProto()
config.gpu_options.allow_growth=True
sess = tf.Session(config=config)
Обновлено для TensorFlow 2.0 Alpha и выше
Из 2.0 Alpha docs ответ теперь - всего одна строка, прежде чем что-то делать с TensorFlow:
import tensorflow as tf
tf.config.gpu.set_per_process_memory_growth(True)
Вот выдержка из Книги 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.
Для 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)
Все ответы выше предполагают выполнение с sess.run()
вызов, который становится исключением, а не правилом в последних версиях TensorFlow.
При использовании tf.Estimator
Framework (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)
Вы можете использовать
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();
}
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
- tf.config.experimental.set_memory_growth
https://www.tensorflow.org/versions/r2.0/api_docs/python/tf/config/experimental/set_memory_growth https://www.tensorflow.org/beta/guide/using_gpu
Все приведенные выше ответы относятся либо к настройке памяти в определенной степени в TensorFlow 1.X
версии или разрешить увеличение памяти в TensorFlow 2.X
.
Метод tf.config.experimental.set_memory_growth
действительно работает для обеспечения динамического роста во время выделения / предварительной обработки. Тем не менее, можно с самого начала выделить определенную память GPU.
Логика выделения определенной памяти графического процессора также должна заключаться в предотвращении использования памяти OOM во время тренировок. Например, если вы тренируетесь при открытии видеопамяти с использованием вкладок Chrome,tf.config.experimental.set_memory_growth(gpu, True)
может привести к появлению ошибок OOM, следовательно, в некоторых случаях необходимо с самого начала выделить больше памяти.
Рекомендуемый и правильный способ выделения памяти для каждого графического процессора в TensorFlow 2.X выполняется следующим образом:
gpus = tf.config.experimental.list_physical_devices('GPU')
if gpus:
# Restrict TensorFlow to only allocate 1GB of memory on the first GPU
try:
tf.config.experimental.set_virtual_device_configuration(
gpus[0],
[tf.config.experimental.VirtualDeviceConfiguration(memory_limit=1024)]
Бесстыдный плагин: если вы устанавливаете Tensorflow, поддерживаемый графическим процессором, сеанс сначала выделяет все графические процессоры, независимо от того, настроены ли вы на использование только центрального процессора или графического процессора. Я могу добавить мой совет, что даже если вы настроите график для использования только процессора, вы должны установить ту же конфигурацию (как ответ выше:)), чтобы предотвратить нежелательное использование графического процессора.
И в интерактивном интерфейсе, таком как IPython, вы также должны установить эту конфигурацию, в противном случае она будет выделять всю память и почти не оставлять ее другим. Это иногда трудно заметить.
Если вы используете Tensorflow 2, попробуйте следующее:
config = tf.compat.v1.ConfigProto()
config.gpu_options.allow_growth = True
session = tf.compat.v1.Session(config=config)
Для 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)
# 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))
Этот код сработал для меня:
import tensorflow as tf
config = tf.compat.v1.ConfigProto()
config.gpu_options.allow_growth = True
session = tf.compat.v1.InteractiveSession(config=config)
Ну, я новичок в 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 эпох без каких-либо проблем, я надеюсь, что это поможет..
Я попытался обучить unet на наборе данных вокала, но из-за огромного размера изображения память заканчивается Я попробовал все вышеупомянутые советы, даже попробовал с размером партии ==1, но без улучшения. иногда версия TensorFlow также вызывает проблемы с памятью. попробуйте с помощью
pip install tenorflow-gpu==1.8.0