From 99a4ff8fe4be92c982177b735b176aa8f55fae71 Mon Sep 17 00:00:00 2001 From: Leo Chen Date: Thu, 30 Jun 2022 15:10:09 +0800 Subject: [PATCH] [new-exec] support runing with different scope and the same program using scope_guard (#43962) * support scope_guard * fix test --- .../new_executor/standalone_executor.cc | 19 +++++++++----- .../new_executor/standalone_executor.h | 6 ++++- paddle/fluid/pybind/pybind.cc | 12 ++++++--- python/paddle/fluid/executor.py | 8 +++--- .../interpreter/test_standalone_executor.py | 26 ++++++++++++------- 5 files changed, 47 insertions(+), 24 deletions(-) diff --git a/paddle/fluid/framework/new_executor/standalone_executor.cc b/paddle/fluid/framework/new_executor/standalone_executor.cc index 3ef0a827c24..31b1627dc65 100644 --- a/paddle/fluid/framework/new_executor/standalone_executor.cc +++ b/paddle/fluid/framework/new_executor/standalone_executor.cc @@ -28,44 +28,50 @@ StandaloneExecutor::StandaloneExecutor(const platform::Place& place, scope_(scope) { // NOTE(zhiqiu): for startup_program, run once ? if (startup_prog.Block(0).AllOps().size() > 0) { - auto core = GetInterpreterCore(startup_prog, {}, {}, false); + auto core = GetInterpreterCore(scope, startup_prog, {}, {}, false); VLOG(4) << "StandaloneExecutor: " << this << ", InterpreterCore: " << core; core->Run({}); } } paddle::framework::FetchList StandaloneExecutor::Run( + Scope* scope, const std::vector& feed_names, const std::vector& feed_tensors, const std::vector& fetch_names) { platform::RecordEvent record_event( "StandaloneExecutor::run", platform::TracerEventType::UserDefined, 1); - auto core = GetInterpreterCore(main_prog_, feed_names, fetch_names, true); + auto core = + GetInterpreterCore(scope, main_prog_, feed_names, fetch_names, true); return core->Run(feed_names, feed_tensors); } paddle::framework::FetchList StandaloneExecutor::Run( + Scope* scope, const std::vector& feed_names, const std::vector& fetch_names) { platform::RecordEvent record_event( "StandaloneExecutor::run", platform::TracerEventType::UserDefined, 1); - auto core = GetInterpreterCore(main_prog_, feed_names, fetch_names, false); + auto core = + GetInterpreterCore(scope, main_prog_, feed_names, fetch_names, false); VLOG(4) << "StandaloneExecutor: " << this << ", InterpreterCore: " << core; return core->Run(feed_names); } framework::interpreter::CostInfo StandaloneExecutor::DryRun( + Scope* scope, const std::vector& feed_names, const std::vector& feed_tensors) { - auto core = GetInterpreterCore(main_prog_, feed_names, {}, true); + auto core = GetInterpreterCore(scope, main_prog_, feed_names, {}, true); return core->DryRun(feed_names, feed_tensors); } std::shared_ptr StandaloneExecutor::GetInterpreterCore( + Scope* scope, const ProgramDesc& prog, const std::vector& feed_names, const std::vector& fetch_names, @@ -79,6 +85,7 @@ std::shared_ptr StandaloneExecutor::GetInterpreterCore( for (auto& fetchname : fetch_names) { oss << fetchname << ","; } + oss << "scope:" << scope; auto iter = interpretercores_.find(oss.str()); @@ -89,13 +96,13 @@ std::shared_ptr StandaloneExecutor::GetInterpreterCore( std::shared_ptr core = nullptr; if (add_fetch_op) { - core = CreateInterpreterCore(place_, prog, scope_, fetch_names); + core = CreateInterpreterCore(place_, prog, scope, fetch_names); } else { core = std::make_shared( place_, prog.Block(0), /*skip_gc_vars=*/std::set(), - scope_); + scope); } interpretercores_.emplace(oss.str(), core); return core; diff --git a/paddle/fluid/framework/new_executor/standalone_executor.h b/paddle/fluid/framework/new_executor/standalone_executor.h index 7b54a855007..5b9c48009ea 100644 --- a/paddle/fluid/framework/new_executor/standalone_executor.h +++ b/paddle/fluid/framework/new_executor/standalone_executor.h @@ -39,6 +39,7 @@ class StandaloneExecutor { ~StandaloneExecutor() {} paddle::framework::FetchList Run( + Scope* scope, const std::vector& feed_names, const std::vector& feed_tensors, const std::vector& fetch_names); @@ -46,15 +47,18 @@ class StandaloneExecutor { // NOTE(zhiqiu): feed_names are only used for caching interpretercore. // fetch_names are used for caching interpretercore and inserting fetch ops, // the latter can be moved to python side. - paddle::framework::FetchList Run(const std::vector& feed_names, + paddle::framework::FetchList Run(Scope* scope, + const std::vector& feed_names, const std::vector& fetch_names); framework::interpreter::CostInfo DryRun( + Scope* scope, const std::vector& feed_names, const std::vector& feed_tensors); private: std::shared_ptr GetInterpreterCore( + Scope* scope, const ProgramDesc& prog, const std::vector& feed_names, const std::vector& fetch_names, diff --git a/paddle/fluid/pybind/pybind.cc b/paddle/fluid/pybind/pybind.cc index 18a3fb1aab8..7b7e9d1a6c9 100644 --- a/paddle/fluid/pybind/pybind.cc +++ b/paddle/fluid/pybind/pybind.cc @@ -3063,6 +3063,7 @@ All parameter, weight, gradient are variables in Paddle. Scope *>()) .def("run", [](StandaloneExecutor &self, + Scope *scope, const std::unordered_map &input_dict, std::vector fetch_names) { std::vector feed_tensors; @@ -3079,12 +3080,13 @@ All parameter, weight, gradient are variables in Paddle. paddle::framework::FetchList ret; { pybind11::gil_scoped_release release; - ret = self.Run(feed_names, feed_tensors, fetch_names); + ret = self.Run(scope, feed_names, feed_tensors, fetch_names); } return py::cast(std::move(ret)); }) .def("run", [](StandaloneExecutor &self, + Scope *scope, const std::unordered_map &input_dict, std::vector fetch_names) { @@ -3099,23 +3101,25 @@ All parameter, weight, gradient are variables in Paddle. paddle::framework::FetchList ret; { pybind11::gil_scoped_release release; - ret = self.Run(feed_names, feed_tensors, fetch_names); + ret = self.Run(scope, feed_names, feed_tensors, fetch_names); } return py::cast(std::move(ret)); }) .def("run", [](StandaloneExecutor &self, + Scope *scope, std::vector feed_names, std::vector fetch_names) { paddle::framework::FetchList ret; { pybind11::gil_scoped_release release; - ret = self.Run(feed_names, fetch_names); + ret = self.Run(scope, feed_names, fetch_names); } return py::cast(std::move(ret)); }) .def("dry_run", [](StandaloneExecutor &self, + Scope *scope, const std::unordered_map &input_dict) { std::vector feed_tensors; std::vector feed_names; @@ -3131,7 +3135,7 @@ All parameter, weight, gradient are variables in Paddle. framework::interpreter::CostInfo cost_info; { pybind11::gil_scoped_release release; - cost_info = self.DryRun(feed_names, feed_tensors); + cost_info = self.DryRun(scope, feed_names, feed_tensors); } return cost_info; }); diff --git a/python/paddle/fluid/executor.py b/python/paddle/fluid/executor.py index 62578eef86c..d932b3f219b 100755 --- a/python/paddle/fluid/executor.py +++ b/python/paddle/fluid/executor.py @@ -537,7 +537,7 @@ class _StandaloneExecutor(object): self._scope = scope self._new_exe = self._create_new_executor() - def run(self, feed_names, fetch_list, return_numpy=True): + def run(self, scope, feed_names, fetch_list, return_numpy=True): """ Args: feed_names(list): This parameter represents the input names of the model. @@ -549,7 +549,8 @@ class _StandaloneExecutor(object): """ fetch_list = self._check_fetch(fetch_list) - tensors = self._new_exe.run(feed_names, fetch_list)._move_to_list() + tensors = self._new_exe.run(scope, feed_names, + fetch_list)._move_to_list() if return_numpy: return as_numpy(tensors, copy=True) else: @@ -1470,7 +1471,8 @@ class Executor(object): cpu_tensor = _as_lodtensor(data, core.CPUPlace()) tensor._copy_from(cpu_tensor, self.place) - return new_exe.run(list(feed.keys()), fetch_list, return_numpy) + return new_exe.run(scope, list(feed.keys()), fetch_list, + return_numpy) compiled = isinstance(program, compiler.CompiledProgram) diff --git a/python/paddle/fluid/tests/unittests/interpreter/test_standalone_executor.py b/python/paddle/fluid/tests/unittests/interpreter/test_standalone_executor.py index 9e375126550..6fa419ae282 100644 --- a/python/paddle/fluid/tests/unittests/interpreter/test_standalone_executor.py +++ b/python/paddle/fluid/tests/unittests/interpreter/test_standalone_executor.py @@ -50,27 +50,30 @@ class LinearTestCase(unittest.TestCase): def test_interp_base(self): startup_program, main_program, c = self.build_program() + scope = core.Scope() standaloneexecutor = StandaloneExecutor(self.place, startup_program.desc, - main_program.desc, core.Scope()) + main_program.desc, scope) out = standaloneexecutor.run( - {"a": np.ones([2, 2], dtype="float32") * 2}, [c.name]) + scope, {"a": np.ones([2, 2], dtype="float32") * 2}, [c.name]) for i in range(10): out = standaloneexecutor.run( - {"a": np.ones([2, 2], dtype="float32") * i}, [c.name]) + scope, {"a": np.ones([2, 2], dtype="float32") * i}, [c.name]) for i in range(10): out = standaloneexecutor.run( - {"a": np.ones([2, 2], dtype="float32") * i}, ['a', c.name]) + scope, {"a": np.ones([2, 2], dtype="float32") * i}, + ['a', c.name]) def test_dry_run(self): + scope = core.Scope() startup_program, main_program, c = self.build_program() standaloneexecutor = StandaloneExecutor(self.place, startup_program.desc, - main_program.desc, core.Scope()) + main_program.desc, scope) # test for cost_info cost_info = standaloneexecutor.dry_run( - {"a": np.ones([2, 2], dtype="float32")}) + scope, {"a": np.ones([2, 2], dtype="float32")}) self.check_cost_info(cost_info) def check_cost_info(self, cost_info): @@ -132,14 +135,15 @@ class ExecutorStatisticsTestCase(unittest.TestCase): p = core.Place() p.set_place(self.place) + scope = core.Scope() executor = StandaloneExecutor(p, startup_program.desc, - main_program.desc, core.Scope()) + main_program.desc, scope) helper_profiler = profiler.Profiler( targets=[profiler.ProfilerTarget.CPU], scheduler=(1, 2)) helper_profiler.start() for i in range(self.iter_n): - executor.run({}, fetch_list) + executor.run(scope, {}, fetch_list) helper_profiler.step() helper_profiler.stop() @@ -251,13 +255,15 @@ class MultiStreamModelTestCase(unittest.TestCase): p = core.Place() p.set_place(self.place) + scope = core.Scope() inter_core = StandaloneExecutor(p, startup_program.desc, - main_program.desc, core.Scope()) + main_program.desc, scope) outs = [] for i in range(self.iter_n): outs.append( - np.array(inter_core.run({}, fetch_list)._move_to_list()[0])) + np.array( + inter_core.run(scope, {}, fetch_list)._move_to_list()[0])) return outs -- GitLab