debugging_cn.md 5.6 KB
Newer Older
1 2
# 调试方法

A
Aurelius84 已提交
3 4 5 6
本节内容将介绍动态图转静态图(下文简称:动转静)推荐的几种调试方法。

> **注解:**
>
7
> 请确保转换前的动态图代码能够成功运行,建议使用 [paddle.jit.ProgramTranslator().enable(False)](../../api_cn/dygraph_cn/ProgramTranslator_cn.html#enable)关闭动转静功能,直接运行动态图,如下:
8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27

```python
import paddle
import numpy as np
paddle.disable_static()
# 关闭动转静动能
paddle.jit.ProgramTranslator().enable(False)

@paddle.jit.to_static
def func(x):
    x = paddle.to_tensor(x)
    if x > 3:
        x = x - 1
    return x

func(np.ones([3, 2]))
```

## 断点调试
使用动转静功能时,您可以使用断点调试代码。
28
例如,在代码中,调用 `pdb.set_trace()`
29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54
```Python
import pdb

@paddle.jit.to_static
def func(x):
    x = paddle.to_tensor(x)
    pdb.set_trace()
    if x > 3:
        x = x - 1
    return x
```
执行以下代码,将会在转化后的静态图代码中使用调试器:
```Python
func(np.ones([3, 2]))
```

运行结果:
```bash
> /tmp/tmpR809hf.py(6)func()
-> def true_fn_0(x):
(Pdb) n
> /tmp/tmpR809hf.py(6)func()
-> def false_fn_0(x):
...
```

55
如果您想在原始的动态图代码中使用调试器,请先调用 [`paddle.jit.ProgramTranslator().enable(False)`](../../api_cn/dygraph_cn/ProgramTranslator_cn.html#enable),如下:
56 57 58 59 60 61 62 63 64 65 66 67 68 69 70
```python
paddle.jit.ProgramTranslator().enable(False)
func(np.ones([3, 2]))
```
运行结果:
```bash
> <ipython-input-22-0bd4eab35cd5>(10)func()
-> if x > 3:
...

```

## 打印转换后的代码
您可以打印转换后的静态图代码,有2种方法:

71 72
1. 使用被装饰后的函数的 `code` 属性
   如下代码中,装饰器 `paddle.jit.to_static` 会将函数 `func` 转化为一个类对象 `StaticLayer`,可以使用 StaticLayer 的 `code` 属性来获得转化后的代码。
73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100
    ```Python
    @paddle.jit.to_static
    def func(x):
    x = paddle.to_tensor(x)
        if x > 3:
            x = x - 1
        return x

    print(func.code)
    ```
    运行结果:

    ```bash

    def func(x):
        x = fluid.layers.assign(x)

        def true_fn_0(x):
            x = x - 1
            return x

        def false_fn_0(x):
            return x
        x = fluid.dygraph.dygraph_to_static.convert_operators.convert_ifelse(x >
            3, true_fn_0, false_fn_0, (x,), (x,), (x,))
        return x
    ```

101
2. 使用 `set_code_level(level)` 或环境变量 `TRANSLATOR_CODE_LEVEL=level`
102

103
    通过调用 `set_code_level` 或设置环境变量 `TRANSLATOR_CODE_LEVEL`,可以在日志中查看转换后的代码:
104

A
Aurelius84 已提交
105 106 107 108 109 110 111 112 113 114 115 116
    ```python
    @paddle.jit.to_static
       def func(x):
       x = paddle.to_tensor(x)
       if x > 3:
           x = x - 1
       return x

    paddle.jit.set_code_level() # 也可设置 os.environ["TRANSLATOR_CODE_LEVEL"] = '100',效果相同
    func(np.ones([1]))
    ```
   运行结果:
117

A
Aurelius84 已提交
118 119 120 121
    ```bash
    2020-XX-XX 00:00:00,980-INFO: After the level 100 ast transformer: 'All Transformers', the transformed code:
    def func(x):
        x = fluid.layers.assign(x)
122

A
Aurelius84 已提交
123 124 125
        def true_fn_0(x):
            x = x - 1
            return x
126

A
Aurelius84 已提交
127 128 129 130
        def false_fn_0(x):
            return x
        x = fluid.dygraph.dygraph_to_static.convert_operators.convert_ifelse(x >
            3, true_fn_0, false_fn_0, (x,), (x,), (x,))
131
        return x
A
Aurelius84 已提交
132
    ```
133
    `set_code_level` 函数可以设置查看不同的AST Transformer转化后的代码,详情请见 [set_code_level](../../../paddle/api/paddle/fluid/dygraph/jit/set_code_level_cn.html)。
134 135

## 使用 `print`
136
`print` 函数可以用来查看变量,该函数在动转静中会被转化。当仅打印 Paddle Tensor 时,实际运行时会被转换为 Paddle 算子 [Print](../../api_cn/layers_cn/Print_cn.html),否则仍然运行 `print`
137 138 139 140
```python
@paddle.jit.to_static
def func(x):
    x = paddle.to_tensor(x)
A
Aurelius84 已提交
141

142 143
    # 打印x,x是Paddle Tensor,实际运行时会运行Paddle Print(x)
    print(x)
A
Aurelius84 已提交
144

145 146
    # 打印注释,非Paddle Tensor,实际运行时仍运行print
    print("Here call print function.")
A
Aurelius84 已提交
147

148 149 150 151 152
    if len(x) > 3:
        x = x - 1
    else:
        x = paddle.ones(shape=[1])
    return x
A
Aurelius84 已提交
153

154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170
func(np.ones([1]))
```

运行结果:
```bash
Variable: assign_0.tmp_0
  - lod: {}
  - place: CPUPlace
  - shape: [1]
  - layout: NCHW
  - dtype: double
  - data: [1]
Here call print function.  
```

## 日志打印
ProgramTranslator在日志中记录了额外的调试信息,以帮助您了解动转静过程中函数是否被成功转换。
171
您可以调用 [`paddle.jit.set_verbosity(level)`]((../../../paddle/api/paddle/fluid/dygraph/jit/set_verbosity_cn.html)) 或设置环境变量 `TRANSLATOR_VERBOSITY=level` 来设置日志详细等级,并查看不同等级的日志信息。目前,`level` 可以取值0-3:
172 173 174 175 176
- 0: 无日志
- 1: 包括了动转静转化流程的信息,如转换前的源码、转换的可调用对象
- 2: 包括以上信息,还包括更详细函数转化日志
- 3: 包括以上信息,以及更详细的动转静日志

A
Aurelius84 已提交
177 178 179
> **注意:**
>
> 日志中包括了源代码等信息,请在共享日志前确保它不包含敏感信息。
180

181
可以在代码运行前调用 `paddle.jit.set_verbosity` 控制日志详细程度:
182 183 184
```python
paddle.jit.set_verbosity(3)
```
185
或者设置环境变量 `TRANSLATOR_VERBOSITY`
186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204
```python
import os
os.environ["TRANSLATOR_VERBOSITY"] = '3'
```

运行结果:
```bash
2020-XX-XX 00:00:00,123-Level 1:    Source code:
@paddle.jit.to_static
def func(x):
    x = paddle.to_tensor(x)
    if len(x) > 3:
        x = x - 1
    else:
        x = paddle.ones(shape=[1])
    return x

2020-XX-XX 00:00:00,152-Level 1: Convert callable object: convert <built-in function len>.
```