Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
PaddlePaddle
FluidDoc
提交
a7763adb
F
FluidDoc
项目概览
PaddlePaddle
/
FluidDoc
通知
5
Star
2
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
23
列表
看板
标记
里程碑
合并请求
111
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
F
FluidDoc
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
23
Issue
23
列表
看板
标记
里程碑
合并请求
111
合并请求
111
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
提交
a7763adb
编写于
6月 27, 2019
作者:
Z
Zeng Jinle
提交者:
xsrobin
6月 27, 2019
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Update memory_optimize.rst (#919)
* update memory_optimize.rst, test=develop * follow comment, fix typo, test=develop
上级
54dac895
变更
3
隐藏空白更改
内联
并排
Showing
3 changed file
with
121 addition
and
49 deletion
+121
-49
doc/fluid/advanced_usage/best_practice/index_cn.rst
doc/fluid/advanced_usage/best_practice/index_cn.rst
+1
-0
doc/fluid/advanced_usage/best_practice/memory_optimize.rst
doc/fluid/advanced_usage/best_practice/memory_optimize.rst
+120
-0
doc/fluid/api_guides/low_level/memory_optimize.rst
doc/fluid/api_guides/low_level/memory_optimize.rst
+0
-49
未找到文件。
doc/fluid/advanced_usage/best_practice/index_cn.rst
浏览文件 @
a7763adb
...
...
@@ -7,3 +7,4 @@
cpu_train_best_practice.rst
dist_training_gpu.rst
memory_optimize.rst
doc/fluid/advanced_usage/best_practice/memory_optimize.rst
0 → 100644
浏览文件 @
a7763adb
.. _api_guide_memory_optimize:
###########
显存分配与优化
###########
PaddlePaddle的显存分配策略
========================
由于原生的CUDA系统调用 :code:`cudaMalloc` 和 :code:`cudaFree` 均是同步操作,非常耗时。因此与许多框架类似,PaddlePaddle采用了显存预分配的策略加速显存分配。具体方式为:
- 在分配requested_size大小的显存时,
- 若requested_size <= chunk_size,则框架会预先分配chunk_size大小的显存池chunk,并从chunk中分出requested_size大小的块返回。之后每次申请显存都会从chunk中分配。
- 若requested_size > chunk_size,则框架会直接调用 :code:`cudaMalloc` 分配requested_size大小的显存返回。
- 在释放free_size大小的显存时,
- 若free_size <= chunk_size,则框架会将该显存放回预分配的chunk中,而不是直接返回给CUDA。
- 若free_size > chunk_size,则框架会直接调用 :code:`cudaFree` 将显存返回给CUDA。
上述的chunk_size由环境变量 :code:`FLAGS_fraction_of_gpu_memory_to_use` 确定,chunk_size的计算公式为:
.. code-block:: python
chunk_size = FLAGS_fraction_of_gpu_memory_to_use * 单张GPU卡的总显存
:code:`FLAGS_fraction_of_gpu_memory_to_use` 的默认值为0.92,即框架预先分配显卡92%的显存。
若你的GPU卡上有其他任务占用显存,你可以适当将 :code:`FLAGS_fraction_of_gpu_memory_to_use` 减少,保证框架能预分配到合适的chunk,例如:
.. code-block:: shell
export FLAGS_fraction_of_gpu_memory_to_use=0.4 # 预先40%的GPU显存
若 :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的显存优化策略
========================
PaddlePaddle提供了多种通用显存优化方法,优化你的网络的显存占用。
GC策略: 显存垃圾及时回收
====================
GC(Garbage Collection)的原理是在网络运行阶段及时释放无用变量的显存空间,达到节省显存的目的。GC适用于使用Executor,ParallelExecutor做模型训练/预测的场合。
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` 。
若 :code:`FLAGS_eager_delete_tensor_gb=0` ,则一旦有显存垃圾则马上回收,最为节省显存。
若 :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` 。
若 :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=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操作的输出和输入可复用同一片显存空间。
Inplace策略适用于使用ParallelExecutor或CompiledProgram+with_data_parallel的场合,通过 :code:`BuildStrategy` 设置。
具体方式为:
.. code-block:: python
build_strategy = fluid.BuildStrategy()
build_strategy.enable_inplace = True # 开启Inplace策略
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,则必须设置:
.. code-block:: python
loss.persistable = True
acc.persistable = True
MemoryOptimize策略: 跨Op间的显存复用(不推荐)
========================================
MemoryOptimize策略的原理是当前Op的输出变量复用前继Op的无用变量空间。由于MemoryOptimize策略会延长显存空间的生命周期,这部分复用的显存可能无法及时释放,导致显存峰值升高,因此不建议用户使用该开关。
由于历史原因,PaddlePaddle提供了2个MemoryOptimize接口:
- :code:`BuildStrategy` 中的 :code:`memory_optimize` :设置 :code:`build_strategy.memory_optimize=True` 开启MemoryOptimize策略。
- :code:`fluid.memory_optimize()` 接口:**该接口已废弃,不建议用户使用!**
与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` 。
doc/fluid/api_guides/low_level/memory_optimize.rst
已删除
100644 → 0
浏览文件 @
54dac895
.. _api_guide_memory_optimize:
#####
显存优化
#####
显存优化是通过分析、复用 :code:`Program` 中 :code:`Variable` 使用的显存,从而降低 :code:`Program` 执行时显存消耗的方法。用户可以通过Python脚本调用 :code:`memory_optimize` 接口进行显存优化,显存优化的执行策略如下:
- 首先根据 :code:`Program` 中 :code:`Operator` 之间的关系对 :code:`Variable` 的最后存活时间进行分析,得到每个 :code:`Variable` 的最后存活时间;
- 其次根据每个 :code:`Variable` 的最后存活时间,我们将到达存活时间、不再存活的 :code:`Variable` 所占用的显存提供给后来的 :code:`Variable` 使用。
.. code-block:: python
z = fluid.layers.sum([x, y])
m = fluid.layers.matmul(y, z)
在这个示例中,:code:`x` 的存活时间到 :code:`fluid.layers.sum` 操作为止,所以它的显存可以被 :code:`m` 复用。
针对特定部分禁用显存优化
===========
:code:`memory_optimize` 支持针对特定部分禁用显存优化,用户可以通过传入 :code:`Variable` 名字的集合来指定哪些 :code:`Variable` 所使用的显存不会被复用;
与此同时,:code:`memory_optimize` 能够针对网络的反向部分禁用显存优化,用户可以通过传入 :code:`skip_grads` 参数来开启这个功能。
.. code-block:: python
fluid.memory_optimize(fluid.default_main_program(),
skip_opt_set=("fc"), skip_grads=True)
在这个示例中,:code:`fluid.memory_optimize` 接口对默认的 :code:`Program` 进行了 :code:`Variable` 最后存活时间的分析,并跳过了名字为 :code:`fc` 的 :code:`Variable` 以及网络反向部分的所有 :code:`Variable` 。
这部分 :code:`Variable` 的显存都不会被别的 :code:`Variable` 再次使用。
指定显存优化等级
===========
:code:`memory_optimize` 支持打印显存复用的信息以方便用户进行调试,用户可以通过指定 :code:`print_log=True` 来开启显存复用的调试信息;
:code:`memory_optimize` 支持两种显存优化的等级,:code:`0` 或者 :code:`1` :
- 优化等级为 :code:`0` 时: :code:`memory_optimize` 在分析完 :code:`Variable` 的最后生存时间后,会判断 :code:`Variable` 的 :code:`shape` ,只有 :code:`shape` 相同的 :code:`Variable` 才会进行显存复用;
- 优化等级为 :code:`1` 时: :code:`memory_optimize` 会尽可能地进行显存复用,在分析完 :code:`Variable` 的最后生存时间后,即使是 :code:`shape` 不同的 :code:`Variable` 也会进行最大程度的显存复用。
.. code-block:: python
fluid.memory_optimize(fluid.default_main_program(),
level=0, print_log=True)
在这个示例中,:code:`fluid.memory_optimize` 接口对默认的 :code:`Program` 进行了 :code:`Variable` 最后存活时间的分析。
只有 :code:`shape` 完全相同的 :code:`Variable` 才会进行显存复用,并且在分析结束后,会打印出所有显存复用相关的调试信息。
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录