diff --git a/mindspore/ccsrc/plugin/device/ascend/hal/common/ascend_utils.h b/mindspore/ccsrc/plugin/device/ascend/hal/common/ascend_utils.h index a62cba376b0..0eb5cea3813 100644 --- a/mindspore/ccsrc/plugin/device/ascend/hal/common/ascend_utils.h +++ b/mindspore/ccsrc/plugin/device/ascend/hal/common/ascend_utils.h @@ -25,6 +25,20 @@ namespace mindspore { namespace device { namespace ascend { +template +std::string MapToString(const Map &value) { + std::stringstream buffer; + buffer << "{"; + for (auto it = value.begin(); it != value.end(); it++) { + if (it != value.begin()) { + buffer << ", "; + } + buffer << it->first << ": " << it->second; + } + buffer << "}"; + return buffer.str(); +} + std::string GetErrorMessage(bool add_title = false); std::string GetWarningMessage(); void SetErrorManagerContext(); diff --git a/mindspore/ccsrc/plugin/device/ascend/hal/hardware/ge_device_context.cc b/mindspore/ccsrc/plugin/device/ascend/hal/hardware/ge_device_context.cc index b98f4ae380b..5b90486e871 100644 --- a/mindspore/ccsrc/plugin/device/ascend/hal/hardware/ge_device_context.cc +++ b/mindspore/ccsrc/plugin/device/ascend/hal/hardware/ge_device_context.cc @@ -35,6 +35,7 @@ #include "runtime/hardware/device_context_manager.h" #include "plugin/device/ascend/hal/hccl_adapter/hccl_adapter.h" #include "plugin/device/ascend/optimizer/ge_optimization.h" +#include "plugin/device/ascend/hal/common/ascend_utils.h" #include "runtime/config.h" #include "runtime/dev.h" #include "distributed/init.h" @@ -43,6 +44,8 @@ namespace mindspore { namespace device { namespace ascend { namespace { +using mindspore::transform::OptionMap; + constexpr auto kMindsporeDumpConfig = "MINDSPORE_DUMP_CONFIG"; constexpr char kGeDumpMode[3][7] = {"all", "input", "output"}; @@ -101,6 +104,38 @@ transform::TensorOrderMap GetParams(const FuncGraphPtr &anf_graph) { return res; } +std::string ShapesToString(const ShapeArray &shapes) { + std::stringstream buffer; + for (size_t i = 0; i < shapes.size(); ++i) { + if (i != 0) { + buffer << ","; + } + buffer << "["; + const auto &shape = shapes[i]; + for (size_t j = 0; j < shape.size(); ++j) { + if (j != 0) { + buffer << ","; + } + buffer << shape[j]; + } + buffer << "]"; + } + return buffer.str(); +} + +OptionMap GetComputeGraphOptions(const ShapeArray &input_shapes, bool is_dynamic_shape) { + OptionMap options{}; + if (common::GetEnv("GE_TRAIN") == "1") { + (void)options.emplace("ge.exec.variable_acc", "1"); + } + if (!is_dynamic_shape) { + return options; + } + (void)options.emplace("ge.exec.dynamicGraphExecuteMode", "dynamic_execute"); + (void)options.emplace("ge.exec.dataInputsShapeRange", ShapesToString(input_shapes)); + return options; +} + bool AddDFGraph(const FuncGraphPtr &anf_graph, const transform::TensorOrderMap &init_inputs_map, bool export_air) { MS_EXCEPTION_IF_NULL(anf_graph); auto converter = transform::NewConverter(anf_graph); @@ -121,11 +156,9 @@ bool AddDFGraph(const FuncGraphPtr &anf_graph, const transform::TensorOrderMap & std::string graph_name = anf_graph->ToString(); std::string init_graph = "init_subgraph." + graph_name; std::string checkpoint_name = "save." + GetGraphName(anf_graph); - if (common::GetEnv("GE_TRAIN") == "1") { - (void)transform::AddGraph(graph_name, transform::GetComputeGraph(converter), {{"ge.exec.variable_acc", "1"}}); - } else { - (void)transform::AddGraph(graph_name, transform::GetComputeGraph(converter)); - } + const auto options = GetComputeGraphOptions(converter->input_shapes(), converter->dynamic_shape_inputs()); + MS_LOG(INFO) << "Set options of compute graph: " << graph_name << " to " << MapToString(options); + (void)transform::AddGraph(graph_name, transform::GetComputeGraph(converter), options); (void)transform::AddGraph(init_graph, transform::GetInitGraph(converter)); (void)transform::AddGraph(BROADCAST_GRAPH_NAME, transform::GetBroadcastGraph(converter)); @@ -488,7 +521,7 @@ void GeDeviceContext::InitGe(const std::shared_ptr &inst_context) { { // Release GIL before calling into (potentially long-running) C++ code mindspore::ScopedLongRunning long_running; - if (ge::GEInitialize(ge_options) != ge::GRAPH_SUCCESS) { + if (::ge::GEInitialize(ge_options) != ::ge::GRAPH_SUCCESS) { MS_LOG(EXCEPTION) << "Initialize GE failed!"; } } @@ -670,7 +703,7 @@ bool GeDeviceContext::FinalizeGe(const std::shared_ptr &inst_context) std::string exName(abi::__cxa_current_exception_type()->name()); MS_LOG(ERROR) << "Error occurred when deleting GE graph runner and session fail. Exception name: " << exName; } - if (ge::GEFinalize() != ge::GRAPH_SUCCESS) { + if (::ge::GEFinalize() != ::ge::GRAPH_SUCCESS) { MS_LOG(WARNING) << "Finalize GE failed!"; } inst_context->set_param(MS_CTX_IS_PYNATIVE_GE_INIT, false); diff --git a/mindspore/ccsrc/transform/graph_ir/convert.cc b/mindspore/ccsrc/transform/graph_ir/convert.cc index 9d2d9e79e67..700d8b45c91 100644 --- a/mindspore/ccsrc/transform/graph_ir/convert.cc +++ b/mindspore/ccsrc/transform/graph_ir/convert.cc @@ -20,6 +20,7 @@ #include #include #include +#include #include "include/common/utils/utils.h" #include "mindspore/core/ops/core_ops.h" #include "utils/anf_utils.h" @@ -392,14 +393,16 @@ DfGraphConvertor &DfGraphConvertor::InitParam(const TensorOrderMap &tensors) { return *this; } - // Processing input with MakeDatasetHandler + // Processing input with MakeDatasetHandler and check whether input is dynamic for (auto &it : anf_graph_->inputs()) { auto op_itor = op_cache_.find(it.get()); // converted node if (it->isa() && op_itor != op_cache_.end()) { - string name = std::static_pointer_cast(it)->name(); + const auto ¶m = std::static_pointer_cast(it); + string name = param->name(); auto tensor_itor = tensors.find(name); // in init value map if (tensor_itor == tensors.end()) { - DfGraphConvertor::MakeDatasetHandler(name, input_idx, it); + MakeDatasetHandler(name, input_idx, it); + AddGraphDynamicInput(param); input_idx++; } } @@ -1941,6 +1944,19 @@ void DfGraphConvertor::SetNodeInput(const AnfNodePtr node) { DfGraphConvertor::SetOpInput(adpt, cnode); } +void DfGraphConvertor::AddGraphDynamicInput(const ParameterPtr ¶m) { + MS_EXCEPTION_IF_NULL(param); + const auto &base_shape = param->Shape(); + MS_EXCEPTION_IF_NULL(base_shape); + const auto &shape = base_shape->cast(); + MS_EXCEPTION_IF_NULL(shape); + const auto &sv = shape->shape(); + if (std::any_of(sv.cbegin(), sv.cend(), [](const auto e) { return e == -1; })) { + dynamic_shape_inputs_ = true; + } + (void)input_shapes_.emplace_back(sv); +} + std::string DfGraphConvertor::GetGNodeName(const ::ge::GNode &node) const { ::ge::AscendString name; auto ret = node.GetName(name); @@ -2224,7 +2240,7 @@ OperatorPtr DfGraphConvertor::Convert(const AnfNodePtr node) { return nullptr; } -void DfGraphConvertor::ConvertTopK(const CNodePtr node) { +void DfGraphConvertor::ConvertTopK(const CNodePtr &node) { MS_EXCEPTION_IF_NULL(node); MS_LOG(INFO) << "Convert TopK second input's type from int64 to int32."; auto value_ptr = node->input(2)->cast(); @@ -2372,7 +2388,7 @@ std::vector DfGraphConvertor::CastToInt(const ValuePtr &value) const { return cur_value; } -void DfGraphConvertor::ConvertReshape(const CNodePtr node) { +void DfGraphConvertor::ConvertReshape(const CNodePtr &node) { MS_LOG(INFO) << "Convert the second input of reshape to op attr."; const auto kInputNum = 3; if (node->size() < kInputNum) { @@ -2386,10 +2402,7 @@ void DfGraphConvertor::ConvertReshape(const CNodePtr node) { auto op = adpt->generate(node); MS_EXCEPTION_IF_NULL(op); // get shape form attr - auto value_node = node->input(0)->cast(); - MS_EXCEPTION_IF_NULL(value_node); - MS_EXCEPTION_IF_NULL(value_node->value()); - auto primitive = value_node->value()->cast(); + auto primitive = GetCNodePrimitive(node); MS_EXCEPTION_IF_NULL(primitive); auto value = primitive->GetAttr("shape"); std::vector list; @@ -2399,7 +2412,34 @@ void DfGraphConvertor::ConvertReshape(const CNodePtr node) { op_cache_[node.get()] = op; } -void DfGraphConvertor::ConvertAllReduce(const CNodePtr node) { +void DfGraphConvertor::ConvertDynamicStitch(const CNodePtr &node) { + MS_LOG(INFO) << "Convert and set 'N' attr of DynamicStitch."; + OpAdapterPtr adpt = FindAdapter(node, training_); + if (adpt == nullptr) { + return; + } + auto op = adpt->generate(node); + MS_EXCEPTION_IF_NULL(op); + int64_t input_length = 0; + auto indices = node->input(1); + MS_EXCEPTION_IF_NULL(indices); + if (indices->isa()) { + input_length = SizeToLong(indices->cast()->size()) - 1; + } else if (IsValueNode(indices)) { + const auto tuple = GetValueNode(indices); + MS_EXCEPTION_IF_NULL(tuple); + input_length = SizeToLong(tuple->size()); + } else { + MS_LOG(EXCEPTION) << "Input 1 of DynamicStitch is neither CNode nor ValueNode contains ValueSequence, but " + << indices->ToString() << ", can not set 'N' attr."; + } + + (void)op->SetAttr("N", input_length); + MS_LOG(INFO) << "Set 'N' attr of DynamicStitch to " << input_length; + op_cache_[node.get()] = op; +} + +void DfGraphConvertor::ConvertAllReduce(const CNodePtr &node) { MS_LOG(INFO) << "Add AllReduce fusion_id"; OpAdapterPtr adpt = FindAdapter(node, training_); if (adpt == nullptr) { @@ -2408,10 +2448,7 @@ void DfGraphConvertor::ConvertAllReduce(const CNodePtr node) { auto op = adpt->generate(node); MS_EXCEPTION_IF_NULL(op); // get shape form attr - auto value_node = node->input(0)->cast(); - MS_EXCEPTION_IF_NULL(value_node); - MS_EXCEPTION_IF_NULL(value_node->value()); - auto primitive = value_node->value()->cast(); + auto primitive = GetCNodePrimitive(node); MS_EXCEPTION_IF_NULL(primitive); auto fusion_value = primitive->GetAttr("fusion"); auto fusion = GetValue(fusion_value); @@ -2425,7 +2462,8 @@ void DfGraphConvertor::ConvertAllReduce(const CNodePtr node) { op_cache_[node.get()] = op; } -void DfGraphConvertor::ConvertConv2D(const CNodePtr node) { +void DfGraphConvertor::ConvertConv2D(const CNodePtr &node) { + MS_LOG(INFO) << "Convert and set 'padding' attr for Conv2D-like op."; MS_EXCEPTION_IF_NULL(node); OpAdapterPtr adpt = FindAdapter(node, training_); if (adpt == nullptr) { @@ -2433,20 +2471,33 @@ void DfGraphConvertor::ConvertConv2D(const CNodePtr node) { } auto op = adpt->generate(node); MS_EXCEPTION_IF_NULL(op); - auto value_node = node->input(0)->cast(); - MS_EXCEPTION_IF_NULL(value_node); - MS_EXCEPTION_IF_NULL(value_node->value()); - auto primitive = value_node->value()->cast(); - MS_EXCEPTION_IF_NULL(primitive); - auto value = primitive->GetAttr("padding"); - if (value != nullptr) { - std::string pad_mode = GetValue(value); - (void)op->SetAttr("padding", pad_mode); - } op_cache_[node.get()] = op; + auto primitive = GetCNodePrimitive(node); + MS_EXCEPTION_IF_NULL(primitive); + std::string pad_mode; + if (auto value = primitive->GetAttr("padding"); value != nullptr) { + pad_mode = GetValue(value); + } else if (auto value = primitive->GetAttr("pad_mode"); value != nullptr) { + // Get 'pad_mode' attr and set it to 'padding' attr for ge + const mindspore::HashMap pad_mode_map{{1, "SAME"}, {2, "VALID"}}; + if (value->isa()) { + pad_mode = GetValue(value); + (void)std::transform(pad_mode.cbegin(), pad_mode.cend(), pad_mode.begin(), toupper); + } else if (auto it = pad_mode_map.find(GetValue(value)); it != pad_mode_map.cend()) { + // 'pad_mode' attr could be an enumeration + pad_mode = it->second; + } else { + return; + } + } else { + MS_LOG(INFO) << "Node: " << node->fullname_with_scope() << " has no 'padding' or 'pad_mode' attr"; + return; + } + MS_LOG(INFO) << "Set 'padding' attr of node: " << node->fullname_with_scope() << " to " << pad_mode; + (void)op->SetAttr("padding", pad_mode); } -void DfGraphConvertor::ConvertOCRRecPreHandle(const CNodePtr node) { +void DfGraphConvertor::ConvertOCRRecPreHandle(const CNodePtr &node) { MS_LOG(INFO) << "Add OCRRecognitionPreHandle _op_max_shape attr"; OpAdapterPtr adpt = FindAdapter(node, training_); if (adpt == nullptr) { @@ -2455,10 +2506,7 @@ void DfGraphConvertor::ConvertOCRRecPreHandle(const CNodePtr node) { auto op = adpt->generate(node); MS_EXCEPTION_IF_NULL(op); // get shape form attr - auto value_node = node->input(0)->cast(); - MS_EXCEPTION_IF_NULL(value_node); - MS_EXCEPTION_IF_NULL(value_node->value()); - auto primitive = value_node->value()->cast(); + auto primitive = GetCNodePrimitive(node); MS_EXCEPTION_IF_NULL(primitive); auto value = primitive->GetAttr("_op_max_shape"); if (value == nullptr) { @@ -2517,33 +2565,26 @@ bool DfGraphConvertor::CheckCNode(const std::string &name, const CNodePtr node) return false; } - // Convert TopK second input from int64 to int32. - if (name == prim::kPrimTopK->name()) { - ConvertTopK(node); - return true; - } + const mindspore::HashMap> + auxiliary_node_converters{ + // Convert TopK second input from int64 to int32. + {prim::kPrimTopK->name(), &DfGraphConvertor::ConvertTopK}, + // Convert Reshape add const input to attr(shape) + {prim::kPrimReshape->name(), &DfGraphConvertor::ConvertReshape}, + {prim::kPrimOCRRecognitionPreHandle->name(), &DfGraphConvertor::ConvertOCRRecPreHandle}, + // Add attr 'pad_mode' to Conv2D-like op + {prim::kPrimConv2D->name(), &DfGraphConvertor::ConvertConv2D}, + {prim::kPrimDepthwiseConv2dNative->name(), &DfGraphConvertor::ConvertConv2D}, + {kNameConv2DBackpropInputV2, &DfGraphConvertor::ConvertConv2D}, + {prim::kPrimConv2DBackpropInput->name(), &DfGraphConvertor::ConvertConv2D}, + {prim::kPrimConv2DBackpropFilter->name(), &DfGraphConvertor::ConvertConv2D}, + // Add attr 'N' to DynamicStitch + {prim::kPrimDynamicStitch->name(), &DfGraphConvertor::ConvertDynamicStitch}, + {prim::kPrimAllReduce->name(), &DfGraphConvertor::ConvertAllReduce}, + }; - // Convert Reshape add const input to attr(shape) - if (name == prim::kPrimReshape->name()) { - ConvertReshape(node); - return true; - } - - if (name == prim::kPrimOCRRecognitionPreHandle->name()) { - ConvertOCRRecPreHandle(node); - return true; - } - - // Add attr pad mode to Conv2D - if (name == prim::kPrimConv2D->name() || name == prim::kPrimDepthwiseConv2dNative->name() || - name == kNameConv2DBackpropInputV2) { - ConvertConv2D(node); - return true; - } - - if (name == prim::kPrimAllReduce->name()) { - ConvertAllReduce(node); - return true; + if (const auto it = auxiliary_node_converters.find(name); it != auxiliary_node_converters.cend()) { + it->second(this, node); } return true; diff --git a/mindspore/ccsrc/transform/graph_ir/convert.h b/mindspore/ccsrc/transform/graph_ir/convert.h index 5892ea3a942..d1c62c224b1 100644 --- a/mindspore/ccsrc/transform/graph_ir/convert.h +++ b/mindspore/ccsrc/transform/graph_ir/convert.h @@ -156,6 +156,8 @@ class DfGraphConvertor { bool is_training() const { return training_; } void set_training(bool is_training) { training_ = is_training; } + bool dynamic_shape_inputs() const { return dynamic_shape_inputs_; } + std::vector input_shapes() { return input_shapes_; } protected: void InitLoopVar(std::vector<::ge::Operator> *init_input); @@ -178,15 +180,16 @@ class DfGraphConvertor { OperatorPtr ConvertValueNode(ValueNodePtr node); void SaveParamFormat(CNodePtr node); void GetBranchNodeInput(const CNodePtr node); - void ConvertTopK(const CNodePtr node); + void ConvertTopK(const CNodePtr &node); void ConvertResizeBilinear(const FuncGraphPtr anf_graph) const; void ConvertSpaceBatchNd(const FuncGraphPtr anf_graph) const; void ConvertTile(const FuncGraphPtr anf_graph) const; AnfNodePtr CreateCast(const AnfNodePtr &input, const TypePtr &dst_type) const; - void ConvertReshape(const CNodePtr node); - void ConvertAllReduce(const CNodePtr node); - void ConvertOCRRecPreHandle(const CNodePtr node); - void ConvertConv2D(const CNodePtr node); + void ConvertReshape(const CNodePtr &node); + void ConvertAllReduce(const CNodePtr &node); + void ConvertOCRRecPreHandle(const CNodePtr &node); + void ConvertConv2D(const CNodePtr &node); + void ConvertDynamicStitch(const CNodePtr &node); std::vector CastToInt(const ValuePtr &value) const; bool CheckCNode(const std::string &name, const CNodePtr node); void SetNodeInput(AnfNodePtr node); @@ -198,6 +201,7 @@ class DfGraphConvertor { void UpdateDataOpDesc(const AnfNodePtr &it, const OperatorPtr &op) const; void UpdateConstOpDesc(const AnfNodePtr &it, const OperatorPtr &op) const; void AddGraphConstInput(const OperatorPtr &op); + void AddGraphDynamicInput(const ParameterPtr ¶m); AnfNodePtr ParseLoadInput(const CNodePtr &cnode) const; void SetGraphInputs(std::vector *inputs); void TransformConstOp(const CNodePtr &node, const AnfNodePtr &pred); @@ -264,6 +268,7 @@ class DfGraphConvertor { std::vector init_ops_; std::vector broadcast_ops_; std::vector inputs_; + ShapeArray input_shapes_; OperatorPtr dataset_iter_getnext_; OperatorPtr queue_data_; OperatorPtr get_next_from_queue_; @@ -271,6 +276,7 @@ class DfGraphConvertor { bool training_ = false; bool distribute_ = false; bool use_inputs_ = false; + bool dynamic_shape_inputs_ = false; AnfNodePtr while_cond_node_ = nullptr; mindspore::HashMap>> while_dfgraph_cache_; diff --git a/mindspore/ccsrc/transform/graph_ir/op_adapter_map.h b/mindspore/ccsrc/transform/graph_ir/op_adapter_map.h index 838fef26b00..55f59b3df26 100644 --- a/mindspore/ccsrc/transform/graph_ir/op_adapter_map.h +++ b/mindspore/ccsrc/transform/graph_ir/op_adapter_map.h @@ -396,6 +396,9 @@ constexpr const char kNameTransData[] = "TransData"; constexpr const char kNameSend[] = "Send"; constexpr const char kNameReceive[] = "Receive"; constexpr const char kNameIndexAdd[] = "IndexAdd"; +constexpr const char kNameUnique[] = "Unique"; +constexpr const char kNameDynamicBroadcastGradientArgs[] = "DynamicBroadcastGradientArgs"; +constexpr const char kNameDynamicStitch[] = "DynamicStitch"; class OpAdapterDesc; diff --git a/mindspore/ccsrc/transform/graph_ir/op_declare/array_ops_declare.cc b/mindspore/ccsrc/transform/graph_ir/op_declare/array_ops_declare.cc index 34d67902e96..3f9ef5a1048 100644 --- a/mindspore/ccsrc/transform/graph_ir/op_declare/array_ops_declare.cc +++ b/mindspore/ccsrc/transform/graph_ir/op_declare/array_ops_declare.cc @@ -160,5 +160,15 @@ REG_ADPT_DESC(IdentityNMakeTuple, kNameMakeTuple, ADPT_DESC(IdentityN)) REG_ADPT_DESC(IdentityNDepend, kNameDepend, ADPT_DESC(IdentityN)) REG_ADPT_DESC(IdentityNReturn, kNameReturn, ADPT_DESC(IdentityN)) -// IdentityN +// Unique +INPUT_MAP(Unique) = {{1, INPUT_DESC(x)}}; +ATTR_MAP(Unique) = EMPTY_ATTR_MAP; +OUTPUT_MAP(Unique) = {{0, OUTPUT_DESC(y)}, {1, OUTPUT_DESC(idx)}}; +REG_ADPT_DESC(Unique, kNameUnique, ADPT_DESC(Unique)) + +// BroadcastGradientArgs +INPUT_MAP(BroadcastGradientArgs) = {{1, INPUT_DESC(x1)}, {2, INPUT_DESC(x2)}}; +ATTR_MAP(BroadcastGradientArgs) = EMPTY_ATTR_MAP; +OUTPUT_MAP(BroadcastGradientArgs) = {{0, OUTPUT_DESC(y1)}, {1, OUTPUT_DESC(y2)}}; +REG_ADPT_DESC(BroadcastGradientArgs, kNameDynamicBroadcastGradientArgs, ADPT_DESC(BroadcastGradientArgs)) } // namespace mindspore::transform diff --git a/mindspore/ccsrc/transform/graph_ir/op_declare/array_ops_declare.h b/mindspore/ccsrc/transform/graph_ir/op_declare/array_ops_declare.h index 587c49f6174..df25cd8fbae 100644 --- a/mindspore/ccsrc/transform/graph_ir/op_declare/array_ops_declare.h +++ b/mindspore/ccsrc/transform/graph_ir/op_declare/array_ops_declare.h @@ -84,5 +84,11 @@ DECLARE_OP_USE_OUTPUT(Identity) DECLARE_OP_ADAPTER(IdentityN) DECLARE_OP_USE_DYN_OUTPUT(IdentityN) + +DECLARE_OP_ADAPTER(Unique) +DECLARE_OP_USE_OUTPUT(Unique) + +DECLARE_OP_ADAPTER(BroadcastGradientArgs) +DECLARE_OP_USE_OUTPUT(BroadcastGradientArgs) } // namespace mindspore::transform #endif // MINDSPORE_CCSRC_TRANSFORM_GRAPH_IR_OP_DECLARE_ARRAY_OPS_DECLARE_H_ diff --git a/mindspore/ccsrc/transform/graph_ir/op_declare/data_flow_ops_declare.cc b/mindspore/ccsrc/transform/graph_ir/op_declare/data_flow_ops_declare.cc index 22e38d06272..6b60adcac23 100644 --- a/mindspore/ccsrc/transform/graph_ir/op_declare/data_flow_ops_declare.cc +++ b/mindspore/ccsrc/transform/graph_ir/op_declare/data_flow_ops_declare.cc @@ -40,4 +40,11 @@ ATTR_MAP(TensorArrayGather) = {{"dtype", ATTR_DESC(dtype, AnyTraits())}, {"element_shape", ATTR_DESC(element_shape, AnyTraits>())}}; OUTPUT_MAP(TensorArrayGather) = {{0, OUTPUT_DESC(value)}}; REG_ADPT_DESC(TensorArrayGather, kNameTensorArrayGather, ADPT_DESC(TensorArrayGather)) + +// DynamicStitch +INPUT_MAP(DynamicStitch) = EMPTY_INPUT_MAP; +DYN_INPUT_MAP(DynamicStitch) = {{1, DYN_INPUT_DESC(indices)}, {2, DYN_INPUT_DESC(x)}}; +ATTR_MAP(DynamicStitch) = EMPTY_ATTR_MAP; +OUTPUT_MAP(DynamicStitch) = {{0, OUTPUT_DESC(y)}}; +REG_ADPT_DESC(DynamicStitch, kNameDynamicStitch, ADPT_DESC(DynamicStitch)) } // namespace mindspore::transform diff --git a/mindspore/ccsrc/transform/graph_ir/op_declare/data_flow_ops_declare.h b/mindspore/ccsrc/transform/graph_ir/op_declare/data_flow_ops_declare.h index 49634719c74..333465a32aa 100644 --- a/mindspore/ccsrc/transform/graph_ir/op_declare/data_flow_ops_declare.h +++ b/mindspore/ccsrc/transform/graph_ir/op_declare/data_flow_ops_declare.h @@ -29,5 +29,8 @@ DECLARE_OP_USE_OUTPUT(TensorArrayWrite) DECLARE_OP_ADAPTER(TensorArrayGather) DECLARE_OP_USE_OUTPUT(TensorArrayGather) + +DECLARE_OP_ADAPTER(DynamicStitch) +DECLARE_OP_USE_OUTPUT(DynamicStitch) } // namespace mindspore::transform #endif // MINDSPORE_CCSRC_TRANSFORM_GRAPH_IR_OP_DECLARE_DATA_FLOW_OPS_DECLARE_H_ diff --git a/tests/st/ge/ge_pass/ge_infer_env.py b/tests/st/ge/ge_infer_env.py similarity index 99% rename from tests/st/ge/ge_pass/ge_infer_env.py rename to tests/st/ge/ge_infer_env.py index 893386f175d..5f1aaa2ab76 100644 --- a/tests/st/ge/ge_pass/ge_infer_env.py +++ b/tests/st/ge/ge_infer_env.py @@ -14,5 +14,6 @@ # ============================================================================ import os + os.environ['MS_ENABLE_GE'] = '1' os.environ['MS_GE_TRAIN'] = '0' diff --git a/tests/st/ge/ge_pass/ge_convert.py b/tests/st/ge/ge_pass/ge_convert.py index 8b42d4005a5..5fbfe0fe836 100644 --- a/tests/st/ge/ge_pass/ge_convert.py +++ b/tests/st/ge/ge_pass/ge_convert.py @@ -13,7 +13,7 @@ # limitations under the License. # ============================================================================ import numpy as np -import ge_train_env # pylint: disable=unused-import +from tests.st.ge import ge_train_env # pylint: disable=unused-import import mindspore as ms import mindspore.context as context import mindspore.nn as nn diff --git a/tests/st/ge/ge_pass/pass_avg_pool_grad.py b/tests/st/ge/ge_pass/pass_avg_pool_grad.py index 3abbf1810bc..b1ac899d3f0 100644 --- a/tests/st/ge/ge_pass/pass_avg_pool_grad.py +++ b/tests/st/ge/ge_pass/pass_avg_pool_grad.py @@ -15,7 +15,7 @@ """ test ge frontend pass `AvgPoolGradForGE` """ import numpy as np -import ge_infer_env # pylint: disable=unused-import +from tests.st.ge import ge_infer_env # pylint: disable=unused-import import mindspore.context as context import mindspore.nn as nn from mindspore.ops import operations as op diff --git a/tests/st/ge/ge_pass/pass_convert_attr_to_input.py b/tests/st/ge/ge_pass/pass_convert_attr_to_input.py index 9c846db2063..f45dc745e8c 100644 --- a/tests/st/ge/ge_pass/pass_convert_attr_to_input.py +++ b/tests/st/ge/ge_pass/pass_convert_attr_to_input.py @@ -14,7 +14,7 @@ # ============================================================================ import numpy as np -import ge_infer_env # pylint: disable=unused-import +from tests.st.ge import ge_infer_env # pylint: disable=unused-import import mindspore from mindspore import context, nn, Tensor, ops diff --git a/tests/st/ge/ge_pass/pass_convert_resize_nearest_neighbor_x_dtype.py b/tests/st/ge/ge_pass/pass_convert_resize_nearest_neighbor_x_dtype.py index 9ec49cff19b..663c09d7078 100644 --- a/tests/st/ge/ge_pass/pass_convert_resize_nearest_neighbor_x_dtype.py +++ b/tests/st/ge/ge_pass/pass_convert_resize_nearest_neighbor_x_dtype.py @@ -14,7 +14,7 @@ # ============================================================================ import numpy as np -import ge_infer_env # pylint: disable=unused-import +from tests.st.ge import ge_infer_env # pylint: disable=unused-import import mindspore from mindspore import context, nn, Tensor, ops diff --git a/tests/st/ge/ge_pass/pass_dropout.py b/tests/st/ge/ge_pass/pass_dropout.py index 3f508e0c684..c9d9d854171 100644 --- a/tests/st/ge/ge_pass/pass_dropout.py +++ b/tests/st/ge/ge_pass/pass_dropout.py @@ -15,7 +15,7 @@ """ test ge frontend pass `DropoutForGE` `DropoutGradForGE` """ import numpy as np -import ge_infer_env # pylint: disable=unused-import +from tests.st.ge import ge_infer_env # pylint: disable=unused-import from mindspore import ops, nn, context, Tensor from mindspore.ops.composite import GradOperation diff --git a/tests/st/ge/ge_pass/pass_reduce_axis_update.py b/tests/st/ge/ge_pass/pass_reduce_axis_update.py index a5df51f5c09..62445f565cc 100644 --- a/tests/st/ge/ge_pass/pass_reduce_axis_update.py +++ b/tests/st/ge/ge_pass/pass_reduce_axis_update.py @@ -14,7 +14,7 @@ # ============================================================================ import numpy as np -import ge_infer_env # pylint: disable=unused-import +from tests.st.ge import ge_infer_env # pylint: disable=unused-import import mindspore from mindspore import context, nn, Tensor, ops diff --git a/tests/st/ge/ge_pass/pass_tensor_array.py b/tests/st/ge/ge_pass/pass_tensor_array.py index 611656f2a19..96a5ed2f647 100644 --- a/tests/st/ge/ge_pass/pass_tensor_array.py +++ b/tests/st/ge/ge_pass/pass_tensor_array.py @@ -15,7 +15,7 @@ """ test ge frontend pass and op `TensorArray`""" import numpy as np -import ge_infer_env # pylint: disable=unused-import +from tests.st.ge import ge_infer_env # pylint: disable=unused-import import mindspore.context as context from mindspore import nn from mindspore import Tensor diff --git a/tests/st/ge/ge_pass/test_ge_convert.py b/tests/st/ge/ge_pass/test_ge_convert.py index 9d4953a6766..38a6b0e7d17 100644 --- a/tests/st/ge/ge_pass/test_ge_convert.py +++ b/tests/st/ge/ge_pass/test_ge_convert.py @@ -13,7 +13,7 @@ # limitations under the License. # ============================================================================ import pytest -import ge_test_utils as utils +import tests.st.ge.ge_test_utils as utils @pytest.mark.level0 diff --git a/tests/st/ge/ge_pass/test_ge_passes.py b/tests/st/ge/ge_pass/test_ge_passes.py index 83a0980f058..257f0097ffb 100644 --- a/tests/st/ge/ge_pass/test_ge_passes.py +++ b/tests/st/ge/ge_pass/test_ge_passes.py @@ -13,7 +13,7 @@ # limitations under the License. # ============================================================================ import pytest -import ge_test_utils as utils +import tests.st.ge.ge_test_utils as utils @pytest.mark.level1 diff --git a/tests/st/ge/ge_pass/ge_test_utils.py b/tests/st/ge/ge_test_utils.py similarity index 90% rename from tests/st/ge/ge_pass/ge_test_utils.py rename to tests/st/ge/ge_test_utils.py index 187de4722e3..47a930657b4 100644 --- a/tests/st/ge/ge_pass/ge_test_utils.py +++ b/tests/st/ge/ge_test_utils.py @@ -12,11 +12,14 @@ # See the License for the specific language governing permissions and # limitations under the License. # ============================================================================ +import inspect import os import sys def run_testcase(file_name, case_name=""): + caller_working_dir = os.path.dirname(inspect.stack()[1][1]) + os.chdir(caller_working_dir) log_file = file_name + "_" + case_name + '.log' if case_name == "": ret = os.system(f'{sys.executable} {file_name}.py &> {log_file}') diff --git a/tests/st/ge/ge_pass/ge_train_env.py b/tests/st/ge/ge_train_env.py similarity index 99% rename from tests/st/ge/ge_pass/ge_train_env.py rename to tests/st/ge/ge_train_env.py index fedac9548a1..9319afe06b4 100644 --- a/tests/st/ge/ge_pass/ge_train_env.py +++ b/tests/st/ge/ge_train_env.py @@ -14,5 +14,6 @@ # ============================================================================ import os + os.environ['MS_ENABLE_GE'] = '1' os.environ['MS_GE_TRAIN'] = '1' diff --git a/tests/st/ge/ops/broadcast_gradient_args.py b/tests/st/ge/ops/broadcast_gradient_args.py new file mode 100644 index 00000000000..eb30d3d7d69 --- /dev/null +++ b/tests/st/ge/ops/broadcast_gradient_args.py @@ -0,0 +1,53 @@ +# Copyright 2022 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. +# ============================================================================ +from tests.st.ge import ge_infer_env # pylint: disable=unused-import +import numpy as np +import mindspore.nn as nn +import mindspore.context as context +from mindspore.ops.operations import _inner_ops + + +context.set_context(mode=context.GRAPH_MODE, device_target="Ascend") + + +class Net(nn.Cell): + def __init__(self): + super(Net, self).__init__() + self.args = _inner_ops.DynamicBroadcastGradientArgs() + + def construct(self, s0, s1): + r = self.args(s0, s1) + return (r[0], r[1]) + + +def test_broadcast_gradient_args(): + """ + Feature: for DynamicBroadcastGradientArgs op + Description: inputs are two shapes + Expectation: the result is correct + """ + shape0 = (4, 2, 1) + shape1 = (2, 7) + net = Net() + r0, r1 = net(shape0, shape1) + r0_expected = [2] + r1_expected = [0] + + assert np.array_equal(r0_expected, r0.asnumpy()) + assert np.array_equal(r1_expected, r1.asnumpy()) + + +if __name__ == "__main__": + test_broadcast_gradient_args() diff --git a/tests/st/ge/ops/conv2d_backprop_filter.py b/tests/st/ge/ops/conv2d_backprop_filter.py new file mode 100644 index 00000000000..b9af8aae26a --- /dev/null +++ b/tests/st/ge/ops/conv2d_backprop_filter.py @@ -0,0 +1,81 @@ +# Copyright 2022 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. +# ============================================================================ +from tests.st.ge import ge_infer_env # pylint: disable=unused-import +import numpy as np +import mindspore.context as context +import mindspore.nn as nn +from mindspore import Tensor +from mindspore.common.api import ms_function +from mindspore.common.initializer import initializer +from mindspore.common.parameter import Parameter +from mindspore.ops import operations as P +from mindspore.ops.operations import _grad_ops as G + + +context.set_context(mode=context.GRAPH_MODE, device_target="Ascend") + + +class Net(nn.Cell): + def __init__(self): + super(Net, self).__init__() + out_channel = 4 + kernel_size = 1 + self.conv_filter = G.Conv2DBackpropFilter(out_channel, + kernel_size, + pad_mode="valid", + pad=0, + mode=1, + stride=1, + dilation=1, + group=1) + self.w = Parameter( + initializer(Tensor(np.array( + [[[[1, 0, -1], [1, 0, -1], [1, 0, -1]]]]).astype(np.float32)), [1, 1, 3, 3]), + name='w') + self.x = Parameter(initializer(Tensor(np.array([[[ + [3, 0, 1, 2, 7, 4], + [1, 5, 8, 9, 3, 1], + [2, 7, 2, 5, 1, 3], + [0, 1, 3, 1, 7, 8], + [4, 2, 1, 6, 2, 8], + [2, 4, 5, 2, 3, 9]]]]).astype(np.float32)), [1, 1, 6, 6]), name='x') + self.out = Parameter(initializer(Tensor(np.array([[[ + [-5, -4, 0, 8], + [-10, -2, 2, 3], + [0, -2, -4, -7], + [-3, -2, -3, -16]]]]).astype(np.float32)), [1, 1, 4, 4]), name='y') + self.get_shape = P.Shape() + + @ms_function + def construct(self): + return self.conv_filter(self.out, self.x, self.get_shape(self.w)) + + +def test_conv2d_backprop_filter(): + """ + Feature: for Conv2DBackpropFilter op + Description: inputs are integers + Expectation: the result is correct + """ + conv2d_filter = Net() + output = conv2d_filter() + expect = np.array([[[[-60, -142, -265], + [-104, -211, -322], + [-102, -144, -248]]]]).astype(np.float32) + assert (output.asnumpy() == expect).all() + + +if __name__ == "__main__": + test_conv2d_backprop_filter() diff --git a/tests/st/ge/ops/conv2d_backprop_input.py b/tests/st/ge/ops/conv2d_backprop_input.py new file mode 100644 index 00000000000..b6c2cc20aa1 --- /dev/null +++ b/tests/st/ge/ops/conv2d_backprop_input.py @@ -0,0 +1,83 @@ +# Copyright 2022 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. +# ============================================================================ +from tests.st.ge import ge_infer_env # pylint: disable=unused-import +import numpy as np +import mindspore.context as context +import mindspore.nn as nn +from mindspore import Tensor +from mindspore.common.api import ms_function +from mindspore.common.initializer import initializer +from mindspore.common.parameter import Parameter +from mindspore.ops import operations as P + + +context.set_context(mode=context.GRAPH_MODE, device_target="Ascend") + + +class Net(nn.Cell): + def __init__(self): + super(Net, self).__init__() + out_channel = 4 + kernel_size = 1 + self.conv_input = P.Conv2DBackpropInput(out_channel, + kernel_size, + pad_mode="valid", + pad=0, + mode=1, + stride=1, + dilation=1, + group=1) + self.w = Parameter( + initializer(Tensor(np.array( + [[[[1, 0, -1], [1, 0, -1], [1, 0, -1]]]]).astype(np.float32)), [1, 1, 3, 3]), + name='w') + self.x = Parameter(initializer(Tensor(np.array([[[ + [3, 0, 1, 2, 7, 4], + [1, 5, 8, 9, 3, 1], + [2, 7, 2, 5, 1, 3], + [0, 1, 3, 1, 7, 8], + [4, 2, 1, 6, 2, 8], + [2, 4, 5, 2, 3, 9]]]]).astype(np.float32)), [1, 1, 6, 6]), name='x') + self.out = Parameter(initializer(Tensor(np.array([[[ + [-5, -4, 0, 8], + [-10, -2, 2, 3], + [0, -2, -4, -7], + [-3, -2, -3, -16]]]]).astype(np.float32)), [1, 1, 4, 4]), name='y') + self.get_shape = P.Shape() + + @ms_function + def construct(self): + return self.conv_input(self.out, self.w, self.get_shape(self.x)) + + +def test_conv2d_backprop_input(): + """ + Feature: for Conv2DBackpropInput op + Description: inputs are integers + Expectation: the result is correct + """ + conv2d_input = Net() + output = conv2d_input() + expect = np.array([[[[-5, -4, 5, 12, 0, -8], + [-15, -6, 17, 17, -2, -11], + [-15, -8, 13, 12, 2, -4], + [-13, -6, 8, -14, 5, 20], + [-3, -4, -4, -19, 7, 23], + [-3, -2, 0, -14, 3, 16]]]]).astype(np.float32) + assert (output.asnumpy() == expect).all() + + +if __name__ == "__main__": + test_conv2d_backprop_input() diff --git a/tests/st/ge/ops/conv2d_transpose.py b/tests/st/ge/ops/conv2d_transpose.py new file mode 100644 index 00000000000..38ab5eccf8d --- /dev/null +++ b/tests/st/ge/ops/conv2d_transpose.py @@ -0,0 +1,83 @@ +# Copyright 2022 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. +# ============================================================================ +from tests.st.ge import ge_infer_env # pylint: disable=unused-import +import numpy as np +import mindspore.context as context +import mindspore.nn as nn +from mindspore import Tensor +from mindspore.common.api import ms_function +from mindspore.common.initializer import initializer +from mindspore.common.parameter import Parameter +from mindspore.ops import operations as P + + +context.set_context(mode=context.GRAPH_MODE, device_target="Ascend") + + +class Net(nn.Cell): + def __init__(self): + super(Net, self).__init__() + out_channel = 4 + kernel_size = 1 + self.conv_input = P.Conv2DTranspose(out_channel, + kernel_size, + pad_mode="valid", + pad=0, + mode=1, + stride=1, + dilation=1, + group=1) + self.w = Parameter( + initializer(Tensor(np.array( + [[[[1, 0, -1], [1, 0, -1], [1, 0, -1]]]]).astype(np.float32)), [1, 1, 3, 3]), + name='w') + self.x = Parameter(initializer(Tensor(np.array([[[ + [3, 0, 1, 2, 7, 4], + [1, 5, 8, 9, 3, 1], + [2, 7, 2, 5, 1, 3], + [0, 1, 3, 1, 7, 8], + [4, 2, 1, 6, 2, 8], + [2, 4, 5, 2, 3, 9]]]]).astype(np.float32)), [1, 1, 6, 6]), name='x') + self.out = Parameter(initializer(Tensor(np.array([[[ + [-5, -4, 0, 8], + [-10, -2, 2, 3], + [0, -2, -4, -7], + [-3, -2, -3, -16]]]]).astype(np.float32)), [1, 1, 4, 4]), name='y') + self.get_shape = P.Shape() + + @ms_function + def construct(self): + return self.conv_input(self.out, self.w, self.get_shape(self.x)) + + +def test_conv2d_transpose(): + """ + Feature: for Conv2DTranspose op + Description: inputs are integers + Expectation: the result is correct + """ + conv2d_input = Net() + output = conv2d_input() + expect = np.array([[[[-5, -4, 5, 12, 0, -8], + [-15, -6, 17, 17, -2, -11], + [-15, -8, 13, 12, 2, -4], + [-13, -6, 8, -14, 5, 20], + [-3, -4, -4, -19, 7, 23], + [-3, -2, 0, -14, 3, 16]]]]).astype(np.float32) + assert (output.asnumpy() == expect).all() + + +if __name__ == "__main__": + test_conv2d_transpose() diff --git a/tests/st/ge/ops/dynamic_broadcast_to.py b/tests/st/ge/ops/dynamic_broadcast_to.py new file mode 100644 index 00000000000..8ea7a2028f1 --- /dev/null +++ b/tests/st/ge/ops/dynamic_broadcast_to.py @@ -0,0 +1,54 @@ +# Copyright 2022 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. +# ============================================================================ +from tests.st.ge import ge_infer_env # pylint: disable=unused-import +import numpy as np +import mindspore.context as context +import mindspore.common.dtype as mstype +import mindspore.nn as nn +import mindspore.ops.operations as ops +from mindspore import Tensor +from mindspore.ops.operations import _inner_ops as inner + + +context.set_context(mode=context.GRAPH_MODE, device_target="Ascend") + + +class Net(nn.Cell): + def __init__(self): + super(Net, self).__init__() + self.d_shape = ops.TensorShape() + self.d_broadcastto = inner.DynamicBroadcastTo() + + def construct(self, data, shape): + shape = self.d_shape(shape) + return self.d_broadcastto(data, shape) + + +def test_dynamic_broadcast_to(): + """ + Feature: for DynamicBroadcastTo op + Description: inputs are data and shape + Expectation: the result is correct + """ + data = Tensor(np.array([1, 2, 3]), mstype.float32) + shape = Tensor(np.zeros((2, 3)), mstype.int64) + expect_data = np.array([[1, 2, 3], [1, 2, 3]]).astype(np.float32) + net = Net() + output = net(data, shape) + assert np.array_equal(output.asnumpy(), expect_data) + + +if __name__ == "__main__": + test_dynamic_broadcast_to() diff --git a/tests/st/ge/ops/test_ge_ops.py b/tests/st/ge/ops/test_ge_ops.py new file mode 100644 index 00000000000..f81ea1ba67e --- /dev/null +++ b/tests/st/ge/ops/test_ge_ops.py @@ -0,0 +1,94 @@ +# Copyright 2022 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. +# ============================================================================ +import pytest +import tests.st.ge.ge_test_utils as utils + + +@pytest.mark.level0 +@pytest.mark.platform_arm_ascend_training +@pytest.mark.platform_x86_ascend_training +@pytest.mark.env_onecard +def test_broadcast_gradient_args(): + """ + Feature: for DynamicBroadcastGradientArgs op + Description: inputs are two shapes + Expectation: the result is correct + """ + utils.run_testcase('broadcast_gradient_args') + + +@pytest.mark.level0 +@pytest.mark.platform_arm_ascend_training +@pytest.mark.platform_x86_ascend_training +@pytest.mark.env_onecard +def test_conv2d_backprop_filter(): + """ + Feature: for Conv2DBackpropFilter op + Description: inputs are integers + Expectation: the result is correct + """ + utils.run_testcase('conv2d_backprop_filter') + + +@pytest.mark.level0 +@pytest.mark.platform_arm_ascend_training +@pytest.mark.platform_x86_ascend_training +@pytest.mark.env_onecard +def test_conv2d_backprop_input(): + """ + Feature: for Conv2DBackpropInput op + Description: inputs are integers + Expectation: the result is correct + """ + utils.run_testcase('conv2d_backprop_input') + + +@pytest.mark.level0 +@pytest.mark.platform_arm_ascend_training +@pytest.mark.platform_x86_ascend_training +@pytest.mark.env_onecard +def test_conv2d_transpose(): + """ + Feature: for Conv2DTranspose op + Description: inputs are integers + Expectation: the result is correct + """ + utils.run_testcase('conv2d_transpose') + + +@pytest.mark.level0 +@pytest.mark.platform_arm_ascend_training +@pytest.mark.platform_x86_ascend_training +@pytest.mark.env_onecard +def test_dynamic_broadcast_to(): + """ + Feature: for DynamicBroadcastTo op + Description: inputs are data and shape + Expectation: the result is correct + """ + utils.run_testcase('dynamic_broadcast_to') + + +@pytest.mark.level0 +@pytest.mark.platform_arm_ascend_training +@pytest.mark.platform_x86_ascend_training +@pytest.mark.env_onecard +def test_unique(): + """ + Feature: for Unique op + Description: inputs are integers + Expectation: the result is correct + """ + utils.run_testcase('unique') diff --git a/tests/st/ge/ops/unique.py b/tests/st/ge/ops/unique.py new file mode 100644 index 00000000000..edf72c55192 --- /dev/null +++ b/tests/st/ge/ops/unique.py @@ -0,0 +1,53 @@ +# Copyright 2022 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. +# ============================================================================ +from tests.st.ge import ge_infer_env # pylint: disable=unused-import +import numpy as np +import mindspore.context as context +import mindspore.nn as nn +from mindspore import Tensor +import mindspore.common.dtype as mstype +from mindspore.ops import operations as P + + +context.set_context(mode=context.GRAPH_MODE, device_target="Ascend") + + +class Net(nn.Cell): + def __init__(self): + super(Net, self).__init__() + self.unique = P.Unique() + + def construct(self, x): + x = self.unique(x) + return (x[0], x[1]) + + +def test_unique(): + """ + Feature: for Unique op + Description: inputs are integers + Expectation: the result is correct + """ + x = Tensor(np.array([1, 1, 2, 3, 3, 3]), mstype.int32) + unique = Net() + output = unique(x) + expect1 = np.array([1, 2, 3]) + expect2 = np.array([0, 0, 1, 2, 2, 2]) + assert (output[0].asnumpy() == expect1).all() + assert (output[1].asnumpy() == expect2).all() + + +if __name__ == "__main__": + test_unique()