【问题标题】:How to prevent tensorflow from allocating the totality of a GPU memory?如何防止 tensorflow 分配整个 GPU 内存?
【发布时间】:2016-03-15 22:21:36
【问题描述】:

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

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

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

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

【问题讨论】:

    标签: python tensorflow tensorflow2.0 tensorflow2.x nvidia-titan


    【解决方案1】:

    您可以通过将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 上下文初始化。这仅在您执行使用这些库的内核时才相关。
    【解决方案2】:
    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) 以避免内存限制
    【解决方案3】:

    对于 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/…
    • 第一部分“For TensorFlow 2.0 and 2.1...”不准确。它不在引用的文档源中,我有 TF2.0,当我测试它时出现错误。第二部分虽然适用于 TF2.0 和 TF2.2+
    【解决方案4】:

    这是本书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 和动态网络上运行多个应用程序,那么使用“允许增长”选项是有意义的。
    【解决方案5】:

    对于 Tensorflow 2.0 和 2.1 版本,请使用以下 sn-p

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

    对于以前的版本,以下 sn-p 曾经为我工作:

    import tensorflow as tf
    tf_config=tf.ConfigProto()
    tf_config.gpu_options.allow_growth=True
    sess = tf.Session(config=tf_config)
    

    【讨论】:

      【解决方案6】:

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

      【讨论】:

        【解决方案7】:

        你可以使用

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

        【讨论】:

          【解决方案8】:

          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,请参阅: this answer

          【讨论】:

            【解决方案9】:

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

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

            【讨论】:

              【解决方案10】:

              以上所有答案都是指在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 并且成功了。谢谢!
              【解决方案11】:

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

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

              【讨论】:

                【解决方案12】:

                对于 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 上都很有趣。不知何故,我总是认为在接近硬件时问题会有所不同。也许随着时间的推移,这种情况会越来越少——也许是件好事。
                【解决方案13】:
                # 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
                【解决方案14】:

                这段代码对我有用:

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

                【讨论】:

                  【解决方案15】:

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

                  【讨论】:

                  • 我对 TF 的实用性以及它的内存使用感到惊讶。在 CPU 上,python 为可能 TF 示例中使用的花卉数据集的训练作业分配了 30GB 左右的空间。疯了。
                  【解决方案16】:

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

                  pip install tensorflow-gpu==1.8.0

                  【讨论】:

                    猜你喜欢
                    • 2017-11-13
                    • 2019-04-07
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 2019-08-29
                    • 1970-01-01
                    相关资源
                    最近更新 更多