Skip to content

Commit 3acb995

Browse files
authored
[cherry-pick]add NotImplementedError for multi optimizers (#22181) (#22229)
* add NotImplementedError for multi optimizers used on multi-places . test=develop * assert error only if num_devices>1. test=develop * set test_optimizer_in_control_flow in CMakeLists for using multi-GPU.test=develop
1 parent 0d82baf commit 3acb995

File tree

3 files changed

+102
-14
lines changed

3 files changed

+102
-14
lines changed

python/paddle/fluid/compiler.py

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,28 @@ def _prune_feed_ops(program):
6262
program.global_block()._remove_op(index)
6363

6464

65+
def _has_optimize_op(block):
66+
for op in block.ops:
67+
op_maker = core.op_proto_and_checker_maker
68+
optimize = core.op_proto_and_checker_maker.OpRole.Optimize
69+
if op_maker.kOpRoleVarAttrName() in op.attr_names and \
70+
int(op.all_attrs()[op_maker.kOpRoleAttrName()]) == int(optimize):
71+
return True
72+
return False
73+
74+
75+
def _has_optimizer_in_control_flow(program):
76+
if not program:
77+
program = framework.default_main_program()
78+
for op in program.global_block().ops:
79+
if op.type == "conditional_block_grad":
80+
sub_block = program.block(op._block_attr_id("sub_block"))
81+
if _has_optimize_op(sub_block):
82+
return True
83+
84+
return False
85+
86+
6587
class CompiledProgram(object):
6688
"""
6789
The CompiledProgram is used to transform a program or graph for
@@ -386,6 +408,16 @@ def _compile(self, scope, place):
386408
self._places = self._get_places(self._place, self._places)
387409
else:
388410
self._places = [self._place]
411+
412+
# Todo(liym27):If optimizer is used in control flow,
413+
# training on multi-places is not supported now, will
414+
# be supported later.
415+
if len(self._places) > 1 and \
416+
_has_optimizer_in_control_flow(self._program):
417+
raise NotImplementedError(
418+
"If optimizer is used in control flow, "
419+
"training on multi-places is not supported now.")
420+
389421
self._executor = self._compile_data_parallel(
390422
use_cuda=isinstance(self._place, core.CUDAPlace),
391423
scope=self._scope,

python/paddle/fluid/tests/unittests/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -331,4 +331,5 @@ set_tests_properties(test_parallel_executor_test_while_train test_parallel_execu
331331
test_parallel_executor_feed_persistable_var
332332
test_parallel_executor_crf_auto_growth test_buffer_shared_memory_reuse_pass_and_fuse_optimization_op_pass
333333
test_data_norm_op test_imperative_using_non_zero_gpu
334+
test_optimizer_in_control_flow
334335
test_buffer_shared_memory_reuse_pass PROPERTIES LABELS "RUN_TYPE=DIST")

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

Lines changed: 69 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@
2222
import paddle.fluid.optimizer as optimizer
2323
from paddle.fluid.framework import Program, program_guard
2424
import paddle.fluid.core as core
25+
import paddle.fluid.compiler as compiler
26+
import os
2527

2628
BATCH_SIZE = 1
2729
INPUT_SIZE = 784
@@ -104,20 +106,20 @@ def fn_2(opt, avg_loss=None, pred=None, label=None):
104106
avg_loss = layers.case([(mod_two, lambda: fn_1(adam, avg_loss_1))],
105107
lambda: fn_2(sgd, avg_loss_2))
106108

107-
place = fluid.CUDAPlace(0) if use_cuda else fluid.CPUPlace()
108-
exe = fluid.Executor(place)
109-
exe.run(fluid.default_startup_program())
110-
111-
for epoch in range(EPOCH_NUM):
112-
feed_image, feed_label = train_data[epoch]
113-
fetch_list = [hidden, prediction, avg_loss]
114-
feed = {
115-
'image': feed_image,
116-
'label': feed_label,
117-
'id': np.array([epoch]).astype('int32')
118-
}
119-
out = exe.run(main_program, feed=feed, fetch_list=fetch_list)
120-
out_hidden, out_pred, loss = out
109+
place = fluid.CUDAPlace(0) if use_cuda else fluid.CPUPlace()
110+
exe = fluid.Executor(place)
111+
exe.run(startup_program)
112+
113+
for epoch in range(EPOCH_NUM):
114+
feed_image, feed_label = train_data[epoch]
115+
fetch_list = [hidden, prediction, avg_loss]
116+
feed = {
117+
'image': feed_image,
118+
'label': feed_label,
119+
'id': np.array([epoch]).astype('int32')
120+
}
121+
out = exe.run(main_program, feed=feed, fetch_list=fetch_list)
122+
out_hidden, out_pred, loss = out
121123

122124
return out_hidden, out_pred, loss
123125

@@ -225,5 +227,58 @@ def test_optimzier_in_switch(self):
225227
loss_2))
226228

227229

230+
class TestMultiOptimizersMultiCardsError(unittest.TestCase):
231+
def test_error(self):
232+
startup_program = Program()
233+
main_program = Program()
234+
use_cuda = core.is_compiled_with_cuda()
235+
with program_guard(main_program, startup_program):
236+
237+
def fn_1(opt, avg_loss):
238+
opt.minimize(avg_loss)
239+
240+
def fn_2(opt, avg_loss):
241+
opt.minimize(avg_loss)
242+
243+
x = fluid.layers.data("X", [10], 'float32')
244+
hidden = layers.fc(x, 5)
245+
avg_loss = layers.mean(hidden)
246+
247+
adam = optimizer.Adam(learning_rate=LR)
248+
sgd = optimizer.SGD(learning_rate=LR)
249+
250+
cond = layers.fill_constant([1], 'bool', True)
251+
252+
layers.case([(cond, lambda: fn_1(adam, avg_loss))],
253+
lambda: fn_2(sgd, avg_loss))
254+
255+
cpu_place = fluid.CPUPlace()
256+
cuda_place = fluid.CUDAPlace(0) if use_cuda else fluid.CPUPlace()
257+
258+
for place in [cpu_place, cuda_place]:
259+
260+
exe = fluid.Executor(place)
261+
exe.run(startup_program)
262+
263+
np.random.seed(SEED)
264+
os.environ['CPU_NUM'] = str(2)
265+
pe_exe = fluid.ParallelExecutor(
266+
use_cuda=use_cuda,
267+
main_program=main_program,
268+
loss_name=avg_loss.name)
269+
num_devices = pe_exe.device_count
270+
271+
def not_implemented_error():
272+
pe_exe.run(feed={
273+
'X': np.random.random(size=[64, 10]).astype('float32'),
274+
},
275+
fetch_list=[avg_loss.name])
276+
277+
if num_devices > 1:
278+
self.assertRaises(NotImplementedError, not_implemented_error)
279+
else:
280+
not_implemented_error()
281+
282+
228283
if __name__ == '__main__':
229284
unittest.main()

0 commit comments

Comments
 (0)