From: @liangzhibo Reviewed-by: @ginfung Signed-off-by:tags/v1.2.0-rc1
| @@ -23,6 +23,7 @@ | |||||
| #include "backend/optimizer/pass/convert_tuple_input_to_dynamic_input.h" | #include "backend/optimizer/pass/convert_tuple_input_to_dynamic_input.h" | ||||
| #include "backend/optimizer/pass/const_to_attr_strided_slice_grad.h" | #include "backend/optimizer/pass/const_to_attr_strided_slice_grad.h" | ||||
| #include "backend/optimizer/pass/convert_const_scalar_to_tensor.h" | #include "backend/optimizer/pass/convert_const_scalar_to_tensor.h" | ||||
| #include "backend/optimizer/pass/convert_attr_to_unify_mindir.h" | |||||
| #include "utils/ms_context.h" | #include "utils/ms_context.h" | ||||
| #include "debug/anf_ir_dump.h" | #include "debug/anf_ir_dump.h" | ||||
| @@ -41,6 +42,7 @@ void BackendCommonOptimization(const std::shared_ptr<session::KernelGraph> &kern | |||||
| auto optimizer = std::make_shared<GraphOptimizer>(); | auto optimizer = std::make_shared<GraphOptimizer>(); | ||||
| auto common_pm = std::make_shared<PassManager>("common_pm"); | auto common_pm = std::make_shared<PassManager>("common_pm"); | ||||
| common_pm->AddPass(std::make_shared<ConvertConstInputToAttr>()); | common_pm->AddPass(std::make_shared<ConvertConstInputToAttr>()); | ||||
| common_pm->AddPass(std::make_shared<ConvertAttrToUnifyMindIR>()); | |||||
| common_pm->AddPass(std::make_shared<ConstToAttrStridedSliceGradPass>()); | common_pm->AddPass(std::make_shared<ConstToAttrStridedSliceGradPass>()); | ||||
| common_pm->AddPass(std::make_shared<ConvertConstInputToTensorInput>()); | common_pm->AddPass(std::make_shared<ConvertConstInputToTensorInput>()); | ||||
| common_pm->AddPass(std::make_shared<ConvertTupleOutputToMaketuple>()); | common_pm->AddPass(std::make_shared<ConvertTupleOutputToMaketuple>()); | ||||
| @@ -0,0 +1,65 @@ | |||||
| /** | |||||
| * 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. | |||||
| */ | |||||
| #include "backend/optimizer/pass/convert_attr_to_unify_mindir.h" | |||||
| #include <vector> | |||||
| #include <string> | |||||
| #include "utils/check_convert_utils.h" | |||||
| #include "backend/session/anf_runtime_algorithm.h" | |||||
| #include "backend/kernel_compiler/common_utils.h" | |||||
| namespace mindspore { | |||||
| namespace opt { | |||||
| const AnfNodePtr ConvertAttrToUnifyMindIR::Process(const FuncGraphPtr &, const AnfNodePtr &node, | |||||
| const EquivPtr &) const { | |||||
| if (node == nullptr || !AnfAlgo::IsRealCNodeKernel(node)) { | |||||
| return nullptr; | |||||
| } | |||||
| std::vector<AnfNodePtr> todos; | |||||
| if (AnfAlgo::IsGraphKernel(node)) { | |||||
| auto sub_graph = AnfAlgo::GetCNodeFuncGraphPtr(node); | |||||
| MS_EXCEPTION_IF_NULL(sub_graph); | |||||
| kernel::GetValidKernelNodes(sub_graph, &todos); | |||||
| } else { | |||||
| todos.push_back(node); | |||||
| } | |||||
| for (auto &t : todos) { | |||||
| CNodePtr cnode = t->cast<CNodePtr>(); | |||||
| auto inputs = cnode->inputs(); | |||||
| AnfNodePtr op = inputs[0]; | |||||
| if (IsValueNode<Primitive>(op)) { | |||||
| auto prim = GetValueNode<PrimitivePtr>(op); | |||||
| auto attrs = prim->attrs(); | |||||
| std::string type_name = prim->name(); | |||||
| for (auto attr : attrs) { | |||||
| bool converted = CheckAndConvertUtils::ConvertAttrValueToString(type_name, attr.first, &attr.second); | |||||
| if (converted) { | |||||
| prim->set_attr(attr.first, attr.second); | |||||
| } | |||||
| bool converted_ir_attr = CheckAndConvertUtils::CheckIrAttrtoOpAttr(type_name, attr.first, &attr.second); | |||||
| if (converted_ir_attr) { | |||||
| prim->set_attr(attr.first, attr.second); | |||||
| } | |||||
| } | |||||
| } | |||||
| } | |||||
| return node; | |||||
| } | |||||
| } // namespace opt | |||||
| } // namespace mindspore | |||||
| @@ -0,0 +1,34 @@ | |||||
| /** | |||||
| * 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. | |||||
| */ | |||||
| #ifndef MINDSPORE_CCSRC_BACKEND_OPTIMIZER_PASS_CONVERT_ATTR_TO_UNIFY_MINDIR_H_ | |||||
| #define MINDSPORE_CCSRC_BACKEND_OPTIMIZER_PASS_CONVERT_ATTR_TO_UNIFY_MINDIR_H_ | |||||
| #include "ir/anf.h" | |||||
| #include "backend/optimizer/common/optimizer.h" | |||||
| namespace mindspore { | |||||
| namespace opt { | |||||
| class ConvertAttrToUnifyMindIR : public PatternProcessPass { | |||||
| public: | |||||
| explicit ConvertAttrToUnifyMindIR(bool multigraph = true) | |||||
| : PatternProcessPass("convert_attr_to_unify_mindir", multigraph) {} | |||||
| ~ConvertAttrToUnifyMindIR() override = default; | |||||
| const AnfNodePtr Process(const FuncGraphPtr &, const AnfNodePtr &, const EquivPtr &) const override; | |||||
| }; | |||||
| } // namespace opt | |||||
| } // namespace mindspore | |||||
| #endif // MINDSPORE_CCSRC_BACKEND_OPTIMIZER_PASS_CONVERT_ATTR_TO_UNIFY_MINDIR_H_ | |||||
| @@ -296,8 +296,8 @@ Strategys PrepareL2Normalize(const std::vector<std::shared_ptr<OperatorInfo>> &o | |||||
| auto iter = ops[iter_ops]->attrs().find(AXIS); | auto iter = ops[iter_ops]->attrs().find(AXIS); | ||||
| if (iter != ops[iter_ops]->attrs().end()) { | if (iter != ops[iter_ops]->attrs().end()) { | ||||
| MS_EXCEPTION_IF_NULL(iter->second); | MS_EXCEPTION_IF_NULL(iter->second); | ||||
| if (iter->second->isa<Int64Imm>()) { | |||||
| axis = iter->second->cast<Int64ImmPtr>()->value(); | |||||
| if (iter->second->isa<ValueSequeue>()) { | |||||
| axis = GetValue<std::vector<int64_t>>(iter->second)[0]; | |||||
| } else { | } else { | ||||
| MS_LOG(EXCEPTION) << ops[iter_ops]->name() << " : The value of axis is not int64_t."; | MS_LOG(EXCEPTION) << ops[iter_ops]->name() << " : The value of axis is not int64_t."; | ||||
| } | } | ||||
| @@ -51,8 +51,8 @@ Status L2NormalizeInfo::GetAttrs() { | |||||
| auto iter = attrs_.find(AXIS); | auto iter = attrs_.find(AXIS); | ||||
| if (iter != attrs_.end()) { | if (iter != attrs_.end()) { | ||||
| MS_EXCEPTION_IF_NULL(iter->second); | MS_EXCEPTION_IF_NULL(iter->second); | ||||
| if (iter->second->isa<Int64Imm>()) { | |||||
| axis_ = iter->second->cast<Int64ImmPtr>()->value(); | |||||
| if (iter->second->isa<ValueSequeue>()) { | |||||
| axis_ = GetValue<std::vector<int64_t>>(iter->second)[0]; | |||||
| } else { | } else { | ||||
| MS_LOG(ERROR) << name_ << " : The value of axis is not int64_t."; | MS_LOG(ERROR) << name_ << " : The value of axis is not int64_t."; | ||||
| return FAILED; | return FAILED; | ||||
| @@ -33,6 +33,7 @@ | |||||
| #include "utils/any.h" | #include "utils/any.h" | ||||
| #include "utils/utils.h" | #include "utils/utils.h" | ||||
| #include "utils/ms_context.h" | #include "utils/ms_context.h" | ||||
| #include "utils/check_convert_utils.h" | |||||
| #include "utils/context/context_extends.h" | #include "utils/context/context_extends.h" | ||||
| #include "utils/config_manager.h" | #include "utils/config_manager.h" | ||||
| #include "utils/convert_utils_py.h" | #include "utils/convert_utils_py.h" | ||||
| @@ -458,6 +459,27 @@ void ConstructInputTensor(const OpExecInfoPtr &op_run_info, std::vector<int64_t> | |||||
| op_prim->EndRecordAddAttr(); | op_prim->EndRecordAddAttr(); | ||||
| } | } | ||||
| void ConvertAttrToUnifyMindIR(const OpExecInfoPtr &op_run_info) { | |||||
| MS_EXCEPTION_IF_NULL(op_run_info); | |||||
| PrimitivePtr op_prim = op_run_info->py_primitive; | |||||
| MS_EXCEPTION_IF_NULL(op_prim); | |||||
| std::string op_name = op_run_info->op_name; | |||||
| auto attrs = op_prim->attrs(); | |||||
| for (auto attr : attrs) { | |||||
| bool converted = CheckAndConvertUtils::ConvertAttrValueToString(op_name, attr.first, &attr.second); | |||||
| if (converted) { | |||||
| op_prim->set_attr(attr.first, attr.second); | |||||
| } | |||||
| bool converted_ir_attr = CheckAndConvertUtils::CheckIrAttrtoOpAttr(op_name, attr.first, &attr.second); | |||||
| if (converted_ir_attr) { | |||||
| op_prim->set_attr(attr.first, attr.second); | |||||
| } | |||||
| } | |||||
| } | |||||
| BaseRef TransformBaseRefListToTuple(const BaseRef &base_ref) { | BaseRef TransformBaseRefListToTuple(const BaseRef &base_ref) { | ||||
| if (utils::isa<VectorRef>(base_ref)) { | if (utils::isa<VectorRef>(base_ref)) { | ||||
| auto ref_list = utils::cast<VectorRef>(base_ref); | auto ref_list = utils::cast<VectorRef>(base_ref); | ||||
| @@ -1425,6 +1447,7 @@ py::object PynativeExecutor::RunOpInMs(const OpExecInfoPtr &op_exec_info, Pynati | |||||
| std::vector<tensor::TensorPtr> input_tensors; | std::vector<tensor::TensorPtr> input_tensors; | ||||
| std::vector<int64_t> tensors_mask; | std::vector<int64_t> tensors_mask; | ||||
| ConstructInputTensor(op_exec_info, &tensors_mask, &input_tensors); | ConstructInputTensor(op_exec_info, &tensors_mask, &input_tensors); | ||||
| ConvertAttrToUnifyMindIR(op_exec_info); | |||||
| // get graph info for checking it whether existing in the cache | // get graph info for checking it whether existing in the cache | ||||
| std::string graph_info = GetSingleOpGraphInfo(op_exec_info, input_tensors); | std::string graph_info = GetSingleOpGraphInfo(op_exec_info, input_tensors); | ||||
| #if defined(__APPLE__) | #if defined(__APPLE__) | ||||
| @@ -14,6 +14,7 @@ | |||||
| * limitations under the License. | * limitations under the License. | ||||
| */ | */ | ||||
| #include "transform/graph_ir/op_adapter.h" | #include "transform/graph_ir/op_adapter.h" | ||||
| #include "utils/check_convert_utils.h" | |||||
| namespace mindspore { | namespace mindspore { | ||||
| namespace transform { | namespace transform { | ||||
| @@ -567,6 +568,9 @@ int OpAdapterImpl::SetNormalOpAttr(const OperatorPtr &op, const PrimitivePtr &pr | |||||
| for (auto &it : attr_map_) { | for (auto &it : attr_map_) { | ||||
| auto value = prim->GetAttr(it.first); | auto value = prim->GetAttr(it.first); | ||||
| if (value != nullptr) { | if (value != nullptr) { | ||||
| // convert parts of attr to str eg. data_format or change ir attr to op attr eg. axis[0] | |||||
| CheckAndConvertUtils::ConvertAttrValueToString(prim->name(), it.first, &value); | |||||
| CheckAndConvertUtils::CheckIrAttrtoOpAttr(prim->name(), it.first, &value); | |||||
| // set attr from primitive | // set attr from primitive | ||||
| int ret = setAttr(op, it.first, value); | int ret = setAttr(op, it.first, value); | ||||
| if (ret) { | if (ret) { | ||||
| @@ -226,6 +226,7 @@ bool CheckAndConvertUtils::ConvertAttrValueToString(const std::string &op_type, | |||||
| return true; | return true; | ||||
| } | } | ||||
| namespace { | namespace { | ||||
| typedef std::map<std::string, std::function<ValuePtr(ValuePtr)>> AttrFunction; | typedef std::map<std::string, std::function<ValuePtr(ValuePtr)>> AttrFunction; | ||||
| @@ -241,6 +242,7 @@ std::map<std::string, AttrFunction> kIrAttrToOpAttr = {{"L2Normalize", {{"axis", | |||||
| {"L2NormalizeGrad", {{"axis", L2NormalizeAttrConversion}}}}; | {"L2NormalizeGrad", {{"axis", L2NormalizeAttrConversion}}}}; | ||||
| } // namespace | } // namespace | ||||
| bool CheckAndConvertUtils::IsEqualVector(const std::vector<int64_t> &vec_1, const std::vector<int64_t> &vec_2) { | bool CheckAndConvertUtils::IsEqualVector(const std::vector<int64_t> &vec_1, const std::vector<int64_t> &vec_2) { | ||||
| if (vec_1.size() != vec_2.size()) { | if (vec_1.size() != vec_2.size()) { | ||||
| return false; | return false; | ||||
| @@ -1083,7 +1083,7 @@ class L2NormalizeGrad(PrimitiveWithInfer): | |||||
| Gradients of L2 normalize. | Gradients of L2 normalize. | ||||
| Args: | Args: | ||||
| axis (int): The begin axis for the input to apply L2 normalize. Default: 0. | |||||
| axis (Union[list(int), tuple(int), int]): The begin axis for the input to apply L2 normalize. Default: 0. | |||||
| epsilon (float): A small value added for numerical stability. Default: 1e-4. | epsilon (float): A small value added for numerical stability. Default: 1e-4. | ||||
| Inputs: | Inputs: | ||||
| @@ -1097,8 +1097,13 @@ class L2NormalizeGrad(PrimitiveWithInfer): | |||||
| @prim_attr_register | @prim_attr_register | ||||
| def __init__(self, axis=0, epsilon=1e-4): | def __init__(self, axis=0, epsilon=1e-4): | ||||
| validator.check_value_type('axis', axis, [int], self.name) | |||||
| axis = [axis] if isinstance(axis, int) else axis | |||||
| validator.check_value_type('axis', axis, [list, tuple], self.name) | |||||
| validator.check_value_type('epsilon', epsilon, [int, float], self.name) | validator.check_value_type('epsilon', epsilon, [int, float], self.name) | ||||
| self.add_prim_attr('axis', axis) | |||||
| self.init_attrs['axis'] = axis | |||||
| if len(axis) != 1: | |||||
| raise TypeError("The length of axis must be 1, later will support multiple axis!") | |||||
| def infer_shape(self, input_x, out, dout): | def infer_shape(self, input_x, out, dout): | ||||
| validator.check('input_x shape', input_x, 'out shape', out, Rel.EQ, self.name) | validator.check('input_x shape', input_x, 'out shape', out, Rel.EQ, self.name) | ||||
| @@ -2990,7 +2990,8 @@ class L2Normalize(PrimitiveWithInfer): | |||||
| where :math:`\epsilon` is epsilon. | where :math:`\epsilon` is epsilon. | ||||
| Args: | Args: | ||||
| axis (int): The starting axis for the input to apply the L2 normalization. Default: 0. | |||||
| axis (Union[list(int), tuple(int), int]): The starting axis for the input to apply the L2 normalization. | |||||
| Default: 0. | |||||
| epsilon (float): A small value added for numerical stability. Default: 1e-4. | epsilon (float): A small value added for numerical stability. Default: 1e-4. | ||||
| Inputs: | Inputs: | ||||
| @@ -3012,12 +3013,18 @@ class L2Normalize(PrimitiveWithInfer): | |||||
| @prim_attr_register | @prim_attr_register | ||||
| def __init__(self, axis=0, epsilon=1e-4): | def __init__(self, axis=0, epsilon=1e-4): | ||||
| validator.check_value_type('axis', axis, [int], self.name) | |||||
| axis = [axis] if isinstance(axis, int) else axis | |||||
| validator.check_value_type('axis', axis, [list, tuple], self.name) | |||||
| validator.check_value_type('epsilon', epsilon, [int, float], self.name) | validator.check_value_type('epsilon', epsilon, [int, float], self.name) | ||||
| self.add_prim_attr('axis', axis) | |||||
| self.init_attrs['axis'] = axis | |||||
| if len(axis) != 1: | |||||
| raise TypeError("The length of axis must be 1, later will support multiple axis!") | |||||
| self.axis = axis | |||||
| def infer_shape(self, input_x): | def infer_shape(self, input_x): | ||||
| dim = len(input_x) | dim = len(input_x) | ||||
| validator.check_int_range(self.axis, -dim, dim, Rel.INC_LEFT, 'axis value', self.name) | |||||
| validator.check_int_range(self.axis[0], -dim, dim, Rel.INC_LEFT, 'axis value', self.name) | |||||
| return input_x | return input_x | ||||
| def infer_dtype(self, input_x): | def infer_dtype(self, input_x): | ||||
| @@ -54,7 +54,7 @@ void TestL2NormalizeInfo::SetUp() { | |||||
| g_device_manager = std::make_shared<DeviceManager>(); | g_device_manager = std::make_shared<DeviceManager>(); | ||||
| g_device_manager->Init(dev_list, local_dev, stage_map, "hccl"); | g_device_manager->Init(dev_list, local_dev, stage_map, "hccl"); | ||||
| ValuePtr axis = MakeValue(static_cast<int64_t>(1)); | |||||
| ValuePtr axis = MakeValue(std::vector<int64_t>{1}); | |||||
| std::unordered_map<std::string, ValuePtr> attr = {{AXIS, axis}}; | std::unordered_map<std::string, ValuePtr> attr = {{AXIS, axis}}; | ||||
| Shapes inputs_shape = {{32, 64, 96}}; | Shapes inputs_shape = {{32, 64, 96}}; | ||||