ChatGPT解决这个技术问题 Extra ChatGPT

如何防止 tensorflow 分配整个 GPU 内存?

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

对于中小型模型,Titan X 的 12 GB 通常足以让 2-3 人在同一个 GPU 上同时运行训练。如果模型足够小,以至于单个模型无法充分利用 GPU 的所有计算单元,那么与一个接一个地运行训练过程相比,这实际上会导致加速。即使在并发访问 GPU 确实会减慢个人训练时间的情况下,让多个用户同时在 GPU 上训练的灵活性仍然很好。

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

有没有办法让 TensorFlow 只分配 4 GB 的 GPU 内存,如果知道这对于给定模型来说已经足够了吗?


m
mrry

您可以通过将 tf.GPUOptions 作为可选 config 参数的一部分传递来设置在构造 tf.Session 时分配的 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 的基础上进行设置。


非常感谢。此信息在当前文档中非常隐藏。我自己永远不会找到它:-) 如果你能回答,我想询问两个额外的信息:1-这是否限制了曾经使用的内存量,或者只是最初分配的内存? (即,如果计算图需要它,它是否仍会分配更多内存) 2- 有没有办法在每个 GPU 的基础上设置它?
相关说明:设置 CUDA_VISIBLE_DEVICES 以将 TensorFlow 限制为单个 GPU 对我有用。请参阅acceleware.com/blog/cudavisibledevices-masking-gpus
似乎内存分配超出了请求,例如我在 24443MiB gpu 上请求了 per_process_gpu_memory_fraction=0.0909 并获得了占用 2627MiB 的进程
我似乎无法让它在 MonitoredTrainingSession 中工作
@jeremy_rutman 我相信这是由于 cudnn 和 cublas 上下文初始化。不过,这仅在您执行使用这些库的内核时才有意义。
S
Sergey Demyanov
config = tf.ConfigProto()
config.gpu_options.allow_growth=True
sess = tf.Session(config=config)

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


这正是我想要的,因为在多用户环境中,在代码本身中指定要保留的确切 GPU 内存量非常不方便。
此外,如果您使用带有 TF 后端的 Keras,您可以使用它并运行 from keras import backend as KK.set_session(sess) 以避免内存限制
M
Mateen Ulhaq

对于 TensorFlow 2.0 和 2.1 (docs):

import tensorflow as tf
tf.config.gpu.set_per_process_memory_growth(True)

对于 TensorFlow 2.2+ (docs):

import tensorflow as tf
gpus = tf.config.experimental.list_physical_devices('GPU')
for gpu in gpus:
  tf.config.experimental.set_memory_growth(gpu, True)

文档还列出了更多方法:

将环境变量 TF_FORCE_GPU_ALLOW_GROWTH 设置为 true。

使用 tf.config.experimental.set_virtual_device_configuration 在虚拟 GPU 设备上设置硬限制。


@AkshayLAradhya 不,这仅适用于 TF 2.0 及更高版本。此处的其他答案适用于 1.13 及更早版本。
不超过。对于 TF 2.2,它是 'tf.config.experimental.set_memory_growth'
由于这是一个高度赞成的答案,我已经更新到最新版本的 TF。
@MateenUlhaq 这里是您可能使用的 Tensorflow 文档的链接:tensorflow.org/api_docs/python/tf/config/experimental/…
第一部分“对于 TensorFlow 2.0 和 2.1...”不准确。它不在引用的文档源中,我有 TF2.0,当我测试它时出现错误。第二部分虽然适用于 TF2.0 和 TF2.2+
u
user1767754

这是本书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 可见 GPU 应分配的内存总量的比例。 注意:不需要释放内存,完成后甚至会加剧内存碎片。

2)分配固定内存:

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

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

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


就您的问题而言,选项 2 可能对您有用。一般来说,如果您没有在 GPU 和动态网络上运行多个应用程序,那么使用“允许增长”选项是有意义的。
C
CATALUNA84

对于 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)

G
GPrathap

上述所有答案都假设使用 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)

M
Mey Khalili

您可以使用

TF_FORCE_GPU_ALLOW_GROWTH=true

在您的环境变量中。

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();
}

m
maxstrobel

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

参考:

https://www.tensorflow.org/versions/r2.0/api_docs/python/tf/config/experimental/set_memory_growth

https://www.tensorflow.org/guide/gpu#limiting_gpu_memory_growth

另请参阅: Tensorflow - 使用 GPUhttps://www.tensorflow.org/guide/gpu

对于 TensorFlow 2.0 Alpha,请参阅: this answer


T
Timbus Calin

上面的所有答案都是指在 TensorFlow 1.X 版本中将内存设置到一定程度,或者在 TensorFlow 2.X 中允许内存增长。

方法 tf.config.experimental.set_memory_growth 确实适用于在分配/预处理期间允许动态增长。尽管如此,人们可能希望从一开始就分配一个特定上限的 GPU 内存。

分配特定 GPU 内存背后的逻辑也是为了防止在训练期间出现 OOM 内存。例如,如果在打开显存消耗 Chrome 选项卡/任何其他视频消耗进程时进行训练,则 tf.config.experimental.set_memory_growth(gpu, True) 可能会导致引发 OOM 错误,因此在某些情况下需要从一开始就分配更多内存。

在 TensorFlow 2.X 中为每个 GPU 分配内存的推荐且正确的方法是通过以下方式完成的:

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)]

我的笔记本有一个专用的 NVIDIA (GForce 920M) 和 2GB RAM。我试过 set_memory_growth 但它不起作用。而且我试图将最大内存限制为 1024MB,但也没有用。所以我尝试了 1.5GB,它成功了。谢谢!
L
Lerner Zhang

无耻插件:如果你安装了GPU支持的Tensorflow,无论你设置为只使用CPU还是GPU,session都会先分配所有GPU。我可能会添加我的提示,即使您将图表设置为仅使用 CPU,您也应该设置相同的配置(如上面回答的:))以防止不必要的 GPU 占用。

在像 IPython 和 Jupyter 这样的交互式界面中,您还应该设置该配置,否则,它将分配所有内存而几乎没有留给其他人。这有时很难注意到。


s
ssp

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

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

S
SunsetQuest

对于 Tensorflow 2.0,此 this solution 对我有用。 (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)

我正在使用 TF-GPU 2.0、Ubuntu 16.04.6、Tesla K80。
@azar - 感谢分享。这在 Ubuntu 和 Windows 上都很有趣。不知何故,我总是认为在接近硬件时问题会有所不同。也许随着时间的推移,这种情况会变得越来越少——也许是件好事。
D
DSBLR
# 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))

提供的答案被标记为低质量帖子以供审核。以下是 How do I write a good answer? 的一些准则。提供的这个答案可能是正确的,但它可以从解释中受益。仅代码答案不被视为“好”答案。从review
K
Kamil Marczak

这段代码对我有用:

import tensorflow as tf
config = tf.compat.v1.ConfigProto()
config.gpu_options.allow_growth = True
session = tf.compat.v1.InteractiveSession(config=config)

I
Imran Ud Din

好吧,我是 tensorflow 的新手,我有 Geforce 740m 或带有 2GB ram 的 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 个 epoch 之后出现内存错误,然后我想为什么不为任务创建函数,所以我不知道它是否在 tensrorflow 中以这种方式工作,但我想如果一个局部变量是使用过,当超出范围时它可能会释放内存,并且我在模块中定义了上述用于训练和测试的元素,我能够毫无问题地实现 10000 个 epoch,我希望这会有所帮助..


我对 TF 的实用性感到惊讶,但也对它的内存使用感到惊讶。在 CPU 上,python 为可能 TF 示例中使用的花卉数据集的训练作业分配了 30GB 左右的空间。疯狂的。
K
Khan

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

pip install tensorflow-gpu==1.8.0