已合并
add fusion pass: multi_add_rms_norm_dynamic_quant | dynamic_quant_update_scatter_v2 #5243
liu-zihao35创建于 5月25日
add fusion pass: multi_add_rms_norm_dynamic_quant | dynamic_quant_update_scatter_v2 #5243
已合并
共 11 个文件变更+2209-6
The file is empty
| @@ -0,0 +1,601 @@ | |||
| 1 | +/** | ||
| 2 | + * Copyright (c) 2026 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 multi_add_rms_norm_dynamic_quant_fusion_pass.cpp | ||
| 13 | + * \brief quant fusion for multiaddrmsnorm | ||
| 14 | + * | ||
| 15 | + * Function: Define fusion multiple Add and AddRmsNorm and dynamicquant pattern; | ||
| 16 | + * Fusion pattern: | ||
| 17 | + * ... | ||
| 18 | + * x1_0 x1_1 or Add_1 | ||
| 19 | + * \ / (x1: 1-5 list of tensor) | ||
| 20 | + * gamma x2 Add_0 (dynamic, 0-4 Add op) x1 x2 gamma s1 s2 | ||
| 21 | + * \ | / \ | / / / | ||
| 22 | + * AddRmsNorm ==> MultiAddRmsNormDynamicQuant | ||
| 23 | + * / | / / | | \ \ | ||
| 24 | + * x (Reshape) (Reshape) (Reshape) | (Reshape) \ \ | ||
| 25 | + * | / / | | \ \ | ||
| 26 | + * y--+ (s1) (s2) y1 y2 x y scale1 scale2 | ||
| 27 | + * | * * | ||
| 28 | + * / \* * Note: Either all or none Reshape(s) are present. | ||
| 29 | + * / * \ * | ||
| 30 | + * DynamicQuant (DynamicQuant) (1-2 dynamic DQ) | ||
| 31 | + * / \ / \ | ||
| 32 | + * y1 scale1 y2 scale2 | ||
| 33 | + * | ||
| 34 | + */ | ||
| 35 | + | ||
| 36 | +#include "multi_add_rms_norm_dynamic_quant_fusion_pass.h" | ||
| 37 | + | ||
| 38 | +#include <string> | ||
| 39 | +#include <vector> | ||
| 40 | + | ||
| 41 | +#include "ge/ge_utils.h" | ||
| 42 | +#include "common/inc/error_util.h" | ||
| 43 | +#include "es_nn_ops.h" | ||
| 44 | +#include "es_math_ops.h" | ||
| 45 | +#include "platform/platform_info.h" | ||
| 46 | +#include "compliant_node_builder.h" | ||
| 47 | + | ||
| 48 | +using namespace ge; | ||
| 49 | +using namespace fe; | ||
| 50 | +using namespace fusion; | ||
| 51 | + | ||
| 52 | +namespace ops { | ||
| 53 | + | ||
| 54 | +static const std::string FUSED_OP_TYPE = "MultiAddRmsNormDynamicQuant"; | ||
| 55 | +static const std::string SOC_ASCEND910B = "Ascend910b"; | ||
| 56 | +static const std::string SOC_ASCEND910_93 = "Ascend910_93"; | ||
| 57 | + | ||
| 58 | +using UniqueGraphPtr = std::unique_ptr<Graph>; | ||
| 59 | +static const std::string PASS_NAME = "MultiAddRmsNormDynamicQuantFusionPass"; | ||
| 60 | + | ||
| 61 | +static es::EsTensorHolder BuildPatternConstNode(es::EsGraphBuilder& builder) | ||
| 62 | +{ | ||
| 63 | + static int counter = 0; | ||
| 64 | + std::string name = "Const_" + std::to_string(counter++); | ||
| 65 | + auto graph = builder.GetCGraphBuilder()->GetGraph(); | ||
| 66 | + GNode node = es::CompliantNodeBuilder(graph) | ||
| 67 | + .OpType("Const") | ||
| 68 | + .Name(name.c_str()) | ||
| 69 | + .IrDefOutputs({{"y", es::CompliantNodeBuilder::kEsIrOutputRequired, ""}}) | ||
| 70 | + .Build(); | ||
| 71 | + return es::EsTensorHolder(builder.GetCGraphBuilder()->GetTensorHolderFromNode(node, 0)); | ||
| 72 | +} | ||
| 73 | + | ||
| 74 | +static es::EsTensorHolder BuildPatternReshapeNode( | ||
| 75 | + es::EsGraphBuilder& builder, const es::EsTensorHolder& x, const es::EsTensorHolder& shape) | ||
| 76 | +{ | ||
| 77 | + static int counter = 0; | ||
| 78 | + std::string name = "Reshape_" + std::to_string(counter++); | ||
| 79 | + auto graph = builder.GetCGraphBuilder()->GetGraph(); | ||
| 80 | + GNode node = es::CompliantNodeBuilder(graph) | ||
| 81 | + .OpType("Reshape") | ||
| 82 | + .Name(name.c_str()) | ||
| 83 | + .IrDefInputs({ | ||
| 84 | + {"x", es::CompliantNodeBuilder::kEsIrInputRequired, ""}, | ||
| 85 | + {"shape", es::CompliantNodeBuilder::kEsIrInputRequired, ""} | ||
| 86 | + }) | ||
| 87 | + .IrDefOutputs({{"y", es::CompliantNodeBuilder::kEsIrOutputRequired, ""}}) | ||
| 88 | + .Build(); | ||
| 89 | + es::AddEdgeAndUpdatePeerDesc(*graph, *x.GetProducer(), x.GetProducerOutIndex(), node, 0); | ||
| 90 | + es::AddEdgeAndUpdatePeerDesc(*graph, *shape.GetProducer(), shape.GetProducerOutIndex(), node, 1); | ||
| 91 | + return es::EsTensorHolder(builder.GetCGraphBuilder()->GetTensorHolderFromNode(node, 0)); | ||
| 92 | +} | ||
| 93 | + | ||
| 94 | +static constexpr int64_t OUTPUT_IDX_Y1 = 0; | ||
| 95 | +static constexpr int64_t OUTPUT_IDX_Y2 = 1; | ||
| 96 | +static constexpr int64_t OUTPUT_IDX_X = 2; | ||
| 97 | +static constexpr int64_t OUTPUT_IDX_Y = 3; | ||
| 98 | +static constexpr int64_t OUTPUT_IDX_SCALE1 = 4; | ||
| 99 | +static constexpr int64_t OUTPUT_IDX_SCALE2 = 5; | ||
| 100 | + | ||
| @@ -0,0 +1,41 @@ | |||
| 1 | +/** | ||
| 2 | + * Copyright (c) 2026 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 multi_add_rms_norm_dynamic_quant_fusion_pass.h | ||
| 13 | + * \brief quant fusion for multi-add, addrmsnorm | ||
| 14 | + */ | ||
| 15 | + | ||
| 16 | +#ifndef OPS_BUILT_IN_FUSION_PASS_GRAPH_FUSION_AI_CORE_MULTI_ADD_RMS_NORM_DYNAMIC_QUANT_FUSION_PASS_H_ | ||
| 17 | +#define OPS_BUILT_IN_FUSION_PASS_GRAPH_FUSION_AI_CORE_MULTI_ADD_RMS_NORM_DYNAMIC_QUANT_FUSION_PASS_H_ | ||
| 18 | + | ||
| 19 | +#include "ge/fusion/pass/pattern_fusion_pass.h" | ||
| 20 | + | ||
| 21 | +namespace ops { | ||
| 22 | +using namespace ge; | ||
| 23 | +using namespace fusion; | ||
| 24 | + | ||
| 25 | +class __attribute__((visibility("default"))) MultiAddRmsNormDynamicQuantFusionPass : public PatternFusionPass { | ||
| 26 | +protected: | ||
| 27 | + std::vector<PatternUniqPtr> Patterns() override; | ||
| 28 | + bool MeetRequirements(const std::unique_ptr<MatchResult>& match_result) override; | ||
| 29 | + std::unique_ptr<Graph> Replacement(const std::unique_ptr<MatchResult>& match_result) override; | ||
| 30 | + | ||
| 31 | +private: | ||
| 32 | + static constexpr int64_t MAX_ADD_NUM = 4; | ||
| 33 | + static constexpr int64_t MAX_SMOOTH_NUM = 2; | ||
| 34 | + int64_t add_num_ = 0; | ||
| 35 | + int64_t smooth_num_ = 0; | ||
| 36 | + bool has_reshape_ = false; | ||
| 37 | +}; | ||
| 38 | + | ||
| 39 | +} // namespace ops | ||
| 40 | + | ||
| 41 | +#endif // OPS_BUILT_IN_FUSION_PASS_GRAPH_FUSION_AI_CORE_MULTI_ADD_RMS_NORM_DYNAMIC_QUANT_FUSION_PASS_H_ | ||
Rnorm/multi_add_rms_norm_dynamic_quant/CMakeLists.txt→norm/multi_add_rms_norm_dynamic_quant/tests/ut/op_graph/CMakeLists.txt+2-3
| @@ -8,10 +8,9 @@ | |||
| 8 | # See LICENSE in the root of the software repository for the full text of the License. | 8 | # See LICENSE in the root of the software repository for the full text of the License. |
| 9 | # ---------------------------------------------------------------------------- | 9 | # ---------------------------------------------------------------------------- |
| 10 | 10 | ||
| 11 | +# 每个目录下需要生成的可执行文件,具体参考:ops/built-in/test/CMakeLists.txt: 50~124 | ||
| 11 | file(GLOB CURRENT_DIRS RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/*) | 12 | file(GLOB CURRENT_DIRS RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/*) |
| 12 | -if(NOT ENABLE_TEST AND NOT BENCHMARK) | 13 | +message(STATUS "=== Debug: CURRENT_DIRS =${CURRENT_DIRS} ") |
| 13 | - list(REMOVE_ITEM CURRENT_DIRS tests) | ||
| 14 | -endif() | ||
| 15 | foreach(SUB_DIR ${CURRENT_DIRS}) | 14 | foreach(SUB_DIR ${CURRENT_DIRS}) |
| 16 | if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/${SUB_DIR}/CMakeLists.txt") | 15 | if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/${SUB_DIR}/CMakeLists.txt") |
| 17 | add_subdirectory(${SUB_DIR}) | 16 | add_subdirectory(${SUB_DIR}) |
| @@ -0,0 +1,331 @@ | |||
| 1 | +/** | ||
| 2 | + * Copyright (c) 2026 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 | +#include "gtest/gtest.h" | ||
| 12 | +#include "multi_add_rms_norm_dynamic_quant_fusion_pass.h" | ||
| 13 | +#include "es_nn_ops.h" | ||
| 14 | +#include "es_math_ops.h" | ||
| 15 | +#include "platform/platform_info.h" | ||
| 16 | +#include "platform_info_stub.h" | ||
| 17 | +#include "compliant_node_builder.h" | ||
| 18 | + | ||
| 19 | +using namespace ge; | ||
| 20 | +using namespace fe; | ||
| 21 | +using namespace fusion; | ||
| 22 | + | ||
| 23 | +static es::EsTensorHolder BuildConstNode(es::EsGraphBuilder& builder) | ||
| 24 | +{ | ||
| 25 | + static int counter = 0; | ||
| 26 | + std::string name = "Const_" + std::to_string(counter++); | ||
| 27 | + auto graph = builder.GetCGraphBuilder()->GetGraph(); | ||
| 28 | + GNode node = es::CompliantNodeBuilder(graph) | ||
| 29 | + .OpType("Const") | ||
| 30 | + .Name(name.c_str()) | ||
| 31 | + .IrDefOutputs({{"y", es::CompliantNodeBuilder::kEsIrOutputRequired, ""}}) | ||
| 32 | + .Build(); | ||
| 33 | + return es::EsTensorHolder(builder.GetCGraphBuilder()->GetTensorHolderFromNode(node, 0)); | ||
| 34 | +} | ||
| 35 | + | ||
| 36 | +static es::EsTensorHolder BuildReshapeNode( | ||
| 37 | + es::EsGraphBuilder& builder, const es::EsTensorHolder& x, const es::EsTensorHolder& shape) | ||
| 38 | +{ | ||
| 39 | + static int counter = 0; | ||
| 40 | + std::string name = "Reshape_" + std::to_string(counter++); | ||
| 41 | + auto graph = builder.GetCGraphBuilder()->GetGraph(); | ||
| 42 | + GNode node = es::CompliantNodeBuilder(graph) | ||
| 43 | + .OpType("Reshape") | ||
| 44 | + .Name(name.c_str()) | ||
| 45 | + .IrDefInputs({ | ||
| 46 | + {"x", es::CompliantNodeBuilder::kEsIrInputRequired, ""}, | ||
| 47 | + {"shape", es::CompliantNodeBuilder::kEsIrInputRequired, ""} | ||
| 48 | + }) | ||
| 49 | + .IrDefOutputs({{"y", es::CompliantNodeBuilder::kEsIrOutputRequired, ""}}) | ||
| 50 | + .Build(); | ||
| 51 | + es::AddEdgeAndUpdatePeerDesc(*graph, *x.GetProducer(), x.GetProducerOutIndex(), node, 0); | ||
| 52 | + es::AddEdgeAndUpdatePeerDesc(*graph, *shape.GetProducer(), shape.GetProducerOutIndex(), node, 1); | ||
| 53 | + return es::EsTensorHolder(builder.GetCGraphBuilder()->GetTensorHolderFromNode(node, 0)); | ||
| 54 | +} | ||
| 55 | + | ||
| 56 | +static GNode BuildAddNode( | ||
| 57 | + es::EsGraphBuilder& builder, const es::EsTensorHolder& x1, const es::EsTensorHolder& x2) | ||
| 58 | +{ | ||
| 59 | + static int counter = 0; | ||
| 60 | + std::string name = "Add_" + std::to_string(counter++); | ||
| 61 | + auto graph = builder.GetCGraphBuilder()->GetGraph(); | ||
| 62 | + GNode node = es::CompliantNodeBuilder(graph) | ||
| 63 | + .OpType("Add") | ||
| 64 | + .Name(name.c_str()) | ||
| 65 | + .IrDefInputs({ | ||
| 66 | + {"x1", es::CompliantNodeBuilder::kEsIrInputRequired, ""}, | ||
| 67 | + {"x2", es::CompliantNodeBuilder::kEsIrInputRequired, ""} | ||
| 68 | + }) | ||
| 69 | + .IrDefOutputs({{"y", es::CompliantNodeBuilder::kEsIrOutputRequired, ""}}) | ||
| 70 | + .Build(); | ||
| 71 | + es::AddEdgeAndUpdatePeerDesc(*graph, *x1.GetProducer(), x1.GetProducerOutIndex(), node, 0); | ||
| 72 | + es::AddEdgeAndUpdatePeerDesc(*graph, *x2.GetProducer(), x2.GetProducerOutIndex(), node, 1); | ||
| 73 | + return node; | ||
| 74 | +} | ||
| 75 | + | ||
| 76 | +static es::EsTensorHolder BuildAddTensor( | ||
| 77 | + es::EsGraphBuilder& builder, const es::EsTensorHolder& x1, const es::EsTensorHolder& x2) | ||
| 78 | +{ | ||
| 79 | + GNode node = BuildAddNode(builder, x1, x2); | ||
| 80 | + return es::EsTensorHolder(builder.GetCGraphBuilder()->GetTensorHolderFromNode(node, 0)); | ||
| 81 | +} | ||
| 82 | + | ||
| 83 | +struct AddRmsNormResult { | ||
| 84 | + es::EsTensorHolder x; | ||
| 85 | + es::EsTensorHolder y; | ||
| 86 | + es::EsTensorHolder rstd; | ||
| 87 | +}; | ||
| 88 | + | ||
| 89 | +static AddRmsNormResult BuildAddRmsNormNode( | ||
| 90 | + es::EsGraphBuilder& builder, const es::EsTensorHolder& x1, | ||
| 91 | + const es::EsTensorHolder& x2, const es::EsTensorHolder& gamma) | ||
| 92 | +{ | ||
| 93 | + static int counter = 0; | ||
| 94 | + std::string name = "AddRmsNorm_" + std::to_string(counter++); | ||
| 95 | + auto graph = builder.GetCGraphBuilder()->GetGraph(); | ||
| 96 | + GNode node = es::CompliantNodeBuilder(graph) | ||
| 97 | + .OpType("AddRmsNorm") | ||
| 98 | + .Name(name.c_str()) | ||
| 99 | + .IrDefInputs({ | ||
| 100 | + {"x1", es::CompliantNodeBuilder::kEsIrInputRequired, ""}, | ||
| 101 | + {"x2", es::CompliantNodeBuilder::kEsIrInputRequired, ""}, | ||
| 102 | + {"gamma", es::CompliantNodeBuilder::kEsIrInputRequired, ""} | ||
| 103 | + }) | ||
| 104 | + .IrDefOutputs({ | ||
| 105 | + {"y", es::CompliantNodeBuilder::kEsIrOutputRequired, ""}, | ||
| 106 | + {"rstd", es::CompliantNodeBuilder::kEsIrOutputRequired, ""}, | ||
| 107 | + {"x", es::CompliantNodeBuilder::kEsIrOutputRequired, ""} | ||
| 108 | + }) | ||
| 109 | + .IrDefAttrs({ | ||
| 110 | + {"epsilon", es::CompliantNodeBuilder::kEsAttrOptional, "Float", | ||
| 111 | + es::CreateFrom(1e-6f)} | ||
| 112 | + }) | ||
| 113 | + .Build(); | ||
| 114 | + es::AddEdgeAndUpdatePeerDesc(*graph, *x1.GetProducer(), x1.GetProducerOutIndex(), node, 0); | ||
| 115 | + es::AddEdgeAndUpdatePeerDesc(*graph, *x2.GetProducer(), x2.GetProducerOutIndex(), node, 1); | ||
| 116 | + es::AddEdgeAndUpdatePeerDesc(*graph, *gamma.GetProducer(), gamma.GetProducerOutIndex(), node, 2); | ||
| 117 | + return { | ||
| 118 | + es::EsTensorHolder(builder.GetCGraphBuilder()->GetTensorHolderFromNode(node, 2)), | ||
| 119 | + es::EsTensorHolder(builder.GetCGraphBuilder()->GetTensorHolderFromNode(node, 0)), | ||
| 120 | + es::EsTensorHolder(builder.GetCGraphBuilder()->GetTensorHolderFromNode(node, 1)) | ||
| 121 | + }; | ||
| 122 | +} | ||
| 123 | + | ||
| 124 | +struct DynamicQuantResult { | ||
| 125 | + es::EsTensorHolder y; | ||
| 126 | + es::EsTensorHolder scale; | ||
| 127 | +}; | ||
| 128 | + | ||
| 129 | +static DynamicQuantResult BuildDynamicQuantNode( | ||
| 130 | + es::EsGraphBuilder& builder, const es::EsTensorHolder& x, const es::EsTensorHolder& smooth) | ||
| 131 | +{ | ||
| 132 | + static int counter = 0; | ||
| 133 | + std::string name = "DynamicQuant_" + std::to_string(counter++); | ||
| 134 | + auto graph = builder.GetCGraphBuilder()->GetGraph(); | ||
| 135 | + GNode node = es::CompliantNodeBuilder(graph) | ||
| 136 | + .OpType("DynamicQuant") | ||
| 137 | + .Name(name.c_str()) | ||
| 138 | + .IrDefInputs({ | ||
| 139 | + {"x", es::CompliantNodeBuilder::kEsIrInputRequired, ""}, | ||
| 140 | + {"smooth_scales", es::CompliantNodeBuilder::kEsIrInputRequired, ""}, | ||
| 141 | + {"group_index", es::CompliantNodeBuilder::kEsIrInputOptional, ""} | ||
| 142 | + }) | ||
| 143 | + .IrDefOutputs({ | ||
| 144 | + {"y", es::CompliantNodeBuilder::kEsIrOutputRequired, ""}, | ||
| 145 | + {"scale", es::CompliantNodeBuilder::kEsIrOutputRequired, ""} | ||
| 146 | + }) | ||
| 147 | + .Build(); | ||
| 148 | + es::AddEdgeAndUpdatePeerDesc(*graph, *x.GetProducer(), x.GetProducerOutIndex(), node, 0); | ||
| 149 | + es::AddEdgeAndUpdatePeerDesc(*graph, *smooth.GetProducer(), smooth.GetProducerOutIndex(), node, 1); | ||
| 150 | + return { | ||
| 151 | + es::EsTensorHolder(builder.GetCGraphBuilder()->GetTensorHolderFromNode(node, 0)), | ||
| 152 | + es::EsTensorHolder(builder.GetCGraphBuilder()->GetTensorHolderFromNode(node, 1)) | ||
| 153 | + }; | ||
| 154 | +} | ||
| 155 | + | ||
| 156 | +class multi_add_rms_norm_dynamic_quant_fusion_test : public testing::Test { | ||
| 157 | +protected: | ||
| 158 | + static void SetUpTestCase() | ||
| 159 | + { | ||
| 160 | + std::cout << "multi_add_rms_norm_dynamic_quant_fusion_test SetUp" << std::endl; | ||
| 161 | + } | ||
| 162 | + | ||
| 163 | + static void TearDownTestCase() | ||
| 164 | + { | ||
| 165 | + std::cout << "multi_add_rms_norm_dynamic_quant_fusion_test TearDown" << std::endl; | ||
| 166 | + } | ||
| 167 | + | ||
| 168 | + void SetUpPlatform() | ||
| 169 | + { | ||
| 170 | + PlatformInfo platform_info; | ||
| 171 | + OptionalInfo opti_compilation_info; | ||
| 172 | + platform_info.soc_info.ai_core_cnt = 40; | ||
| 173 | + opti_compilation_info.soc_version = "Ascend910B1"; | ||
| 174 | + platform_info.str_info.short_soc_version = "Ascend910B"; | ||
| 175 | + PlatformInfoManager::Instance().platform_info_map_["Ascend910B1"] = platform_info; | ||
| 176 | + PlatformInfoManager::Instance().SetOptionalCompilationInfo(opti_compilation_info); | ||
| 177 | + } | ||
| 178 | + | ||
| 179 | + void ClearPlatform() | ||
| 180 | + { | ||
| 181 | + PlatformInfoManager::Instance().platform_info_map_.clear(); | ||
| 182 | + } | ||
| 183 | + | ||
| 184 | + bool HasFusedOp(std::shared_ptr<Graph>& graph, const std::string& op_type) | ||
| 185 | + { | ||
| 186 | + for (auto node : graph->GetAllNodes()) { | ||
| 187 | + AscendString type; | ||
| 188 | + node.GetType(type); | ||
| 189 | + if (type == op_type.c_str()) { | ||
| 190 | + return true; | ||
| 191 | + } | ||
| 192 | + } | ||
| 193 | + return false; | ||
| 194 | + } | ||
| 195 | +}; | ||
| 196 | + | ||
| 197 | +/** | ||
| 198 | + * Test dual: 2 Add + AddRmsNorm + 2 DynamicQuant (with separate smooth_scales inputs) | ||
| 199 | + * Graph topology: | ||
| 200 | + * x1_0, x1_1 -> Add1 -> Add2(with x1_2) -> AddRmsNorm(with x2, gamma) -> [y, x_out] | ||
| 201 | + * y, smooth1 -> DynamicQuant1 -> [y1, scale1] | ||
| 202 | + * y, smooth2 -> DynamicQuant2 -> [y2, scale2] | ||
| 203 | + */ | ||
| 204 | +TEST_F(multi_add_rms_norm_dynamic_quant_fusion_test, multi_add_rms_norm_dynamic_quant_fusion_test_dual) | ||
| 205 | +{ | ||
| 206 | + SetUpPlatform(); | ||
| 207 | + | ||
| 208 | + std::vector<int64_t> dims_x{1, 1024, 8192}; | ||
| 209 | + std::vector<int64_t> dims_gamma{8192}; | ||
| 210 | + | ||
| 211 | + auto graph_builder = es::EsGraphBuilder("multi_add_rms_norm_dq_dual"); | ||
| 212 | + auto x1_0 = graph_builder.CreateInput(0, "x1_0", DT_FLOAT16, FORMAT_ND, dims_x); | ||
| 213 | + auto x1_1 = graph_builder.CreateInput(1, "x1_1", DT_FLOAT16, FORMAT_ND, dims_x); | ||
| 214 | + auto x1_2 = graph_builder.CreateInput(2, "x1_2", DT_FLOAT16, FORMAT_ND, dims_x); | ||
| 215 | + auto x2 = graph_builder.CreateInput(3, "x2", DT_FLOAT16, FORMAT_ND, dims_x); | ||
| 216 | + auto gamma = graph_builder.CreateInput(4, "gamma", DT_FLOAT16, FORMAT_ND, dims_gamma); | ||
| 217 | + auto smooth1 = graph_builder.CreateInput(5, "smooth1", DT_FLOAT16, FORMAT_ND, dims_gamma); | ||
| 218 | + auto smooth2 = graph_builder.CreateInput(6, "smooth2", DT_FLOAT16, FORMAT_ND, dims_gamma); | ||
| 219 | + | ||
| 220 | + // Build pattern: 2 Add -> AddRmsNorm -> 2 DynamicQuant(with smooth) | ||
| 221 | + auto add1 = BuildAddTensor(graph_builder, x1_0, x1_1); | ||
| 222 | + auto add2 = BuildAddTensor(graph_builder, add1, x1_2); | ||
| 223 | + auto arnResult = BuildAddRmsNormNode(graph_builder, add2, x2, gamma); | ||
| 224 | + auto dq1 = BuildDynamicQuantNode(graph_builder, arnResult.y, smooth1); | ||
| 225 | + auto dq2 = BuildDynamicQuantNode(graph_builder, arnResult.y, smooth2); | ||
| 226 | + | ||
| 227 | + std::vector<es::EsTensorHolder> outputs; | ||
| 228 | + outputs.emplace_back(std::move(dq1.y)); | ||
| 229 | + outputs.emplace_back(std::move(dq2.y)); | ||
| 230 | + outputs.emplace_back(std::move(arnResult.x)); | ||
| 231 | + outputs.emplace_back(std::move(arnResult.y)); | ||
| 232 | + outputs.emplace_back(std::move(dq1.scale)); | ||
| 233 | + outputs.emplace_back(std::move(dq2.scale)); | ||
| 234 | + std::shared_ptr<Graph> graph = graph_builder.Build(outputs); | ||
| 235 | + CustomPassContext pass_context; | ||
| 236 | + | ||
| 237 | + ops::MultiAddRmsNormDynamicQuantFusionPass pass; | ||
| 238 | + Status status = pass.Run(graph, pass_context); | ||
| 239 | + ClearPlatform(); | ||
| 240 | + EXPECT_EQ(status, SUCCESS); | ||
| 241 | + EXPECT_TRUE(HasFusedOp(graph, "MultiAddRmsNormDynamicQuant")); | ||
| 242 | +} | ||
| 243 | + | ||
| 244 | +/** | ||
| 245 | + * Test dual_reshape: 2 Add + AddRmsNorm + Reshape + 2 DynamicQuant | ||
| 246 | + * Graph topology: | ||
| 247 | + * x1_0, x1_1 -> Add1 -> Add2(with x1_2) -> AddRmsNorm(with x2, gamma) -> [y, x_out] | ||
| 248 | + * y -> Reshape -> smooth_reshaped | ||
| 249 | + * y, smooth_reshaped -> DynamicQuant1 -> [y1, scale1] | ||
| 250 | + * y, smooth_reshaped -> DynamicQuant2 -> [y2, scale2] | ||
| 251 | + */ | ||
| 252 | +TEST_F(multi_add_rms_norm_dynamic_quant_fusion_test, multi_add_rms_norm_dynamic_quant_fusion_test_dual_reshape) | ||
| 253 | +{ | ||
| 254 | + SetUpPlatform(); | ||
| 255 | + | ||
| 256 | + std::vector<int64_t> dims_x{1, 1024, 8192}; | ||
| 257 | + std::vector<int64_t> dims_gamma{8192}; | ||
| 258 | + | ||
| 259 | + auto graph_builder = es::EsGraphBuilder("multi_add_rms_norm_dq_dual_reshape"); | ||
| 260 | + auto x1_0 = graph_builder.CreateInput(0, "x1_0", DT_FLOAT16, FORMAT_ND, dims_x); | ||
| 261 | + auto x1_1 = graph_builder.CreateInput(1, "x1_1", DT_FLOAT16, FORMAT_ND, dims_x); | ||
| 262 | + auto x1_2 = graph_builder.CreateInput(2, "x1_2", DT_FLOAT16, FORMAT_ND, dims_x); | ||
| 263 | + auto x2 = graph_builder.CreateInput(3, "x2", DT_FLOAT16, FORMAT_ND, dims_x); | ||
| 264 | + auto gamma = graph_builder.CreateInput(4, "gamma", DT_FLOAT16, FORMAT_ND, dims_gamma); | ||
| 265 | + | ||
| 266 | + // Build pattern: 2 Add -> AddRmsNorm -> Reshape -> 2 DynamicQuant | ||
| 267 | + auto add1 = BuildAddTensor(graph_builder, x1_0, x1_1); | ||
| 268 | + auto add2 = BuildAddTensor(graph_builder, add1, x1_2); | ||
| 269 | + auto arnResult = BuildAddRmsNormNode(graph_builder, add2, x2, gamma); | ||
| 270 | + auto smooth_reshaped = BuildReshapeNode(graph_builder, arnResult.y, BuildConstNode(graph_builder)); | ||
| 271 | + auto dq1 = BuildDynamicQuantNode(graph_builder, arnResult.y, smooth_reshaped); | ||
| 272 | + auto dq2 = BuildDynamicQuantNode(graph_builder, arnResult.y, smooth_reshaped); | ||
| 273 | + | ||
| 274 | + std::vector<es::EsTensorHolder> outputs; | ||
| 275 | + outputs.emplace_back(std::move(dq1.y)); | ||
| 276 | + outputs.emplace_back(std::move(dq2.y)); | ||
| 277 | + outputs.emplace_back(std::move(arnResult.x)); | ||
| 278 | + outputs.emplace_back(std::move(smooth_reshaped)); | ||
| 279 | + outputs.emplace_back(std::move(dq1.scale)); | ||
| 280 | + outputs.emplace_back(std::move(dq2.scale)); | ||
| 281 | + std::shared_ptr<Graph> graph = graph_builder.Build(outputs); | ||
| 282 | + CustomPassContext pass_context; | ||
| 283 | + | ||
| 284 | + ops::MultiAddRmsNormDynamicQuantFusionPass pass; | ||
| 285 | + Status status = pass.Run(graph, pass_context); | ||
| 286 | + ClearPlatform(); | ||
| 287 | + EXPECT_EQ(status, SUCCESS); | ||
| 288 | + EXPECT_TRUE(HasFusedOp(graph, "MultiAddRmsNormDynamicQuant")); | ||
| 289 | +} | ||
| 290 | + | ||
| 291 | +/** | ||
| 292 | + * Test sole: 2 Add + AddRmsNorm + 1 DynamicQuant (with smooth_scales) | ||
| 293 | + * Graph topology: | ||
| 294 | + * x1_0, x1_1 -> Add1 -> Add2(with x1_2) -> AddRmsNorm(with x2, gamma) -> [y, x_out] | ||
| 295 | + * y, smooth -> DynamicQuant -> [y1, scale1] | ||
| 296 | + */ | ||
| 297 | +TEST_F(multi_add_rms_norm_dynamic_quant_fusion_test, multi_add_rms_norm_dynamic_quant_fusion_test_sole) | ||
| 298 | +{ | ||
| 299 | + SetUpPlatform(); | ||
| 300 | + | ||
| 301 | + std::vector<int64_t> dims_x{1, 1024, 8192}; | ||
| 302 | + std::vector<int64_t> dims_gamma{8192}; | ||
| 303 | + | ||
| 304 | + auto graph_builder = es::EsGraphBuilder("multi_add_rms_norm_dq_sole"); | ||
| 305 | + auto x1_0 = graph_builder.CreateInput(0, "x1_0", DT_FLOAT16, FORMAT_ND, dims_x); | ||
| 306 | + auto x1_1 = graph_builder.CreateInput(1, "x1_1", DT_FLOAT16, FORMAT_ND, dims_x); | ||
| 307 | + auto x1_2 = graph_builder.CreateInput(2, "x1_2", DT_FLOAT16, FORMAT_ND, dims_x); | ||
| 308 | + auto x2 = graph_builder.CreateInput(3, "x2", DT_FLOAT16, FORMAT_ND, dims_x); | ||
| 309 | + auto gamma = graph_builder.CreateInput(4, "gamma", DT_FLOAT16, FORMAT_ND, dims_gamma); | ||
| 310 | + auto smooth = graph_builder.CreateInput(5, "smooth", DT_FLOAT16, FORMAT_ND, dims_gamma); | ||
| 311 | + | ||
| 312 | + // Build pattern: 2 Add -> AddRmsNorm -> 1 DynamicQuant(with smooth) | ||
| 313 | + auto add1 = BuildAddTensor(graph_builder, x1_0, x1_1); | ||
| 314 | + auto add2 = BuildAddTensor(graph_builder, add1, x1_2); | ||
| 315 | + auto arnResult = BuildAddRmsNormNode(graph_builder, add2, x2, gamma); | ||
| 316 | + auto dq1 = BuildDynamicQuantNode(graph_builder, arnResult.y, smooth); | ||
| 317 | + | ||
| 318 | + std::vector<es::EsTensorHolder> outputs; | ||
| 319 | + outputs.emplace_back(std::move(dq1.y)); | ||
| 320 | + outputs.emplace_back(std::move(arnResult.x)); | ||
| 321 | + outputs.emplace_back(std::move(arnResult.y)); | ||
| 322 | + outputs.emplace_back(std::move(dq1.scale)); | ||
| 323 | + std::shared_ptr<Graph> graph = graph_builder.Build(outputs); | ||
| 324 | + CustomPassContext pass_context; | ||
| 325 | + | ||
| 326 | + ops::MultiAddRmsNormDynamicQuantFusionPass pass; | ||
| 327 | + Status status = pass.Run(graph, pass_context); | ||
| 328 | + ClearPlatform(); | ||
| 329 | + EXPECT_EQ(status, SUCCESS); | ||
| 330 | + EXPECT_TRUE(HasFusedOp(graph, "MultiAddRmsNormDynamicQuant")); | ||
| 331 | +} | ||
| @@ -1,12 +1,14 @@ | |||
| 1 | # ---------------------------------------------------------------------------- | 1 | # ---------------------------------------------------------------------------- |
| 2 | # Copyright (c) 2025 Huawei Technologies Co., Ltd. | 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 | 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"). | 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. | 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, | 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. | 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. | 8 | # See LICENSE in the root of the software repository for the full text of the License. |
| 9 | # ---------------------------------------------------------------------------- | 9 | # ---------------------------------------------------------------------------- |
| 10 | 10 | ||
| 11 | message(STATUS "=== Debug:start ops.quant.dynamic_quant_update_scatter_v2.op_graph.CMakeLists.txt") | 11 | message(STATUS "=== Debug:start ops.quant.dynamic_quant_update_scatter_v2.op_graph.CMakeLists.txt") |
| 12 | -add_graph_plugin_sources() | 12 | +if(BUILD_OPEN_PROJECT) |
| 13 | + add_graph_plugin_sources() | ||
| 14 | +endif() | ||
The file is empty
| @@ -0,0 +1,562 @@ | |||
| 1 | +/** | ||
| 2 | + * Copyright (c) 2026 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 | + * \brief dynamic_quant_update_scatter_v2_fusion_pass.cpp | ||
| 13 | + * \details fusion pass | ||
| 14 | + * x x indices In0 In1 In2 | ||
| 15 | + * | | | | | | | ||
| 16 | + * Const0 DynamicQuantV2 | | | | | | ||
| 17 | + * \ /|\ | | | | | | ||
| 18 | + * Reshape0| \ ---> DynamicQuantUpdateScatterV2 | ||
| 19 | + * / | Neg indices | | | | ||
| 20 | + * Const1 Bitcast0| \ * /| | | | | ||
| 21 | + * \ / | * \ / | var var_scale var_offset | ||
| 22 | + * In0 Reshape1 *| In1 X | In2 | ||
| 23 | + * \ / * | | / \ | | | ||
| 24 | + * Const2 Scatter0 Scatter1 Scatter2 | ||
| 25 | + * \ | | | | ||
| 26 | + * Reshape2 | | | ||
| 27 | + * | | | | ||
| 28 | + * Const3 Bitcast1 Unsqueeze0 Unsqueeze1 | ||
| 29 | + * \ | | | | ||
| 30 | + * Reshape3 | | | ||
| 31 | + * | | | | ||
| 32 | + * var var_scale var_offset | ||
| 33 | + */ | ||
| 34 | + | ||
| 35 | +#include "dynamic_quant_update_scatter_v2_fusion_pass.h" | ||
| 36 | + | ||
| 37 | +#include <string> | ||
| 38 | + | ||
| 39 | +#include "es_nn_ops.h" | ||
| 40 | +#include "es_math_ops.h" | ||
| 41 | +#include "ge/ge_utils.h" | ||
| 42 | +#include "common/inc/error_util.h" | ||
| 43 | +#include "platform/platform_info.h" | ||
| 44 | +#include "compliant_node_builder.h" | ||
| 45 | + | ||
| 46 | +using namespace ge; | ||
| 47 | +using namespace fe; | ||
| 48 | +using namespace fusion; | ||
| 49 | + | ||
| 50 | +namespace ops { | ||
| 51 | + | ||
| 52 | +static constexpr uint32_t IDX_0 = 0; | ||
| 53 | +static constexpr uint32_t IDX_1 = 1; | ||
| 54 | +static constexpr uint32_t IDX_2 = 2; | ||
| 55 | +static constexpr uint32_t IDX_3 = 3; | ||
| 56 | +static constexpr uint32_t IDX_4 = 4; | ||
| 57 | +static constexpr uint32_t IDX_5 = 5; | ||
| 58 | +static constexpr uint32_t IDX_8 = 8; | ||
| 59 | +static constexpr int64_t FULL_LOAD_H_SIZE = 14960; | ||
| 60 | + | ||
| 61 | +static const std::string FUSED_OP_TYPE = "DynamicQuantUpdateScatterV2"; | ||
| 62 | +static const std::string PASS_NAME = "DynamicQuantUpdateScatterV2FusionPass"; | ||
| 63 | + | ||
| 64 | +using UniqueGraphPtr = std::unique_ptr<Graph>; | ||
| 65 | + | ||
| 66 | +static es::EsTensorHolder BuildPatternReshapeNode( | ||
| 67 | + es::EsGraphBuilder& builder, const es::EsTensorHolder& x, const es::EsTensorHolder& shape) | ||
| 68 | +{ | ||
| 69 | + static int counter = 0; | ||
| 70 | + auto graph = builder.GetCGraphBuilder()->GetGraph(); | ||
| 71 | + std::string name = "Reshape_" + std::to_string(counter++); | ||
| 72 | + GNode node = es::CompliantNodeBuilder(graph) | ||
| 73 | + .OpType("Reshape") | ||
| 74 | + .IrDefInputs({ | ||
| 75 | + {"x", es::CompliantNodeBuilder::kEsIrInputRequired, ""}, | ||
| 76 | + {"shape", es::CompliantNodeBuilder::kEsIrInputRequired, ""} | ||
| 77 | + }) | ||
| 78 | + .Name(name.c_str()) | ||
| 79 | + .IrDefOutputs({{"y", es::CompliantNodeBuilder::kEsIrOutputRequired, ""}}) | ||
| 80 | + .Build(); | ||
| 81 | + es::AddEdgeAndUpdatePeerDesc(*graph, *x.GetProducer(), x.GetProducerOutIndex(), node, 0); | ||
| 82 | + es::AddEdgeAndUpdatePeerDesc(*graph, *shape.GetProducer(), shape.GetProducerOutIndex(), node, 1); | ||
| 83 | + return es::EsTensorHolder(builder.GetCGraphBuilder()->GetTensorHolderFromNode(node, 0)); | ||
| 84 | +} | ||
| 85 | + | ||
| 86 | +static es::EsTensorHolder BuildPatternConstNode(es::EsGraphBuilder& builder) | ||
| 87 | +{ | ||
| 88 | + static int counter = 0; | ||
| 89 | + auto graph = builder.GetCGraphBuilder()->GetGraph(); | ||
| 90 | + std::string name = "Const_" + std::to_string(counter++); | ||
| 91 | + GNode node = es::CompliantNodeBuilder(graph) | ||
| 92 | + .OpType("Const") | ||
| 93 | + .Name(name.c_str()) | ||
| 94 | + .IrDefOutputs({{"y", es::CompliantNodeBuilder::kEsIrOutputRequired, ""}}) | ||
| 95 | + .Build(); | ||
| 96 | + return es::EsTensorHolder(builder.GetCGraphBuilder()->GetTensorHolderFromNode(node, 0)); | ||
| 97 | +} | ||
| 98 | + | ||
| 99 | +static es::EsTensorHolder BuildNegNode(es::EsGraphBuilder& builder, const es::EsTensorHolder& x) | ||
| 100 | +{ | ||
| @@ -0,0 +1,33 @@ | |||
| 1 | +/** | ||
| 2 | + * Copyright (c) 2026 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 dynamic_quant_update_scatter_v2_fusion_pass.h | ||
| 13 | + * \brief | ||
| 14 | + */ | ||
| 15 | +#ifndef OPS_BUILT_IN_FUSION_PASS_GRAPH_DYNAMIC_QUANT_SCATTER_V2_H | ||
| 16 | +#define OPS_BUILT_IN_FUSION_PASS_GRAPH_DYNAMIC_QUANT_SCATTER_V2_H | ||
| 17 | + | ||
| 18 | +#include "ge/fusion/pass/pattern_fusion_pass.h" | ||
| 19 | + | ||
| 20 | +namespace ops { | ||
| 21 | +using namespace ge; | ||
| 22 | +using namespace fusion; | ||
| 23 | + | ||
| 24 | +class __attribute__((visibility("default"))) DynamicQuantUpdateScatterV2FusionPass : public PatternFusionPass { | ||
| 25 | +protected: | ||
| 26 | + std::vector<PatternUniqPtr> Patterns() override; | ||
| 27 | + bool MeetRequirements(const std::unique_ptr<MatchResult>& match_result) override; | ||
| 28 | + std::unique_ptr<Graph> Replacement(const std::unique_ptr<MatchResult>& match_result) override; | ||
| 29 | +}; | ||
| 30 | + | ||
| 31 | +} // namespace ops | ||
| 32 | + | ||
| 33 | +#endif // OPS_BUILT_IN_FUSION_PASS_GRAPH_DYNAMIC_QUANT_SCATTER_V2_H | ||
| @@ -0,0 +1,18 @@ | |||
| 1 | +# ---------------------------------------------------------------------------- | ||
| 2 | +# This program is free software, you can redistribute it and/or modify. | ||
| 3 | +# Copyright (c) 2025 Huawei Technologies Co., Ltd. | ||
| 4 | +# This file is a part of the CANN Open Software. | ||
| 5 | +# Licensed under CANN Open Software License Agreement Version 2.0 (the "License"). | ||
| 6 | +# Please refer to the License for details. You may not use this file except in compliance with the License. | ||
| 7 | +# 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. | ||
| 8 | +# See LICENSE in the root of the software repository for the full text of the License. | ||
| 9 | +# ---------------------------------------------------------------------------- | ||
| 10 | + | ||
| 11 | +# 每个目录下需要生成的可执行文件,具体参考:ops/built-in/test/CMakeLists.txt: 50~124 | ||
| 12 | +file(GLOB CURRENT_DIRS RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/*) | ||
| 13 | +message(STATUS "=== Debug: CURRENT_DIRS =${CURRENT_DIRS} ") | ||
| 14 | +foreach(SUB_DIR ${CURRENT_DIRS}) | ||
| 15 | + if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/${SUB_DIR}/CMakeLists.txt") | ||
| 16 | + add_subdirectory(${SUB_DIR}) | ||
| 17 | + endif() | ||
| 18 | +endforeach() | ||
| @@ -0,0 +1,616 @@ | |||
| 1 | +/** | ||
| 2 | + * Copyright (c) 2026 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 | +#include "array_ops.h" | ||
| 12 | +#include "nn_quantize.h" | ||
| 13 | +#include "experiment_ops.h" | ||
| 14 | +#include "matrix_calculation_ops.h" | ||
| 15 | +#include "fusion_ops.h" | ||
| 16 | +#include "elewise_calculation_ops.h" | ||
| 17 | +#include "selection_ops.h" | ||
| 18 | +#include "fusion_pass_test_utils.h" | ||
| 19 | +#include "graph_dsl/graph_checker.h" | ||
| 20 | +#include "graph_dsl/graph_dsl.h" | ||
| 21 | +#include "graph/utils/graph_utils.h" | ||
| 22 | +#include "graph/utils/graph_utils_ex.h" | ||
| 23 | +#include "gtest/gtest.h" | ||
| 24 | +#include "graph_builder_utils.h" | ||
| 25 | +#include "platform_info_stub.h" | ||
| 26 | +#include "graph/compute_graph.h" | ||
| 27 | +#include "graph/graph.h" | ||
| 28 | +#include "graph/utils/op_desc_utils.h" | ||
| 29 | +#include "graph/operator.h" | ||
| 30 | +#include "util/util.h" | ||
| 31 | +#include "platform/platform_info.h" | ||
| 32 | +#include "common/configuration.h" | ||
| 33 | +#include "common/utils/ut_op_util.h" | ||
| 34 | +#include "graph/utils/attr_utils.h" | ||
| 35 | +#include "register/graph_optimizer/fusion_common/fusion_statistic_recorder.h" | ||
| 36 | +#include "es_nn_ops.h" | ||
| 37 | +#include "es_math_ops.h" | ||
| 38 | +#include "dynamic_quant_update_scatter_v2_fusion_pass.h" | ||
| 39 | +#include "compliant_node_builder.h" | ||
| 40 | + | ||
| 41 | +using namespace ge; | ||
| 42 | +using namespace op; | ||
| 43 | + | ||
| 44 | +static es::EsTensorHolder BuildConstNode(es::EsGraphBuilder& builder) | ||
| 45 | +{ | ||
| 46 | + static int counter = 0; | ||
| 47 | + std::string name = "Const_" + std::to_string(counter++); | ||
| 48 | + auto graph = builder.GetCGraphBuilder()->GetGraph(); | ||
| 49 | + GNode node = es::CompliantNodeBuilder(graph) | ||
| 50 | + .OpType("Const") | ||
| 51 | + .Name(name.c_str()) | ||
| 52 | + .IrDefOutputs({{"y", es::CompliantNodeBuilder::kEsIrOutputRequired, ""}}) | ||
| 53 | + .Build(); | ||
| 54 | + return es::EsTensorHolder(builder.GetCGraphBuilder()->GetTensorHolderFromNode(node, 0)); | ||
| 55 | +} | ||
| 56 | + | ||
| 57 | +static es::EsTensorHolder BuildReshapeNode( | ||
| 58 | + es::EsGraphBuilder& builder, const es::EsTensorHolder& x, const es::EsTensorHolder& shape) | ||
| 59 | +{ | ||
| 60 | + static int counter = 0; | ||
| 61 | + std::string name = "Reshape_" + std::to_string(counter++); | ||
| 62 | + auto graph = builder.GetCGraphBuilder()->GetGraph(); | ||
| 63 | + GNode node = es::CompliantNodeBuilder(graph) | ||
| 64 | + .OpType("Reshape") | ||
| 65 | + .Name(name.c_str()) | ||
| 66 | + .IrDefInputs({ | ||
| 67 | + {"x", es::CompliantNodeBuilder::kEsIrInputRequired, ""}, | ||
| 68 | + {"shape", es::CompliantNodeBuilder::kEsIrInputRequired, ""} | ||
| 69 | + }) | ||
| 70 | + .IrDefOutputs({{"y", es::CompliantNodeBuilder::kEsIrOutputRequired, ""}}) | ||
| 71 | + .Build(); | ||
| 72 | + es::AddEdgeAndUpdatePeerDesc(*graph, *x.GetProducer(), x.GetProducerOutIndex(), node, 0); | ||
| 73 | + es::AddEdgeAndUpdatePeerDesc(*graph, *shape.GetProducer(), shape.GetProducerOutIndex(), node, 1); | ||
| 74 | + return es::EsTensorHolder(builder.GetCGraphBuilder()->GetTensorHolderFromNode(node, 0)); | ||
| 75 | +} | ||
| 76 | + | ||
| 77 | +static es::EsTensorHolder BuildBitcastNode(es::EsGraphBuilder& builder, const es::EsTensorHolder& x, DataType dt) | ||
| 78 | +{ | ||
| 79 | + static int counter = 0; | ||
| 80 | + std::string name = "Bitcast_" + std::to_string(counter++); | ||
| 81 | + auto graph = builder.GetCGraphBuilder()->GetGraph(); | ||
| 82 | + GNode node = es::CompliantNodeBuilder(graph) | ||
| 83 | + .OpType("Bitcast") | ||
| 84 | + .Name(name.c_str()) | ||
| 85 | + .IrDefInputs({{"x", es::CompliantNodeBuilder::kEsIrInputRequired, ""}}) | ||
| 86 | + .IrDefOutputs({{"y", es::CompliantNodeBuilder::kEsIrOutputRequired, ""}}) | ||
| 87 | + .IrDefAttrs({ | ||
| 88 | + {"type", es::CompliantNodeBuilder::kEsAttrRequired, "Int", | ||
| 89 | + es::CreateFrom(static_cast<int64_t>(dt))} | ||
| 90 | + }) | ||
| 91 | + .Build(); | ||
| 92 | + es::AddEdgeAndUpdatePeerDesc(*graph, *x.GetProducer(), x.GetProducerOutIndex(), node, 0); | ||
| 93 | + return es::EsTensorHolder(builder.GetCGraphBuilder()->GetTensorHolderFromNode(node, 0)); | ||
| 94 | +} | ||
| 95 | + | ||
| 96 | +static es::EsTensorHolder BuildNegNode(es::EsGraphBuilder& builder, const es::EsTensorHolder& x) | ||
| 97 | +{ | ||
| 98 | + static int counter = 0; | ||
| 99 | + std::string name = "Neg_" + std::to_string(counter++); | ||
| 100 | + auto graph = builder.GetCGraphBuilder()->GetGraph(); | ||