已合并
fusion pass兼容性问题修复 #3908
pengyiming7创建于 7月8日
fusion pass兼容性问题修复 #3908
已合并
共 3 个文件变更+161-105
| @@ -39,6 +39,7 @@ namespace ops { | |||
| 39 | // D1 scenario: uses kCompatibleInherited stage (9.0.0+). | 39 | // D1 scenario: uses kCompatibleInherited stage (9.0.0+). |
| 40 | // Strategy: compile-time macro guard + runtime version check + overall silence. | 40 | // Strategy: compile-time macro guard + runtime version check + overall silence. |
| 41 | 41 | ||
| 42 | + | ||
| 42 | 43 | ||
| 43 | 44 | ||
| 44 | // Weak declare aclsysGetVersionNum to avoid hard link dependency on libascendcl. | 45 | // Weak declare aclsysGetVersionNum to avoid hard link dependency on libascendcl. |
| @@ -197,11 +198,28 @@ static es::EsTensorHolder BuildTransposeNode(es::EsGraphBuilder& replaceGraphBui | |||
| 197 | return es::EsTensorHolder(output); | 198 | return es::EsTensorHolder(output); |
| 198 | } | 199 | } |
| 199 | 200 | ||
| 201 | +static bool IsTargetVersion() | ||
| 202 | +{ | ||
| 203 | + int32_t version = 0; | ||
| 204 | + char pkgName[] = "ge_compiler"; | ||
| 205 | + if (aclsysGetVersionNum) { | ||
| 206 | + aclsysGetVersionNum(pkgName, &version); | ||
| 207 | + } | ||
| 208 | + if (version >= GE_COMPILER_VERSION_910) { | ||
| 209 | + return true; | ||
| 210 | + } | ||
| 211 | + return false; | ||
| 212 | +} | ||
| 213 | + | ||
| 200 | std::vector<PatternUniqPtr> PermuteFusionPass::Patterns() | 214 | std::vector<PatternUniqPtr> PermuteFusionPass::Patterns() |
| 201 | { | 215 | { |
| 202 | OP_LOGD(kFusionPassName.c_str(), "Enter Patterns for PermuteFusionPass."); | 216 | OP_LOGD(kFusionPassName.c_str(), "Enter Patterns for PermuteFusionPass."); |
| 203 | std::vector<PatternUniqPtr> patternGraphs; | 217 | std::vector<PatternUniqPtr> patternGraphs; |
| 204 | 218 | ||
| 219 | + if (!IsTargetVersion()) { | ||
| 220 | + return patternGraphs; | ||
| 221 | + } | ||
| 222 | + | ||
| 205 | auto graphBuilder = es::EsGraphBuilder("PermuteFusionPass"); | 223 | auto graphBuilder = es::EsGraphBuilder("PermuteFusionPass"); |
| 206 | 224 | ||
| 207 | // Create input node | 225 | // Create input node |
| @@ -238,8 +256,9 @@ bool PermuteFusionPass::MeetRequirements(const std::unique_ptr<MatchResult>& mat | |||
| 238 | 256 | ||
| 239 | // Runtime version check: on GE 8.5.0, return false to no-op. | 257 | // Runtime version check: on GE 8.5.0, return false to no-op. |
| 240 | int32_t version = 0; | 258 | int32_t version = 0; |
| 259 | + char pkgName[] = "ge_compiler"; | ||
| 241 | if (aclsysGetVersionNum) { | 260 | if (aclsysGetVersionNum) { |
| 242 | - aclsysGetVersionNum(const_cast<char*>("ge_compiler"), &version); | 261 | + aclsysGetVersionNum(pkgName, &version); |
| 243 | } | 262 | } |
| 244 | if (version < GE_COMPILER_VERSION_900) { | 263 | if (version < GE_COMPILER_VERSION_900) { |
| 245 | OP_LOGD(kFusionPassName.c_str(), "GE runtime version %d < 90000000, skip pass.", version); | 264 | OP_LOGD(kFusionPassName.c_str(), "GE runtime version %d < 90000000, skip pass.", version); |
| @@ -25,13 +25,13 @@ namespace ops { | |||
| 25 | // D1 scenario: uses kCompatibleInherited stage (9.0.0+). | 25 | // D1 scenario: uses kCompatibleInherited stage (9.0.0+). |
| 26 | // Strategy: compile-time macro guard + runtime version check + overall silence. | 26 | // Strategy: compile-time macro guard + runtime version check + overall silence. |
| 27 | 27 | ||
| 28 | + | ||
| 28 | 29 | ||
| 29 | 30 | ||
| 30 | // Weak declare aclsysGetVersionNum to avoid hard link dependency on libascendcl. | 31 | // Weak declare aclsysGetVersionNum to avoid hard link dependency on libascendcl. |
| 31 | // At runtime: if GE >= 9.0.0, symbol resolves normally; if GE 8.5.0, pointer is NULL. | 32 | // At runtime: if GE >= 9.0.0, symbol resolves normally; if GE 8.5.0, pointer is NULL. |
| 32 | extern "C" { | 33 | extern "C" { |
| 33 | -__attribute__((weak)) | 34 | +__attribute__((weak)) int32_t aclsysGetVersionNum(char* pkgName, int32_t* versionNum); |
| 34 | -int32_t aclsysGetVersionNum(char* pkgName, int32_t* versionNum); | ||
| 35 | } | 35 | } |
| 36 | 36 | ||
| 37 | const std::string FUSION_PASS_NAME = "GlobalavgpoolPass"; | 37 | const std::string FUSION_PASS_NAME = "GlobalavgpoolPass"; |
| @@ -53,13 +53,12 @@ CustomPassStage GetGlobalavgpoolPassStage() | |||
| 53 | if (version >= GE_COMPILER_VERSION_900) { | 53 | if (version >= GE_COMPILER_VERSION_900) { |
| 54 | return CustomPassStage::kCompatibleInherited; | 54 | return CustomPassStage::kCompatibleInherited; |
| 55 | } | 55 | } |
| 56 | - return CustomPassStage::kBeforeInferShape; // fallback to old stage for 8.5.0 | 56 | + return CustomPassStage::kBeforeInferShape; // fallback to old stage for 8.5.0 |
| 57 | } | 57 | } |
| 58 | -} // anonymous namespace | 58 | +} // anonymous namespace |
| 59 | 59 | ||
| 60 | -static void GetInputsInfo( | 60 | +static void GetInputsInfo(const std::vector<SubgraphInput>& subGraphInputs, std::vector<Shape>& inputShapes, |
| 61 | - const std::vector<SubgraphInput>& subGraphInputs, std::vector<Shape>& inputShapes, | 61 | + std::vector<DataType>& inputDtypes, std::vector<Format>& inputFormats) |
| 62 | - std::vector<DataType>& inputDtypes, std::vector<Format>& inputFormats) | ||
| 63 | { | 62 | { |
| 64 | for (const auto& subGraphInput : subGraphInputs) { | 63 | for (const auto& subGraphInput : subGraphInputs) { |
| 65 | auto matchNode = subGraphInput.GetAllInputs().at(0); | 64 | auto matchNode = subGraphInput.GetAllInputs().at(0); |
| @@ -72,12 +71,13 @@ static void GetInputsInfo( | |||
| 72 | // 如果失败,尝试获取输出描述 | 71 | // 如果失败,尝试获取输出描述 |
| 73 | status = matchNode.node.GetOutputDesc(matchNode.index, tensorDesc); | 72 | status = matchNode.node.GetOutputDesc(matchNode.index, tensorDesc); |
| 74 | if (status != GRAPH_SUCCESS) { | 73 | if (status != GRAPH_SUCCESS) { |
| 75 | - OP_LOGE("GlobalavgpoolPass", "Failed to get output desc from GlobalAveragePool node, status: %u", status); | 74 | + OP_LOGE("GlobalavgpoolPass", "Failed to get output desc from GlobalAveragePool node, status: %u", |
| 75 | + status); | ||
| 76 | // 使用默认值 | 76 | // 使用默认值 |
| 77 | tensorDesc.SetDataType(DT_FLOAT); | 77 | tensorDesc.SetDataType(DT_FLOAT); |
| 78 | tensorDesc.SetFormat(FORMAT_ND); | 78 | tensorDesc.SetFormat(FORMAT_ND); |
| 79 | // 使用合理的默认形状 | 79 | // 使用合理的默认形状 |
| 80 | - Shape defaultShape({1, 1, 1}); // 3D默认形状 | 80 | + Shape defaultShape({1, 1, 1}); // 3D默认形状 |
| 81 | tensorDesc.SetShape(defaultShape); | 81 | tensorDesc.SetShape(defaultShape); |
| 82 | } | 82 | } |
| 83 | } | 83 | } |
| @@ -96,7 +96,8 @@ static Status InferShape(const GraphUniqPtr& replaceGraph, const std::vector<Sub | |||
| 96 | // matchNode.node是GlobalAveragePool节点,matchNode.index是输出索引(0) | 96 | // matchNode.node是GlobalAveragePool节点,matchNode.index是输出索引(0) |
| 97 | // 我们需要获取GlobalAveragePool的输入描述(索引0) | 97 | // 我们需要获取GlobalAveragePool的输入描述(索引0) |
| 98 | if (matchNode.node.GetInputDesc(0, tensorDesc) != GRAPH_SUCCESS) { | 98 | if (matchNode.node.GetInputDesc(0, tensorDesc) != GRAPH_SUCCESS) { |
| 99 | - OP_LOGE_WITHOUT_REPORT("GlobalavgpoolPass", "Failed to get input desc from GlobalAveragePool node in InferShape"); | 99 | + OP_LOGE_WITHOUT_REPORT("GlobalavgpoolPass", |
| 100 | + "Failed to get input desc from GlobalAveragePool node in InferShape"); | ||
| 100 | // 如果失败,尝试获取输出描述 | 101 | // 如果失败,尝试获取输出描述 |
| 101 | matchNode.node.GetOutputDesc(matchNode.index, tensorDesc); | 102 | matchNode.node.GetOutputDesc(matchNode.index, tensorDesc); |
| 102 | } | 103 | } |
| @@ -105,35 +106,52 @@ static Status InferShape(const GraphUniqPtr& replaceGraph, const std::vector<Sub | |||
| 105 | return GeUtils::InferShape(*replaceGraph, inputShapes); | 106 | return GeUtils::InferShape(*replaceGraph, inputShapes); |
| 106 | } | 107 | } |
| 107 | 108 | ||
| 109 | +static bool IsTargetVersion() | ||
| 110 | +{ | ||
| 111 | + int32_t version = 0; | ||
| 112 | + char pkgName[] = "ge_compiler"; | ||
| 113 | + if (aclsysGetVersionNum) { | ||
| 114 | + aclsysGetVersionNum(pkgName, &version); | ||
| 115 | + } | ||
| 116 | + if (version >= GE_COMPILER_VERSION_910) { | ||
| 117 | + return true; | ||
| 118 | + } | ||
| 119 | + return false; | ||
| 120 | +} | ||
| 121 | + | ||
| 108 | std::vector<PatternUniqPtr> GlobalavgpoolPass::Patterns() | 122 | std::vector<PatternUniqPtr> GlobalavgpoolPass::Patterns() |
| 109 | { | 123 | { |
| 110 | OP_LOGD(FUSION_PASS_NAME.c_str(), "Enter Patterns for GlobalavgpoolPass"); | 124 | OP_LOGD(FUSION_PASS_NAME.c_str(), "Enter Patterns for GlobalavgpoolPass"); |
| 111 | std::vector<PatternUniqPtr> patternGraphs; | 125 | std::vector<PatternUniqPtr> patternGraphs; |
| 126 | + if (!IsTargetVersion()) { | ||
| 127 | + return patternGraphs; | ||
| 128 | + } | ||
| 112 | auto graphBuilder = es::EsGraphBuilder(FUSION_PASS_NAME.c_str()); | 129 | auto graphBuilder = es::EsGraphBuilder(FUSION_PASS_NAME.c_str()); |
| 113 | 130 | ||
| 114 | // 创建输入 | 131 | // 创建输入 |
| 115 | auto x = graphBuilder.CreateInput(0); | 132 | auto x = graphBuilder.CreateInput(0); |
| 116 | OP_LOGD(FUSION_PASS_NAME.c_str(), "Created input node"); | 133 | OP_LOGD(FUSION_PASS_NAME.c_str(), "Created input node"); |
| 117 | - | 134 | + |
| 118 | // 构建 GlobalAveragePool 节点 | 135 | // 构建 GlobalAveragePool 节点 |
| 119 | // 注意:我们需要获取Graph对象来构建CompliantNode | 136 | // 注意:我们需要获取Graph对象来构建CompliantNode |
| 120 | auto* graph = graphBuilder.GetCGraphBuilder()->GetGraph(); | 137 | auto* graph = graphBuilder.GetCGraphBuilder()->GetGraph(); |
| 121 | OP_LOGD(FUSION_PASS_NAME.c_str(), "Got graph pointer: %p", graph); | 138 | OP_LOGD(FUSION_PASS_NAME.c_str(), "Got graph pointer: %p", graph); |
| 122 | auto globalAvgPool = es::CompliantNodeBuilder(graph) | 139 | auto globalAvgPool = es::CompliantNodeBuilder(graph) |
| 123 | - .OpType("GlobalAveragePool") | 140 | + .OpType("GlobalAveragePool") |
| 124 | - .Name("global_avg_pool") | 141 | + .Name("global_avg_pool") |
| 125 | - .IrDefInputs({{"x", es::CompliantNodeBuilder::kEsIrInputRequired, ""}}) | 142 | + .IrDefInputs({{"x", es::CompliantNodeBuilder::kEsIrInputRequired, ""}}) |
| 126 | - .IrDefOutputs({{"y", es::CompliantNodeBuilder::kEsIrOutputRequired, ""}}) | 143 | + .IrDefOutputs({{"y", es::CompliantNodeBuilder::kEsIrOutputRequired, ""}}) |
| 127 | - .Build(); | 144 | + .Build(); |
| 128 | OP_LOGD(FUSION_PASS_NAME.c_str(), "Built GlobalAveragePool node"); | 145 | OP_LOGD(FUSION_PASS_NAME.c_str(), "Built GlobalAveragePool node"); |
| 129 | - | 146 | + |
| 130 | // 连接输入 - 使用正确的Graph参数 | 147 | // 连接输入 - 使用正确的Graph参数 |
| 131 | - if (es::AddEdgeAndUpdatePeerDesc(*graph, *x.GetProducer(), x.GetProducerOutIndex(), globalAvgPool, 0) != GRAPH_SUCCESS) { | 148 | + if (es::AddEdgeAndUpdatePeerDesc(*graph, *x.GetProducer(), x.GetProducerOutIndex(), globalAvgPool, 0) != |
| 149 | + GRAPH_SUCCESS) { | ||
| 132 | OP_LOGE_WITHOUT_REPORT(FUSION_PASS_NAME.c_str(), "Failed to add edge in pattern"); | 150 | OP_LOGE_WITHOUT_REPORT(FUSION_PASS_NAME.c_str(), "Failed to add edge in pattern"); |
| 133 | return patternGraphs; | 151 | return patternGraphs; |
| 134 | } | 152 | } |
| 135 | OP_LOGD(FUSION_PASS_NAME.c_str(), "Added edge successfully"); | 153 | OP_LOGD(FUSION_PASS_NAME.c_str(), "Added edge successfully"); |
| 136 | - | 154 | + |
| 137 | // 获取输出并构建图 | 155 | // 获取输出并构建图 |
| 138 | // 注意:GetTensorHolderFromNode需要EsCGraphBuilder和节点 | 156 | // 注意:GetTensorHolderFromNode需要EsCGraphBuilder和节点 |
| 139 | auto y = graphBuilder.GetCGraphBuilder()->GetTensorHolderFromNode(globalAvgPool, 0); | 157 | auto y = graphBuilder.GetCGraphBuilder()->GetTensorHolderFromNode(globalAvgPool, 0); |
| @@ -148,7 +166,7 @@ std::vector<PatternUniqPtr> GlobalavgpoolPass::Patterns() | |||
| 148 | NodeIo nodeIo = {y->GetProducer(), 0}; | 166 | NodeIo nodeIo = {y->GetProducer(), 0}; |
| 149 | pattern->CaptureTensor(nodeIo); | 167 | pattern->CaptureTensor(nodeIo); |
| 150 | OP_LOGD(FUSION_PASS_NAME.c_str(), "Pattern created and tensor captured"); | 168 | OP_LOGD(FUSION_PASS_NAME.c_str(), "Pattern created and tensor captured"); |
| 151 | - | 169 | + |
| 152 | patternGraphs.emplace_back(std::move(pattern)); | 170 | patternGraphs.emplace_back(std::move(pattern)); |
| 153 | return patternGraphs; | 171 | return patternGraphs; |
| 154 | } | 172 | } |
| @@ -156,11 +174,12 @@ std::vector<PatternUniqPtr> GlobalavgpoolPass::Patterns() | |||
| 156 | bool GlobalavgpoolPass::MeetRequirements(const std::unique_ptr<MatchResult>& match_result) | 174 | bool GlobalavgpoolPass::MeetRequirements(const std::unique_ptr<MatchResult>& match_result) |
| 157 | { | 175 | { |
| 158 | OP_LOGD(FUSION_PASS_NAME.c_str(), "=== Enter MeetRequirements for GlobalavgpoolPass ==="); | 176 | OP_LOGD(FUSION_PASS_NAME.c_str(), "=== Enter MeetRequirements for GlobalavgpoolPass ==="); |
| 159 | - | 177 | + |
| 160 | // Runtime version check: on GE 8.5.0, return false to no-op. | 178 | // Runtime version check: on GE 8.5.0, return false to no-op. |
| 161 | int32_t version = 0; | 179 | int32_t version = 0; |
| 180 | + char pkgName[] = "ge_compiler"; | ||
| 162 | if (aclsysGetVersionNum) { | 181 | if (aclsysGetVersionNum) { |
| 163 | - aclsysGetVersionNum(const_cast<char*>("ge_compiler"), &version); | 182 | + aclsysGetVersionNum(pkgName, &version); |
| 164 | } | 183 | } |
| 165 | if (version < GE_COMPILER_VERSION_900) { | 184 | if (version < GE_COMPILER_VERSION_900) { |
| 166 | OP_LOGD(FUSION_PASS_NAME.c_str(), "GE runtime version %d < 90000000, skip pass.", version); | 185 | OP_LOGD(FUSION_PASS_NAME.c_str(), "GE runtime version %d < 90000000, skip pass.", version); |
| @@ -175,7 +194,7 @@ bool GlobalavgpoolPass::MeetRequirements(const std::unique_ptr<MatchResult>& mat | |||
| 175 | OP_LOGE_WITHOUT_REPORT(FUSION_PASS_NAME.c_str(), "Failed to GetCaptrue tensor"); | 194 | OP_LOGE_WITHOUT_REPORT(FUSION_PASS_NAME.c_str(), "Failed to GetCaptrue tensor"); |
| 176 | return false; | 195 | return false; |
| 177 | } | 196 | } |
| 178 | - | 197 | + |
| 179 | auto node = matchedNode.node; | 198 | auto node = matchedNode.node; |
| 180 | AscendString nodeType; | 199 | AscendString nodeType; |
| 181 | node.GetType(nodeType); | 200 | node.GetType(nodeType); |
| @@ -221,7 +240,8 @@ GraphUniqPtr GlobalavgpoolPass::Replacement(const std::unique_ptr<MatchResult>& | |||
| 221 | auto replaceGraphBuilder = es::EsGraphBuilder("replacement"); | 240 | auto replaceGraphBuilder = es::EsGraphBuilder("replacement"); |
| 222 | 241 | ||
| 223 | // 创建输入节点 - 使用带有数据类型和形状的重载版本 | 242 | // 创建输入节点 - 使用带有数据类型和形状的重载版本 |
| 224 | - auto reduceMeanInput = replaceGraphBuilder.CreateInput(0, "x", inputDtypes[0], inputFormats[0], inputShapes[0].GetDims()); | 243 | + auto reduceMeanInput = replaceGraphBuilder.CreateInput(0, "x", inputDtypes[0], inputFormats[0], |
| 244 | + inputShapes[0].GetDims()); | ||
| 225 | 245 | ||
| 226 | // 根据输入维度计算axes | 246 | // 根据输入维度计算axes |
| 227 | int64_t inputDim = inputShapes[0].GetDims().size(); | 247 | int64_t inputDim = inputShapes[0].GetDims().size(); |
| @@ -244,28 +264,32 @@ GraphUniqPtr GlobalavgpoolPass::Replacement(const std::unique_ptr<MatchResult>& | |||
| 244 | // 使用CompliantNodeBuilder创建ReduceMean节点 | 264 | // 使用CompliantNodeBuilder创建ReduceMean节点 |
| 245 | auto* graph = replaceGraphBuilder.GetCGraphBuilder()->GetGraph(); | 265 | auto* graph = replaceGraphBuilder.GetCGraphBuilder()->GetGraph(); |
| 246 | auto reduceMeanNode = es::CompliantNodeBuilder(graph) | 266 | auto reduceMeanNode = es::CompliantNodeBuilder(graph) |
| 247 | - .OpType("ReduceMean") | 267 | + .OpType("ReduceMean") |
| 248 | - .Name("reduce_mean") | 268 | + .Name("reduce_mean") |
| 249 | - .IrDefInputs({ | 269 | + .IrDefInputs({ |
| 250 | - {"x", es::CompliantNodeBuilder::kEsIrInputRequired, ""}, | 270 | + {"x", es::CompliantNodeBuilder::kEsIrInputRequired, ""}, |
| 251 | - {"axes", es::CompliantNodeBuilder::kEsIrInputRequired, ""}, | 271 | + {"axes", es::CompliantNodeBuilder::kEsIrInputRequired, ""}, |
| 252 | - }) | 272 | + }) |
| 253 | - .IrDefOutputs({ | 273 | + .IrDefOutputs({ |
| 254 | - {"y", es::CompliantNodeBuilder::kEsIrOutputRequired, ""}, | 274 | + {"y", es::CompliantNodeBuilder::kEsIrOutputRequired, ""}, |
| 255 | - }) | 275 | + }) |
| 256 | - .IrDefAttrs({ | 276 | + .IrDefAttrs({ |
| 257 | - {"keep_dims", es::CompliantNodeBuilder::kEsAttrRequired, "Bool", es::CreateFrom(true)}, | 277 | + {"keep_dims", es::CompliantNodeBuilder::kEsAttrRequired, "Bool", |
| 258 | - {"noop_with_empty_axes", es::CompliantNodeBuilder::kEsAttrRequired, "Bool", es::CreateFrom(true)}, | 278 | + es::CreateFrom(true)}, |
| 259 | - }) | 279 | + {"noop_with_empty_axes", es::CompliantNodeBuilder::kEsAttrRequired, "Bool", |
| 260 | - .Build(); | 280 | + es::CreateFrom(true)}, |
| 281 | + }) | ||
| 282 | + .Build(); | ||
| 261 | // 连接输入 | 283 | // 连接输入 |
| 262 | - if (es::AddEdgeAndUpdatePeerDesc(*graph, *reduceMeanInput.GetProducer(), reduceMeanInput.GetProducerOutIndex(), reduceMeanNode, 0) != GRAPH_SUCCESS) { | 284 | + if (es::AddEdgeAndUpdatePeerDesc(*graph, *reduceMeanInput.GetProducer(), reduceMeanInput.GetProducerOutIndex(), |
| 285 | + reduceMeanNode, 0) != GRAPH_SUCCESS) { | ||
| 263 | OP_LOGE_WITHOUT_REPORT(FUSION_PASS_NAME.c_str(), "Failed to add edge for reduceMean input"); | 286 | OP_LOGE_WITHOUT_REPORT(FUSION_PASS_NAME.c_str(), "Failed to add edge for reduceMean input"); |
| 264 | return nullptr; | 287 | return nullptr; |
| 265 | } | 288 | } |
| 266 | 289 | ||
| 267 | // 连接axes常量节点 | 290 | // 连接axes常量节点 |
| 268 | - if (es::AddEdgeAndUpdatePeerDesc(*graph, *axesConst.GetProducer(), axesConst.GetProducerOutIndex(), reduceMeanNode, 1) != GRAPH_SUCCESS) { | 291 | + if (es::AddEdgeAndUpdatePeerDesc(*graph, *axesConst.GetProducer(), axesConst.GetProducerOutIndex(), reduceMeanNode, |
| 292 | + 1) != GRAPH_SUCCESS) { | ||
| 269 | OP_LOGE_WITHOUT_REPORT(FUSION_PASS_NAME.c_str(), "Failed to add edge for axes constant"); | 293 | OP_LOGE_WITHOUT_REPORT(FUSION_PASS_NAME.c_str(), "Failed to add edge for axes constant"); |
| 270 | return nullptr; | 294 | return nullptr; |
| 271 | } | 295 | } |
| @@ -288,6 +312,6 @@ GraphUniqPtr GlobalavgpoolPass::Replacement(const std::unique_ptr<MatchResult>& | |||
| 288 | 312 | ||
| 289 | REG_FUSION_PASS(GlobalavgpoolPass).Stage(GetGlobalavgpoolPassStage()); | 313 | REG_FUSION_PASS(GlobalavgpoolPass).Stage(GetGlobalavgpoolPassStage()); |
| 290 | 314 | ||
| 291 | -#endif // GE_COMPILER_VERSION_NUM >= GE_COMPILER_VERSION_900 | 315 | +#endif // GE_COMPILER_VERSION_NUM >= GE_COMPILER_VERSION_900 |
| 292 | 316 | ||
| 293 | -} // namespace ops | 317 | +} // namespace ops |
| @@ -27,13 +27,13 @@ namespace ops { | |||
| 27 | // D1 scenario: uses kCompatibleInherited stage (9.0.0+). | 27 | // D1 scenario: uses kCompatibleInherited stage (9.0.0+). |
| 28 | // Strategy: compile-time macro guard + runtime version check + overall silence. | 28 | // Strategy: compile-time macro guard + runtime version check + overall silence. |
| 29 | 29 | ||
| 30 | + | ||
| 30 | 31 | ||
| 31 | 32 | ||
| 32 | // Weak declare aclsysGetVersionNum to avoid hard link dependency on libascendcl. | 33 | // Weak declare aclsysGetVersionNum to avoid hard link dependency on libascendcl. |
| 33 | // At runtime: if GE >= 9.0.0, symbol resolves normally; if GE 8.5.0, pointer is NULL. | 34 | // At runtime: if GE >= 9.0.0, symbol resolves normally; if GE 8.5.0, pointer is NULL. |
| 34 | extern "C" { | 35 | extern "C" { |
| 35 | -__attribute__((weak)) | 36 | +__attribute__((weak)) int32_t aclsysGetVersionNum(char* pkgName, int32_t* versionNum); |
| 36 | -int32_t aclsysGetVersionNum(char* pkgName, int32_t* versionNum); | ||
| 37 | } | 37 | } |
| 38 | 38 | ||
| 39 | const std::string kPassName = "ReduceMeanWithCastFusionPass"; | 39 | const std::string kPassName = "ReduceMeanWithCastFusionPass"; |
| @@ -50,13 +50,12 @@ CustomPassStage GetReduceMeanWithCastPassStage() | |||
| 50 | if (version >= GE_COMPILER_VERSION_900) { | 50 | if (version >= GE_COMPILER_VERSION_900) { |
| 51 | return CustomPassStage::kCompatibleInherited; | 51 | return CustomPassStage::kCompatibleInherited; |
| 52 | } | 52 | } |
| 53 | - return CustomPassStage::kBeforeInferShape; // fallback to old stage for 8.5.0 | 53 | + return CustomPassStage::kBeforeInferShape; // fallback to old stage for 8.5.0 |
| 54 | } | 54 | } |
| 55 | -} // anonymous namespace | 55 | +} // anonymous namespace |
| 56 | 56 | ||
| 57 | -static void GetInputsInfo( | 57 | +static void GetInputsInfo(const std::vector<SubgraphInput>& subgraphInputs, std::vector<Shape>& inputShapes, |
| 58 | - const std::vector<SubgraphInput>& subgraphInputs, std::vector<Shape>& inputShapes, | 58 | + std::vector<DataType>& inputDtypes, std::vector<Format>& inputFormats) |
| 59 | - std::vector<DataType>& inputDtypes, std::vector<Format>& inputFormats) | ||
| 60 | { | 59 | { |
| 61 | for (const auto& subgraphInput : subgraphInputs) { | 60 | for (const auto& subgraphInput : subgraphInputs) { |
| 62 | auto matchNode = subgraphInput.GetAllInputs().at(0); | 61 | auto matchNode = subgraphInput.GetAllInputs().at(0); |
| @@ -68,8 +67,7 @@ static void GetInputsInfo( | |||
| 68 | } | 67 | } |
| 69 | } | 68 | } |
| 70 | 69 | ||
| 71 | -static Status InferShape(const GraphUniqPtr& replaceGraph, | 70 | +static Status InferShape(const GraphUniqPtr& replaceGraph, const std::vector<SubgraphInput>& subgraphInputs) |
| 72 | - const std::vector<SubgraphInput>& subgraphInputs) | ||
| 73 | { | 71 | { |
| 74 | OP_LOGD(kPassName.c_str(), "Begin InferShape for replacement."); | 72 | OP_LOGD(kPassName.c_str(), "Begin InferShape for replacement."); |
| 75 | std::vector<Shape> inputShapes; | 73 | std::vector<Shape> inputShapes; |
| @@ -82,11 +80,28 @@ static Status InferShape(const GraphUniqPtr& replaceGraph, | |||
| 82 | return GeUtils::InferShape(*replaceGraph, inputShapes); | 80 | return GeUtils::InferShape(*replaceGraph, inputShapes); |
| 83 | } | 81 | } |
| 84 | 82 | ||
| 83 | +static bool IsTargetVersion() | ||
| 84 | +{ | ||
| 85 | + int32_t version = 0; | ||
| 86 | + char pkgName[] = "ge_compiler"; | ||
| 87 | + if (aclsysGetVersionNum) { | ||
| 88 | + aclsysGetVersionNum(pkgName, &version); | ||
| 89 | + } | ||
| 90 | + if (version >= GE_COMPILER_VERSION_910) { | ||
| 91 | + return true; | ||
| 92 | + } | ||
| 93 | + return false; | ||
| 94 | +} | ||
| 95 | + | ||
| 85 | std::vector<PatternUniqPtr> ReduceMeanWithCastFusionPass::Patterns() | 96 | std::vector<PatternUniqPtr> ReduceMeanWithCastFusionPass::Patterns() |
| 86 | { | 97 | { |
| 87 | OP_LOGD(kPassName.c_str(), "Enter Patterns for ReduceMeanWithCastFusionPass"); | 98 | OP_LOGD(kPassName.c_str(), "Enter Patterns for ReduceMeanWithCastFusionPass"); |
| 88 | std::vector<PatternUniqPtr> patternGraphs; | 99 | std::vector<PatternUniqPtr> patternGraphs; |
| 89 | 100 | ||
| 101 | + if (!IsTargetVersion()) { | ||
| 102 | + return patternGraphs; | ||
| 103 | + } | ||
| 104 | + | ||
| 90 | auto graphBuilder = es::EsGraphBuilder(kPassName.c_str()); | 105 | auto graphBuilder = es::EsGraphBuilder(kPassName.c_str()); |
| 91 | 106 | ||
| 92 | // Create input x (index 0) | 107 | // Create input x (index 0) |
| @@ -97,24 +112,24 @@ std::vector<PatternUniqPtr> ReduceMeanWithCastFusionPass::Patterns() | |||
| 97 | // Build ReduceMeanWithCast node using CompliantNodeBuilder (no ES API available) | 112 | // Build ReduceMeanWithCast node using CompliantNodeBuilder (no ES API available) |
| 98 | auto* graph = graphBuilder.GetCGraphBuilder()->GetGraph(); | 113 | auto* graph = graphBuilder.GetCGraphBuilder()->GetGraph(); |
| 99 | auto reduceMeanWithCast = es::CompliantNodeBuilder(graph) | 114 | auto reduceMeanWithCast = es::CompliantNodeBuilder(graph) |
| 100 | - .OpType("ReduceMeanWithCast") | 115 | + .OpType("ReduceMeanWithCast") |
| 101 | - .Name("reduce_mean_with_cast") | 116 | + .Name("reduce_mean_with_cast") |
| 102 | - .IrDefInputs({ | 117 | + .IrDefInputs({ |
| 103 | - {"x", es::CompliantNodeBuilder::kEsIrInputRequired, ""}, | 118 | + {"x", es::CompliantNodeBuilder::kEsIrInputRequired, ""}, |
| 104 | - {"axes", es::CompliantNodeBuilder::kEsIrInputRequired, ""}, | 119 | + {"axes", es::CompliantNodeBuilder::kEsIrInputRequired, ""}, |
| 105 | - }) | 120 | + }) |
| 106 | - .IrDefOutputs({{"y", es::CompliantNodeBuilder::kEsIrOutputRequired, ""}}) | 121 | + .IrDefOutputs({{"y", es::CompliantNodeBuilder::kEsIrOutputRequired, ""}}) |
| 107 | - .Build(); | 122 | + .Build(); |
| 108 | // Connect x to ReduceMeanWithCast input 0 | 123 | // Connect x to ReduceMeanWithCast input 0 |
| 109 | - if (es::AddEdgeAndUpdatePeerDesc(*graph, *x.GetProducer(), x.GetProducerOutIndex(), | 124 | + if (es::AddEdgeAndUpdatePeerDesc(*graph, *x.GetProducer(), x.GetProducerOutIndex(), reduceMeanWithCast, 0) != |
| 110 | - reduceMeanWithCast, 0) != GRAPH_SUCCESS) { | 125 | + GRAPH_SUCCESS) { |
| 111 | OP_LOGE_WITHOUT_REPORT(kPassName.c_str(), "Failed to add edge for x input in pattern"); | 126 | OP_LOGE_WITHOUT_REPORT(kPassName.c_str(), "Failed to add edge for x input in pattern"); |
| 112 | return patternGraphs; | 127 | return patternGraphs; |
| 113 | } | 128 | } |
| 114 | 129 | ||
| 115 | // Connect axes to ReduceMeanWithCast input 1 | 130 | // Connect axes to ReduceMeanWithCast input 1 |
| 116 | - if (es::AddEdgeAndUpdatePeerDesc(*graph, *axes.GetProducer(), axes.GetProducerOutIndex(), | 131 | + if (es::AddEdgeAndUpdatePeerDesc(*graph, *axes.GetProducer(), axes.GetProducerOutIndex(), reduceMeanWithCast, 1) != |
| 117 | - reduceMeanWithCast, 1) != GRAPH_SUCCESS) { | 132 | + GRAPH_SUCCESS) { |
| 118 | OP_LOGE_WITHOUT_REPORT(kPassName.c_str(), "Failed to add edge for axes input in pattern"); | 133 | OP_LOGE_WITHOUT_REPORT(kPassName.c_str(), "Failed to add edge for axes input in pattern"); |
| 119 | return patternGraphs; | 134 | return patternGraphs; |
| 120 | } | 135 | } |
| @@ -143,8 +158,9 @@ bool ReduceMeanWithCastFusionPass::MeetRequirements(const std::unique_ptr<MatchR | |||
| 143 | 158 | ||
| 144 | // Runtime version check: on GE 8.5.0, return false to no-op. | 159 | // Runtime version check: on GE 8.5.0, return false to no-op. |
| 145 | int32_t version = 0; | 160 | int32_t version = 0; |
| 161 | + char pkgName[] = "ge_compiler"; | ||
| 146 | if (aclsysGetVersionNum) { | 162 | if (aclsysGetVersionNum) { |
| 147 | - aclsysGetVersionNum(const_cast<char*>("ge_compiler"), &version); | 163 | + aclsysGetVersionNum(pkgName, &version); |
| 148 | } | 164 | } |
| 149 | if (version < GE_COMPILER_VERSION_900) { | 165 | if (version < GE_COMPILER_VERSION_900) { |
| 150 | OP_LOGD(kPassName.c_str(), "GE runtime version %d < 90000000, skip pass.", version); | 166 | OP_LOGD(kPassName.c_str(), "GE runtime version %d < 90000000, skip pass.", version); |
| @@ -200,18 +216,16 @@ GraphUniqPtr ReduceMeanWithCastFusionPass::Replacement(const std::unique_ptr<Mat | |||
| 200 | } | 216 | } |
| 201 | 217 | ||
| 202 | OP_LOGD(kPassName.c_str(), "hasDtype=%d, dataType=%d, keep_dims=%d, noop_with_empty_axes=%d", | 218 | OP_LOGD(kPassName.c_str(), "hasDtype=%d, dataType=%d, keep_dims=%d, noop_with_empty_axes=%d", |
| 203 | - static_cast<int>(hasDtype), static_cast<int>(dataType), | 219 | + static_cast<int>(hasDtype), static_cast<int>(dataType), static_cast<int>(keepDims), |
| 204 | - static_cast<int>(keepDims), static_cast<int>(noopWithEmptyAxes)); | 220 | + static_cast<int>(noopWithEmptyAxes)); |
| 205 | 221 | ||
| 206 | // Build replacement graph | 222 | // Build replacement graph |
| 207 | auto replaceBuilder = es::EsGraphBuilder("replacement"); | 223 | auto replaceBuilder = es::EsGraphBuilder("replacement"); |
| 208 | 224 | ||
| 209 | // Create input x | 225 | // Create input x |
| 210 | - auto rX = replaceBuilder.CreateInput(0, "x", inputDtypes[0], inputFormats[0], | 226 | + auto rX = replaceBuilder.CreateInput(0, "x", inputDtypes[0], inputFormats[0], inputShapes[0].GetDims()); |
| 211 | - inputShapes[0].GetDims()); | ||
| 212 | // Create input axes | 227 | // Create input axes |
| 213 | - auto rAxes = replaceBuilder.CreateInput(1, "axes", inputDtypes[1], inputFormats[1], | 228 | + auto rAxes = replaceBuilder.CreateInput(1, "axes", inputDtypes[1], inputFormats[1], inputShapes[1].GetDims()); |
| 214 | - inputShapes[1].GetDims()); | ||
| 215 | 229 | ||
| 216 | auto* graph = replaceBuilder.GetCGraphBuilder()->GetGraph(); | 230 | auto* graph = replaceBuilder.GetCGraphBuilder()->GetGraph(); |
| 217 | 231 | ||
| @@ -223,18 +237,18 @@ GraphUniqPtr ReduceMeanWithCastFusionPass::Replacement(const std::unique_ptr<Mat | |||
| 223 | if (hasDtype) { | 237 | if (hasDtype) { |
| 224 | // Build Cast node | 238 | // Build Cast node |
| 225 | auto castNode = es::CompliantNodeBuilder(graph) | 239 | auto castNode = es::CompliantNodeBuilder(graph) |
| 226 | - .OpType("Cast") | 240 | + .OpType("Cast") |
| 227 | - .Name("cast_node") | 241 | + .Name("cast_node") |
| 228 | - .IrDefInputs({{"x", es::CompliantNodeBuilder::kEsIrInputRequired, ""}}) | 242 | + .IrDefInputs({{"x", es::CompliantNodeBuilder::kEsIrInputRequired, ""}}) |
| 229 | - .IrDefOutputs({{"y", es::CompliantNodeBuilder::kEsIrOutputRequired, ""}}) | 243 | + .IrDefOutputs({{"y", es::CompliantNodeBuilder::kEsIrOutputRequired, ""}}) |
| 230 | - .IrDefAttrs({ | 244 | + .IrDefAttrs({ |
| 231 | - {"dst_type", es::CompliantNodeBuilder::kEsAttrRequired, "Int", | 245 | + {"dst_type", es::CompliantNodeBuilder::kEsAttrRequired, "Int", |
| 232 | - es::CreateFrom(static_cast<int64_t>(dataType))}, | 246 | + es::CreateFrom(static_cast<int64_t>(dataType))}, |
| 233 | - }) | 247 | + }) |
| 234 | - .Build(); | 248 | + .Build(); |
| 235 | // Connect x to Cast input 0 | 249 | // Connect x to Cast input 0 |
| 236 | - if (es::AddEdgeAndUpdatePeerDesc(*graph, *rX.GetProducer(), rX.GetProducerOutIndex(), | 250 | + if (es::AddEdgeAndUpdatePeerDesc(*graph, *rX.GetProducer(), rX.GetProducerOutIndex(), castNode, 0) != |
| 237 | - castNode, 0) != GRAPH_SUCCESS) { | 251 | + GRAPH_SUCCESS) { |
| 238 | OP_LOGE_WITHOUT_REPORT(kPassName.c_str(), "Failed to add edge for Cast input"); | 252 | OP_LOGE_WITHOUT_REPORT(kPassName.c_str(), "Failed to add edge for Cast input"); |
| 239 | return nullptr; | 253 | return nullptr; |
| 240 | } | 254 | } |
| @@ -242,47 +256,46 @@ GraphUniqPtr ReduceMeanWithCastFusionPass::Replacement(const std::unique_ptr<Mat | |||
| 242 | reduceMeanInputNode = castNode; | 256 | reduceMeanInputNode = castNode; |
| 243 | reduceMeanInputIdx = 0; | 257 | reduceMeanInputIdx = 0; |
| 244 | useCast = true; | 258 | useCast = true; |
| 245 | - OP_LOGD(kPassName.c_str(), "Cast node built and connected, dst_type=%d", | 259 | + OP_LOGD(kPassName.c_str(), "Cast node built and connected, dst_type=%d", static_cast<int>(dataType)); |
| 246 | - static_cast<int>(dataType)); | ||
| 247 | } | 260 | } |
| 248 | 261 | ||
| 249 | // Build ReduceMean node | 262 | // Build ReduceMean node |
| 250 | auto reduceMeanNode = es::CompliantNodeBuilder(graph) | 263 | auto reduceMeanNode = es::CompliantNodeBuilder(graph) |
| 251 | - .OpType("ReduceMean") | 264 | + .OpType("ReduceMean") |
| 252 | - .Name("reduce_mean") | 265 | + .Name("reduce_mean") |
| 253 | - .IrDefInputs({ | 266 | + .IrDefInputs({ |
| 254 | - {"x", es::CompliantNodeBuilder::kEsIrInputRequired, ""}, | 267 | + {"x", es::CompliantNodeBuilder::kEsIrInputRequired, ""}, |
| 255 | - {"axes", es::CompliantNodeBuilder::kEsIrInputRequired, ""}, | 268 | + {"axes", es::CompliantNodeBuilder::kEsIrInputRequired, ""}, |
| 256 | - }) | 269 | + }) |
| 257 | - .IrDefOutputs({{"y", es::CompliantNodeBuilder::kEsIrOutputRequired, ""}}) | 270 | + .IrDefOutputs({{"y", es::CompliantNodeBuilder::kEsIrOutputRequired, ""}}) |
| 258 | - .IrDefAttrs({ | 271 | + .IrDefAttrs({ |
| 259 | - {"keep_dims", es::CompliantNodeBuilder::kEsAttrRequired, "Bool", | 272 | + {"keep_dims", es::CompliantNodeBuilder::kEsAttrRequired, "Bool", |
| 260 | - es::CreateFrom(keepDims)}, | 273 | + es::CreateFrom(keepDims)}, |
| 261 | - {"noop_with_empty_axes", es::CompliantNodeBuilder::kEsAttrRequired, "Bool", | 274 | + {"noop_with_empty_axes", es::CompliantNodeBuilder::kEsAttrRequired, "Bool", |
| 262 | - es::CreateFrom(noopWithEmptyAxes)}, | 275 | + es::CreateFrom(noopWithEmptyAxes)}, |
| 263 | - }) | 276 | + }) |
| 264 | - .Build(); | 277 | + .Build(); |
| 265 | 278 | ||
| 266 | // Connect data input to ReduceMean | 279 | // Connect data input to ReduceMean |
| 267 | if (useCast) { | 280 | if (useCast) { |
| 268 | // Connect Cast output to ReduceMean input 0 | 281 | // Connect Cast output to ReduceMean input 0 |
| 269 | - if (es::AddEdgeAndUpdatePeerDesc(*graph, reduceMeanInputNode, reduceMeanInputIdx, | 282 | + if (es::AddEdgeAndUpdatePeerDesc(*graph, reduceMeanInputNode, reduceMeanInputIdx, reduceMeanNode, 0) != |
| 270 | - reduceMeanNode, 0) != GRAPH_SUCCESS) { | 283 | + GRAPH_SUCCESS) { |
| 271 | OP_LOGE_WITHOUT_REPORT(kPassName.c_str(), "Failed to add edge for Cast->ReduceMean"); | 284 | OP_LOGE_WITHOUT_REPORT(kPassName.c_str(), "Failed to add edge for Cast->ReduceMean"); |
| 272 | return nullptr; | 285 | return nullptr; |
| 273 | } | 286 | } |
| 274 | } else { | 287 | } else { |
| 275 | // Connect x directly to ReduceMean input 0 | 288 | // Connect x directly to ReduceMean input 0 |
| 276 | - if (es::AddEdgeAndUpdatePeerDesc(*graph, *rX.GetProducer(), rX.GetProducerOutIndex(), | 289 | + if (es::AddEdgeAndUpdatePeerDesc(*graph, *rX.GetProducer(), rX.GetProducerOutIndex(), reduceMeanNode, 0) != |
| 277 | - reduceMeanNode, 0) != GRAPH_SUCCESS) { | 290 | + GRAPH_SUCCESS) { |
| 278 | OP_LOGE_WITHOUT_REPORT(kPassName.c_str(), "Failed to add edge for x->ReduceMean"); | 291 | OP_LOGE_WITHOUT_REPORT(kPassName.c_str(), "Failed to add edge for x->ReduceMean"); |
| 279 | return nullptr; | 292 | return nullptr; |
| 280 | } | 293 | } |
| 281 | } | 294 | } |
| 282 | 295 | ||
| 283 | // Connect axes to ReduceMean input 1 | 296 | // Connect axes to ReduceMean input 1 |
| 284 | - if (es::AddEdgeAndUpdatePeerDesc(*graph, *rAxes.GetProducer(), rAxes.GetProducerOutIndex(), | 297 | + if (es::AddEdgeAndUpdatePeerDesc(*graph, *rAxes.GetProducer(), rAxes.GetProducerOutIndex(), reduceMeanNode, 1) != |
| 285 | - reduceMeanNode, 1) != GRAPH_SUCCESS) { | 298 | + GRAPH_SUCCESS) { |
| 286 | OP_LOGE_WITHOUT_REPORT(kPassName.c_str(), "Failed to add edge for axes->ReduceMean"); | 299 | OP_LOGE_WITHOUT_REPORT(kPassName.c_str(), "Failed to add edge for axes->ReduceMean"); |
| 287 | return nullptr; | 300 | return nullptr; |
| 288 | } | 301 | } |
| @@ -307,6 +320,6 @@ GraphUniqPtr ReduceMeanWithCastFusionPass::Replacement(const std::unique_ptr<Mat | |||
| 307 | 320 | ||
| 308 | REG_FUSION_PASS(ReduceMeanWithCastFusionPass).Stage(GetReduceMeanWithCastPassStage()); | 321 | REG_FUSION_PASS(ReduceMeanWithCastFusionPass).Stage(GetReduceMeanWithCastPassStage()); |
| 309 | 322 | ||
| 310 | -#endif // GE_COMPILER_VERSION_NUM >= GE_COMPILER_VERSION_900 | 323 | +#endif // GE_COMPILER_VERSION_NUM >= GE_COMPILER_VERSION_900 |
| 311 | 324 | ||
| 312 | } // namespace ops | 325 | } // namespace ops |