Skip to content

OP Should Not Have Unused Input

Leo Chen edited this page Apr 2, 2020 · 9 revisions

OP规范:OP中不允许注册未使用的Input


OP Specification: OP Should Not Have Unused Input (English)


规范概要:

  • 第1节,本规范的背景
  • 第2节,本规范的检查方法
  • 第3节,未通过检查的修改建议

补充说明:

  1. 规范在执行过程中,可能会发现现有规范未考虑到的方面,需要在实施过程中不断补充与完善,也请大家积极反馈意见。
  2. 当前白名单中的OP需要进一步确认未通过的原因,对于可通过修改OP代码解决的,需要进行相应的修改。

本规范的背景

目前,Paddle中OP的input是通过OpMaker/GradOpMaker中注册的。然而,部分OP存在着注册了一些input,但实际kernel计算中未使用该input的问题。该问题会导致:

  • 显存(内存)浪费。在显存(内存)回收(GC)/复用等策略中,需要计算引用计数,如果某个variable被设置OP的input,则引用计数会+1,如果该input实际上并未使用,则会导致该input的存活时间变长,不能及时回收或复用。

  • 代码前后不一致。注册Input说明是需要使用的,但是实际上却并未使用。

因此,为了检查提高Paddle的显存(内存)性能,减少OP中未使用的input,提出了本条规范,并在CI中添加了相应的检查方法。

本规范的检查方法

  • 在OpKernel运行前,初始化一个ThreadLocal set,用于记录该OP计算过程中使用的input。 在调用ExecutionContextInput / MultiInputVar / MultiInput / Inputs等接口的时候记录使用的input的name,加入set中。
  • 在OpKernel运行后,将OP的inputs与set进行比较,找出未使用的input。
    • 跳过使用mkldnn的OP,因为mkldnn使用特殊的内存复用方法且运行在CPU,不影响显存。
    • 跳过注册过NoNeedBufferVarsInferer的input,因为这些input不占用显存。
    • 跳过未初始化tensor的input,因为这些input不占用显存。
  • 设置FLAGS_enable_unused_var_check控制该检查的开启和关闭,目前只在PR_CI_Coverage中开启,因为该CI运行的单测较全。
  • 设置一个白名单,记录部分存量问题OP,白名单详见unused_var_check.cc

未通过检查的修改建议

目前已在PR_CI_Coverage中开启本规范的检查,存量问题OP已经修复或加入白名单。 若新增OP或修改OP导致该检查不过,build_log中会出现类似如下记录:

Error Message Summary:
----------------------
PermissionDeniedError: Unused input variables check failed: Operator op_with_unused_var has input(s) not uesed: X, please make sure it(them) is(are) needed. 
If not, remove it(them) from inputs; if yes, register NoNeedBufferVars or add the operator to white list in unused_var_check.h.
  [Hint: Expected unsed_input_var_names.size() == 0, but received unsed_input_var_names.size():1 != 0:0.] at (/Paddle/Paddle/paddle/fluid/framework/unused_var_check.cc:82)

出现问题的原因可以分为三种情况,相应解决方法如下:

  • 该input的dims和tensor在任意情况下都不需要参与计算。
    • 解决方法:从OpMaker中删除该input。
    • 例如PR24107中abs_grad。
  • 该input的dims需要在InferShape或计算时使用,而tensor不需要参与计算。
    • 解决方法:可以注册NoNeedBufferVarsInferer。
    • 例如PR21169中flatten_grad和squeeze_grad。
  • 该input的tensor在某些条件下需要参与计算(在if语句中/或CUDA与CPU计算逻辑不同)。
    • 解决方法:可以加入unused_var_check.cc文件中的白名单。
    • 例如PR21169中将fake_quantize_range_abs_max加入白名单,正是因为FakeQuantizeRangeAbsMaxKernel中涉及if语句,不同条件使用不同input。
    • 白名单的修改需要approval(CI中会提示相应审批人)。

若遇到其他问题,请联系 @zhiqiu

Clone this wiki locally