Merge pull request !25909 from huangbingjian/update_global_paramstags/v1.6.0
| @@ -611,11 +611,11 @@ class Parser: | |||
| value = self.global_namespace[var] | |||
| if self.is_unsupported_namespace(value): | |||
| error_info = f"The builtin function '{var}' of python is not supported in graph mode." | |||
| return None, var, error_info | |||
| return None, error_info | |||
| return self.global_namespace, var | |||
| error_info = f"The name '{var}' is not defined in function '{self.function_name}'." | |||
| return None, var, error_info | |||
| return None, error_info | |||
| def is_unsupported_builtin_type(self, value_type): | |||
| """To check if not supported builtin type""" | |||
| @@ -681,7 +681,7 @@ class Parser: | |||
| return True | |||
| # Support nn.layer. To check if exclude other module. | |||
| if rightmost_name in self.ms_nn_ns: | |||
| logger.info(f"Found '{name}'({rightmost_name}) in nn namespace: {str(self.ms_nn_ns)}.") | |||
| logger.debug(f"Found '{name}'({rightmost_name}) in nn namespace: {str(self.ms_nn_ns)}.") | |||
| return True | |||
| if rightmost_name in trope_ns: | |||
| logger.debug(f"Found '{name}'({rightmost_name}) in trope namespace: {str(trope_ns)}.") | |||
| @@ -707,11 +707,12 @@ class Parser: | |||
| return self.global_namespace, var, value | |||
| if not self.is_supported_namespace_module(value): # Check if support including instance of types.ModuleType | |||
| return self.global_namespace, var, value | |||
| return self.global_namespace, var | |||
| supported = True | |||
| return self.global_namespace, var, value, supported | |||
| error_info = f"The name '{var}' is not defined, or not supported in graph mode." | |||
| logger.debug(f"error_info: {error_info}") | |||
| return None, var, error_info | |||
| return None, error_info | |||
| def analyze_super(self, class_type_node, subclass_instance): | |||
| """Analyze super and return a class instance.""" | |||
| @@ -195,33 +195,59 @@ AnfNodePtr FunctionBlock::MakeResolveClassMember(const std::string &attr) { | |||
| return MakeResolve(name_space, symbol); | |||
| } | |||
| AnfNodePtr FunctionBlock::HandleNamespaceInfo(const py::tuple &namespace_info) { | |||
| const size_t namespace_info_size = 2; | |||
| const size_t namespace_more_info_size = 3; | |||
| if (namespace_info.size() != namespace_info_size && namespace_info.size() != namespace_more_info_size) { | |||
| MS_EXCEPTION(NameError) << "namespace info size should be 2 or 3, but got " << namespace_info.size(); | |||
| AnfNodePtr FunctionBlock::GetResolveNode(const py::tuple &info) { | |||
| constexpr size_t namespace_index = 0; | |||
| constexpr size_t symbol_index = 1; | |||
| NameSpacePtr name_space = std::make_shared<NameSpace>(RESOLVE_NAMESPACE_NAME_SYMBOL_STR, info[namespace_index]); | |||
| SymbolPtr symbol = std::make_shared<Symbol>(info[symbol_index].cast<std::string>()); | |||
| return MakeResolve(name_space, symbol); | |||
| } | |||
| AnfNodePtr FunctionBlock::HandleNamespaceInfo(const py::tuple &info) { | |||
| constexpr size_t namespace_index = 0; | |||
| constexpr size_t symbol_index = 1; | |||
| constexpr size_t namespace_info_size = 2; | |||
| if (info.size() != namespace_info_size) { | |||
| MS_EXCEPTION(NameError) << "namespace info size should be 2, but got " << info.size(); | |||
| } | |||
| bool unsupported = false; | |||
| py::object py_obj; | |||
| if (namespace_info.size() == namespace_more_info_size) { | |||
| if (namespace_info[0].is_none()) { // If namespace is None, the symbol is an undefined name. | |||
| MS_EXCEPTION(NameError) << namespace_info[namespace_more_info_size - 1].cast<std::string>(); | |||
| } else { // Or, the symbol is an unsupported builtin symbol in Graph mode. | |||
| unsupported = true; | |||
| py_obj = namespace_info[namespace_more_info_size - 1]; | |||
| // If namespace is None, the symbol is an undefined name. | |||
| if (info[namespace_index].is_none()) { | |||
| MS_EXCEPTION(NameError) << info[symbol_index].cast<std::string>(); | |||
| } | |||
| return GetResolveNode(info); | |||
| } | |||
| AnfNodePtr FunctionBlock::HandleBuiltinNamespaceInfo(const py::tuple &info) { | |||
| constexpr size_t closure_info_size = 2; | |||
| constexpr size_t unsupported_info_size = 3; | |||
| constexpr size_t supported_info_size = 4; | |||
| constexpr size_t namespace_index = 0; | |||
| constexpr size_t symbol_index = 1; | |||
| constexpr size_t value_index = 2; | |||
| if (info.size() < closure_info_size || info.size() > supported_info_size) { | |||
| MS_EXCEPTION(NameError) << "namespace info size should be 2, 3 or 4, but got " << info.size(); | |||
| } | |||
| // Handle closure namespace info. | |||
| if (info.size() == closure_info_size) { | |||
| // If namespace is None, the symbol is an undefined name. | |||
| if (info[namespace_index].is_none()) { | |||
| MS_EXCEPTION(NameError) << info[symbol_index].cast<std::string>(); | |||
| } | |||
| return GetResolveNode(info); | |||
| } | |||
| NameSpacePtr name_space = std::make_shared<NameSpace>(RESOLVE_NAMESPACE_NAME_SYMBOL_STR, namespace_info[0]); | |||
| SymbolPtr symbol = std::make_shared<Symbol>(namespace_info[1].cast<std::string>()); | |||
| MS_LOG(DEBUG) << "[" << func_graph()->ToString() << "] name_space: " << name_space->ToString() | |||
| << ", symbol: " << symbol->ToString() << ", unsupported: " << unsupported; | |||
| auto resolved_node = MakeResolve(name_space, symbol); | |||
| if (unsupported) { | |||
| // Handle global namespace info. | |||
| auto resolved_node = GetResolveNode(info); | |||
| if (info.size() == unsupported_info_size) { | |||
| resolved_node->set_interpret(true); | |||
| AddGlobalPyParam(symbol->name(), py_obj); | |||
| MS_LOG(INFO) << "[" << func_graph()->ToString() << "] Added global python symbol: {" << symbol->name() << " : " | |||
| << py::str(py_obj) << "}"; | |||
| } | |||
| SymbolPtr symbol = std::make_shared<Symbol>(info[symbol_index].cast<std::string>()); | |||
| py::object py_obj = info[value_index]; | |||
| AddGlobalPyParam(symbol->name(), py_obj); | |||
| MS_LOG(INFO) << "[" << func_graph()->ToString() << "] Added global python symbol: {" << symbol->name() << " : " | |||
| << py::str(py_obj) << "}"; | |||
| return resolved_node; | |||
| } | |||
| @@ -248,7 +274,7 @@ AnfNodePtr FunctionBlock::MakeResolveSymbol(const std::string &value) { | |||
| return HandleNamespaceInfo(namespace_info); | |||
| } else { | |||
| py::tuple namespace_info = ast->CallParserObjMethod(PYTHON_PARSE_GET_BUILTIN_NAMESPACE_SYMBOL, value); | |||
| return HandleNamespaceInfo(namespace_info); | |||
| return HandleBuiltinNamespaceInfo(namespace_info); | |||
| } | |||
| } | |||
| @@ -537,10 +563,12 @@ void FunctionBlock::AttachIsolatedNodesBeforeReturn() { | |||
| isolated_nodes_.clear(); | |||
| AnfNodePtr state = nullptr; | |||
| if (states.size() == 1) { | |||
| constexpr size_t no_state_size = 1; | |||
| constexpr size_t only_one_state_size = 2; | |||
| if (states.size() == no_state_size) { | |||
| // Only MakeTuple, no state left. | |||
| return; | |||
| } else if (states.size() == 2) { | |||
| } else if (states.size() == only_one_state_size) { | |||
| // If there are only MakeTuple and another node in states(the states size is 2), | |||
| // do not need to MakeTuple, just use the node. | |||
| state = states[1]; | |||
| @@ -74,7 +74,9 @@ class FunctionBlock : public std::enable_shared_from_this<FunctionBlock> { | |||
| AnfNodePtr MakeResolveSymbol(const std::string &value); | |||
| AnfNodePtr MakeResolveOperation(const std::string &value); | |||
| AnfNodePtr MakeResolve(const std::shared_ptr<NameSpace> &name_space, const std::shared_ptr<Symbol> &resolve_symbol); | |||
| AnfNodePtr GetResolveNode(const py::tuple &namespace_info); | |||
| AnfNodePtr HandleNamespaceInfo(const py::tuple &namespace_info); | |||
| AnfNodePtr HandleBuiltinNamespaceInfo(const py::tuple &namespace_info); | |||
| AnfNodePtr MakeInterpret(const std::string &script_text, const AnfNodePtr &global_dict_node, | |||
| const AnfNodePtr &local_dict_node, const AnfNodePtr &orig_node); | |||
| const std::unordered_map<ParameterPtr, AnfNodePtr> &removable_phis() const { return removable_phis_; } | |||
| @@ -0,0 +1,83 @@ | |||
| # Copyright 2021 Huawei Technologies Co., Ltd | |||
| # | |||
| # 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. | |||
| # ============================================================================ | |||
| """ test graph fallback """ | |||
| import pytest | |||
| import numpy as np | |||
| import mindspore.nn as nn | |||
| from mindspore import Tensor, ms_function, context | |||
| import mindspore.common.dtype as mstype | |||
| context.set_context(mode=context.GRAPH_MODE) | |||
| class ControlNet(nn.Cell): | |||
| def inner_function_1(self, a, b): | |||
| return a + b | |||
| def inner_function_2(self, a, b): | |||
| return a - b | |||
| def construct(self, x): | |||
| a = Tensor(np.array(4), mstype.int32) | |||
| b = Tensor(np.array(5), mstype.int32) | |||
| if a + b > x: | |||
| return self.inner_function_1(a, b) | |||
| return self.inner_function_2(a, b) | |||
| @pytest.mark.level0 | |||
| @pytest.mark.platform_x86_gpu_training | |||
| @pytest.mark.platform_arm_ascend_training | |||
| @pytest.mark.platform_x86_ascend_training | |||
| @pytest.mark.env_onecard | |||
| def test_fallback_control_sink_tensor(): | |||
| """ | |||
| Feature: Fallback feature: support define Tensor in Class construct. | |||
| Description: Fallback feature: support define Tensor in Class construct. | |||
| Expectation: Fallback feature: support define Tensor in Class construct. | |||
| """ | |||
| x = Tensor(np.array(1), mstype.int32) | |||
| net = ControlNet() | |||
| output = net(x) | |||
| output_expect = Tensor(9, mstype.int32) | |||
| assert output == output_expect | |||
| @pytest.mark.level0 | |||
| @pytest.mark.platform_x86_gpu_training | |||
| @pytest.mark.platform_arm_ascend_training | |||
| @pytest.mark.platform_x86_ascend_training | |||
| @pytest.mark.env_onecard | |||
| def test_np_tensor_list(): | |||
| """ | |||
| Feature: Fallback feature | |||
| Description: support Basic method of Tensor list. | |||
| Expectation: No exception. | |||
| """ | |||
| @ms_function | |||
| def np_tensor_list(): | |||
| a = Tensor(np.array(4), mstype.int32) | |||
| b = Tensor(np.array(5), mstype.int32) | |||
| c = Tensor(np.array(6), mstype.int32) | |||
| tensor_list = [a, b] | |||
| for tensor in tensor_list: | |||
| print(tensor) | |||
| tensor_list.append(tensor_list[-1] + c) | |||
| return tensor_list | |||
| tensor_list = np_tensor_list() | |||
| print("tensor_list:", tensor_list) | |||
| assert len(tensor_list) == 3 | |||
| @@ -60,7 +60,6 @@ def use_tensor_with_mstype(): | |||
| return me_x | |||
| @pytest.mark.skip(reason='Not support graph fallback feature yet') | |||
| def test_tensor_with_mstype(): | |||
| """ | |||
| Feature: JIT Fallback | |||
| @@ -70,6 +69,22 @@ def test_tensor_with_mstype(): | |||
| print(use_tensor_with_mstype()) | |||
| @ms_function | |||
| def use_tuple_of_tensor(): | |||
| me_x = (Tensor(1), Tensor(1)) | |||
| return me_x | |||
| @pytest.mark.skip(reason='Not support graph fallback feature yet') | |||
| def test_tuple_of_tensor(): | |||
| """ | |||
| Feature: JIT Fallback | |||
| Description: Test tuple of tensor in graph mode. | |||
| Expectation: No exception. | |||
| """ | |||
| print(use_tuple_of_tensor()) | |||
| class Net(nn.Cell): | |||
| def __init__(self): | |||
| super(Net, self).__init__() | |||
| @@ -215,63 +230,6 @@ def test_np_fallback_func_tensor_index(): | |||
| assert output == output_expect | |||
| class ControlNet(nn.Cell): | |||
| def __init__(self): | |||
| super(ControlNet, self).__init__() | |||
| def inner_function_1(self, a, b): | |||
| return a + b | |||
| def inner_function_2(self, a, b): | |||
| return a - b | |||
| def construct(self, x): | |||
| a = Tensor(np.array(4), mstype.int32) | |||
| b = Tensor(np.array(5), mstype.int32) | |||
| if a + b > x: | |||
| return self.inner_function_1(a, b) | |||
| return self.inner_function_2(a, b) | |||
| # NameError: name 'mstype' is not defined. | |||
| @pytest.mark.skip(reason='Not support graph fallback feature yet') | |||
| def test_fallback_control_sink_tensor(): | |||
| """ | |||
| Feature: Fallback feature: support define Tensor in Class construct. | |||
| Description: Fallback feature: support define Tensor in Class construct. | |||
| Expectation: Fallback feature: support define Tensor in Class construct. | |||
| """ | |||
| x = Tensor(np.array(1), mstype.int32) | |||
| net = ControlNet() | |||
| output = net(x) | |||
| output_expect = Tensor(9, mstype.int32) | |||
| assert output == output_expect | |||
| # NameError: name 'mytype' is not defined | |||
| @pytest.mark.skip(reason='Not support graph fallback feature yet') | |||
| def test_np_tensor_list(): | |||
| """ | |||
| Feature: Fallback feature | |||
| Description: support Basic method of Tensor list. | |||
| Expectation: No exception. | |||
| """ | |||
| @ms_function | |||
| def np_tensor_list(): | |||
| a = Tensor(np.array(4), mstype.int32) | |||
| b = Tensor(np.array(5), mstype.int32) | |||
| c = Tensor(np.array(6), mstype.int32) | |||
| tensor_list = [a, b] | |||
| for tensor in tensor_list: | |||
| print(tensor) | |||
| tensor_list.append(tensor_list[-1] + c) | |||
| return tensor_list | |||
| tensor_list = np_tensor_list() | |||
| print("tensor_list:", tensor_list) | |||
| assert len(tensor_list) == 3 | |||
| # EvalCNode: This may be not defined, or it can't be a operator. | |||
| @pytest.mark.skip(reason='Not support graph fallback feature yet') | |||
| def test_np_tensor_add(): | |||