已合并
[CANNBot] 迁移RandomStandardNormal融合规则到新pass框架 #2420
xuejinghui创建于 4月24日
[CANNBot] 迁移RandomStandardNormal融合规则到新pass框架 #2420
已合并
从已删除 :fussion-pass合入到cann/ops-mathmaster
共 5 个文件变更+565-2
| @@ -156,6 +156,7 @@ function(add_op_graph_ut_modules OP_GRAPH_MODULE_NAME) | |||
| 156 | gtest | 156 | gtest |
| 157 | register | 157 | register |
| 158 | ge_compiler | 158 | ge_compiler |
| 159 | + ge_common | ||
| 159 | ) | 160 | ) |
| 160 | 161 | ||
| 161 | target_compile_options( | 162 | target_compile_options( |
| @@ -0,0 +1,210 @@ | |||
| 1 | +/** | ||
| 2 | + * Copyright (c) 2025 Huawei Technologies Co., Ltd. | ||
| 3 | + * This program is free software, you can redistribute it and/or modify it under the terms and conditions of | ||
| 4 | + * CANN Open Software License Agreement Version 2.0 (the "License"). | ||
| 5 | + * Please refer to the License for details. You may not use this file except in compliance with the License. | ||
| 6 | + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, | ||
| 7 | + * INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. | ||
| 8 | + * See LICENSE in the root of the software repository for the full text of the License. | ||
| 9 | + */ | ||
| 10 | + | ||
| 11 | +/*! | ||
| 12 | + * \file random_standard_normal_fusion_pass.cpp | ||
| 13 | + * \brief RandomStandardNormal fusion pass (RandomStandardNormal --> RandomStandardNormalV2) | ||
| 14 | + * | ||
| 15 | + * Pattern: | ||
| 16 | + * shape shape offset(const 0) | ||
| 17 | + * | | / | ||
| 18 | + * RandomStandardNormal ==> RandomStandardNormalV2 | ||
| 19 | + * | | \ | ||
| 20 | + * output output offset | ||
| 21 | + * | ||
| 22 | + * The key transformation: | ||
| 23 | + * - RandomStandardNormal has 1 input: shape, 1 output: y | ||
| 24 | + * - RandomStandardNormalV2 has 2 inputs: shape + offset, 2 outputs: y + offset | ||
| 25 | + * - An offset constant (value 0, dtype int64) is created as the additional input | ||
| 26 | + * - Attributes seed, seed2, dtype are transferred to the new node | ||
| 27 | + */ | ||
| 28 | + | ||
| 29 | + | ||
| 30 | + | ||
| 31 | + | ||
| 32 | + | ||
| 33 | + | ||
| 34 | + | ||
| 35 | + | ||
| 36 | + | ||
| 37 | + | ||
| 38 | +using namespace ge; | ||
| 39 | +using namespace ge::fusion; | ||
| 40 | +using namespace fe; | ||
| 41 | + | ||
| 42 | +namespace ops { | ||
| 43 | + | ||
| 44 | +static const std::string kPassName = "RandomStandardNormalFusionPass"; | ||
| 45 | +static const int64_t kCaptureIdx = 0L; | ||
| 46 | + | ||
| 47 | +static const std::set<ge::DataType> kSupportedDtypes = {ge::DT_FLOAT, ge::DT_FLOAT16, ge::DT_BF16}; | ||
| 48 | + | ||
| 49 | +static void GetInputsInfo(const std::vector<SubgraphInput>& subgraphInputs, | ||
| 50 | + std::vector<Shape>& inputShapes, | ||
| 51 | + std::vector<DataType>& inputDtypes, | ||
| 52 | + std::vector<Format>& inputFormats) | ||
| 53 | +{ | ||
| 54 | + for (const auto& subgraphInput : subgraphInputs) { | ||
| 55 | + auto matchNode = subgraphInput.GetAllInputs().at(0); | ||
| 56 | + TensorDesc tensorDesc; | ||
| 57 | + matchNode.node.GetInputDesc(matchNode.index, tensorDesc); | ||
| 58 | + inputShapes.emplace_back(tensorDesc.GetShape()); | ||
| 59 | + inputDtypes.emplace_back(tensorDesc.GetDataType()); | ||
| 60 | + inputFormats.emplace_back(tensorDesc.GetFormat()); | ||
| 61 | + } | ||
| 62 | +} | ||
| 63 | + | ||
| 64 | +std::vector<PatternUniqPtr> RandomStandardNormalFusionPass::Patterns() | ||
| 65 | +{ | ||
| 66 | + OP_LOGD(kPassName.c_str(), "Enter Patterns for RandomStandardNormalFusionPass"); | ||
| 67 | + std::vector<PatternUniqPtr> patternGraphs; | ||
| 68 | + | ||
| 69 | + auto graphBuilder = es::EsGraphBuilder(kPassName.c_str()); | ||
| 70 | + auto shape = graphBuilder.CreateInput(0); | ||
| 71 | + | ||
| 72 | + auto graphPtr = graphBuilder.GetCGraphBuilder()->GetGraph(); | ||
| 73 | + auto srcBuilder = es::CompliantNodeBuilder(graphPtr); | ||
| 74 | + srcBuilder.OpType("RandomStandardNormal") | ||
| 75 | + .Name("pattern_random_standard_normal") | ||
| 76 | + .IrDefInputs({{"shape", es::CompliantNodeBuilder::kEsIrInputRequired, ""}}) | ||
| 77 | + .IrDefOutputs({{"y", es::CompliantNodeBuilder::kEsIrOutputRequired, ""}}) | ||
| 78 | + .IrDefAttrs({ | ||
| 79 | + {"seed", es::CompliantNodeBuilder::kEsAttrOptional, "Int", es::CreateFrom(static_cast<int64_t>(0))}, | ||
| 80 | + {"seed2", es::CompliantNodeBuilder::kEsAttrOptional, "Int", es::CreateFrom(static_cast<int64_t>(0))}, | ||
| 81 | + {"dtype", es::CompliantNodeBuilder::kEsAttrOptional, "Type", es::CreateFrom(DT_FLOAT)} | ||
| 82 | + }); | ||
| 83 | + GNode srcNode = srcBuilder.Build(); | ||
| 84 | + | ||
| 85 | + auto dataNode = shape.GetProducer(); | ||
| 86 | + if (dataNode != nullptr) { | ||
| 87 | + es::AddEdgeAndUpdatePeerDesc(*graphPtr, *dataNode, 0, srcNode, 0); | ||
| 88 | + } | ||
| 89 | + | ||
| 90 | + es::EsGraphBuilder::SetOutput(shape, 0); | ||
| 91 | + auto graph = graphBuilder.BuildAndReset(); | ||
| 92 | + | ||
| 93 | + std::vector<std::pair<GNode, int32_t>> outputs = {{srcNode, 0}}; | ||
| 94 | + graph->SetOutputs(outputs); | ||
| 95 | + | ||
| 96 | + auto pattern = std::make_unique<Pattern>(std::move(*graph)); | ||
| 97 | + pattern->CaptureTensor({srcNode, 0}); | ||
| 98 | + | ||
| 99 | + patternGraphs.emplace_back(std::move(pattern)); | ||
| 100 | + return patternGraphs; | ||
| 101 | +} | ||
| 102 | + | ||
| 103 | + | ||
| 104 | +bool RandomStandardNormalFusionPass::MeetRequirements(const std::unique_ptr<MatchResult>& matchResult) | ||
| 105 | +{ | ||
| 106 | + OP_LOGD(kPassName.c_str(), "Enter MeetRequirements for RandomStandardNormalFusionPass"); | ||
| 107 | + | ||
| 108 | + // 1. Platform check - regbase architectures only | ||
| 109 | + PlatformInfo platformInfo; | ||
| 110 | + OptionalInfo optionalInfo; | ||
| 111 | + if (PlatformInfoManager::Instance().GetPlatformInfoWithOutSocVersion(platformInfo, optionalInfo) != SUCCESS) { | ||
| 112 | + OP_LOGE(kPassName.c_str(), "Get platform info failed."); | ||
| 113 | + return false; | ||
| 114 | + } | ||
| 115 | + const std::string soc = platformInfo.str_info.short_soc_version; | ||
| 116 | + if (soc != "Ascend950") { | ||
| 117 | + OP_LOGD(kPassName.c_str(), "Platform %s is not supported, skip.", soc.c_str()); | ||
| 118 | + return false; | ||
| 119 | + } | ||
| 120 | + | ||
| 121 | + // 2. Get captured RandomStandardNormal node | ||
| 122 | + NodeIo nodeIo; | ||
| 123 | + if (matchResult->GetCapturedTensor(kCaptureIdx, nodeIo) != SUCCESS) { | ||
| 124 | + OP_LOGE(kPassName.c_str(), "Failed to get captured tensor."); | ||
| 125 | + return false; | ||
| 126 | + } | ||
| 127 | + | ||
| 128 | + // 3. Check dtype attribute | ||
| 129 | + ge::DataType dtype = ge::DT_FLOAT; | ||
| 130 | + if (nodeIo.node.GetAttr("dtype", dtype) != GRAPH_SUCCESS) { | ||
| 131 | + OP_LOGD(kPassName.c_str(), "Failed to get dtype attribute, using default DT_FLOAT."); | ||
| 132 | + } | ||
| 133 | + if (kSupportedDtypes.count(dtype) == 0) { | ||
| 134 | + OP_LOGD(kPassName.c_str(), | ||
| 135 | + "RandomStandardNormalV2 dtype only supports float32/float16/bfloat16, got %d, skip.", | ||
| 136 | + static_cast<int32_t>(dtype)); | ||
| 137 | + return false; | ||
| 138 | + } | ||
| 139 | + | ||
| 140 | + return true; | ||
| 141 | +} | ||
| 142 | + | ||
| 143 | +std::unique_ptr<Graph> RandomStandardNormalFusionPass::Replacement(const std::unique_ptr<MatchResult>& matchResult) | ||
| 144 | +{ | ||
| 145 | + OP_LOGD(kPassName.c_str(), "Enter Replacement for RandomStandardNormalFusionPass"); | ||
| 146 | + | ||
| 147 | + std::vector<SubgraphInput> subgraphInputs; | ||
| 148 | + matchResult->ToSubgraphBoundary()->GetAllInputs(subgraphInputs); | ||
| 149 | + | ||
| 150 | + if (subgraphInputs.empty()) { | ||
| 151 | + OP_LOGE(kPassName.c_str(), "SubgraphInputs is empty, cannot get input info."); | ||
| 152 | + return nullptr; | ||
| 153 | + } | ||
| 154 | + | ||
| 155 | + std::vector<Shape> inputShapes; | ||
| 156 | + std::vector<DataType> inputDtypes; | ||
| 157 | + std::vector<Format> inputFormats; | ||
| 158 | + GetInputsInfo(subgraphInputs, inputShapes, inputDtypes, inputFormats); | ||
| 159 | + | ||
| 160 | + NodeIo nodeIo; | ||
| 161 | + if (matchResult->GetCapturedTensor(kCaptureIdx, nodeIo) != SUCCESS) { | ||
| 162 | + OP_LOGE(kPassName.c_str(), "Failed to GetCaptured tensor in Replacement."); | ||
| 163 | + return nullptr; | ||
| 164 | + } | ||
| 165 | + | ||
S | |||
| 166 | + DataType dtype = DT_FLOAT; | ||
| 167 | + nodeIo.node.GetAttr("dtype", dtype); | ||
| 168 | + int64_t dtypeInt = static_cast<int64_t>(dtype); | ||
| 169 | + | ||
| 170 | + int64_t seed = 0; | ||
| 171 | + nodeIo.node.GetAttr("seed", seed); | ||
| 172 | + | ||
| 173 | + int64_t seed2 = 0; | ||
| 174 | + nodeIo.node.GetAttr("seed2", seed2); | ||
| 175 | + | ||
| 176 | + auto replaceGraphBuilder = es::EsGraphBuilder("replacement"); | ||
| 177 | + | ||
| 178 | + auto rShape = replaceGraphBuilder.CreateInput(0, "shape", inputDtypes[0], inputFormats[0], inputShapes[0].GetDims()); | ||
| 179 | + | ||
| 180 | + AscendString nodeName; | ||
| 181 | + if (nodeIo.node.GetName(nodeName) != GRAPH_SUCCESS) { | ||
| 182 | + OP_LOGE(kPassName.c_str(), "Failed to get node name."); | ||
| 183 | + return nullptr; | ||
| 184 | + } | ||
| 185 | + std::string varName = std::string(nodeName.GetString()) + "/offsetVariable"; | ||
| 186 | + | ||
| 187 | + TensorDesc offsetDesc(Shape({1}), FORMAT_ND, DT_INT64); | ||
| 188 | + | ||
| 189 | + auto rOffset = replaceGraphBuilder.CreateVariable(1, varName.c_str()); | ||
| 190 | + | ||
| 191 | + auto v2Output = es::RandomStandardNormalV2(rShape, rOffset, seed, seed2, dtypeInt); | ||
| 192 | + GNode v2NodePtr = *v2Output.y.GetProducer(); | ||
| 193 | + | ||
| 194 | + TensorDesc shapeInputDesc(inputShapes[0], inputFormats[0], inputDtypes[0]); | ||
| 195 | + v2NodePtr.UpdateInputDesc(0, shapeInputDesc); | ||
| 196 | + v2NodePtr.UpdateInputDesc(1, offsetDesc); | ||
| 197 | + | ||
| 198 | + TensorDesc outputYDesc; | ||
| 199 | + nodeIo.node.GetOutputDesc(0, outputYDesc); | ||
| 200 | + v2NodePtr.UpdateOutputDesc(0, outputYDesc); | ||
| 201 | + v2NodePtr.UpdateOutputDesc(1, offsetDesc); | ||
| 202 | + | ||
| 203 | + es::EsGraphBuilder::SetOutput(v2Output.y, 0); | ||
| 204 | + GraphUniqPtr replaceGraph = replaceGraphBuilder.BuildAndReset({v2Output.y}); | ||
| 205 | + return replaceGraph; | ||
| 206 | +} | ||
| 207 | + | ||
| 208 | +REG_FUSION_PASS(RandomStandardNormalFusionPass).Stage(CustomPassStage::kCompatibleInherited); | ||
| 209 | + | ||
| 210 | +} // namespace ops | ||
| @@ -0,0 +1,29 @@ | |||
| 1 | +/** | ||
| 2 | + * Copyright (c) 2025 Huawei Technologies Co., Ltd. | ||
| 3 | + * This program is free software, you can redistribute it and/or modify it under the terms and conditions of | ||
| 4 | + * CANN Open Software License Agreement Version 2.0 (the "License"). | ||
| 5 | + * Please refer to the License for details. You may not use this file except in compliance with the License. | ||
| 6 | + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, | ||
| 7 | + * INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. | ||
| 8 | + * See LICENSE in the root of the software repository for the full text of the License. | ||
| 9 | + */ | ||
| 10 | + | ||
| 11 | + | ||
| 12 | + | ||
| 13 | + | ||
| 14 | + | ||
| 15 | + | ||
| 16 | +namespace ops { | ||
| 17 | + | ||
| 18 | +class __attribute__((visibility("default"))) RandomStandardNormalFusionPass : public ge::fusion::PatternFusionPass { | ||
| 19 | +protected: | ||
| 20 | + std::vector<ge::fusion::PatternUniqPtr> Patterns() override; | ||
| 21 | + | ||
| 22 | + bool MeetRequirements(const std::unique_ptr<ge::fusion::MatchResult>& matchResult) override; | ||
| 23 | + | ||
| 24 | + std::unique_ptr<ge::Graph> Replacement(const std::unique_ptr<ge::fusion::MatchResult>& matchResult) override; | ||
| 25 | +}; | ||
| 26 | + | ||
| 27 | +} // namespace ops | ||
| 28 | + | ||
| 29 | + | ||
Arandom/random_standard_normal_v2/tests/ut/op_graph/test_random_standard_normal_fusion_pass.cpp+325-0
| @@ -0,0 +1,325 @@ | |||
| 1 | +/** | ||
| 2 | + * Copyright (c) 2025 Huawei Technologies Co., Ltd. | ||
| 3 | + * This program is free software, you can redistribute it and/or modify it under the terms and conditions of | ||
| 4 | + * CANN Open Software License Agreement Version 2.0 (the "License"). | ||
| 5 | + * Please refer to the License for details. You may not use this file except in compliance with the License. | ||
| 6 | + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, | ||
| 7 | + * INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. | ||
| 8 | + * See LICENSE in the root of the software repository for the full text of the License. | ||
| 9 | + */ | ||
| 10 | + | ||
| 11 | + | ||
| 12 | + | ||
| 13 | + | ||
| 14 | + | ||
| 15 | + | ||
| 16 | + | ||
| 17 | + | ||
| 18 | + | ||
| 19 | + | ||
| 20 | + | ||
| 21 | +using namespace std; | ||
| 22 | +using namespace ge; | ||
| 23 | +using namespace fe; | ||
| 24 | +using namespace fusion; | ||
| 25 | +using namespace ops; | ||
| 26 | + | ||
| 27 | +class RandomStandardNormalFusionPassTest : public testing::Test { | ||
| 28 | +protected: | ||
| 29 | + static void SetUpTestCase() | ||
| 30 | + { | ||
| 31 | + fe::PlatformInfo platformInfo; | ||
| 32 | + fe::OptionalInfo optiCompilationInfo; | ||
| 33 | + platformInfo.soc_info.ai_core_cnt = 64; | ||
| 34 | + platformInfo.str_info.short_soc_version = "Ascend910_93"; | ||
| 35 | + optiCompilationInfo.soc_version = "Ascend910_93"; | ||
| 36 | + fe::PlatformInfoManager::Instance().platform_info_map_["Ascend910_93"] = platformInfo; | ||
| 37 | + fe::PlatformInfoManager::Instance().SetOptionalCompilationInfo(optiCompilationInfo); | ||
| 38 | + } | ||
| 39 | + | ||
| 40 | + void SetUp() override | ||
| 41 | + { | ||
| 42 | + fe::PlatformInfo platformInfo; | ||
| 43 | + fe::OptionalInfo optiCompilationInfo; | ||
| 44 | + platformInfo.soc_info.ai_core_cnt = 64; | ||
| 45 | + platformInfo.str_info.short_soc_version = "Ascend910_93"; | ||
| 46 | + optiCompilationInfo.soc_version = "Ascend910_93"; | ||
| 47 | + fe::PlatformInfoManager::Instance().platform_info_map_["Ascend910_93"] = platformInfo; | ||
| 48 | + fe::PlatformInfoManager::Instance().SetOptionalCompilationInfo(optiCompilationInfo); | ||
| 49 | + } | ||
| 50 | +}; | ||
| 51 | + | ||
| 52 | +// Test 1: Verify Pattern can be created correctly | ||
| 53 | +TEST_F(RandomStandardNormalFusionPassTest, patternTest) | ||
| 54 | +{ | ||
| 55 | + ops::RandomStandardNormalFusionPass pass; | ||
| 56 | + std::vector<PatternUniqPtr> patterns = pass.Patterns(); | ||
| 57 | + EXPECT_GT(patterns.size(), 0); | ||
| 58 | +} | ||
| 59 | + | ||
| 60 | +// Test 2: Verify unsupported dtype returns GRAPH_NOT_CHANGED | ||
| 61 | +TEST_F(RandomStandardNormalFusionPassTest, unsupportedDtypeFail) | ||
| 62 | +{ | ||
| 63 | + std::vector<int64_t> shapeDims{2}; | ||
| 64 | + | ||
| 65 | + auto graphBuilder = es::EsGraphBuilder("test"); | ||
| 66 | + auto shape = graphBuilder.CreateInput(0, "shape", DT_INT64, FORMAT_ND, shapeDims); | ||
| 67 | + // DT_INT32 is not in the supported dtype list | ||
| 68 | + auto output = es::RandomStandardNormal(shape, DT_INT32, 1024, 2048); | ||
| 69 | + | ||
| 70 | + TensorDesc shapeDesc; | ||
| 71 | + shape.GetProducer()->GetOutputDesc(0, shapeDesc); | ||
| 72 | + shapeDesc.SetDataType(DT_INT64); | ||
| 73 | + shapeDesc.SetShape(Shape(shapeDims)); | ||
| 74 | + shapeDesc.SetFormat(FORMAT_ND); | ||
| 75 | + shape.GetProducer()->UpdateOutputDesc(0, shapeDesc); | ||
| 76 | + | ||
| 77 | + std::shared_ptr<Graph> graph = graphBuilder.BuildAndReset({output}); | ||
| 78 | + CustomPassContext passContext; | ||
| 79 | + ops::RandomStandardNormalFusionPass pass; | ||
| 80 | + Status status = pass.Run(graph, passContext); | ||
| 81 | + | ||
| 82 | + EXPECT_EQ(status, GRAPH_NOT_CHANGED); | ||
| 83 | +} | ||
| 84 | + | ||
| 85 | +// Test 3: Verify unsupported platform returns GRAPH_NOT_CHANGED | ||
| 86 | +TEST_F(RandomStandardNormalFusionPassTest, unsupportedPlatformFail) | ||
| 87 | +{ | ||
| 88 | + fe::PlatformInfo platformInfo; | ||
| 89 | + fe::OptionalInfo optiCompilationInfo; | ||
| 90 | + platformInfo.str_info.short_soc_version = "Ascend310"; | ||
| 91 | + optiCompilationInfo.soc_version = "Ascend310"; | ||
| 92 | + fe::PlatformInfoManager::Instance().platform_info_map_["Ascend310"] = platformInfo; | ||
| 93 | + fe::PlatformInfoManager::Instance().SetOptionalCompilationInfo(optiCompilationInfo); | ||
| 94 | + | ||
| 95 | + std::vector<int64_t> shapeDims{2}; | ||
| 96 | + | ||
| 97 | + auto graphBuilder = es::EsGraphBuilder("test"); | ||
| 98 | + auto shape = graphBuilder.CreateInput(0, "shape", DT_INT64, FORMAT_ND, shapeDims); | ||
| 99 | + auto output = es::RandomStandardNormal(shape, DT_FLOAT, 1024, 2048); | ||
| 100 | + | ||
| 101 | + TensorDesc shapeDesc; | ||
| 102 | + shape.GetProducer()->GetOutputDesc(0, shapeDesc); | ||
| 103 | + shapeDesc.SetDataType(DT_INT64); | ||
| 104 | + shapeDesc.SetShape(Shape(shapeDims)); | ||
| 105 | + shapeDesc.SetFormat(FORMAT_ND); | ||
| 106 | + shape.GetProducer()->UpdateOutputDesc(0, shapeDesc); | ||
| 107 | + | ||
| 108 | + std::shared_ptr<Graph> graph = graphBuilder.BuildAndReset({output}); | ||
| 109 | + CustomPassContext passContext; | ||
| 110 | + ops::RandomStandardNormalFusionPass pass; | ||
| 111 | + Status status = pass.Run(graph, passContext); | ||
| 112 | + | ||
| 113 | + EXPECT_EQ(status, GRAPH_NOT_CHANGED); | ||
| 114 | +} | ||
| 115 | + | ||
| 116 | +// Test 4: Verify successful fusion with float32 dtype | ||
| 117 | +TEST_F(RandomStandardNormalFusionPassTest, fusionFloatSuccess) | ||
| 118 | +{ | ||
| 119 | + fe::PlatformInfo platformInfo; | ||
| 120 | + fe::OptionalInfo optiCompilationInfo; | ||
| 121 | + platformInfo.soc_info.ai_core_cnt = 64; | ||
| 122 | + platformInfo.str_info.short_soc_version = "Ascend950"; | ||
| 123 | + optiCompilationInfo.soc_version = "Ascend950"; | ||
| 124 | + fe::PlatformInfoManager::Instance().platform_info_map_["Ascend950"] = platformInfo; | ||
| 125 | + fe::PlatformInfoManager::Instance().SetOptionalCompilationInfo(optiCompilationInfo); | ||
| 126 | + | ||
| 127 | + std::vector<int64_t> shapeDims{2}; | ||
| 128 | + | ||
| 129 | + auto graphBuilder = es::EsGraphBuilder("test"); | ||
| 130 | + auto shape = graphBuilder.CreateInput(0, "shape", DT_INT64, FORMAT_ND, shapeDims); | ||
| 131 | + auto output = es::RandomStandardNormal(shape, DT_FLOAT, 1024, 2048); | ||
| 132 | + | ||
| 133 | + TensorDesc shapeDesc; | ||
| 134 | + shape.GetProducer()->GetOutputDesc(0, shapeDesc); | ||
| 135 | + shapeDesc.SetDataType(DT_INT64); | ||
| 136 | + shapeDesc.SetShape(Shape(shapeDims)); | ||
| 137 | + shapeDesc.SetFormat(FORMAT_ND); | ||
| 138 | + shape.GetProducer()->UpdateOutputDesc(0, shapeDesc); | ||
| 139 | + | ||
| 140 | + std::shared_ptr<Graph> graph = graphBuilder.BuildAndReset({output}); | ||
| 141 | + CustomPassContext passContext; | ||
| 142 | + ops::RandomStandardNormalFusionPass pass; | ||
| 143 | + Status status = pass.Run(graph, passContext); | ||
| 144 | + | ||
| 145 | + EXPECT_EQ(status, SUCCESS); | ||
| 146 | + | ||
| 147 | + // Verify RandomStandardNormalV2 node exists | ||
| 148 | + bool foundV2 = false; | ||
| 149 | + for (auto node : graph->GetAllNodes()) { | ||
| 150 | + AscendString type; | ||
| 151 | + node.GetType(type); | ||
| 152 | + if (std::string(type.GetString()) == "RandomStandardNormalV2") { | ||
| 153 | + foundV2 = true; | ||
| 154 | + } | ||
| 155 | + } | ||
| 156 | + EXPECT_TRUE(foundV2); | ||
| 157 | +} | ||
| 158 | + | ||
| 159 | +// Test 5: Verify successful fusion with float16 dtype | ||
| 160 | +TEST_F(RandomStandardNormalFusionPassTest, fusionFloat16Success) | ||
| 161 | +{ | ||
| 162 | + fe::PlatformInfo platformInfo; | ||
| 163 | + fe::OptionalInfo optiCompilationInfo; | ||
S
![]() ![]() | |||
| 164 | + platformInfo.soc_info.ai_core_cnt = 64; | ||
| 165 | + platformInfo.str_info.short_soc_version = "Ascend950"; | ||
| 166 | + optiCompilationInfo.soc_version = "Ascend950"; | ||
| 167 | + fe::PlatformInfoManager::Instance().platform_info_map_["Ascend950"] = platformInfo; | ||
| 168 | + fe::PlatformInfoManager::Instance().SetOptionalCompilationInfo(optiCompilationInfo); | ||
| 169 | + | ||
| 170 | + std::vector<int64_t> shapeDims{3}; | ||
| 171 | + | ||
| 172 | + auto graphBuilder = es::EsGraphBuilder("test"); | ||
| 173 | + auto shape = graphBuilder.CreateInput(0, "shape", DT_INT64, FORMAT_ND, shapeDims); | ||
| 174 | + auto output = es::RandomStandardNormal(shape, DT_FLOAT16, 0, 0); | ||
| 175 | + | ||
| 176 | + TensorDesc shapeDesc; | ||
| 177 | + shape.GetProducer()->GetOutputDesc(0, shapeDesc); | ||
| 178 | + shapeDesc.SetDataType(DT_INT64); | ||
| 179 | + shapeDesc.SetShape(Shape(shapeDims)); | ||
| 180 | + shapeDesc.SetFormat(FORMAT_ND); | ||
| 181 | + shape.GetProducer()->UpdateOutputDesc(0, shapeDesc); | ||
| 182 | + | ||
| 183 | + std::shared_ptr<Graph> graph = graphBuilder.BuildAndReset({output}); | ||
| 184 | + CustomPassContext passContext; | ||
| 185 | + ops::RandomStandardNormalFusionPass pass; | ||
| 186 | + Status status = pass.Run(graph, passContext); | ||
| 187 | + | ||
| 188 | + EXPECT_EQ(status, SUCCESS); | ||
| 189 | + | ||
| 190 | + bool foundV2 = false; | ||
| 191 | + for (auto node : graph->GetAllNodes()) { | ||
| 192 | + AscendString type; | ||
| 193 | + node.GetType(type); | ||
| 194 | + if (std::string(type.GetString()) == "RandomStandardNormalV2") { | ||
| 195 | + foundV2 = true; | ||
| 196 | + } | ||
| 197 | + } | ||
| 198 | + EXPECT_TRUE(foundV2); | ||
| 199 | +} | ||
| 200 | + | ||
| 201 | +// Test 6: Verify successful fusion with bfloat16 dtype | ||
| 202 | +TEST_F(RandomStandardNormalFusionPassTest, fusionBf16Success) | ||
| 203 | +{ | ||
| 204 | + fe::PlatformInfo platformInfo; | ||
| 205 | + fe::OptionalInfo optiCompilationInfo; | ||
| 206 | + platformInfo.soc_info.ai_core_cnt = 64; | ||
| 207 | + platformInfo.str_info.short_soc_version = "Ascend950"; | ||
| 208 | + optiCompilationInfo.soc_version = "Ascend950"; | ||
| 209 | + fe::PlatformInfoManager::Instance().platform_info_map_["Ascend950"] = platformInfo; | ||
| 210 | + fe::PlatformInfoManager::Instance().SetOptionalCompilationInfo(optiCompilationInfo); | ||
| 211 | + | ||
| 212 | + std::vector<int64_t> shapeDims{2}; | ||
| 213 | + | ||
| 214 | + auto graphBuilder = es::EsGraphBuilder("test"); | ||
| 215 | + auto shape = graphBuilder.CreateInput(0, "shape", DT_INT64, FORMAT_ND, shapeDims); | ||
| 216 | + auto output = es::RandomStandardNormal(shape, DT_BF16, 512, 1024); | ||
| 217 | + | ||
| 218 | + TensorDesc shapeDesc; | ||
| 219 | + shape.GetProducer()->GetOutputDesc(0, shapeDesc); | ||
| 220 | + shapeDesc.SetDataType(DT_INT64); | ||
| 221 | + shapeDesc.SetShape(Shape(shapeDims)); | ||
| 222 | + shapeDesc.SetFormat(FORMAT_ND); | ||
| 223 | + shape.GetProducer()->UpdateOutputDesc(0, shapeDesc); | ||
| 224 | + | ||
| 225 | + std::shared_ptr<Graph> graph = graphBuilder.BuildAndReset({output}); | ||
| 226 | + CustomPassContext passContext; | ||
| 227 | + ops::RandomStandardNormalFusionPass pass; | ||
| 228 | + Status status = pass.Run(graph, passContext); | ||
| 229 | + | ||
| 230 | + EXPECT_EQ(status, SUCCESS); | ||
| 231 | + | ||
| 232 | + bool foundV2 = false; | ||
| 233 | + for (auto node : graph->GetAllNodes()) { | ||
| 234 | + AscendString type; | ||
| 235 | + node.GetType(type); | ||
| 236 | + if (std::string(type.GetString()) == "RandomStandardNormalV2") { | ||
| 237 | + foundV2 = true; | ||
| 238 | + } | ||
| 239 | + } | ||
| 240 | + EXPECT_TRUE(foundV2); | ||
| 241 | +} | ||
| 242 | + | ||
| 243 | +// Test 7: Verify successful fusion on Ascend950 platform | ||
| 244 | +TEST_F(RandomStandardNormalFusionPassTest, fusion950Success) | ||
| 245 | +{ | ||
| 246 | + fe::PlatformInfo platformInfo; | ||
| 247 | + fe::OptionalInfo optiCompilationInfo; | ||
| 248 | + platformInfo.soc_info.ai_core_cnt = 64; | ||
| 249 | + platformInfo.str_info.short_soc_version = "Ascend950"; | ||
| 250 | + optiCompilationInfo.soc_version = "Ascend950"; | ||
| 251 | + fe::PlatformInfoManager::Instance().platform_info_map_["Ascend950"] = platformInfo; | ||
| 252 | + fe::PlatformInfoManager::Instance().SetOptionalCompilationInfo(optiCompilationInfo); | ||
| 253 | + | ||
| 254 | + std::vector<int64_t> shapeDims{4}; | ||
| 255 | + | ||
| 256 | + auto graphBuilder = es::EsGraphBuilder("test"); | ||
| 257 | + auto shape = graphBuilder.CreateInput(0, "shape", DT_INT64, FORMAT_ND, shapeDims); | ||
| 258 | + auto output = es::RandomStandardNormal(shape, DT_FLOAT, 512, 1024); | ||
| 259 | + | ||
| 260 | + TensorDesc shapeDesc; | ||
| 261 | + shape.GetProducer()->GetOutputDesc(0, shapeDesc); | ||
| 262 | + shapeDesc.SetDataType(DT_INT64); | ||
| 263 | + shapeDesc.SetShape(Shape(shapeDims)); | ||
| 264 | + shapeDesc.SetFormat(FORMAT_ND); | ||
| 265 | + shape.GetProducer()->UpdateOutputDesc(0, shapeDesc); | ||
| 266 | + | ||
| 267 | + std::shared_ptr<Graph> graph = graphBuilder.BuildAndReset({output}); | ||
| 268 | + CustomPassContext passContext; | ||
| 269 | + ops::RandomStandardNormalFusionPass pass; | ||
| 270 | + Status status = pass.Run(graph, passContext); | ||
| 271 | + | ||
| 272 | + EXPECT_EQ(status, SUCCESS); | ||
| 273 | + | ||
| 274 | + bool foundV2 = false; | ||
| 275 | + for (auto node : graph->GetAllNodes()) { | ||
| 276 | + AscendString type; | ||
| 277 | + node.GetType(type); | ||
| 278 | + if (std::string(type.GetString()) == "RandomStandardNormalV2") { | ||
| 279 | + foundV2 = true; | ||
| 280 | + } | ||
| 281 | + } | ||
| 282 | + EXPECT_TRUE(foundV2); | ||
| 283 | +} | ||
| 284 | + | ||
| 285 | +// Test 8: Verify successful fusion with different shape dimension | ||
| 286 | +TEST_F(RandomStandardNormalFusionPassTest, fusionDifferentShapeSuccess) | ||
| 287 | +{ | ||
| 288 | + fe::PlatformInfo platformInfo; | ||
| 289 | + fe::OptionalInfo optiCompilationInfo; | ||
| 290 | + platformInfo.soc_info.ai_core_cnt = 64; | ||
| 291 | + platformInfo.str_info.short_soc_version = "Ascend950"; | ||
| 292 | + optiCompilationInfo.soc_version = "Ascend950"; | ||
| 293 | + fe::PlatformInfoManager::Instance().platform_info_map_["Ascend950"] = platformInfo; | ||
| 294 | + fe::PlatformInfoManager::Instance().SetOptionalCompilationInfo(optiCompilationInfo); | ||
| 295 | + | ||
| 296 | + std::vector<int64_t> shapeDims{4}; | ||
| 297 | + | ||
| 298 | + auto graphBuilder = es::EsGraphBuilder("test"); | ||
| 299 | + auto shape = graphBuilder.CreateInput(0, "shape", DT_INT64, FORMAT_ND, shapeDims); | ||
| 300 | + auto output = es::RandomStandardNormal(shape, DT_FLOAT, 0, 0); | ||
| 301 | + | ||
| 302 | + TensorDesc shapeDesc; | ||
| 303 | + shape.GetProducer()->GetOutputDesc(0, shapeDesc); | ||
| 304 | + shapeDesc.SetDataType(DT_INT64); | ||
| 305 | + shapeDesc.SetShape(Shape(shapeDims)); | ||
| 306 | + shapeDesc.SetFormat(FORMAT_ND); | ||
| 307 | + shape.GetProducer()->UpdateOutputDesc(0, shapeDesc); | ||
| 308 | + | ||
| 309 | + std::shared_ptr<Graph> graph = graphBuilder.BuildAndReset({output}); | ||
| 310 | + CustomPassContext passContext; | ||
| 311 | + ops::RandomStandardNormalFusionPass pass; | ||
| 312 | + Status status = pass.Run(graph, passContext); | ||
| 313 | + | ||
| 314 | + EXPECT_EQ(status, SUCCESS); | ||
| 315 | + | ||
| 316 | + bool foundV2 = false; | ||
| 317 | + for (auto node : graph->GetAllNodes()) { | ||
| 318 | + AscendString type; | ||
| 319 | + node.GetType(type); | ||
| 320 | + if (std::string(type.GetString()) == "RandomStandardNormalV2") { | ||
| 321 | + foundV2 = true; | ||
| 322 | + } | ||
| 323 | + } | ||
| 324 | + EXPECT_TRUE(foundV2); | ||
| 325 | +} | ||
| @@ -47,12 +47,10 @@ if(UT_TEST_ALL OR OP_GRAPH_UT) | |||
| 47 | -Wl,--no-whole-archive | 47 | -Wl,--no-whole-archive |
| 48 | -Wl,--no-as-needed | 48 | -Wl,--no-as-needed |
| 49 | metadef | 49 | metadef |
| 50 | - ge_common | ||
| 51 | -Wl,--as-needed | 50 | -Wl,--as-needed |
| 52 | error_manager | 51 | error_manager |
| 53 | exe_graph | 52 | exe_graph |
| 54 | graph_base | 53 | graph_base |
| 55 | - ge_common | ||
| 56 | gtest | 54 | gtest |
| 57 | graph | 55 | graph |
| 58 | register | 56 | register |


inputDtypes[0]、inputFormats[0]、inputShapes[0]直接按下标访问,没有对subgraphInputs做空检查。虽然正常匹配流程下不应该为空,但如果GetAllInputs返回空容器,这里会有越界访问的风险。建议加一个防御性检查。