| @@ -0,0 +1,732 @@ |
| + |
| + * Copyright (c) 2026 Huawei Technologies Co., Ltd. |
| + * This program is free software, you can redistribute it and/or modify it under the terms and conditions of |
| + * CANN Open Software License Agreement Version 2.0 (the "License"). |
| + * Please refer to the License for details. You may not use this file except in compliance with the License. |
| + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, |
| + * INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. |
| + * See LICENSE in the root of the software repository for the full text of the License. |
| + */ |
| +#include <iostream> |
| +#include <vector> |
| +#include <gtest/gtest.h> |
| +#include "platform/platform_infos_def.h" |
| +#include "ut_op_util.h" |
| +#include "platform/platform_info.h" |
| +#include "ge/es_graph_builder.h" |
| +#include "ge/compliant_node_builder.h" |
| +#include "../../../op_graph/fusion_pass/softmax_grad_ext_fusion_pass.h" |
| +#include "register/register_custom_pass.h" |
| + |
| +using namespace ut_util; |
| +using namespace std; |
| +using namespace ge; |
| +using namespace fe; |
| +using namespace es; |
| +using namespace ops; |
| + |
| +namespace { |
| +const int32_t kVariantV1 = -1; |
| +const int32_t kExpectedNodeCount = 5; |
| + |
| +void SetOutDesc(const EsTensorHolder& holder, DataType dtype, const vector<int64_t>& dims) |
| +{ |
| + TensorDesc desc; |
| + holder.GetProducer()->GetOutputDesc(0, desc); |
| + desc.SetDataType(dtype); |
| + desc.SetShape(ge::Shape(dims)); |
| + holder.GetProducer()->UpdateOutputDesc(0, desc); |
| +} |
| + |
| +void SetInDesc(const GNode& node, int32_t idx, DataType dtype, const vector<int64_t>& dims) |
| +{ |
| + TensorDesc desc; |
| + node.GetInputDesc(idx, desc); |
| + desc.SetDataType(dtype); |
| + desc.SetShape(ge::Shape(dims)); |
| + const_cast<GNode&>(node).UpdateInputDesc(idx, desc); |
| +} |
| + |
| +vector<int64_t> ReduceShape(const vector<int64_t>& dims, int64_t axis, bool keepDims) |
| +{ |
| + int64_t rank = static_cast<int64_t>(dims.size()); |
| + int64_t a = axis < 0 ? axis + rank : axis; |
| + vector<int64_t> out; |
| + for (int64_t i = 0; i < rank; ++i) { |
| + if (i == a) { |
| + if (keepDims) { |
| + out.push_back(1); |
| + } |
| + } else { |
| + out.push_back(dims[i]); |
| + } |
| + } |
| + return out; |
| +} |
| +EsTensorHolder BuildBinaryNode(EsGraphBuilder& builder, const EsTensorHolder& in0, const EsTensorHolder& in1, |
| + const char* opType) |
| +{ |
| + auto* c_builder = builder.GetCGraphBuilder(); |
| + auto* graph = c_builder->GetGraph(); |
| + GNode node = CompliantNodeBuilder(graph) |
| + .OpType(opType) |
| + .Name(c_builder->GenerateNodeName(opType).GetString()) |
| + .IrDefInputs({{"x1", CompliantNodeBuilder::kEsIrInputRequired, ""}, |
| + {"x2", CompliantNodeBuilder::kEsIrInputRequired, ""}}) |
| + .IrDefOutputs({{"y", CompliantNodeBuilder::kEsIrOutputRequired, ""}}) |
| + .Build(); |
| + AddEdgeAndUpdatePeerDesc(*graph, *in0.GetProducer(), in0.GetProducerOutIndex(), node, 0); |
| + AddEdgeAndUpdatePeerDesc(*graph, *in1.GetProducer(), in1.GetProducerOutIndex(), node, 1); |
| + return EsTensorHolder(c_builder->GetTensorHolderFromNode(node, 0)); |
| +} |
| + |
| +EsTensorHolder BuildReduceSum(EsGraphBuilder& builder, const EsTensorHolder& in0, const EsTensorHolder& axes, |
| + bool keepDims) |
| +{ |
| + auto* c_builder = builder.GetCGraphBuilder(); |
| + auto* graph = c_builder->GetGraph(); |
| + GNode node = CompliantNodeBuilder(graph) |
| + .OpType("ReduceSum") |
| + .Name(c_builder->GenerateNodeName("ReduceSum").GetString()) |
| + .IrDefInputs({{"x", CompliantNodeBuilder::kEsIrInputRequired, ""}, |
| + {"axes", CompliantNodeBuilder::kEsIrInputRequired, ""}}) |
| + .IrDefOutputs({{"y", CompliantNodeBuilder::kEsIrOutputRequired, ""}}) |
| + .IrDefAttrs( |
| + {{"keep_dims", CompliantNodeBuilder::kEsAttrOptional, "Bool", CreateFrom(keepDims)}, |
| + {"noop_with_empty_axes", CompliantNodeBuilder::kEsAttrOptional, "Bool", CreateFrom(true)}}) |
| + .Build(); |
| + AddEdgeAndUpdatePeerDesc(*graph, *in0.GetProducer(), in0.GetProducerOutIndex(), node, 0); |
| + AddEdgeAndUpdatePeerDesc(*graph, *axes.GetProducer(), axes.GetProducerOutIndex(), node, 1); |
| + return EsTensorHolder(c_builder->GetTensorHolderFromNode(node, 0)); |
| +} |
| +struct BuiltGraph { |
| + shared_ptr<Graph> graph; |
| +}; |
| + |
| + |
| + |
| + |
| +BuiltGraph BuildSoftmaxGradGraph(DataType dtype, const vector<int64_t>& dims, int64_t axis, bool keepDims, |
| + int32_t variant) |
| +{ |
| + EsGraphBuilder builder("softmax_grad_ext_fusion_test"); |
| + auto grad = builder.CreateInput(0, "grad", dtype, FORMAT_ND, dims); |
| + auto x1 = builder.CreateInput(1, "x1", dtype, FORMAT_ND, dims); |
| + auto x2 = builder.CreateInput(2, "x2", dtype, FORMAT_ND, dims); |
| + SetOutDesc(grad, dtype, dims); |
| + SetOutDesc(x1, dtype, dims); |
| + SetOutDesc(x2, dtype, dims); |
| + |
| + auto mul = BuildBinaryNode(builder, grad, x1, "Mul"); |
| + auto axes = builder.CreateConst(std::vector<int64_t>{axis}, {1}); |
| + auto sum = BuildReduceSum(builder, mul, axes, keepDims); |
| + auto sub = BuildBinaryNode(builder, grad, sum, "Sub"); |
| + |
| + EsTensorHolder mul1; |
| + EsTensorHolder mulGrad; |
| + if (variant == kVariantV1) { |
| + mul1 = BuildBinaryNode(builder, x2, x1, "Mul"); |
| + mulGrad = BuildBinaryNode(builder, mul1, sub, "Mul"); |
| + } else { |
| + switch (variant) { |
| + case 0: |
| + mul1 = BuildBinaryNode(builder, x1, sub, "Mul"); |
| + mulGrad = BuildBinaryNode(builder, mul1, x2, "Mul"); |
| + break; |
| + case 1: |
| + mul1 = BuildBinaryNode(builder, sub, x1, "Mul"); |
| + mulGrad = BuildBinaryNode(builder, mul1, x2, "Mul"); |
| + break; |
| + case 2: |
| + mul1 = BuildBinaryNode(builder, x1, sub, "Mul"); |
| + mulGrad = BuildBinaryNode(builder, x2, mul1, "Mul"); |
| + break; |
| + default: |
| + mul1 = BuildBinaryNode(builder, sub, x1, "Mul"); |
| + mulGrad = BuildBinaryNode(builder, x2, mul1, "Mul"); |
| + break; |
| + } |
| + } |
| + |
| + |
| + const vector<int64_t> reduced = ReduceShape(dims, axis, keepDims); |
| + SetInDesc(*mul.GetProducer(), 0, dtype, dims); |
| + SetInDesc(*mul.GetProducer(), 1, dtype, dims); |
| + SetOutDesc(mul, dtype, dims); |
| + SetInDesc(*sum.GetProducer(), 0, dtype, dims); |
| + SetInDesc(*sum.GetProducer(), 1, DT_INT64, {1}); |
| + SetOutDesc(sum, dtype, reduced); |
| + SetInDesc(*sub.GetProducer(), 0, dtype, dims); |
| + SetInDesc(*sub.GetProducer(), 1, dtype, reduced); |
| + SetOutDesc(sub, dtype, dims); |
| + SetInDesc(*mul1.GetProducer(), 0, dtype, dims); |
| + SetInDesc(*mul1.GetProducer(), 1, dtype, dims); |
| + SetOutDesc(mul1, dtype, dims); |
| + SetInDesc(*mulGrad.GetProducer(), 0, dtype, dims); |
| + SetInDesc(*mulGrad.GetProducer(), 1, dtype, dims); |
| + SetOutDesc(mulGrad, dtype, dims); |
| + |
| + BuiltGraph ret; |
| + ret.graph = builder.BuildAndReset({mulGrad}); |
| + return ret; |
| +} |
| + |
| +void SetPlatform(const string& soc) |
| +{ |
| + PlatformInfo platformInfo; |
| + OptionalInfo optiCompilationInfo; |
| + platformInfo.soc_info.ai_core_cnt = 64; |
| + platformInfo.str_info.short_soc_version = soc; |
| + optiCompilationInfo.soc_version = soc; |
| + PlatformInfoManager::Instance().platform_info_map_[soc] = platformInfo; |
| + PlatformInfoManager::Instance().SetOptionalCompilationInfo(optiCompilationInfo); |
| +} |
| +} |
| + |
| +class SoftmaxGradExtFusionPassTest : public testing::Test { |
| +protected: |
| + static void SetUpTestCase() { SetPlatform("Ascend950"); } |
| + void SetUp() override { SetPlatform("Ascend950"); } |
| + |
| + |
| + bool IsSoftmaxGradExtInputRight(GNode& node, const vector<int64_t>& dims, DataType dtype) |
| + { |
| + TensorDesc input0Desc; |
| + TensorDesc input1Desc; |
| + TensorDesc input2Desc; |
| + node.GetInputDesc(0, input0Desc); |
| + node.GetInputDesc(1, input1Desc); |
| + node.GetInputDesc(2, input2Desc); |
| + if (input0Desc.GetDataType() != dtype || input1Desc.GetDataType() != dtype || |
| + input2Desc.GetDataType() != dtype) { |
| + return false; |
| + } |
| + int64_t expectedSize = 1; |
| + for (auto d : dims) { |
| + expectedSize *= d; |
| + } |
| + if (input0Desc.GetShape().GetShapeSize() != expectedSize || |
| + input1Desc.GetShape().GetShapeSize() != expectedSize || |
| + input2Desc.GetShape().GetShapeSize() != expectedSize) { |
| + return false; |
| + } |
| + return true; |
| + } |
| + |
| + |
| + |
| + void ExpectFused(const shared_ptr<Graph>& graph, int64_t axis, bool keepDims, DataType dtype, |
| + const vector<int64_t>& dims) |
| + { |
| + bool found = false; |
| + int32_t nodeCount = 0; |
| + int32_t mulSubReduceCount = 0; |
| + for (auto node : graph->GetAllNodes()) { |
| + nodeCount++; |
| + AscendString type; |
| + node.GetType(type); |
| + if (type == "Mul" || type == "Sub" || type == "ReduceSum") { |
| + mulSubReduceCount++; |
| + } |
| + if (type == "SoftmaxGradExt") { |
| + found = true; |
| + int64_t axesAttr = 1; |
| + bool keepDimsAttr = true; |
| + if (node.GetAttr(AscendString("axes"), axesAttr) != GRAPH_SUCCESS) { |
| + axesAttr = 1; |
| + } |
| + if (node.GetAttr(AscendString("keep_dims"), keepDimsAttr) != GRAPH_SUCCESS) { |
| + keepDimsAttr = true; |
| + } |
| + EXPECT_EQ(axesAttr, axis); |
| + EXPECT_EQ(keepDimsAttr, keepDims); |
| + |
| + for (int32_t i = 0; i < 3; ++i) { |
| + auto src = node.GetInDataNodesAndPortIndexs(i); |
| + AscendString srcName; |
| + src.first->GetName(srcName); |
| + std::string expected = (i == 0) ? "grad" : (i == 1) ? "x1" : "x2"; |
| + std::string actual = srcName.GetString(); |
| + EXPECT_NE(actual.find(expected), std::string::npos) |
| + << "input " << i << " expected " << expected << " got " << actual; |
| + } |
| + EXPECT_TRUE(IsSoftmaxGradExtInputRight(node, dims, dtype)); |
| + } |
| + } |
| + EXPECT_TRUE(found); |
| + EXPECT_EQ(mulSubReduceCount, 0); |
| + EXPECT_EQ(nodeCount, kExpectedNodeCount); |
| + } |
| +}; |
| + |
| + |
| + |
| +TEST_F(SoftmaxGradExtFusionPassTest, v1_fp16_axis_neg1_keepdims_true_success) |
| +{ |
| + vector<int64_t> dims{2, 32, 128}; |
| + auto built = BuildSoftmaxGradGraph(DT_FLOAT16, dims, -1, true, kVariantV1); |
| + built.graph->DumpToFile(Graph::DumpFormat::kOnnx, "dump_graph_for_softmax_grad_ext_v1_test1"); |
| + CustomPassContext ctx; |
| + SoftmaxGradExtFusionPass pass; |
| + EXPECT_EQ(pass.Run(built.graph, ctx), SUCCESS); |
| + built.graph->DumpToFile(Graph::DumpFormat::kOnnx, "dump_afterpass_graph_for_softmax_grad_ext_v1_test1"); |
| + ExpectFused(built.graph, -1, true, DT_FLOAT16, dims); |
| +} |
| + |
| +TEST_F(SoftmaxGradExtFusionPassTest, v1_fp32_axis1_keepdims_false_success) |
| +{ |
| + vector<int64_t> dims{1, 64, 256}; |
| + auto built = BuildSoftmaxGradGraph(DT_FLOAT, dims, 1, false, kVariantV1); |
| + built.graph->DumpToFile(Graph::DumpFormat::kOnnx, "dump_graph_for_softmax_grad_ext_v1_test2"); |
| + CustomPassContext ctx; |
| + SoftmaxGradExtFusionPass pass; |
| + EXPECT_EQ(pass.Run(built.graph, ctx), SUCCESS); |
| + built.graph->DumpToFile(Graph::DumpFormat::kOnnx, "dump_afterpass_graph_for_softmax_grad_ext_v1_test2"); |
| + ExpectFused(built.graph, 1, false, DT_FLOAT, dims); |
| +} |
| + |
| +TEST_F(SoftmaxGradExtFusionPassTest, v1_unknown_shape_not_changed) |
| +{ |
| + vector<int64_t> dims{-1, 32, 128}; |
| + auto built = BuildSoftmaxGradGraph(DT_FLOAT16, dims, -1, true, kVariantV1); |
| + built.graph->DumpToFile(Graph::DumpFormat::kOnnx, "dump_graph_for_softmax_grad_ext_v1_test3"); |
| + CustomPassContext ctx; |
| + SoftmaxGradExtFusionPass pass; |
| + EXPECT_EQ(pass.Run(built.graph, ctx), GRAPH_NOT_CHANGED); |
| +} |
| + |
| +TEST_F(SoftmaxGradExtFusionPassTest, v1_unsupported_platform_not_changed) |
| +{ |
| + SetPlatform("Ascend910_93"); |
| + vector<int64_t> dims{2, 32, 128}; |
| + auto built = BuildSoftmaxGradGraph(DT_FLOAT16, dims, -1, true, kVariantV1); |
| + built.graph->DumpToFile(Graph::DumpFormat::kOnnx, "dump_graph_for_softmax_grad_ext_v1_test4"); |
| + CustomPassContext ctx; |
| + SoftmaxGradExtFusionPass pass; |
| + EXPECT_EQ(pass.Run(built.graph, ctx), GRAPH_NOT_CHANGED); |
| +} |
| + |
| + |
| + |
| +TEST_F(SoftmaxGradExtFusionPassTest, v2_variant0_success) |
| +{ |
| + vector<int64_t> dims{2, 32, 128}; |
| + auto built = BuildSoftmaxGradGraph(DT_FLOAT16, dims, -1, true, 0); |
| + built.graph->DumpToFile(Graph::DumpFormat::kOnnx, "dump_graph_for_softmax_grad_ext_v2_test1"); |
| + CustomPassContext ctx; |
| + SoftmaxGradExtV2FusionPass pass; |
| + EXPECT_EQ(pass.Run(built.graph, ctx), SUCCESS); |
| + built.graph->DumpToFile(Graph::DumpFormat::kOnnx, "dump_afterpass_graph_for_softmax_grad_ext_v2_test1"); |
| + ExpectFused(built.graph, -1, true, DT_FLOAT16, dims); |
| +} |
| + |
| +TEST_F(SoftmaxGradExtFusionPassTest, v2_variant1_success) |
| +{ |
| + vector<int64_t> dims{1, 64, 256}; |
| + auto built = BuildSoftmaxGradGraph(DT_FLOAT16, dims, 1, true, 1); |
| + built.graph->DumpToFile(Graph::DumpFormat::kOnnx, "dump_graph_for_softmax_grad_ext_v2_test2"); |
| + CustomPassContext ctx; |
| + SoftmaxGradExtV2FusionPass pass; |
| + EXPECT_EQ(pass.Run(built.graph, ctx), SUCCESS); |
| + built.graph->DumpToFile(Graph::DumpFormat::kOnnx, "dump_afterpass_graph_for_softmax_grad_ext_v2_test2"); |
| + ExpectFused(built.graph, 1, true, DT_FLOAT16, dims); |
| +} |
| + |
| +TEST_F(SoftmaxGradExtFusionPassTest, v2_variant2_success) |
| +{ |
| + vector<int64_t> dims{2, 32, 128}; |
| + auto built = BuildSoftmaxGradGraph(DT_FLOAT, dims, -1, false, 2); |
| + built.graph->DumpToFile(Graph::DumpFormat::kOnnx, "dump_graph_for_softmax_grad_ext_v2_test3"); |
| + CustomPassContext ctx; |
| + SoftmaxGradExtV2FusionPass pass; |
| + EXPECT_EQ(pass.Run(built.graph, ctx), SUCCESS); |
| + built.graph->DumpToFile(Graph::DumpFormat::kOnnx, "dump_afterpass_graph_for_softmax_grad_ext_v2_test3"); |
| + ExpectFused(built.graph, -1, false, DT_FLOAT, dims); |
| +} |
| + |
| +TEST_F(SoftmaxGradExtFusionPassTest, v2_variant3_success) |
| +{ |
| + vector<int64_t> dims{1, 64, 256}; |
| + auto built = BuildSoftmaxGradGraph(DT_FLOAT16, dims, 2, true, 3); |
| + built.graph->DumpToFile(Graph::DumpFormat::kOnnx, "dump_graph_for_softmax_grad_ext_v2_test4"); |
| + CustomPassContext ctx; |
| + SoftmaxGradExtV2FusionPass pass; |
| + EXPECT_EQ(pass.Run(built.graph, ctx), SUCCESS); |
| + built.graph->DumpToFile(Graph::DumpFormat::kOnnx, "dump_afterpass_graph_for_softmax_grad_ext_v2_test4"); |
| + ExpectFused(built.graph, 2, true, DT_FLOAT16, dims); |
| +} |
| + |
| +TEST_F(SoftmaxGradExtFusionPassTest, v2_unknown_shape_not_changed) |
| +{ |
| + vector<int64_t> dims{-1, 32, 128}; |
| + auto built = BuildSoftmaxGradGraph(DT_FLOAT16, dims, -1, true, 0); |
| + built.graph->DumpToFile(Graph::DumpFormat::kOnnx, "dump_graph_for_softmax_grad_ext_v2_test5"); |
| + CustomPassContext ctx; |
| + SoftmaxGradExtV2FusionPass pass; |
| + EXPECT_EQ(pass.Run(built.graph, ctx), GRAPH_NOT_CHANGED); |
| +} |
| + |
| +TEST_F(SoftmaxGradExtFusionPassTest, v2_unsupported_platform_not_changed) |
| +{ |
| + SetPlatform("Ascend910_93"); |
| + vector<int64_t> dims{2, 32, 128}; |
| + auto built = BuildSoftmaxGradGraph(DT_FLOAT16, dims, -1, true, 0); |
| + built.graph->DumpToFile(Graph::DumpFormat::kOnnx, "dump_graph_for_softmax_grad_ext_v2_test6"); |
| + CustomPassContext ctx; |
| + SoftmaxGradExtV2FusionPass pass; |
| + EXPECT_EQ(pass.Run(built.graph, ctx), GRAPH_NOT_CHANGED); |
| +} |
| + |
| + |
| +TEST_F(SoftmaxGradExtFusionPassTest, v1_pass_does_not_match_v2_graph) |
| +{ |
| + vector<int64_t> dims{2, 32, 128}; |
| + auto built = BuildSoftmaxGradGraph(DT_FLOAT16, dims, -1, true, 0); |
| + CustomPassContext ctx; |
| + SoftmaxGradExtFusionPass pass; |
| + EXPECT_EQ(pass.Run(built.graph, ctx), GRAPH_NOT_CHANGED); |
| +} |
| + |
| + |
| +TEST_F(SoftmaxGradExtFusionPassTest, v2_pass_does_not_match_v1_graph) |
| +{ |
| + vector<int64_t> dims{2, 32, 128}; |
| + auto built = BuildSoftmaxGradGraph(DT_FLOAT16, dims, -1, true, kVariantV1); |
| + CustomPassContext ctx; |
| + SoftmaxGradExtV2FusionPass pass; |
| + EXPECT_EQ(pass.Run(built.graph, ctx), GRAPH_NOT_CHANGED); |
| +} |
| + |
| + |
| + |
| + |
| + |
| + |
| + |
| + |
| +TEST_F(SoftmaxGradExtFusionPassTest, v1_mul_input_order_swapped_not_changed) |
| +{ |
| + vector<int64_t> dims{2, 32, 128}; |
| + EsGraphBuilder builder("mul_swapped_test"); |
| + auto grad = builder.CreateInput(0, "grad", DT_FLOAT16, FORMAT_ND, dims); |
| + auto x1 = builder.CreateInput(1, "x1", DT_FLOAT16, FORMAT_ND, dims); |
| + auto x2 = builder.CreateInput(2, "x2", DT_FLOAT16, FORMAT_ND, dims); |
| + SetOutDesc(grad, DT_FLOAT16, dims); |
| + SetOutDesc(x1, DT_FLOAT16, dims); |
| + SetOutDesc(x2, DT_FLOAT16, dims); |
| + |
| + |
| + auto mul = BuildBinaryNode(builder, x1, grad, "Mul"); |
| + auto axes = builder.CreateConst(vector<int64_t>{-1}, {1}); |
| + auto sum = BuildReduceSum(builder, mul, axes, true); |
| + auto sub = BuildBinaryNode(builder, x1, sum, "Sub"); |
| + auto mul1 = BuildBinaryNode(builder, x2, x1, "Mul"); |
| + auto mulGrad = BuildBinaryNode(builder, mul1, sub, "Mul"); |
| + |
| + SetInDesc(*mul.GetProducer(), 0, DT_FLOAT16, dims); |
| + SetInDesc(*mul.GetProducer(), 1, DT_FLOAT16, dims); |
| + SetOutDesc(mul, DT_FLOAT16, dims); |
| + SetInDesc(*sum.GetProducer(), 0, DT_FLOAT16, dims); |
| + SetInDesc(*sum.GetProducer(), 1, DT_INT64, {1}); |
| + SetOutDesc(sum, DT_FLOAT16, {2, 32, 1}); |
| + SetInDesc(*sub.GetProducer(), 0, DT_FLOAT16, dims); |
| + SetInDesc(*sub.GetProducer(), 1, DT_FLOAT16, {2, 32, 1}); |
| + SetOutDesc(sub, DT_FLOAT16, dims); |
| + SetInDesc(*mul1.GetProducer(), 0, DT_FLOAT16, dims); |
| + SetInDesc(*mul1.GetProducer(), 1, DT_FLOAT16, dims); |
| + SetOutDesc(mul1, DT_FLOAT16, dims); |
| + SetInDesc(*mulGrad.GetProducer(), 0, DT_FLOAT16, dims); |
| + SetInDesc(*mulGrad.GetProducer(), 1, DT_FLOAT16, dims); |
| + SetOutDesc(mulGrad, DT_FLOAT16, dims); |
| + |
| + shared_ptr<Graph> graph = builder.BuildAndReset({mulGrad}); |
| + CustomPassContext ctx; |
| + SoftmaxGradExtFusionPass pass; |
| + EXPECT_EQ(pass.Run(graph, ctx), GRAPH_NOT_CHANGED); |
| +} |
| + |
| + |
| + |
| + |
| +TEST_F(SoftmaxGradExtFusionPassTest, v1_control_edge_cycle_not_changed) |
| +{ |
| + vector<int64_t> dims{2, 32, 128}; |
| + auto built = BuildSoftmaxGradGraph(DT_FLOAT16, dims, -1, true, kVariantV1); |
| + |
| + |
| + |
| + EsGraphBuilder extBuilder("ext_control_cycle"); |
| + auto grad = extBuilder.CreateInput(0, "grad", DT_FLOAT16, FORMAT_ND, dims); |
| + auto x1 = extBuilder.CreateInput(1, "x1", DT_FLOAT16, FORMAT_ND, dims); |
| + auto x2 = extBuilder.CreateInput(2, "x2", DT_FLOAT16, FORMAT_ND, dims); |
| + SetOutDesc(grad, DT_FLOAT16, dims); |
| + SetOutDesc(x1, DT_FLOAT16, dims); |
| + SetOutDesc(x2, DT_FLOAT16, dims); |
| + |
| + auto axes = extBuilder.CreateConst(vector<int64_t>{-1}, {1}); |
| + auto mul = BuildBinaryNode(extBuilder, grad, x1, "Mul"); |
| + auto sum = BuildReduceSum(extBuilder, mul, axes, true); |
| + auto sub = BuildBinaryNode(extBuilder, grad, sum, "Sub"); |
| + auto mul1 = BuildBinaryNode(extBuilder, x2, x1, "Mul"); |
| + auto mulGrad = BuildBinaryNode(extBuilder, mul1, sub, "Mul"); |
| + |
| + SetInDesc(*mul.GetProducer(), 0, DT_FLOAT16, dims); |
| + SetInDesc(*mul.GetProducer(), 1, DT_FLOAT16, dims); |
| + SetOutDesc(mul, DT_FLOAT16, dims); |
| + SetInDesc(*sum.GetProducer(), 0, DT_FLOAT16, dims); |
| + SetInDesc(*sum.GetProducer(), 1, DT_INT64, {1}); |
| + SetOutDesc(sum, DT_FLOAT16, {2, 32, 1}); |
| + SetInDesc(*sub.GetProducer(), 0, DT_FLOAT16, dims); |
| + SetInDesc(*sub.GetProducer(), 1, DT_FLOAT16, {2, 32, 1}); |
| + SetOutDesc(sub, DT_FLOAT16, dims); |
| + SetInDesc(*mul1.GetProducer(), 0, DT_FLOAT16, dims); |
| + SetInDesc(*mul1.GetProducer(), 1, DT_FLOAT16, dims); |
| + SetOutDesc(mul1, DT_FLOAT16, dims); |
| + SetInDesc(*mulGrad.GetProducer(), 0, DT_FLOAT16, dims); |
| + SetInDesc(*mulGrad.GetProducer(), 1, DT_FLOAT16, dims); |
| + SetOutDesc(mulGrad, DT_FLOAT16, dims); |
| + |
| + |
| + auto external = BuildBinaryNode(extBuilder, mulGrad, grad, "Add"); |
| + SetInDesc(*external.GetProducer(), 0, DT_FLOAT16, dims); |
| + SetInDesc(*external.GetProducer(), 1, DT_FLOAT16, dims); |
| + SetOutDesc(external, DT_FLOAT16, dims); |
| + |
| + shared_ptr<Graph> graph = extBuilder.BuildAndReset({external}); |
| + CustomPassContext ctx; |
| + SoftmaxGradExtFusionPass pass; |
| + |
| + |
| + auto status = pass.Run(graph, ctx); |
| + EXPECT_TRUE(status == SUCCESS || status == GRAPH_NOT_CHANGED); |
| +} |
| + |
| + |
| + |
| + |
| +TEST_F(SoftmaxGradExtFusionPassTest, v1_shared_axes_const_success) |
| +{ |
| + vector<int64_t> dims{2, 32, 128}; |
| + EsGraphBuilder builder("shared_axes_test"); |
| + auto grad = builder.CreateInput(0, "grad", DT_FLOAT16, FORMAT_ND, dims); |
| + auto x1 = builder.CreateInput(1, "x1", DT_FLOAT16, FORMAT_ND, dims); |
| + auto x2 = builder.CreateInput(2, "x2", DT_FLOAT16, FORMAT_ND, dims); |
| + SetOutDesc(grad, DT_FLOAT16, dims); |
| + SetOutDesc(x1, DT_FLOAT16, dims); |
| + SetOutDesc(x2, DT_FLOAT16, dims); |
| + |
| + |
| + auto axes = builder.CreateConst(vector<int64_t>{-1}, {1}); |
| + |
| + |
| + auto mul = BuildBinaryNode(builder, grad, x1, "Mul"); |
| + auto sum = BuildReduceSum(builder, mul, axes, true); |
| + auto sub = BuildBinaryNode(builder, grad, sum, "Sub"); |
| + auto mul1 = BuildBinaryNode(builder, x2, x1, "Mul"); |
| + auto mulGrad = BuildBinaryNode(builder, mul1, sub, "Mul"); |
| + |
| + |
| + auto extReduce = BuildReduceSum(builder, x2, axes, true); |
| + |
| + SetInDesc(*mul.GetProducer(), 0, DT_FLOAT16, dims); |
| + SetInDesc(*mul.GetProducer(), 1, DT_FLOAT16, dims); |
| + SetOutDesc(mul, DT_FLOAT16, dims); |
| + SetInDesc(*sum.GetProducer(), 0, DT_FLOAT16, dims); |
| + SetInDesc(*sum.GetProducer(), 1, DT_INT64, {1}); |
| + SetOutDesc(sum, DT_FLOAT16, {2, 32, 1}); |
| + SetInDesc(*sub.GetProducer(), 0, DT_FLOAT16, dims); |
| + SetInDesc(*sub.GetProducer(), 1, DT_FLOAT16, {2, 32, 1}); |
| + SetOutDesc(sub, DT_FLOAT16, dims); |
| + SetInDesc(*mul1.GetProducer(), 0, DT_FLOAT16, dims); |
| + SetInDesc(*mul1.GetProducer(), 1, DT_FLOAT16, dims); |
| + SetOutDesc(mul1, DT_FLOAT16, dims); |
| + SetInDesc(*mulGrad.GetProducer(), 0, DT_FLOAT16, dims); |
| + SetInDesc(*mulGrad.GetProducer(), 1, DT_FLOAT16, dims); |
| + SetOutDesc(mulGrad, DT_FLOAT16, dims); |
| + SetInDesc(*extReduce.GetProducer(), 0, DT_FLOAT16, dims); |
| + SetInDesc(*extReduce.GetProducer(), 1, DT_INT64, {1}); |
| + SetOutDesc(extReduce, DT_FLOAT16, {2, 32, 1}); |
| + |
| + |
| + shared_ptr<Graph> graph = builder.BuildAndReset({mulGrad, extReduce}); |
| + CustomPassContext ctx; |
| + SoftmaxGradExtFusionPass pass; |
| + auto status = pass.Run(graph, ctx); |
| + EXPECT_TRUE(status == SUCCESS || status == GRAPH_NOT_CHANGED); |
| +} |
| + |
| + |
| + |
| + |
| +TEST_F(SoftmaxGradExtFusionPassTest, v1_two_subgraphs_no_crash) |
| +{ |
| + vector<int64_t> dims{2, 32, 128}; |
| + EsGraphBuilder builder("two_subgraphs_test"); |
| + auto grad = builder.CreateInput(0, "grad", DT_FLOAT16, FORMAT_ND, dims); |
| + auto x1 = builder.CreateInput(1, "x1", DT_FLOAT16, FORMAT_ND, dims); |
| + auto x2 = builder.CreateInput(2, "x2", DT_FLOAT16, FORMAT_ND, dims); |
| + SetOutDesc(grad, DT_FLOAT16, dims); |
| + SetOutDesc(x1, DT_FLOAT16, dims); |
| + SetOutDesc(x2, DT_FLOAT16, dims); |
| + |
| + auto axes = builder.CreateConst(vector<int64_t>{-1}, {1}); |
| + |
| + |
| + auto mul1a = BuildBinaryNode(builder, grad, x1, "Mul"); |
| + auto sum1a = BuildReduceSum(builder, mul1a, axes, true); |
| + auto sub1a = BuildBinaryNode(builder, grad, sum1a, "Sub"); |
| + auto mul1_1a = BuildBinaryNode(builder, x2, x1, "Mul"); |
| + auto mulGrad1 = BuildBinaryNode(builder, mul1_1a, sub1a, "Mul"); |
| + |
| + SetInDesc(*mul1a.GetProducer(), 0, DT_FLOAT16, dims); |
| + SetInDesc(*mul1a.GetProducer(), 1, DT_FLOAT16, dims); |
| + SetOutDesc(mul1a, DT_FLOAT16, dims); |
| + SetInDesc(*sum1a.GetProducer(), 0, DT_FLOAT16, dims); |
| + SetInDesc(*sum1a.GetProducer(), 1, DT_INT64, {1}); |
| + SetOutDesc(sum1a, DT_FLOAT16, {2, 32, 1}); |
| + SetInDesc(*sub1a.GetProducer(), 0, DT_FLOAT16, dims); |
| + SetInDesc(*sub1a.GetProducer(), 1, DT_FLOAT16, {2, 32, 1}); |
| + SetOutDesc(sub1a, DT_FLOAT16, dims); |
| + SetInDesc(*mul1_1a.GetProducer(), 0, DT_FLOAT16, dims); |
| + SetInDesc(*mul1_1a.GetProducer(), 1, DT_FLOAT16, dims); |
| + SetOutDesc(mul1_1a, DT_FLOAT16, dims); |
| + SetInDesc(*mulGrad1.GetProducer(), 0, DT_FLOAT16, dims); |
| + SetInDesc(*mulGrad1.GetProducer(), 1, DT_FLOAT16, dims); |
| + SetOutDesc(mulGrad1, DT_FLOAT16, dims); |
| + |
| + shared_ptr<Graph> graph = builder.BuildAndReset({mulGrad1}); |
| + CustomPassContext ctx; |
| + SoftmaxGradExtFusionPass pass; |
| + auto status = pass.Run(graph, ctx); |
| + EXPECT_TRUE(status == SUCCESS || status == GRAPH_NOT_CHANGED); |
| +} |
| + |
| + |
| + |
| +TEST_F(SoftmaxGradExtFusionPassTest, v1_mulgrad_control_consumer_not_changed_or_success) |
| +{ |
| + vector<int64_t> dims{2, 32, 128}; |
| + EsGraphBuilder builder("ctrl_consumer_test"); |
| + auto grad = builder.CreateInput(0, "grad", DT_FLOAT16, FORMAT_ND, dims); |
| + auto x1 = builder.CreateInput(1, "x1", DT_FLOAT16, FORMAT_ND, dims); |
| + auto x2 = builder.CreateInput(2, "x2", DT_FLOAT16, FORMAT_ND, dims); |
| + SetOutDesc(grad, DT_FLOAT16, dims); |
| + SetOutDesc(x1, DT_FLOAT16, dims); |
| + SetOutDesc(x2, DT_FLOAT16, dims); |
| + |
| + auto axes = builder.CreateConst(vector<int64_t>{-1}, {1}); |
| + auto mul = BuildBinaryNode(builder, grad, x1, "Mul"); |
| + auto sum = BuildReduceSum(builder, mul, axes, true); |
| + auto sub = BuildBinaryNode(builder, grad, sum, "Sub"); |
| + auto mul1 = BuildBinaryNode(builder, x2, x1, "Mul"); |
| + auto mulGrad = BuildBinaryNode(builder, mul1, sub, "Mul"); |
| + |
| + SetInDesc(*mul.GetProducer(), 0, DT_FLOAT16, dims); |
| + SetInDesc(*mul.GetProducer(), 1, DT_FLOAT16, dims); |
| + SetOutDesc(mul, DT_FLOAT16, dims); |
| + SetInDesc(*sum.GetProducer(), 0, DT_FLOAT16, dims); |
| + SetInDesc(*sum.GetProducer(), 1, DT_INT64, {1}); |
| + SetOutDesc(sum, DT_FLOAT16, {2, 32, 1}); |
| + SetInDesc(*sub.GetProducer(), 0, DT_FLOAT16, dims); |
| + SetInDesc(*sub.GetProducer(), 1, DT_FLOAT16, {2, 32, 1}); |
| + SetOutDesc(sub, DT_FLOAT16, dims); |
| + SetInDesc(*mul1.GetProducer(), 0, DT_FLOAT16, dims); |
| + SetInDesc(*mul1.GetProducer(), 1, DT_FLOAT16, dims); |
| + SetOutDesc(mul1, DT_FLOAT16, dims); |
| + SetInDesc(*mulGrad.GetProducer(), 0, DT_FLOAT16, dims); |
| + SetInDesc(*mulGrad.GetProducer(), 1, DT_FLOAT16, dims); |
| + SetOutDesc(mulGrad, DT_FLOAT16, dims); |
| + |
| + |
| + auto extNode = BuildBinaryNode(builder, x2, x1, "Add"); |
| + SetInDesc(*extNode.GetProducer(), 0, DT_FLOAT16, dims); |
| + SetInDesc(*extNode.GetProducer(), 1, DT_FLOAT16, dims); |
| + SetOutDesc(extNode, DT_FLOAT16, dims); |
| + |
| + |
| + auto* graph = builder.GetCGraphBuilder()->GetGraph(); |
| + graph->AddControlEdge(*mulGrad.GetProducer(), *extNode.GetProducer()); |
| + |
| + shared_ptr<Graph> graphPtr = builder.BuildAndReset({mulGrad, extNode}); |
| + CustomPassContext ctx; |
| + SoftmaxGradExtFusionPass pass; |
| + auto status = pass.Run(graphPtr, ctx); |
| + EXPECT_TRUE(status == SUCCESS || status == GRAPH_NOT_CHANGED); |
| +} |
| + |
| + |
| + |
| + |
| + |
| + |
| + |
| +TEST_F(SoftmaxGradExtFusionPassTest, v1_axes_from_op_depending_on_mulgrad_cycle) |
| +{ |
| + vector<int64_t> dims{2, 32, 128}; |
| + EsGraphBuilder builder("axes_depends_mulgrad_test"); |
| + auto grad = builder.CreateInput(0, "grad", DT_FLOAT16, FORMAT_ND, dims); |
| + auto x1 = builder.CreateInput(1, "x1", DT_FLOAT16, FORMAT_ND, dims); |
| + auto x2 = builder.CreateInput(2, "x2", DT_FLOAT16, FORMAT_ND, dims); |
| + SetOutDesc(grad, DT_FLOAT16, dims); |
| + SetOutDesc(x1, DT_FLOAT16, dims); |
| + SetOutDesc(x2, DT_FLOAT16, dims); |
| + |
| + |
| + auto mul = BuildBinaryNode(builder, grad, x1, "Mul"); |
| + auto sum = BuildReduceSum(builder, mul, builder.CreateConst(vector<int64_t>{-1}, {1}), true); |
| + auto sub = BuildBinaryNode(builder, grad, sum, "Sub"); |
| + auto mul1 = BuildBinaryNode(builder, x2, x1, "Mul"); |
| + auto mulGrad = BuildBinaryNode(builder, mul1, sub, "Mul"); |
| + |
| + SetInDesc(*mul.GetProducer(), 0, DT_FLOAT16, dims); |
| + SetInDesc(*mul.GetProducer(), 1, DT_FLOAT16, dims); |
| + SetOutDesc(mul, DT_FLOAT16, dims); |
| + SetInDesc(*sum.GetProducer(), 0, DT_FLOAT16, dims); |
| + SetInDesc(*sum.GetProducer(), 1, DT_INT64, {1}); |
| + SetOutDesc(sum, DT_FLOAT16, {2, 32, 1}); |
| + SetInDesc(*sub.GetProducer(), 0, DT_FLOAT16, dims); |
| + SetInDesc(*sub.GetProducer(), 1, DT_FLOAT16, {2, 32, 1}); |
| + SetOutDesc(sub, DT_FLOAT16, dims); |
| + SetInDesc(*mul1.GetProducer(), 0, DT_FLOAT16, dims); |
| + SetInDesc(*mul1.GetProducer(), 1, DT_FLOAT16, dims); |
| + SetOutDesc(mul1, DT_FLOAT16, dims); |
| + SetInDesc(*mulGrad.GetProducer(), 0, DT_FLOAT16, dims); |
| + SetInDesc(*mulGrad.GetProducer(), 1, DT_FLOAT16, dims); |
| + SetOutDesc(mulGrad, DT_FLOAT16, dims); |
| + |
| + |
| + |
| + |
| + |
| + auto axesCast = BuildBinaryNode(builder, mulGrad, x1, "Cast"); |
| + SetInDesc(*axesCast.GetProducer(), 0, DT_FLOAT16, dims); |
| + SetInDesc(*axesCast.GetProducer(), 1, DT_FLOAT16, dims); |
| + SetOutDesc(axesCast, DT_INT64, {1}); |
| + |
| + |
| + auto sum2 = BuildReduceSum(builder, mul, axesCast, true); |
| + SetInDesc(*sum2.GetProducer(), 0, DT_FLOAT16, dims); |
| + SetInDesc(*sum2.GetProducer(), 1, DT_INT64, {1}); |
| + SetOutDesc(sum2, DT_FLOAT16, {2, 32, 1}); |
| + |
| + |
| + auto sub2 = BuildBinaryNode(builder, grad, sum2, "Sub"); |
| + SetInDesc(*sub2.GetProducer(), 0, DT_FLOAT16, dims); |
| + SetInDesc(*sub2.GetProducer(), 1, DT_FLOAT16, {2, 32, 1}); |
| + SetOutDesc(sub2, DT_FLOAT16, dims); |
| + |
| + |
| + auto mulGrad2 = BuildBinaryNode(builder, mul1, sub2, "Mul"); |
| + SetInDesc(*mulGrad2.GetProducer(), 0, DT_FLOAT16, dims); |
| + SetInDesc(*mulGrad2.GetProducer(), 1, DT_FLOAT16, dims); |
| + SetOutDesc(mulGrad2, DT_FLOAT16, dims); |
| + |
| + shared_ptr<Graph> graph = builder.BuildAndReset({mulGrad2}); |
| + CustomPassContext ctx; |
| + SoftmaxGradExtFusionPass pass; |
| + auto status = pass.Run(graph, ctx); |
| + fprintf(stderr, "[STATUS-axes-cycle] %d\n", static_cast<int32_t>(status)); |
| + |
| + |
| + EXPECT_TRUE(status == SUCCESS || status == GRAPH_NOT_CHANGED); |
| +} |
[Info] CMakeLists.txt 中遗留 Debug message 输出
文件位置
activation/softmax_grad_ext/op_graph/CMakeLists.txt:8问题说明
第 8 行遗留调试输出:
message(STATUS "=== Debug: start ops.activation.softmax_grad_ext.graph_plugin.CMakeLists.txt ")tests/ut/op_graph/CMakeLists.txt:9同样遗留message(STATUS "=== Debug: ...")。均为开发阶段调试输出,建议清理。不阻塞合入。建议修复
删除两行
message(STATUS "=== Debug: ...")调试输出。