Skip to content

Commit 5d579e1

Browse files
authored
add export_for_deployment flag to save_inference_model (#12582)
add export_for_deployment flag to save_inference_model
1 parent 83c85f3 commit 5d579e1

File tree

4 files changed

+59
-16
lines changed

4 files changed

+59
-16
lines changed

paddle/fluid/API.spec

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ paddle.fluid.Program.create_block ArgSpec(args=['self', 'parent_idx'], varargs=N
66
paddle.fluid.Program.current_block ArgSpec(args=['self'], varargs=None, keywords=None, defaults=None)
77
paddle.fluid.Program.get_desc ArgSpec(args=['self'], varargs=None, keywords=None, defaults=None)
88
paddle.fluid.Program.global_block ArgSpec(args=['self'], varargs=None, keywords=None, defaults=None)
9-
paddle.fluid.Program.inference_optimize ArgSpec(args=['self'], varargs=None, keywords=None, defaults=None)
9+
paddle.fluid.Program.inference_optimize ArgSpec(args=['self', 'export_for_deployment'], varargs=None, keywords=None, defaults=(True,))
1010
paddle.fluid.Program.list_vars ArgSpec(args=['self'], varargs=None, keywords=None, defaults=None)
1111
paddle.fluid.Program.optimized_guard ArgSpec(args=[], varargs='args', keywords='kwds', defaults=None)
1212
paddle.fluid.Program.parse_from_string ArgSpec(args=['binary_str'], varargs=None, keywords=None, defaults=None)
@@ -74,7 +74,7 @@ paddle.fluid.io.save_persistables ArgSpec(args=['executor', 'dirname', 'main_pro
7474
paddle.fluid.io.load_vars ArgSpec(args=['executor', 'dirname', 'main_program', 'vars', 'predicate', 'filename'], varargs=None, keywords=None, defaults=(None, None, None, None))
7575
paddle.fluid.io.load_params ArgSpec(args=['executor', 'dirname', 'main_program', 'filename'], varargs=None, keywords=None, defaults=(None, None))
7676
paddle.fluid.io.load_persistables ArgSpec(args=['executor', 'dirname', 'main_program', 'filename'], varargs=None, keywords=None, defaults=(None, None))
77-
paddle.fluid.io.save_inference_model ArgSpec(args=['dirname', 'feeded_var_names', 'target_vars', 'executor', 'main_program', 'model_filename', 'params_filename'], varargs=None, keywords=None, defaults=(None, None, None))
77+
paddle.fluid.io.save_inference_model ArgSpec(args=['dirname', 'feeded_var_names', 'target_vars', 'executor', 'main_program', 'model_filename', 'params_filename', 'export_for_deployment'], varargs=None, keywords=None, defaults=(None, None, None, True))
7878
paddle.fluid.io.load_inference_model ArgSpec(args=['dirname', 'executor', 'model_filename', 'params_filename'], varargs=None, keywords=None, defaults=(None, None))
7979
paddle.fluid.io.get_inference_program ArgSpec(args=['target_vars', 'main_program'], varargs=None, keywords=None, defaults=(None,))
8080
paddle.fluid.initializer.ConstantInitializer.__init__ ArgSpec(args=['self', 'value', 'force_cpu'], varargs=None, keywords=None, defaults=(0.0, False))

python/paddle/fluid/framework.py

Lines changed: 17 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1518,7 +1518,7 @@ def clone(self, for_test=False):
15181518
The two code snippets above will generate same programs.
15191519
"""
15201520
if for_test:
1521-
p = self.inference_optimize()
1521+
p = self.inference_optimize(export_for_deployment=False)
15221522
else:
15231523
p = Program()
15241524
p.desc = core.ProgramDesc(self.desc)
@@ -1578,7 +1578,7 @@ def prune(self, targets):
15781578
res._sync_with_cpp()
15791579
return res
15801580

1581-
def inference_optimize(self):
1581+
def inference_optimize(self, export_for_deployment=True):
15821582
"""
15831583
This method will create a new program and do following adjustments on it:
15841584
1. Remove all reader variables and their creator ops if exist.
@@ -1589,6 +1589,10 @@ def inference_optimize(self):
15891589
attribute of operators to :code:`True`. All the :code:`Parameter`
15901590
information will be lost.
15911591
1592+
Args:
1593+
export_for_deployment(bool): remove the read ops that are added by py_reader
1594+
for cpp inference library
1595+
15921596
Notes: This API is a very low level API. Use
15931597
:code:`Program.clone(for_test=True)` instead.
15941598
@@ -1603,16 +1607,17 @@ def inference_optimize(self):
16031607
# remove all readers and the read_op if exist
16041608
read_op_idx = 0
16051609
root_block = res.desc.block(0)
1606-
while True:
1607-
if read_op_idx >= root_block.op_size() or root_block.op(
1608-
read_op_idx).type() == 'read':
1609-
break
1610-
read_op_idx += 1
1611-
if read_op_idx < root_block.op_size():
1612-
root_block._remove_op(0, read_op_idx + 1)
1613-
for var in root_block.all_vars():
1614-
if var.type() == core.VarDesc.VarType.READER:
1615-
root_block._remove_var(var.name())
1610+
if export_for_deployment:
1611+
while True:
1612+
if read_op_idx >= root_block.op_size() or root_block.op(
1613+
read_op_idx).type() == 'read':
1614+
break
1615+
read_op_idx += 1
1616+
if read_op_idx < root_block.op_size():
1617+
root_block._remove_op(0, read_op_idx + 1)
1618+
for var in root_block.all_vars():
1619+
if var.type() == core.VarDesc.VarType.READER:
1620+
root_block._remove_var(var.name())
16161621

16171622
# change all `is_test` attributes to True
16181623
for i in range(res.desc.num_blocks()):

python/paddle/fluid/io.py

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -555,7 +555,8 @@ def save_inference_model(dirname,
555555
executor,
556556
main_program=None,
557557
model_filename=None,
558-
params_filename=None):
558+
params_filename=None,
559+
export_for_deployment=True):
559560
"""
560561
Prune the given `main_program` to build a new program especially for inference,
561562
and then save it and all related parameters to given `dirname` by the `executor`.
@@ -577,6 +578,8 @@ def save_inference_model(dirname,
577578
params_filename(str|None): The name of file to save all related parameters.
578579
If it is setted None, parameters will be saved
579580
in separate files .
581+
export_for_deployment(bool): remove the read ops that are added by py_reader
582+
for cpp inference lib. Default True
580583
581584
Returns:
582585
None
@@ -643,7 +646,8 @@ def save_inference_model(dirname,
643646
copy_program.desc.flush()
644647

645648
pruned_program = copy_program.prune(targets=target_vars)
646-
inference_program = pruned_program.inference_optimize()
649+
inference_program = pruned_program.inference_optimize(
650+
export_for_deployment=export_for_deployment)
647651
fetch_var_names = [v.name for v in target_vars]
648652

649653
prepend_feed_ops(inference_program, feeded_var_names)

python/paddle/fluid/tests/unittests/test_program.py

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717

1818
from paddle.fluid.framework import Program, default_main_program, program_guard, grad_var_name
1919
import paddle.fluid.layers as layers
20+
import paddle.fluid as fluid
2021

2122
main_program = default_main_program()
2223

@@ -98,6 +99,39 @@ def test_program_clone_with_parameter(self):
9899
new_program = main_program.clone()
99100
self.assertNotEqual(0, len(new_program.blocks[0].all_parameters()))
100101

102+
def test_program_inference_optimize(self):
103+
def net():
104+
reader = fluid.layers.py_reader(
105+
capacity=10,
106+
shapes=[[-1, 10], [-1, 1]],
107+
lod_levels=[0, 0],
108+
dtypes=['float32', 'int64'],
109+
use_double_buffer=True)
110+
in_data, label = fluid.layers.read_file(reader)
111+
predict_label = fluid.layers.fc(in_data, size=2, act='softmax')
112+
loss = fluid.layers.mean(
113+
fluid.layers.cross_entropy(
114+
input=predict_label, label=label))
115+
116+
optimizer = fluid.optimizer.Adam()
117+
optimizer.minimize(loss)
118+
119+
startup_program = fluid.Program()
120+
main_program = fluid.Program()
121+
with fluid.program_guard(main_program, startup_program):
122+
net()
123+
no_read_program = main_program.inference_optimize()
124+
keep_read_program = main_program.inference_optimize(
125+
export_for_deployment=False)
126+
no_read_ops = no_read_program.global_block().ops
127+
keep_read_ops = keep_read_program.global_block().ops
128+
self.assertEqual(len(keep_read_ops) - len(no_read_ops), 2)
129+
self.assertEqual(keep_read_ops[0].type, 'create_double_buffer_reader')
130+
self.assertEqual(keep_read_ops[1].type, 'read')
131+
132+
for i in range(len(no_read_ops)):
133+
self.assertEqual(no_read_ops[i].type, keep_read_ops[i + 2].type)
134+
101135

102136
if __name__ == '__main__':
103137
unittest.main()

0 commit comments

Comments
 (0)