Skip to content

Commit 7570e5e

Browse files
authored
Print readable program codes. (#12673)
1 parent f0f0699 commit 7570e5e

File tree

2 files changed

+214
-0
lines changed

2 files changed

+214
-0
lines changed
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
# Copyright (c) 2018 PaddlePaddle Authors. All Rights Reserved.
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
import os
16+
import time
17+
import unittest
18+
from multiprocessing import Process
19+
import signal
20+
21+
import numpy
22+
23+
import paddle.fluid as fluid
24+
import paddle.fluid.layers as layers
25+
from paddle.fluid.layers.io import ListenAndServ
26+
from paddle.fluid.layers.io import Recv
27+
from paddle.fluid.layers.io import Send
28+
29+
from paddle.fluid.transpiler.details import program_to_code
30+
31+
32+
class TestProgram2Code(unittest.TestCase):
33+
def test_print(self):
34+
place = fluid.CPUPlace()
35+
self.init_serv(place)
36+
self.init_client(place, 9123)
37+
38+
def init_serv(self, place):
39+
main = fluid.Program()
40+
41+
with fluid.program_guard(main):
42+
serv = ListenAndServ("127.0.0.1:0", ["X"], optimizer_mode=False)
43+
with serv.do():
44+
out_var = main.global_block().create_var(
45+
name="scale_0.tmp_0",
46+
psersistable=True,
47+
dtype="float32",
48+
shape=[32, 32])
49+
x = layers.data(
50+
shape=[32, 32],
51+
dtype='float32',
52+
name="X",
53+
append_batch_size=False)
54+
fluid.initializer.Constant(value=1.0)(x, main.global_block())
55+
layers.scale(x=x, scale=10.0, out=out_var)
56+
57+
program_to_code(main)
58+
59+
def init_client(self, place, port):
60+
main = fluid.Program()
61+
with fluid.program_guard(main):
62+
x = layers.data(
63+
shape=[32, 32],
64+
dtype='float32',
65+
name='X',
66+
append_batch_size=False)
67+
fluid.initializer.Constant(value=2.3)(x, main.global_block())
68+
get_var = main.global_block().create_var(
69+
name="scale_0.tmp_0", # server side var
70+
dtype="float32",
71+
persistable=False,
72+
shape=[32, 32])
73+
fluid.initializer.Constant(value=2.3)(get_var, main.global_block())
74+
Send("127.0.0.1:%d" % port, [x])
75+
o = Recv("127.0.0.1:%d" % port, [get_var])
76+
77+
program_to_code(main)
78+
79+
80+
if __name__ == "__main__":
81+
unittest.main()

python/paddle/fluid/transpiler/details/program_utils.py

Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,9 @@
1616

1717
import six
1818

19+
from paddle.fluid import core
20+
import paddle
21+
1922

2023
def delete_ops(block, ops):
2124
try:
@@ -39,3 +42,133 @@ def find_op_by_output_arg(block, arg_name):
3942
if arg_name in op.output_arg_names:
4043
return index
4144
return -1
45+
46+
47+
def get_indent_space(indent, space_num=4):
48+
ret = ""
49+
for i in range(0, indent * space_num):
50+
ret += " "
51+
52+
return ret
53+
54+
55+
def variable_to_code(var):
56+
"""
57+
Get readable codes of fluid variable.
58+
59+
Args:
60+
var: A fluid operator.
61+
62+
Returns:
63+
string: The formatted string.
64+
"""
65+
66+
var_str = "{name} : fluid.{type}.shape{shape}.astype({dtype})".\
67+
format(i="{", e="}", name=var.name, type=var.type, shape=var.shape, dtype=var.dtype)
68+
69+
if type(var) == paddle.fluid.framework.Parameter:
70+
if var.trainable:
71+
var_str = "trainable parameter " + var_str
72+
else:
73+
var_str = "parameter " + var_str
74+
else:
75+
var_str = "var " + var_str
76+
77+
if var.persistable:
78+
var_str = "persist " + var_str
79+
80+
return var_str
81+
82+
83+
def op_to_code(op):
84+
"""
85+
Get readable codes of fluid operator.
86+
87+
Args:
88+
op: A fluid operator.
89+
90+
Returns:
91+
string: The foramtted string.
92+
"""
93+
94+
outputs_str = "{"
95+
for i in range(0, len(op.output_names)):
96+
outputs_str += "{name}=".format(name=op.output_names[i])
97+
o = op.output(op.output_names[i])
98+
outputs_str += "{value}".format(value=o)
99+
if i != len(op.output_names) - 1:
100+
outputs_str += ", "
101+
outputs_str += "}"
102+
103+
inputs_str = "{"
104+
for i in range(0, len(op.input_names)):
105+
inputs_str += "{name}=".format(name=op.input_names[i])
106+
o = op.input(op.input_names[i])
107+
inputs_str += "{value}".format(value=o)
108+
109+
if i != len(op.input_names) - 1:
110+
inputs_str += ", "
111+
inputs_str += "}"
112+
113+
attrs_str = ""
114+
for i in range(0, len(op.attr_names)):
115+
name = op.attr_names[i]
116+
117+
attr_type = op.desc.attr_type(name)
118+
if attr_type == core.AttrType.BLOCK:
119+
a = "{name} = block[{value}]".format(
120+
name=name, type=attr_type, value=op.block_attr_id(name))
121+
attrs_str += a
122+
continue
123+
124+
if attr_type == core.AttrType.BLOCKS:
125+
a = "{name} = blocks{value}".format(
126+
name=name, type=attr_type, value=op.blocks_attr_ids(name))
127+
attrs_str += a
128+
continue
129+
130+
a = "{name} = {value}".format(
131+
name=name, type=attr_type, value=op.desc.attr(name))
132+
attrs_str += a
133+
if i != len(op.attr_names) - 1:
134+
attrs_str += ", "
135+
136+
if outputs_str != "{}":
137+
op_str = "{outputs} = {op_type}(inputs={inputs}, {attrs})".\
138+
format(outputs = outputs_str, op_type=op.type, inputs=inputs_str, attrs=attrs_str)
139+
else:
140+
op_str = "{op_type}(inputs={inputs}, {attrs})".\
141+
format(op_type=op.type, inputs=inputs_str, attrs=attrs_str)
142+
return op_str
143+
144+
145+
def program_to_code(prog):
146+
"""
147+
Print readable codes of fluid program.
148+
149+
Args:
150+
prog : A fluid program.
151+
152+
An example result like bellow:
153+
https://github.com/PaddlePaddle/Paddle/pull/12673
154+
"""
155+
indent = 0
156+
block_idx = 0
157+
for block in prog.blocks:
158+
print("{0}{1} // block {2}".format(
159+
get_indent_space(indent), '{', block_idx))
160+
indent += 1
161+
# sort all vars
162+
all_vars = sorted(block.vars.iteritems(), key=lambda x: x[0])
163+
for var in all_vars:
164+
print("{}{}".format(
165+
get_indent_space(indent), variable_to_code(var[1])))
166+
167+
if len(all_vars) > 0:
168+
print("")
169+
170+
for op in block.ops:
171+
print("{}{}".format(get_indent_space(indent), op_to_code(op)))
172+
indent -= 1
173+
print("{0}{1}".format(get_indent_space(indent), '}'))
174+
block_idx += 1

0 commit comments

Comments
 (0)