From 21440b4d69d1a8b390ae62611b2ea0e90261e14c Mon Sep 17 00:00:00 2001 From: chengduo <30176695+chengduoZH@users.noreply.github.com> Date: Fri, 9 Aug 2019 07:21:18 +0800 Subject: [PATCH] Add call stack info during compile time (#19067) * Add call stack info during runtime and compile time test=develop * Rename operator_call_stack test=develop * Add unit test test=develop * follow comment test=develop --- paddle/fluid/framework/CMakeLists.txt | 4 +- paddle/fluid/framework/op_call_stack.cc | 47 ++++++++++++++++ paddle/fluid/framework/op_call_stack.h | 26 +++++++++ paddle/fluid/framework/op_desc.cc | 49 +++++++++------- paddle/fluid/framework/operator.cc | 22 +------- .../test_runtime_and_compiletime_exception.py | 56 +++++++++++++++++++ 6 files changed, 163 insertions(+), 41 deletions(-) create mode 100644 paddle/fluid/framework/op_call_stack.cc create mode 100644 paddle/fluid/framework/op_call_stack.h create mode 100644 python/paddle/fluid/tests/unittests/test_runtime_and_compiletime_exception.py diff --git a/paddle/fluid/framework/CMakeLists.txt b/paddle/fluid/framework/CMakeLists.txt index 54f3511e157..7dc3a6c60e7 100644 --- a/paddle/fluid/framework/CMakeLists.txt +++ b/paddle/fluid/framework/CMakeLists.txt @@ -124,7 +124,7 @@ cc_library(shape_inference SRCS shape_inference.cc DEPS ddim attribute device_co cc_library(transfer_scope_cache SRCS transfer_scope_cache.cc DEPS scope framework_proto device_context) cc_library(op_kernel_type SRCS op_kernel_type.cc DEPS device_context place) cc_library(operator SRCS operator.cc DEPS op_info device_context tensor scope glog - shape_inference data_transform lod_tensor profiler transfer_scope_cache op_kernel_type) + shape_inference data_transform lod_tensor profiler transfer_scope_cache op_kernel_type op_call_stack) cc_test(operator_test SRCS operator_test.cc DEPS operator op_registry device_context) @@ -135,6 +135,8 @@ cc_library(proto_desc SRCS var_desc.cc op_desc.cc block_desc.cc program_desc.cc cc_library(op_registry SRCS op_registry.cc DEPS op_proto_maker op_info operator glog proto_desc) +cc_library(op_call_stack SRCS op_call_stack.cc DEPS op_proto_maker enforce) + nv_test(op_registry_test SRCS op_registry_test.cc DEPS op_registry) py_proto_compile(framework_py_proto SRCS framework.proto data_feed.proto) diff --git a/paddle/fluid/framework/op_call_stack.cc b/paddle/fluid/framework/op_call_stack.cc new file mode 100644 index 00000000000..cf3b7188acb --- /dev/null +++ b/paddle/fluid/framework/op_call_stack.cc @@ -0,0 +1,47 @@ +/* Copyright (c) 2019 PaddlePaddle Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. */ + +#include "paddle/fluid/framework/op_call_stack.h" +#include +#include +#include "paddle/fluid/framework/attribute.h" +#include "paddle/fluid/framework/op_proto_maker.h" + +namespace paddle { +namespace framework { + +void InsertCallStackInfo(const std::string &type, const AttributeMap &attrs, + platform::EnforceNotMet *exception) { + if (attrs.count("sub_block") != 0) { + return; + } + auto &callstack = boost::get>( + attrs.at(OpProtoAndCheckerMaker::OpCreationCallstackAttrName())); + + if (callstack.empty()) { + return; + } + std::ostringstream sout; + sout << "Invoke operator " << type << " error.\n"; + sout << "Python Call stacks: \n"; + for (auto &line : callstack) { + sout << line; + } + sout << "C++ Call stacks: \n"; + sout << exception->err_str_; + exception->err_str_ = sout.str(); +} + +} // namespace framework +} // namespace paddle diff --git a/paddle/fluid/framework/op_call_stack.h b/paddle/fluid/framework/op_call_stack.h new file mode 100644 index 00000000000..4408601abf0 --- /dev/null +++ b/paddle/fluid/framework/op_call_stack.h @@ -0,0 +1,26 @@ +/* Copyright (c) 2019 PaddlePaddle Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. */ + +#pragma once + +#include +#include "paddle/fluid/framework/type_defs.h" +#include "paddle/fluid/platform/enforce.h" + +namespace paddle { +namespace framework { +void InsertCallStackInfo(const std::string &type, const AttributeMap &attrs, + platform::EnforceNotMet *exception); +} // namespace framework +} // namespace paddle diff --git a/paddle/fluid/framework/op_desc.cc b/paddle/fluid/framework/op_desc.cc index 1ea93b7638a..8fbed7aac78 100644 --- a/paddle/fluid/framework/op_desc.cc +++ b/paddle/fluid/framework/op_desc.cc @@ -18,8 +18,10 @@ limitations under the License. */ #include // NOLINT #include #include +#include #include "glog/logging.h" #include "paddle/fluid/framework/block_desc.h" +#include "paddle/fluid/framework/op_call_stack.h" #include "paddle/fluid/framework/op_proto_maker.h" #include "paddle/fluid/framework/operator.h" #include "paddle/fluid/framework/program_desc.h" @@ -679,26 +681,33 @@ void OpDesc::CheckAttrs() { } void OpDesc::InferShape(const BlockDesc &block) const { - VLOG(3) << "CompileTime infer shape on " << Type(); - InitInferShapeFuncs(); - auto &infer_shape = OpInfoMap::Instance().Get(this->Type()).infer_shape_; - PADDLE_ENFORCE(static_cast(infer_shape), - "%s's infer_shape has not been registered", this->Type()); - CompileTimeInferShapeContext ctx(*this, block); - if (VLOG_IS_ON(10)) { - std::ostringstream sout; - auto inames = this->InputArgumentNames(); - sout << " From ["; - std::copy(inames.begin(), inames.end(), - std::ostream_iterator(sout, ", ")); - sout << "] to ["; - auto onames = this->OutputArgumentNames(); - std::copy(onames.begin(), onames.end(), - std::ostream_iterator(sout, ", ")); - sout << "]"; - VLOG(10) << sout.str(); - } - infer_shape(&ctx); + try { + VLOG(3) << "CompileTime infer shape on " << Type(); + InitInferShapeFuncs(); + auto &infer_shape = OpInfoMap::Instance().Get(this->Type()).infer_shape_; + PADDLE_ENFORCE(static_cast(infer_shape), + "%s's infer_shape has not been registered", this->Type()); + CompileTimeInferShapeContext ctx(*this, block); + if (VLOG_IS_ON(10)) { + std::ostringstream sout; + auto inames = this->InputArgumentNames(); + sout << " From ["; + std::copy(inames.begin(), inames.end(), + std::ostream_iterator(sout, ", ")); + sout << "] to ["; + auto onames = this->OutputArgumentNames(); + std::copy(onames.begin(), onames.end(), + std::ostream_iterator(sout, ", ")); + sout << "]"; + VLOG(10) << sout.str(); + } + infer_shape(&ctx); + } catch (platform::EnforceNotMet exception) { + framework::InsertCallStackInfo(Type(), attrs_, &exception); + throw std::move(exception); + } catch (...) { + std::rethrow_exception(std::current_exception()); + } } void OpDesc::InferVarType(BlockDesc *block) const { diff --git a/paddle/fluid/framework/operator.cc b/paddle/fluid/framework/operator.cc index 2f7476aa38c..3a06b522229 100644 --- a/paddle/fluid/framework/operator.cc +++ b/paddle/fluid/framework/operator.cc @@ -23,6 +23,7 @@ limitations under the License. */ #include "paddle/fluid/framework/data_transform.h" #include "paddle/fluid/framework/executor.h" #include "paddle/fluid/framework/lod_tensor.h" +#include "paddle/fluid/framework/op_call_stack.h" #include "paddle/fluid/framework/op_proto_maker.h" #include "paddle/fluid/framework/operator.h" #include "paddle/fluid/framework/shape_inference.h" @@ -186,28 +187,9 @@ void OperatorBase::Run(const Scope& scope, const platform::Place& place) { } else { RunImpl(scope, place); } - VLOG(3) << place << " " << DebugStringEx(&scope); } catch (platform::EnforceNotMet exception) { - if (Attrs().count("sub_block") != 0) { - throw std::move(exception); - } - - auto& callstack = Attr>( - OpProtoAndCheckerMaker::OpCreationCallstackAttrName()); - - if (callstack.empty()) { - throw std::move(exception); - } - std::ostringstream sout; - sout << "Invoke operator " << Type() << " error.\n"; - sout << "Python Callstacks: \n"; - for (auto& line : callstack) { - sout << line; - } - sout << "C++ Callstacks: \n"; - sout << exception.err_str_; - exception.err_str_ = sout.str(); + framework::InsertCallStackInfo(Type(), Attrs(), &exception); throw std::move(exception); } catch (...) { std::rethrow_exception(std::current_exception()); diff --git a/python/paddle/fluid/tests/unittests/test_runtime_and_compiletime_exception.py b/python/paddle/fluid/tests/unittests/test_runtime_and_compiletime_exception.py new file mode 100644 index 00000000000..9a002a31d14 --- /dev/null +++ b/python/paddle/fluid/tests/unittests/test_runtime_and_compiletime_exception.py @@ -0,0 +1,56 @@ +# Copyright (c) 2019 PaddlePaddle Authors. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +from __future__ import print_function + +import unittest +import numpy as np +from op_test import OpTest +import paddle.fluid as fluid +import paddle.fluid.core as core + + +class TestRunTimeException(OpTest): + def test_run_time_exception(self): + place = fluid.CPUPlace() + exe = fluid.Executor(place) + + train_program = fluid.Program() + startup_program = fluid.Program() + with fluid.program_guard(train_program, startup_program): + label = fluid.layers.data(name="label", shape=[1], dtype="int64") + fluid.layers.one_hot(input=label, depth=100) + + def _run_program(): + x = np.random.random(size=(10)).astype('int64') + exe.run(train_program, feed={"label": x}) + + self.assertRaises(core.EnforceNotMet, _run_program) + + +class TestCompileTimeException(OpTest): + def test_compile_time_exception(self): + self.assertRaises(core.EnforceNotMet, self.build_model) + + def build_model(self): + train_program = fluid.Program() + startup_program = fluid.Program() + with fluid.program_guard(train_program, startup_program): + label = fluid.layers.data( + name="label", shape=[1], dtype="int64", append_batch_size=False) + fluid.layers.one_hot(input=label, depth=100) + + +if __name__ == '__main__': + unittest.main() -- GitLab