Created by: chenwhql
Print Transformer
print
在PY2和PY3中存在诸多不同之处,详见代码中单测
转换前代码示例:
def dyfunc_print_variable(x):
x_v = fluid.dygraph.to_variable(x)
# NOTE: transform to static code, var name will be changed
print(x_v)
转换后代码示例:
def dyfunc_print_variable(x):
x_v = fluid.layers.assign(x)
fluid.layers.Print(x_v)
Print Variable的格式变化
修改前
- 原格式,无论哪个都无法令人满意
- 最重要的是,两种打印格式无法统一
print(VarBase)
name generated_var_0, dtype: VarType.INT32 shape: [5] lod: {}
dim: 5
layout: NCHW
dtype: int
data: [1 1 1 1 1]
问题包括但不限于:
- lod位置突兀
- 两个dtype,重复
- shape和dim重复
- 缺少place信息
- 整体信息混乱
layers.Print(Variable)示例
1587219215 The place is:CUDAPlace(0)
Tensor[assign_0.tmp_0]
shape: [5,]
dtype: i
data: 1,1,1,1,1,
问题包括但不限于:
- time打出来有多大意义
- message参数没有会导致第一行中间两个\t\t,不美观
- dtype的name没有demangle转换,导致int显示为i,当然其他类型也会显示有问题
- 没有layout
- 细节处理糟糕,最后的逗号对强迫症患者不友好
修改后
修改要点:
- print(VarBase)和layers.Print(Variable)主要都是打印类型为LoDTensor的Variable,在LoDTensor上结果格式应该统一
-
\t
统一转换成-
,\t
有时候是4个空格,有时候是8个,不美观 - 如果lod为空,就不打印了
- 统一成如下格式:
Variable: (Name)
- lod: ***
- place: ***
- shape: ***
- layout: ***
- dtype: ***
- data: ***
结果示例:
Variable: assign_0.tmp_0
- place: CUDAPlace(0)
- shape: [5]
- layout: NCHW
- dtype: int
- data: [1 1 1 1 1]
文档变动
补充问题
- 为什么还要给Print op新增参数?为什么不干脆在Print op中直接print(Tensor)?
因为PrintOp在使用上需要更灵活,如果用户想隐藏一些不需要信息,应该提供这种操作,而如果直接print(Tensor),会将所有的信息打印出来,这可能并不是用户想要的结果
- 单测结果对比问题
fluid.layers.Print
的打印结果是C++ std::cout
输出的,在python端捕获C++ stdout的输出不太容易,尝试了一些解决方案均不适用于我们的场景,继续投入精力不太值得,以下方案原理是类似的
- 方案1:https://stackoverflow.com/questions/24277488/in-python-how-to-capture-the-stdout-from-a-c-shared-library-to-a-variable
- 方案2:https://eli.thegreenplace.net/2015/redirecting-all-kinds-of-stdout-in-python/
- 【bug修复】用
declarative
会在fetch_list上出错
这个PR中的单测没有返回值,不需要fetch_list
,这种场景也是可能的,但使用declarative
默认构建的fetch_list在不fetch的时候是[None]
,应该改为None
- 【bug修复】类型错误bug修复
下面例子中,y_v的类型不能被正确记录,应该在binary_op_output_type
方法中增加支持类型PADDLE_RETURN_TYPES
def dyfunc_print_multi_vars(x):
"""
# NOTE: y_v type is error before cur PR in this case
Assign(targets=[Name(id='y_v', annotation=None, type_comment=None)],
value=BinOp(left=Name(id='x_v', annotation=None, type_comment=None), op=Mult, right=Constant(value=2, kind=None)))
"""
x_v = fluid.dygraph.to_variable(x)
y_v = x_v * 2
print(x_v)
print(y_v)