已合并
fix: restore reshape axis padding before autofuse can-fuse #4309
ling-DT创建于 8月8日
fix: restore reshape axis padding before autofuse can-fuse #4309
已合并
共 22 个文件变更+2307-66
| @@ -86,6 +86,17 @@ Status CacheGraphAfterMerge(const NodePtr &new_node, const NodePtr &node1, const | |||
| 86 | return SUCCESS; | 86 | return SUCCESS; |
| 87 | } | 87 | } |
| 88 | 88 | ||
| 89 | +bool CompleteReshapeAxesForBackendCanFuse(const NodePtr &node1, const NodePtr &node2, const NodeFuseInfo &fuse_info) { | ||
| 90 | + // Backend can-fuse checks rely on complete axis semantics. Complete axes recorded by no-op reshape lowering here | ||
| 91 | + // so graph/node/tensor attrs are in the same axis space before evaluating fusion legality. | ||
| 92 | + if (BackendUtils::CompleteReshapeAxesForBackendCanFuse(node1, node2, fuse_info) == SUCCESS) { | ||
| 93 | + return true; | ||
| 94 | + } | ||
| 95 | + GELOGI("node1 %s(%s) and node2 %s(%s) cannot fuse, complete reshape axes before backend can-fuse failed.", | ||
| 96 | + node1->GetNamePtr(), node1->GetType().c_str(), node2->GetNamePtr(), node2->GetType().c_str()); | ||
| 97 | + return false; | ||
| 98 | +} | ||
| 99 | + | ||
| 89 | bool AscBackendSubGraphFusionDecider::CanFuse(const NodePtr &node1, const NodePtr &node2) const { | 100 | bool AscBackendSubGraphFusionDecider::CanFuse(const NodePtr &node1, const NodePtr &node2) const { |
| 90 | uint32_t max_fusion_node_input_size = AutoFuseConfig::Config().GetFusionStrategySolver().max_input_nums_after_fuse; | 101 | uint32_t max_fusion_node_input_size = AutoFuseConfig::Config().GetFusionStrategySolver().max_input_nums_after_fuse; |
| 91 | if (!BackendUtils::CanFuseByStrategy(node1, node2, max_fusion_node_input_size)) { | 102 | if (!BackendUtils::CanFuseByStrategy(node1, node2, max_fusion_node_input_size)) { |
| @@ -156,6 +167,7 @@ NodePtr AscBackendSubGraphFusionDecider::Fuse(const NodePtr &node1, const NodePt | |||
| 156 | node2->GetType().c_str()); | 167 | node2->GetType().c_str()); |
| 157 | // 子图融合流程异常时dump图的缓存融合前dump图流程 | 168 | // 子图融合流程异常时dump图的缓存融合前dump图流程 |
| 158 | GE_ASSERT_SUCCESS(CacheGraphBeforeSubGraphMerge(node1, node2, origin_graph)); | 169 | GE_ASSERT_SUCCESS(CacheGraphBeforeSubGraphMerge(node1, node2, origin_graph)); |
| 170 | + GE_ASSERT_TRUE(CompleteReshapeAxesForBackendCanFuse(node1, node2, node_fuse_info)); | ||
| 159 | 171 | ||
| 160 | GE_ASSERT_SUCCESS(BackendUtils::UpdateSubgraphOutputAttr(graph1, node1)); | 172 | GE_ASSERT_SUCCESS(BackendUtils::UpdateSubgraphOutputAttr(graph1, node1)); |
| 161 | GE_ASSERT_SUCCESS(BackendUtils::UpdateSubgraphOutputAttr(graph2, node2)); | 173 | GE_ASSERT_SUCCESS(BackendUtils::UpdateSubgraphOutputAttr(graph2, node2)); |
| @@ -413,6 +425,8 @@ Status AscBackendFusionDecider::UpdateNewNodeAttr(const OpDescPtr op, const Node | |||
| 413 | GetInterAttrs(attr).fuse_type = fuse_type; | 425 | GetInterAttrs(attr).fuse_type = fuse_type; |
| 414 | BackendUtils::SetReduceOriginalAxisInfo(GetInterAttrs(attr), GetInterAttrs(autofuse_attr1), | 426 | BackendUtils::SetReduceOriginalAxisInfo(GetInterAttrs(attr), GetInterAttrs(autofuse_attr1), |
| 415 | GetInterAttrs(autofuse_attr2)); | 427 | GetInterAttrs(autofuse_attr2)); |
| 428 | + BackendUtils::SetReshapeAxisChangeInfo(GetInterAttrs(attr), GetInterAttrs(autofuse_attr1), | ||
| 429 | + GetInterAttrs(autofuse_attr2)); | ||
| 416 | 430 | ||
| 417 | // 处理is_reduce_all_load属性:按照优先级设置融合后的值 | 431 | // 处理is_reduce_all_load属性:按照优先级设置融合后的值 |
| 418 | // 优先级1:存在REDUCE_ALL_LOAD_NOT_ALL,则设置为REDUCE_ALL_LOAD_NOT_ALL | 432 | // 优先级1:存在REDUCE_ALL_LOAD_NOT_ALL,则设置为REDUCE_ALL_LOAD_NOT_ALL |
| @@ -936,6 +950,7 @@ NodePtr AscBackendFusionDecider::Fuse(const NodePtr &node1, const NodePtr &node2 | |||
| 936 | node2->GetType().c_str()); | 950 | node2->GetType().c_str()); |
| 937 | // 异常时dump图的缓存融合前dump图流程 | 951 | // 异常时dump图的缓存融合前dump图流程 |
| 938 | GE_ASSERT_SUCCESS(CacheGraphBeforeMerge(node1, node2)); | 952 | GE_ASSERT_SUCCESS(CacheGraphBeforeMerge(node1, node2)); |
| 953 | + GE_ASSERT_TRUE(CompleteReshapeAxesForBackendCanFuse(node1, node2, node_fuse_info)); | ||
| 939 | 954 | ||
| 940 | GE_ASSERT_SUCCESS(BackendUtils::UpdateSubgraphOutputAttr(graph1, node1)); | 955 | GE_ASSERT_SUCCESS(BackendUtils::UpdateSubgraphOutputAttr(graph1, node1)); |
| 941 | GE_ASSERT_SUCCESS(BackendUtils::UpdateSubgraphOutputAttr(graph2, node2)); | 956 | GE_ASSERT_SUCCESS(BackendUtils::UpdateSubgraphOutputAttr(graph2, node2)); |
| @@ -842,6 +842,8 @@ Status AscGraphAxisMapping::FlushAscSubGraphAxisInfo(const NodePtr &node, const | |||
| 842 | } | 842 | } |
| 843 | GE_ASSERT_SUCCESS(BackendUtils::FlushReduceOriginalAxisIfIsReduceNode(node, asc_node, axis_before_Flush, | 843 | GE_ASSERT_SUCCESS(BackendUtils::FlushReduceOriginalAxisIfIsReduceNode(node, asc_node, axis_before_Flush, |
| 844 | output_desc_tensor_attr->axis)); | 844 | output_desc_tensor_attr->axis)); |
| 845 | + GE_ASSERT_SUCCESS( | ||
| 846 | + BackendUtils::FlushReshapeAxisChanges(node, asc_node, axis_before_Flush, output_desc_tensor_attr->axis)); | ||
| 845 | } | 847 | } |
| 846 | } | 848 | } |
| 847 | auto graph_attr = graph->GetAttrsGroup<AscGraphAttr>(); | 849 | auto graph_attr = graph->GetAttrsGroup<AscGraphAttr>(); |
| @@ -310,7 +310,6 @@ class AscGraphAxisMapping { | |||
| 310 | return open_log_; | 310 | return open_log_; |
| 311 | } | 311 | } |
| 312 | 312 | ||
| 313 | - private: | ||
| 314 | /** | 313 | /** |
| 315 | * 该函数用于获取指定节点的前置节点的属性信息,包括维度、轴和大小。。 | 314 | * 该函数用于获取指定节点的前置节点的属性信息,包括维度、轴和大小。。 |
| 316 | * | 315 | * |
| @@ -336,6 +335,7 @@ class AscGraphAxisMapping { | |||
| 336 | Status GetCurNodeAttrs(const NodePtr &node, const int32_t index, std::vector<int64_t> &axis, | 335 | Status GetCurNodeAttrs(const NodePtr &node, const int32_t index, std::vector<int64_t> &axis, |
| 337 | std::vector<ge::Expression> &repeats) const; | 336 | std::vector<ge::Expression> &repeats) const; |
| 338 | 337 | ||
| 338 | + private: | ||
| 339 | /** | 339 | /** |
| 340 | * 该函数用于找到节点(node_repeats)在基准信息(base_repeats)中的索引。 | 340 | * 该函数用于找到节点(node_repeats)在基准信息(base_repeats)中的索引。 |
| 341 | * 它会遍历node_repeats中的每个元素,并在base_repeats中查找匹配的元素,记录其索引。 | 341 | * 它会遍历node_repeats中的每个元素,并在base_repeats中查找匹配的元素,记录其索引。 |
| @@ -28,6 +28,7 @@ | |||
| 28 | 28 | ||
| 29 | 29 | ||
| 30 | 30 | ||
| 31 | + | ||
| 31 | 32 | ||
| 32 | 33 | ||
| 33 | 34 | ||
| @@ -2745,6 +2746,11 @@ Status BackendUtils::UpdateTransposeBeforeMerge(const NodePtr &node2, const Comp | |||
| 2745 | return SUCCESS; | 2746 | return SUCCESS; |
| 2746 | } | 2747 | } |
| 2747 | 2748 | ||
| 2749 | +Status BackendUtils::CompleteReshapeAxesForBackendCanFuse(const NodePtr &node1, const NodePtr &node2, | ||
| 2750 | + const NodeFuseInfo &fuse_info) { | ||
| 2751 | + return asc_adapt::CompletePairReshapeAxes(node1, node2, fuse_info); | ||
| 2752 | +} | ||
| 2753 | + | ||
| 2748 | Status CompleteNodeAttrsBeforeMerge(const NodePtr &node1, const NodePtr &node2) { | 2754 | Status CompleteNodeAttrsBeforeMerge(const NodePtr &node1, const NodePtr &node2) { |
| 2749 | auto asc_graph1 = BackendUtils::GetNodeFusedAscGraph(node1); | 2755 | auto asc_graph1 = BackendUtils::GetNodeFusedAscGraph(node1); |
| 2750 | GE_ASSERT_NOTNULL(asc_graph1); | 2756 | GE_ASSERT_NOTNULL(asc_graph1); |
| @@ -3291,7 +3297,10 @@ bool BackendUtils::IsOnlyPointwise(const NodePtr &node) { | |||
| 3291 | 3297 | ||
| 3292 | void BackendUtils::SetReduceOriginalAxisInfo(AutofuseInnerAttrs &attr_new, const AutofuseInnerAttrs &attr1, | 3298 | void BackendUtils::SetReduceOriginalAxisInfo(AutofuseInnerAttrs &attr_new, const AutofuseInnerAttrs &attr1, |
| 3293 | const AutofuseInnerAttrs &attr2) { | 3299 | const AutofuseInnerAttrs &attr2) { |
| 3294 | - // 目前业界暂不支持融合reduce和reduce,即融合的两个节点只有一个是reduce,后期如果要融合两个reduce则需要根据reduce节点名字保存对应的原始轴信息 | 3300 | + attr_new.reduce_original_axis_infos = attr1.reduce_original_axis_infos; |
| 3301 | + attr_new.reduce_original_axis_infos.insert(attr2.reduce_original_axis_infos.begin(), | ||
| 3302 | + attr2.reduce_original_axis_infos.end()); | ||
| 3303 | + | ||
| 3295 | if (!attr1.reduce_original_axis.empty()) { | 3304 | if (!attr1.reduce_original_axis.empty()) { |
| 3296 | attr_new.reduce_original_axis = attr1.reduce_original_axis; | 3305 | attr_new.reduce_original_axis = attr1.reduce_original_axis; |
| 3297 | } else { | 3306 | } else { |
| @@ -3304,6 +3313,11 @@ void BackendUtils::SetReduceOriginalAxisInfo(AutofuseInnerAttrs &attr_new, const | |||
| 3304 | } | 3313 | } |
| 3305 | } | 3314 | } |
| 3306 | 3315 | ||
| 3316 | +void BackendUtils::SetReshapeAxisChangeInfo(AutofuseInnerAttrs &attr_new, const AutofuseInnerAttrs &attr1, | ||
| 3317 | + const AutofuseInnerAttrs &attr2) { | ||
| 3318 | + asc_adapt::InheritReshapeAxisChanges(attr_new, attr1, attr2); | ||
| 3319 | +} | ||
| 3320 | + | ||
| 3307 | // 融合存在轴映射之后index对应的axis变化的场景,则记录的reduce的原始axis也要相应变化 | 3321 | // 融合存在轴映射之后index对应的axis变化的场景,则记录的reduce的原始axis也要相应变化 |
| 3308 | Status BackendUtils::FlushReduceOriginalAxisIfIsReduceNode(const NodePtr &node, const NodePtr &asc_node, | 3322 | Status BackendUtils::FlushReduceOriginalAxisIfIsReduceNode(const NodePtr &node, const NodePtr &asc_node, |
| 3309 | const std::vector<int64_t> axis_before_Flush, | 3323 | const std::vector<int64_t> axis_before_Flush, |
| @@ -3329,7 +3343,7 @@ Status BackendUtils::FlushReduceOriginalAxisIfIsReduceNode(const NodePtr &node, | |||
| 3329 | auto autofuse_attr = BackendUtils::GetNodeAutoFuseAttr(node); | 3343 | auto autofuse_attr = BackendUtils::GetNodeAutoFuseAttr(node); |
| 3330 | GE_ASSERT_NOTNULL(autofuse_attr); | 3344 | GE_ASSERT_NOTNULL(autofuse_attr); |
| 3331 | 3345 | ||
| 3332 | - auto reduce_original_axis = autofuse_attr->GetReduceOriginalAxis(); | 3346 | + auto reduce_original_axis = autofuse_attr->GetReduceOriginalAxis(asc_node->GetName()); |
| 3333 | if (reduce_original_axis.empty()) { | 3347 | if (reduce_original_axis.empty()) { |
| 3334 | return SUCCESS; | 3348 | return SUCCESS; |
| 3335 | } | 3349 | } |
| @@ -3353,13 +3367,20 @@ Status BackendUtils::FlushReduceOriginalAxisIfIsReduceNode(const NodePtr &node, | |||
| 3353 | } | 3367 | } |
| 3354 | } | 3368 | } |
| 3355 | 3369 | ||
| 3356 | - autofuse_attr->SetReduceOriginalAxis(updated_axis); | 3370 | + autofuse_attr->SetReduceOriginalAxis(asc_node->GetName(), updated_axis); |
| 3357 | GELOGD("Flush reduce original axis for asc_node %s, before: %s, after: %s", asc_node->GetName().c_str(), | 3371 | GELOGD("Flush reduce original axis for asc_node %s, before: %s, after: %s", asc_node->GetName().c_str(), |
| 3358 | AutofuseUtils::VectorToStr(reduce_original_axis).c_str(), AutofuseUtils::VectorToStr(updated_axis).c_str()); | 3372 | AutofuseUtils::VectorToStr(reduce_original_axis).c_str(), AutofuseUtils::VectorToStr(updated_axis).c_str()); |
| 3359 | 3373 | ||
| 3360 | return SUCCESS; | 3374 | return SUCCESS; |
| 3361 | } | 3375 | } |
| 3362 | 3376 | ||
| 3377 | +// Keep AutoFuseAttrs reshape axis metadata in the current AscGraph axis space after axis mapping flush. | ||
| 3378 | +Status BackendUtils::FlushReshapeAxisChanges(const NodePtr &node, const NodePtr &asc_node, | ||
| 3379 | + const std::vector<int64_t> axis_before_Flush, | ||
| 3380 | + const std::vector<int64_t> axis_after_Flush) { | ||
| 3381 | + return asc_adapt::FlushReshapeAxisChanges(node, asc_node, axis_before_Flush, axis_after_Flush); | ||
| 3382 | +} | ||
| 3383 | + | ||
| 3363 | Status GetNodeTransposeInfo(const NodePtr &node, const TensorAttrInfo &temp_graph_attr, | 3384 | Status GetNodeTransposeInfo(const NodePtr &node, const TensorAttrInfo &temp_graph_attr, |
| 3364 | std::vector<std::pair<int64_t, int64_t>> &transpose_info) { | 3385 | std::vector<std::pair<int64_t, int64_t>> &transpose_info) { |
| 3365 | const auto cur_op_desc = node->GetOpDesc(); | 3386 | const auto cur_op_desc = node->GetOpDesc(); |
| @@ -670,6 +670,8 @@ class BackendUtils { | |||
| 670 | static Status ApplySwaps(TensorAttrInfo &temp_data_attr, const std::vector<std::pair<int64_t, int64_t>> &swaps); | 670 | static Status ApplySwaps(TensorAttrInfo &temp_data_attr, const std::vector<std::pair<int64_t, int64_t>> &swaps); |
| 671 | static Status PostProBackSteppingViewOp(AscGraph &asc_graph, const NodePtr &cur_node, ViewOpAttrInfo &attr_info, | 671 | static Status PostProBackSteppingViewOp(AscGraph &asc_graph, const NodePtr &cur_node, ViewOpAttrInfo &attr_info, |
| 672 | bool is_back_broadcast); | 672 | bool is_back_broadcast); |
| 673 | + static Status CompleteReshapeAxesForBackendCanFuse(const NodePtr &node1, const NodePtr &node2, | ||
| 674 | + const NodeFuseInfo &fuse_info); | ||
| 673 | static Status TuningSubgraphBeforeMerge(const NodePtr &node1, const NodePtr &node2, const ComputeGraphPtr &graph1, | 675 | static Status TuningSubgraphBeforeMerge(const NodePtr &node1, const NodePtr &node2, const ComputeGraphPtr &graph1, |
| 674 | const ComputeGraphPtr &graph2, const NodeFuseInfo &fuse_info); | 676 | const ComputeGraphPtr &graph2, const NodeFuseInfo &fuse_info); |
| 675 | static Status GetPreNodeAndAnchor(const NodePtr &node, const int32_t index, NodePtr &peer_node, | 677 | static Status GetPreNodeAndAnchor(const NodePtr &node, const int32_t index, NodePtr &peer_node, |
| @@ -850,9 +852,16 @@ class BackendUtils { | |||
| 850 | static bool OnlyHasTypesInAscgraph(const NodePtr &node, const std::vector<std::string> &target_types); | 852 | static bool OnlyHasTypesInAscgraph(const NodePtr &node, const std::vector<std::string> &target_types); |
| 851 | static void SetReduceOriginalAxisInfo(AutofuseInnerAttrs &attr_new, const AutofuseInnerAttrs &attr1, | 853 | static void SetReduceOriginalAxisInfo(AutofuseInnerAttrs &attr_new, const AutofuseInnerAttrs &attr1, |
| 852 | const AutofuseInnerAttrs &attr2); | 854 | const AutofuseInnerAttrs &attr2); |
| 855 | + // Inherit reshape axis changes when creating a fused backend node. | ||
| 856 | + static void SetReshapeAxisChangeInfo(AutofuseInnerAttrs &attr_new, const AutofuseInnerAttrs &attr1, | ||
| 857 | + const AutofuseInnerAttrs &attr2); | ||
| 853 | static Status FlushReduceOriginalAxisIfIsReduceNode(const NodePtr &node, const NodePtr &asc_node, | 858 | static Status FlushReduceOriginalAxisIfIsReduceNode(const NodePtr &node, const NodePtr &asc_node, |
| 854 | const std::vector<int64_t> axis_before_Flush, | 859 | const std::vector<int64_t> axis_before_Flush, |
| 855 | const std::vector<int64_t> axis_after_Flush); | 860 | const std::vector<int64_t> axis_after_Flush); |
| 861 | + // Refresh reshape axis changes after backend axis ids are remapped. | ||
| 862 | + static Status FlushReshapeAxisChanges(const NodePtr &node, const NodePtr &asc_node, | ||
| 863 | + const std::vector<int64_t> axis_before_Flush, | ||
| 864 | + const std::vector<int64_t> axis_after_Flush); | ||
| 856 | static Status GetTransposeInfos( | 865 | static Status GetTransposeInfos( |
| 857 | AscGraph &asc_graph, bool &has_only_one_transpose, | 866 | AscGraph &asc_graph, bool &has_only_one_transpose, |
| 858 | std::unordered_map<NodePtr, std::vector<std::pair<int64_t, int64_t>>> &fallback_node_to_transpose_info); | 867 | std::unordered_map<NodePtr, std::vector<std::pair<int64_t, int64_t>>> &fallback_node_to_transpose_info); |
| @@ -14,7 +14,6 @@ | |||
| 14 | 14 | ||
| 15 | 15 | ||
| 16 | 16 | ||
| 17 | - | ||
| 18 | 17 | ||
| 19 | 18 | ||
| 20 | namespace ge { | 19 | namespace ge { |
| @@ -36,33 +35,6 @@ void CheckAndInitReduceAllLoadState(const NodePtr &node, AutoFuseAttrs *attr, co | |||
| 36 | } | 35 | } |
| 37 | } | 36 | } |
| 38 | 37 | ||
| 39 | -bool HasReduceOriginalInfo(const AutoFuseAttrs *attr) { | ||
| 40 | - return (!attr->GetReduceOriginalAxis().empty()) || (!attr->GetReduceOriginalRepeats().empty()); | ||
| 41 | -} | ||
| 42 | - | ||
| 43 | -bool IsReduceOriginalInfoCompatible(const NodePtr &node1, const AutoFuseAttrs *attr1, const NodePtr &node2, | ||
| 44 | - const AutoFuseAttrs *attr2) { | ||
| 45 | - if (!HasReduceOriginalInfo(attr1) || !HasReduceOriginalInfo(attr2)) { | ||
| 46 | - return true; | ||
| 47 | - } | ||
| 48 | - | ||
| 49 | - const auto &axis1 = attr1->GetReduceOriginalAxis(); | ||
| 50 | - const auto &axis2 = attr2->GetReduceOriginalAxis(); | ||
| 51 | - const auto &repeats1 = attr1->GetReduceOriginalRepeats(); | ||
| 52 | - const auto &repeats2 = attr2->GetReduceOriginalRepeats(); | ||
| 53 | - if ((axis1.size() != repeats1.size()) || (axis2.size() != repeats2.size()) || (axis1 != axis2) || | ||
| 54 | - (repeats1 != repeats2)) { | ||
| 55 | - GELOGI( | ||
| 56 | - "node1 %s(%s) and node2 %s(%s) cannot fuse, reduce original axis or repeats conflict. node1 axis:%s, " | ||
| 57 | - "repeats:%s; node2 axis:%s, repeats:%s.", | ||
| 58 | - node1->GetNamePtr(), node1->GetType().c_str(), node2->GetNamePtr(), node2->GetType().c_str(), | ||
| 59 | - AutofuseUtils::VectorToStr(axis1).c_str(), AutofuseUtils::VectorToStr(repeats1).c_str(), | ||
| 60 | - AutofuseUtils::VectorToStr(axis2).c_str(), AutofuseUtils::VectorToStr(repeats2).c_str()); | ||
| 61 | - return false; | ||
| 62 | - } | ||
| 63 | - return true; | ||
| 64 | -} | ||
| 65 | - | ||
| 66 | bool ReduceFusionStrategy::CanFuse(const NodePtr &node1, const NodePtr &node2) { | 38 | bool ReduceFusionStrategy::CanFuse(const NodePtr &node1, const NodePtr &node2) { |
| 67 | const auto attr1 = BackendUtils::GetNodeAutoFuseAttr(node1); | 39 | const auto attr1 = BackendUtils::GetNodeAutoFuseAttr(node1); |
| 68 | GE_ASSERT_NOTNULL(attr1); | 40 | GE_ASSERT_NOTNULL(attr1); |
| @@ -73,10 +45,6 @@ bool ReduceFusionStrategy::CanFuse(const NodePtr &node1, const NodePtr &node2) { | |||
| 73 | std::string node1_desc = std::string("node1 ") + node1->GetNamePtr() + "(" + node1->GetType().c_str() + ")"; | 45 | std::string node1_desc = std::string("node1 ") + node1->GetNamePtr() + "(" + node1->GetType().c_str() + ")"; |
| 74 | std::string node2_desc = std::string("node2 ") + node2->GetNamePtr() + "(" + node2->GetType().c_str() + ")"; | 46 | std::string node2_desc = std::string("node2 ") + node2->GetNamePtr() + "(" + node2->GetType().c_str() + ")"; |
| 75 | 47 | ||
| 76 | - if (!IsReduceOriginalInfoCompatible(node1, attr1, node2, attr2)) { | ||
| 77 | - return false; | ||
| 78 | - } | ||
| 79 | - | ||
| 80 | // 检查并初始化node1的is_reduce_all_load状态 | 48 | // 检查并初始化node1的is_reduce_all_load状态 |
| 81 | CheckAndInitReduceAllLoadState(node1, attr1, node1_desc); | 49 | CheckAndInitReduceAllLoadState(node1, attr1, node1_desc); |
| 82 | 50 | ||
| @@ -28,6 +28,14 @@ | |||
| 28 | namespace ge { | 28 | namespace ge { |
| 29 | namespace loop { | 29 | namespace loop { |
| 30 | using Edge = std::pair<const ge::OutDataAnchor *, const ge::InDataAnchor *>; | 30 | using Edge = std::pair<const ge::OutDataAnchor *, const ge::InDataAnchor *>; |
| 31 | +struct ReshapeAxisMeta { | ||
| 32 | + std::vector<ReshapeAxisChangeInfo> axis_changes; | ||
| 33 | +}; | ||
| 34 | + | ||
| 35 | +struct NodeAxisMeta { | ||
| 36 | + ReshapeAxisMeta reshape; | ||
| 37 | +}; | ||
| 38 | + | ||
| 31 | // lazy init extra data, never hold any sharedptr of the node | 39 | // lazy init extra data, never hold any sharedptr of the node |
| 32 | struct ExtraKernelBoxMeta { | 40 | struct ExtraKernelBoxMeta { |
| 33 | size_t num_ops = 0U; | 41 | size_t num_ops = 0U; |
| @@ -37,6 +45,7 @@ struct ExtraKernelBoxMeta { | |||
| 37 | std::set<const ge::OutDataAnchor *> used_ascend_buffers; | 45 | std::set<const ge::OutDataAnchor *> used_ascend_buffers; |
| 38 | std::set<const ge::OutDataAnchor *> optimized_ascend_buffers; | 46 | std::set<const ge::OutDataAnchor *> optimized_ascend_buffers; |
| 39 | std::set<loop::Edge> concrete_edges; // edges consumed by this fused kernel | 47 | std::set<loop::Edge> concrete_edges; // edges consumed by this fused kernel |
| 48 | + NodeAxisMeta node_axis_meta; | ||
| 40 | std::string stream_label; | 49 | std::string stream_label; |
| 41 | std::string stream_priority; | 50 | std::string stream_priority; |
| 42 | static ExtraKernelBoxMeta &Default() { | 51 | static ExtraKernelBoxMeta &Default() { |
| @@ -86,6 +95,10 @@ struct KernelBoxMeta { | |||
| 86 | if (op->Type() == "ops.StoreStridedSlice") { | 95 | if (op->Type() == "ops.StoreStridedSlice") { |
| 87 | extra->num_slices++; | 96 | extra->num_slices++; |
| 88 | } | 97 | } |
| 98 | + const auto &reshape_axis_changes = op->GetReshapeAxisChanges(); | ||
| 99 | + auto &reshape_meta = extra->node_axis_meta.reshape; | ||
| 100 | + reshape_meta.axis_changes.insert(reshape_meta.axis_changes.end(), reshape_axis_changes.begin(), | ||
| 101 | + reshape_axis_changes.end()); | ||
| 89 | const auto node = op->GetAscendIrNode(); | 102 | const auto node = op->GetAscendIrNode(); |
| 90 | if (node != nullptr && seen_nodes.insert(node).second) { | 103 | if (node != nullptr && seen_nodes.insert(node).second) { |
| 91 | if (extra->stream_label.empty()) { | 104 | if (extra->stream_label.empty()) { |
| @@ -350,6 +363,10 @@ class KernelBox { | |||
| 350 | return GetExtraMeta().optimized_ascend_buffers; | 363 | return GetExtraMeta().optimized_ascend_buffers; |
| 351 | } | 364 | } |
| 352 | 365 | ||
| 366 | + const std::vector<ReshapeAxisChangeInfo> &GetReshapeAxisChanges() { | ||
| 367 | + return GetExtraMeta().node_axis_meta.reshape.axis_changes; | ||
| 368 | + } | ||
| 369 | + | ||
| 353 | size_t NumOps() { | 370 | size_t NumOps() { |
| 354 | return GetExtraMeta().num_ops; | 371 | return GetExtraMeta().num_ops; |
| 355 | } | 372 | } |
| @@ -668,6 +668,28 @@ bool CheckAndGetDims(const std::vector<Expression> &long_dims, const std::vector | |||
| 668 | return !dims.empty(); | 668 | return !dims.empty(); |
| 669 | } | 669 | } |
| 670 | 670 | ||
| 671 | +std::vector<int64_t> MakeAxisByRank(const size_t rank) { | ||
| 672 | + std::vector<int64_t> axis; | ||
| 673 | + axis.reserve(rank); | ||
| 674 | + for (size_t i = 0U; i < rank; ++i) { | ||
| 675 | + axis.push_back(static_cast<int64_t>(i)); | ||
| 676 | + } | ||
| 677 | + return axis; | ||
| 678 | +} | ||
| 679 | + | ||
| 680 | +void AddReshapeAxisChange(const LoopVar &reshape, const std::vector<Expression> &src_dims, | ||
| 681 | + const std::vector<Expression> &dst_dims) { | ||
| 682 | + if (!reshape.IsValid()) { | ||
| 683 | + return; | ||
| 684 | + } | ||
| 685 | + ReshapeAxisChangeInfo change; | ||
| 686 | + change.before_axis = MakeAxisByRank(src_dims.size()); | ||
| 687 | + change.before_repeats = src_dims; | ||
| 688 | + change.after_axis = MakeAxisByRank(dst_dims.size()); | ||
| 689 | + change.after_repeats = dst_dims; | ||
| 690 | + reshape.Op()->AddReshapeAxisChange(change); | ||
| 691 | +} | ||
| 692 | + | ||
| 671 | // Reshape只做attr为默认参数,且不进行轴转换,能进行unsqueeze/squeeze的情况。[3,4]->[1,3,4]/[2,1,3]->[2,3] | 693 | // Reshape只做attr为默认参数,且不进行轴转换,能进行unsqueeze/squeeze的情况。[3,4]->[1,3,4]/[2,1,3]->[2,3] |
| 672 | // 新增支持 [A*B, C]->[A,B,C]/[A,B,C]->[A*B,C] | 694 | // 新增支持 [A*B, C]->[A,B,C]/[A,B,C]->[A*B,C] |
| 673 | LoopVar Reshape(const LoopVar &op, const std::vector<Expression> &src_dims, const std::vector<Expression> &dst_dims) { | 695 | LoopVar Reshape(const LoopVar &op, const std::vector<Expression> &src_dims, const std::vector<Expression> &dst_dims) { |
| @@ -163,6 +163,8 @@ LoopVar Transpose(const LoopVar &op, const std::vector<ge::Expression> &dims, co | |||
| 163 | LoopVar Squeeze(const LoopVar &op, int64_t dim); | 163 | LoopVar Squeeze(const LoopVar &op, int64_t dim); |
| 164 | LoopVar Unsqueeze(const LoopVar &op, int64_t dim); | 164 | LoopVar Unsqueeze(const LoopVar &op, int64_t dim); |
| 165 | LoopVar Reshape(const LoopVar &op, const std::vector<Expression> &src_dims, const std::vector<Expression> &dst_dims); | 165 | LoopVar Reshape(const LoopVar &op, const std::vector<Expression> &src_dims, const std::vector<Expression> &dst_dims); |
| 166 | +void AddReshapeAxisChange(const LoopVar &reshape, const std::vector<Expression> &src_dims, | ||
| 167 | + const std::vector<Expression> &dst_dims); | ||
| 166 | LoopVar LoadSeed(const std::string &name, const LoopVar &offset); | 168 | LoopVar LoadSeed(const std::string &name, const LoopVar &offset); |
| 167 | LoopVar ReduceThenBroadcast(ReduceType type, const LoopVar &op, int64_t dim); | 169 | LoopVar ReduceThenBroadcast(ReduceType type, const LoopVar &op, int64_t dim); |
| 168 | LoopVar ToDtypeBitcast(const LoopVar &x, ge::DataType dst_type, ge::DataType src_type); | 170 | LoopVar ToDtypeBitcast(const LoopVar &x, ge::DataType dst_type, ge::DataType src_type); |
| @@ -68,6 +68,13 @@ struct LoopAxis { | |||
| 68 | */ | 68 | */ |
| 69 | using Index = std::vector<ge::Expression>; | 69 | using Index = std::vector<ge::Expression>; |
| 70 | 70 | ||
| 71 | +struct ReshapeAxisChangeInfo { | ||
| 72 | + std::vector<int64_t> before_axis; | ||
| 73 | + std::vector<Expression> before_repeats; | ||
| 74 | + std::vector<int64_t> after_axis; | ||
| 75 | + std::vector<Expression> after_repeats; | ||
| 76 | +}; | ||
| 77 | + | ||
| 71 | /** | 78 | /** |
| 72 | * TensorLoopDesc用于表达一个Loop lowering后的Ascend IR输出值的循环描述,其包含了一个Loop的所有信息。 | 79 | * TensorLoopDesc用于表达一个Loop lowering后的Ascend IR输出值的循环描述,其包含了一个Loop的所有信息。 |
| 73 | * 包括循环的遍历范围、循环的步长。 | 80 | * 包括循环的遍历范围、循环的步长。 |
| @@ -114,8 +114,17 @@ class LoopOp { | |||
| 114 | return inputs_; | 114 | return inputs_; |
| 115 | } | 115 | } |
| 116 | 116 | ||
| 117 | + void AddReshapeAxisChange(const ReshapeAxisChangeInfo &change) { | ||
| 118 | + reshape_axis_changes_.push_back(change); | ||
| 119 | + } | ||
| 120 | + | ||
| 121 | + [[nodiscard]] const std::vector<ReshapeAxisChangeInfo> &GetReshapeAxisChanges() const { | ||
| 122 | + return reshape_axis_changes_; | ||
| 123 | + } | ||
| 124 | + | ||
| 117 | [[nodiscard]] LoopOpPtr Clone() const { | 125 | [[nodiscard]] LoopOpPtr Clone() const { |
| 118 | auto op = CloneImpl(); | 126 | auto op = CloneImpl(); |
| 127 | + op->reshape_axis_changes_ = reshape_axis_changes_; | ||
| 119 | for (size_t i = 0U; i < inputs_.size(); ++i) { | 128 | for (size_t i = 0U; i < inputs_.size(); ++i) { |
| 120 | op->inputs_[i] = op->inputs_[i]->Clone(); | 129 | op->inputs_[i] = op->inputs_[i]->Clone(); |
| 121 | } | 130 | } |
| @@ -132,6 +141,7 @@ class LoopOp { | |||
| 132 | 141 | ||
| 133 | private: | 142 | private: |
| 134 | static std::atomic<int64_t> global_id_; | 143 | static std::atomic<int64_t> global_id_; |
| 144 | + std::vector<ReshapeAxisChangeInfo> reshape_axis_changes_; | ||
| 135 | }; | 145 | }; |
| 136 | 146 | ||
| 137 | class LoopVar { | 147 | class LoopVar { |
| @@ -243,6 +243,21 @@ string CreateAscbackendName(loop::KernelBox &kernel_box, CounterPtr counter) { | |||
| 243 | return ascbackend_name; | 243 | return ascbackend_name; |
| 244 | } | 244 | } |
| 245 | 245 | ||
| 246 | +Status SaveReshapeAxisChangeInfo(loop::KernelBox &kernel_box, const std::shared_ptr<AscGraph> &asc_graph, | ||
| 247 | + AutoFuseAttrs *fuse_attrs) { | ||
| 248 | + (void)asc_graph; | ||
| 249 | + const auto &reshape_axis_changes = kernel_box.GetReshapeAxisChanges(); | ||
| 250 | + for (const auto &loop_change : reshape_axis_changes) { | ||
| 251 | + af::ReshapeAxisChangeInfo change; | ||
| 252 | + change.before_axis = loop_change.before_axis; | ||
| 253 | + change.before_repeats = loop_change.before_repeats; | ||
| 254 | + change.after_axis = loop_change.after_axis; | ||
| 255 | + change.after_repeats = loop_change.after_repeats; | ||
| 256 | + fuse_attrs->AddReshapeAxisChange(change); | ||
| 257 | + } | ||
| 258 | + return SUCCESS; | ||
| 259 | +} | ||
| 260 | + | ||
| 246 | graphStatus BuildOpForKernelBox(loop::KernelBox &kernel_box, CounterPtr counter, | 261 | graphStatus BuildOpForKernelBox(loop::KernelBox &kernel_box, CounterPtr counter, |
| 247 | shared_ptr<loop::AscOverrides> asc_graph, af::Operator &asc_op) { | 262 | shared_ptr<loop::AscOverrides> asc_graph, af::Operator &asc_op) { |
| 248 | std::string asc_op_name = CreateAscbackendName(kernel_box, counter); | 263 | std::string asc_op_name = CreateAscbackendName(kernel_box, counter); |
| @@ -424,6 +439,7 @@ OpDescPtr LoweringManager::BuildOpDescForKernelBox(loop::KernelBox &kernel_box, | |||
| 424 | GE_ASSERT_NOTNULL(fuse_attrs); | 439 | GE_ASSERT_NOTNULL(fuse_attrs); |
| 425 | GE_ASSERT_NOTNULL(asc_graph->SharedGraph()); | 440 | GE_ASSERT_NOTNULL(asc_graph->SharedGraph()); |
| 426 | fuse_attrs->SetAscGraph(asc_graph->SharedGraph(), kernel_box.Type()); | 441 | fuse_attrs->SetAscGraph(asc_graph->SharedGraph(), kernel_box.Type()); |
| 442 | + GE_ASSERT_SUCCESS(SaveReshapeAxisChangeInfo(kernel_box, asc_graph->SharedGraph(), fuse_attrs)); | ||
| 427 | fuse_attrs->SetOriginOutputBuffers({anchor}); | 443 | fuse_attrs->SetOriginOutputBuffers({anchor}); |
| 428 | fuse_attrs->SetOriginNodes(kernel_box.GetAscendIrNodes()); | 444 | fuse_attrs->SetOriginNodes(kernel_box.GetAscendIrNodes()); |
| 429 | fuse_attrs->SetOptimizedInputBuffers(kernel_box.GetOptimizedInputAscendBuffers()); | 445 | fuse_attrs->SetOptimizedInputBuffers(kernel_box.GetOptimizedInputAscendBuffers()); |
| @@ -1914,11 +1914,21 @@ REGISTER_LOWERING(SquareSumV1) { | |||
| 1914 | 1914 | ||
| 1915 | REGISTER_LOWERING(Unsqueeze) { | 1915 | REGISTER_LOWERING(Unsqueeze) { |
| 1916 | auto x = loop::Load(node->GetInDataAnchor(0)); | 1916 | auto x = loop::Load(node->GetInDataAnchor(0)); |
| 1917 | + GE_ASSERT_NOTNULL(node->GetInDataAnchor(0)); | ||
| 1918 | + auto src = node->GetInDataAnchor(0)->GetPeerOutAnchor(); | ||
| 1919 | + GE_ASSERT_NOTNULL(src); | ||
| 1920 | + std::vector<ge::Expression> dims; | ||
| 1921 | + LOWERING_WARN_RECORD_REASON(loop::GetBufferShape(src, dims) == GRAPH_SUCCESS, node, | ||
| 1922 | + "Failed to get 0th-input symbol shape."); | ||
| 1923 | + std::vector<ge::Expression> output_dims; | ||
| 1924 | + LOWERING_WARN_RECORD_REASON(loop::GetBufferShape(node->GetOutDataAnchor(0), output_dims) == GRAPH_SUCCESS, node, | ||
| 1925 | + "Failed to get 0th-output symbol shape."); | ||
| 1917 | std::vector<int64_t> vec_axes; | 1926 | std::vector<int64_t> vec_axes; |
| 1918 | GE_ASSERT_TRUE(AttrUtils::GetListInt(node->GetOpDesc(), "axes", vec_axes)); | 1927 | GE_ASSERT_TRUE(AttrUtils::GetListInt(node->GetOpDesc(), "axes", vec_axes)); |
| 1919 | for (const auto vec_axe : vec_axes) { | 1928 | for (const auto vec_axe : vec_axes) { |
| 1920 | x = loop::Unsqueeze(x, vec_axe); | 1929 | x = loop::Unsqueeze(x, vec_axe); |
| 1921 | } | 1930 | } |
| 1931 | + loop::AddReshapeAxisChange(x, dims, output_dims); | ||
| 1922 | loop::StoreReshape(node->GetOutDataAnchor(0), x); | 1932 | loop::StoreReshape(node->GetOutDataAnchor(0), x); |
| 1923 | return GRAPH_SUCCESS; | 1933 | return GRAPH_SUCCESS; |
| 1924 | } | 1934 | } |
| @@ -1950,6 +1960,10 @@ REGISTER_LOWERING(Squeeze) { | |||
| 1950 | for (size_t i = 0; i < vec_axes.size(); i++) { | 1960 | for (size_t i = 0; i < vec_axes.size(); i++) { |
| 1951 | x = loop::Squeeze(x, vec_axes[i] - static_cast<int64_t>(i)); | 1961 | x = loop::Squeeze(x, vec_axes[i] - static_cast<int64_t>(i)); |
| 1952 | } | 1962 | } |
| 1963 | + std::vector<ge::Expression> output_dims; | ||
| 1964 | + LOWERING_WARN_RECORD_REASON(loop::GetBufferShape(node->GetOutDataAnchor(0), output_dims) == GRAPH_SUCCESS, node, | ||
| 1965 | + "Failed to get 0th-output symbol shape."); | ||
| 1966 | + loop::AddReshapeAxisChange(x, dims, output_dims); | ||
| 1953 | loop::Store(node->GetOutDataAnchor(0), x); | 1967 | loop::Store(node->GetOutDataAnchor(0), x); |
| 1954 | return GRAPH_SUCCESS; | 1968 | return GRAPH_SUCCESS; |
| 1955 | } | 1969 | } |
| @@ -2121,8 +2135,6 @@ REGISTER_LOWERING(Reshape) { | |||
| 2121 | GE_ASSERT_NOTNULL(node->GetInDataAnchor(0)); | 2135 | GE_ASSERT_NOTNULL(node->GetInDataAnchor(0)); |
| 2122 | auto src = node->GetInDataAnchor(0)->GetPeerOutAnchor(); | 2136 | auto src = node->GetInDataAnchor(0)->GetPeerOutAnchor(); |
| 2123 | GE_ASSERT_NOTNULL(src); | 2137 | GE_ASSERT_NOTNULL(src); |
| 2124 | - auto desc = src->GetOwnerNode()->GetOpDesc()->GetOutputDescPtr(src->GetIdx()); | ||
| 2125 | - GE_ASSERT_NOTNULL(desc); | ||
| 2126 | std::vector<Expression> dims; | 2138 | std::vector<Expression> dims; |
| 2127 | LOWERING_WARN_RECORD_REASON(loop::GetBufferShape(src, dims) == GRAPH_SUCCESS, node, | 2139 | LOWERING_WARN_RECORD_REASON(loop::GetBufferShape(src, dims) == GRAPH_SUCCESS, node, |
| 2128 | "Failed to get 0th-input symbol shape"); | 2140 | "Failed to get 0th-input symbol shape"); |
| @@ -2143,12 +2155,22 @@ REGISTER_LOWERING(Reshape) { | |||
| 2143 | auto x = loop::Load(node->GetInDataAnchor(0)); | 2155 | auto x = loop::Load(node->GetInDataAnchor(0)); |
| 2144 | auto reshape = loop::Reshape(x, dims, output_dims); | 2156 | auto reshape = loop::Reshape(x, dims, output_dims); |
| 2145 | LOWERING_WARN_RECORD_REASON(reshape.IsValid(), node, "no specific reshape pattern matched"); | 2157 | LOWERING_WARN_RECORD_REASON(reshape.IsValid(), node, "no specific reshape pattern matched"); |
| 2158 | + loop::AddReshapeAxisChange(reshape, dims, output_dims); | ||
| 2146 | loop::StoreReshape(node->GetOutDataAnchor(0), reshape); | 2159 | loop::StoreReshape(node->GetOutDataAnchor(0), reshape); |
| 2147 | return GRAPH_SUCCESS; | 2160 | return GRAPH_SUCCESS; |
| 2148 | } | 2161 | } |
| 2149 | 2162 | ||
| 2150 | REGISTER_LOWERING(ExpandDims) { | 2163 | REGISTER_LOWERING(ExpandDims) { |
| 2151 | auto x = loop::Load(node->GetInDataAnchor(0)); | 2164 | auto x = loop::Load(node->GetInDataAnchor(0)); |
| 2165 | + GE_ASSERT_NOTNULL(node->GetInDataAnchor(0)); | ||
| 2166 | + auto src = node->GetInDataAnchor(0)->GetPeerOutAnchor(); | ||
| 2167 | + GE_ASSERT_NOTNULL(src); | ||
| 2168 | + std::vector<ge::Expression> input_dims; | ||
| 2169 | + LOWERING_WARN_RECORD_REASON(loop::GetBufferShape(src, input_dims) == GRAPH_SUCCESS, node, | ||
| 2170 | + "Failed to get 0th-input symbol shape."); | ||
| 2171 | + std::vector<ge::Expression> output_dims; | ||
| 2172 | + LOWERING_WARN_RECORD_REASON(loop::GetBufferShape(node->GetOutDataAnchor(0), output_dims) == GRAPH_SUCCESS, node, | ||
| 2173 | + "Failed to get 0th-output symbol shape."); | ||
| 2152 | const auto op = ge::OpDescUtils::CreateOperatorFromNode(node); | 2174 | const auto op = ge::OpDescUtils::CreateOperatorFromNode(node); |
| 2153 | ge::Tensor axis_tensor; | 2175 | ge::Tensor axis_tensor; |
| 2154 | LOWERING_WARN_RECORD_REASON(op.GetInputConstData("axis", axis_tensor) == ge::SUCCESS, node, "Input is dynamic axis"); | 2176 | LOWERING_WARN_RECORD_REASON(op.GetInputConstData("axis", axis_tensor) == ge::SUCCESS, node, "Input is dynamic axis"); |
| @@ -2172,6 +2194,7 @@ REGISTER_LOWERING(ExpandDims) { | |||
| 2172 | } | 2194 | } |
| 2173 | 2195 | ||
| 2174 | x = loop::Unsqueeze(x, dim); | 2196 | x = loop::Unsqueeze(x, dim); |
| 2197 | + loop::AddReshapeAxisChange(x, input_dims, output_dims); | ||
| 2175 | loop::StoreReshape(node->GetOutDataAnchor(0), x); | 2198 | loop::StoreReshape(node->GetOutDataAnchor(0), x); |
| 2176 | return GRAPH_SUCCESS; | 2199 | return GRAPH_SUCCESS; |
| 2177 | } | 2200 | } |
| @@ -543,11 +543,12 @@ inline Status SaveReduceOriginalAxisToFuseAttrPro(AscGraph &asc_graph, [[maybe_u | |||
| 543 | GE_ASSERT_SUCCESS(asc_adapt::GetPeerOutNode(node, reduce_input_node, 0)); | 543 | GE_ASSERT_SUCCESS(asc_adapt::GetPeerOutNode(node, reduce_input_node, 0)); |
| 544 | TensorAttrInfo reduce_input_node_attr; | 544 | TensorAttrInfo reduce_input_node_attr; |
| 545 | GE_ASSERT_SUCCESS(BackendUtils::GetNodeTensorAttrInfo(reduce_input_node, reduce_input_node_attr)); | 545 | GE_ASSERT_SUCCESS(BackendUtils::GetNodeTensorAttrInfo(reduce_input_node, reduce_input_node_attr)); |
| 546 | - autofuse_attr->SetReduceOriginalAxis(reduce_input_node_attr.axis); | 546 | + autofuse_attr->SetReduceOriginalAxisInfo(node->GetName(), reduce_input_node_attr.axis, |
| 547 | - autofuse_attr->SetReduceOriginalRepeats(reduce_input_node_attr.repeats); | 547 | + reduce_input_node_attr.repeats); |
| 548 | - GELOGI("graph %s has broadcast linkto reduce, save axis(axis:%s repeat:%s) between broadcast reduce .", | 548 | + GELOGI("graph %s has broadcast linkto reduce %s, save axis(axis:%s repeat:%s) between broadcast reduce .", |
| 549 | - asc_graph.GetName().c_str(), AutofuseUtils::VectorToStr(autofuse_attr->GetReduceOriginalAxis()).c_str(), | 549 | + asc_graph.GetName().c_str(), node->GetNamePtr(), |
| 550 | - AutofuseUtils::VectorToStr(autofuse_attr->GetReduceOriginalRepeats()).c_str()); | 550 | + AutofuseUtils::VectorToStr(reduce_input_node_attr.axis).c_str(), |
| 551 | + AutofuseUtils::VectorToStr(reduce_input_node_attr.repeats).c_str()); | ||
| 551 | } | 552 | } |
| 552 | } | 553 | } |
| 553 | return SUCCESS; | 554 | return SUCCESS; |
| @@ -290,12 +290,9 @@ inline Status FlashContinueGraphAxis(std::vector<AxisPtr> &axis, const std::vect | |||
| 290 | return SUCCESS; | 290 | return SUCCESS; |
| 291 | } | 291 | } |
| 292 | 292 | ||
| 293 | -inline Status RemoveReduceOriginalInvalidAxis(const NodePtr &asc_node, | 293 | +inline Status RemoveReduceOriginalInvalidAxis(std::vector<int64_t> &reduce_original_axis, |
| 294 | + std::vector<Expression> &reduce_original_repeats, const NodePtr &asc_node, | ||
| 294 | const std::vector<int64_t> &graph_invalid_axis_id) { | 295 | const std::vector<int64_t> &graph_invalid_axis_id) { |
| 295 | - auto attr = BackendUtils::GetNodeAutoFuseAttr(asc_node); | ||
| 296 | - GE_ASSERT_NOTNULL(attr); | ||
| 297 | - auto reduce_original_axis = attr->GetReduceOriginalAxis(); | ||
| 298 | - auto reduce_original_repeats = attr->GetReduceOriginalRepeats(); | ||
| 299 | if (reduce_original_axis.empty() || reduce_original_repeats.empty()) { | 296 | if (reduce_original_axis.empty() || reduce_original_repeats.empty()) { |
| 300 | return SUCCESS; | 297 | return SUCCESS; |
| 301 | } | 298 | } |
| @@ -313,8 +310,25 @@ inline Status RemoveReduceOriginalInvalidAxis(const NodePtr &asc_node, | |||
| 313 | reduce_original_repeats.erase(reduce_original_repeats.begin() + axis_idx); | 310 | reduce_original_repeats.erase(reduce_original_repeats.begin() + axis_idx); |
| 314 | } | 311 | } |
| 315 | GE_ASSERT_SUCCESS(FlashContinueNodeAxis(reduce_original_axis, graph_invalid_axis_id)); | 312 | GE_ASSERT_SUCCESS(FlashContinueNodeAxis(reduce_original_axis, graph_invalid_axis_id)); |
| 313 | + return SUCCESS; | ||
| 314 | +} | ||
| 315 | + | ||
| 316 | +inline Status RemoveReduceOriginalInvalidAxis(const NodePtr &asc_node, | ||
| 317 | + const std::vector<int64_t> &graph_invalid_axis_id) { | ||
| 318 | + auto attr = BackendUtils::GetNodeAutoFuseAttr(asc_node); | ||
| 319 | + GE_ASSERT_NOTNULL(attr); | ||
| 320 | + | ||
| 321 | + auto reduce_original_axis = attr->GetReduceOriginalAxis(); | ||
| 322 | + auto reduce_original_repeats = attr->GetReduceOriginalRepeats(); | ||
| 323 | + GE_ASSERT_SUCCESS( | ||
| 324 | + RemoveReduceOriginalInvalidAxis(reduce_original_axis, reduce_original_repeats, asc_node, graph_invalid_axis_id)); | ||
| 316 | attr->SetReduceOriginalAxis(reduce_original_axis); | 325 | attr->SetReduceOriginalAxis(reduce_original_axis); |
| 317 | attr->SetReduceOriginalRepeats(reduce_original_repeats); | 326 | attr->SetReduceOriginalRepeats(reduce_original_repeats); |
| 327 | + | ||
| 328 | + for (auto &reduce_info : attr->GetMutableInterAttrs().reduce_original_axis_infos) { | ||
| 329 | + GE_ASSERT_SUCCESS(RemoveReduceOriginalInvalidAxis(reduce_info.second.axis, reduce_info.second.repeats, asc_node, | ||
| 330 | + graph_invalid_axis_id)); | ||
| 331 | + } | ||
| 318 | return SUCCESS; | 332 | return SUCCESS; |
| 319 | } | 333 | } |
| 320 | 334 | ||
| @@ -72,14 +72,15 @@ inline Status InsertBroadcastBeforeNode(AscGraph &asc_graph, const NodePtr &node | |||
| 72 | return SUCCESS; | 72 | return SUCCESS; |
| 73 | } | 73 | } |
| 74 | 74 | ||
| 75 | -inline Status UpdateReduceNodeRepeats(const NodePtr &asc_node, TensorAttrInfo &temp_cur_attr) { | 75 | +inline Status UpdateReduceNodeRepeats(const NodePtr &asc_node, const NodePtr &reduce_node, |
| 76 | + TensorAttrInfo &temp_cur_attr) { | ||
| 76 | auto reduce_attrs = BackendUtils::GetNodeAutoFuseAttr(asc_node); | 77 | auto reduce_attrs = BackendUtils::GetNodeAutoFuseAttr(asc_node); |
| 77 | if (reduce_attrs == nullptr) { | 78 | if (reduce_attrs == nullptr) { |
| 78 | return SUCCESS; | 79 | return SUCCESS; |
| 79 | } | 80 | } |
| 80 | 81 | ||
| 81 | - const auto &original_axis = reduce_attrs->GetReduceOriginalAxis(); | 82 | + const auto &original_axis = reduce_attrs->GetReduceOriginalAxis(reduce_node->GetName()); |
| 82 | - const auto &original_repeats = reduce_attrs->GetReduceOriginalRepeats(); | 83 | + const auto &original_repeats = reduce_attrs->GetReduceOriginalRepeats(reduce_node->GetName()); |
| 83 | 84 | ||
| 84 | if (original_axis.empty() || | 85 | if (original_axis.empty() || |
| 85 | original_repeats.empty()) { // 如果为空,说明前面是lowering出来不需要反推broadcast(load后或者融合点)的计算节点 | 86 | original_repeats.empty()) { // 如果为空,说明前面是lowering出来不需要反推broadcast(load后或者融合点)的计算节点 |
| @@ -108,7 +109,7 @@ inline Status GetBroadcastInfoForNode(const NodePtr &cur_node, TensorAttrInfo &t | |||
| 108 | attr_info.broadcast_info.clear(); | 109 | attr_info.broadcast_info.clear(); |
| 109 | 110 | ||
| 110 | if (IsReduceNode(cur_node)) { | 111 | if (IsReduceNode(cur_node)) { |
| 111 | - GE_ASSERT_SUCCESS(UpdateReduceNodeRepeats(asc_node, temp_cur_attr)); | 112 | + GE_ASSERT_SUCCESS(UpdateReduceNodeRepeats(asc_node, cur_node, temp_cur_attr)); |
| 112 | } | 113 | } |
| 113 | 114 | ||
| 114 | TensorAttrInfo temp_peer_out_attr; | 115 | TensorAttrInfo temp_peer_out_attr; |
| @@ -0,0 +1,1741 @@ | |||
| 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 | + | ||
| 13 | + | ||
| 14 | + | ||
| 15 | + | ||
| 16 | + | ||
| 17 | + | ||
| 18 | + | ||
| 19 | + | ||
| 20 | + | ||
| 21 | + | ||
| 22 | + | ||
| 23 | +namespace ge { | ||
| 24 | +namespace asc_adapt { | ||
| 25 | +inline bool IsSameRepeat(const Expression &lhs, const Expression &rhs) { | ||
| 26 | + return SymbolicUtils::StaticCheckEq(lhs, rhs) == TriBool::kTrue; | ||
| 27 | +} | ||
| 28 | + | ||
| 29 | +inline bool IsUnitRepeat(const Expression &repeat) { | ||
| 30 | + return IsSameRepeat(repeat, kSymbolOne); | ||
| 31 | +} | ||
| 32 | + | ||
| 33 | +inline bool IsSameRepeats(const std::vector<Expression> &lhs, const std::vector<Expression> &rhs) { | ||
| 34 | + return (lhs.size() == rhs.size()) && std::equal(lhs.begin(), lhs.end(), rhs.begin(), IsSameRepeat); | ||
| 35 | +} | ||
| 36 | + | ||
| 37 | +inline std::vector<Expression> RemoveUnitRepeats(const std::vector<Expression> &repeats) { | ||
| 38 | + std::vector<Expression> non_unit_repeats; | ||
| 39 | + for (const auto &repeat : repeats) { | ||
| 40 | + if (!IsUnitRepeat(repeat)) { | ||
| 41 | + non_unit_repeats.push_back(repeat); | ||
| 42 | + } | ||
| 43 | + } | ||
| 44 | + return non_unit_repeats; | ||
| 45 | +} | ||
| 46 | + | ||
| 47 | +inline std::vector<size_t> BuildUnitRepeatGapCounts(const std::vector<Expression> &repeats) { | ||
| 48 | + const auto non_unit_repeats = RemoveUnitRepeats(repeats); | ||
| 49 | + std::vector<size_t> unit_gap_counts(non_unit_repeats.size() + 1U, 0U); | ||
| 50 | + size_t non_unit_idx = 0U; | ||
| 51 | + for (const auto &repeat : repeats) { | ||
| 52 | + if (IsUnitRepeat(repeat)) { | ||
| 53 | + ++unit_gap_counts[non_unit_idx]; | ||
| 54 | + } else if (non_unit_idx < non_unit_repeats.size()) { | ||
| 55 | + ++non_unit_idx; | ||
| 56 | + } | ||
| 57 | + } | ||
| 58 | + return unit_gap_counts; | ||
| 59 | +} | ||
| 60 | + | ||
| 61 | +inline void MergeUnitRepeatGapCounts(const std::vector<size_t> &candidate_gaps, std::vector<size_t> &target_gaps) { | ||
| 62 | + if (target_gaps.empty()) { | ||
| 63 | + target_gaps = candidate_gaps; | ||
| 64 | + return; | ||
| 65 | + } | ||
| 66 | + if (target_gaps.size() != candidate_gaps.size()) { | ||
| 67 | + return; | ||
| 68 | + } | ||
| 69 | + for (size_t i = 0U; i < target_gaps.size(); ++i) { | ||
| 70 | + target_gaps[i] = std::max(target_gaps[i], candidate_gaps[i]); | ||
| 71 | + } | ||
| 72 | +} | ||
| 73 | + | ||
| 74 | +inline std::vector<Expression> ApplyUnitRepeatGaps(const std::vector<Expression> &non_unit_repeats, | ||
| 75 | + const std::vector<size_t> &unit_gap_counts) { | ||
| 76 | + if (unit_gap_counts.size() != (non_unit_repeats.size() + 1U)) { | ||
| 77 | + return non_unit_repeats; | ||
| 78 | + } | ||
| 79 | + std::vector<Expression> target_repeats; | ||
| 80 | + for (size_t non_unit_idx = 0U; non_unit_idx < non_unit_repeats.size(); ++non_unit_idx) { | ||
| 81 | + target_repeats.insert(target_repeats.end(), unit_gap_counts[non_unit_idx], kSymbolOne); | ||
| 82 | + target_repeats.push_back(non_unit_repeats[non_unit_idx]); | ||
| 83 | + } | ||
| 84 | + target_repeats.insert(target_repeats.end(), unit_gap_counts.back(), kSymbolOne); | ||
| 85 | + return target_repeats; | ||
| 86 | +} | ||
| 87 | + | ||
| 88 | +inline void AppendUniqueTargetRepeats(const std::vector<Expression> &target_repeats, | ||
| 89 | + std::vector<std::vector<Expression>> &target_candidates) { | ||
| 90 | + if (target_repeats.empty()) { | ||
| 91 | + return; | ||
| 92 | + } | ||
| 93 | + const auto it = std::find_if(target_candidates.begin(), target_candidates.end(), | ||
| 94 | + [&target_repeats](const auto &saved) { return IsSameRepeats(saved, target_repeats); }); | ||
| 95 | + if (it == target_candidates.end()) { | ||
| 96 | + target_candidates.push_back(target_repeats); | ||
| 97 | + } | ||
| 98 | +} | ||
| 99 | + | ||
| 100 | +inline std::vector<Expression> BuildNoOpReshapeTargetRepeats(const af::ReshapeAxisChangeInfo &axis_change) { | ||
| 101 | + const auto before_non_unit_repeats = RemoveUnitRepeats(axis_change.before_repeats); | ||
| 102 | + const auto after_non_unit_repeats = RemoveUnitRepeats(axis_change.after_repeats); | ||
| 103 | + if (!IsSameRepeats(before_non_unit_repeats, after_non_unit_repeats)) { | ||
| 104 | + return axis_change.before_repeats.size() >= axis_change.after_repeats.size() ? axis_change.before_repeats | ||
| 105 | + : axis_change.after_repeats; | ||
| 106 | + } | ||
| 107 | + | ||
| 108 | + std::vector<size_t> unit_gap_counts; | ||
| 109 | + MergeUnitRepeatGapCounts(BuildUnitRepeatGapCounts(axis_change.before_repeats), unit_gap_counts); | ||
| 110 | + MergeUnitRepeatGapCounts(BuildUnitRepeatGapCounts(axis_change.after_repeats), unit_gap_counts); | ||
| 111 | + return ApplyUnitRepeatGaps(before_non_unit_repeats, unit_gap_counts); | ||
| 112 | +} | ||
| 113 | + | ||
| 114 | +inline bool IsCompletedReshapeAxis(const AxisPtr &axis_info) { | ||
| 115 | + return (axis_info != nullptr) && (axis_info->name.rfind("reshape_axis_optimized_", 0U) == 0U); | ||
| 116 | +} | ||
| 117 | + | ||
| 118 | +inline std::string GetCompletedReshapeAxisName(const int64_t axis_id) { | ||
| 119 | + return "reshape_axis_optimized_" + std::to_string(axis_id); | ||
| 120 | +} | ||
| 121 | + | ||
| 122 | +inline void RefreshCompletedReshapeAxisName(const AxisPtr &axis_info) { | ||
| 123 | + if (IsCompletedReshapeAxis(axis_info)) { | ||
| 124 | + axis_info->name = GetCompletedReshapeAxisName(axis_info->id); | ||
| 125 | + } | ||
| 126 | +} | ||
| 127 | + | ||
| 128 | +inline AxisPtr MakeNoOpReshapeAxis(const int64_t axis_id, const Expression &repeat) { | ||
| 129 | + auto axis_info = ComGraphMakeShared<Axis>(); | ||
| 130 | + GE_ASSERT_NOTNULL(axis_info); | ||
| 131 | + axis_info->id = axis_id; | ||
| 132 | + axis_info->name = GetCompletedReshapeAxisName(axis_id); | ||
| 133 | + axis_info->type = Axis::kAxisTypeOriginal; | ||
| 134 | + axis_info->size = repeat; | ||
| 135 | + return axis_info; | ||
| 136 | +} | ||
| 137 | + | ||
| 138 | +inline void ShiftAxisIdFrom(const int64_t insert_axis_id, int64_t &axis_id) { | ||
| 139 | + if (axis_id >= insert_axis_id) { | ||
| 140 | + ++axis_id; | ||
| 141 | + } | ||
| 142 | +} | ||
| 143 | + | ||
| 144 | +inline void ShiftAxisInfoIdFrom(const int64_t insert_axis_id, const AxisPtr &axis_info) { | ||
| 145 | + if (axis_info == nullptr) { | ||
| 146 | + return; | ||
| 147 | + } | ||
| 148 | + const auto old_axis_id = axis_info->id; | ||
| 149 | + ShiftAxisIdFrom(insert_axis_id, axis_info->id); | ||
| 150 | + if (axis_info->id != old_axis_id) { | ||
| 151 | + RefreshCompletedReshapeAxisName(axis_info); | ||
| 152 | + } | ||
| 153 | +} | ||
| 154 | + | ||
| 155 | +inline void ShiftAxisIdsFrom(const int64_t insert_axis_id, std::vector<int64_t> &axis) { | ||
| 156 | + for (auto &axis_id : axis) { | ||
| 157 | + ShiftAxisIdFrom(insert_axis_id, axis_id); | ||
| 158 | + } | ||
| 159 | +} | ||
| 160 | + | ||
| 161 | +inline void ShiftReshapeAxisChangesFrom(const int64_t insert_axis_id, | ||
| 162 | + std::vector<af::ReshapeAxisChangeInfo> &reshape_axis_changes) { | ||
| 163 | + for (auto &change : reshape_axis_changes) { | ||
| 164 | + ShiftAxisIdsFrom(insert_axis_id, change.before_axis); | ||
| 165 | + ShiftAxisIdsFrom(insert_axis_id, change.after_axis); | ||
| 166 | + } | ||
| 167 | +} | ||
| 168 | + | ||
| 169 | +inline Status ShiftAscGraphAxisIdsFrom(const AscGraph &asc_graph, const int64_t insert_axis_id) { | ||
| 170 | + for (const auto &node : AscGraphUtils::GetComputeGraph(asc_graph)->GetAllNodes()) { | ||
| 171 | + const auto &op_desc = node->GetOpDesc(); | ||
| 172 | + GE_ASSERT_NOTNULL(op_desc); | ||
| 173 | + auto node_attr = op_desc->GetAttrsGroup<AscNodeAttr>(); | ||
| 174 | + if (node_attr != nullptr) { | ||
| 175 | + ShiftAxisIdsFrom(insert_axis_id, node_attr->sched.axis); | ||
| 176 | + ShiftAxisIdFrom(insert_axis_id, node_attr->sched.loop_axis); | ||
| 177 | + } | ||
| 178 | + for (size_t i = 0U; i < node->GetAllInDataAnchorsSize(); ++i) { | ||
| 179 | + const auto input_tensor_desc = op_desc->MutableInputDesc(i); | ||
| 180 | + GE_ASSERT_NOTNULL(input_tensor_desc); | ||
| 181 | + auto tensor_attr = input_tensor_desc->GetAttrsGroup<AscTensorAttr>(); | ||
| 182 | + if (tensor_attr == nullptr) { | ||
| 183 | + continue; | ||
| 184 | + } | ||
| 185 | + ShiftAxisIdsFrom(insert_axis_id, tensor_attr->axis); | ||
| 186 | + } | ||
| 187 | + for (size_t i = 0U; i < node->GetAllOutDataAnchorsSize(); ++i) { | ||
| 188 | + const auto output_tensor_desc = op_desc->MutableOutputDesc(i); | ||
| 189 | + GE_ASSERT_NOTNULL(output_tensor_desc); | ||
| 190 | + auto tensor_attr = output_tensor_desc->GetAttrsGroup<AscTensorAttr>(); | ||
| 191 | + if (tensor_attr == nullptr) { | ||
| 192 | + continue; | ||
| 193 | + } | ||
| 194 | + ShiftAxisIdsFrom(insert_axis_id, tensor_attr->axis); | ||
| 195 | + } | ||
| 196 | + } | ||
| 197 | + return SUCCESS; | ||
| 198 | +} | ||
| 199 | + | ||
| 200 | +template <typename ScoreFunc> | ||
| 201 | +inline std::vector<size_t> BuildBestOverlapTargetIndexes(const size_t source_size, const size_t target_size, | ||
| 202 | + const ScoreFunc &score_func) { | ||
| 203 | + if ((source_size == 0U) || (source_size > target_size)) { | ||
| 204 | + return {}; | ||
| 205 | + } | ||
| 206 | + constexpr int32_t kInvalidScore = -1000000; | ||
| 207 | + std::vector<std::vector<int32_t>> dp(source_size + 1U, std::vector<int32_t>(target_size + 1U, kInvalidScore)); | ||
| 208 | + for (size_t target_idx = 0U; target_idx <= target_size; ++target_idx) { | ||
| 209 | + dp[source_size][target_idx] = 0; | ||
| 210 | + } | ||
| 211 | + for (size_t source_idx = source_size; source_idx > 0U; --source_idx) { | ||
| 212 | + for (size_t target_idx = target_size; target_idx > 0U; --target_idx) { | ||
| 213 | + const auto source_pos = source_idx - 1U; | ||
| 214 | + const auto target_pos = target_idx - 1U; | ||
| 215 | + if ((source_size - source_pos) > (target_size - target_pos)) { | ||
| 216 | + continue; | ||
| 217 | + } | ||
| 218 | + const auto match_score = score_func(source_pos, target_pos) + dp[source_pos + 1U][target_pos + 1U]; | ||
| 219 | + const auto skip_score = dp[source_pos][target_pos + 1U]; | ||
| 220 | + dp[source_pos][target_pos] = std::max(match_score, skip_score); | ||
| 221 | + } | ||
| 222 | + } | ||
| 223 | + | ||
| 224 | + std::vector<size_t> target_indexes(source_size, target_size); | ||
| 225 | + size_t source_idx = 0U; | ||
| 226 | + size_t target_idx = 0U; | ||
| 227 | + while ((source_idx < source_size) && (target_idx < target_size)) { | ||
| 228 | + const auto match_score = score_func(source_idx, target_idx) + dp[source_idx + 1U][target_idx + 1U]; | ||
| 229 | + const auto skip_score = dp[source_idx][target_idx + 1U]; | ||
| 230 | + if (((target_size - target_idx - 1U) >= (source_size - source_idx)) && (skip_score >= match_score)) { | ||
| 231 | + ++target_idx; | ||
| 232 | + continue; | ||
| 233 | + } | ||
| 234 | + target_indexes[source_idx++] = target_idx++; | ||
| 235 | + } | ||
| 236 | + return target_indexes; | ||
| 237 | +} | ||
| 238 | + | ||
| 239 | +inline int64_t GetNextNoOpReshapeAxisId(const std::vector<AxisPtr> &graph_axis) { | ||
| 240 | + int64_t max_axis_id = -1; | ||
| 241 | + for (const auto &axis_info : graph_axis) { | ||
| 242 | + if (axis_info != nullptr) { | ||
| 243 | + max_axis_id = std::max(max_axis_id, axis_info->id); | ||
| 244 | + } | ||
| 245 | + } | ||
| 246 | + return max_axis_id + 1; | ||
| 247 | +} | ||
| 248 | + | ||
| 249 | +inline int64_t GetNextNoOpReshapeAxisId(const std::vector<int64_t> &graph_axis_ids) { | ||
| 250 | + int64_t max_axis_id = -1; | ||
| 251 | + for (const auto axis_id : graph_axis_ids) { | ||
| 252 | + max_axis_id = std::max(max_axis_id, axis_id); | ||
| 253 | + } | ||
| 254 | + return max_axis_id + 1; | ||
| 255 | +} | ||
| 256 | + | ||
| 257 | +inline std::vector<int64_t> CollectAxisIds(const std::vector<AxisPtr> &graph_axis) { | ||
| 258 | + std::vector<int64_t> axis_ids; | ||
| 259 | + axis_ids.reserve(graph_axis.size()); | ||
| 260 | + for (const auto &axis_info : graph_axis) { | ||
| 261 | + if (axis_info != nullptr) { | ||
| 262 | + axis_ids.push_back(axis_info->id); | ||
| 263 | + } | ||
| 264 | + } | ||
| 265 | + return axis_ids; | ||
| 266 | +} | ||
| 267 | + | ||
| 268 | +template <typename T> | ||
| 269 | +inline void SortUniqueVector(std::vector<T> &values) { | ||
| 270 | + std::sort(values.begin(), values.end()); | ||
| 271 | + values.erase(std::unique(values.begin(), values.end()), values.end()); | ||
| 272 | +} | ||
| 273 | + | ||
| 274 | +inline void ShiftAxisGroupFrom(const int64_t insert_axis_id, optimize::autoschedule::AxisGroup &axis_group) { | ||
| 275 | + auto shift_axis_ids = [insert_axis_id](std::vector<int64_t> &axis_ids) { | ||
| 276 | + for (auto &axis_id : axis_ids) { | ||
| 277 | + ShiftAxisIdFrom(insert_axis_id, axis_id); | ||
| 278 | + } | ||
| 279 | + SortUniqueVector(axis_ids); | ||
| 280 | + }; | ||
| 281 | + | ||
| 282 | + shift_axis_ids(axis_group.x_group); | ||
| 283 | + shift_axis_ids(axis_group.y_group); | ||
| 284 | + shift_axis_ids(axis_group.r_group); | ||
| 285 | + shift_axis_ids(axis_group.n_group); | ||
| 286 | + | ||
| 287 | + for (auto &axis_order : axis_group.axes_order) { | ||
| 288 | + if (axis_order >= static_cast<size_t>(insert_axis_id)) { | ||
| 289 | + ++axis_order; | ||
| 290 | + } | ||
| 291 | + } | ||
| 292 | + SortUniqueVector(axis_group.axes_order); | ||
| 293 | +} | ||
| 294 | + | ||
| 295 | +inline Status RefreshReshapeAxisGroupByInsertIndexes(const std::vector<int64_t> &axis_before_insert, | ||
| 296 | + const std::vector<size_t> &insert_indexes, | ||
| 297 | + optimize::autoschedule::AxisGroup &axis_group) { | ||
| 298 | + if (insert_indexes.empty() || axis_before_insert.empty() || axis_group.IsEmpty()) { | ||
| 299 | + return SUCCESS; | ||
| 300 | + } | ||
| 301 | + | ||
| 302 | + auto current_axis_ids = axis_before_insert; | ||
| 303 | + auto sorted_insert_indexes = insert_indexes; | ||
| 304 | + std::sort(sorted_insert_indexes.begin(), sorted_insert_indexes.end()); | ||
| 305 | + for (const auto insert_index : sorted_insert_indexes) { | ||
| 306 | + const auto insert_axis_id = (insert_index < current_axis_ids.size()) ? current_axis_ids[insert_index] | ||
| 307 | + : GetNextNoOpReshapeAxisId(current_axis_ids); | ||
| 308 | + ShiftAxisGroupFrom(insert_axis_id, axis_group); | ||
| 309 | + for (auto &axis_id : current_axis_ids) { | ||
| 310 | + ShiftAxisIdFrom(insert_axis_id, axis_id); | ||
| 311 | + } | ||
| 312 | + current_axis_ids.insert( | ||
| 313 | + current_axis_ids.begin() + static_cast<ptrdiff_t>(std::min(insert_index, current_axis_ids.size())), | ||
| 314 | + insert_axis_id); | ||
| 315 | + if (std::find(axis_group.y_group.begin(), axis_group.y_group.end(), insert_axis_id) == axis_group.y_group.end()) { | ||
| 316 | + axis_group.y_group.push_back(insert_axis_id); | ||
| 317 | + } | ||
| 318 | + if (std::find(axis_group.axes_order.begin(), axis_group.axes_order.end(), static_cast<size_t>(insert_axis_id)) == | ||
| 319 | + axis_group.axes_order.end()) { | ||
| 320 | + axis_group.axes_order.push_back(static_cast<size_t>(insert_axis_id)); | ||
| 321 | + } | ||
| 322 | + } | ||
| 323 | + | ||
| 324 | + SortUniqueVector(axis_group.x_group); | ||
| 325 | + SortUniqueVector(axis_group.y_group); | ||
| 326 | + SortUniqueVector(axis_group.r_group); | ||
| 327 | + SortUniqueVector(axis_group.n_group); | ||
| 328 | + SortUniqueVector(axis_group.axes_order); | ||
| 329 | + return SUCCESS; | ||
| 330 | +} | ||
| 331 | + | ||
| 332 | +inline Status RefreshReshapeAxisGroupByInsertedAxisIds(const std::vector<int64_t> &inserted_axis_ids, | ||
| 333 | + const std::vector<int64_t> &graph_axis_after_insert, | ||
| 334 | + optimize::autoschedule::AxisGroup &axis_group) { | ||
| 335 | + if (inserted_axis_ids.empty() || axis_group.IsEmpty()) { | ||
| 336 | + return SUCCESS; | ||
| 337 | + } | ||
| 338 | + | ||
| 339 | + for (const auto axis_id : inserted_axis_ids) { | ||
| 340 | + if (std::find(axis_group.y_group.begin(), axis_group.y_group.end(), axis_id) == axis_group.y_group.end()) { | ||
| 341 | + axis_group.y_group.push_back(axis_id); | ||
| 342 | + } | ||
| 343 | + } | ||
| 344 | + axis_group.axes_order.clear(); | ||
| 345 | + axis_group.axes_order.reserve(graph_axis_after_insert.size()); | ||
| 346 | + for (const auto axis_id : graph_axis_after_insert) { | ||
| 347 | + axis_group.axes_order.push_back(static_cast<size_t>(axis_id)); | ||
| 348 | + } | ||
| 349 | + SortUniqueVector(axis_group.y_group); | ||
| 350 | + return SUCCESS; | ||
| 351 | +} | ||
| 352 | + | ||
| 353 | +inline std::vector<int64_t> CollectInsertedAxisIds(const std::vector<int64_t> &axis_before_insert, | ||
| 354 | + const std::vector<int64_t> &axis_after_insert) { | ||
| 355 | + std::vector<int64_t> inserted_axis_ids; | ||
| 356 | + for (const auto axis_id : axis_after_insert) { | ||
| 357 | + if (std::find(axis_before_insert.begin(), axis_before_insert.end(), axis_id) == axis_before_insert.end()) { | ||
| 358 | + inserted_axis_ids.push_back(axis_id); | ||
| 359 | + } | ||
| 360 | + } | ||
| 361 | + return inserted_axis_ids; | ||
| 362 | +} | ||
| 363 | + | ||
| 364 | +inline void CopyTensorAttrs(const AscTensorAttr &src_attr, AscTensorAttr &dst_attr) { | ||
| 365 | + dst_attr.axis = src_attr.axis; | ||
| 366 | + dst_attr.repeats = src_attr.repeats; | ||
| 367 | + dst_attr.strides = src_attr.strides; | ||
| 368 | +} | ||
| 369 | + | ||
| 370 | +inline void DumpTensorAttrs(const char *stage, const NodePtr &node, const AscTensorAttr &tensor_attr) { | ||
| 371 | + GELOGD("%s node %s(%s) tensor attr axis:%s, repeats:%s, strides:%s.", stage, node->GetNamePtr(), | ||
| 372 | + node->GetType().c_str(), AutofuseUtils::VectorToStr(tensor_attr.axis).c_str(), | ||
| 373 | + AutofuseUtils::VectorToStr(tensor_attr.repeats).c_str(), | ||
| 374 | + AutofuseUtils::VectorToStr(tensor_attr.strides).c_str()); | ||
| 375 | +} | ||
| 376 | + | ||
| 377 | +inline void ReorderGraphAxesToOriginalOrder(std::vector<AxisPtr> &axis) { | ||
| 378 | + std::stable_sort(axis.begin(), axis.end(), [](const AxisPtr &lhs, const AxisPtr &rhs) { | ||
| 379 | + if ((lhs == nullptr) || (rhs == nullptr)) { | ||
| 380 | + return lhs != nullptr; | ||
| 381 | + } | ||
| 382 | + return lhs->id < rhs->id; | ||
| 383 | + }); | ||
| 384 | +} | ||
| 385 | + | ||
| 386 | +inline void ReorderAxisIdsByGraphOrder(const std::vector<int64_t> &graph_axis_order, std::vector<int64_t> &axis) { | ||
| 387 | + std::vector<int64_t> reordered_axis; | ||
| 388 | + for (const auto graph_axis_id : graph_axis_order) { | ||
| 389 | + auto it = std::find(axis.begin(), axis.end(), graph_axis_id); | ||
| 390 | + if (it != axis.end()) { | ||
| 391 | + reordered_axis.push_back(graph_axis_id); | ||
| 392 | + } | ||
| 393 | + } | ||
| 394 | + for (const auto axis_id : axis) { | ||
| 395 | + if (std::find(graph_axis_order.begin(), graph_axis_order.end(), axis_id) == graph_axis_order.end()) { | ||
| 396 | + reordered_axis.push_back(axis_id); | ||
| 397 | + } | ||
| 398 | + } | ||
| 399 | + axis = reordered_axis; | ||
| 400 | +} | ||
| 401 | + | ||
| 402 | +inline void ReorderTensorAttrsByGraphOrder(const std::vector<int64_t> &graph_axis_order, AscTensorAttr &tensor_attr) { | ||
| 403 | + if (tensor_attr.axis.empty()) { | ||
| 404 | + return; | ||
| 405 | + } | ||
| 406 | + if ((tensor_attr.repeats.size() != tensor_attr.axis.size()) || | ||
| 407 | + (tensor_attr.strides.size() != tensor_attr.axis.size())) { | ||
| 408 | + return; | ||
| 409 | + } | ||
| 410 | + AscTensorAttr reordered_attr = tensor_attr; | ||
| 411 | + reordered_attr.axis.clear(); | ||
| 412 | + reordered_attr.repeats.clear(); | ||
| 413 | + reordered_attr.strides.clear(); | ||
| 414 | + for (const auto graph_axis_id : graph_axis_order) { | ||
| 415 | + auto it = std::find(tensor_attr.axis.begin(), tensor_attr.axis.end(), graph_axis_id); | ||
| 416 | + if (it == tensor_attr.axis.end()) { | ||
| 417 | + continue; | ||
| 418 | + } | ||
| 419 | + const auto idx = static_cast<size_t>(std::distance(tensor_attr.axis.begin(), it)); | ||
| 420 | + reordered_attr.axis.push_back(tensor_attr.axis[idx]); | ||
| 421 | + reordered_attr.repeats.push_back(tensor_attr.repeats[idx]); | ||
| 422 | + reordered_attr.strides.push_back(tensor_attr.strides[idx]); | ||
| 423 | + } | ||
| 424 | + for (size_t i = 0U; i < tensor_attr.axis.size(); ++i) { | ||
| 425 | + if (std::find(graph_axis_order.begin(), graph_axis_order.end(), tensor_attr.axis[i]) != graph_axis_order.end()) { | ||
| 426 | + continue; | ||
| 427 | + } | ||
| 428 | + reordered_attr.axis.push_back(tensor_attr.axis[i]); | ||
| 429 | + reordered_attr.repeats.push_back(tensor_attr.repeats[i]); | ||
| 430 | + reordered_attr.strides.push_back(tensor_attr.strides[i]); | ||
| 431 | + } | ||
| 432 | + CopyTensorAttrs(reordered_attr, tensor_attr); | ||
| 433 | +} | ||
| 434 | + | ||
| 435 | +inline Status ReorderAscGraphAttrsByGraphOrder(const AscGraph &asc_graph, | ||
| 436 | + const std::vector<int64_t> &graph_axis_order) { | ||
| 437 | + for (const auto &node : AscGraphUtils::GetComputeGraph(asc_graph)->GetAllNodes()) { | ||
| 438 | + const auto &op_desc = node->GetOpDesc(); | ||
| 439 | + GE_ASSERT_NOTNULL(op_desc); | ||
| 440 | + auto node_attr = op_desc->GetAttrsGroup<AscNodeAttr>(); | ||
| 441 | + if (node_attr != nullptr) { | ||
| 442 | + ReorderAxisIdsByGraphOrder(graph_axis_order, node_attr->sched.axis); | ||
| 443 | + } | ||
| 444 | + for (size_t i = 0U; i < node->GetAllOutDataAnchorsSize(); ++i) { | ||
| 445 | + const auto output_tensor_desc = op_desc->MutableOutputDesc(i); | ||
| 446 | + GE_ASSERT_NOTNULL(output_tensor_desc); | ||
| 447 | + auto tensor_attr = output_tensor_desc->GetAttrsGroup<AscTensorAttr>(); | ||
| 448 | + if (tensor_attr == nullptr) { | ||
| 449 | + continue; | ||
| 450 | + } | ||
| 451 | + ReorderTensorAttrsByGraphOrder(graph_axis_order, *tensor_attr); | ||
| 452 | + } | ||
| 453 | + } | ||
| 454 | + return SUCCESS; | ||
| 455 | +} | ||
| 456 | + | ||
| 457 | +inline Status ReorderAscGraphAttrsByCurrentGraphOrder(const AscGraph &asc_graph, const AscGraphAttr &graph_attr) { | ||
| 458 | + std::vector<int64_t> graph_axis_order; | ||
| 459 | + graph_axis_order.reserve(graph_attr.axis.size()); | ||
| 460 | + for (const auto &axis_info : graph_attr.axis) { | ||
| 461 | + GE_ASSERT_NOTNULL(axis_info); | ||
| 462 | + graph_axis_order.push_back(axis_info->id); | ||
| 463 | + } | ||
| 464 | + GE_ASSERT_SUCCESS(ReorderAscGraphAttrsByGraphOrder(asc_graph, graph_axis_order)); | ||
| 465 | + return SUCCESS; | ||
| 466 | +} | ||
| 467 | + | ||
| 468 | +inline bool BuildTargetToTensorIndexByGraphOrder(const std::vector<int64_t> &graph_axis_order, | ||
| 469 | + const AscTensorAttr &tensor_attr, | ||
| 470 | + std::vector<size_t> &target_to_tensor_index) { | ||
| 471 | + const auto matched_target_indexes = | ||
| 472 | + BuildBestOverlapTargetIndexes(tensor_attr.axis.size(), graph_axis_order.size(), | ||
| 473 | + [&tensor_attr, &graph_axis_order](size_t source_idx, size_t target_idx) -> int32_t { | ||
| 474 | + return tensor_attr.axis[source_idx] == graph_axis_order[target_idx] ? 1 : 0; | ||
| 475 | + }); | ||
| 476 | + if (matched_target_indexes.size() != tensor_attr.axis.size()) { | ||
| 477 | + return false; | ||
| 478 | + } | ||
| 479 | + | ||
| 480 | + const size_t kInvalidIndex = graph_axis_order.size(); | ||
| 481 | + target_to_tensor_index.assign(graph_axis_order.size(), kInvalidIndex); | ||
| 482 | + for (size_t tensor_axis_idx = 0U; tensor_axis_idx < matched_target_indexes.size(); ++tensor_axis_idx) { | ||
| 483 | + target_to_tensor_index[matched_target_indexes[tensor_axis_idx]] = tensor_axis_idx; | ||
| 484 | + } | ||
| 485 | + return true; | ||
| 486 | +} | ||
| 487 | + | ||
| 488 | +inline bool AppendCompletedTensorAxisByGraphOrder(const size_t target_idx, const size_t kInvalidIndex, | ||
| 489 | + const std::vector<int64_t> &graph_axis_order, | ||
| 490 | + const AscTensorAttr &tensor_attr, AscTensorAttr &completed_attr, | ||
| 491 | + std::vector<int64_t> &inserted_axis_ids) { | ||
| 492 | + if (target_idx != kInvalidIndex) { | ||
| 493 | + completed_attr.axis.push_back(tensor_attr.axis[target_idx]); | ||
| 494 | + if (!tensor_attr.repeats.empty()) { | ||
| 495 | + completed_attr.repeats.push_back(tensor_attr.repeats[target_idx]); | ||
| 496 | + } | ||
| 497 | + if (!tensor_attr.strides.empty()) { | ||
| 498 | + completed_attr.strides.push_back(tensor_attr.strides[target_idx]); | ||
| 499 | + } | ||
| 500 | + return false; | ||
| 501 | + } | ||
| 502 | + const auto graph_axis_id = graph_axis_order[completed_attr.axis.size()]; | ||
| 503 | + completed_attr.axis.push_back(graph_axis_id); | ||
| 504 | + if (!tensor_attr.repeats.empty()) { | ||
| 505 | + completed_attr.repeats.push_back(kSymbolOne); | ||
| 506 | + } | ||
| 507 | + if (!tensor_attr.strides.empty()) { | ||
| 508 | + completed_attr.strides.push_back(kSymbolZero); | ||
| 509 | + } | ||
| 510 | + inserted_axis_ids.push_back(graph_axis_id); | ||
| 511 | + return true; | ||
| 512 | +} | ||
| 513 | + | ||
| 514 | +inline void CompleteTensorAttrsByGraphOrderPreserveStrides(const NodePtr &node, const size_t output_idx, | ||
| 515 | + const std::vector<int64_t> &graph_axis_order, | ||
| 516 | + AscTensorAttr &tensor_attr) { | ||
| 517 | + const auto old_axis = tensor_attr.axis; | ||
| 518 | + std::vector<int64_t> inserted_axis_ids; | ||
| 519 | + if (tensor_attr.axis.size() >= graph_axis_order.size()) { | ||
| 520 | + return; | ||
| 521 | + } | ||
| 522 | + | ||
| 523 | + std::vector<size_t> target_to_tensor_index; | ||
| 524 | + if (!BuildTargetToTensorIndexByGraphOrder(graph_axis_order, tensor_attr, target_to_tensor_index)) { | ||
| 525 | + return; | ||
| 526 | + } | ||
| 527 | + | ||
| 528 | + AscTensorAttr completed_attr = tensor_attr; | ||
| 529 | + completed_attr.axis.clear(); | ||
| 530 | + if (!tensor_attr.repeats.empty()) { | ||
| 531 | + completed_attr.repeats.clear(); | ||
| 532 | + } | ||
| 533 | + if (!tensor_attr.strides.empty()) { | ||
| 534 | + completed_attr.strides.clear(); | ||
| 535 | + } | ||
| 536 | + const size_t kInvalidIndex = graph_axis_order.size(); | ||
| 537 | + for (size_t i = 0U; i < graph_axis_order.size(); ++i) { | ||
| 538 | + if (AppendCompletedTensorAxisByGraphOrder(target_to_tensor_index[i], kInvalidIndex, graph_axis_order, tensor_attr, | ||
| 539 | + completed_attr, inserted_axis_ids)) { | ||
| 540 | + GELOGD("node %s(%s) output %zu complete preserve tensor attrs with reshape axis id %ld at graph axis idx %zu.", | ||
| 541 | + node->GetNamePtr(), node->GetType().c_str(), output_idx, graph_axis_order[i], i); | ||
| 542 | + } | ||
| 543 | + } | ||
| 544 | + CopyTensorAttrs(completed_attr, tensor_attr); | ||
| 545 | + if (!inserted_axis_ids.empty()) { | ||
| 546 | + GELOGD("node %s(%s) output %zu complete preserve tensor attrs with reshape axes %s, axis from %s to %s.", | ||
| 547 | + node->GetNamePtr(), node->GetType().c_str(), output_idx, | ||
| 548 | + AutofuseUtils::VectorToStr(inserted_axis_ids).c_str(), AutofuseUtils::VectorToStr(old_axis).c_str(), | ||
| 549 | + AutofuseUtils::VectorToStr(tensor_attr.axis).c_str()); | ||
| 550 | + } | ||
| 551 | +} | ||
| 552 | + | ||
| 553 | +inline Status InsertNoOpAxisByGraphOrder(const std::vector<int64_t> &graph_axis_order, const int64_t axis_id, | ||
| 554 | + std::vector<int64_t> &axis, std::vector<Expression> *repeats = nullptr, | ||
| 555 | + std::vector<Expression> *strides = nullptr) { | ||
| 556 | + if (std::find(axis.begin(), axis.end(), axis_id) != axis.end()) { | ||
| 557 | + return SUCCESS; | ||
| 558 | + } | ||
| 559 | + const auto graph_axis_it = std::find(graph_axis_order.begin(), graph_axis_order.end(), axis_id); | ||
| 560 | + GE_ASSERT_TRUE(graph_axis_it != graph_axis_order.end()); | ||
| 561 | + const auto insert_it = std::find_if(axis.begin(), axis.end(), [&graph_axis_order, graph_axis_it](const auto axis_id) { | ||
| 562 | + const auto current_graph_axis_it = std::find(graph_axis_order.begin(), graph_axis_order.end(), axis_id); | ||
| 563 | + return (current_graph_axis_it != graph_axis_order.end()) && (current_graph_axis_it > graph_axis_it); | ||
| 564 | + }); | ||
| 565 | + const auto insert_index = static_cast<size_t>(std::distance(axis.begin(), insert_it)); | ||
| 566 | + axis.insert(insert_it, axis_id); | ||
| 567 | + if ((repeats != nullptr) && !repeats->empty()) { | ||
| 568 | + GE_ASSERT_TRUE(insert_index <= repeats->size()); | ||
| 569 | + repeats->insert(repeats->begin() + static_cast<ptrdiff_t>(insert_index), kSymbolOne); | ||
| 570 | + } | ||
| 571 | + if ((strides != nullptr) && !strides->empty()) { | ||
| 572 | + GE_ASSERT_TRUE(insert_index <= strides->size()); | ||
| 573 | + strides->insert(strides->begin() + static_cast<ptrdiff_t>(insert_index), kSymbolZero); | ||
| 574 | + } | ||
| 575 | + return SUCCESS; | ||
| 576 | +} | ||
| 577 | + | ||
| 578 | +inline Status CompleteTensorAttrsByInsertedAxisIdsPreserveOrder(const NodePtr &node, const size_t output_idx, | ||
| 579 | + const std::vector<int64_t> &graph_axis_order, | ||
| 580 | + const std::vector<int64_t> &inserted_axis_ids, | ||
| 581 | + AscTensorAttr &tensor_attr) { | ||
| 582 | + const auto old_axis = tensor_attr.axis; | ||
| 583 | + if (tensor_attr.axis.empty()) { | ||
| 584 | + return SUCCESS; | ||
| 585 | + } | ||
| 586 | + for (const auto axis_id : inserted_axis_ids) { | ||
| 587 | + GE_ASSERT_SUCCESS(InsertNoOpAxisByGraphOrder(graph_axis_order, axis_id, tensor_attr.axis, &tensor_attr.repeats, | ||
| 588 | + &tensor_attr.strides)); | ||
| 589 | + } | ||
| 590 | + if (old_axis != tensor_attr.axis) { | ||
| 591 | + GELOGD("node %s(%s) output %zu complete preserve tensor attrs with reshape axes %s, axis from %s to %s.", | ||
| 592 | + node->GetNamePtr(), node->GetType().c_str(), output_idx, | ||
| 593 | + AutofuseUtils::VectorToStr(inserted_axis_ids).c_str(), AutofuseUtils::VectorToStr(old_axis).c_str(), | ||
| 594 | + AutofuseUtils::VectorToStr(tensor_attr.axis).c_str()); | ||
| 595 | + } | ||
| 596 | + return SUCCESS; | ||
| 597 | +} | ||
| 598 | + | ||
| 599 | +inline Status UpdateTensorAttrsPreserveStrides(const NodePtr &node, const std::vector<int64_t> &axis, | ||
| 600 | + const std::vector<Expression> &repeats) { | ||
| 601 | + const auto &op_desc = node->GetOpDesc(); | ||
| 602 | + GE_ASSERT_NOTNULL(op_desc); | ||
| 603 | + for (size_t i = 0U; i < node->GetAllOutDataAnchorsSize(); ++i) { | ||
| 604 | + const auto output_tensor_desc = op_desc->MutableOutputDesc(i); | ||
| 605 | + GE_ASSERT_NOTNULL(output_tensor_desc); | ||
| 606 | + auto tensor_attr = output_tensor_desc->GetAttrsGroup<AscTensorAttr>(); | ||
| 607 | + GE_ASSERT_NOTNULL(tensor_attr); | ||
| 608 | + if (node->GetType() == kScalarType) { | ||
| 609 | + tensor_attr->axis = axis; | ||
| 610 | + tensor_attr->repeats.assign(axis.size(), kSymbolOne); | ||
| 611 | + tensor_attr->strides.assign(axis.size(), kSymbolZero); | ||
| 612 | + continue; | ||
| 613 | + } | ||
| 614 | + if ((tensor_attr->axis.empty()) && (node->GetType() != kDataType)) { | ||
| 615 | + GE_ASSERT_SUCCESS(UpdateTensorAttrsIfEmpty(node, tensor_attr, axis, repeats)); | ||
| 616 | + continue; | ||
| 617 | + } | ||
| 618 | + CompleteTensorAttrsByGraphOrderPreserveStrides(node, i, axis, *tensor_attr); | ||
| 619 | + GELOGD("after preserve attrs: node %s(%s), axis:%s, repeats:%s stride:%s.", node->GetNamePtr(), | ||
| 620 | + node->GetType().c_str(), AutofuseUtils::VectorToStr(tensor_attr->axis).c_str(), | ||
| 621 | + AutofuseUtils::VectorToStr(tensor_attr->repeats).c_str(), | ||
| 622 | + AutofuseUtils::VectorToStr(tensor_attr->strides).c_str()); | ||
| 623 | + } | ||
| 624 | + return SUCCESS; | ||
| 625 | +} | ||
| 626 | + | ||
| 627 | +inline Status UpdateTensorAttrsByInsertedAxisIdsPreserveOrder(const NodePtr &node, const std::vector<int64_t> &axis, | ||
| 628 | + const std::vector<Expression> &repeats, | ||
| 629 | + const std::vector<int64_t> &inserted_axis_ids) { | ||
| 630 | + const auto &op_desc = node->GetOpDesc(); | ||
| 631 | + GE_ASSERT_NOTNULL(op_desc); | ||
| 632 | + for (size_t i = 0U; i < node->GetAllOutDataAnchorsSize(); ++i) { | ||
| 633 | + const auto output_tensor_desc = op_desc->MutableOutputDesc(i); | ||
| 634 | + GE_ASSERT_NOTNULL(output_tensor_desc); | ||
| 635 | + auto tensor_attr = output_tensor_desc->GetAttrsGroup<AscTensorAttr>(); | ||
| 636 | + GE_ASSERT_NOTNULL(tensor_attr); | ||
| 637 | + if (node->GetType() == kScalarType) { | ||
| 638 | + tensor_attr->axis = axis; | ||
| 639 | + tensor_attr->repeats.assign(axis.size(), kSymbolOne); | ||
| 640 | + tensor_attr->strides.assign(axis.size(), kSymbolZero); | ||
| 641 | + continue; | ||
| 642 | + } | ||
| 643 | + if ((tensor_attr->axis.empty()) && (node->GetType() != kDataType)) { | ||
| 644 | + GE_ASSERT_SUCCESS(UpdateTensorAttrsIfEmpty(node, tensor_attr, axis, repeats)); | ||
| 645 | + continue; | ||
| 646 | + } | ||
| 647 | + GE_ASSERT_SUCCESS( | ||
| 648 | + CompleteTensorAttrsByInsertedAxisIdsPreserveOrder(node, i, axis, inserted_axis_ids, *tensor_attr)); | ||
| 649 | + GELOGD("after preserve attrs: node %s(%s), axis:%s, repeats:%s stride:%s.", node->GetNamePtr(), | ||
| 650 | + node->GetType().c_str(), AutofuseUtils::VectorToStr(tensor_attr->axis).c_str(), | ||
| 651 | + AutofuseUtils::VectorToStr(tensor_attr->repeats).c_str(), | ||
| 652 | + AutofuseUtils::VectorToStr(tensor_attr->strides).c_str()); | ||
| 653 | + } | ||
| 654 | + return SUCCESS; | ||
| 655 | +} | ||
| 656 | + | ||
| 657 | +inline bool IsAxisSubsequence(const std::vector<int64_t> &axis, const std::vector<int64_t> &target_axis) { | ||
| 658 | + size_t target_idx = 0U; | ||
| 659 | + for (const auto axis_id : axis) { | ||
| 660 | + while ((target_idx < target_axis.size()) && (target_axis[target_idx] != axis_id)) { | ||
| 661 | + ++target_idx; | ||
| 662 | + } | ||
| 663 | + if (target_idx >= target_axis.size()) { | ||
| 664 | + return false; | ||
| 665 | + } | ||
| 666 | + ++target_idx; | ||
| 667 | + } | ||
| 668 | + return true; | ||
| 669 | +} | ||
| 670 | + | ||
| 671 | +inline void CompleteGatherInputTensorAttrsByTargetAxis(const std::vector<int64_t> &target_axis, | ||
| 672 | + AscTensorAttr &tensor_attr) { | ||
| 673 | + std::unordered_map<int64_t, size_t> axis_to_index; | ||
| 674 | + for (size_t i = 0U; i < tensor_attr.axis.size(); ++i) { | ||
| 675 | + axis_to_index[tensor_attr.axis[i]] = i; | ||
| 676 | + } | ||
| 677 | + | ||
| 678 | + AscTensorAttr completed_attr = tensor_attr; | ||
| 679 | + completed_attr.axis.clear(); | ||
| 680 | + completed_attr.repeats.clear(); | ||
| 681 | + completed_attr.strides.clear(); | ||
| 682 | + for (const auto axis_id : target_axis) { | ||
| 683 | + completed_attr.axis.push_back(axis_id); | ||
| 684 | + const auto iter = axis_to_index.find(axis_id); | ||
| 685 | + if (iter != axis_to_index.end()) { | ||
| 686 | + const auto idx = iter->second; | ||
| 687 | + completed_attr.repeats.push_back(idx < tensor_attr.repeats.size() ? tensor_attr.repeats[idx] : kSymbolOne); | ||
| 688 | + completed_attr.strides.push_back(idx < tensor_attr.strides.size() ? tensor_attr.strides[idx] : kSymbolZero); | ||
| 689 | + } else { | ||
| 690 | + completed_attr.repeats.push_back(kSymbolOne); | ||
| 691 | + completed_attr.strides.push_back(kSymbolZero); | ||
| 692 | + } | ||
| 693 | + } | ||
| 694 | + CopyTensorAttrs(completed_attr, tensor_attr); | ||
| 695 | +} | ||
| 696 | + | ||
| 697 | +inline void CompleteGatherInputTensorAttrsByDimOrder(const std::vector<int64_t> &target_axis, | ||
| 698 | + AscTensorAttr &tensor_attr) { | ||
| 699 | + AscTensorAttr completed_attr = tensor_attr; | ||
| 700 | + completed_attr.axis = target_axis; | ||
| 701 | + for (size_t i = 0U; i < completed_attr.axis.size(); ++i) { | ||
| 702 | + if (i >= completed_attr.repeats.size()) { | ||
| 703 | + completed_attr.repeats.push_back(kSymbolOne); | ||
| 704 | + } | ||
| 705 | + if (i >= completed_attr.strides.size()) { | ||
| 706 | + completed_attr.strides.push_back(kSymbolZero); | ||
| 707 | + } | ||
| 708 | + } | ||
| 709 | + completed_attr.repeats.resize(completed_attr.axis.size()); | ||
| 710 | + completed_attr.strides.resize(completed_attr.axis.size()); | ||
| 711 | + CopyTensorAttrs(completed_attr, tensor_attr); | ||
| 712 | +} | ||
| 713 | + | ||
| 714 | +inline void CompleteGatherInputTensorAttrsByAxes(const std::vector<int64_t> &target_axis, AscTensorAttr &tensor_attr) { | ||
| 715 | + if (IsAxisSubsequence(tensor_attr.axis, target_axis)) { | ||
| 716 | + CompleteGatherInputTensorAttrsByTargetAxis(target_axis, tensor_attr); | ||
| 717 | + return; | ||
| 718 | + } | ||
| 719 | + CompleteGatherInputTensorAttrsByDimOrder(target_axis, tensor_attr); | ||
| 720 | +} | ||
| 721 | + | ||
| 722 | +inline Status GetGatherInputDataNodes(const NodePtr &gather_node, NodePtr ¶ms_data_node, | ||
| 723 | + NodePtr &indices_data_node) { | ||
| 724 | + std::vector<NodePtr> peer_out_nodes; | ||
| 725 | + GE_ASSERT_SUCCESS(asc_adapt::GetPeerOutNodes(gather_node, peer_out_nodes)); | ||
| 726 | + GE_ASSERT_TRUE(peer_out_nodes.size() == 2U); | ||
| 727 | + params_data_node = peer_out_nodes[0]; | ||
| 728 | + indices_data_node = peer_out_nodes[1]; | ||
| 729 | + return SUCCESS; | ||
| 730 | +} | ||
| 731 | + | ||
| 732 | +inline bool IsGatherFuseType(const NodePtr &asc_node) { | ||
| 733 | + const auto autofuse_attr = BackendUtils::GetNodeAutoFuseAttr(asc_node); | ||
| 734 | + return (autofuse_attr != nullptr) && autofuse_attr->HasFuseType(loop::FuseType::kGather); | ||
| 735 | +} | ||
| 736 | + | ||
| 737 | +inline Status GetGatherReplacementAxisIndex(const NodePtr &gather_node, const AscTensorAttr ¶ms_attr, | ||
| 738 | + const AscTensorAttr &indices_attr, const AscTensorAttr &gather_output_attr, | ||
| 739 | + size_t &replacement_axis_index) { | ||
| 740 | + (void)indices_attr; | ||
| 741 | + int64_t gather_axis_index = 0; | ||
| 742 | + GE_ASSERT_SUCCESS(asc_adapt::GetGatherAxis(gather_node, gather_axis_index)); | ||
| 743 | + GE_ASSERT_TRUE(gather_axis_index >= 0); | ||
| 744 | + GE_ASSERT_TRUE(static_cast<size_t>(gather_axis_index) < params_attr.axis.size()); | ||
| 745 | + const auto replacement_axis_id = params_attr.axis[static_cast<size_t>(gather_axis_index)]; | ||
| 746 | + const auto iter = std::find(gather_output_attr.axis.begin(), gather_output_attr.axis.end(), replacement_axis_id); | ||
| 747 | + GE_ASSERT_TRUE(iter != gather_output_attr.axis.end()); | ||
| 748 | + replacement_axis_index = static_cast<size_t>(std::distance(gather_output_attr.axis.begin(), iter)); | ||
| 749 | + if (replacement_axis_index != static_cast<size_t>(gather_axis_index)) { | ||
| 750 | + GE_ASSERT_SUCCESS(asc_adapt::SetGatherAxis(gather_node, static_cast<int64_t>(replacement_axis_index))); | ||
| 751 | + } | ||
| 752 | + return SUCCESS; | ||
| 753 | +} | ||
| 754 | + | ||
| 755 | +inline Status CompleteGatherInputAttrsPreserveStrides(const AscGraph &asc_graph, const NodePtr &gather_node) { | ||
| 756 | + NodePtr params_data_node = nullptr; | ||
| 757 | + NodePtr indices_data_node = nullptr; | ||
| 758 | + GE_ASSERT_SUCCESS(GetGatherInputDataNodes(gather_node, params_data_node, indices_data_node)); | ||
| 759 | + AscTensorAttr *gather_output_attr = nullptr; | ||
| 760 | + GE_ASSERT_SUCCESS(asc_adapt::GetOutputTensorAttr(gather_node, gather_output_attr)); | ||
| 761 | + AscTensorAttr *params_attr = nullptr; | ||
| 762 | + GE_ASSERT_SUCCESS(asc_adapt::GetOutputTensorAttr(params_data_node, params_attr)); | ||
| 763 | + AscTensorAttr *indices_attr = nullptr; | ||
| 764 | + GE_ASSERT_SUCCESS(asc_adapt::GetOutputTensorAttr(indices_data_node, indices_attr)); | ||
| 765 | + if ((gather_output_attr->axis.empty()) || (params_attr->axis.empty()) || (indices_attr->axis.empty())) { | ||
| 766 | + return SUCCESS; | ||
| 767 | + } | ||
| 768 | + | ||
| 769 | + size_t replacement_axis_index = 0U; | ||
| 770 | + GE_ASSERT_SUCCESS(GetGatherReplacementAxisIndex(gather_node, *params_attr, *indices_attr, *gather_output_attr, | ||
| 771 | + replacement_axis_index)); | ||
| 772 | + GE_ASSERT_TRUE(replacement_axis_index + indices_attr->axis.size() <= gather_output_attr->axis.size()); | ||
| 773 | + GELOGD("node %s(%s) complete gather input attrs in graph %s, replacement_axis_index:%zu.", gather_node->GetNamePtr(), | ||
| 774 | + gather_node->GetType().c_str(), asc_graph.GetName().c_str(), replacement_axis_index); | ||
| 775 | + DumpTensorAttrs("before complete gather output", gather_node, *gather_output_attr); | ||
| 776 | + DumpTensorAttrs("before complete gather params", params_data_node, *params_attr); | ||
| 777 | + DumpTensorAttrs("before complete gather indices", indices_data_node, *indices_attr); | ||
| 778 | + | ||
| 779 | + std::vector<int64_t> params_axis; | ||
| 780 | + std::vector<int64_t> indices_axis; | ||
| 781 | + for (size_t i = 0U; i < gather_output_attr->axis.size(); ++i) { | ||
| 782 | + if (i == replacement_axis_index) { | ||
| 783 | + params_axis.push_back(gather_output_attr->axis[i]); | ||
| 784 | + indices_axis.push_back(gather_output_attr->axis[i]); | ||
| 785 | + } else if ((i > replacement_axis_index) && (i < replacement_axis_index + indices_attr->axis.size())) { | ||
| 786 | + indices_axis.push_back(gather_output_attr->axis[i]); | ||
| 787 | + } else { | ||
| 788 | + params_axis.push_back(gather_output_attr->axis[i]); | ||
| 789 | + } | ||
| 790 | + } | ||
| 791 | + GELOGI("node %s(%s) complete gather params axis from %s to %s in graph %s.", params_data_node->GetNamePtr(), | ||
| 792 | + params_data_node->GetType().c_str(), AutofuseUtils::VectorToStr(params_attr->axis).c_str(), | ||
| 793 | + AutofuseUtils::VectorToStr(params_axis).c_str(), asc_graph.GetName().c_str()); | ||
| 794 | + GELOGI("node %s(%s) complete gather indices axis from %s to %s in graph %s.", indices_data_node->GetNamePtr(), | ||
| 795 | + indices_data_node->GetType().c_str(), AutofuseUtils::VectorToStr(indices_attr->axis).c_str(), | ||
| 796 | + AutofuseUtils::VectorToStr(indices_axis).c_str(), asc_graph.GetName().c_str()); | ||
| 797 | + CompleteGatherInputTensorAttrsByAxes(params_axis, *params_attr); | ||
| 798 | + CompleteGatherInputTensorAttrsByAxes(indices_axis, *indices_attr); | ||
| 799 | + DumpTensorAttrs("after complete gather params", params_data_node, *params_attr); | ||
| 800 | + DumpTensorAttrs("after complete gather indices", indices_data_node, *indices_attr); | ||
| 801 | + return SUCCESS; | ||
| 802 | +} | ||
| 803 | + | ||
| 804 | +inline Status CompleteGatherInputAttrsOnAscGraphPreserveStrides(const AscGraph &asc_graph) { | ||
| 805 | + for (const auto &node : AscGraphUtils::GetComputeGraph(asc_graph)->GetAllNodes()) { | ||
| 806 | + if (node->GetType() != kGatherType) { | ||
| 807 | + continue; | ||
| 808 | + } | ||
| 809 | + GE_ASSERT_SUCCESS(CompleteGatherInputAttrsPreserveStrides(asc_graph, node)); | ||
| 810 | + } | ||
| 811 | + return SUCCESS; | ||
| 812 | +} | ||
| 813 | + | ||
| 814 | +inline Status CompleteNodeAttrsOnAscGraphPreserveStrides(AscGraph &asc_graph, const NodePtr &asc_node) { | ||
| 815 | + const auto is_gather_fuse_type = IsGatherFuseType(asc_node); | ||
| 816 | + TensorAttrInfo graph_attr; | ||
| 817 | + GE_ASSERT_SUCCESS(BackendUtils::GetGraphAttrInfo(asc_graph, graph_attr)); | ||
| 818 | + GELOGI("max sched axis %s in graph %s, preserve tensor strides.", AutofuseUtils::VectorToStr(graph_attr.axis).c_str(), | ||
| 819 | + asc_graph.GetName().c_str()); | ||
| 820 | + | ||
| 821 | + for (const auto &node : AscGraphUtils::GetComputeGraph(asc_graph)->GetAllNodes()) { | ||
| 822 | + if (IsTorchDataType(node)) { | ||
| 823 | + GELOGI("torch node %s(%s) not complete node attr.", node->GetNamePtr(), node->GetType().c_str()); | ||
| 824 | + continue; | ||
| 825 | + } | ||
| 826 | + if (IsCubeRelatedAscNode(node)) { | ||
| 827 | + GELOGI("cube related node %s(%s) not complete node attr.", node->GetNamePtr(), node->GetType().c_str()); | ||
| 828 | + continue; | ||
| 829 | + } | ||
| 830 | + if (((!is_gather_fuse_type) || (!IsGatherData(node))) && (!BackendUtils::IsOutputNode(node))) { | ||
| 831 | + GE_ASSERT_SUCCESS(UpdateTensorAttrsPreserveStrides(node, graph_attr.axis, graph_attr.repeats)); | ||
| 832 | + } | ||
| 833 | + const auto &op_desc = node->GetOpDesc(); | ||
| 834 | + GE_ASSERT_NOTNULL(op_desc); | ||
| 835 | + auto node_attr = op_desc->GetAttrsGroup<AscNodeAttr>(); | ||
| 836 | + GE_ASSERT_NOTNULL(node_attr); | ||
| 837 | + GELOGI("node %s(%s) before complete sched axis %s to %s in graph %s, preserve tensor strides.", node->GetNamePtr(), | ||
| 838 | + node->GetType().c_str(), AutofuseUtils::VectorToStr(node_attr->sched.axis).c_str(), | ||
| 839 | + AutofuseUtils::VectorToStr(graph_attr.axis).c_str(), asc_graph.GetName().c_str()); | ||
| 840 | + node_attr->sched.axis = graph_attr.axis; | ||
| 841 | + GELOGI("node %s(%s) after complete sched axis %s to %s in graph %s, preserve tensor strides.", node->GetNamePtr(), | ||
| 842 | + node->GetType().c_str(), AutofuseUtils::VectorToStr(node_attr->sched.axis).c_str(), | ||
| 843 | + AutofuseUtils::VectorToStr(graph_attr.axis).c_str(), asc_graph.GetName().c_str()); | ||
| 844 | + } | ||
| 845 | + if (is_gather_fuse_type) { | ||
| 846 | + GE_ASSERT_SUCCESS(CompleteGatherInputAttrsOnAscGraphPreserveStrides(asc_graph)); | ||
| 847 | + } | ||
| 848 | + return SUCCESS; | ||
| 849 | +} | ||
| 850 | + | ||
| 851 | +inline Status CompleteNodeAttrsByInsertedAxisIdsPreserveOrder(AscGraph &asc_graph, const NodePtr &asc_node, | ||
| 852 | + const std::vector<int64_t> &inserted_axis_ids) { | ||
| 853 | + const auto is_gather_fuse_type = IsGatherFuseType(asc_node); | ||
| 854 | + TensorAttrInfo graph_attr; | ||
| 855 | + GE_ASSERT_SUCCESS(BackendUtils::GetGraphAttrInfo(asc_graph, graph_attr)); | ||
| 856 | + GELOGI("complete inserted reshape axes %s in graph %s, preserve node axis order.", | ||
| 857 | + AutofuseUtils::VectorToStr(inserted_axis_ids).c_str(), asc_graph.GetName().c_str()); | ||
| 858 | + | ||
| 859 | + for (const auto &node : AscGraphUtils::GetComputeGraph(asc_graph)->GetAllNodes()) { | ||
| 860 | + if (IsTorchDataType(node)) { | ||
| 861 | + GELOGI("torch node %s(%s) not complete node attr.", node->GetNamePtr(), node->GetType().c_str()); | ||
| 862 | + continue; | ||
| 863 | + } | ||
| 864 | + if (IsCubeRelatedAscNode(node)) { | ||
| 865 | + GELOGI("cube related node %s(%s) not complete node attr.", node->GetNamePtr(), node->GetType().c_str()); | ||
| 866 | + continue; | ||
| 867 | + } | ||
| 868 | + if (((!is_gather_fuse_type) || (!IsGatherData(node))) && (!BackendUtils::IsOutputNode(node))) { | ||
| 869 | + GE_ASSERT_SUCCESS(UpdateTensorAttrsByInsertedAxisIdsPreserveOrder(node, graph_attr.axis, graph_attr.repeats, | ||
| 870 | + inserted_axis_ids)); | ||
| 871 | + } | ||
| 872 | + const auto &op_desc = node->GetOpDesc(); | ||
| 873 | + GE_ASSERT_NOTNULL(op_desc); | ||
| 874 | + auto node_attr = op_desc->GetAttrsGroup<AscNodeAttr>(); | ||
| 875 | + GE_ASSERT_NOTNULL(node_attr); | ||
| 876 | + const auto old_sched_axis = node_attr->sched.axis; | ||
| 877 | + if (node_attr->sched.axis.empty()) { | ||
| 878 | + node_attr->sched.axis = graph_attr.axis; | ||
| 879 | + } else { | ||
| 880 | + for (const auto axis_id : inserted_axis_ids) { | ||
| 881 | + GE_ASSERT_SUCCESS(InsertNoOpAxisByGraphOrder(graph_attr.axis, axis_id, node_attr->sched.axis)); | ||
| 882 | + } | ||
| 883 | + } | ||
| 884 | + GELOGI("node %s(%s) complete sched axis from %s to %s in graph %s, preserve node axis order.", node->GetNamePtr(), | ||
| 885 | + node->GetType().c_str(), AutofuseUtils::VectorToStr(old_sched_axis).c_str(), | ||
| 886 | + AutofuseUtils::VectorToStr(node_attr->sched.axis).c_str(), asc_graph.GetName().c_str()); | ||
| 887 | + } | ||
| 888 | + if (is_gather_fuse_type) { | ||
| 889 | + GE_ASSERT_SUCCESS(CompleteGatherInputAttrsOnAscGraphPreserveStrides(asc_graph)); | ||
| 890 | + } | ||
| 891 | + return SUCCESS; | ||
| 892 | +} | ||
| 893 | + | ||
| 894 | +inline Status DumpPadLeadingUnitAxisResult(const AscGraph &asc_graph, const NodePtr &asc_node, const char *process_name, | ||
| 895 | + const ComputeGraphPtr &fused_graph) { | ||
| 896 | + GELOGI("AscBackendPostProcessor: End to run the process(%s) on the graph, graph: %s, parent node: %s(%s).", | ||
| 897 | + process_name, fused_graph->GetName().c_str(), asc_node->GetNamePtr(), asc_node->GetType().c_str()); | ||
| 898 | + GELOGD("dump node:%s(%s) asc graph info(with tensor attr info):", asc_node->GetNamePtr(), | ||
| 899 | + asc_node->GetType().c_str()); | ||
| 900 | + (void)asc_graph; | ||
| 901 | + BackendUtils::DumpAscGraph(asc_node); | ||
| 902 | + return SUCCESS; | ||
| 903 | +} | ||
| 904 | + | ||
| 905 | +struct InsertIndexMergeState { | ||
| 906 | + bool initialized = false; | ||
| 907 | + size_t original_rank = 0U; | ||
| 908 | + std::vector<size_t> gap_counts; | ||
| 909 | +}; | ||
| 910 | + | ||
| 911 | +inline std::vector<size_t> BuildInsertGapCounts(const size_t original_rank, const std::vector<size_t> &insert_indexes) { | ||
| 912 | + std::vector<size_t> gap_counts(original_rank + 1U, 0U); | ||
| 913 | + auto sorted_insert_indexes = insert_indexes; | ||
| 914 | + std::sort(sorted_insert_indexes.begin(), sorted_insert_indexes.end()); | ||
| 915 | + | ||
| 916 | + size_t inserted_count = 0U; | ||
| 917 | + for (const auto insert_index : sorted_insert_indexes) { | ||
| 918 | + const size_t gap_index = std::min(insert_index - std::min(insert_index, inserted_count), original_rank); | ||
| 919 | + ++gap_counts[gap_index]; | ||
| 920 | + ++inserted_count; | ||
| 921 | + } | ||
| 922 | + return gap_counts; | ||
| 923 | +} | ||
| 924 | + | ||
| 925 | +inline void BuildInsertIndexesFromGapCounts(const std::vector<size_t> &gap_counts, | ||
| 926 | + std::vector<size_t> &insert_indexes) { | ||
| 927 | + insert_indexes.clear(); | ||
| 928 | + size_t inserted_count = 0U; | ||
| 929 | + for (size_t gap_index = 0U; gap_index < gap_counts.size(); ++gap_index) { | ||
| 930 | + for (size_t i = 0U; i < gap_counts[gap_index]; ++i) { | ||
| 931 | + insert_indexes.push_back(gap_index + inserted_count); | ||
| 932 | + ++inserted_count; | ||
| 933 | + } | ||
| 934 | + } | ||
| 935 | +} | ||
| 936 | + | ||
| 937 | +inline Status MergeRelationInsertIndexes(const size_t original_rank, const std::vector<size_t> &relation_insert_indexes, | ||
| 938 | + InsertIndexMergeState &merge_state, | ||
| 939 | + std::vector<size_t> &merged_insert_indexes) { | ||
| 940 | + if (relation_insert_indexes.empty()) { | ||
| 941 | + return SUCCESS; | ||
| 942 | + } | ||
| 943 | + if (!merge_state.initialized) { | ||
| 944 | + merge_state.initialized = true; | ||
| 945 | + merge_state.original_rank = original_rank; | ||
| 946 | + merge_state.gap_counts.assign(original_rank + 1U, 0U); | ||
| 947 | + } | ||
| 948 | + if (merge_state.original_rank != original_rank) { | ||
| 949 | + GELOGD("skip merging relation insert indexes %s because original rank %zu does not match merged rank %zu.", | ||
| 950 | + AutofuseUtils::VectorToStr(relation_insert_indexes).c_str(), original_rank, merge_state.original_rank); | ||
| 951 | + return SUCCESS; | ||
| 952 | + } | ||
| 953 | + | ||
| 954 | + const auto relation_gap_counts = BuildInsertGapCounts(original_rank, relation_insert_indexes); | ||
| 955 | + for (size_t i = 0U; i < merge_state.gap_counts.size(); ++i) { | ||
| 956 | + merge_state.gap_counts[i] = std::max(merge_state.gap_counts[i], relation_gap_counts[i]); | ||
| 957 | + } | ||
| 958 | + BuildInsertIndexesFromGapCounts(merge_state.gap_counts, merged_insert_indexes); | ||
| 959 | + GELOGD("merge relation insert indexes %s to merged insert indexes %s by original rank %zu.", | ||
| 960 | + AutofuseUtils::VectorToStr(relation_insert_indexes).c_str(), | ||
| 961 | + AutofuseUtils::VectorToStr(merged_insert_indexes).c_str(), original_rank); | ||
| 962 | + return SUCCESS; | ||
| 963 | +} | ||
| 964 | + | ||
| 965 | +inline Status CompleteNoOpReshapeAxesByInsertIndexes(AscGraph &asc_graph, const std::vector<size_t> &insert_indexes, | ||
| 966 | + AscGraphAttr *graph_attr, | ||
| 967 | + std::vector<af::ReshapeAxisChangeInfo> *reshape_axis_changes, | ||
| 968 | + std::vector<int64_t> &inserted_axis_ids) { | ||
| 969 | + GE_ASSERT_NOTNULL(graph_attr); | ||
| 970 | + if (insert_indexes.empty()) { | ||
| 971 | + return SUCCESS; | ||
| 972 | + } | ||
| 973 | + | ||
| 974 | + auto sorted_insert_indexes = insert_indexes; | ||
| 975 | + std::sort(sorted_insert_indexes.begin(), sorted_insert_indexes.end()); | ||
| 976 | + for (const auto insert_index : sorted_insert_indexes) { | ||
| 977 | + int64_t insert_axis_id = GetNextNoOpReshapeAxisId(graph_attr->axis); | ||
| 978 | + if (insert_index < graph_attr->axis.size()) { | ||
| 979 | + GE_ASSERT_NOTNULL(graph_attr->axis[insert_index]); | ||
| 980 | + insert_axis_id = graph_attr->axis[insert_index]->id; | ||
| 981 | + } | ||
| 982 | + for (const auto &axis_info : graph_attr->axis) { | ||
| 983 | + ShiftAxisInfoIdFrom(insert_axis_id, axis_info); | ||
| 984 | + } | ||
| 985 | + if (reshape_axis_changes != nullptr) { | ||
| 986 | + ShiftReshapeAxisChangesFrom(insert_axis_id, *reshape_axis_changes); | ||
| 987 | + } | ||
| 988 | + GE_ASSERT_SUCCESS(ShiftAscGraphAxisIdsFrom(asc_graph, insert_axis_id)); | ||
| 989 | + const auto graph_insert_it = | ||
| 990 | + graph_attr->axis.begin() + static_cast<ptrdiff_t>(std::min(insert_index, graph_attr->axis.size())); | ||
| 991 | + graph_attr->axis.insert(graph_insert_it, MakeNoOpReshapeAxis(insert_axis_id, kSymbolOne)); | ||
| 992 | + inserted_axis_ids.push_back(insert_axis_id); | ||
| 993 | + GELOGD( | ||
| 994 | + "graph %s complete no-op reshape axis id %ld repeat %s at insert index %zu by relation before complete attrs.", | ||
| 995 | + asc_graph.GetName().c_str(), insert_axis_id, kSymbolOne.Str().get(), insert_index); | ||
| 996 | + } | ||
| 997 | + return SUCCESS; | ||
| 998 | +} | ||
| 999 | + | ||
| 1000 | +inline Status CompleteNoOpReshapeAxesByInsertIndexesKeepOriginalAxisIds(AscGraph &asc_graph, | ||
| 1001 | + const std::vector<size_t> &insert_indexes, | ||
| 1002 | + AscGraphAttr *graph_attr, | ||
| 1003 | + std::vector<int64_t> &inserted_axis_ids) { | ||
| 1004 | + GE_ASSERT_NOTNULL(graph_attr); | ||
| 1005 | + if (insert_indexes.empty()) { | ||
| 1006 | + return SUCCESS; | ||
| 1007 | + } | ||
| 1008 | + | ||
| 1009 | + auto sorted_insert_indexes = insert_indexes; | ||
| 1010 | + std::sort(sorted_insert_indexes.begin(), sorted_insert_indexes.end()); | ||
| 1011 | + for (const auto insert_index : sorted_insert_indexes) { | ||
| 1012 | + const auto insert_axis_id = GetNextNoOpReshapeAxisId(graph_attr->axis); | ||
| 1013 | + const auto graph_insert_it = | ||
| 1014 | + graph_attr->axis.begin() + static_cast<ptrdiff_t>(std::min(insert_index, graph_attr->axis.size())); | ||
| 1015 | + graph_attr->axis.insert(graph_insert_it, MakeNoOpReshapeAxis(insert_axis_id, kSymbolOne)); | ||
| 1016 | + inserted_axis_ids.push_back(insert_axis_id); | ||
| 1017 | + GELOGD( | ||
| 1018 | + "graph %s complete no-op reshape axis id %ld repeat %s at insert index %zu by relation without shifting " | ||
| 1019 | + "existing axis ids.", | ||
| 1020 | + asc_graph.GetName().c_str(), insert_axis_id, kSymbolOne.Str().get(), insert_index); | ||
| 1021 | + } | ||
| 1022 | + return SUCCESS; | ||
| 1023 | +} | ||
| 1024 | + | ||
| 1025 | +inline Status PadLeadingUnitAxisByInsertIndexesAndCompleteAttrs(AscGraph &asc_graph, const NodePtr &asc_node, | ||
| 1026 | + const std::vector<size_t> &insert_indexes) { | ||
| 1027 | + if (insert_indexes.empty()) { | ||
| 1028 | + return SUCCESS; | ||
| 1029 | + } | ||
| 1030 | + constexpr const char *kPadLeadingUnitAxisProcName = "pad_leading_unit_axis"; | ||
| 1031 | + const auto fused_graph = AscGraphUtils::GetComputeGraph(asc_graph); | ||
| 1032 | + GE_ASSERT_NOTNULL(fused_graph); | ||
| 1033 | + GE_ASSERT_SUCCESS(BackendUtils::AddInputOutputNodesForAscGraph(fused_graph)); | ||
| 1034 | + GE_ASSERT_SUCCESS(CacheGraphBeforePostProcess(asc_node, kPadLeadingUnitAxisProcName, fused_graph)); | ||
| 1035 | + auto autofuse_attr = BackendUtils::GetNodeAutoFuseAttr(asc_node); | ||
| 1036 | + GE_ASSERT_NOTNULL(autofuse_attr); | ||
| 1037 | + const auto graph_attr = fused_graph->GetAttrsGroup<AscGraphAttr>(); | ||
| 1038 | + GE_ASSERT_NOTNULL(graph_attr); | ||
| 1039 | + const auto axis_before_insert = CollectAxisIds(graph_attr->axis); | ||
| 1040 | + std::vector<int64_t> inserted_axis_ids; | ||
| 1041 | + GELOGD("node %s(%s) graph %s start to pad leading unit axes by relation insert indexes %s.", asc_node->GetNamePtr(), | ||
| 1042 | + asc_node->GetType().c_str(), asc_graph.GetName().c_str(), AutofuseUtils::VectorToStr(insert_indexes).c_str()); | ||
| 1043 | + GE_ASSERT_SUCCESS(CompleteNoOpReshapeAxesByInsertIndexes(asc_graph, insert_indexes, graph_attr, | ||
| 1044 | + &autofuse_attr->GetMutableInterAttrs().reshape_axis_changes, | ||
| 1045 | + inserted_axis_ids)); | ||
| 1046 | + GE_ASSERT_SUCCESS(CompleteNodeAttrsByInsertedAxisIdsPreserveOrder(asc_graph, asc_node, inserted_axis_ids)); | ||
| 1047 | + GE_ASSERT_SUCCESS(RefreshReshapeAxisGroupByInsertIndexes(axis_before_insert, insert_indexes, | ||
| 1048 | + GetInterAttrs(autofuse_attr).axis_group)); | ||
| 1049 | + GE_ASSERT_SUCCESS(DumpPadLeadingUnitAxisResult(asc_graph, asc_node, kPadLeadingUnitAxisProcName, fused_graph)); | ||
| 1050 | + return SUCCESS; | ||
| 1051 | +} | ||
| 1052 | + | ||
| 1053 | +inline Status PadLeadingUnitAxisByInsertIndexesAndCompleteAttrsKeepOriginalAxisIds( | ||
| 1054 | + AscGraph &asc_graph, const NodePtr &asc_node, const std::vector<size_t> &insert_indexes) { | ||
| 1055 | + if (insert_indexes.empty()) { | ||
| 1056 | + return SUCCESS; | ||
| 1057 | + } | ||
| 1058 | + constexpr const char *kPadLeadingUnitAxisProcName = "pad_leading_unit_axis_keep_original_axis_ids"; | ||
| 1059 | + const auto fused_graph = AscGraphUtils::GetComputeGraph(asc_graph); | ||
| 1060 | + GE_ASSERT_NOTNULL(fused_graph); | ||
| 1061 | + GE_ASSERT_SUCCESS(BackendUtils::AddInputOutputNodesForAscGraph(fused_graph)); | ||
| 1062 | + GE_ASSERT_SUCCESS(CacheGraphBeforePostProcess(asc_node, kPadLeadingUnitAxisProcName, fused_graph)); | ||
| 1063 | + auto autofuse_attr = BackendUtils::GetNodeAutoFuseAttr(asc_node); | ||
| 1064 | + GE_ASSERT_NOTNULL(autofuse_attr); | ||
| 1065 | + const auto graph_attr = fused_graph->GetAttrsGroup<AscGraphAttr>(); | ||
| 1066 | + GE_ASSERT_NOTNULL(graph_attr); | ||
| 1067 | + std::vector<int64_t> inserted_axis_ids; | ||
| 1068 | + GELOGD( | ||
| 1069 | + "node %s(%s) graph %s start to pad leading unit axes without shifting existing axis ids by relation insert " | ||
| 1070 | + "indexes %s.", | ||
| 1071 | + asc_node->GetNamePtr(), asc_node->GetType().c_str(), asc_graph.GetName().c_str(), | ||
| 1072 | + AutofuseUtils::VectorToStr(insert_indexes).c_str()); | ||
| 1073 | + GE_ASSERT_SUCCESS(CompleteNoOpReshapeAxesByInsertIndexesKeepOriginalAxisIds(asc_graph, insert_indexes, graph_attr, | ||
| 1074 | + inserted_axis_ids)); | ||
| 1075 | + GE_ASSERT_SUCCESS(CompleteNodeAttrsByInsertedAxisIdsPreserveOrder(asc_graph, asc_node, inserted_axis_ids)); | ||
| 1076 | + GE_ASSERT_SUCCESS(RefreshReshapeAxisGroupByInsertedAxisIds(inserted_axis_ids, CollectAxisIds(graph_attr->axis), | ||
| 1077 | + GetInterAttrs(autofuse_attr).axis_group)); | ||
| 1078 | + GE_ASSERT_SUCCESS(DumpPadLeadingUnitAxisResult(asc_graph, asc_node, kPadLeadingUnitAxisProcName, fused_graph)); | ||
| 1079 | + return SUCCESS; | ||
| 1080 | +} | ||
| 1081 | + | ||
| 1082 | +inline bool IsSameReshapeAxisChange(const af::ReshapeAxisChangeInfo &lhs, const af::ReshapeAxisChangeInfo &rhs) { | ||
| 1083 | + return (lhs.before_axis == rhs.before_axis) && (lhs.after_axis == rhs.after_axis) && | ||
| 1084 | + (lhs.before_repeats.size() == rhs.before_repeats.size()) && | ||
| 1085 | + (lhs.after_repeats.size() == rhs.after_repeats.size()) && | ||
| 1086 | + std::equal(lhs.before_repeats.begin(), lhs.before_repeats.end(), rhs.before_repeats.begin(), IsSameRepeat) && | ||
| 1087 | + std::equal(lhs.after_repeats.begin(), lhs.after_repeats.end(), rhs.after_repeats.begin(), IsSameRepeat); | ||
| 1088 | +} | ||
| 1089 | + | ||
| 1090 | +inline void AppendUniqueReshapeAxisChange(const af::ReshapeAxisChangeInfo &axis_change, | ||
| 1091 | + std::vector<af::ReshapeAxisChangeInfo> &axis_changes) { | ||
| 1092 | + const auto it = std::find_if(axis_changes.begin(), axis_changes.end(), [&axis_change](const auto &saved_change) { | ||
| 1093 | + return IsSameReshapeAxisChange(axis_change, saved_change); | ||
| 1094 | + }); | ||
| 1095 | + if (it == axis_changes.end()) { | ||
| 1096 | + axis_changes.push_back(axis_change); | ||
| 1097 | + } | ||
| 1098 | +} | ||
| 1099 | + | ||
| 1100 | +inline Status CollectNodeReshapeAxisChanges(const NodePtr &node, std::vector<af::ReshapeAxisChangeInfo> &axis_changes) { | ||
| 1101 | + if (!BackendUtils::IsBackendFuseNode(node)) { | ||
| 1102 | + return SUCCESS; | ||
| 1103 | + } | ||
| 1104 | + const auto attr = node->GetOpDescBarePtr()->GetAttrsGroup<AutoFuseAttrs>(); | ||
| 1105 | + GE_ASSERT_NOTNULL(attr); | ||
| 1106 | + for (const auto &axis_change : attr->GetReshapeAxisChanges()) { | ||
| 1107 | + AppendUniqueReshapeAxisChange(axis_change, axis_changes); | ||
| 1108 | + } | ||
| 1109 | + if (node->GetType() == kAscBackendType) { | ||
| 1110 | + return SUCCESS; | ||
| 1111 | + } | ||
| 1112 | + if (node->GetType() != kFusedAscBackendType) { | ||
| 1113 | + return SUCCESS; | ||
| 1114 | + } | ||
| 1115 | + GE_ASSERT_NOTNULL(attr->GetFuseComputeGraph()); | ||
| 1116 | + for (const auto &inner_node : attr->GetFuseComputeGraph()->GetAllNodes()) { | ||
| 1117 | + if ((inner_node == nullptr) || !BackendUtils::IsBackendFuseNode(inner_node) || | ||
| 1118 | + (inner_node->GetType() != kAscBackendType)) { | ||
| 1119 | + continue; | ||
| 1120 | + } | ||
| 1121 | + GE_ASSERT_SUCCESS(CollectNodeReshapeAxisChanges(inner_node, axis_changes)); | ||
| 1122 | + } | ||
| 1123 | + return SUCCESS; | ||
| 1124 | +} | ||
| 1125 | + | ||
| 1126 | +inline Status SaveMergedReshapeAxisChanges(const NodePtr &node, | ||
| 1127 | + const std::vector<af::ReshapeAxisChangeInfo> &axis_changes) { | ||
| 1128 | + if (!BackendUtils::IsBackendFuseNode(node) || axis_changes.empty()) { | ||
| 1129 | + return SUCCESS; | ||
| 1130 | + } | ||
| 1131 | + const auto attr = BackendUtils::GetNodeAutoFuseAttr(node); | ||
| 1132 | + GE_ASSERT_NOTNULL(attr); | ||
| 1133 | + auto merged_axis_changes = attr->GetReshapeAxisChanges(); | ||
| 1134 | + for (const auto &axis_change : axis_changes) { | ||
| 1135 | + AppendUniqueReshapeAxisChange(axis_change, merged_axis_changes); | ||
| 1136 | + } | ||
| 1137 | + attr->SetReshapeAxisChanges(merged_axis_changes); | ||
| 1138 | + return SUCCESS; | ||
| 1139 | +} | ||
| 1140 | + | ||
| 1141 | +inline void AppendEndpointTargetCandidate(const std::vector<Expression> ¤t_repeats, | ||
| 1142 | + const std::vector<af::ReshapeAxisChangeInfo> &axis_changes, | ||
| 1143 | + std::vector<std::vector<Expression>> &target_candidates) { | ||
| 1144 | + if (current_repeats.empty()) { | ||
| 1145 | + return; | ||
| 1146 | + } | ||
| 1147 | + const auto current_non_unit_repeats = RemoveUnitRepeats(current_repeats); | ||
| 1148 | + for (const auto &axis_change : axis_changes) { | ||
| 1149 | + if (IsSameRepeats(current_non_unit_repeats, RemoveUnitRepeats(axis_change.before_repeats)) || | ||
| 1150 | + IsSameRepeats(current_non_unit_repeats, RemoveUnitRepeats(axis_change.after_repeats))) { | ||
| 1151 | + AppendUniqueTargetRepeats(BuildNoOpReshapeTargetRepeats(axis_change), target_candidates); | ||
| 1152 | + } | ||
| 1153 | + } | ||
| 1154 | +} | ||
| 1155 | + | ||
| 1156 | +inline Status BuildRelationTargetRepeats(const std::vector<Expression> &node1_repeats, | ||
| 1157 | + const std::vector<Expression> &node2_repeats, | ||
| 1158 | + const std::vector<af::ReshapeAxisChangeInfo> &node1_axis_changes, | ||
| 1159 | + const std::vector<af::ReshapeAxisChangeInfo> &node2_axis_changes, | ||
| 1160 | + std::vector<Expression> &target_repeats) { | ||
| 1161 | + target_repeats.clear(); | ||
| 1162 | + if (node1_repeats.empty() && node2_repeats.empty()) { | ||
| 1163 | + return SUCCESS; | ||
| 1164 | + } | ||
| 1165 | + if (!node1_repeats.empty() && !node2_repeats.empty() && | ||
| 1166 | + !IsSameRepeats(RemoveUnitRepeats(node1_repeats), RemoveUnitRepeats(node2_repeats))) { | ||
| 1167 | + GELOGD( | ||
| 1168 | + "skip relation reshape target because endpoint non-unit repeats are different, node1 repeats %s, node2 " | ||
| 1169 | + "repeats %s.", | ||
| 1170 | + AutofuseUtils::VectorToStr(node1_repeats).c_str(), AutofuseUtils::VectorToStr(node2_repeats).c_str()); | ||
| 1171 | + return SUCCESS; | ||
| 1172 | + } | ||
| 1173 | + | ||
| 1174 | + std::vector<std::vector<Expression>> candidates; | ||
| 1175 | + AppendUniqueTargetRepeats(node1_repeats, candidates); | ||
| 1176 | + AppendUniqueTargetRepeats(node2_repeats, candidates); | ||
| 1177 | + AppendEndpointTargetCandidate(node1_repeats, node1_axis_changes, candidates); | ||
| 1178 | + AppendEndpointTargetCandidate(node2_repeats, node2_axis_changes, candidates); | ||
| 1179 | + | ||
| 1180 | + const auto base_repeats = !node1_repeats.empty() ? node1_repeats : node2_repeats; | ||
| 1181 | + const auto base_non_unit_repeats = RemoveUnitRepeats(base_repeats); | ||
| 1182 | + std::vector<size_t> unit_gap_counts = BuildUnitRepeatGapCounts(base_repeats); | ||
| 1183 | + bool matched = false; | ||
| 1184 | + for (const auto &candidate : candidates) { | ||
| 1185 | + if (!IsSameRepeats(base_non_unit_repeats, RemoveUnitRepeats(candidate))) { | ||
| 1186 | + continue; | ||
| 1187 | + } | ||
| 1188 | + MergeUnitRepeatGapCounts(BuildUnitRepeatGapCounts(candidate), unit_gap_counts); | ||
| 1189 | + matched = true; | ||
| 1190 | + } | ||
| 1191 | + if (!matched) { | ||
| 1192 | + return SUCCESS; | ||
| 1193 | + } | ||
| 1194 | + target_repeats = ApplyUnitRepeatGaps(base_non_unit_repeats, unit_gap_counts); | ||
| 1195 | + return SUCCESS; | ||
| 1196 | +} | ||
| 1197 | + | ||
| 1198 | +inline Status CollectInsertIndexesByTargetRepeats(const std::vector<Expression> ¤t_repeats, | ||
| 1199 | + const std::vector<Expression> &target_repeats, | ||
| 1200 | + std::vector<size_t> &insert_indexes) { | ||
| 1201 | + if (current_repeats.empty() || target_repeats.empty() || (target_repeats.size() <= current_repeats.size())) { | ||
| 1202 | + return SUCCESS; | ||
| 1203 | + } | ||
| 1204 | + const auto current_non_unit_repeats = RemoveUnitRepeats(current_repeats); | ||
| 1205 | + const auto target_non_unit_repeats = RemoveUnitRepeats(target_repeats); | ||
| 1206 | + if (!IsSameRepeats(current_non_unit_repeats, target_non_unit_repeats)) { | ||
| 1207 | + return SUCCESS; | ||
| 1208 | + } | ||
| 1209 | + | ||
| 1210 | + const auto current_gap_counts = BuildUnitRepeatGapCounts(current_repeats); | ||
| 1211 | + const auto target_gap_counts = BuildUnitRepeatGapCounts(target_repeats); | ||
| 1212 | + if (current_gap_counts.size() != target_gap_counts.size()) { | ||
| 1213 | + return SUCCESS; | ||
| 1214 | + } | ||
| 1215 | + | ||
| 1216 | + insert_indexes.clear(); | ||
| 1217 | + size_t current_gap_start = 0U; | ||
| 1218 | + for (size_t gap_idx = 0U; gap_idx < current_gap_counts.size(); ++gap_idx) { | ||
| 1219 | + if (target_gap_counts[gap_idx] < current_gap_counts[gap_idx]) { | ||
| 1220 | + return SUCCESS; | ||
| 1221 | + } | ||
| 1222 | + const auto extra_unit_count = target_gap_counts[gap_idx] - current_gap_counts[gap_idx]; | ||
| 1223 | + for (size_t i = 0U; i < extra_unit_count; ++i) { | ||
| 1224 | + insert_indexes.push_back(current_gap_start + current_gap_counts[gap_idx] + i); | ||
| 1225 | + } | ||
| 1226 | + current_gap_start += current_gap_counts[gap_idx] + extra_unit_count; | ||
| 1227 | + if (gap_idx + 1U < current_gap_counts.size()) { | ||
| 1228 | + ++current_gap_start; | ||
| 1229 | + } | ||
| 1230 | + } | ||
| 1231 | + GELOGD("collect reshape insert indexes %s by current repeats %s and edge target repeats %s.", | ||
| 1232 | + AutofuseUtils::VectorToStr(insert_indexes).c_str(), AutofuseUtils::VectorToStr(current_repeats).c_str(), | ||
| 1233 | + AutofuseUtils::VectorToStr(target_repeats).c_str()); | ||
| 1234 | + return SUCCESS; | ||
| 1235 | +} | ||
| 1236 | + | ||
| 1237 | +inline Status PadNodeLeadingUnitAxisByInsertIndexes(const NodePtr &node, const std::vector<size_t> &insert_indexes) { | ||
| 1238 | + if (insert_indexes.empty() || !BackendUtils::IsBackendFuseNode(node)) { | ||
| 1239 | + return SUCCESS; | ||
| 1240 | + } | ||
| 1241 | + const auto attr = node->GetOpDescBarePtr()->GetAttrsGroup<AutoFuseAttrs>(); | ||
| 1242 | + GE_ASSERT_NOTNULL(attr); | ||
| 1243 | + if (node->GetType() == kAscBackendType) { | ||
| 1244 | + GE_ASSERT_NOTNULL(attr->GetAscGraph()); | ||
| 1245 | + GE_ASSERT_SUCCESS(PadLeadingUnitAxisByInsertIndexesAndCompleteAttrs(*(attr->GetAscGraph()), node, insert_indexes)); | ||
| 1246 | + return SUCCESS; | ||
| 1247 | + } | ||
| 1248 | + if (node->GetType() != kFusedAscBackendType) { | ||
| 1249 | + return SUCCESS; | ||
| 1250 | + } | ||
| 1251 | + ComputeGraphPtr fused_graph; | ||
| 1252 | + GE_ASSERT_SUCCESS(BackendUtils::GetNodeFusedGraph(node, fused_graph)); | ||
| 1253 | + GE_ASSERT_NOTNULL(fused_graph); | ||
| 1254 | + const auto fused_graph_attr = fused_graph->GetAttrsGroup<AscGraphAttr>(); | ||
| 1255 | + GE_ASSERT_NOTNULL(fused_graph_attr); | ||
| 1256 | + const auto axis_before_insert = CollectAxisIds(fused_graph_attr->axis); | ||
| 1257 | + GE_ASSERT_NOTNULL(attr->GetFuseComputeGraph()); | ||
| 1258 | + for (const auto &inner_node : attr->GetFuseComputeGraph()->GetAllNodes()) { | ||
| 1259 | + if ((inner_node == nullptr) || !BackendUtils::IsBackendFuseNode(inner_node) || | ||
| 1260 | + (inner_node->GetType() != kAscBackendType)) { | ||
| 1261 | + continue; | ||
| 1262 | + } | ||
| 1263 | + GE_ASSERT_SUCCESS(PadNodeLeadingUnitAxisByInsertIndexes(inner_node, insert_indexes)); | ||
| 1264 | + } | ||
| 1265 | + GE_ASSERT_SUCCESS( | ||
| 1266 | + RefreshReshapeAxisGroupByInsertIndexes(axis_before_insert, insert_indexes, GetInterAttrs(attr).axis_group)); | ||
| 1267 | + return SUCCESS; | ||
| 1268 | +} | ||
| 1269 | + | ||
| 1270 | +inline Status PadNodeLeadingUnitAxisByInsertIndexesKeepOriginalAxisIds(const NodePtr &node, | ||
| 1271 | + const std::vector<size_t> &insert_indexes) { | ||
| 1272 | + if (insert_indexes.empty() || !BackendUtils::IsBackendFuseNode(node)) { | ||
| 1273 | + return SUCCESS; | ||
| 1274 | + } | ||
| 1275 | + const auto attr = node->GetOpDescBarePtr()->GetAttrsGroup<AutoFuseAttrs>(); | ||
| 1276 | + GE_ASSERT_NOTNULL(attr); | ||
| 1277 | + if (node->GetType() == kAscBackendType) { | ||
| 1278 | + GE_ASSERT_NOTNULL(attr->GetAscGraph()); | ||
| 1279 | + GE_ASSERT_SUCCESS(PadLeadingUnitAxisByInsertIndexesAndCompleteAttrsKeepOriginalAxisIds(*(attr->GetAscGraph()), node, | ||
| 1280 | + insert_indexes)); | ||
| 1281 | + return SUCCESS; | ||
| 1282 | + } | ||
| 1283 | + if (node->GetType() != kFusedAscBackendType) { | ||
| 1284 | + return SUCCESS; | ||
| 1285 | + } | ||
| 1286 | + ComputeGraphPtr fused_graph; | ||
| 1287 | + GE_ASSERT_SUCCESS(BackendUtils::GetNodeFusedGraph(node, fused_graph)); | ||
| 1288 | + GE_ASSERT_NOTNULL(fused_graph); | ||
| 1289 | + const auto fused_graph_attr = fused_graph->GetAttrsGroup<AscGraphAttr>(); | ||
| 1290 | + GE_ASSERT_NOTNULL(fused_graph_attr); | ||
| 1291 | + const auto axis_before_insert = CollectAxisIds(fused_graph_attr->axis); | ||
| 1292 | + GE_ASSERT_NOTNULL(attr->GetFuseComputeGraph()); | ||
| 1293 | + for (const auto &inner_node : attr->GetFuseComputeGraph()->GetAllNodes()) { | ||
| 1294 | + if ((inner_node == nullptr) || !BackendUtils::IsBackendFuseNode(inner_node) || | ||
| 1295 | + (inner_node->GetType() != kAscBackendType)) { | ||
| 1296 | + continue; | ||
| 1297 | + } | ||
| 1298 | + GE_ASSERT_SUCCESS(PadNodeLeadingUnitAxisByInsertIndexesKeepOriginalAxisIds(inner_node, insert_indexes)); | ||
| 1299 | + } | ||
| 1300 | + GE_ASSERT_SUCCESS(RefreshReshapeAxisGroupByInsertedAxisIds( | ||
| 1301 | + CollectInsertedAxisIds(axis_before_insert, CollectAxisIds(fused_graph_attr->axis)), | ||
| 1302 | + CollectAxisIds(fused_graph_attr->axis), GetInterAttrs(attr).axis_group)); | ||
| 1303 | + return SUCCESS; | ||
| 1304 | +} | ||
| 1305 | + | ||
| 1306 | +inline bool IsReshapeSearchTerminal(const NodePtr &node, const bool search_forward) { | ||
| 1307 | + if (search_forward) { | ||
| 1308 | + return BackendUtils::IsOutputNode(node); | ||
| 1309 | + } | ||
| 1310 | + return (node->GetType() == kDataType) || (node->GetType() == kScalarType); | ||
| 1311 | +} | ||
| 1312 | + | ||
| 1313 | +inline void GetConnectedPeerInNodesForReshapeSearch(const NodePtr &node, const int32_t out_data_idx, | ||
| 1314 | + std::vector<NodePtr> &peer_in_nodes) { | ||
| 1315 | + peer_in_nodes.clear(); | ||
| 1316 | + const auto out_anchor = node->GetOutDataAnchor(out_data_idx); | ||
| 1317 | + if (out_anchor == nullptr) { | ||
| 1318 | + return; | ||
| 1319 | + } | ||
| 1320 | + for (const auto &peer_in_anchor : out_anchor->GetPeerInDataAnchors()) { | ||
| 1321 | + if (peer_in_anchor == nullptr) { | ||
| 1322 | + continue; | ||
| 1323 | + } | ||
| 1324 | + const auto peer_in_node = peer_in_anchor->GetOwnerNode(); | ||
| 1325 | + if (peer_in_node != nullptr) { | ||
| 1326 | + peer_in_nodes.push_back(peer_in_node); | ||
| 1327 | + } | ||
| 1328 | + } | ||
| 1329 | +} | ||
| 1330 | + | ||
| 1331 | +inline void GetConnectedPeerOutNodesForReshapeSearch(const NodePtr &node, std::vector<NodePtr> &peer_out_nodes) { | ||
| 1332 | + peer_out_nodes.clear(); | ||
| 1333 | + const auto size = static_cast<int32_t>(node->GetAllInDataAnchorsSize()); | ||
| 1334 | + for (int32_t i = 0; i < size; ++i) { | ||
| 1335 | + const auto in_anchor = node->GetInDataAnchor(i); | ||
| 1336 | + if (in_anchor == nullptr) { | ||
| 1337 | + continue; | ||
| 1338 | + } | ||
| 1339 | + const auto peer_out_anchor = in_anchor->GetPeerOutAnchor(); | ||
| 1340 | + if (peer_out_anchor == nullptr) { | ||
| 1341 | + continue; | ||
| 1342 | + } | ||
| 1343 | + const auto peer_out_node = peer_out_anchor->GetOwnerNode(); | ||
| 1344 | + if (peer_out_node != nullptr) { | ||
| 1345 | + peer_out_nodes.push_back(peer_out_node); | ||
| 1346 | + } | ||
| 1347 | + } | ||
| 1348 | +} | ||
| 1349 | + | ||
| 1350 | +inline bool FindDirectionalNonUnitRepeatByAxisId(const NodePtr &node, const int64_t axis_id, const bool search_forward, | ||
| 1351 | + std::unordered_set<const void *> &visited, Expression &repeat) { | ||
| 1352 | + if ((node == nullptr) || (visited.find(node.get()) != visited.end())) { | ||
| 1353 | + return false; | ||
| 1354 | + } | ||
| 1355 | + visited.insert(node.get()); | ||
| 1356 | + if (IsReshapeSearchTerminal(node, search_forward)) { | ||
| 1357 | + return false; | ||
| 1358 | + } | ||
| 1359 | + | ||
| 1360 | + const auto op_desc = node->GetOpDesc(); | ||
| 1361 | + if (op_desc == nullptr) { | ||
| 1362 | + return false; | ||
| 1363 | + } | ||
| 1364 | + for (size_t i = 0U; i < node->GetAllOutDataAnchorsSize(); ++i) { | ||
| 1365 | + const auto output_desc = op_desc->MutableOutputDesc(i); | ||
| 1366 | + if (output_desc == nullptr) { | ||
| 1367 | + continue; | ||
| 1368 | + } | ||
| 1369 | + const auto tensor_attr = output_desc->GetAttrsGroup<AscTensorAttr>(); | ||
| 1370 | + if (tensor_attr == nullptr) { | ||
| 1371 | + continue; | ||
| 1372 | + } | ||
| 1373 | + const auto axis_it = std::find(tensor_attr->axis.begin(), tensor_attr->axis.end(), axis_id); | ||
| 1374 | + if (axis_it == tensor_attr->axis.end()) { | ||
| 1375 | + continue; | ||
| 1376 | + } | ||
| 1377 | + const auto axis_index = static_cast<size_t>(std::distance(tensor_attr->axis.begin(), axis_it)); | ||
| 1378 | + if ((axis_index < tensor_attr->repeats.size()) && !BackendUtils::IsEqOne(tensor_attr->repeats[axis_index])) { | ||
| 1379 | + repeat = tensor_attr->repeats[axis_index]; | ||
| 1380 | + return true; | ||
| 1381 | + } | ||
| 1382 | + } | ||
| 1383 | + | ||
| 1384 | + std::vector<NodePtr> peer_nodes; | ||
| 1385 | + if (search_forward) { | ||
| 1386 | + for (size_t i = 0U; i < node->GetAllOutDataAnchorsSize(); ++i) { | ||
| 1387 | + GetConnectedPeerInNodesForReshapeSearch(node, static_cast<int32_t>(i), peer_nodes); | ||
| 1388 | + for (const auto &peer_node : peer_nodes) { | ||
| 1389 | + if (FindDirectionalNonUnitRepeatByAxisId(peer_node, axis_id, search_forward, visited, repeat)) { | ||
| 1390 | + return true; | ||
| 1391 | + } | ||
| 1392 | + } | ||
| 1393 | + } | ||
| 1394 | + return false; | ||
| 1395 | + } | ||
| 1396 | + | ||
| 1397 | + GetConnectedPeerOutNodesForReshapeSearch(node, peer_nodes); | ||
| 1398 | + for (const auto &peer_node : peer_nodes) { | ||
| 1399 | + if (FindDirectionalNonUnitRepeatByAxisId(peer_node, axis_id, search_forward, visited, repeat)) { | ||
| 1400 | + return true; | ||
| 1401 | + } | ||
| 1402 | + } | ||
| 1403 | + return false; | ||
| 1404 | +} | ||
| 1405 | + | ||
| 1406 | +inline bool FindAnchorRepeatByRepeatIndex(const NodePtr &node, const std::vector<int64_t> &axis, | ||
| 1407 | + const size_t repeat_index, const bool search_forward, Expression &repeat) { | ||
| 1408 | + if (repeat_index >= axis.size()) { | ||
| 1409 | + return false; | ||
| 1410 | + } | ||
| 1411 | + std::unordered_set<const void *> visited; | ||
| 1412 | + return FindDirectionalNonUnitRepeatByAxisId(node, axis[repeat_index], search_forward, visited, repeat); | ||
| 1413 | +} | ||
| 1414 | + | ||
| 1415 | +inline void BuildUnitRepeatGapIndexes(const std::vector<Expression> &repeats, | ||
| 1416 | + std::vector<std::vector<size_t>> &gap_indexes, std::vector<size_t> &gap_starts) { | ||
| 1417 | + gap_indexes.assign(RemoveUnitRepeats(repeats).size() + 1U, {}); | ||
| 1418 | + gap_starts.assign(gap_indexes.size(), 0U); | ||
| 1419 | + size_t gap_idx = 0U; | ||
| 1420 | + for (size_t i = 0U; i < repeats.size(); ++i) { | ||
| 1421 | + if (BackendUtils::IsEqOne(repeats[i])) { | ||
| 1422 | + gap_indexes[gap_idx].push_back(i); | ||
| 1423 | + continue; | ||
| 1424 | + } | ||
| 1425 | + ++gap_idx; | ||
| 1426 | + if (gap_idx < gap_starts.size()) { | ||
| 1427 | + gap_starts[gap_idx] = i + 1U; | ||
| 1428 | + } | ||
| 1429 | + } | ||
| 1430 | +} | ||
| 1431 | + | ||
| 1432 | +inline void BuildUnitRepeatGapIndexes(const std::vector<Expression> &repeats, | ||
| 1433 | + std::vector<std::vector<size_t>> &gap_indexes) { | ||
| 1434 | + std::vector<size_t> unused_gap_starts; | ||
| 1435 | + BuildUnitRepeatGapIndexes(repeats, gap_indexes, unused_gap_starts); | ||
| 1436 | +} | ||
| 1437 | + | ||
| 1438 | +inline void RemoveInsertIndexesInRange(const size_t range_start, const size_t range_end, | ||
| 1439 | + std::vector<size_t> &insert_indexes) { | ||
| 1440 | + insert_indexes.erase(std::remove_if(insert_indexes.begin(), insert_indexes.end(), | ||
| 1441 | + [range_start, range_end](const size_t insert_index) { | ||
| 1442 | + return (insert_index >= range_start) && (insert_index < range_end); | ||
| 1443 | + }), | ||
| 1444 | + insert_indexes.end()); | ||
| 1445 | +} | ||
| 1446 | + | ||
| 1447 | +inline bool CollectAnchorAlignedInsertIndexes(const NodePtr &node, const std::vector<int64_t> &axis, | ||
| 1448 | + const std::vector<size_t> ¤t_gap_indexes, const bool search_forward, | ||
| 1449 | + const NodePtr &peer_node, const std::vector<int64_t> &peer_axis, | ||
| 1450 | + const std::vector<size_t> &peer_gap_indexes, | ||
| 1451 | + const bool peer_search_forward, const size_t gap_start, | ||
| 1452 | + std::vector<size_t> &aligned_insert_indexes) { | ||
| 1453 | + constexpr size_t kInvalidIndex = static_cast<size_t>(-1); | ||
| 1454 | + std::vector<size_t> peer_offset_to_current_index(peer_gap_indexes.size(), kInvalidIndex); | ||
| 1455 | + for (const auto current_index : current_gap_indexes) { | ||
| 1456 | + Expression current_anchor; | ||
| 1457 | + if (!FindAnchorRepeatByRepeatIndex(node, axis, current_index, search_forward, current_anchor)) { | ||
| 1458 | + continue; | ||
| 1459 | + } | ||
| 1460 | + for (size_t peer_offset = 0U; peer_offset < peer_gap_indexes.size(); ++peer_offset) { | ||
| 1461 | + Expression peer_anchor; | ||
| 1462 | + if (FindAnchorRepeatByRepeatIndex(peer_node, peer_axis, peer_gap_indexes[peer_offset], peer_search_forward, | ||
| 1463 | + peer_anchor) && | ||
| 1464 | + IsSameRepeat(current_anchor, peer_anchor)) { | ||
| 1465 | + peer_offset_to_current_index[peer_offset] = current_index; | ||
| 1466 | + break; | ||
| 1467 | + } | ||
| 1468 | + } | ||
| 1469 | + } | ||
| 1470 | + if (std::all_of(peer_offset_to_current_index.begin(), peer_offset_to_current_index.end(), | ||
| 1471 | + [](const size_t current_index) { return current_index == kInvalidIndex; })) { | ||
| 1472 | + return false; | ||
| 1473 | + } | ||
| 1474 | + | ||
| 1475 | + aligned_insert_indexes.clear(); | ||
| 1476 | + for (size_t peer_offset = 0U; peer_offset < peer_offset_to_current_index.size(); ++peer_offset) { | ||
| 1477 | + if (peer_offset_to_current_index[peer_offset] != kInvalidIndex) { | ||
| 1478 | + continue; | ||
| 1479 | + } | ||
| 1480 | + size_t insert_index = gap_start + current_gap_indexes.size(); | ||
| 1481 | + for (size_t next_offset = peer_offset + 1U; next_offset < peer_offset_to_current_index.size(); ++next_offset) { | ||
| 1482 | + if (peer_offset_to_current_index[next_offset] != kInvalidIndex) { | ||
| 1483 | + insert_index = peer_offset_to_current_index[next_offset]; | ||
| 1484 | + break; | ||
| 1485 | + } | ||
| 1486 | + } | ||
| 1487 | + aligned_insert_indexes.push_back(insert_index); | ||
| 1488 | + } | ||
| 1489 | + return true; | ||
| 1490 | +} | ||
| 1491 | + | ||
| 1492 | +inline void AdjustInsertIndexesByAnchorAlignment(const NodePtr &node, const std::vector<int64_t> &axis, | ||
| 1493 | + const std::vector<Expression> &repeats, const bool search_forward, | ||
| 1494 | + const NodePtr &peer_node, const std::vector<int64_t> &peer_axis, | ||
| 1495 | + const std::vector<Expression> &peer_repeats, | ||
| 1496 | + const bool peer_search_forward, std::vector<size_t> &insert_indexes) { | ||
| 1497 | + std::vector<std::vector<size_t>> gap_indexes; | ||
| 1498 | + std::vector<size_t> gap_starts; | ||
| 1499 | + std::vector<std::vector<size_t>> peer_gap_indexes; | ||
| 1500 | + BuildUnitRepeatGapIndexes(repeats, gap_indexes, gap_starts); | ||
| 1501 | + BuildUnitRepeatGapIndexes(peer_repeats, peer_gap_indexes); | ||
| 1502 | + if (gap_indexes.size() != peer_gap_indexes.size()) { | ||
| 1503 | + return; | ||
| 1504 | + } | ||
| 1505 | + | ||
| 1506 | + for (size_t gap_idx = 0U; gap_idx < gap_indexes.size(); ++gap_idx) { | ||
| 1507 | + if ((peer_gap_indexes[gap_idx].size() <= gap_indexes[gap_idx].size()) || (peer_gap_indexes[gap_idx].size() <= 1U)) { | ||
| 1508 | + continue; | ||
| 1509 | + } | ||
| 1510 | + std::vector<size_t> aligned_insert_indexes; | ||
| 1511 | + if (!CollectAnchorAlignedInsertIndexes(node, axis, gap_indexes[gap_idx], search_forward, peer_node, peer_axis, | ||
| 1512 | + peer_gap_indexes[gap_idx], peer_search_forward, gap_starts[gap_idx], | ||
| 1513 | + aligned_insert_indexes)) { | ||
| 1514 | + continue; | ||
| 1515 | + } | ||
| 1516 | + RemoveInsertIndexesInRange(gap_starts[gap_idx], gap_starts[gap_idx] + peer_gap_indexes[gap_idx].size(), | ||
| 1517 | + insert_indexes); | ||
| 1518 | + insert_indexes.insert(insert_indexes.end(), aligned_insert_indexes.begin(), aligned_insert_indexes.end()); | ||
| 1519 | + } | ||
| 1520 | + std::sort(insert_indexes.begin(), insert_indexes.end()); | ||
| 1521 | +} | ||
| 1522 | + | ||
| 1523 | +inline Status CollectVerticalRelationInsertIndexes(const NodePtr &node1, const NodePtr &node2, | ||
| 1524 | + const NodeFuseInfo &fuse_info, | ||
| 1525 | + const std::vector<af::ReshapeAxisChangeInfo> &node1_axis_changes, | ||
| 1526 | + const std::vector<af::ReshapeAxisChangeInfo> &node2_axis_changes, | ||
| 1527 | + InsertIndexMergeState &node1_insert_index_state, | ||
| 1528 | + InsertIndexMergeState &node2_insert_index_state, | ||
| 1529 | + std::vector<size_t> &node1_insert_indexes, | ||
| 1530 | + std::vector<size_t> &node2_insert_indexes) { | ||
| 1531 | + AscGraphAxisMapping axis_mapping(false); | ||
| 1532 | + for (const auto &relation : fuse_info.GetNode1ToNode2LinkMap()) { | ||
| 1533 | + std::vector<Expression> node1_output_repeats; | ||
| 1534 | + std::vector<Expression> node2_input_repeats; | ||
| 1535 | + std::vector<Expression> dims; | ||
| 1536 | + std::vector<int64_t> node1_output_axis; | ||
| 1537 | + std::vector<int64_t> node2_input_axis; | ||
| 1538 | + std::vector<Expression> target_repeats; | ||
| 1539 | + std::vector<size_t> relation_node1_insert_indexes; | ||
| 1540 | + std::vector<size_t> relation_node2_insert_indexes; | ||
| 1541 | + GE_ASSERT_SUCCESS( | ||
| 1542 | + axis_mapping.GetPreNodeAttrs(node2, relation.second, dims, node1_output_axis, node1_output_repeats)); | ||
| 1543 | + GE_ASSERT_SUCCESS(axis_mapping.GetCurNodeAttrs(node2, relation.second, node2_input_axis, node2_input_repeats)); | ||
| 1544 | + | ||
| 1545 | + GE_ASSERT_SUCCESS(BuildRelationTargetRepeats(node1_output_repeats, node2_input_repeats, node1_axis_changes, | ||
| 1546 | + node2_axis_changes, target_repeats)); | ||
| 1547 | + GE_ASSERT_SUCCESS( | ||
| 1548 | + CollectInsertIndexesByTargetRepeats(node1_output_repeats, target_repeats, relation_node1_insert_indexes)); | ||
| 1549 | + GE_ASSERT_SUCCESS( | ||
| 1550 | + CollectInsertIndexesByTargetRepeats(node2_input_repeats, target_repeats, relation_node2_insert_indexes)); | ||
| 1551 | + AdjustInsertIndexesByAnchorAlignment(node1, node1_output_axis, node1_output_repeats, false, node2, node2_input_axis, | ||
| 1552 | + node2_input_repeats, true, relation_node1_insert_indexes); | ||
| 1553 | + AdjustInsertIndexesByAnchorAlignment(node2, node2_input_axis, node2_input_repeats, true, node1, node1_output_axis, | ||
| 1554 | + node1_output_repeats, false, relation_node2_insert_indexes); | ||
| 1555 | + GE_ASSERT_SUCCESS(MergeRelationInsertIndexes(node1_output_repeats.size(), relation_node1_insert_indexes, | ||
| 1556 | + node1_insert_index_state, node1_insert_indexes)); | ||
| 1557 | + GE_ASSERT_SUCCESS(MergeRelationInsertIndexes(node2_input_repeats.size(), relation_node2_insert_indexes, | ||
| 1558 | + node2_insert_index_state, node2_insert_indexes)); | ||
| 1559 | + GELOGD( | ||
| 1560 | + "collect vertical reshape insert indexes, node1 %s out %d repeats %s indexes %s, node2 %s in %d repeats %s " | ||
| 1561 | + "indexes %s, target repeats %s.", | ||
| 1562 | + node1->GetNamePtr(), relation.first, AutofuseUtils::VectorToStr(node1_output_repeats).c_str(), | ||
| 1563 | + AutofuseUtils::VectorToStr(node1_insert_indexes).c_str(), node2->GetNamePtr(), relation.second, | ||
| 1564 | + AutofuseUtils::VectorToStr(node2_input_repeats).c_str(), | ||
| 1565 | + AutofuseUtils::VectorToStr(node2_insert_indexes).c_str(), AutofuseUtils::VectorToStr(target_repeats).c_str()); | ||
| 1566 | + } | ||
| 1567 | + return SUCCESS; | ||
| 1568 | +} | ||
| 1569 | + | ||
| 1570 | +inline Status CollectCommonInputRelationInsertIndexes(const NodePtr &node1, const NodePtr &node2, | ||
| 1571 | + const NodeFuseInfo &fuse_info, | ||
| 1572 | + const std::vector<af::ReshapeAxisChangeInfo> &node1_axis_changes, | ||
| 1573 | + const std::vector<af::ReshapeAxisChangeInfo> &node2_axis_changes, | ||
| 1574 | + InsertIndexMergeState &node1_insert_index_state, | ||
| 1575 | + InsertIndexMergeState &node2_insert_index_state, | ||
| 1576 | + std::vector<size_t> &node1_insert_indexes, | ||
| 1577 | + std::vector<size_t> &node2_insert_indexes) { | ||
| 1578 | + AscGraphAxisMapping axis_mapping(false); | ||
| 1579 | + for (const auto &relation : fuse_info.GetSameInputMap()) { | ||
| 1580 | + std::vector<Expression> node1_input_repeats; | ||
| 1581 | + std::vector<Expression> node2_input_repeats; | ||
| 1582 | + std::vector<int64_t> node1_input_axis; | ||
| 1583 | + std::vector<int64_t> node2_input_axis; | ||
| 1584 | + std::vector<Expression> target_repeats; | ||
| 1585 | + std::vector<size_t> relation_node1_insert_indexes; | ||
| 1586 | + std::vector<size_t> relation_node2_insert_indexes; | ||
| 1587 | + GE_ASSERT_SUCCESS(axis_mapping.GetCurNodeAttrs(node1, relation.first, node1_input_axis, node1_input_repeats)); | ||
| 1588 | + GE_ASSERT_SUCCESS(axis_mapping.GetCurNodeAttrs(node2, relation.second, node2_input_axis, node2_input_repeats)); | ||
| 1589 | + | ||
| 1590 | + GE_ASSERT_SUCCESS(BuildRelationTargetRepeats(node1_input_repeats, node2_input_repeats, node1_axis_changes, | ||
| 1591 | + node2_axis_changes, target_repeats)); | ||
| 1592 | + GE_ASSERT_SUCCESS( | ||
| 1593 | + CollectInsertIndexesByTargetRepeats(node1_input_repeats, target_repeats, relation_node1_insert_indexes)); | ||
| 1594 | + GE_ASSERT_SUCCESS( | ||
| 1595 | + CollectInsertIndexesByTargetRepeats(node2_input_repeats, target_repeats, relation_node2_insert_indexes)); | ||
| 1596 | + AdjustInsertIndexesByAnchorAlignment(node1, node1_input_axis, node1_input_repeats, true, node2, node2_input_axis, | ||
| 1597 | + node2_input_repeats, true, relation_node1_insert_indexes); | ||
| 1598 | + AdjustInsertIndexesByAnchorAlignment(node2, node2_input_axis, node2_input_repeats, true, node1, node1_input_axis, | ||
| 1599 | + node1_input_repeats, true, relation_node2_insert_indexes); | ||
| 1600 | + GE_ASSERT_SUCCESS(MergeRelationInsertIndexes(node1_input_repeats.size(), relation_node1_insert_indexes, | ||
| 1601 | + node1_insert_index_state, node1_insert_indexes)); | ||
| 1602 | + GE_ASSERT_SUCCESS(MergeRelationInsertIndexes(node2_input_repeats.size(), relation_node2_insert_indexes, | ||
| 1603 | + node2_insert_index_state, node2_insert_indexes)); | ||
| 1604 | + GELOGD( | ||
| 1605 | + "collect common-input reshape insert indexes, node1 %s in %d repeats %s indexes %s, node2 %s in %d repeats " | ||
| 1606 | + "%s indexes %s, target repeats %s.", | ||
| 1607 | + node1->GetNamePtr(), relation.first, AutofuseUtils::VectorToStr(node1_input_repeats).c_str(), | ||
| 1608 | + AutofuseUtils::VectorToStr(node1_insert_indexes).c_str(), node2->GetNamePtr(), relation.second, | ||
| 1609 | + AutofuseUtils::VectorToStr(node2_input_repeats).c_str(), | ||
| 1610 | + AutofuseUtils::VectorToStr(node2_insert_indexes).c_str(), AutofuseUtils::VectorToStr(target_repeats).c_str()); | ||
| 1611 | + } | ||
| 1612 | + return SUCCESS; | ||
| 1613 | +} | ||
| 1614 | + | ||
| 1615 | +inline Status CollectRelationInsertIndexes(const NodePtr &node1, const NodePtr &node2, const NodeFuseInfo &fuse_info, | ||
| 1616 | + const std::vector<af::ReshapeAxisChangeInfo> &node1_axis_changes, | ||
| 1617 | + const std::vector<af::ReshapeAxisChangeInfo> &node2_axis_changes, | ||
| 1618 | + std::vector<size_t> &node1_insert_indexes, | ||
| 1619 | + std::vector<size_t> &node2_insert_indexes) { | ||
| 1620 | + node1_insert_indexes.clear(); | ||
| 1621 | + node2_insert_indexes.clear(); | ||
| 1622 | + InsertIndexMergeState node1_insert_index_state; | ||
| 1623 | + InsertIndexMergeState node2_insert_index_state; | ||
| 1624 | + GE_ASSERT_SUCCESS(CollectVerticalRelationInsertIndexes( | ||
| 1625 | + node1, node2, fuse_info, node1_axis_changes, node2_axis_changes, node1_insert_index_state, | ||
| 1626 | + node2_insert_index_state, node1_insert_indexes, node2_insert_indexes)); | ||
| 1627 | + GE_ASSERT_SUCCESS(CollectCommonInputRelationInsertIndexes( | ||
| 1628 | + node1, node2, fuse_info, node1_axis_changes, node2_axis_changes, node1_insert_index_state, | ||
| 1629 | + node2_insert_index_state, node1_insert_indexes, node2_insert_indexes)); | ||
| 1630 | + return SUCCESS; | ||
| 1631 | +} | ||
| 1632 | + | ||
| 1633 | +// Backend can-fuse 前置处理接口:根据 node1/node2 的真实连接关系补齐 AscBackend/FusedAscBackend 的 | ||
| 1634 | +// reshape no-op 单位轴,避免后续比较或合并属性时使用不一致的轴空间。 | ||
| 1635 | +inline Status CompletePairReshapeAxes(const NodePtr &node1, const NodePtr &node2, const NodeFuseInfo &fuse_info) { | ||
| 1636 | + std::vector<af::ReshapeAxisChangeInfo> node1_axis_changes; | ||
| 1637 | + std::vector<af::ReshapeAxisChangeInfo> node2_axis_changes; | ||
| 1638 | + GE_ASSERT_SUCCESS(CollectNodeReshapeAxisChanges(node1, node1_axis_changes)); | ||
| 1639 | + GE_ASSERT_SUCCESS(CollectNodeReshapeAxisChanges(node2, node2_axis_changes)); | ||
| 1640 | + if (node1_axis_changes.empty() && node2_axis_changes.empty()) { | ||
| 1641 | + return SUCCESS; | ||
| 1642 | + } | ||
| 1643 | + | ||
| 1644 | + std::vector<size_t> node1_insert_indexes; | ||
| 1645 | + std::vector<size_t> node2_insert_indexes; | ||
| 1646 | + GE_ASSERT_SUCCESS(CollectRelationInsertIndexes(node1, node2, fuse_info, node1_axis_changes, node2_axis_changes, | ||
| 1647 | + node1_insert_indexes, node2_insert_indexes)); | ||
| 1648 | + GE_ASSERT_SUCCESS(PadNodeLeadingUnitAxisByInsertIndexesKeepOriginalAxisIds(node1, node1_insert_indexes)); | ||
| 1649 | + GE_ASSERT_SUCCESS(PadNodeLeadingUnitAxisByInsertIndexesKeepOriginalAxisIds(node2, node2_insert_indexes)); | ||
| 1650 | + std::vector<af::ReshapeAxisChangeInfo> merged_axis_changes; | ||
| 1651 | + GE_ASSERT_SUCCESS(CollectNodeReshapeAxisChanges(node1, merged_axis_changes)); | ||
| 1652 | + GE_ASSERT_SUCCESS(CollectNodeReshapeAxisChanges(node2, merged_axis_changes)); | ||
| 1653 | + GE_ASSERT_SUCCESS(SaveMergedReshapeAxisChanges(node1, merged_axis_changes)); | ||
| 1654 | + GE_ASSERT_SUCCESS(SaveMergedReshapeAxisChanges(node2, merged_axis_changes)); | ||
| 1655 | + return SUCCESS; | ||
| 1656 | +} | ||
| 1657 | + | ||
| 1658 | +// Backend 融合属性继承接口:两个 backend 节点融合成新 backend 节点时,将两侧保存的 reshape 轴变化 | ||
| 1659 | +// 元数据继承到新节点。此处不重映射 axis id,后续由 FlushReshapeAxisChanges 统一刷新。 | ||
| 1660 | +inline void InheritReshapeAxisChanges(AutofuseInnerAttrs &attr_new, const AutofuseInnerAttrs &attr1, | ||
| 1661 | + const AutofuseInnerAttrs &attr2) { | ||
| 1662 | + attr_new.reshape_axis_changes.clear(); | ||
| 1663 | + for (const auto &axis_change : attr1.reshape_axis_changes) { | ||
| 1664 | + AppendUniqueReshapeAxisChange(axis_change, attr_new.reshape_axis_changes); | ||
| 1665 | + } | ||
| 1666 | + for (const auto &axis_change : attr2.reshape_axis_changes) { | ||
| 1667 | + AppendUniqueReshapeAxisChange(axis_change, attr_new.reshape_axis_changes); | ||
| 1668 | + } | ||
| 1669 | +} | ||
| 1670 | + | ||
| 1671 | +inline Status FlushReshapeAxisByRepeats(const NodePtr &node, const NodePtr &asc_node, | ||
| 1672 | + const std::vector<int64_t> &axis_before_Flush, | ||
| 1673 | + const std::vector<int64_t> &axis_after_Flush, | ||
| 1674 | + const std::vector<Expression> &reshape_repeats, | ||
| 1675 | + std::vector<int64_t> &reshape_axis, const char *info_name) { | ||
| 1676 | + if (axis_before_Flush.empty() || axis_after_Flush.empty() || reshape_axis.empty()) { | ||
| 1677 | + return SUCCESS; | ||
| 1678 | + } | ||
| 1679 | + | ||
| 1680 | + GE_ASSERT_TRUE(axis_before_Flush.size() == axis_after_Flush.size(), | ||
| 1681 | + "axis_before_Flush size %zu must equal to axis_after_Flush size %zu", axis_before_Flush.size(), | ||
| 1682 | + axis_after_Flush.size()); | ||
| 1683 | + GE_ASSERT_TRUE(reshape_axis.size() == reshape_repeats.size(), "reshape axis size %zu must equal repeats size %zu", | ||
| 1684 | + reshape_axis.size(), reshape_repeats.size()); | ||
| 1685 | + | ||
| 1686 | + std::unordered_map<int64_t, size_t> axis_before_to_index; | ||
| 1687 | + for (size_t i = 0U; i < axis_before_Flush.size(); ++i) { | ||
| 1688 | + axis_before_to_index[axis_before_Flush[i]] = i; | ||
| 1689 | + } | ||
| 1690 | + | ||
| 1691 | + std::vector<int64_t> updated_axis; | ||
| 1692 | + updated_axis.reserve(reshape_axis.size()); | ||
| 1693 | + for (size_t i = 0U; i < reshape_axis.size(); ++i) { | ||
| 1694 | + const auto axis = reshape_axis[i]; | ||
| 1695 | + auto it = axis_before_to_index.find(axis); | ||
| 1696 | + if (it != axis_before_to_index.end()) { | ||
| 1697 | + updated_axis.push_back(axis_after_Flush[it->second]); | ||
| 1698 | + continue; | ||
| 1699 | + } | ||
| 1700 | + if (BackendUtils::IsEqOne(reshape_repeats[i]) && (reshape_axis.size() == axis_after_Flush.size())) { | ||
| 1701 | + updated_axis.push_back(axis_after_Flush[i]); | ||
| 1702 | + continue; | ||
| 1703 | + } | ||
| 1704 | + GELOGW("Axis %ld in %s not found in axis_before_Flush for asc_node %s, keep original value", axis, info_name, | ||
| 1705 | + asc_node->GetNamePtr()); | ||
| 1706 | + updated_axis.push_back(axis); | ||
| 1707 | + } | ||
| 1708 | + | ||
| 1709 | + GELOGD("Flush %s for node %s, asc_node %s, before: %s, after: %s", info_name, node->GetNamePtr(), | ||
| 1710 | + asc_node->GetNamePtr(), AutofuseUtils::VectorToStr(reshape_axis).c_str(), | ||
| 1711 | + AutofuseUtils::VectorToStr(updated_axis).c_str()); | ||
| 1712 | + reshape_axis = updated_axis; | ||
| 1713 | + return SUCCESS; | ||
| 1714 | +} | ||
| 1715 | + | ||
| 1716 | +// Backend reshape 轴元数据刷新接口:FlushAscSubGraphAxisInfo 转换 AscGraph 轴 id 后,同步刷新 backend | ||
| 1717 | +// 节点中保存的 before_axis/after_axis,避免后续 can-fuse 或后处理读取到过期 axis id。 | ||
| 1718 | +inline Status FlushReshapeAxisChanges(const NodePtr &node, const NodePtr &asc_node, | ||
| 1719 | + const std::vector<int64_t> &axis_before_Flush, | ||
| 1720 | + const std::vector<int64_t> &axis_after_Flush) { | ||
| 1721 | + auto autofuse_attr = BackendUtils::GetNodeAutoFuseAttr(node); | ||
| 1722 | + GE_ASSERT_NOTNULL(autofuse_attr); | ||
| 1723 | + auto reshape_axis_changes = autofuse_attr->GetReshapeAxisChanges(); | ||
| 1724 | + if (reshape_axis_changes.empty()) { | ||
| 1725 | + return SUCCESS; | ||
| 1726 | + } | ||
| 1727 | + | ||
| 1728 | + for (auto &change : reshape_axis_changes) { | ||
| 1729 | + GE_ASSERT_SUCCESS(FlushReshapeAxisByRepeats(node, asc_node, axis_before_Flush, axis_after_Flush, | ||
| 1730 | + change.before_repeats, change.before_axis, "reshape_before_axis")); | ||
| 1731 | + GE_ASSERT_SUCCESS(FlushReshapeAxisByRepeats(node, asc_node, axis_before_Flush, axis_after_Flush, | ||
| 1732 | + change.after_repeats, change.after_axis, "reshape_after_axis")); | ||
| 1733 | + } | ||
| 1734 | + autofuse_attr->SetReshapeAxisChanges(reshape_axis_changes); | ||
| 1735 | + | ||
| 1736 | + return SUCCESS; | ||
| 1737 | +} | ||
| 1738 | + | ||
| 1739 | +} // namespace asc_adapt | ||
| 1740 | +} // namespace ge | ||
| 1741 | + | ||
| @@ -52,6 +52,18 @@ enum class SplitFusionRatioRequirementState : uint32_t { | |||
| 52 | SATISFIED = 2U // 融合比例满足阈值要求 | 52 | SATISFIED = 2U // 融合比例满足阈值要求 |
| 53 | }; | 53 | }; |
| 54 | 54 | ||
| 55 | +struct ReshapeAxisChangeInfo { | ||
| 56 | + std::vector<int64_t> before_axis; | ||
| 57 | + std::vector<Expression> before_repeats; | ||
| 58 | + std::vector<int64_t> after_axis; | ||
| 59 | + std::vector<Expression> after_repeats; | ||
| 60 | +}; | ||
| 61 | + | ||
| 62 | +struct ReduceOriginalAxisInfo { | ||
| 63 | + std::vector<int64_t> axis; | ||
| 64 | + std::vector<Expression> repeats; | ||
| 65 | +}; | ||
| 66 | + | ||
| 55 | struct AutofuseInnerAttrs { | 67 | struct AutofuseInnerAttrs { |
| 56 | std::vector<const af::Node *> origin_nodes; // Asc节点对应的原始节点,用于Dfx打印、获取融合前ComputeGraph片段等 | 68 | std::vector<const af::Node *> origin_nodes; // Asc节点对应的原始节点,用于Dfx打印、获取融合前ComputeGraph片段等 |
| 57 | std::vector<af::OutDataAnchor *> output_buffers; // Asc节点负责写入的原始输出anchor,用于lifting | 69 | std::vector<af::OutDataAnchor *> output_buffers; // Asc节点负责写入的原始输出anchor,用于lifting |
| @@ -76,7 +88,9 @@ struct AutofuseInnerAttrs { | |||
| 76 | bool is_fuse_from_lowering = false; // 标识融合节点来自lowering还是can_fuse | 88 | bool is_fuse_from_lowering = false; // 标识融合节点来自lowering还是can_fuse |
| 77 | std::vector<int64_t> reduce_original_axis; // reduce操作前的原始轴信息 | 89 | std::vector<int64_t> reduce_original_axis; // reduce操作前的原始轴信息 |
| 78 | std::vector<Expression> reduce_original_repeats; // reduce操作前的原始repeats信息 | 90 | std::vector<Expression> reduce_original_repeats; // reduce操作前的原始repeats信息 |
| 79 | - int32_t is_reduce_all_load = REDUCE_ALL_LOAD_INIT; // 标识reduce是否所有load都是norm-like | 91 | + std::map<std::string, ReduceOriginalAxisInfo> reduce_original_axis_infos; // 每个reduce节点操作前的原始轴信息 |
| 92 | + std::vector<ReshapeAxisChangeInfo> reshape_axis_changes; // 每个reshape操作前后的轴变化信息 | ||
| 93 | + int32_t is_reduce_all_load = REDUCE_ALL_LOAD_INIT; // 标识reduce是否所有load都是norm-like | ||
| 80 | 94 | ||
| 81 | bool IsReduction() const { | 95 | bool IsReduction() const { |
| 82 | return HasFuseType(loop::FuseType::kReduction); | 96 | return HasFuseType(loop::FuseType::kReduction); |
| @@ -92,7 +106,12 @@ using AfAttrGroupsBase = af::AttrGroupsBase; | |||
| 92 | class AutoFuseAttrs : public AfAttrGroupsBase { | 106 | class AutoFuseAttrs : public AfAttrGroupsBase { |
| 93 | public: | 107 | public: |
| 94 | AutoFuseAttrs() = default; | 108 | AutoFuseAttrs() = default; |
| 95 | - AutoFuseAttrs(const AutoFuseAttrs &other) : fuse_type_(other.fuse_type_), asc_graph_(other.asc_graph_) {} | 109 | + AutoFuseAttrs(const AutoFuseAttrs &other) : fuse_type_(other.fuse_type_), asc_graph_(other.asc_graph_) { |
| 110 | + inner_attrs_.reduce_original_axis = other.inner_attrs_.reduce_original_axis; | ||
| 111 | + inner_attrs_.reduce_original_repeats = other.inner_attrs_.reduce_original_repeats; | ||
| 112 | + inner_attrs_.reduce_original_axis_infos = other.inner_attrs_.reduce_original_axis_infos; | ||
| 113 | + inner_attrs_.reshape_axis_changes = other.inner_attrs_.reshape_axis_changes; | ||
| 114 | + } | ||
| 96 | AutoFuseAttrs &operator=(const AutoFuseAttrs &other) = delete; | 115 | AutoFuseAttrs &operator=(const AutoFuseAttrs &other) = delete; |
| 97 | 116 | ||
| 98 | [[nodiscard]] const std::shared_ptr<AscGraph> &GetAscGraph() const { | 117 | [[nodiscard]] const std::shared_ptr<AscGraph> &GetAscGraph() const { |
| @@ -229,18 +248,66 @@ class AutoFuseAttrs : public AfAttrGroupsBase { | |||
| 229 | inner_attrs_.reduce_original_axis = axis; | 248 | inner_attrs_.reduce_original_axis = axis; |
| 230 | } | 249 | } |
| 231 | 250 | ||
| 251 | + void SetReduceOriginalAxis(const std::string &node_name, const std::vector<int64_t> &axis) { | ||
| 252 | + inner_attrs_.reduce_original_axis_infos[node_name].axis = axis; | ||
| 253 | + SetReduceOriginalAxis(axis); | ||
| 254 | + } | ||
| 255 | + | ||
| 232 | [[nodiscard]] const std::vector<int64_t> &GetReduceOriginalAxis() const { | 256 | [[nodiscard]] const std::vector<int64_t> &GetReduceOriginalAxis() const { |
| 233 | return inner_attrs_.reduce_original_axis; | 257 | return inner_attrs_.reduce_original_axis; |
| 234 | } | 258 | } |
| 235 | 259 | ||
| 260 | + [[nodiscard]] const std::vector<int64_t> &GetReduceOriginalAxis(const std::string &node_name) const { | ||
| 261 | + const auto it = inner_attrs_.reduce_original_axis_infos.find(node_name); | ||
| 262 | + if (it != inner_attrs_.reduce_original_axis_infos.end()) { | ||
| 263 | + return it->second.axis; | ||
| 264 | + } | ||
| 265 | + return GetReduceOriginalAxis(); | ||
| 266 | + } | ||
| 267 | + | ||
| 236 | void SetReduceOriginalRepeats(const std::vector<Expression> &repeats) { | 268 | void SetReduceOriginalRepeats(const std::vector<Expression> &repeats) { |
| 237 | inner_attrs_.reduce_original_repeats = repeats; | 269 | inner_attrs_.reduce_original_repeats = repeats; |
| 238 | } | 270 | } |
| 239 | 271 | ||
| 272 | + void SetReduceOriginalRepeats(const std::string &node_name, const std::vector<Expression> &repeats) { | ||
| 273 | + inner_attrs_.reduce_original_axis_infos[node_name].repeats = repeats; | ||
| 274 | + SetReduceOriginalRepeats(repeats); | ||
| 275 | + } | ||
| 276 | + | ||
| 240 | [[nodiscard]] const std::vector<Expression> &GetReduceOriginalRepeats() const { | 277 | [[nodiscard]] const std::vector<Expression> &GetReduceOriginalRepeats() const { |
| 241 | return inner_attrs_.reduce_original_repeats; | 278 | return inner_attrs_.reduce_original_repeats; |
| 242 | } | 279 | } |
| 243 | 280 | ||
| 281 | + [[nodiscard]] const std::vector<Expression> &GetReduceOriginalRepeats(const std::string &node_name) const { | ||
| 282 | + const auto it = inner_attrs_.reduce_original_axis_infos.find(node_name); | ||
| 283 | + if (it != inner_attrs_.reduce_original_axis_infos.end()) { | ||
| 284 | + return it->second.repeats; | ||
| 285 | + } | ||
| 286 | + return GetReduceOriginalRepeats(); | ||
| 287 | + } | ||
| 288 | + | ||
| 289 | + void SetReduceOriginalAxisInfo(const std::string &node_name, const std::vector<int64_t> &axis, | ||
| 290 | + const std::vector<Expression> &repeats) { | ||
| 291 | + SetReduceOriginalAxis(node_name, axis); | ||
| 292 | + SetReduceOriginalRepeats(node_name, repeats); | ||
| 293 | + } | ||
| 294 | + | ||
| 295 | + [[nodiscard]] const std::map<std::string, ReduceOriginalAxisInfo> &GetReduceOriginalAxisInfos() const { | ||
| 296 | + return inner_attrs_.reduce_original_axis_infos; | ||
| 297 | + } | ||
| 298 | + | ||
| 299 | + void AddReshapeAxisChange(const ReshapeAxisChangeInfo &change) { | ||
| 300 | + inner_attrs_.reshape_axis_changes.push_back(change); | ||
| 301 | + } | ||
| 302 | + | ||
| 303 | + void SetReshapeAxisChanges(const std::vector<ReshapeAxisChangeInfo> &changes) { | ||
| 304 | + inner_attrs_.reshape_axis_changes = changes; | ||
| 305 | + } | ||
| 306 | + | ||
| 307 | + [[nodiscard]] const std::vector<ReshapeAxisChangeInfo> &GetReshapeAxisChanges() const { | ||
| 308 | + return inner_attrs_.reshape_axis_changes; | ||
| 309 | + } | ||
| 310 | + | ||
| 244 | void SetReduceAllLoadState(const int32_t state) { | 311 | void SetReduceAllLoadState(const int32_t state) { |
| 245 | inner_attrs_.is_reduce_all_load = state; | 312 | inner_attrs_.is_reduce_all_load = state; |
| 246 | } | 313 | } |
| @@ -27,6 +27,7 @@ | |||
| 27 | 27 | ||
| 28 | 28 | ||
| 29 | 29 | ||
| 30 | + | ||
| 30 | 31 | ||
| 31 | 32 | ||
| 32 | 33 | ||
| @@ -15632,6 +15633,245 @@ TEST_F(AscBackendPostProcessorTest, GatherInsertCastImproveprecision) { | |||
| 15632 | EXPECT_NE(cnt, 2); | 15633 | EXPECT_NE(cnt, 2); |
| 15633 | } | 15634 | } |
| 15634 | 15635 | ||
| 15636 | +struct ReshapeAxisPaddingCase { | ||
| 15637 | + ComputeGraphPtr outer_graph; | ||
| 15638 | + NodePtr asc_backend; | ||
| 15639 | + AutoFuseAttrs *attr = nullptr; | ||
| 15640 | +}; | ||
| 15641 | + | ||
| 15642 | +void BuildBestOverlapReshapeCase(ReshapeAxisPaddingCase &test_case) { | ||
| 15643 | + GraphBuilder builder("best_overlap_reshape_outer"); | ||
| 15644 | + test_case.asc_backend = | ||
| 15645 | + builder.AddNode("best_overlap_reshape_backend", kAscBackendType, 1, 1, FORMAT_ND, DT_FLOAT16, {4, 15120}); | ||
| 15646 | + ASSERT_NE(test_case.asc_backend, nullptr); | ||
| 15647 | + test_case.attr = GetOrCreateAutoFuseAttrs(test_case.asc_backend->GetOpDesc()); | ||
| 15648 | + ASSERT_NE(test_case.attr, nullptr); | ||
| 15649 | + | ||
| 15650 | + ge::AscGraph graph("best_overlap_reshape_graph"); | ||
| 15651 | + const auto one = Symbol(1); | ||
| 15652 | + const auto size0 = Symbol(4); | ||
| 15653 | + const auto size1 = Symbol(15120); | ||
| 15654 | + auto z0 = graph.CreateAxis("z0", size0); | ||
| 15655 | + auto z1 = graph.CreateAxis("z1", size1); | ||
| 15656 | + const std::vector<int64_t> graph_axis = {z0.id, z1.id}; | ||
| 15657 | + | ||
| 15658 | + af::ascir_op::Data data("best_overlap_data", graph); | ||
| 15659 | + data.attr.sched.axis = graph_axis; | ||
| 15660 | + data.y.dtype = DT_FLOAT16; | ||
| 15661 | + *data.y.axis = graph_axis; | ||
| 15662 | + *data.y.repeats = {size0, size1}; | ||
| 15663 | + *data.y.strides = {size1, one}; | ||
| 15664 | + | ||
| 15665 | + af::ascir_op::Load load("best_overlap_load"); | ||
| 15666 | + load.x = data.y; | ||
| 15667 | + load.attr.sched.axis = graph_axis; | ||
| 15668 | + load.y.dtype = DT_FLOAT16; | ||
| 15669 | + *load.y.axis = graph_axis; | ||
| 15670 | + *load.y.repeats = {size0, size1}; | ||
| 15671 | + *load.y.strides = {size1, one}; | ||
| 15672 | + | ||
| 15673 | + af::ascir_op::Store store("best_overlap_store"); | ||
| 15674 | + store.x = load.y; | ||
| 15675 | + store.attr.sched.axis = graph_axis; | ||
| 15676 | + store.y.dtype = DT_FLOAT16; | ||
| 15677 | + *store.y.axis = graph_axis; | ||
| 15678 | + *store.y.repeats = {size0, size1}; | ||
| 15679 | + *store.y.strides = {size1, one}; | ||
| 15680 | + test_case.attr->SetAscGraph(std::shared_ptr<ge::AscGraph>(new ge::AscGraph(graph)), loop::FuseType::kPointwise); | ||
| 15681 | + | ||
| 15682 | + af::ReshapeAxisChangeInfo change; | ||
| 15683 | + change.before_axis = {0, 1, 2}; | ||
| 15684 | + change.before_repeats = {one, one, one}; | ||
| 15685 | + change.after_axis = {0, 1}; | ||
| 15686 | + change.after_repeats = {one, one}; | ||
| 15687 | + test_case.attr->AddReshapeAxisChange(change); | ||
| 15688 | + test_case.outer_graph = builder.GetGraph(); | ||
| 15689 | +} | ||
| 15690 | + | ||
| 15691 | +void CheckBestOverlapReshapeResult(const std::shared_ptr<ge::AscGraph> &asc_graph) { | ||
| 15692 | + const auto completed_graph_attr = AscGraphUtils::GetComputeGraph(*asc_graph)->GetAttrsGroup<AscGraphAttr>(); | ||
| 15693 | + ASSERT_NE(completed_graph_attr, nullptr); | ||
| 15694 | + ASSERT_EQ(completed_graph_attr->axis.size(), 3U); | ||
| 15695 | + EXPECT_EQ(completed_graph_attr->axis[0]->id, 0); | ||
| 15696 | + EXPECT_EQ(completed_graph_attr->axis[1]->id, 1); | ||
| 15697 | + EXPECT_EQ(completed_graph_attr->axis[2]->id, 2); | ||
| 15698 | + EXPECT_TRUE(BackendUtils::IsEqOne(completed_graph_attr->axis[0]->size)); | ||
| 15699 | + EXPECT_EQ(std::string(completed_graph_attr->axis[1]->size.Str().get()), "4"); | ||
| 15700 | + EXPECT_EQ(std::string(completed_graph_attr->axis[2]->size.Str().get()), "15120"); | ||
| 15701 | + | ||
| 15702 | + auto store_node = asc_graph->FindNode("best_overlap_store"); | ||
| 15703 | + ASSERT_NE(store_node, nullptr); | ||
| 15704 | + AscTensorAttr *store_attr = nullptr; | ||
| 15705 | + ASSERT_EQ(asc_adapt::GetOutputTensorAttr(store_node, store_attr), SUCCESS); | ||
| 15706 | + ASSERT_NE(store_attr, nullptr); | ||
| 15707 | + EXPECT_EQ(store_attr->axis, std::vector<int64_t>({0, 1, 2})); | ||
| 15708 | + ASSERT_EQ(store_attr->repeats.size(), 3U); | ||
| 15709 | + EXPECT_TRUE(BackendUtils::IsEqOne(store_attr->repeats[0])); | ||
| 15710 | + EXPECT_EQ(std::string(store_attr->repeats[1].Str().get()), "4"); | ||
| 15711 | + EXPECT_EQ(std::string(store_attr->repeats[2].Str().get()), "15120"); | ||
| 15712 | + ASSERT_EQ(store_attr->strides.size(), 3U); | ||
| 15713 | + EXPECT_TRUE(BackendUtils::IsEqZero(store_attr->strides[0])); | ||
| 15714 | + EXPECT_EQ(std::string(store_attr->strides[1].Str().get()), "15120"); | ||
| 15715 | + EXPECT_TRUE(BackendUtils::IsEqOne(store_attr->strides[2])); | ||
| 15716 | +} | ||
| 15717 | + | ||
| 15718 | +void BuildMultipleReshapeAxisChangesCase(ReshapeAxisPaddingCase &test_case) { | ||
| 15719 | + GraphBuilder builder("multi_reshape_outer"); | ||
| 15720 | + test_case.asc_backend = | ||
| 15721 | + builder.AddNode("multi_reshape_backend", kAscBackendType, 1, 1, FORMAT_ND, DT_FLOAT16, {22, 15120, 1}); | ||
| 15722 | + ASSERT_NE(test_case.asc_backend, nullptr); | ||
| 15723 | + test_case.attr = GetOrCreateAutoFuseAttrs(test_case.asc_backend->GetOpDesc()); | ||
| 15724 | + ASSERT_NE(test_case.attr, nullptr); | ||
| 15725 | + | ||
| 15726 | + ge::AscGraph graph("multi_reshape_axis_graph"); | ||
| 15727 | + auto z0 = graph.CreateAxis("z0", Symbol(22)); | ||
| 15728 | + auto z1 = graph.CreateAxis("z1", Symbol(15120)); | ||
| 15729 | + auto z2 = graph.CreateAxis("z2", Symbol(1)); | ||
| 15730 | + af::ascir_op::Data data("data", graph); | ||
| 15731 | + data.attr.sched.axis = {z0.id, z1.id, z2.id}; | ||
| 15732 | + data.y.dtype = DT_FLOAT16; | ||
| 15733 | + *data.y.axis = {z0.id, z1.id, z2.id}; | ||
| 15734 | + *data.y.repeats = {Symbol(22), Symbol(15120), Symbol(1)}; | ||
| 15735 | + *data.y.strides = {Symbol(15120), Symbol(1), Symbol(0)}; | ||
| 15736 | + | ||
| 15737 | + af::ascir_op::Load load("load"); | ||
| 15738 | + load.x = data.y; | ||
| 15739 | + load.attr.sched.axis = {z0.id, z1.id, z2.id}; | ||
| 15740 | + load.y.dtype = DT_FLOAT16; | ||
| 15741 | + *load.y.axis = {z0.id, z1.id, z2.id}; | ||
| 15742 | + *load.y.repeats = {Symbol(22), Symbol(15120), Symbol(1)}; | ||
| 15743 | + *load.y.strides = {Symbol(15120), Symbol(1), Symbol(0)}; | ||
| 15744 | + | ||
| 15745 | + af::ascir_op::Store store("store"); | ||
| 15746 | + store.x = load.y; | ||
| 15747 | + store.attr.sched.axis = {z0.id, z1.id, z2.id}; | ||
| 15748 | + store.y.dtype = DT_FLOAT16; | ||
| 15749 | + *store.y.axis = {z0.id, z1.id, z2.id}; | ||
| 15750 | + *store.y.repeats = {Symbol(22), Symbol(15120), Symbol(1)}; | ||
| 15751 | + *store.y.strides = {Symbol(15120), Symbol(1), Symbol(0)}; | ||
| 15752 | + test_case.attr->SetAscGraph(std::shared_ptr<ge::AscGraph>(new ge::AscGraph(graph)), loop::FuseType::kPointwise); | ||
| 15753 | + | ||
| 15754 | + af::ReshapeAxisChangeInfo squeeze_change; | ||
| 15755 | + squeeze_change.before_axis = {0, 1, 2}; | ||
| 15756 | + squeeze_change.before_repeats = {Symbol(1), Symbol(22), Symbol(15120)}; | ||
| 15757 | + squeeze_change.after_axis = {0, 1}; | ||
| 15758 | + squeeze_change.after_repeats = {Symbol(22), Symbol(15120)}; | ||
| 15759 | + test_case.attr->AddReshapeAxisChange(squeeze_change); | ||
| 15760 | + | ||
| 15761 | + af::ReshapeAxisChangeInfo unsqueeze_change; | ||
| 15762 | + unsqueeze_change.before_axis = {0, 1}; | ||
| 15763 | + unsqueeze_change.before_repeats = {Symbol(22), Symbol(15120)}; | ||
| 15764 | + unsqueeze_change.after_axis = {0, 1, 2}; | ||
| 15765 | + unsqueeze_change.after_repeats = {Symbol(22), Symbol(15120), Symbol(1)}; | ||
| 15766 | + test_case.attr->AddReshapeAxisChange(unsqueeze_change); | ||
| 15767 | + test_case.outer_graph = builder.GetGraph(); | ||
| 15768 | +} | ||
| 15769 | + | ||
| 15770 | +void CheckMultipleReshapeAxisChangesResult(const std::shared_ptr<ge::AscGraph> &asc_graph) { | ||
| 15771 | + const auto graph_attr = AscGraphUtils::GetComputeGraph(*asc_graph)->GetAttrsGroup<AscGraphAttr>(); | ||
| 15772 | + ASSERT_NE(graph_attr, nullptr); | ||
| 15773 | + EXPECT_EQ(graph_attr->axis.size(), 4U); | ||
| 15774 | + | ||
| 15775 | + std::vector<int64_t> graph_axis_after_second_pad; | ||
| 15776 | + for (const auto &axis : graph_attr->axis) { | ||
| 15777 | + ASSERT_NE(axis, nullptr); | ||
| 15778 | + graph_axis_after_second_pad.push_back(axis->id); | ||
| 15779 | + } | ||
| 15780 | + auto store_node = asc_graph->FindNode("store"); | ||
| 15781 | + ASSERT_NE(store_node, nullptr); | ||
| 15782 | + AscTensorAttr *store_attr = nullptr; | ||
| 15783 | + ASSERT_EQ(asc_adapt::GetOutputTensorAttr(store_node, store_attr), SUCCESS); | ||
| 15784 | + ASSERT_NE(store_attr, nullptr); | ||
| 15785 | + EXPECT_EQ(store_attr->axis, graph_axis_after_second_pad); | ||
| 15786 | + EXPECT_EQ(store_attr->axis.size(), 4U); | ||
| 15787 | + EXPECT_EQ(store_attr->repeats.size(), 4U); | ||
| 15788 | + EXPECT_EQ(store_attr->strides.size(), 4U); | ||
| 15789 | +} | ||
| 15790 | + | ||
| 15791 | +void CheckKeepOriginalAxisIdsReshapeResult(const ReshapeAxisPaddingCase &test_case) { | ||
| 15792 | + const auto graph_attr = | ||
| 15793 | + AscGraphUtils::GetComputeGraph(*(test_case.attr->GetAscGraph()))->GetAttrsGroup<AscGraphAttr>(); | ||
| 15794 | + ASSERT_NE(graph_attr, nullptr); | ||
| 15795 | + ASSERT_EQ(graph_attr->axis.size(), 4U); | ||
| 15796 | + EXPECT_EQ(graph_attr->axis[0]->id, 0); | ||
| 15797 | + EXPECT_EQ(graph_attr->axis[1]->id, 3); | ||
| 15798 | + EXPECT_EQ(graph_attr->axis[2]->id, 1); | ||
| 15799 | + EXPECT_EQ(graph_attr->axis[3]->id, 2); | ||
| 15800 | + | ||
| 15801 | + auto store_node = test_case.attr->GetAscGraph()->FindNode("store"); | ||
| 15802 | + ASSERT_NE(store_node, nullptr); | ||
| 15803 | + AscTensorAttr *store_attr = nullptr; | ||
| 15804 | + ASSERT_EQ(asc_adapt::GetOutputTensorAttr(store_node, store_attr), SUCCESS); | ||
| 15805 | + ASSERT_NE(store_attr, nullptr); | ||
| 15806 | + EXPECT_EQ(store_attr->axis, std::vector<int64_t>({0, 3, 1, 2})); | ||
| 15807 | + ASSERT_EQ(store_attr->repeats.size(), 4U); | ||
| 15808 | + EXPECT_TRUE(BackendUtils::IsEqOne(store_attr->repeats[1])); | ||
| 15809 | + ASSERT_EQ(store_attr->strides.size(), 4U); | ||
| 15810 | + EXPECT_TRUE(BackendUtils::IsEqZero(store_attr->strides[1])); | ||
| 15811 | + | ||
| 15812 | + const auto &reshape_axis_changes = test_case.attr->GetReshapeAxisChanges(); | ||
| 15813 | + ASSERT_EQ(reshape_axis_changes.size(), 2U); | ||
| 15814 | + EXPECT_EQ(reshape_axis_changes[0].before_axis, std::vector<int64_t>({0, 1, 2})); | ||
| 15815 | + EXPECT_EQ(reshape_axis_changes[0].after_axis, std::vector<int64_t>({0, 1})); | ||
| 15816 | + EXPECT_EQ(reshape_axis_changes[1].before_axis, std::vector<int64_t>({0, 1})); | ||
| 15817 | + EXPECT_EQ(reshape_axis_changes[1].after_axis, std::vector<int64_t>({0, 1, 2})); | ||
| 15818 | + | ||
| 15819 | + const auto &axis_group = GetInterAttrs(test_case.attr).axis_group; | ||
| 15820 | + EXPECT_EQ(axis_group.y_group, std::vector<int64_t>({0, 1, 2, 3})); | ||
| 15821 | + EXPECT_TRUE(axis_group.n_group.empty()); | ||
| 15822 | + EXPECT_EQ(axis_group.axes_order, std::vector<size_t>({0U, 3U, 1U, 2U})); | ||
| 15823 | +} | ||
| 15824 | + | ||
| 15825 | +TEST_F(AscBackendPostProcessorTest, CompleteAttrs_RestoreReshapeAxisByBestOverlap) { | ||
| 15826 | + ReshapeAxisPaddingCase test_case; | ||
| 15827 | + ASSERT_NO_FATAL_FAILURE(BuildBestOverlapReshapeCase(test_case)); | ||
| 15828 | + ASSERT_NE(test_case.outer_graph, nullptr); | ||
| 15829 | + ASSERT_EQ(asc_adapt::PadLeadingUnitAxisByInsertIndexesAndCompleteAttrs(*(test_case.attr->GetAscGraph()), | ||
| 15830 | + test_case.asc_backend, {0U}), | ||
| 15831 | + SUCCESS); | ||
| 15832 | + ASSERT_NO_FATAL_FAILURE(CheckBestOverlapReshapeResult(test_case.attr->GetAscGraph())); | ||
| 15833 | +} | ||
| 15834 | + | ||
| 15835 | +TEST_F(AscBackendPostProcessorTest, CompleteAttrs_RestoreMultipleReshapeAxisChangesByInsertIndexes) { | ||
| 15836 | + ReshapeAxisPaddingCase test_case; | ||
| 15837 | + ASSERT_NO_FATAL_FAILURE(BuildMultipleReshapeAxisChangesCase(test_case)); | ||
| 15838 | + ASSERT_NE(test_case.outer_graph, nullptr); | ||
| 15839 | + ASSERT_EQ(asc_adapt::PadLeadingUnitAxisByInsertIndexesAndCompleteAttrs(*(test_case.attr->GetAscGraph()), | ||
| 15840 | + test_case.asc_backend, {0U}), | ||
| 15841 | + SUCCESS); | ||
| 15842 | + const auto &reshape_axis_changes = test_case.attr->GetReshapeAxisChanges(); | ||
| 15843 | + ASSERT_EQ(reshape_axis_changes.size(), 2U); | ||
| 15844 | + EXPECT_EQ(reshape_axis_changes[0].before_axis, std::vector<int64_t>({1, 2, 3})); | ||
| 15845 | + EXPECT_EQ(reshape_axis_changes[0].after_axis, std::vector<int64_t>({1, 2})); | ||
| 15846 | + EXPECT_EQ(reshape_axis_changes[1].before_axis, std::vector<int64_t>({1, 2})); | ||
| 15847 | + EXPECT_EQ(reshape_axis_changes[1].after_axis, std::vector<int64_t>({1, 2, 3})); | ||
| 15848 | + auto graph_attr = AscGraphUtils::GetComputeGraph(*(test_case.attr->GetAscGraph()))->GetAttrsGroup<AscGraphAttr>(); | ||
| 15849 | + ASSERT_NE(graph_attr, nullptr); | ||
| 15850 | + ASSERT_EQ(graph_attr->axis.size(), 4U); | ||
| 15851 | + ASSERT_NO_FATAL_FAILURE(CheckMultipleReshapeAxisChangesResult(test_case.attr->GetAscGraph())); | ||
| 15852 | +} | ||
| 15853 | + | ||
| 15854 | +TEST_F(AscBackendPostProcessorTest, CompleteAttrs_RestoreReshapeAxisKeepOriginalAxisIds) { | ||
| 15855 | + ReshapeAxisPaddingCase test_case; | ||
| 15856 | + ASSERT_NO_FATAL_FAILURE(BuildMultipleReshapeAxisChangesCase(test_case)); | ||
| 15857 | + ASSERT_NE(test_case.outer_graph, nullptr); | ||
| 15858 | + GetInterAttrs(test_case.attr).axis_group.y_group = {0, 1, 2}; | ||
| 15859 | + GetInterAttrs(test_case.attr).axis_group.axes_order = {0U, 1U, 2U}; | ||
| 15860 | + ASSERT_EQ(asc_adapt::PadLeadingUnitAxisByInsertIndexesAndCompleteAttrsKeepOriginalAxisIds( | ||
| 15861 | + *(test_case.attr->GetAscGraph()), test_case.asc_backend, {1U}), | ||
| 15862 | + SUCCESS); | ||
| 15863 | + ASSERT_NO_FATAL_FAILURE(CheckKeepOriginalAxisIdsReshapeResult(test_case)); | ||
| 15864 | +} | ||
| 15865 | + | ||
| 15866 | +TEST_F(AscBackendPostProcessorTest, CollectInsertIndexesByTargetRepeatsKeepsLaterGapPosition) { | ||
| 15867 | + std::vector<size_t> insert_indexes; | ||
| 15868 | + ASSERT_EQ(asc_adapt::CollectInsertIndexesByTargetRepeats( | ||
| 15869 | + {Symbol(2), Symbol(1024), Symbol(1024)}, {Symbol(2), Symbol(1024), Symbol(1), Symbol(1024), Symbol(1)}, | ||
| 15870 | + insert_indexes), | ||
| 15871 | + SUCCESS); | ||
| 15872 | + EXPECT_EQ(insert_indexes, std::vector<size_t>({2U, 4U})); | ||
| 15873 | +} | ||
| 15874 | + | ||
| 15635 | TEST_F(AscBackendPostProcessorTest, CompleteAttrWithGraphInvalidAxisNodeValidAxis) { | 15875 | TEST_F(AscBackendPostProcessorTest, CompleteAttrWithGraphInvalidAxisNodeValidAxis) { |
| 15636 | ComputeGraphPtr compute_graph = BuildGraph1("AscBackend"); | 15876 | ComputeGraphPtr compute_graph = BuildGraph1("AscBackend"); |
| 15637 | EXPECT_EQ(compute_graph->GetAllNodesSize(), 5); | 15877 | EXPECT_EQ(compute_graph->GetAllNodesSize(), 5); |
| @@ -1877,7 +1877,8 @@ TEST_F(AscGraphAxisMappingTest, AscBackendFusionDecider_CreateSubGraphAxisMapInf | |||
| 1877 | EXPECT_EQ(asc_graph_axis_map.CreateSubGraphAxisMapInfo(addn1, shape1, node_fuse_info), SUCCESS); | 1877 | EXPECT_EQ(asc_graph_axis_map.CreateSubGraphAxisMapInfo(addn1, shape1, node_fuse_info), SUCCESS); |
| 1878 | } | 1878 | } |
| 1879 | 1879 | ||
| 1880 | -TEST_F(AscGraphAxisMappingTest, AscBackendFusionDecider_CreateSubGraphAxisMapInfo_For_Reduce_Vertical_Merge_Fail) { | 1880 | +TEST_F(AscGraphAxisMappingTest, |
| 1881 | + AscBackendFusionDecider_CreateSubGraphAxisMapInfo_For_Reduce_Vertical_Merge_UnitAxisFailed) { | ||
| 1881 | AscBackendFusionDecider decider; | 1882 | AscBackendFusionDecider decider; |
| 1882 | ComputeGraphPtr compute_graph = BuildGraph1("AscBackend"); | 1883 | ComputeGraphPtr compute_graph = BuildGraph1("AscBackend"); |
| 1883 | ASSERT_NE(compute_graph, nullptr); | 1884 | ASSERT_NE(compute_graph, nullptr); |
| @@ -43,6 +43,26 @@ class LoopNodeLoweringUT : public testing::Test { | |||
| 43 | std::unique_ptr<es::Graph> es_graph_; | 43 | std::unique_ptr<es::Graph> es_graph_; |
| 44 | }; | 44 | }; |
| 45 | 45 | ||
| 46 | +std::vector<std::string> ToExpressionStrings(const std::vector<Expression> &expressions) { | ||
| 47 | + std::vector<std::string> result; | ||
| 48 | + result.reserve(expressions.size()); | ||
| 49 | + for (const auto &expression : expressions) { | ||
| 50 | + result.emplace_back(expression.Str().get()); | ||
| 51 | + } | ||
| 52 | + return result; | ||
| 53 | +} | ||
| 54 | + | ||
| 55 | +void ExpectReshapeAxisChange(loop::KernelBox &kernel, const std::vector<int64_t> &before_axis, | ||
| 56 | + const std::vector<std::string> &before_repeats, const std::vector<int64_t> &after_axis, | ||
| 57 | + const std::vector<std::string> &after_repeats) { | ||
| 58 | + const auto &axis_changes = kernel.GetReshapeAxisChanges(); | ||
| 59 | + ASSERT_EQ(axis_changes.size(), 1U); | ||
| 60 | + EXPECT_EQ(axis_changes[0].before_axis, before_axis); | ||
| 61 | + EXPECT_EQ(ToExpressionStrings(axis_changes[0].before_repeats), before_repeats); | ||
| 62 | + EXPECT_EQ(axis_changes[0].after_axis, after_axis); | ||
| 63 | + EXPECT_EQ(ToExpressionStrings(axis_changes[0].after_repeats), after_repeats); | ||
| 64 | +} | ||
| 65 | + | ||
| 46 | TEST_F(LoopNodeLoweringUT, In2Out1Lowering) { | 66 | TEST_F(LoopNodeLoweringUT, In2Out1Lowering) { |
| 47 | [this]() { | 67 | [this]() { |
| 48 | auto data0 = es_graph_->CreateInput(0, "data0", nullptr); | 68 | auto data0 = es_graph_->CreateInput(0, "data0", nullptr); |
| @@ -1763,6 +1783,7 @@ TEST_F(LoopNodeLoweringUT, LoweringUnsqueeze) { | |||
| 1763 | "tmp1 = ops.Unsqueeze(tmp0, 0)\n" | 1783 | "tmp1 = ops.Unsqueeze(tmp0, 0)\n" |
| 1764 | "tmp2 = ops.Unsqueeze(tmp1, 1)\n" | 1784 | "tmp2 = ops.Unsqueeze(tmp1, 1)\n" |
| 1765 | "tmp3 = ops.StoreReshape(\"Unsqueeze_0:0\", tmp2)\n"); | 1785 | "tmp3 = ops.StoreReshape(\"Unsqueeze_0:0\", tmp2)\n"); |
| 1786 | + ExpectReshapeAxisChange(kernel, {0, 1}, {"s0", "2"}, {0, 1, 2, 3}, {"1", "1", "s0", "2"}); | ||
| 1766 | } | 1787 | } |
| 1767 | 1788 | ||
| 1768 | TEST_F(LoopNodeLoweringUT, LoweringSqueeze) { | 1789 | TEST_F(LoopNodeLoweringUT, LoweringSqueeze) { |
| @@ -1788,6 +1809,7 @@ TEST_F(LoopNodeLoweringUT, LoweringSqueeze) { | |||
| 1788 | "tmp2 = ops.Squeeze(tmp1, 2)\n" | 1809 | "tmp2 = ops.Squeeze(tmp1, 2)\n" |
| 1789 | "tmp3 = ops.Squeeze(tmp2, 2)\n" | 1810 | "tmp3 = ops.Squeeze(tmp2, 2)\n" |
| 1790 | "tmp4 = ops.Store(\"Squeeze_0:0\", tmp3)\n"); | 1811 | "tmp4 = ops.Store(\"Squeeze_0:0\", tmp3)\n"); |
| 1812 | + ExpectReshapeAxisChange(kernel, {0, 1, 2, 3, 4}, {"s0", "1", "2", "1", "1"}, {0, 1}, {"s0", "2"}); | ||
| 1791 | } | 1813 | } |
| 1792 | 1814 | ||
| 1793 | TEST_F(LoopNodeLoweringUT, LoweringSqueezeLowerAxisIsNull) { | 1815 | TEST_F(LoopNodeLoweringUT, LoweringSqueezeLowerAxisIsNull) { |
| @@ -2279,6 +2301,8 @@ TEST_F(LoopNodeLoweringUT, LoweringExpandDims) { | |||
| 2279 | "tmp0 = ops.Load(\"data0:0\")\n" | 2301 | "tmp0 = ops.Load(\"data0:0\")\n" |
| 2280 | "tmp1 = ops.Unsqueeze(tmp0, 2)\n" | 2302 | "tmp1 = ops.Unsqueeze(tmp0, 2)\n" |
| 2281 | "tmp2 = ops.StoreReshape(\"ExpandDims_3:0\", tmp1)\n"); | 2303 | "tmp2 = ops.StoreReshape(\"ExpandDims_3:0\", tmp1)\n"); |
| 2304 | + ExpectReshapeAxisChange(kernel, {0, 1}, {"s0", "2"}, {0, 1, 2}, {"s0", "2", "1"}); | ||
| 2305 | + ExpectReshapeAxisChange(kernel1, {0, 1}, {"s0", "2"}, {0, 1, 2}, {"s0", "2", "1"}); | ||
| 2282 | 2306 | ||
| 2283 | auto kernel2 = ge::loop::GetKernelBox(expanddims2->GetOutDataAnchor(0)); | 2307 | auto kernel2 = ge::loop::GetKernelBox(expanddims2->GetOutDataAnchor(0)); |
| 2284 | ASSERT_TRUE(kernel2.IsExternKernel()); | 2308 | ASSERT_TRUE(kernel2.IsExternKernel()); |
| @@ -26,6 +26,7 @@ | |||
| 26 | 26 | ||
| 27 | 27 | ||
| 28 | 28 | ||
| 29 | + | ||
| 29 | 30 | ||
| 30 | 31 | ||
| 31 | 32 | ||
| @@ -108,6 +109,22 @@ NodePtr CreateReduceNodeWithOriginalAxis(const ComputeGraphPtr &graph, const std | |||
| 108 | attr->SetReduceOriginalRepeats(repeats); | 109 | attr->SetReduceOriginalRepeats(repeats); |
| 109 | return node; | 110 | return node; |
| 110 | } | 111 | } |
| 112 | + | ||
| 113 | +NodePtr CreateNodeWithOutputAttr(const ComputeGraphPtr &graph, const std::string &name, | ||
| 114 | + const std::vector<int64_t> &axis, const std::vector<Expression> &repeats) { | ||
| 115 | + auto tensor_desc = std::make_shared<GeTensorDesc>(); | ||
| 116 | + tensor_desc->SetShape(GeShape({1, 1, 1})); | ||
| 117 | + tensor_desc->SetFormat(FORMAT_ND); | ||
| 118 | + tensor_desc->SetDataType(DT_FLOAT); | ||
| 119 | + auto tensor_attr = tensor_desc->GetOrCreateAttrsGroup<AscTensorAttr>(); | ||
| 120 | + tensor_attr->axis = axis; | ||
| 121 | + tensor_attr->repeats = repeats; | ||
| 122 | + | ||
| 123 | + auto op_desc = std::make_shared<OpDesc>(name, kAscBackendType); | ||
| 124 | + op_desc->AddInputDesc(tensor_desc->Clone()); | ||
| 125 | + op_desc->AddOutputDesc(tensor_desc->Clone()); | ||
| 126 | + return graph->AddNode(op_desc); | ||
| 127 | +} | ||
| 111 | } // namespace | 128 | } // namespace |
| 112 | 129 | ||
| 113 | class LoweringAndCanfuseUT : public testing::Test { | 130 | class LoweringAndCanfuseUT : public testing::Test { |
| @@ -318,16 +335,13 @@ class LoweringAndCanfuseUT : public testing::Test { | |||
| 318 | } | 335 | } |
| 319 | } | 336 | } |
| 320 | 337 | ||
| 321 | - void VerifyAscNodeNoSizeOneAxis(const NodePtr &asc_node, bool is_concat) { | 338 | + void VerifyAscNodeAxisAttrs(const NodePtr &asc_node) { |
| 322 | asc_adapt::TensorInfo tensor_desc; | 339 | asc_adapt::TensorInfo tensor_desc; |
| 323 | ASSERT_EQ(asc_adapt::GetTensorInfo(asc_node, tensor_desc), SUCCESS); | 340 | ASSERT_EQ(asc_adapt::GetTensorInfo(asc_node, tensor_desc), SUCCESS); |
| 324 | std::cout << " AscNode: " << asc_node->GetName() << ", Type: " << asc_node->GetType() | 341 | std::cout << " AscNode: " << asc_node->GetName() << ", Type: " << asc_node->GetType() |
| 325 | << ", Repeats: " << AutofuseUtils::VectorToStr(tensor_desc.repeats) << std::endl; | 342 | << ", Repeats: " << AutofuseUtils::VectorToStr(tensor_desc.repeats) << std::endl; |
| 326 | - if (!is_concat) { | 343 | + EXPECT_EQ(tensor_desc.axis.size(), tensor_desc.repeats.size()); |
| 327 | - for (size_t i = 0; i < tensor_desc.repeats.size(); ++i) { | 344 | + EXPECT_EQ(tensor_desc.strides.size(), tensor_desc.repeats.size()); |
| 328 | - EXPECT_NE(tensor_desc.repeats[i], 1) << "Found size=1 axis in " << asc_node->GetName(); | ||
| 329 | - } | ||
| 330 | - } | ||
| 331 | } | 345 | } |
| 332 | 346 | ||
| 333 | void VerifyAscBackendNode(const NodePtr &node) { | 347 | void VerifyAscBackendNode(const NodePtr &node) { |
| @@ -342,7 +356,7 @@ class LoweringAndCanfuseUT : public testing::Test { | |||
| 342 | ASSERT_NE(attr->GetAscGraph(), nullptr); | 356 | ASSERT_NE(attr->GetAscGraph(), nullptr); |
| 343 | 357 | ||
| 344 | for (const auto &asc_node : attr->GetAscGraph()->GetAllNodes()) { | 358 | for (const auto &asc_node : attr->GetAscGraph()->GetAllNodes()) { |
| 345 | - VerifyAscNodeNoSizeOneAxis(asc_node, is_concat); | 359 | + VerifyAscNodeAxisAttrs(asc_node); |
| 346 | } | 360 | } |
| 347 | } | 361 | } |
| 348 | 362 | ||
| @@ -2088,20 +2102,20 @@ TEST_F(LoweringAndCanfuseUT, BroadcastToProdAxisProbe) { | |||
| 2088 | SetCurShapeEnvContext(nullptr); | 2102 | SetCurShapeEnvContext(nullptr); |
| 2089 | } | 2103 | } |
| 2090 | 2104 | ||
| 2091 | -TEST_F(LoweringAndCanfuseUT, ReduceOriginalAxisConflictCanNotFuse) { | 2105 | +TEST_F(LoweringAndCanfuseUT, ReduceOriginalAxisConflictCanFuse) { |
| 2092 | auto graph = std::make_shared<ComputeGraph>("reduce_original_axis_conflict_graph"); | 2106 | auto graph = std::make_shared<ComputeGraph>("reduce_original_axis_conflict_graph"); |
| 2093 | const auto node1 = CreateReduceNodeWithOriginalAxis(graph, "reduce1", {0, 1}, {Symbol(64), Symbol(32)}); | 2107 | const auto node1 = CreateReduceNodeWithOriginalAxis(graph, "reduce1", {0, 1}, {Symbol(64), Symbol(32)}); |
| 2094 | const auto node2 = CreateReduceNodeWithOriginalAxis(graph, "reduce2", {1, 2}, {Symbol(32), Symbol(16)}); | 2108 | const auto node2 = CreateReduceNodeWithOriginalAxis(graph, "reduce2", {1, 2}, {Symbol(32), Symbol(16)}); |
| 2095 | 2109 | ||
| 2096 | - EXPECT_FALSE(ReduceFusionStrategy().CanFuse(node1, node2)); | 2110 | + EXPECT_TRUE(ReduceFusionStrategy().CanFuse(node1, node2)); |
| 2097 | } | 2111 | } |
| 2098 | 2112 | ||
| 2099 | -TEST_F(LoweringAndCanfuseUT, ReduceOriginalRepeatsConflictCanNotFuse) { | 2113 | +TEST_F(LoweringAndCanfuseUT, ReduceOriginalRepeatsConflictCanFuse) { |
| 2100 | auto graph = std::make_shared<ComputeGraph>("reduce_original_repeats_conflict_graph"); | 2114 | auto graph = std::make_shared<ComputeGraph>("reduce_original_repeats_conflict_graph"); |
| 2101 | const auto node1 = CreateReduceNodeWithOriginalAxis(graph, "reduce1", {0, 1}, {Symbol(64), Symbol(32)}); | 2115 | const auto node1 = CreateReduceNodeWithOriginalAxis(graph, "reduce1", {0, 1}, {Symbol(64), Symbol(32)}); |
| 2102 | const auto node2 = CreateReduceNodeWithOriginalAxis(graph, "reduce2", {0, 1}, {Symbol(64), Symbol(16)}); | 2116 | const auto node2 = CreateReduceNodeWithOriginalAxis(graph, "reduce2", {0, 1}, {Symbol(64), Symbol(16)}); |
| 2103 | 2117 | ||
| 2104 | - EXPECT_FALSE(ReduceFusionStrategy().CanFuse(node1, node2)); | 2118 | + EXPECT_TRUE(ReduceFusionStrategy().CanFuse(node1, node2)); |
| 2105 | } | 2119 | } |
| 2106 | 2120 | ||
| 2107 | TEST_F(LoweringAndCanfuseUT, ReduceOriginalAxisCompatibleCanFuse) { | 2121 | TEST_F(LoweringAndCanfuseUT, ReduceOriginalAxisCompatibleCanFuse) { |
| @@ -2112,4 +2126,30 @@ TEST_F(LoweringAndCanfuseUT, ReduceOriginalAxisCompatibleCanFuse) { | |||
| 2112 | EXPECT_TRUE(ReduceFusionStrategy().CanFuse(node1, node2)); | 2126 | EXPECT_TRUE(ReduceFusionStrategy().CanFuse(node1, node2)); |
| 2113 | } | 2127 | } |
| 2114 | 2128 | ||
| 2129 | +TEST_F(LoweringAndCanfuseUT, ReshapePaddingAnchorAlignmentInsertBeforeExistingUnitAxis) { | ||
| 2130 | + auto graph = std::make_shared<ComputeGraph>("reshape_padding_anchor_alignment_graph"); | ||
| 2131 | + const auto node1 = CreateNodeWithOutputAttr(graph, "node1", {0, 2}, {Symbol(4), Symbol(4)}); | ||
| 2132 | + const auto node2 = CreateNodeWithOutputAttr(graph, "node2", {0, 1, 2}, {Symbol(1), Symbol(4), Symbol(4)}); | ||
| 2133 | + std::vector<size_t> insert_indexes = {1U}; | ||
| 2134 | + | ||
| 2135 | + asc_adapt::AdjustInsertIndexesByAnchorAlignment(node1, {0, 2}, {Symbol(1), Symbol(4)}, false, node2, {0, 1, 2}, | ||
| 2136 | + {Symbol(1), Symbol(1), Symbol(4)}, true, insert_indexes); | ||
| 2137 | + | ||
| 2138 | + ASSERT_EQ(insert_indexes.size(), 1U); | ||
| 2139 | + EXPECT_EQ(insert_indexes[0], 0U); | ||
| 2140 | +} | ||
| 2141 | + | ||
| 2142 | +TEST_F(LoweringAndCanfuseUT, ReshapePaddingAnchorAlignmentFallbackWhenNoAnchorMatched) { | ||
| 2143 | + auto graph = std::make_shared<ComputeGraph>("reshape_padding_anchor_fallback_graph"); | ||
| 2144 | + const auto node1 = CreateNodeWithOutputAttr(graph, "node1", {0, 2}, {Symbol(1), Symbol(4)}); | ||
| 2145 | + const auto node2 = CreateNodeWithOutputAttr(graph, "node2", {0, 1, 2}, {Symbol(1), Symbol(1), Symbol(4)}); | ||
| 2146 | + std::vector<size_t> insert_indexes = {1U}; | ||
| 2147 | + | ||
| 2148 | + asc_adapt::AdjustInsertIndexesByAnchorAlignment(node1, {0, 2}, {Symbol(1), Symbol(4)}, false, node2, {0, 1, 2}, | ||
| 2149 | + {Symbol(1), Symbol(1), Symbol(4)}, true, insert_indexes); | ||
| 2150 | + | ||
| 2151 | + ASSERT_EQ(insert_indexes.size(), 1U); | ||
| 2152 | + EXPECT_EQ(insert_indexes[0], 1U); | ||
| 2153 | +} | ||
| 2154 | + | ||
| 2115 | } // namespace ge | 2155 | } // namespace ge |