如何防止张量流分配GPU内存的总量?


281

我在共享计算资源的环境中工作,即,我们有几台服务器计算机,每台服务器计算机都配备了一些Nvidia Titan X GPU。

对于中小型型号,Titan X的12 GB通常足以让2-3个人在同一GPU上同时进行训练。如果模型足够小,以至于单个模型无法充分利用GPU的所有计算单元,那么与运行一个训练过程之后再执行另一个训练过程相比,这实际上可以提高速度。即使在同时访问GPU确实减慢了单个训练时间的情况下,具有让多个用户同时在GPU上进行训练的灵活性仍然很好。

TensorFlow的问题在于,默认情况下,它在启动时会分配全部可用的GPU内存。即使对于小型的两层神经网络,我也看到所有12 GB的GPU内存都已用完。

如果有人知道这足以满足给定模型的需求,是否有办法使TensorFlow仅分配4 GB的GPU内存?

Answers:


292

您可以tf.Session通过传递a tf.GPUOptions作为可选config参数的一部分来设置构造a时要分配的GPU内存的比例:

# 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内存量的硬上限。当前,这部分被均匀地应用于同一台机器上的所有GPU。无法基于每个GPU进行设置。


3
非常感谢你。该信息在当前文档中相当隐蔽。我永远不会一个人找到它:-)如果您可以回答,我想问两个附加信息:1-这是否限制了曾经使用的内存量,或者只是限制了最初分配的内存?(即,如果计算图需要它,它将仍然分配更多的内存)2-是否可以在每个GPU的基础上进行设置?
Fabien C.

15
相关说明:设置CUDA_VISIBLE_DEVICES以将TensorFlow限制为单个GPU对我有用。参见acceleware.com/blog/cudavisibledevices-masking-gpus
rd11'1

2
似乎内存分配超出了请求的范围,例如,我在24443MiB gpu上请求了per_process_gpu_memory_fraction = 0.0909,并获得了采用2627MiB的进程
jeremy_rutman

2
我似乎无法得到这个工作的MonitoredTrainingSession
Anjum赛义德

2
@jeremy_rutman我相信这是由于cudnn和cublas上下文初始化引起的。这仅在您正在执行使用这些库的内核时才有意义。
丹尼尔(Daniel)

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

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


13
这正是我想要的,因为在多用户环境中,在代码本身中指定要保留的GPU内存的确切数量非常不便。
xuancong84

4
另外,如果您将Keras与TF后端一起使用,则可以使用它并运行from keras import backend as KK.set_session(sess)避免内存限制
Oliver

50

这是本书的摘录 Deep Learning with TensorFlow

在某些情况下,希望该过程仅分配可用内存的子集,或者仅增加该过程所需的内存使用量。TensorFlow 在会话中提供了两个配置选项来控制它。第一个是该allow_growth选项,它尝试根据运行时分配仅分配尽可能多的GPU内存,它开始时分配的内存很少,并且随着会话的运行和需要更多GPU内存,我们扩展了TensorFlow所需的GPU内存区域处理。

1)允许增长:(更灵活)

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

第二种方法是per_process_gpu_memory_fraction选项,它确定each应分配可见GPU 的内存总量的一部分。注意:不需要释放内存,完成后甚至会加剧内存碎片。

2)分配固定内存

仅通过以下方式分配40%每个GPU的总内存:

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

注意: 这仅在您真正想绑定TensorFlow进程上可用的GPU内存量时有用。


就您的问题而言,选项2可能对您有用。通常,如果您没有在GPU和动态网络上运行多个应用程序,则可以使用“允许增长”选项。
aniket


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)

同样在“急切”模式(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-使用GPUhttps : //www.tensorflow.org/guide/gpu

对于Tensorflow 2.0 Alpha,请参阅: 此答案


8

您可以使用

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

无耻插件:如果安装了GPU支持的Tensorflow,则无论您将其设置为仅使用CPU还是GPU,该会话都会首先分配所有GPU。我可能会补充一点,即使您将图形设置为仅使用CPU,也应该设置相同的配置(如上回答:)),以防止不必要的GPU占用。

并且在类似IPython的交互式界面中,您还应该设置configure,否则它将分配所有内存,而几乎不分配给其他人。有时很难注意到。


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)

1
我正在使用TF-GPU 2.0,Ubuntu 16.04.6,Tesla K80。
阿扎尔

@azar-感谢您的分享。这在Ubuntu和Windows上都是同样有趣的问题。不知何故,我总是认为在接近硬件时问题是不同的。随着时间的流逝,这种情况可能会越来越少-也许是一件好事。
Sunsetquest

2

如果您使用的是Tensorflow 2,请尝试以下操作:

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

1

我尝试对voc数据集进行unet训练,但是由于巨大的图像大小,内存完成了。我尝试了上述所有技巧,甚至尝试使用批处理大小== 1,但没有任何改善。有时TensorFlow版本也会导致内存问题。尝试使用

点安装tensorflow-gpu == 1.8.0


1

好吧,我是tensorflow的新手,我有Geforce 740m或具有2GB内存的GPU,我正在运行mnist手写的本地语言示例,其训练数据包含38700张图像和4300张测试图像,并试图获得精度,召回率, F1使用以下代码作为sklearn并没有给我精确的结果。一旦将其添加到现有代码中,我就开始出现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)

再加上我的模型很沉重,我想我在147个,148个纪元后出现内存错误,然后我想为什么不为这些任务创建函数,所以我不知道它是否在tensrorflow中以这种方式工作,但是我想如果局部变量是使用,并且超出范围可能释放内存,并且我在模块中定义了用于培训和测试的上述元素,我能够实现10000个纪元而没有任何问题,希望对您有所帮助。


我对TF的实用程序感到惊讶,但也对它的内存使用感到惊讶。在CPU上,python分配了30GB左右的空间用于May TF示例中使用的flowers数据集上的训练作业。疯。
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))

提供的答案被标记为低质量帖子,以供审核。以下是一些有关如何编写好的答案的指导原则。提供的答案可能是正确的,但可以从解释中受益。仅代码答案不视为“好”答案。从审查
特伦顿·麦金尼
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.