未验证 提交 5b0bec40 编写于 作者: Z Zeng Jinle 提交者: GitHub

Refine memory_optimize_doc (#1432)

* refine memory_optimize_doc, test=develop

* follow xiaoguang's comments, test=develop
上级 b8780798
.. _api_guide_memory_optimize:
###########
显存分配与优化
存储分配与优化
###########
PaddlePaddle的显存分配策略
========================
1. PaddlePaddle的显存分配策略
===========================
由于原生的CUDA系统调用 :code:`cudaMalloc` 和 :code:`cudaFree` 均是同步操作,非常耗时。因此与许多框架类似,PaddlePaddle采用了显存预分配的策略加速显存分配。具体方式为:
1.1. 显存预分配策略
----------------
由于原生的CUDA系统调用 :code:`cudaMalloc` 和 :code:`cudaFree` 均是同步操作,非常耗时。因此PaddlePaddle采用了显存预分配的策略加速显存分配。具体方式为:
- 在分配requested_size大小的显存时,
- 若requested_size <= chunk_size,则框架会预先分配chunk_size大小的显存池chunk,并从chunk中分出requested_size大小的块返回。之后每次申请显存都会从chunk中分配。
......@@ -21,10 +24,9 @@ PaddlePaddle的显存分配策略
.. code-block:: python
chunk_size = FLAGS_fraction_of_gpu_memory_to_use * 单张GPU卡的总显存
chunk_size = FLAGS_fraction_of_gpu_memory_to_use * 单张GPU卡的当前可用显存值
:code:`FLAGS_fraction_of_gpu_memory_to_use` 的默认值为0.92,即框架预先分配显卡92%的显存
:code:`FLAGS_fraction_of_gpu_memory_to_use` 的默认值为0.92,即框架预先分配显卡92%的当前可用显存值
若你的GPU卡上有其他任务占用显存,你可以适当将 :code:`FLAGS_fraction_of_gpu_memory_to_use` 减少,保证框架能预分配到合适的chunk,例如:
......@@ -35,49 +37,82 @@ PaddlePaddle的显存分配策略
若 :code:`FLAGS_fraction_of_gpu_memory_to_use` 设为0,则每次显存分配和释放均会调用 :code:`cudaMalloc` 和 :code:`cudaFree` ,会严重影响性能,不建议你使用。
只有当你想测量网络的实际显存占用量时,你可以设置 :code:`FLAGS_fraction_of_gpu_memory_to_use` 为0,观察nvidia-smi显示的显存占用情况。
PaddlePaddle的显存优化策略
========================
1.2. 显存自增长AutoGrowth策略
--------------------------
在1.6+的版本中,PaddlePaddle支持显存自增长AutoGrowth策略,按需分配显存。若您希望按需分配显存,您可选择使用显存自增长AutoGrowth策略。
在前几次显存分配时,会调用 :code:`cudaMalloc` 按需分配,但释放时不会调用 :code:`cudaFree` 返回给GPU,而是在框架内部缓存起来。
在随后的显存分配时,会首先检查缓存的显存中是否有合适的块,若有则从中分割出所需的显存空间返回,否则才调用 :code:`cudaMalloc` 直接从GPU中分配。随后的显存释放亦会缓存起来供后续分配使用。
因此,显存自增长AutoGrowth策略会在前几个batch训练时分配较慢(因为频繁调用 :code:`cudaMalloc` ),在随后训练过程中基本不会影响模型训练速度。
显存自增长AutoGrowth策略通过设置环境变量 :code:`FLAGS_allocator_strategy` 开启,设置方式为:
.. code-block:: shell
export FLAGS_allocator_strategy=auto_growth
对应地,显存预分配策略通过以下方法开启:
.. code-block:: shell
export FLAGS_allocator_strategy=naive_best_fit
环境变量 :code:`FLAGS_allocator_strategy` 的默认值为naive_best_fit,表示默认使用显存预分配策略。
PaddlePaddle提供了多种通用显存优化方法,优化你的网络的显存占用。
GC策略: 显存垃圾及时回收
====================
2. PaddlePaddle的存储优化策略
===========================
GC(Garbage Collection)的原理是在网络运行阶段及时释放无用变量的显存空间,达到节省显存的目的。GC适用于使用Executor,ParallelExecutor做模型训练/预测的场合。
PaddlePaddle提供了多种通用存储优化方法,优化你的网络的存储占用(包括显存和内存)。
2.1. GC策略: 存储垃圾及时回收
-------------------------
GC(Garbage Collection)的原理是在网络运行阶段及时释放无用变量的存储空间,达到节省存储空间的目的。GC适用于使用Executor,ParallelExecutor做模型训练/预测的场合,但不适用于C++预测库接口。
**GC策略已于1.6+版本中默认开启。**
GC策略由三个环境变量控制:
- :code:`FLAGS_eager_delete_tensor_gb`
GC策略的使能开关,double类型,默认值为-1。GC策略会积攒一定大小的显存垃圾后再统一释放,:code:`FLAGS_eager_delete_tensor_gb` 控制的是显存垃圾的阈值,单位是GB。**建议用户设置** :code:`FLAGS_eager_delete_tensor_gb=0` 。
GC策略的使能开关,double类型,在<1.6的版本中默认值为-1,在1.6+版本中默认值为0。GC策略会积攒一定大小的存储垃圾后再统一释放,:code:`FLAGS_eager_delete_tensor_gb` 控制的是存储垃圾的阈值,单位是GB。**建议用户设置** :code:`FLAGS_eager_delete_tensor_gb=0` 。
若 :code:`FLAGS_eager_delete_tensor_gb=0` ,则一旦有显存垃圾则马上回收,最为节省显存
若 :code:`FLAGS_eager_delete_tensor_gb=0` ,则一旦有存储垃圾则马上回收,最为节省存储空间
若 :code:`FLAGS_eager_delete_tensor_gb=1` ,则显存垃圾积攒到1G后才触发回收。
若 :code:`FLAGS_eager_delete_tensor_gb=1` ,则存储垃圾积攒到1G后才触发回收。
若 :code:`FLAGS_eager_delete_tensor_gb<0` ,则GC策略关闭。
- :code:`FLAGS_memory_fraction_of_eager_deletion`
GC策略的调节flag,double类型,默认值为1,范围为[0,1],仅适用于使用ParallelExecutor或CompiledProgram+with_data_parallel的场合。
GC内部会根据变量占用的显存大小,对变量进行降序排列,且仅回收前 :code:`FLAGS_memory_fraction_of_eager_deletion` 大的变量显存。**建议用户维持默认值**,即 :code:`FLAGS_memory_fraction_of_eager_deletion=1` 。
GC内部会根据变量占用的存储空间大小,对变量进行降序排列,且仅回收前 :code:`FLAGS_memory_fraction_of_eager_deletion` 大的变量的存储空间。**建议用户维持默认值**,即 :code:`FLAGS_memory_fraction_of_eager_deletion=1` 。
若 :code:`FLAGS_memory_fraction_of_eager_deletion=0.6` ,则表示仅回收存储占用60%大的变量的存储空间。
若 :code:`FLAGS_memory_fraction_of_eager_deletion=0.6` ,则表示仅回收显存占用60%大的变量显存
若 :code:`FLAGS_memory_fraction_of_eager_deletion=0` ,则表示不回收任何变量的存储空间,GC策略关闭
若 :code:`FLAGS_memory_fraction_of_eager_deletion=0` ,则表示不回收任何变量的显存,GC策略关闭
若 :code:`FLAGS_memory_fraction_of_eager_deletion=1` ,则表示回收所有变量的存储空间
若 :code:`FLAGS_memory_fraction_of_eager_deletion=1` ,则表示回收所有变量的显存。
- :code:`FLAGS_fast_eager_deletion_mode`
快速GC策略的开关,bool类型,默认值为True,表示使用快速GC策略。快速GC策略会不等待CUDA Kernel结束直接释放显存。**建议用户维持默认值**,即 :code:`FLAGS_fast_eager_deletion_mode=True` 。
Inplace策略: Op内部的输出复用输入
=============================
Inplace策略的原理是Op的输出复用Op输入的显存空间。例如,reshape操作的输出和输入可复用同一片显存空间。
2.2. Inplace策略: Op内部的输出复用输入
----------------------------------
Inplace策略的原理是Op的输出复用Op输入的存储空间。例如,reshape操作的输出和输入可复用同一片存储空间。
Inplace策略适用于使用ParallelExecutor或CompiledProgram+with_data_parallel的场合,通过 :code:`BuildStrategy` 设置。
Inplace策略适用于使用ParallelExecutor或CompiledProgram+with_data_parallel的场合,通过 :code:`BuildStrategy` 设置。此策略不支持使用Executor+Program做单卡训练、使用C++预测库接口等场合。
**Inplace策略已于1.6+版本中默认开启。**
具体方式为:
......@@ -89,32 +124,26 @@ Inplace策略适用于使用ParallelExecutor或CompiledProgram+with_data_paralle
compiled_program = fluid.CompiledProgram(train_program)
.with_data_parallel(loss_name=loss.name, build_strategy=build_strategy)
由于目前设计上的一些问题,在开启Inplace策略后,必须保证后续exe.run中fetch_list的变量是persistable的,即假如你后续需要fetch的变量为loss和acc,则必须设置:
在<1.6的版本中,由于设计上的一些问题,在开启Inplace策略后,必须保证后续exe.run中fetch_list的变量是persistable的,即假如你后续需要fetch的变量为loss和acc,则必须设置:
.. code-block:: python
loss.persistable = True
acc.persistable = True
MemoryOptimize策略: 跨Op间的显存复用(不推荐)
========================================
MemoryOptimize策略的原理是当前Op的输出变量复用前继Op的无用变量空间。由于MemoryOptimize策略会延长显存空间的生命周期,这部分复用的显存可能无法及时释放,导致显存峰值升高,因此不建议用户使用该开关。
由于历史原因,PaddlePaddle提供了2个MemoryOptimize接口:
**在1.6+的版本中,无需设置fetch变量为persistable。**
- :code:`BuildStrategy` 中的 :code:`memory_optimize` :设置 :code:`build_strategy.memory_optimize=True` 开启MemoryOptimize策略。
- :code:`fluid.memory_optimize()` 接口:**该接口已废弃,不建议用户使用!**
3. 存储优化Best Practice
=======================
与Inplace策略相同,开启MemoryOptimize策略时同样要保证后续exe.run中fetch_list的变量是persistable的。
显存优化Best Practice
====================
我们推荐你的最佳显存优化策略为:
我们推荐你的最佳存储优化策略为:
- 开启GC策略:设置 :code:`FLAGS_eager_delete_tensor_gb=0` 。
- 开启Inplace策略:设置 :code:`build_strategy.enable_inplace = True` ,并设置fetch_list中的 :code:`var.persistable = True` 。
- 开启Inplace策略:设置 :code:`build_strategy.enable_inplace = True` ,并在<1.6版本中设置fetch_list中的 :code:`var.persistable = True` 。
**在1.6+的版本中,上述最佳策略均已默认打开,无需手动配置,亦无需设置fetch_list变量为persistable。**
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册