已开启
fix: restore reshape axes before autofuse can-fuse #1
ling-DT创建于 7月28日
fix: restore reshape axes before autofuse can-fuse #1
已开启
共 21 个文件变更+4190-1046
| @@ -21,6 +21,7 @@ | |||
| 21 | 21 | ||
| 22 | 22 | ||
| 23 | 23 | ||
| 24 | + | ||
| 24 | 25 | ||
| 25 | 26 | ||
| 26 | 27 | ||
| @@ -8,6 +8,7 @@ | |||
| 8 | * See LICENSE in the root of the software repository for the full text of the License. | 8 | * See LICENSE in the root of the software repository for the full text of the License. |
| 9 | */ | 9 | */ |
| 10 | 10 | ||
| 11 | + | ||
| 11 | 12 | ||
| 12 | 13 | ||
| 13 | 14 | ||
| @@ -27,6 +28,48 @@ | |||
| 27 | 28 | ||
| 28 | namespace ge { | 29 | namespace ge { |
| 29 | using namespace autofuse; | 30 | using namespace autofuse; |
| 31 | +namespace { | ||
| 32 | +bool HasAxisId(const std::vector<AxisPtr> &axis, const int64_t axis_id) { | ||
| 33 | + for (const auto &axis_info : axis) { | ||
| 34 | + if ((axis_info != nullptr) && (axis_info->id == axis_id)) { | ||
| 35 | + return true; | ||
| 36 | + } | ||
| 37 | + } | ||
| 38 | + return false; | ||
| 39 | +} | ||
| 40 | + | ||
| 41 | +bool IsSameAxisIds(const std::vector<AxisPtr> &axis1, const std::vector<AxisPtr> &axis2) { | ||
| 42 | + if (axis1.size() != axis2.size()) { | ||
| 43 | + return false; | ||
| 44 | + } | ||
| 45 | + for (size_t i = 0U; i < axis1.size(); ++i) { | ||
| 46 | + if ((axis1[i] == nullptr) || (axis2[i] == nullptr) || (axis1[i]->id != axis2[i]->id)) { | ||
| 47 | + return false; | ||
| 48 | + } | ||
| 49 | + } | ||
| 50 | + return true; | ||
| 51 | +} | ||
| 52 | + | ||
| 53 | +std::vector<AxisPtr> MergeAxisById(const std::vector<AxisPtr> &axis1, const std::vector<AxisPtr> &axis2) { | ||
| 54 | + std::vector<AxisPtr> merged_axis = axis1; | ||
| 55 | + for (const auto &axis_info : axis2) { | ||
| 56 | + if ((axis_info != nullptr) && !HasAxisId(merged_axis, axis_info->id)) { | ||
| 57 | + merged_axis.push_back(axis_info); | ||
| 58 | + } | ||
| 59 | + } | ||
| 60 | + std::sort(merged_axis.begin(), merged_axis.end(), [](const AxisPtr &lhs, const AxisPtr &rhs) { | ||
| 61 | + if (lhs == nullptr) { | ||
| 62 | + return false; | ||
| 63 | + } | ||
| 64 | + if (rhs == nullptr) { | ||
| 65 | + return true; | ||
| 66 | + } | ||
| 67 | + return lhs->id < rhs->id; | ||
| 68 | + }); | ||
| 69 | + return merged_axis; | ||
| 70 | +} | ||
| 71 | +} // namespace | ||
| 72 | + | ||
| 30 | // 子图融合流程缓存dump图和缓存当前正在融合的节点名字 | 73 | // 子图融合流程缓存dump图和缓存当前正在融合的节点名字 |
| 31 | Status CacheGraphBeforeSubGraphMerge(const NodePtr &node1, const NodePtr &node2, const ComputeGraphPtr &origin_graph) { | 74 | Status CacheGraphBeforeSubGraphMerge(const NodePtr &node1, const NodePtr &node2, const ComputeGraphPtr &origin_graph) { |
| 32 | if (!IsLogEnable(GE_MODULE_NAME, DLOG_DEBUG)) { | 75 | if (!IsLogEnable(GE_MODULE_NAME, DLOG_DEBUG)) { |
| @@ -216,7 +259,9 @@ Status AscBackendFusionDecider::UpdateSubgraphAxisAttr(const NodePtr &new_node, | |||
| 216 | } | 259 | } |
| 217 | } | 260 | } |
| 218 | // 如果轴个数相同按照后序graph更新,否则用轴个数最多的子图作为新图的属性 | 261 | // 如果轴个数相同按照后序graph更新,否则用轴个数最多的子图作为新图的属性 |
| 219 | - if (graph_attr1->axis.size() == graph_attr2->axis.size()) { | 262 | + if (!IsSameAxisIds(graph_attr1->axis, new_graph_attr2->axis)) { |
| 263 | + new_graph_attr->axis = MergeAxisById(graph_attr1->axis, new_graph_attr2->axis); | ||
| 264 | + } else if (graph_attr1->axis.size() == graph_attr2->axis.size()) { | ||
| 220 | new_graph_attr->axis = new_graph_attr2->axis; | 265 | new_graph_attr->axis = new_graph_attr2->axis; |
| 221 | } else { | 266 | } else { |
| 222 | if (graph_attr1->axis.size() > graph_attr2->axis.size()) { | 267 | if (graph_attr1->axis.size() > graph_attr2->axis.size()) { |
| @@ -413,6 +458,8 @@ Status AscBackendFusionDecider::UpdateNewNodeAttr(const OpDescPtr op, const Node | |||
| 413 | GetInterAttrs(attr).fuse_type = fuse_type; | 458 | GetInterAttrs(attr).fuse_type = fuse_type; |
| 414 | BackendUtils::SetReduceOriginalAxisInfo(GetInterAttrs(attr), GetInterAttrs(autofuse_attr1), | 459 | BackendUtils::SetReduceOriginalAxisInfo(GetInterAttrs(attr), GetInterAttrs(autofuse_attr1), |
| 415 | GetInterAttrs(autofuse_attr2)); | 460 | GetInterAttrs(autofuse_attr2)); |
| 461 | + BackendUtils::SetReshapeAxisChangeInfo(GetInterAttrs(attr), GetInterAttrs(autofuse_attr1), | ||
| 462 | + GetInterAttrs(autofuse_attr2)); | ||
| 416 | 463 | ||
| 417 | // 处理is_reduce_all_load属性:按照优先级设置融合后的值 | 464 | // 处理is_reduce_all_load属性:按照优先级设置融合后的值 |
| 418 | // 优先级1:存在REDUCE_ALL_LOAD_NOT_ALL,则设置为REDUCE_ALL_LOAD_NOT_ALL | 465 | // 优先级1:存在REDUCE_ALL_LOAD_NOT_ALL,则设置为REDUCE_ALL_LOAD_NOT_ALL |
| @@ -138,6 +138,98 @@ Status BuildAxisIndex(const AxisIndexMatchState &match_state, std::vector<uint32 | |||
| 138 | } | 138 | } |
| 139 | return SUCCESS; | 139 | return SUCCESS; |
| 140 | } | 140 | } |
| 141 | + | ||
| 142 | +bool IsCoveredBySequence(const size_t pos, const size_t offset, const size_t sequence_size) { | ||
| 143 | + return (pos >= offset) && (pos < (offset + sequence_size)); | ||
| 144 | +} | ||
| 145 | + | ||
| 146 | +bool CanPlaceRepeatSequences(const std::vector<Expression> &repeats1, const size_t offset1, | ||
| 147 | + const std::vector<Expression> &repeats2, const size_t offset2, const size_t common_size) { | ||
| 148 | + bool has_overlap = false; | ||
| 149 | + for (size_t pos = 0U; pos < common_size; ++pos) { | ||
| 150 | + const bool in_seq1 = IsCoveredBySequence(pos, offset1, repeats1.size()); | ||
| 151 | + const bool in_seq2 = IsCoveredBySequence(pos, offset2, repeats2.size()); | ||
| 152 | + if (in_seq1 && in_seq2) { | ||
| 153 | + has_overlap = true; | ||
| 154 | + if (repeats1[pos - offset1] != repeats2[pos - offset2]) { | ||
| 155 | + return false; | ||
| 156 | + } | ||
| 157 | + continue; | ||
| 158 | + } | ||
| 159 | + if (in_seq1 && !BackendUtils::IsEqOne(repeats1[pos - offset1])) { | ||
| 160 | + return false; | ||
| 161 | + } | ||
| 162 | + if (in_seq2 && !BackendUtils::IsEqOne(repeats2[pos - offset2])) { | ||
| 163 | + return false; | ||
| 164 | + } | ||
| 165 | + } | ||
| 166 | + return has_overlap; | ||
| 167 | +} | ||
| 168 | + | ||
| 169 | +void BuildOffsetAxisMap(const std::vector<int64_t> &axis, const size_t offset, AxisPairSet &axis_map) { | ||
| 170 | + axis_map.clear(); | ||
| 171 | + for (size_t i = 0U; i < axis.size(); ++i) { | ||
| 172 | + axis_map.insert(std::make_pair(axis[i], static_cast<int64_t>(offset + i))); | ||
| 173 | + } | ||
| 174 | +} | ||
| 175 | + | ||
| 176 | +bool TryBuildExpandedAxisMap(const std::vector<int64_t> &axis1, const std::vector<Expression> &repeats1, | ||
| 177 | + const std::vector<int64_t> &axis2, const std::vector<Expression> &repeats2, | ||
| 178 | + AxisPairSet &axis_map1, AxisPairSet &axis_map2) { | ||
| 179 | + const auto min_common_size = std::max(repeats1.size(), repeats2.size()); | ||
| 180 | + const auto max_common_size = repeats1.size() + repeats2.size(); | ||
| 181 | + for (size_t common_size = min_common_size + 1U; common_size <= max_common_size; ++common_size) { | ||
| 182 | + for (size_t offset1 = 0U; offset1 + repeats1.size() <= common_size; ++offset1) { | ||
| 183 | + for (size_t offset2 = 0U; offset2 + repeats2.size() <= common_size; ++offset2) { | ||
| 184 | + if (!CanPlaceRepeatSequences(repeats1, offset1, repeats2, offset2, common_size)) { | ||
| 185 | + continue; | ||
| 186 | + } | ||
| 187 | + BuildOffsetAxisMap(axis1, offset1, axis_map1); | ||
| 188 | + BuildOffsetAxisMap(axis2, offset2, axis_map2); | ||
| 189 | + return true; | ||
| 190 | + } | ||
| 191 | + } | ||
| 192 | + } | ||
| 193 | + return false; | ||
| 194 | +} | ||
| 195 | + | ||
| 196 | +bool IsOrderedBefore(const std::vector<int64_t> &axis, const int64_t lhs, const int64_t rhs) { | ||
| 197 | + auto lhs_pos = axis.end(); | ||
| 198 | + auto rhs_pos = axis.end(); | ||
| 199 | + for (auto it = axis.begin(); it != axis.end(); ++it) { | ||
| 200 | + if (*it == lhs) { | ||
| 201 | + lhs_pos = it; | ||
| 202 | + } | ||
| 203 | + if (*it == rhs) { | ||
| 204 | + rhs_pos = it; | ||
| 205 | + } | ||
| 206 | + } | ||
| 207 | + return (lhs_pos != axis.end()) && (rhs_pos != axis.end()) && (lhs_pos < rhs_pos); | ||
| 208 | +} | ||
| 209 | + | ||
| 210 | +bool HasConsistentCommonAxisOrder(const std::vector<int64_t> &axis1, const std::vector<int64_t> &axis2) { | ||
| 211 | + for (size_t i = 0U; i < axis1.size(); ++i) { | ||
| 212 | + for (size_t j = i + 1U; j < axis1.size(); ++j) { | ||
| 213 | + const auto lhs = axis1[i]; | ||
| 214 | + const auto rhs = axis1[j]; | ||
| 215 | + if (std::find(axis2.begin(), axis2.end(), lhs) == axis2.end() || | ||
| 216 | + std::find(axis2.begin(), axis2.end(), rhs) == axis2.end()) { | ||
| 217 | + continue; | ||
| 218 | + } | ||
| 219 | + if (!IsOrderedBefore(axis2, lhs, rhs)) { | ||
| 220 | + return false; | ||
| 221 | + } | ||
| 222 | + } | ||
| 223 | + } | ||
| 224 | + return true; | ||
| 225 | +} | ||
| 226 | + | ||
| 227 | +Status ConvertLoopAxis(const AxisPairSet &node_map, int64_t &loop_axis, const bool need_flash) { | ||
| 228 | + if (loop_axis == af::kIdNone) { | ||
| 229 | + return SUCCESS; | ||
| 230 | + } | ||
| 231 | + return BackendUtils::ConvertAxis(node_map, loop_axis, need_flash); | ||
| 232 | +} | ||
| 141 | } // namespace | 233 | } // namespace |
| 142 | 234 | ||
| 143 | Status NodeFuseInfo::GetSubgraphSameInputIndex(const NodePtr &node1, const NodePtr &node2, | 235 | Status NodeFuseInfo::GetSubgraphSameInputIndex(const NodePtr &node1, const NodePtr &node2, |
| @@ -603,6 +695,30 @@ bool AscGraphAxisMapping::CanAxisMap(std::vector<int64_t> &node1_axis, std::vect | |||
| 603 | std::vector<int64_t> &node2_axis, std::vector<ge::Expression> &node2_repeats, | 695 | std::vector<int64_t> &node2_axis, std::vector<ge::Expression> &node2_repeats, |
| 604 | AxisPairSet &node1_map, AxisPairSet &node2_map, AxisPairSet &temp_node1_map, | 696 | AxisPairSet &node1_map, AxisPairSet &node2_map, AxisPairSet &temp_node1_map, |
| 605 | AxisPairSet &temp_node2_map) const { | 697 | AxisPairSet &temp_node2_map) const { |
| 698 | + temp_node1_map.clear(); | ||
| 699 | + temp_node2_map.clear(); | ||
| 700 | + if (node1_repeats.size() == node2_repeats.size() && node1_repeats != node2_repeats) { | ||
| 701 | + std::vector<int64_t> mapped_node1_axis = node1_axis; | ||
| 702 | + std::vector<int64_t> mapped_node2_axis = node2_axis; | ||
| 703 | + if (!node1_map.empty() && (BackendUtils::ConvertAxis(node1_map, mapped_node1_axis) != SUCCESS)) { | ||
| 704 | + return false; | ||
| 705 | + } | ||
| 706 | + if (!node2_map.empty() && (BackendUtils::ConvertAxis(node2_map, mapped_node2_axis) != SUCCESS)) { | ||
| 707 | + return false; | ||
| 708 | + } | ||
| 709 | + if (TryBuildExpandedAxisMap(mapped_node1_axis, node1_repeats, mapped_node2_axis, node2_repeats, temp_node1_map, | ||
| 710 | + temp_node2_map)) { | ||
| 711 | + GELOGD_IF(open_log_, | ||
| 712 | + "find expanded axis map info: left axis(%s), repeats(%s), right axis(%s), repeats(%s), axis map1(%s), " | ||
| 713 | + "axis map2(%s).", | ||
| 714 | + AutofuseUtils::VectorToStr(node1_axis).c_str(), AutofuseUtils::VectorToStr(node1_repeats).c_str(), | ||
| 715 | + AutofuseUtils::VectorToStr(node2_axis).c_str(), AutofuseUtils::VectorToStr(node2_repeats).c_str(), | ||
| 716 | + AutofuseUtils::VectorPairToStr(temp_node1_map).c_str(), | ||
| 717 | + AutofuseUtils::VectorPairToStr(temp_node2_map).c_str()); | ||
| 718 | + return true; | ||
| 719 | + } | ||
| 720 | + } | ||
| 721 | + | ||
| 606 | if (node1_repeats.size() >= node2_repeats.size()) { | 722 | if (node1_repeats.size() >= node2_repeats.size()) { |
| 607 | std::vector<uint32_t> axis_index; | 723 | std::vector<uint32_t> axis_index; |
| 608 | if (FindAxisIndex(node2_repeats, node1_repeats, axis_index) != SUCCESS) { | 724 | if (FindAxisIndex(node2_repeats, node1_repeats, axis_index) != SUCCESS) { |
| @@ -614,8 +730,6 @@ bool AscGraphAxisMapping::CanAxisMap(std::vector<int64_t> &node1_axis, std::vect | |||
| 614 | return false; | 730 | return false; |
| 615 | } | 731 | } |
| 616 | } | 732 | } |
| 617 | - temp_node1_map.clear(); | ||
| 618 | - temp_node2_map.clear(); | ||
| 619 | for (auto i = 0U; i < axis_index.size(); i++) { | 733 | for (auto i = 0U; i < axis_index.size(); i++) { |
| 620 | GE_ASSERT_TRUE(static_cast<size_t>(axis_index[i]) < node1_axis.size()); | 734 | GE_ASSERT_TRUE(static_cast<size_t>(axis_index[i]) < node1_axis.size()); |
| 621 | temp_node2_map.insert(std::pair<int64_t, int64_t>(node2_axis[i], node1_axis[axis_index[i]])); | 735 | temp_node2_map.insert(std::pair<int64_t, int64_t>(node2_axis[i], node1_axis[axis_index[i]])); |
| @@ -634,8 +748,6 @@ bool AscGraphAxisMapping::CanAxisMap(std::vector<int64_t> &node1_axis, std::vect | |||
| 634 | return false; | 748 | return false; |
| 635 | } | 749 | } |
| 636 | } | 750 | } |
| 637 | - temp_node1_map.clear(); | ||
| 638 | - temp_node2_map.clear(); | ||
| 639 | for (auto i = 0U; i < axis_index.size(); i++) { | 751 | for (auto i = 0U; i < axis_index.size(); i++) { |
| 640 | GE_ASSERT_TRUE(static_cast<size_t>(axis_index[i]) < node2_axis.size()); | 752 | GE_ASSERT_TRUE(static_cast<size_t>(axis_index[i]) < node2_axis.size()); |
| 641 | temp_node1_map.insert(std::pair<int64_t, int64_t>(node1_axis[i], node2_axis[axis_index[i]])); | 753 | temp_node1_map.insert(std::pair<int64_t, int64_t>(node1_axis[i], node2_axis[axis_index[i]])); |
| @@ -680,35 +792,35 @@ bool AscGraphAxisMapping::IsSameMapAxis(AxisPairSet &map1, AxisPairSet &map2) co | |||
| 680 | } | 792 | } |
| 681 | 793 | ||
| 682 | Status AscGraphAxisMapping::FlashContinueAxisId() { | 794 | Status AscGraphAxisMapping::FlashContinueAxisId() { |
| 683 | - AxisPairSet *max_map; | ||
| 684 | - AxisPairSet *min_map; | ||
| 685 | GELOGD_IF(open_log_, "flash continue axis before, node1 map(%s) and node2 map(%s).", | 795 | GELOGD_IF(open_log_, "flash continue axis before, node1 map(%s) and node2 map(%s).", |
| 686 | AutofuseUtils::VectorPairToStr(node1_map_).c_str(), AutofuseUtils::VectorPairToStr(node2_map_).c_str()); | 796 | AutofuseUtils::VectorPairToStr(node1_map_).c_str(), AutofuseUtils::VectorPairToStr(node2_map_).c_str()); |
| 687 | - if (node1_map_.size() >= node2_map_.size()) { | 797 | + |
| 688 | - max_map = &node1_map_; | 798 | + std::set<int64_t> axis_values; |
| 689 | - min_map = &node2_map_; | 799 | + for (const auto &pair : node1_map_) { |
| 690 | - } else { | 800 | + axis_values.insert(pair.second); |
| 691 | - max_map = &node2_map_; | 801 | + } |
| 692 | - min_map = &node1_map_; | 802 | + for (const auto &pair : node2_map_) { |
| 803 | + axis_values.insert(pair.second); | ||
| 693 | } | 804 | } |
| 694 | std::unordered_map<int64_t, int64_t> value_map; | 805 | std::unordered_map<int64_t, int64_t> value_map; |
| 695 | - AxisPairSet temp_map; | ||
| 696 | int64_t i = 0; | 806 | int64_t i = 0; |
| 697 | - for (auto &pair : *max_map) { | 807 | + for (const auto axis_value : axis_values) { |
| 698 | - value_map[pair.second] = i; | 808 | + value_map[axis_value] = i++; |
| 699 | - temp_map.insert(std::pair<int64_t, int64_t>(pair.first, i)); | ||
| 700 | - i++; | ||
| 701 | } | 809 | } |
| 702 | - *max_map = temp_map; | ||
| 703 | - GE_ASSERT_TRUE(value_map.size() == (*max_map).size()); | ||
| 704 | 810 | ||
| 705 | - temp_map.clear(); | 811 | + auto flush_map = [&value_map](AxisPairSet &node_map) -> Status { |
| 706 | - for (auto &pair : *min_map) { | 812 | + AxisPairSet temp_map; |
| 707 | - auto it = value_map.find(pair.second); | 813 | + for (const auto &pair : node_map) { |
| 708 | - GE_ASSERT_TRUE(it != value_map.end()); | 814 | + const auto it = value_map.find(pair.second); |
| 709 | - temp_map.insert(std::pair<int64_t, int64_t>(pair.first, it->second)); | 815 | + GE_ASSERT_TRUE(it != value_map.end()); |
| 710 | - } | 816 | + temp_map.insert(std::make_pair(pair.first, it->second)); |
| 711 | - *min_map = temp_map; | 817 | + } |
| 818 | + node_map = std::move(temp_map); | ||
| 819 | + return SUCCESS; | ||
| 820 | + }; | ||
| 821 | + GE_ASSERT_SUCCESS(flush_map(node1_map_)); | ||
| 822 | + GE_ASSERT_SUCCESS(flush_map(node2_map_)); | ||
| 823 | + | ||
| 712 | GELOGD_IF(open_log_, "flash continue axis after, node1 map(%s) and node2 map(%s).", | 824 | GELOGD_IF(open_log_, "flash continue axis after, node1 map(%s) and node2 map(%s).", |
| 713 | AutofuseUtils::VectorPairToStr(node1_map_).c_str(), AutofuseUtils::VectorPairToStr(node2_map_).c_str()); | 825 | AutofuseUtils::VectorPairToStr(node1_map_).c_str(), AutofuseUtils::VectorPairToStr(node2_map_).c_str()); |
| 714 | return SUCCESS; | 826 | return SUCCESS; |
| @@ -822,14 +934,26 @@ Status AscGraphAxisMapping::GetVerticalAxisMapInfo(const NodePtr &node, const in | |||
| 822 | 934 | ||
| 823 | Status AscGraphAxisMapping::FlushAscSubGraphAxisInfo(const NodePtr &node, const ComputeGraphPtr &graph, | 935 | Status AscGraphAxisMapping::FlushAscSubGraphAxisInfo(const NodePtr &node, const ComputeGraphPtr &graph, |
| 824 | const AxisPairSet &node_map, bool need_flash) const { | 936 | const AxisPairSet &node_map, bool need_flash) const { |
| 937 | + auto graph_attr = graph->GetAttrsGroup<AscGraphAttr>(); | ||
| 938 | + GE_ASSERT_NOTNULL(graph_attr); | ||
| 825 | for (auto &asc_node : graph->GetAllNodes()) { | 939 | for (auto &asc_node : graph->GetAllNodes()) { |
| 826 | GE_ASSERT_NOTNULL(asc_node); | 940 | GE_ASSERT_NOTNULL(asc_node); |
| 827 | auto asc_node_op_desc = asc_node->GetOpDesc(); | 941 | auto asc_node_op_desc = asc_node->GetOpDesc(); |
| 828 | GE_ASSERT_NOTNULL(asc_node_op_desc); | 942 | GE_ASSERT_NOTNULL(asc_node_op_desc); |
| 829 | AscNodeAttr *asc_node_attr = asc_node_op_desc->GetAttrsGroup<AscNodeAttr>(); | 943 | AscNodeAttr *asc_node_attr = asc_node_op_desc->GetAttrsGroup<AscNodeAttr>(); |
| 830 | GE_ASSERT_NOTNULL(asc_node_attr); | 944 | GE_ASSERT_NOTNULL(asc_node_attr); |
| 831 | - if (BackendUtils::ConvertAxis(node_map, asc_node_attr->sched.axis, need_flash) != SUCCESS) { | 945 | + GE_ASSERT_SUCCESS(BackendUtils::ConvertAxis(node_map, asc_node_attr->sched.axis, need_flash)); |
| 832 | - return FAILED; | 946 | + GE_ASSERT_SUCCESS(ConvertLoopAxis(node_map, asc_node_attr->sched.loop_axis, need_flash)); |
| 947 | + | ||
| 948 | + for (size_t i = 0U; i < asc_node->GetAllInDataAnchorsSize(); ++i) { | ||
| 949 | + const auto input_desc = asc_node_op_desc->MutableInputDesc(i); | ||
| 950 | + GE_ASSERT_NOTNULL(input_desc); | ||
| 951 | + auto input_desc_tensor_attr = input_desc->GetAttrsGroup<AscTensorAttr>(); | ||
| 952 | + if (input_desc_tensor_attr == nullptr) { | ||
| 953 | + continue; | ||
| 954 | + } | ||
| 955 | + GE_ASSERT_SUCCESS(BackendUtils::ConvertAxis(node_map, input_desc_tensor_attr->axis, need_flash)); | ||
| 956 | + GE_ASSERT_SUCCESS(BackendUtils::ConvertAxis(node_map, input_desc_tensor_attr->vectorized_axis, need_flash)); | ||
| 833 | } | 957 | } |
| 834 | 958 | ||
| 835 | for (auto &output_desc : asc_node_op_desc->GetAllOutputsDescPtr()) { | 959 | for (auto &output_desc : asc_node_op_desc->GetAllOutputsDescPtr()) { |
| @@ -837,19 +961,16 @@ Status AscGraphAxisMapping::FlushAscSubGraphAxisInfo(const NodePtr &node, const | |||
| 837 | auto output_desc_tensor_attr = output_desc->GetAttrsGroup<AscTensorAttr>(); | 961 | auto output_desc_tensor_attr = output_desc->GetAttrsGroup<AscTensorAttr>(); |
| 838 | GE_ASSERT_NOTNULL(output_desc_tensor_attr); | 962 | GE_ASSERT_NOTNULL(output_desc_tensor_attr); |
| 839 | auto axis_before_Flush = output_desc_tensor_attr->axis; | 963 | auto axis_before_Flush = output_desc_tensor_attr->axis; |
| 840 | - if (BackendUtils::ConvertAxis(node_map, output_desc_tensor_attr->axis, need_flash) != SUCCESS) { | 964 | + GE_ASSERT_SUCCESS(BackendUtils::ConvertAxis(node_map, output_desc_tensor_attr->axis, need_flash)); |
| 841 | - return FAILED; | 965 | + GE_ASSERT_SUCCESS(BackendUtils::ConvertAxis(node_map, output_desc_tensor_attr->vectorized_axis, need_flash)); |
| 842 | - } | ||
| 843 | GE_ASSERT_SUCCESS(BackendUtils::FlushReduceOriginalAxisIfIsReduceNode(node, asc_node, axis_before_Flush, | 966 | GE_ASSERT_SUCCESS(BackendUtils::FlushReduceOriginalAxisIfIsReduceNode(node, asc_node, axis_before_Flush, |
| 844 | output_desc_tensor_attr->axis)); | 967 | output_desc_tensor_attr->axis)); |
| 968 | + GE_ASSERT_SUCCESS( | ||
| 969 | + BackendUtils::FlushReshapeAxisChanges(node, asc_node, axis_before_Flush, output_desc_tensor_attr->axis)); | ||
| 845 | } | 970 | } |
| 846 | } | 971 | } |
| 847 | - auto graph_attr = graph->GetAttrsGroup<AscGraphAttr>(); | ||
| 848 | - GE_ASSERT_NOTNULL(graph_attr); | ||
| 849 | for (auto &axis_info : graph_attr->axis) { | 972 | for (auto &axis_info : graph_attr->axis) { |
| 850 | - if (BackendUtils::ConvertAxis(node_map, axis_info->id, need_flash) != SUCCESS) { | 973 | + GE_ASSERT_SUCCESS(BackendUtils::ConvertAxis(node_map, axis_info->id, need_flash)); |
| 851 | - return FAILED; | ||
| 852 | - } | ||
| 853 | GELOGD_IF(open_log_, " \nflash graph axis info: axis name(%s), axis id(%ld), axis size(%s), graph name(%s).", | 974 | GELOGD_IF(open_log_, " \nflash graph axis info: axis name(%s), axis id(%ld), axis size(%s), graph name(%s).", |
| 854 | axis_info->name.c_str(), axis_info->id, std::string(axis_info->size.Str().get()).c_str(), | 975 | axis_info->name.c_str(), axis_info->id, std::string(axis_info->size.Str().get()).c_str(), |
| 855 | graph->GetName().c_str()); | 976 | graph->GetName().c_str()); |
| @@ -918,7 +1039,7 @@ bool AscGraphAxisMapping::CanLoopMerge(const NodePtr &node1, const NodePtr &node | |||
| 918 | 1039 | ||
| 919 | if (axis1 != axis2) { | 1040 | if (axis1 != axis2) { |
| 920 | // 判断轴是否是顺序子集关系,子集关系认为也是可以循环合并的,后期schedue adapter补轴实现 | 1041 | // 判断轴是否是顺序子集关系,子集关系认为也是可以循环合并的,后期schedue adapter补轴实现 |
| 921 | - if (!BackendUtils::CheckAxisSubsetRelation(axis1, axis2)) { | 1042 | + if (!BackendUtils::CheckAxisSubsetRelation(axis1, axis2) && !HasConsistentCommonAxisOrder(axis1, axis2)) { |
| 922 | GELOGI_IF(open_log_, "sched axis different and not subset relation, can't merge."); | 1043 | GELOGI_IF(open_log_, "sched axis different and not subset relation, can't merge."); |
| 923 | return false; | 1044 | return false; |
| 924 | } | 1045 | } |
| @@ -49,6 +49,55 @@ size_t FindIndex(const Container &container, const ValueType &value) { | |||
| 49 | return std::distance(container.begin(), it); | 49 | return std::distance(container.begin(), it); |
| 50 | } | 50 | } |
| 51 | 51 | ||
| 52 | +bool IsOnlyUnitRepeatAxisOrderChange(const TensorAttrInfo &in_attr, const TensorAttrInfo &out_attr) { | ||
| 53 | + if (in_attr.axis == out_attr.axis) { | ||
| 54 | + return false; | ||
| 55 | + } | ||
| 56 | + if ((in_attr.axis.size() != in_attr.repeats.size()) || (out_attr.axis.size() != out_attr.repeats.size())) { | ||
| 57 | + return false; | ||
| 58 | + } | ||
| 59 | + if (in_attr.repeats.empty() || out_attr.repeats.empty()) { | ||
| 60 | + return false; | ||
| 61 | + } | ||
| 62 | + | ||
| 63 | + std::vector<int64_t> in_non_unit_axis; | ||
| 64 | + std::vector<int64_t> out_non_unit_axis; | ||
| 65 | + std::vector<Expression> in_non_unit_repeats; | ||
| 66 | + std::vector<Expression> out_non_unit_repeats; | ||
| 67 | + in_non_unit_axis.reserve(in_attr.axis.size()); | ||
| 68 | + out_non_unit_axis.reserve(out_attr.axis.size()); | ||
| 69 | + in_non_unit_repeats.reserve(in_attr.repeats.size()); | ||
| 70 | + out_non_unit_repeats.reserve(out_attr.repeats.size()); | ||
| 71 | + for (size_t i = 0U; i < in_attr.repeats.size(); ++i) { | ||
| 72 | + if (!BackendUtils::IsEqOne(in_attr.repeats[i])) { | ||
| 73 | + in_non_unit_axis.push_back(in_attr.axis[i]); | ||
| 74 | + in_non_unit_repeats.push_back(in_attr.repeats[i]); | ||
| 75 | + } | ||
| 76 | + } | ||
| 77 | + for (size_t i = 0U; i < out_attr.repeats.size(); ++i) { | ||
| 78 | + if (!BackendUtils::IsEqOne(out_attr.repeats[i])) { | ||
| 79 | + out_non_unit_axis.push_back(out_attr.axis[i]); | ||
| 80 | + out_non_unit_repeats.push_back(out_attr.repeats[i]); | ||
| 81 | + } | ||
| 82 | + } | ||
| 83 | + if ((in_non_unit_repeats.size() == in_attr.repeats.size()) && | ||
| 84 | + (out_non_unit_repeats.size() == out_attr.repeats.size())) { | ||
| 85 | + return false; | ||
| 86 | + } | ||
| 87 | + if (in_non_unit_axis != out_non_unit_axis) { | ||
| 88 | + return false; | ||
| 89 | + } | ||
| 90 | + if (in_non_unit_repeats.size() != out_non_unit_repeats.size()) { | ||
| 91 | + return false; | ||
| 92 | + } | ||
| 93 | + for (size_t i = 0U; i < in_non_unit_repeats.size(); ++i) { | ||
| 94 | + if (SymbolicUtils::StaticCheckEq(in_non_unit_repeats[i], out_non_unit_repeats[i]) != TriBool::kTrue) { | ||
| 95 | + return false; | ||
| 96 | + } | ||
| 97 | + } | ||
| 98 | + return true; | ||
| 99 | +} | ||
| 100 | + | ||
| 52 | bool IsLoadConnectedToSplit(const NodePtr &load_node) { | 101 | bool IsLoadConnectedToSplit(const NodePtr &load_node) { |
| 53 | const auto load_out_anchor = load_node->GetOutDataAnchor(0); | 102 | const auto load_out_anchor = load_node->GetOutDataAnchor(0); |
| 54 | GE_ASSERT_NOTNULL(load_out_anchor); | 103 | GE_ASSERT_NOTNULL(load_out_anchor); |
| @@ -394,6 +443,11 @@ Status BackendUtils::FusedBackSteppingViewOpTranspose(TensorAttrInfo &temp_graph | |||
| 394 | const auto &graph_axis = temp_graph_attr.axis; | 443 | const auto &graph_axis = temp_graph_attr.axis; |
| 395 | const auto &load_axis = temp_load_attr.axis; | 444 | const auto &load_axis = temp_load_attr.axis; |
| 396 | 445 | ||
| 446 | + if (IsOnlyUnitRepeatAxisOrderChange(temp_graph_attr, temp_load_attr)) { | ||
| 447 | + GELOGD("Fused back stepping view op only has reshape unit axis change, skip transpose."); | ||
| 448 | + return SUCCESS; | ||
| 449 | + } | ||
| 450 | + | ||
| 397 | // 计算将load轴变为graph轴所需的最小交换次数,并记录每次交换的axis id | 451 | // 计算将load轴变为graph轴所需的最小交换次数,并记录每次交换的axis id |
| 398 | int64_t swap_count = 0; | 452 | int64_t swap_count = 0; |
| 399 | GE_ASSERT_SUCCESS(MinSwapCount(graph_axis, load_axis, swap_count, transpose_info)); | 453 | GE_ASSERT_SUCCESS(MinSwapCount(graph_axis, load_axis, swap_count, transpose_info)); |
| @@ -525,6 +579,10 @@ Status BackendUtils::PostProBackSteppingViewOpTranspose(TensorAttrInfo &temp_gra | |||
| 525 | const auto &graph_axis = temp_graph_attr.axis; | 579 | const auto &graph_axis = temp_graph_attr.axis; |
| 526 | auto &cur_axis = temp_load_attr.axis; | 580 | auto &cur_axis = temp_load_attr.axis; |
| 527 | // 反推出 transpose_info 并 根据反推结果还原临时 attr_info ,为下一次反推处理准备attr_info | 581 | // 反推出 transpose_info 并 根据反推结果还原临时 attr_info ,为下一次反推处理准备attr_info |
| 582 | + if (IsOnlyUnitRepeatAxisOrderChange(temp_graph_attr, temp_load_attr)) { | ||
| 583 | + GELOGD("post process back stepping view op only has reshape unit axis change, skip transpose."); | ||
| 584 | + return SUCCESS; | ||
| 585 | + } | ||
| 528 | int64_t swap_count = 0; | 586 | int64_t swap_count = 0; |
| 529 | if ((cur_node_type == kLoadType) || (cur_node_type == kGatherType)) { | 587 | if ((cur_node_type == kLoadType) || (cur_node_type == kGatherType)) { |
| 530 | GE_ASSERT_SUCCESS(MinSwapCount(cur_axis, graph_axis, swap_count, transpose_info)); | 588 | GE_ASSERT_SUCCESS(MinSwapCount(cur_axis, graph_axis, swap_count, transpose_info)); |
| @@ -2704,6 +2762,17 @@ Status BackendUtils::UpdateTransposeBeforeMerge(const NodePtr &node2, const Comp | |||
| 2704 | return SUCCESS; | 2762 | return SUCCESS; |
| 2705 | } | 2763 | } |
| 2706 | 2764 | ||
| 2765 | +Status BackendUtils::CompleteNodeAttrsBeforeCanFuse(const NodePtr &node1, const NodePtr &node2) { | ||
| 2766 | + GE_ASSERT_SUCCESS(asc_adapt::PadPairLeadingUnitAxisBeforeCompleteAttrs(node1, node2)); | ||
| 2767 | + auto asc_graph1 = BackendUtils::GetNodeFusedAscGraph(node1); | ||
| 2768 | + GE_ASSERT_NOTNULL(asc_graph1); | ||
| 2769 | + GE_ASSERT_SUCCESS(asc_adapt::CompleteNodeAttrsOnAscGraph(*asc_graph1, node1)); | ||
| 2770 | + auto asc_graph2 = BackendUtils::GetNodeFusedAscGraph(node2); | ||
| 2771 | + GE_ASSERT_NOTNULL(asc_graph2); | ||
| 2772 | + GE_ASSERT_SUCCESS(asc_adapt::CompleteNodeAttrsOnAscGraph(*asc_graph2, node2)); | ||
| 2773 | + return SUCCESS; | ||
| 2774 | +} | ||
| 2775 | + | ||
| 2707 | Status CompleteNodeAttrsBeforeMerge(const NodePtr &node1, const NodePtr &node2) { | 2776 | Status CompleteNodeAttrsBeforeMerge(const NodePtr &node1, const NodePtr &node2) { |
| 2708 | auto asc_graph1 = BackendUtils::GetNodeFusedAscGraph(node1); | 2777 | auto asc_graph1 = BackendUtils::GetNodeFusedAscGraph(node1); |
| 2709 | GE_ASSERT_NOTNULL(asc_graph1); | 2778 | GE_ASSERT_NOTNULL(asc_graph1); |
| @@ -3263,15 +3332,17 @@ void BackendUtils::SetReduceOriginalAxisInfo(AutofuseInnerAttrs &attr_new, const | |||
| 3263 | } | 3332 | } |
| 3264 | } | 3333 | } |
| 3265 | 3334 | ||
| 3266 | -// 融合存在轴映射之后index对应的axis变化的场景,则记录的reduce的原始axis也要相应变化 | 3335 | +void BackendUtils::SetReshapeAxisChangeInfo(AutofuseInnerAttrs &attr_new, const AutofuseInnerAttrs &attr1, |
| 3267 | -Status BackendUtils::FlushReduceOriginalAxisIfIsReduceNode(const NodePtr &node, const NodePtr &asc_node, | 3336 | + const AutofuseInnerAttrs &attr2) { |
| 3268 | - const std::vector<int64_t> axis_before_Flush, | 3337 | + attr_new.reshape_axis_changes = attr1.reshape_axis_changes; |
| 3269 | - const std::vector<int64_t> axis_after_Flush) { | 3338 | + attr_new.reshape_axis_changes.insert(attr_new.reshape_axis_changes.end(), attr2.reshape_axis_changes.begin(), |
| 3270 | - if (!asc_adapt::IsReduceNode(asc_node)) { | 3339 | + attr2.reshape_axis_changes.end()); |
| 3271 | - return SUCCESS; | 3340 | +} |
| 3272 | - } | ||
| 3273 | 3341 | ||
| 3274 | - if (axis_before_Flush.empty() || axis_after_Flush.empty()) { | 3342 | +Status FlushOriginalAxis(const NodePtr &node, const NodePtr &asc_node, const std::vector<int64_t> &axis_before_Flush, |
| 3343 | + const std::vector<int64_t> &axis_after_Flush, std::vector<int64_t> &original_axis, | ||
| 3344 | + const char *info_name) { | ||
| 3345 | + if (axis_before_Flush.empty() || axis_after_Flush.empty() || original_axis.empty()) { | ||
| 3275 | return SUCCESS; | 3346 | return SUCCESS; |
| 3276 | } | 3347 | } |
| 3277 | 3348 | ||
| @@ -3285,36 +3356,112 @@ Status BackendUtils::FlushReduceOriginalAxisIfIsReduceNode(const NodePtr &node, | |||
| 3285 | return SUCCESS; | 3356 | return SUCCESS; |
| 3286 | } | 3357 | } |
| 3287 | 3358 | ||
| 3288 | - auto autofuse_attr = BackendUtils::GetNodeAutoFuseAttr(node); | 3359 | + std::unordered_map<int64_t, size_t> axis_before_to_index; |
| 3289 | - GE_ASSERT_NOTNULL(autofuse_attr); | 3360 | + for (size_t i = 0U; i < axis_before_Flush.size(); ++i) { |
| 3361 | + axis_before_to_index[axis_before_Flush[i]] = i; | ||
| 3362 | + } | ||
| 3290 | 3363 | ||
| 3291 | - auto reduce_original_axis = autofuse_attr->GetReduceOriginalAxis(); | 3364 | + std::vector<int64_t> updated_axis; |
| 3292 | - if (reduce_original_axis.empty()) { | 3365 | + updated_axis.reserve(original_axis.size()); |
| 3366 | + for (const auto &axis : original_axis) { | ||
| 3367 | + auto it = axis_before_to_index.find(axis); | ||
| 3368 | + if (it != axis_before_to_index.end()) { | ||
| 3369 | + updated_axis.push_back(axis_after_Flush[it->second]); | ||
| 3370 | + } else { | ||
| 3371 | + GELOGW("Axis %ld in %s not found in axis_before_Flush for asc_node %s, keep original value", axis, info_name, | ||
| 3372 | + asc_node->GetName().c_str()); | ||
| 3373 | + updated_axis.push_back(axis); | ||
| 3374 | + } | ||
| 3375 | + } | ||
| 3376 | + | ||
| 3377 | + GELOGD("Flush %s for node %s, asc_node %s, before: %s, after: %s", info_name, node->GetName().c_str(), | ||
| 3378 | + asc_node->GetName().c_str(), AutofuseUtils::VectorToStr(original_axis).c_str(), | ||
| 3379 | + AutofuseUtils::VectorToStr(updated_axis).c_str()); | ||
| 3380 | + original_axis = updated_axis; | ||
| 3381 | + return SUCCESS; | ||
| 3382 | +} | ||
| 3383 | + | ||
| 3384 | +Status FlushReshapeAxisByRepeats(const NodePtr &node, const NodePtr &asc_node, | ||
| 3385 | + const std::vector<int64_t> &axis_before_Flush, | ||
| 3386 | + const std::vector<int64_t> &axis_after_Flush, | ||
| 3387 | + const std::vector<Expression> &reshape_repeats, std::vector<int64_t> &reshape_axis, | ||
| 3388 | + const char *info_name) { | ||
| 3389 | + if (axis_before_Flush.empty() || axis_after_Flush.empty() || reshape_axis.empty()) { | ||
| 3293 | return SUCCESS; | 3390 | return SUCCESS; |
| 3294 | } | 3391 | } |
| 3295 | 3392 | ||
| 3393 | + GE_ASSERT_TRUE(axis_before_Flush.size() == axis_after_Flush.size(), | ||
| 3394 | + "axis_before_Flush size %zu must equal to axis_after_Flush size %zu", axis_before_Flush.size(), | ||
| 3395 | + axis_after_Flush.size()); | ||
| 3396 | + GE_ASSERT_TRUE(reshape_axis.size() == reshape_repeats.size(), "reshape axis size %zu must equal repeats size %zu", | ||
| 3397 | + reshape_axis.size(), reshape_repeats.size()); | ||
| 3398 | + | ||
| 3296 | std::unordered_map<int64_t, size_t> axis_before_to_index; | 3399 | std::unordered_map<int64_t, size_t> axis_before_to_index; |
| 3297 | for (size_t i = 0U; i < axis_before_Flush.size(); ++i) { | 3400 | for (size_t i = 0U; i < axis_before_Flush.size(); ++i) { |
| 3298 | axis_before_to_index[axis_before_Flush[i]] = i; | 3401 | axis_before_to_index[axis_before_Flush[i]] = i; |
| 3299 | } | 3402 | } |
| 3300 | 3403 | ||
| 3301 | std::vector<int64_t> updated_axis; | 3404 | std::vector<int64_t> updated_axis; |
| 3302 | - updated_axis.reserve(reduce_original_axis.size()); | 3405 | + updated_axis.reserve(reshape_axis.size()); |
| 3303 | - for (const auto &axis : reduce_original_axis) { | 3406 | + for (size_t i = 0U; i < reshape_axis.size(); ++i) { |
| 3407 | + const auto axis = reshape_axis[i]; | ||
| 3304 | auto it = axis_before_to_index.find(axis); | 3408 | auto it = axis_before_to_index.find(axis); |
| 3305 | if (it != axis_before_to_index.end()) { | 3409 | if (it != axis_before_to_index.end()) { |
| 3306 | - size_t index = it->second; | 3410 | + updated_axis.push_back(axis_after_Flush[it->second]); |
| 3307 | - updated_axis.push_back(axis_after_Flush[index]); | 3411 | + continue; |
| 3308 | - } else { | ||
| 3309 | - GELOGW("Axis %ld in reduce_original_axis not found in axis_before_Flush for asc_node %s, keep original value", | ||
| 3310 | - axis, asc_node->GetName().c_str()); | ||
| 3311 | - updated_axis.push_back(axis); | ||
| 3312 | } | 3412 | } |
| 3413 | + if (BackendUtils::IsEqOne(reshape_repeats[i]) && (reshape_axis.size() == axis_after_Flush.size())) { | ||
| 3414 | + updated_axis.push_back(axis_after_Flush[i]); | ||
| 3415 | + continue; | ||
| 3416 | + } | ||
| 3417 | + GELOGW("Axis %ld in %s not found in axis_before_Flush for asc_node %s, keep original value", axis, info_name, | ||
| 3418 | + asc_node->GetName().c_str()); | ||
| 3419 | + updated_axis.push_back(axis); | ||
| 3313 | } | 3420 | } |
| 3314 | 3421 | ||
| 3315 | - autofuse_attr->SetReduceOriginalAxis(updated_axis); | 3422 | + GELOGD("Flush %s for node %s, asc_node %s, before: %s, after: %s", info_name, node->GetName().c_str(), |
| 3316 | - GELOGD("Flush reduce original axis for asc_node %s, before: %s, after: %s", asc_node->GetName().c_str(), | 3423 | + asc_node->GetName().c_str(), AutofuseUtils::VectorToStr(reshape_axis).c_str(), |
| 3317 | - AutofuseUtils::VectorToStr(reduce_original_axis).c_str(), AutofuseUtils::VectorToStr(updated_axis).c_str()); | 3424 | + AutofuseUtils::VectorToStr(updated_axis).c_str()); |
| 3425 | + reshape_axis = updated_axis; | ||
| 3426 | + return SUCCESS; | ||
| 3427 | +} | ||
| 3428 | + | ||
| 3429 | +// 融合存在轴映射之后index对应的axis变化的场景,则记录的reduce的原始axis也要相应变化 | ||
| 3430 | +Status BackendUtils::FlushReduceOriginalAxisIfIsReduceNode(const NodePtr &node, const NodePtr &asc_node, | ||
| 3431 | + const std::vector<int64_t> axis_before_Flush, | ||
| 3432 | + const std::vector<int64_t> axis_after_Flush) { | ||
| 3433 | + if (!asc_adapt::IsReduceNode(asc_node)) { | ||
| 3434 | + return SUCCESS; | ||
| 3435 | + } | ||
| 3436 | + | ||
| 3437 | + auto autofuse_attr = BackendUtils::GetNodeAutoFuseAttr(node); | ||
| 3438 | + GE_ASSERT_NOTNULL(autofuse_attr); | ||
| 3439 | + | ||
| 3440 | + auto reduce_original_axis = autofuse_attr->GetReduceOriginalAxis(); | ||
| 3441 | + GE_ASSERT_SUCCESS(FlushOriginalAxis(node, asc_node, axis_before_Flush, axis_after_Flush, reduce_original_axis, | ||
| 3442 | + "reduce_original_axis")); | ||
| 3443 | + autofuse_attr->SetReduceOriginalAxis(reduce_original_axis); | ||
| 3444 | + | ||
| 3445 | + return SUCCESS; | ||
| 3446 | +} | ||
| 3447 | + | ||
| 3448 | +Status BackendUtils::FlushReshapeAxisChanges(const NodePtr &node, const NodePtr &asc_node, | ||
| 3449 | + const std::vector<int64_t> axis_before_Flush, | ||
| 3450 | + const std::vector<int64_t> axis_after_Flush) { | ||
| 3451 | + auto autofuse_attr = BackendUtils::GetNodeAutoFuseAttr(node); | ||
| 3452 | + GE_ASSERT_NOTNULL(autofuse_attr); | ||
| 3453 | + auto reshape_axis_changes = autofuse_attr->GetReshapeAxisChanges(); | ||
| 3454 | + if (reshape_axis_changes.empty()) { | ||
| 3455 | + return SUCCESS; | ||
| 3456 | + } | ||
| 3457 | + | ||
| 3458 | + for (auto &change : reshape_axis_changes) { | ||
| 3459 | + GE_ASSERT_SUCCESS(FlushReshapeAxisByRepeats(node, asc_node, axis_before_Flush, axis_after_Flush, | ||
| 3460 | + change.before_repeats, change.before_axis, "reshape_before_axis")); | ||
| 3461 | + GE_ASSERT_SUCCESS(FlushReshapeAxisByRepeats(node, asc_node, axis_before_Flush, axis_after_Flush, | ||
| 3462 | + change.after_repeats, change.after_axis, "reshape_after_axis")); | ||
| 3463 | + } | ||
| 3464 | + autofuse_attr->SetReshapeAxisChanges(reshape_axis_changes); | ||
| 3318 | 3465 | ||
| 3319 | return SUCCESS; | 3466 | return SUCCESS; |
| 3320 | } | 3467 | } |
| @@ -3327,6 +3474,14 @@ Status GetNodeTransposeInfo(const NodePtr &node, const TensorAttrInfo &temp_grap | |||
| 3327 | GE_ASSERT_NOTNULL(cur_output_desc); | 3474 | GE_ASSERT_NOTNULL(cur_output_desc); |
| 3328 | const auto cur_output_attr = cur_output_desc->GetAttrsGroup<AscTensorAttr>(); | 3475 | const auto cur_output_attr = cur_output_desc->GetAttrsGroup<AscTensorAttr>(); |
| 3329 | GE_ASSERT_NOTNULL(cur_output_attr); | 3476 | GE_ASSERT_NOTNULL(cur_output_attr); |
| 3477 | + TensorAttrInfo cur_output_attr_info; | ||
| 3478 | + cur_output_attr_info.axis = cur_output_attr->axis; | ||
| 3479 | + cur_output_attr_info.repeats = cur_output_attr->repeats; | ||
| 3480 | + if (IsOnlyUnitRepeatAxisOrderChange(temp_graph_attr, cur_output_attr_info)) { | ||
| 3481 | + GELOGI("node %s(%s) only has reshape unit axis change in graph attr compare, skip transpose.", | ||
| 3482 | + node->GetName().c_str(), node->GetType().c_str()); | ||
| 3483 | + return SUCCESS; | ||
| 3484 | + } | ||
| 3330 | int64_t swap = 0; | 3485 | int64_t swap = 0; |
| 3331 | if ((node->GetType() == kLoadType) || (node->GetType() == kGatherType)) { | 3486 | if ((node->GetType() == kLoadType) || (node->GetType() == kGatherType)) { |
| 3332 | GE_ASSERT_SUCCESS(BackendUtils::MinSwapCount(cur_output_attr->axis, temp_graph_attr.axis, swap, transpose_info)); | 3487 | GE_ASSERT_SUCCESS(BackendUtils::MinSwapCount(cur_output_attr->axis, temp_graph_attr.axis, swap, transpose_info)); |
| @@ -670,6 +670,7 @@ 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 CompleteNodeAttrsBeforeCanFuse(const NodePtr &node1, const NodePtr &node2); | ||
| 673 | static Status TuningSubgraphBeforeMerge(const NodePtr &node1, const NodePtr &node2, const ComputeGraphPtr &graph1, | 674 | static Status TuningSubgraphBeforeMerge(const NodePtr &node1, const NodePtr &node2, const ComputeGraphPtr &graph1, |
| 674 | const ComputeGraphPtr &graph2, const NodeFuseInfo &fuse_info); | 675 | const ComputeGraphPtr &graph2, const NodeFuseInfo &fuse_info); |
| 675 | static Status GetPreNodeAndAnchor(const NodePtr &node, const int32_t index, NodePtr &peer_node, | 676 | static Status GetPreNodeAndAnchor(const NodePtr &node, const int32_t index, NodePtr &peer_node, |
| @@ -850,9 +851,14 @@ class BackendUtils { | |||
| 850 | static bool OnlyHasTypesInAscgraph(const NodePtr &node, const std::vector<std::string> &target_types); | 851 | static bool OnlyHasTypesInAscgraph(const NodePtr &node, const std::vector<std::string> &target_types); |
| 851 | static void SetReduceOriginalAxisInfo(AutofuseInnerAttrs &attr_new, const AutofuseInnerAttrs &attr1, | 852 | static void SetReduceOriginalAxisInfo(AutofuseInnerAttrs &attr_new, const AutofuseInnerAttrs &attr1, |
| 852 | const AutofuseInnerAttrs &attr2); | 853 | const AutofuseInnerAttrs &attr2); |
| 854 | + static void SetReshapeAxisChangeInfo(AutofuseInnerAttrs &attr_new, const AutofuseInnerAttrs &attr1, | ||
| 855 | + const AutofuseInnerAttrs &attr2); | ||
| 853 | static Status FlushReduceOriginalAxisIfIsReduceNode(const NodePtr &node, const NodePtr &asc_node, | 856 | static Status FlushReduceOriginalAxisIfIsReduceNode(const NodePtr &node, const NodePtr &asc_node, |
| 854 | const std::vector<int64_t> axis_before_Flush, | 857 | const std::vector<int64_t> axis_before_Flush, |
| 855 | const std::vector<int64_t> axis_after_Flush); | 858 | const std::vector<int64_t> axis_after_Flush); |
| 859 | + static Status FlushReshapeAxisChanges(const NodePtr &node, const NodePtr &asc_node, | ||
| 860 | + const std::vector<int64_t> axis_before_Flush, | ||
| 861 | + const std::vector<int64_t> axis_after_Flush); | ||
| 856 | static Status GetTransposeInfos( | 862 | static Status GetTransposeInfos( |
| 857 | AscGraph &asc_graph, bool &has_only_one_transpose, | 863 | 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); | 864 | std::unordered_map<NodePtr, std::vector<std::pair<int64_t, int64_t>>> &fallback_node_to_transpose_info); |
| @@ -603,6 +603,14 @@ bool FusionStrategySolver::CanFuse(const ComputeGraphPtr &graph, const FusingNod | |||
| 603 | return false; | 603 | return false; |
| 604 | } | 604 | } |
| 605 | 605 | ||
| 606 | + if (BackendUtils::CompleteNodeAttrsBeforeCanFuse(node1->GetOrgNode(), node2->GetOrgNode()) != SUCCESS) { | ||
| 607 | + GELOGI("node1 %s(%s) and node2 %s(%s) cannot fuse, complete node attrs before can-fuse failed.", | ||
| 608 | + node1->GetNamePtr(), node1->GetOrgNode()->GetType().c_str(), node2->GetNamePtr(), | ||
| 609 | + node2->GetOrgNode()->GetType().c_str()); | ||
| 610 | + can_not_fuse_nodes.insert({node1.get(), node2.get()}); | ||
| 611 | + return false; | ||
| 612 | + } | ||
| 613 | + | ||
| 606 | // node1是node2的祖先节点,判断纵向融合,否则判断横向融合 | 614 | // node1是node2的祖先节点,判断纵向融合,否则判断横向融合 |
| 607 | if (node2->IsAncestor(node1)) { | 615 | if (node2->IsAncestor(node1)) { |
| 608 | if (!GetBackEnd(graph)->CanFuseVertical(node1->GetOrgNode(), node2->GetOrgNode())) { | 616 | if (!GetBackEnd(graph)->CanFuseVertical(node1->GetOrgNode(), node2->GetOrgNode())) { |
| @@ -85,15 +85,6 @@ bool ConcatFusionStrategy::CanFuse(const NodePtr &node1, const NodePtr &node2) { | |||
| 85 | graph_attr2->axis.size()); | 85 | graph_attr2->axis.size()); |
| 86 | return false; | 86 | return false; |
| 87 | } | 87 | } |
| 88 | - if (attr2->HasFuseType(loop::FuseType::kConcat) && graph_attr2->axis.size() < graph_attr1->axis.size()) { | ||
| 89 | - GELOGI( | ||
| 90 | - "node1 %s(%s) and node2 %s(%s) cannot fuse, the reason is [%s][In concat fusion occasion, node1 sched axis " | ||
| 91 | - "size(%zu) more than node2 sched axis size(%zu)]", | ||
| 92 | - node1->GetNamePtr(), node1->GetType().c_str(), node2->GetNamePtr(), node2->GetType().c_str(), | ||
| 93 | - ge::NotFuseReasonCode(ge::NotFuseReason::kConcatNodeSchedAxisSizeNotEqual), graph_attr1->axis.size(), | ||
| 94 | - graph_attr2->axis.size()); | ||
| 95 | - return false; | ||
| 96 | - } | ||
| 97 | return true; | 88 | return true; |
| 98 | } | 89 | } |
| 99 | 90 | ||
| @@ -52,6 +52,13 @@ 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 | + | ||
| 55 | struct AutofuseInnerAttrs { | 62 | struct AutofuseInnerAttrs { |
| 56 | std::vector<const af::Node *> origin_nodes; // Asc节点对应的原始节点,用于Dfx打印、获取融合前ComputeGraph片段等 | 63 | std::vector<const af::Node *> origin_nodes; // Asc节点对应的原始节点,用于Dfx打印、获取融合前ComputeGraph片段等 |
| 57 | std::vector<af::OutDataAnchor *> output_buffers; // Asc节点负责写入的原始输出anchor,用于lifting | 64 | std::vector<af::OutDataAnchor *> output_buffers; // Asc节点负责写入的原始输出anchor,用于lifting |
| @@ -71,12 +78,13 @@ struct AutofuseInnerAttrs { | |||
| 71 | size_t reduce_fused_elementwise_node_num = 0U; // reduce节点向后融合的elementwise节点数量 | 78 | size_t reduce_fused_elementwise_node_num = 0U; // reduce节点向后融合的elementwise节点数量 |
| 72 | int64_t split_global_id = kNonSplitGlobalId; // split op 在 lowering 之前的全局编号,不是split节点的话,这个编号为-1 | 79 | int64_t split_global_id = kNonSplitGlobalId; // split op 在 lowering 之前的全局编号,不是split节点的话,这个编号为-1 |
| 73 | SplitFusionRatioRequirementState split_fusion_ratio_requirement_state = | 80 | SplitFusionRatioRequirementState split_fusion_ratio_requirement_state = |
| 74 | - SplitFusionRatioRequirementState::NOT_DETERMINED; // 缓存对split融合比例是否超过阈值的预测结果 | 81 | + SplitFusionRatioRequirementState::NOT_DETERMINED; // 缓存对split融合比例是否超过阈值的预测结果 |
| 75 | - bool is_split_complete = false; // 缓存原split节点是否完全恢复的判断结果 | 82 | + bool is_split_complete = false; // 缓存原split节点是否完全恢复的判断结果 |
| 76 | - bool is_fuse_from_lowering = false; // 标识融合节点来自lowering还是can_fuse | 83 | + bool is_fuse_from_lowering = false; // 标识融合节点来自lowering还是can_fuse |
| 77 | - std::vector<int64_t> reduce_original_axis; // reduce操作前的原始轴信息 | 84 | + std::vector<int64_t> reduce_original_axis; // reduce操作前的原始轴信息 |
| 78 | - std::vector<Expression> reduce_original_repeats; // reduce操作前的原始repeats信息 | 85 | + std::vector<Expression> reduce_original_repeats; // reduce操作前的原始repeats信息 |
| 79 | - int32_t is_reduce_all_load = REDUCE_ALL_LOAD_INIT; // 标识reduce是否所有load都是norm-like | 86 | + std::vector<ReshapeAxisChangeInfo> reshape_axis_changes; // 每个reshape操作前后的轴变化信息 |
| 87 | + int32_t is_reduce_all_load = REDUCE_ALL_LOAD_INIT; // 标识reduce是否所有load都是norm-like | ||
| 80 | 88 | ||
| 81 | bool IsReduction() const { | 89 | bool IsReduction() const { |
| 82 | return HasFuseType(loop::FuseType::kReduction); | 90 | return HasFuseType(loop::FuseType::kReduction); |
| @@ -241,6 +249,18 @@ class AutoFuseAttrs : public AfAttrGroupsBase { | |||
| 241 | return inner_attrs_.reduce_original_repeats; | 249 | return inner_attrs_.reduce_original_repeats; |
| 242 | } | 250 | } |
| 243 | 251 | ||
| 252 | + void AddReshapeAxisChange(const ReshapeAxisChangeInfo &change) { | ||
| 253 | + inner_attrs_.reshape_axis_changes.push_back(change); | ||
| 254 | + } | ||
| 255 | + | ||
| 256 | + void SetReshapeAxisChanges(const std::vector<ReshapeAxisChangeInfo> &changes) { | ||
| 257 | + inner_attrs_.reshape_axis_changes = changes; | ||
| 258 | + } | ||
| 259 | + | ||
| 260 | + [[nodiscard]] const std::vector<ReshapeAxisChangeInfo> &GetReshapeAxisChanges() const { | ||
| 261 | + return inner_attrs_.reshape_axis_changes; | ||
| 262 | + } | ||
| 263 | + | ||
| 244 | void SetReduceAllLoadState(const int32_t state) { | 264 | void SetReduceAllLoadState(const int32_t state) { |
| 245 | inner_attrs_.is_reduce_all_load = state; | 265 | inner_attrs_.is_reduce_all_load = state; |
| 246 | } | 266 | } |
| @@ -37,6 +37,9 @@ struct ExtraKernelBoxMeta { | |||
| 37 | std::set<const ge::OutDataAnchor *> used_ascend_buffers; | 37 | std::set<const ge::OutDataAnchor *> used_ascend_buffers; |
| 38 | std::set<const ge::OutDataAnchor *> optimized_ascend_buffers; | 38 | std::set<const ge::OutDataAnchor *> optimized_ascend_buffers; |
| 39 | std::set<loop::Edge> concrete_edges; // edges consumed by this fused kernel | 39 | std::set<loop::Edge> concrete_edges; // edges consumed by this fused kernel |
| 40 | + std::vector<ReshapeAxisChangeInfo> reshape_axis_changes; | ||
| 41 | + std::vector<int64_t> reshape_before_axis; | ||
| 42 | + std::vector<Expression> reshape_before_repeats; | ||
| 40 | std::string stream_label; | 43 | std::string stream_label; |
| 41 | std::string stream_priority; | 44 | std::string stream_priority; |
| 42 | static ExtraKernelBoxMeta &Default() { | 45 | static ExtraKernelBoxMeta &Default() { |
| @@ -86,6 +89,9 @@ struct KernelBoxMeta { | |||
| 86 | if (op->Type() == "ops.StoreStridedSlice") { | 89 | if (op->Type() == "ops.StoreStridedSlice") { |
| 87 | extra->num_slices++; | 90 | extra->num_slices++; |
| 88 | } | 91 | } |
| 92 | + const auto &reshape_axis_changes = op->GetReshapeAxisChanges(); | ||
| 93 | + extra->reshape_axis_changes.insert(extra->reshape_axis_changes.end(), reshape_axis_changes.begin(), | ||
| 94 | + reshape_axis_changes.end()); | ||
| 89 | const auto node = op->GetAscendIrNode(); | 95 | const auto node = op->GetAscendIrNode(); |
| 90 | if (node != nullptr && seen_nodes.insert(node).second) { | 96 | if (node != nullptr && seen_nodes.insert(node).second) { |
| 91 | if (extra->stream_label.empty()) { | 97 | if (extra->stream_label.empty()) { |
| @@ -350,6 +356,32 @@ class KernelBox { | |||
| 350 | return GetExtraMeta().optimized_ascend_buffers; | 356 | return GetExtraMeta().optimized_ascend_buffers; |
| 351 | } | 357 | } |
| 352 | 358 | ||
| 359 | + void SetReshapeBeforeRepeats(const std::vector<Expression> &repeats) { | ||
| 360 | + if (meta_ == nullptr || IsExternKernel()) { | ||
| 361 | + return; | ||
| 362 | + } | ||
| 363 | + meta_->Extra().reshape_before_repeats = repeats; | ||
| 364 | + } | ||
| 365 | + | ||
| 366 | + void SetReshapeBeforeAxis(const std::vector<int64_t> &axis) { | ||
| 367 | + if (meta_ == nullptr || IsExternKernel()) { | ||
| 368 | + return; | ||
| 369 | + } | ||
| 370 | + meta_->Extra().reshape_before_axis = axis; | ||
| 371 | + } | ||
| 372 | + | ||
| 373 | + const std::vector<Expression> &GetReshapeBeforeRepeats() { | ||
| 374 | + return GetExtraMeta().reshape_before_repeats; | ||
| 375 | + } | ||
| 376 | + | ||
| 377 | + const std::vector<int64_t> &GetReshapeBeforeAxis() { | ||
| 378 | + return GetExtraMeta().reshape_before_axis; | ||
| 379 | + } | ||
| 380 | + | ||
| 381 | + const std::vector<ReshapeAxisChangeInfo> &GetReshapeAxisChanges() { | ||
| 382 | + return GetExtraMeta().reshape_axis_changes; | ||
| 383 | + } | ||
| 384 | + | ||
| 353 | size_t NumOps() { | 385 | size_t NumOps() { |
| 354 | return GetExtraMeta().num_ops; | 386 | return GetExtraMeta().num_ops; |
| 355 | } | 387 | } |
| @@ -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) { |
| @@ -682,10 +704,12 @@ LoopVar Reshape(const LoopVar &op, const std::vector<Expression> &src_dims, cons | |||
| 682 | // -i为后续减轴,index维度有变化需要更新 | 704 | // -i为后续减轴,index维度有变化需要更新 |
| 683 | reshape = loop::Squeeze(reshape, dims_new[i] - static_cast<int64_t>(i)); | 705 | reshape = loop::Squeeze(reshape, dims_new[i] - static_cast<int64_t>(i)); |
| 684 | } | 706 | } |
| 707 | + AddReshapeAxisChange(reshape, src_dims, dst_dims); | ||
| 685 | return reshape; | 708 | return reshape; |
| 686 | } | 709 | } |
| 687 | if (AutofuseUtils::CheckAndMulDetect(src_dims, dst_dims, short_idx, mul_idx)) { | 710 | if (AutofuseUtils::CheckAndMulDetect(src_dims, dst_dims, short_idx, mul_idx)) { |
| 688 | reshape = LoopVar(std::make_shared<ReshapeOp>(op.Op(), src_dims, dst_dims, short_idx, mul_idx)); | 711 | reshape = LoopVar(std::make_shared<ReshapeOp>(op.Op(), src_dims, dst_dims, short_idx, mul_idx)); |
| 712 | + AddReshapeAxisChange(reshape, src_dims, dst_dims); | ||
| 689 | return reshape; | 713 | return reshape; |
| 690 | } | 714 | } |
| 691 | } else { | 715 | } else { |
| @@ -693,10 +717,12 @@ LoopVar Reshape(const LoopVar &op, const std::vector<Expression> &src_dims, cons | |||
| 693 | for (const auto &new_dim : dims_new) { | 717 | for (const auto &new_dim : dims_new) { |
| 694 | reshape = loop::Unsqueeze(reshape, new_dim); | 718 | reshape = loop::Unsqueeze(reshape, new_dim); |
| 695 | } | 719 | } |
| 720 | + AddReshapeAxisChange(reshape, src_dims, dst_dims); | ||
| 696 | return reshape; | 721 | return reshape; |
| 697 | } | 722 | } |
| 698 | if (AutofuseUtils::CheckAndMulDetect(dst_dims, src_dims, short_idx, mul_idx)) { | 723 | if (AutofuseUtils::CheckAndMulDetect(dst_dims, src_dims, short_idx, mul_idx)) { |
| 699 | reshape = LoopVar(std::make_shared<ReshapeOp>(op.Op(), src_dims, dst_dims, short_idx, mul_idx)); | 724 | reshape = LoopVar(std::make_shared<ReshapeOp>(op.Op(), src_dims, dst_dims, short_idx, mul_idx)); |
| 725 | + AddReshapeAxisChange(reshape, src_dims, dst_dims); | ||
| 700 | return reshape; | 726 | return reshape; |
| 701 | } | 727 | } |
| 702 | } | 728 | } |
| @@ -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,6 +114,14 @@ 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(); |
| 119 | for (size_t i = 0U; i < inputs_.size(); ++i) { | 127 | for (size_t i = 0U; i < inputs_.size(); ++i) { |
| @@ -132,6 +140,7 @@ class LoopOp { | |||
| 132 | 140 | ||
| 133 | private: | 141 | private: |
| 134 | static std::atomic<int64_t> global_id_; | 142 | static std::atomic<int64_t> global_id_; |
| 143 | + std::vector<ReshapeAxisChangeInfo> reshape_axis_changes_; | ||
| 135 | }; | 144 | }; |
| 136 | 145 | ||
| 137 | class LoopVar { | 146 | class LoopVar { |
| @@ -243,6 +243,57 @@ 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 | + const auto &reshape_axis_changes = kernel_box.GetReshapeAxisChanges(); | ||
| 249 | + if (!reshape_axis_changes.empty()) { | ||
| 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 | + | ||
| 261 | + const auto &before_axis = kernel_box.GetReshapeBeforeAxis(); | ||
| 262 | + const auto &before_repeats = kernel_box.GetReshapeBeforeRepeats(); | ||
| 263 | + if (before_axis.empty() && before_repeats.empty()) { | ||
| 264 | + return SUCCESS; | ||
| 265 | + } | ||
| 266 | + GE_ASSERT_NOTNULL(asc_graph); | ||
| 267 | + const auto graph_attr = af::AscGraphUtils::GetComputeGraph(*asc_graph)->GetAttrsGroup<AscGraphAttr>(); | ||
| 268 | + GE_ASSERT_NOTNULL(graph_attr); | ||
| 269 | + | ||
| 270 | + af::ReshapeAxisChangeInfo change; | ||
| 271 | + change.before_repeats = before_repeats; | ||
| 272 | + for (const auto &axis : graph_attr->axis) { | ||
| 273 | + GE_ASSERT_NOTNULL(axis); | ||
| 274 | + change.after_axis.push_back(axis->id); | ||
| 275 | + change.after_repeats.push_back(axis->size); | ||
| 276 | + } | ||
| 277 | + if (!before_axis.empty()) { | ||
| 278 | + change.before_axis = before_axis; | ||
| 279 | + } else { | ||
| 280 | + int64_t next_axis_id = | ||
| 281 | + change.after_axis.empty() ? 0 : (*std::max_element(change.after_axis.begin(), change.after_axis.end()) + 1); | ||
| 282 | + size_t after_idx = 0U; | ||
| 283 | + for (const auto &repeat : before_repeats) { | ||
| 284 | + if ((after_idx < change.after_repeats.size()) && | ||
| 285 | + (SymbolicUtils::StaticCheckEq(repeat, change.after_repeats[after_idx]) == TriBool::kTrue)) { | ||
| 286 | + change.before_axis.push_back(change.after_axis[after_idx++]); | ||
| 287 | + continue; | ||
| 288 | + } | ||
| 289 | + GE_ASSERT_TRUE(SymbolicUtils::StaticCheckEq(repeat, Symbol(1)) == TriBool::kTrue); | ||
| 290 | + change.before_axis.push_back(next_axis_id++); | ||
| 291 | + } | ||
| 292 | + } | ||
| 293 | + fuse_attrs->AddReshapeAxisChange(change); | ||
| 294 | + return SUCCESS; | ||
| 295 | +} | ||
| 296 | + | ||
| 246 | graphStatus BuildOpForKernelBox(loop::KernelBox &kernel_box, CounterPtr counter, | 297 | graphStatus BuildOpForKernelBox(loop::KernelBox &kernel_box, CounterPtr counter, |
| 247 | shared_ptr<loop::AscOverrides> asc_graph, af::Operator &asc_op) { | 298 | shared_ptr<loop::AscOverrides> asc_graph, af::Operator &asc_op) { |
| 248 | std::string asc_op_name = CreateAscbackendName(kernel_box, counter); | 299 | std::string asc_op_name = CreateAscbackendName(kernel_box, counter); |
| @@ -424,6 +475,7 @@ OpDescPtr LoweringManager::BuildOpDescForKernelBox(loop::KernelBox &kernel_box, | |||
| 424 | GE_ASSERT_NOTNULL(fuse_attrs); | 475 | GE_ASSERT_NOTNULL(fuse_attrs); |
| 425 | GE_ASSERT_NOTNULL(asc_graph->SharedGraph()); | 476 | GE_ASSERT_NOTNULL(asc_graph->SharedGraph()); |
| 426 | fuse_attrs->SetAscGraph(asc_graph->SharedGraph(), kernel_box.Type()); | 477 | fuse_attrs->SetAscGraph(asc_graph->SharedGraph(), kernel_box.Type()); |
| 478 | + GE_ASSERT_SUCCESS(SaveReshapeAxisChangeInfo(kernel_box, asc_graph->SharedGraph(), fuse_attrs)); | ||
| 427 | fuse_attrs->SetOriginOutputBuffers({anchor}); | 479 | fuse_attrs->SetOriginOutputBuffers({anchor}); |
| 428 | fuse_attrs->SetOriginNodes(kernel_box.GetAscendIrNodes()); | 480 | fuse_attrs->SetOriginNodes(kernel_box.GetAscendIrNodes()); |
| 429 | fuse_attrs->SetOptimizedInputBuffers(kernel_box.GetOptimizedInputAscendBuffers()); | 481 | fuse_attrs->SetOptimizedInputBuffers(kernel_box.GetOptimizedInputAscendBuffers()); |
| @@ -2025,6 +2025,7 @@ REGISTER_LOWERING(Log) { | |||
| 2025 | GE_ASSERT_NOTNULL(node->GetInDataAnchor(0)); | 2025 | GE_ASSERT_NOTNULL(node->GetInDataAnchor(0)); |
| 2026 | auto src = node->GetInDataAnchor(0)->GetPeerOutAnchor(); | 2026 | auto src = node->GetInDataAnchor(0)->GetPeerOutAnchor(); |
| 2027 | GE_ASSERT_NOTNULL(src); | 2027 | GE_ASSERT_NOTNULL(src); |
| 2028 | + loop::GetKernelBox(src).Realize(); | ||
| 2028 | auto desc = src->GetOwnerNode()->GetOpDesc()->GetOutputDescPtr(src->GetIdx()); | 2029 | auto desc = src->GetOwnerNode()->GetOpDesc()->GetOutputDescPtr(src->GetIdx()); |
| 2029 | GE_ASSERT_NOTNULL(desc); | 2030 | GE_ASSERT_NOTNULL(desc); |
| 2030 | auto dtype = desc->GetDataType(); | 2031 | auto dtype = desc->GetDataType(); |
| @@ -2139,7 +2140,14 @@ REGISTER_LOWERING(Reshape) { | |||
| 2139 | auto x = loop::Load(node->GetInDataAnchor(0)); | 2140 | auto x = loop::Load(node->GetInDataAnchor(0)); |
| 2140 | auto reshape = loop::Reshape(x, dims, output_dims); | 2141 | auto reshape = loop::Reshape(x, dims, output_dims); |
| 2141 | LOWERING_WARN_RECORD_REASON(reshape.IsValid(), node, "no specific reshape pattern matched"); | 2142 | LOWERING_WARN_RECORD_REASON(reshape.IsValid(), node, "no specific reshape pattern matched"); |
| 2142 | - loop::StoreReshape(node->GetOutDataAnchor(0), reshape); | 2143 | + auto kernel_box = loop::Store(node->GetOutDataAnchor(0), reshape); |
| 2144 | + if (dims.size() > output_dims.size()) { | ||
| 2145 | + const auto tensor_attr = desc->GetAttrsGroup<AscTensorAttr>(); | ||
| 2146 | + if ((tensor_attr != nullptr) && (tensor_attr->axis.size() == dims.size())) { | ||
| 2147 | + kernel_box.SetReshapeBeforeAxis(tensor_attr->axis); | ||
| 2148 | + } | ||
| 2149 | + kernel_box.SetReshapeBeforeRepeats(dims); | ||
| 2150 | + } | ||
| 2143 | return GRAPH_SUCCESS; | 2151 | return GRAPH_SUCCESS; |
| 2144 | } | 2152 | } |
| 2145 | 2153 | ||
| @@ -10,7 +10,11 @@ | |||
| 10 | 10 | ||
| 11 | 11 | ||
| 12 | 12 | ||
| 13 | + | ||
| 13 | 14 | ||
| 15 | + | ||
| 16 | + | ||
| 17 | + | ||
| 14 | 18 | ||
| 15 | 19 | ||
| 16 | namespace ge { | 20 | namespace ge { |
| @@ -68,6 +72,10 @@ inline Status UpdateTensorAttrsIfEmpty(const NodePtr &node, AscTensorAttr *tenso | |||
| 68 | return SUCCESS; | 72 | return SUCCESS; |
| 69 | } | 73 | } |
| 70 | 74 | ||
| 75 | +inline bool ContainsAxisId(const std::vector<int64_t> &axis, const int64_t axis_id) { | ||
| 76 | + return std::find(axis.begin(), axis.end(), axis_id) != axis.end(); | ||
| 77 | +} | ||
| 78 | + | ||
| 71 | inline Status UpdateTensorAttrsIfNotEmpty(const NodePtr &node, const std::vector<int64_t> &axis, | 79 | inline Status UpdateTensorAttrsIfNotEmpty(const NodePtr &node, const std::vector<int64_t> &axis, |
| 72 | const std::vector<Expression> &repeats, AscTensorAttr *tensor_attr) { | 80 | const std::vector<Expression> &repeats, AscTensorAttr *tensor_attr) { |
| 73 | (void)repeats; | 81 | (void)repeats; |
| @@ -154,6 +162,451 @@ inline Status UpdateTensorAttrs(const NodePtr &node, const std::vector<int64_t> | |||
| 154 | return SUCCESS; | 162 | return SUCCESS; |
| 155 | } | 163 | } |
| 156 | 164 | ||
| 165 | +inline bool IsSameRepeat(const Expression &lhs, const Expression &rhs) { | ||
| 166 | + return SymbolicUtils::StaticCheckEq(lhs, rhs) == TriBool::kTrue; | ||
| 167 | +} | ||
| 168 | + | ||
| 169 | +inline bool ContainsRepeatsByOrder(const std::vector<AxisPtr> &axis, const std::vector<Expression> &repeats) { | ||
| 170 | + if (repeats.empty()) { | ||
| 171 | + return true; | ||
| 172 | + } | ||
| 173 | + size_t repeat_idx = 0U; | ||
| 174 | + for (const auto &axis_info : axis) { | ||
| 175 | + if (axis_info == nullptr) { | ||
| 176 | + continue; | ||
| 177 | + } | ||
| 178 | + if (IsSameRepeat(axis_info->size, repeats[repeat_idx])) { | ||
| 179 | + ++repeat_idx; | ||
| 180 | + if (repeat_idx == repeats.size()) { | ||
| 181 | + return true; | ||
| 182 | + } | ||
| 183 | + } | ||
| 184 | + } | ||
| 185 | + return false; | ||
| 186 | +} | ||
| 187 | + | ||
| 188 | +inline void MergeNoOpReshapeRepeats(const std::vector<Expression> &candidate_repeats, | ||
| 189 | + std::vector<Expression> &target_repeats) { | ||
| 190 | + if (candidate_repeats.empty()) { | ||
| 191 | + return; | ||
| 192 | + } | ||
| 193 | + if (target_repeats.empty()) { | ||
| 194 | + target_repeats = candidate_repeats; | ||
| 195 | + return; | ||
| 196 | + } | ||
| 197 | + size_t target_idx = 0U; | ||
| 198 | + for (const auto &repeat : candidate_repeats) { | ||
| 199 | + size_t matched_idx = target_repeats.size(); | ||
| 200 | + for (size_t i = target_idx; i < target_repeats.size(); ++i) { | ||
| 201 | + if (SymbolicUtils::StaticCheckEq(target_repeats[i], repeat) == TriBool::kTrue) { | ||
| 202 | + matched_idx = i; | ||
| 203 | + break; | ||
| 204 | + } | ||
| 205 | + } | ||
| 206 | + if (matched_idx != target_repeats.size()) { | ||
| 207 | + target_idx = matched_idx + 1U; | ||
| 208 | + continue; | ||
| 209 | + } | ||
| 210 | + target_repeats.insert(target_repeats.begin() + static_cast<ptrdiff_t>(target_idx), repeat); | ||
| 211 | + ++target_idx; | ||
| 212 | + } | ||
| 213 | +} | ||
| 214 | + | ||
| 215 | +inline std::vector<Expression> BuildNoOpReshapeRepeats(const std::vector<af::ReshapeAxisChangeInfo> &axis_changes) { | ||
| 216 | + std::vector<Expression> target_repeats; | ||
| 217 | + for (const auto &change : axis_changes) { | ||
| 218 | + MergeNoOpReshapeRepeats(change.before_repeats, target_repeats); | ||
| 219 | + MergeNoOpReshapeRepeats(change.after_repeats, target_repeats); | ||
| 220 | + } | ||
| 221 | + return target_repeats; | ||
| 222 | +} | ||
| 223 | + | ||
| 224 | +inline Status CollectSplitCoveredUnitAxes(const AscGraph &asc_graph, const AscGraphAttr &graph_attr, | ||
| 225 | + std::vector<int64_t> &split_covered_axis) { | ||
| 226 | + split_covered_axis.clear(); | ||
| 227 | + for (const auto &node : AscGraphUtils::GetComputeGraph(asc_graph)->GetAllNodes()) { | ||
| 228 | + if (node->GetType() != kSplitType) { | ||
| 229 | + continue; | ||
| 230 | + } | ||
| 231 | + const auto &op_desc = node->GetOpDesc(); | ||
| 232 | + GE_ASSERT_NOTNULL(op_desc); | ||
| 233 | + for (size_t output_idx = 0U; output_idx < node->GetAllOutDataAnchorsSize(); ++output_idx) { | ||
| 234 | + const auto output_tensor_desc = op_desc->MutableOutputDesc(output_idx); | ||
| 235 | + GE_ASSERT_NOTNULL(output_tensor_desc); | ||
| 236 | + const auto tensor_attr = output_tensor_desc->GetAttrsGroup<AscTensorAttr>(); | ||
| 237 | + if ((tensor_attr == nullptr) || (tensor_attr->axis.size() != tensor_attr->repeats.size()) || | ||
| 238 | + (tensor_attr->axis.size() != tensor_attr->strides.size())) { | ||
| 239 | + continue; | ||
| 240 | + } | ||
| 241 | + for (size_t i = 0U; i < tensor_attr->axis.size(); ++i) { | ||
| 242 | + const auto graph_axis_it = std::find_if(graph_attr.axis.begin(), graph_attr.axis.end(), | ||
| 243 | + [axis_id = tensor_attr->axis[i]](const AxisPtr &axis_info) { | ||
| 244 | + return (axis_info != nullptr) && (axis_info->id == axis_id); | ||
| 245 | + }); | ||
| 246 | + if (graph_axis_it == graph_attr.axis.end()) { | ||
| 247 | + continue; | ||
| 248 | + } | ||
| 249 | + const auto &graph_axis = *graph_axis_it; | ||
| 250 | + if (BackendUtils::IsEqOne(graph_axis->size) || !BackendUtils::IsEqOne(tensor_attr->repeats[i]) || | ||
| 251 | + !BackendUtils::IsEqZero(tensor_attr->strides[i]) || | ||
| 252 | + ContainsAxisId(split_covered_axis, tensor_attr->axis[i])) { | ||
| 253 | + continue; | ||
| 254 | + } | ||
| 255 | + split_covered_axis.push_back(tensor_attr->axis[i]); | ||
| 256 | + } | ||
| 257 | + } | ||
| 258 | + } | ||
| 259 | + return SUCCESS; | ||
| 260 | +} | ||
| 261 | + | ||
| 262 | +inline Status CollectConcatCoveredUnitAxes(const AscGraph &asc_graph, const AscGraphAttr &graph_attr, | ||
| 263 | + std::vector<int64_t> &covered_axis) { | ||
| 264 | + const auto compute_graph = AscGraphUtils::GetComputeGraph(asc_graph); | ||
| 265 | + GE_ASSERT_NOTNULL(compute_graph); | ||
| 266 | + for (const auto &node : AscGraphUtils::GetComputeGraph(asc_graph)->GetAllNodes()) { | ||
| 267 | + if (node->GetType() != kConcatType) { | ||
| 268 | + continue; | ||
| 269 | + } | ||
| 270 | + const auto &op_desc = node->GetOpDesc(); | ||
| 271 | + GE_ASSERT_NOTNULL(op_desc); | ||
| 272 | + if (node->GetAllOutDataAnchorsSize() == 0U) { | ||
| 273 | + continue; | ||
| 274 | + } | ||
| 275 | + const auto output_tensor_desc = op_desc->MutableOutputDesc(0U); | ||
| 276 | + GE_ASSERT_NOTNULL(output_tensor_desc); | ||
| 277 | + const auto output_tensor_attr = output_tensor_desc->GetAttrsGroup<AscTensorAttr>(); | ||
| 278 | + if ((output_tensor_attr == nullptr) || (output_tensor_attr->axis.size() != output_tensor_attr->repeats.size())) { | ||
| 279 | + continue; | ||
| 280 | + } | ||
| 281 | + for (size_t input_idx = 0U; input_idx < node->GetAllInDataAnchorsSize(); ++input_idx) { | ||
| 282 | + const auto input_tensor_desc = op_desc->MutableInputDesc(input_idx); | ||
| 283 | + GE_ASSERT_NOTNULL(input_tensor_desc); | ||
| 284 | + const auto input_tensor_attr = input_tensor_desc->GetAttrsGroup<AscTensorAttr>(); | ||
| 285 | + if ((input_tensor_attr == nullptr) || (input_tensor_attr->axis.size() != input_tensor_attr->repeats.size()) || | ||
| 286 | + (input_tensor_attr->axis.size() != input_tensor_attr->strides.size())) { | ||
| 287 | + continue; | ||
| 288 | + } | ||
| 289 | + for (size_t i = 0U; i < input_tensor_attr->axis.size(); ++i) { | ||
| 290 | + const auto output_axis_it = | ||
| 291 | + std::find(output_tensor_attr->axis.begin(), output_tensor_attr->axis.end(), input_tensor_attr->axis[i]); | ||
| 292 | + if (output_axis_it == output_tensor_attr->axis.end()) { | ||
| 293 | + continue; | ||
| 294 | + } | ||
| 295 | + const auto output_axis_idx = | ||
| 296 | + static_cast<size_t>(std::distance(output_tensor_attr->axis.begin(), output_axis_it)); | ||
| 297 | + if (output_axis_idx >= output_tensor_attr->repeats.size()) { | ||
| 298 | + continue; | ||
| 299 | + } | ||
| 300 | + const auto graph_axis_it = std::find_if(graph_attr.axis.begin(), graph_attr.axis.end(), | ||
| 301 | + [axis_id = input_tensor_attr->axis[i]](const AxisPtr &axis_info) { | ||
| 302 | + return (axis_info != nullptr) && (axis_info->id == axis_id); | ||
| 303 | + }); | ||
| 304 | + if (graph_axis_it == graph_attr.axis.end()) { | ||
| 305 | + continue; | ||
| 306 | + } | ||
| 307 | + const auto &graph_axis = *graph_axis_it; | ||
| 308 | + if (BackendUtils::IsEqOne(graph_axis->size) || !BackendUtils::IsEqOne(input_tensor_attr->repeats[i]) || | ||
| 309 | + !BackendUtils::IsEqZero(input_tensor_attr->strides[i]) || | ||
| 310 | + BackendUtils::IsEqOne(output_tensor_attr->repeats[output_axis_idx]) || | ||
| 311 | + !IsSameRepeat(graph_axis->size, output_tensor_attr->repeats[output_axis_idx]) || | ||
| 312 | + ContainsAxisId(covered_axis, input_tensor_attr->axis[i])) { | ||
| 313 | + continue; | ||
| 314 | + } | ||
| 315 | + covered_axis.push_back(input_tensor_attr->axis[i]); | ||
| 316 | + } | ||
| 317 | + } | ||
| 318 | + for (size_t output_axis_idx = 0U; output_axis_idx < output_tensor_attr->axis.size(); ++output_axis_idx) { | ||
| 319 | + const auto axis_id = output_tensor_attr->axis[output_axis_idx]; | ||
| 320 | + const auto graph_axis_it = std::find_if( | ||
| 321 | + graph_attr.axis.begin(), graph_attr.axis.end(), | ||
| 322 | + [axis_id](const AxisPtr &axis_info) { return (axis_info != nullptr) && (axis_info->id == axis_id); }); | ||
| 323 | + if ((graph_axis_it == graph_attr.axis.end()) || BackendUtils::IsEqOne((*graph_axis_it)->size) || | ||
| 324 | + BackendUtils::IsEqOne(output_tensor_attr->repeats[output_axis_idx]) || | ||
| 325 | + !IsSameRepeat((*graph_axis_it)->size, output_tensor_attr->repeats[output_axis_idx]) || | ||
| 326 | + ContainsAxisId(covered_axis, axis_id)) { | ||
| 327 | + continue; | ||
| 328 | + } | ||
| 329 | + for (const auto &producer_node : compute_graph->GetAllNodes()) { | ||
| 330 | + if ((producer_node == node) || (producer_node->GetType() == kConcatType)) { | ||
| 331 | + continue; | ||
| 332 | + } | ||
| 333 | + const auto &producer_op_desc = producer_node->GetOpDesc(); | ||
| 334 | + GE_ASSERT_NOTNULL(producer_op_desc); | ||
| 335 | + bool is_covered = false; | ||
| 336 | + for (size_t output_idx = 0U; output_idx < producer_node->GetAllOutDataAnchorsSize(); ++output_idx) { | ||
| 337 | + const auto producer_output_desc = producer_op_desc->MutableOutputDesc(output_idx); | ||
| 338 | + GE_ASSERT_NOTNULL(producer_output_desc); | ||
| 339 | + const auto producer_tensor_attr = producer_output_desc->GetAttrsGroup<AscTensorAttr>(); | ||
| 340 | + if ((producer_tensor_attr == nullptr) || | ||
| 341 | + (producer_tensor_attr->axis.size() != producer_tensor_attr->repeats.size()) || | ||
| 342 | + (producer_tensor_attr->axis.size() != producer_tensor_attr->strides.size())) { | ||
| 343 | + continue; | ||
| 344 | + } | ||
| 345 | + const auto producer_axis_it = | ||
| 346 | + std::find(producer_tensor_attr->axis.begin(), producer_tensor_attr->axis.end(), axis_id); | ||
| 347 | + if (producer_axis_it == producer_tensor_attr->axis.end()) { | ||
| 348 | + continue; | ||
| 349 | + } | ||
| 350 | + const auto producer_axis_idx = | ||
| 351 | + static_cast<size_t>(std::distance(producer_tensor_attr->axis.begin(), producer_axis_it)); | ||
| 352 | + if (BackendUtils::IsEqOne(producer_tensor_attr->repeats[producer_axis_idx]) && | ||
| 353 | + BackendUtils::IsEqZero(producer_tensor_attr->strides[producer_axis_idx])) { | ||
| 354 | + covered_axis.push_back(axis_id); | ||
| 355 | + is_covered = true; | ||
| 356 | + break; | ||
| 357 | + } | ||
| 358 | + } | ||
| 359 | + if (is_covered) { | ||
| 360 | + break; | ||
| 361 | + } | ||
| 362 | + } | ||
| 363 | + } | ||
| 364 | + } | ||
| 365 | + return SUCCESS; | ||
| 366 | +} | ||
| 367 | + | ||
| 368 | +inline Status CollectCoveredUnitAxes(const AscGraph &asc_graph, const AscGraphAttr &graph_attr, | ||
| 369 | + std::vector<int64_t> &covered_axis) { | ||
| 370 | + GE_ASSERT_SUCCESS(CollectSplitCoveredUnitAxes(asc_graph, graph_attr, covered_axis)); | ||
| 371 | + GE_ASSERT_SUCCESS(CollectConcatCoveredUnitAxes(asc_graph, graph_attr, covered_axis)); | ||
| 372 | + return SUCCESS; | ||
| 373 | +} | ||
| 374 | + | ||
| 375 | +inline AxisPtr MakeNoOpReshapeAxis(const int64_t axis_id, const Expression &repeat) { | ||
| 376 | + auto axis_info = ComGraphMakeShared<Axis>(); | ||
| 377 | + GE_ASSERT_NOTNULL(axis_info); | ||
| 378 | + axis_info->id = axis_id; | ||
| 379 | + axis_info->name = "reshape_axis_optimized_" + std::to_string(axis_id); | ||
| 380 | + axis_info->type = Axis::kAxisTypeOriginal; | ||
| 381 | + axis_info->size = repeat; | ||
| 382 | + return axis_info; | ||
| 383 | +} | ||
| 384 | + | ||
| 385 | +inline int64_t GetNextNoOpReshapeAxisId(const std::vector<AxisPtr> &axis) { | ||
| 386 | + int64_t max_axis_id = -1; | ||
| 387 | + for (const auto &axis_info : axis) { | ||
| 388 | + if (axis_info == nullptr) { | ||
| 389 | + continue; | ||
| 390 | + } | ||
| 391 | + max_axis_id = std::max(max_axis_id, axis_info->id); | ||
| 392 | + } | ||
| 393 | + return max_axis_id + 1; | ||
| 394 | +} | ||
| 395 | + | ||
| 396 | +inline void ShiftAxisIdFrom(const int64_t insert_axis_id, int64_t &axis_id) { | ||
| 397 | + if (axis_id >= insert_axis_id) { | ||
| 398 | + ++axis_id; | ||
| 399 | + } | ||
| 400 | +} | ||
| 401 | + | ||
| 402 | +inline void ShiftAxisIdsFrom(const int64_t insert_axis_id, std::vector<int64_t> &axis) { | ||
| 403 | + for (auto &axis_id : axis) { | ||
| 404 | + ShiftAxisIdFrom(insert_axis_id, axis_id); | ||
| 405 | + } | ||
| 406 | +} | ||
| 407 | + | ||
| 408 | +inline Status ShiftAscGraphAxisIdsFrom(const AscGraph &asc_graph, const int64_t insert_axis_id) { | ||
| 409 | + for (const auto &node : AscGraphUtils::GetComputeGraph(asc_graph)->GetAllNodes()) { | ||
| 410 | + const auto &op_desc = node->GetOpDesc(); | ||
| 411 | + GE_ASSERT_NOTNULL(op_desc); | ||
| 412 | + auto node_attr = op_desc->GetAttrsGroup<AscNodeAttr>(); | ||
| 413 | + if (node_attr != nullptr) { | ||
| 414 | + ShiftAxisIdsFrom(insert_axis_id, node_attr->sched.axis); | ||
| 415 | + ShiftAxisIdFrom(insert_axis_id, node_attr->sched.loop_axis); | ||
| 416 | + } | ||
| 417 | + for (size_t i = 0U; i < node->GetAllInDataAnchorsSize(); ++i) { | ||
| 418 | + const auto input_tensor_desc = op_desc->MutableInputDesc(i); | ||
| 419 | + GE_ASSERT_NOTNULL(input_tensor_desc); | ||
| 420 | + auto tensor_attr = input_tensor_desc->GetAttrsGroup<AscTensorAttr>(); | ||
| 421 | + if (tensor_attr == nullptr) { | ||
| 422 | + continue; | ||
| 423 | + } | ||
| 424 | + ShiftAxisIdsFrom(insert_axis_id, tensor_attr->axis); | ||
| 425 | + ShiftAxisIdsFrom(insert_axis_id, tensor_attr->vectorized_axis); | ||
| 426 | + } | ||
| 427 | + for (size_t i = 0U; i < node->GetAllOutDataAnchorsSize(); ++i) { | ||
| 428 | + const auto output_tensor_desc = op_desc->MutableOutputDesc(i); | ||
| 429 | + GE_ASSERT_NOTNULL(output_tensor_desc); | ||
| 430 | + auto tensor_attr = output_tensor_desc->GetAttrsGroup<AscTensorAttr>(); | ||
| 431 | + if (tensor_attr == nullptr) { | ||
| 432 | + continue; | ||
| 433 | + } | ||
| 434 | + ShiftAxisIdsFrom(insert_axis_id, tensor_attr->axis); | ||
| 435 | + ShiftAxisIdsFrom(insert_axis_id, tensor_attr->vectorized_axis); | ||
| 436 | + } | ||
| 437 | + } | ||
| 438 | + return SUCCESS; | ||
| 439 | +} | ||
| 440 | + | ||
| 441 | +inline int64_t FindInsertAxisIdByNextRepeat(const std::vector<AxisPtr> &axis, const size_t graph_axis_begin, | ||
| 442 | + const std::vector<Expression> &target_repeats, | ||
| 443 | + const size_t target_repeat_index) { | ||
| 444 | + for (size_t i = target_repeat_index + 1U; i < target_repeats.size(); ++i) { | ||
| 445 | + if (BackendUtils::IsEqOne(target_repeats[i])) { | ||
| 446 | + continue; | ||
| 447 | + } | ||
| 448 | + for (size_t j = graph_axis_begin; j < axis.size(); ++j) { | ||
| 449 | + if ((axis[j] != nullptr) && IsSameRepeat(axis[j]->size, target_repeats[i])) { | ||
| 450 | + return axis[j]->id; | ||
| 451 | + } | ||
| 452 | + } | ||
| 453 | + } | ||
| 454 | + return GetNextNoOpReshapeAxisId(axis); | ||
| 455 | +} | ||
| 456 | + | ||
| 457 | +template <typename ScoreFunc> | ||
| 458 | +inline std::vector<size_t> BuildBestOverlapTargetIndexes(const size_t source_size, const size_t target_size, | ||
| 459 | + const ScoreFunc &score_func) { | ||
| 460 | + if ((source_size == 0U) || (source_size > target_size)) { | ||
| 461 | + return {}; | ||
| 462 | + } | ||
| 463 | + constexpr int32_t kInvalidScore = -1000000; | ||
| 464 | + std::vector<std::vector<int32_t>> dp(source_size + 1U, std::vector<int32_t>(target_size + 1U, kInvalidScore)); | ||
| 465 | + for (size_t target_idx = 0U; target_idx <= target_size; ++target_idx) { | ||
| 466 | + dp[source_size][target_idx] = 0; | ||
| 467 | + } | ||
| 468 | + for (size_t source_idx = source_size; source_idx > 0U; --source_idx) { | ||
| 469 | + for (size_t target_idx = target_size; target_idx > 0U; --target_idx) { | ||
| 470 | + const auto source_pos = source_idx - 1U; | ||
| 471 | + const auto target_pos = target_idx - 1U; | ||
| 472 | + if ((source_size - source_pos) > (target_size - target_pos)) { | ||
| 473 | + continue; | ||
| 474 | + } | ||
| 475 | + const auto match_score = score_func(source_pos, target_pos) + dp[source_pos + 1U][target_pos + 1U]; | ||
| 476 | + const auto skip_score = dp[source_pos][target_pos + 1U]; | ||
| 477 | + dp[source_pos][target_pos] = std::max(match_score, skip_score); | ||
| 478 | + } | ||
| 479 | + } | ||
| 480 | + | ||
| 481 | + std::vector<size_t> target_indexes(source_size, target_size); | ||
| 482 | + size_t source_idx = 0U; | ||
| 483 | + size_t target_idx = 0U; | ||
| 484 | + while ((source_idx < source_size) && (target_idx < target_size)) { | ||
| 485 | + const auto match_score = score_func(source_idx, target_idx) + dp[source_idx + 1U][target_idx + 1U]; | ||
| 486 | + const auto skip_score = dp[source_idx][target_idx + 1U]; | ||
| 487 | + if (((target_size - target_idx - 1U) >= (source_size - source_idx)) && (skip_score >= match_score)) { | ||
| 488 | + ++target_idx; | ||
| 489 | + continue; | ||
| 490 | + } | ||
| 491 | + target_indexes[source_idx++] = target_idx++; | ||
| 492 | + } | ||
| 493 | + return target_indexes; | ||
| 494 | +} | ||
| 495 | + | ||
| 496 | +inline void ShiftInsertedTargetAxesFrom(const std::vector<AxisPtr> &graph_axis, const int64_t insert_axis_id, | ||
| 497 | + std::vector<AxisPtr> &target_axis) { | ||
| 498 | + for (const auto &axis_info : target_axis) { | ||
| 499 | + const auto is_graph_axis = std::find(graph_axis.begin(), graph_axis.end(), axis_info) != graph_axis.end(); | ||
| 500 | + if ((axis_info != nullptr) && !is_graph_axis) { | ||
| 501 | + ShiftAxisIdFrom(insert_axis_id, axis_info->id); | ||
| 502 | + } | ||
| 503 | + } | ||
| 504 | +} | ||
| 505 | + | ||
| 506 | +inline int64_t GetNextNoOpReshapeAxisId(const std::vector<AxisPtr> &graph_axis, | ||
| 507 | + const std::vector<AxisPtr> &target_axis) { | ||
| 508 | + int64_t max_axis_id = -1; | ||
| 509 | + for (const auto &axis_info : graph_axis) { | ||
| 510 | + if (axis_info != nullptr) { | ||
| 511 | + max_axis_id = std::max(max_axis_id, axis_info->id); | ||
| 512 | + } | ||
| 513 | + } | ||
| 514 | + for (const auto &axis_info : target_axis) { | ||
| 515 | + if (axis_info != nullptr) { | ||
| 516 | + max_axis_id = std::max(max_axis_id, axis_info->id); | ||
| 517 | + } | ||
| 518 | + } | ||
| 519 | + return max_axis_id + 1; | ||
| 520 | +} | ||
| 521 | + | ||
| 522 | +inline Status RestoreNoOpReshapeAxisWithSplitCoveredAxes(AscGraph &asc_graph, | ||
| 523 | + const std::vector<Expression> &target_repeats, | ||
| 524 | + const std::vector<int64_t> &split_covered_axis, | ||
| 525 | + AscGraphAttr *graph_attr) { | ||
| 526 | + GE_ASSERT_NOTNULL(graph_attr); | ||
| 527 | + if (graph_attr->axis.size() == target_repeats.size()) { | ||
| 528 | + GELOGD("graph %s axis size %zu equals no-op reshape target repeats size %zu, skip restore before complete attrs.", | ||
| 529 | + asc_graph.GetName().c_str(), graph_attr->axis.size(), target_repeats.size()); | ||
| 530 | + return SUCCESS; | ||
| 531 | + } | ||
| 532 | + if (graph_attr->axis.size() > target_repeats.size()) { | ||
| 533 | + GELOGD( | ||
| 534 | + "graph %s axis size %zu is greater than no-op reshape target repeats size %zu, skip restore before " | ||
| 535 | + "complete attrs.", | ||
| 536 | + asc_graph.GetName().c_str(), graph_attr->axis.size(), target_repeats.size()); | ||
| 537 | + return SUCCESS; | ||
| 538 | + } | ||
| 539 | + | ||
| 540 | + const auto matched_target_indexes = BuildBestOverlapTargetIndexes( | ||
| 541 | + graph_attr->axis.size(), target_repeats.size(), | ||
| 542 | + [&graph_attr, &target_repeats](size_t source_idx, size_t target_idx) -> int32_t { | ||
| 543 | + if (graph_attr->axis[source_idx] == nullptr) { | ||
| 544 | + return 0; | ||
| 545 | + } | ||
| 546 | + return IsSameRepeat(graph_attr->axis[source_idx]->size, target_repeats[target_idx]) ? 1 : 0; | ||
| 547 | + }); | ||
| 548 | + GE_ASSERT_TRUE(matched_target_indexes.size() == graph_attr->axis.size()); | ||
| 549 | + | ||
| 550 | + const size_t kInvalidIndex = target_repeats.size(); | ||
| 551 | + std::vector<size_t> target_to_graph_index(target_repeats.size(), kInvalidIndex); | ||
| 552 | + for (size_t graph_axis_idx = 0U; graph_axis_idx < matched_target_indexes.size(); ++graph_axis_idx) { | ||
| 553 | + GE_ASSERT_TRUE(matched_target_indexes[graph_axis_idx] < target_to_graph_index.size()); | ||
| 554 | + target_to_graph_index[matched_target_indexes[graph_axis_idx]] = graph_axis_idx; | ||
| 555 | + } | ||
| 556 | + | ||
| 557 | + std::vector<AxisPtr> target_axis; | ||
| 558 | + target_axis.reserve(target_repeats.size()); | ||
| 559 | + std::vector<int64_t> inserted_axis_ids; | ||
| 560 | + std::vector<Expression> inserted_axis_repeats; | ||
| 561 | + for (size_t target_repeat_idx = 0U; target_repeat_idx < target_repeats.size(); ++target_repeat_idx) { | ||
| 562 | + if (target_to_graph_index[target_repeat_idx] != kInvalidIndex) { | ||
| 563 | + target_axis.push_back(graph_attr->axis[target_to_graph_index[target_repeat_idx]]); | ||
| 564 | + continue; | ||
| 565 | + } | ||
| 566 | + | ||
| 567 | + int64_t insert_axis_id = GetNextNoOpReshapeAxisId(graph_attr->axis, target_axis); | ||
| 568 | + for (size_t next_target_idx = target_repeat_idx + 1U; next_target_idx < target_to_graph_index.size(); | ||
| 569 | + ++next_target_idx) { | ||
| 570 | + if (target_to_graph_index[next_target_idx] != kInvalidIndex) { | ||
| 571 | + const auto next_graph_axis = graph_attr->axis[target_to_graph_index[next_target_idx]]; | ||
| 572 | + GE_ASSERT_NOTNULL(next_graph_axis); | ||
| 573 | + insert_axis_id = next_graph_axis->id; | ||
| 574 | + break; | ||
| 575 | + } | ||
| 576 | + } | ||
| 577 | + for (const auto &axis_info : graph_attr->axis) { | ||
| 578 | + GE_ASSERT_NOTNULL(axis_info); | ||
| 579 | + ShiftAxisIdFrom(insert_axis_id, axis_info->id); | ||
| 580 | + } | ||
| 581 | + ShiftInsertedTargetAxesFrom(graph_attr->axis, insert_axis_id, target_axis); | ||
| 582 | + GE_ASSERT_SUCCESS(ShiftAscGraphAxisIdsFrom(asc_graph, insert_axis_id)); | ||
| 583 | + target_axis.push_back(MakeNoOpReshapeAxis(insert_axis_id, kSymbolOne)); | ||
| 584 | + inserted_axis_ids.push_back(insert_axis_id); | ||
| 585 | + inserted_axis_repeats.push_back(kSymbolOne); | ||
| 586 | + GELOGD("graph %s restore no-op reshape axis id %ld repeat %s at target repeat idx %zu before complete attrs.", | ||
| 587 | + asc_graph.GetName().c_str(), insert_axis_id, kSymbolOne.Str().get(), target_repeat_idx); | ||
| 588 | + } | ||
| 589 | + const auto old_axis_size = graph_attr->axis.size(); | ||
| 590 | + graph_attr->axis = std::move(target_axis); | ||
| 591 | + GELOGD( | ||
| 592 | + "graph %s restore no-op reshape axes by target repeats %s, covered axes %s, inserted axis ids %s, inserted " | ||
| 593 | + "repeats " | ||
| 594 | + "%s before complete attrs.", | ||
| 595 | + asc_graph.GetName().c_str(), AutofuseUtils::VectorToStr(target_repeats).c_str(), | ||
| 596 | + AutofuseUtils::VectorToStr(split_covered_axis).c_str(), AutofuseUtils::VectorToStr(inserted_axis_ids).c_str(), | ||
| 597 | + AutofuseUtils::VectorToStr(inserted_axis_repeats).c_str()); | ||
| 598 | + GELOGI( | ||
| 599 | + "graph %s restore no-op reshape axes with split-covered unit axes, graph axis size from %zu to %zu " | ||
| 600 | + "before complete attrs.", | ||
| 601 | + asc_graph.GetName().c_str(), old_axis_size, graph_attr->axis.size()); | ||
| 602 | + return SUCCESS; | ||
| 603 | +} | ||
| 604 | + | ||
| 605 | +inline bool IsReshapePaddingAxis(const AxisPtr &axis) { | ||
| 606 | + return (axis != nullptr) && BackendUtils::IsEqOne(axis->size) && | ||
| 607 | + (axis->name.rfind("reshape_axis_padding_", 0U) == 0U); | ||
| 608 | +} | ||
| 609 | + | ||
| 157 | inline Status CompleteNodeAttrsOnAscGraph(AscGraph &asc_graph, [[maybe_unused]] const NodePtr &asc_node) { | 610 | inline Status CompleteNodeAttrsOnAscGraph(AscGraph &asc_graph, [[maybe_unused]] const NodePtr &asc_node) { |
| 158 | TensorAttrInfo graph_attr; | 611 | TensorAttrInfo graph_attr; |
| 159 | GE_ASSERT_SUCCESS(BackendUtils::GetGraphAttrInfo(asc_graph, graph_attr)); | 612 | GE_ASSERT_SUCCESS(BackendUtils::GetGraphAttrInfo(asc_graph, graph_attr)); |
| @@ -201,6 +654,496 @@ inline Status CompleteNodeAttrsOnAscGraph(AscGraph &asc_graph, [[maybe_unused]] | |||
| 201 | return SUCCESS; | 654 | return SUCCESS; |
| 202 | } | 655 | } |
| 203 | 656 | ||
| 657 | +inline void CopyTensorAttrs(const AscTensorAttr &src_attr, AscTensorAttr &dst_attr) { | ||
| 658 | + dst_attr.axis = src_attr.axis; | ||
| 659 | + dst_attr.repeats = src_attr.repeats; | ||
| 660 | + dst_attr.strides = src_attr.strides; | ||
| 661 | + dst_attr.vectorized_axis = src_attr.vectorized_axis; | ||
| 662 | +} | ||
| 663 | + | ||
| 664 | +inline void ReorderGraphAxesToOriginalOrder(std::vector<AxisPtr> &axis) { | ||
| 665 | + std::vector<AxisPtr> sorted_original_axis; | ||
| 666 | + sorted_original_axis.reserve(axis.size()); | ||
| 667 | + for (const auto &axis_info : axis) { | ||
| 668 | + if (!IsReshapePaddingAxis(axis_info)) { | ||
| 669 | + sorted_original_axis.push_back(axis_info); | ||
| 670 | + } | ||
| 671 | + } | ||
| 672 | + std::stable_sort(sorted_original_axis.begin(), sorted_original_axis.end(), | ||
| 673 | + [](const AxisPtr &lhs, const AxisPtr &rhs) { | ||
| 674 | + if ((lhs == nullptr) || (rhs == nullptr)) { | ||
| 675 | + return lhs != nullptr; | ||
| 676 | + } | ||
| 677 | + return lhs->id < rhs->id; | ||
| 678 | + }); | ||
| 679 | + size_t original_axis_index = 0U; | ||
| 680 | + for (auto &axis_info : axis) { | ||
| 681 | + if (IsReshapePaddingAxis(axis_info)) { | ||
| 682 | + continue; | ||
| 683 | + } | ||
| 684 | + axis_info = sorted_original_axis[original_axis_index++]; | ||
| 685 | + } | ||
| 686 | +} | ||
| 687 | + | ||
| 688 | +inline void ReorderAxisIdsByGraphOrder(const std::vector<int64_t> &graph_axis_order, std::vector<int64_t> &axis) { | ||
| 689 | + std::vector<int64_t> reordered_axis; | ||
| 690 | + for (const auto graph_axis_id : graph_axis_order) { | ||
| 691 | + auto it = std::find(axis.begin(), axis.end(), graph_axis_id); | ||
| 692 | + if (it != axis.end()) { | ||
| 693 | + reordered_axis.push_back(graph_axis_id); | ||
| 694 | + } | ||
| 695 | + } | ||
| 696 | + for (const auto axis_id : axis) { | ||
| 697 | + if (std::find(graph_axis_order.begin(), graph_axis_order.end(), axis_id) == graph_axis_order.end()) { | ||
| 698 | + reordered_axis.push_back(axis_id); | ||
| 699 | + } | ||
| 700 | + } | ||
| 701 | + axis = reordered_axis; | ||
| 702 | +} | ||
| 703 | + | ||
| 704 | +inline void ReorderTensorAttrsByGraphOrder(const std::vector<int64_t> &graph_axis_order, AscTensorAttr &tensor_attr) { | ||
| 705 | + if (tensor_attr.axis.empty()) { | ||
| 706 | + return; | ||
| 707 | + } | ||
| 708 | + if ((tensor_attr.repeats.size() != tensor_attr.axis.size()) || | ||
| 709 | + (tensor_attr.strides.size() != tensor_attr.axis.size())) { | ||
| 710 | + return; | ||
| 711 | + } | ||
| 712 | + AscTensorAttr reordered_attr = tensor_attr; | ||
| 713 | + reordered_attr.axis.clear(); | ||
| 714 | + reordered_attr.repeats.clear(); | ||
| 715 | + reordered_attr.strides.clear(); | ||
| 716 | + for (const auto graph_axis_id : graph_axis_order) { | ||
| 717 | + auto it = std::find(tensor_attr.axis.begin(), tensor_attr.axis.end(), graph_axis_id); | ||
| 718 | + if (it == tensor_attr.axis.end()) { | ||
| 719 | + continue; | ||
| 720 | + } | ||
| 721 | + const auto idx = static_cast<size_t>(std::distance(tensor_attr.axis.begin(), it)); | ||
| 722 | + reordered_attr.axis.push_back(tensor_attr.axis[idx]); | ||
| 723 | + reordered_attr.repeats.push_back(tensor_attr.repeats[idx]); | ||
| 724 | + reordered_attr.strides.push_back(tensor_attr.strides[idx]); | ||
| 725 | + } | ||
| 726 | + for (size_t i = 0U; i < tensor_attr.axis.size(); ++i) { | ||
| 727 | + if (std::find(graph_axis_order.begin(), graph_axis_order.end(), tensor_attr.axis[i]) != graph_axis_order.end()) { | ||
| 728 | + continue; | ||
| 729 | + } | ||
| 730 | + reordered_attr.axis.push_back(tensor_attr.axis[i]); | ||
| 731 | + reordered_attr.repeats.push_back(tensor_attr.repeats[i]); | ||
| 732 | + reordered_attr.strides.push_back(tensor_attr.strides[i]); | ||
| 733 | + } | ||
| 734 | + CopyTensorAttrs(reordered_attr, tensor_attr); | ||
| 735 | +} | ||
| 736 | + | ||
| 737 | +inline Status ReorderAscGraphAttrsByGraphOrder(const AscGraph &asc_graph, | ||
| 738 | + const std::vector<int64_t> &graph_axis_order) { | ||
| 739 | + for (const auto &node : AscGraphUtils::GetComputeGraph(asc_graph)->GetAllNodes()) { | ||
| 740 | + const auto &op_desc = node->GetOpDesc(); | ||
| 741 | + GE_ASSERT_NOTNULL(op_desc); | ||
| 742 | + auto node_attr = op_desc->GetAttrsGroup<AscNodeAttr>(); | ||
| 743 | + if (node_attr != nullptr) { | ||
| 744 | + ReorderAxisIdsByGraphOrder(graph_axis_order, node_attr->sched.axis); | ||
| 745 | + } | ||
| 746 | + for (size_t i = 0U; i < node->GetAllOutDataAnchorsSize(); ++i) { | ||
| 747 | + const auto output_tensor_desc = op_desc->MutableOutputDesc(i); | ||
| 748 | + GE_ASSERT_NOTNULL(output_tensor_desc); | ||
| 749 | + auto tensor_attr = output_tensor_desc->GetAttrsGroup<AscTensorAttr>(); | ||
| 750 | + if (tensor_attr == nullptr) { | ||
| 751 | + continue; | ||
| 752 | + } | ||
| 753 | + ReorderTensorAttrsByGraphOrder(graph_axis_order, *tensor_attr); | ||
| 754 | + } | ||
| 755 | + } | ||
| 756 | + return SUCCESS; | ||
| 757 | +} | ||
| 758 | + | ||
| 759 | +inline Status ReorderAscGraphAttrsByCurrentGraphOrder(const AscGraph &asc_graph, const AscGraphAttr &graph_attr) { | ||
| 760 | + std::vector<int64_t> graph_axis_order; | ||
| 761 | + graph_axis_order.reserve(graph_attr.axis.size()); | ||
| 762 | + for (const auto &axis_info : graph_attr.axis) { | ||
| 763 | + GE_ASSERT_NOTNULL(axis_info); | ||
| 764 | + graph_axis_order.push_back(axis_info->id); | ||
| 765 | + } | ||
| 766 | + GE_ASSERT_SUCCESS(ReorderAscGraphAttrsByGraphOrder(asc_graph, graph_axis_order)); | ||
| 767 | + return SUCCESS; | ||
| 768 | +} | ||
| 769 | + | ||
| 770 | +inline void CompleteTensorAttrsByGraphOrderPreserveStrides(const NodePtr &node, const size_t output_idx, | ||
| 771 | + const std::vector<int64_t> &graph_axis_order, | ||
| 772 | + AscTensorAttr &tensor_attr) { | ||
| 773 | + const auto old_axis = tensor_attr.axis; | ||
| 774 | + std::vector<int64_t> inserted_axis_ids; | ||
| 775 | + if (tensor_attr.axis.size() >= graph_axis_order.size()) { | ||
| 776 | + return; | ||
| 777 | + } | ||
| 778 | + | ||
| 779 | + const auto matched_target_indexes = | ||
| 780 | + BuildBestOverlapTargetIndexes(tensor_attr.axis.size(), graph_axis_order.size(), | ||
| 781 | + [&tensor_attr, &graph_axis_order](size_t source_idx, size_t target_idx) -> int32_t { | ||
| 782 | + return tensor_attr.axis[source_idx] == graph_axis_order[target_idx] ? 1 : 0; | ||
| 783 | + }); | ||
| 784 | + if (matched_target_indexes.size() != tensor_attr.axis.size()) { | ||
| 785 | + return; | ||
| 786 | + } | ||
| 787 | + | ||
| 788 | + const size_t kInvalidIndex = graph_axis_order.size(); | ||
| 789 | + std::vector<size_t> target_to_tensor_index(graph_axis_order.size(), kInvalidIndex); | ||
| 790 | + for (size_t tensor_axis_idx = 0U; tensor_axis_idx < matched_target_indexes.size(); ++tensor_axis_idx) { | ||
| 791 | + target_to_tensor_index[matched_target_indexes[tensor_axis_idx]] = tensor_axis_idx; | ||
| 792 | + } | ||
| 793 | + | ||
| 794 | + AscTensorAttr completed_attr = tensor_attr; | ||
| 795 | + completed_attr.axis.clear(); | ||
| 796 | + if (!tensor_attr.repeats.empty()) { | ||
| 797 | + completed_attr.repeats.clear(); | ||
| 798 | + } | ||
| 799 | + if (!tensor_attr.strides.empty()) { | ||
| 800 | + completed_attr.strides.clear(); | ||
| 801 | + } | ||
| 802 | + for (size_t i = 0U; i < graph_axis_order.size(); ++i) { | ||
| 803 | + const auto tensor_idx = target_to_tensor_index[i]; | ||
| 804 | + if (tensor_idx != kInvalidIndex) { | ||
| 805 | + completed_attr.axis.push_back(tensor_attr.axis[tensor_idx]); | ||
| 806 | + if (!tensor_attr.repeats.empty()) { | ||
| 807 | + completed_attr.repeats.push_back(tensor_attr.repeats[tensor_idx]); | ||
| 808 | + } | ||
| 809 | + if (!tensor_attr.strides.empty()) { | ||
| 810 | + completed_attr.strides.push_back(tensor_attr.strides[tensor_idx]); | ||
| 811 | + } | ||
| 812 | + continue; | ||
| 813 | + } | ||
| 814 | + const auto graph_axis_id = graph_axis_order[i]; | ||
| 815 | + completed_attr.axis.push_back(graph_axis_id); | ||
| 816 | + if (!tensor_attr.repeats.empty()) { | ||
| 817 | + completed_attr.repeats.push_back(kSymbolOne); | ||
| 818 | + } | ||
| 819 | + if (!tensor_attr.strides.empty()) { | ||
| 820 | + completed_attr.strides.push_back(kSymbolZero); | ||
| 821 | + } | ||
| 822 | + inserted_axis_ids.push_back(graph_axis_id); | ||
| 823 | + GELOGD("node %s(%s) output %zu complete preserve tensor attrs with reshape axis id %ld at graph axis idx %zu.", | ||
| 824 | + node->GetName().c_str(), node->GetType().c_str(), output_idx, graph_axis_id, i); | ||
| 825 | + } | ||
| 826 | + CopyTensorAttrs(completed_attr, tensor_attr); | ||
| 827 | + if (!inserted_axis_ids.empty()) { | ||
| 828 | + GELOGD("node %s(%s) output %zu complete preserve tensor attrs with reshape axes %s, axis from %s to %s.", | ||
| 829 | + node->GetName().c_str(), node->GetType().c_str(), output_idx, | ||
| 830 | + AutofuseUtils::VectorToStr(inserted_axis_ids).c_str(), AutofuseUtils::VectorToStr(old_axis).c_str(), | ||
| 831 | + AutofuseUtils::VectorToStr(tensor_attr.axis).c_str()); | ||
| 832 | + } | ||
| 833 | +} | ||
| 834 | + | ||
| 835 | +inline Status UpdateTensorAttrsPreserveStrides(const NodePtr &node, const std::vector<int64_t> &axis, | ||
| 836 | + const std::vector<Expression> &repeats) { | ||
| 837 | + const auto &op_desc = node->GetOpDesc(); | ||
| 838 | + GE_ASSERT_NOTNULL(op_desc); | ||
| 839 | + for (size_t i = 0U; i < node->GetAllOutDataAnchorsSize(); ++i) { | ||
| 840 | + const auto output_tensor_desc = op_desc->MutableOutputDesc(i); | ||
| 841 | + GE_ASSERT_NOTNULL(output_tensor_desc); | ||
| 842 | + auto tensor_attr = output_tensor_desc->GetAttrsGroup<AscTensorAttr>(); | ||
| 843 | + GE_ASSERT_NOTNULL(tensor_attr); | ||
| 844 | + if (node->GetType() == kScalarType) { | ||
| 845 | + tensor_attr->axis = axis; | ||
| 846 | + tensor_attr->repeats.assign(axis.size(), kSymbolOne); | ||
| 847 | + tensor_attr->strides.assign(axis.size(), kSymbolZero); | ||
| 848 | + continue; | ||
| 849 | + } | ||
| 850 | + if ((tensor_attr->axis.empty()) && (node->GetType() != kDataType)) { | ||
| 851 | + GE_ASSERT_SUCCESS(UpdateTensorAttrsIfEmpty(node, tensor_attr, axis, repeats)); | ||
| 852 | + continue; | ||
| 853 | + } | ||
| 854 | + CompleteTensorAttrsByGraphOrderPreserveStrides(node, i, axis, *tensor_attr); | ||
| 855 | + GELOGD("after preserve attrs: node %s(%s), axis:%s, repeats:%s stride:%s.", node->GetName().c_str(), | ||
| 856 | + node->GetType().c_str(), AutofuseUtils::VectorToStr(tensor_attr->axis).c_str(), | ||
| 857 | + AutofuseUtils::VectorToStr(tensor_attr->repeats).c_str(), | ||
| 858 | + AutofuseUtils::VectorToStr(tensor_attr->strides).c_str()); | ||
| 859 | + } | ||
| 860 | + return SUCCESS; | ||
| 861 | +} | ||
| 862 | + | ||
| 863 | +inline Status CompleteNodeAttrsOnAscGraphPreserveStrides(AscGraph &asc_graph, const NodePtr &asc_node) { | ||
| 864 | + (void)asc_node; | ||
| 865 | + TensorAttrInfo graph_attr; | ||
| 866 | + GE_ASSERT_SUCCESS(BackendUtils::GetGraphAttrInfo(asc_graph, graph_attr)); | ||
| 867 | + GELOGI("max sched axis %s in graph %s, preserve tensor strides.", AutofuseUtils::VectorToStr(graph_attr.axis).c_str(), | ||
| 868 | + asc_graph.GetName().c_str()); | ||
| 869 | + | ||
| 870 | + for (const auto &node : AscGraphUtils::GetComputeGraph(asc_graph)->GetAllNodes()) { | ||
| 871 | + if (IsTorchDataType(node)) { | ||
| 872 | + GELOGI("torch node %s(%s) not complete node attr.", node->GetName().c_str(), node->GetType().c_str()); | ||
| 873 | + continue; | ||
| 874 | + } | ||
| 875 | + if (IsCubeRelatedAscNode(node)) { | ||
| 876 | + GELOGI("cube related node %s(%s) not complete node attr.", node->GetName().c_str(), node->GetType().c_str()); | ||
| 877 | + continue; | ||
| 878 | + } | ||
| 879 | + if ((!IsGatherData(node)) && (!BackendUtils::IsOutputNode(node))) { | ||
| 880 | + GE_ASSERT_SUCCESS(UpdateTensorAttrsPreserveStrides(node, graph_attr.axis, graph_attr.repeats)); | ||
| 881 | + } | ||
| 882 | + const auto &op_desc = node->GetOpDesc(); | ||
| 883 | + GE_ASSERT_NOTNULL(op_desc); | ||
| 884 | + auto node_attr = op_desc->GetAttrsGroup<AscNodeAttr>(); | ||
| 885 | + GE_ASSERT_NOTNULL(node_attr); | ||
| 886 | + GELOGI("node %s(%s) before complete sched axis %s to %s in graph %s, preserve tensor strides.", | ||
| 887 | + node->GetName().c_str(), node->GetType().c_str(), AutofuseUtils::VectorToStr(node_attr->sched.axis).c_str(), | ||
| 888 | + AutofuseUtils::VectorToStr(graph_attr.axis).c_str(), asc_graph.GetName().c_str()); | ||
| 889 | + node_attr->sched.axis = graph_attr.axis; | ||
| 890 | + GELOGI("node %s(%s) after complete sched axis %s to %s in graph %s, preserve tensor strides.", | ||
| 891 | + node->GetName().c_str(), node->GetType().c_str(), AutofuseUtils::VectorToStr(node_attr->sched.axis).c_str(), | ||
| 892 | + AutofuseUtils::VectorToStr(graph_attr.axis).c_str(), asc_graph.GetName().c_str()); | ||
| 893 | + } | ||
| 894 | + return SUCCESS; | ||
| 895 | +} | ||
| 896 | + | ||
| 897 | +inline Status HasLoadFeedingSplit(const AscGraph &asc_graph, bool &has_load_feeding_split) { | ||
| 898 | + has_load_feeding_split = false; | ||
| 899 | + for (const auto &node : AscGraphUtils::GetComputeGraph(asc_graph)->GetAllNodes()) { | ||
| 900 | + if (node->GetType() != kLoadType) { | ||
| 901 | + continue; | ||
| 902 | + } | ||
| 903 | + std::vector<NodePtr> peer_in_nodes; | ||
| 904 | + GE_ASSERT_SUCCESS(asc_adapt::GetPeerInNodes(node, peer_in_nodes, 0)); | ||
| 905 | + for (const auto &peer_in_node : peer_in_nodes) { | ||
| 906 | + if (peer_in_node->GetType() == kSplitType) { | ||
| 907 | + has_load_feeding_split = true; | ||
| 908 | + return SUCCESS; | ||
| 909 | + } | ||
| 910 | + } | ||
| 911 | + } | ||
| 912 | + return SUCCESS; | ||
| 913 | +} | ||
| 914 | + | ||
| 915 | +inline Status CompleteSplitInputTensorAttrs(const AscTensorAttr &src_attr, const AscTensorAttr &split_output_attr, | ||
| 916 | + AscTensorAttr &dst_attr) { | ||
| 917 | + dst_attr.axis = split_output_attr.axis; | ||
| 918 | + dst_attr.repeats.clear(); | ||
| 919 | + dst_attr.strides.clear(); | ||
| 920 | + dst_attr.vectorized_axis = split_output_attr.vectorized_axis; | ||
| 921 | + | ||
| 922 | + size_t src_start = 0U; | ||
| 923 | + if ((!src_attr.axis.empty()) && (!src_attr.repeats.empty()) && (!src_attr.strides.empty()) && | ||
| 924 | + BackendUtils::IsEqOne(src_attr.repeats.front()) && BackendUtils::IsEqZero(src_attr.strides.front())) { | ||
| 925 | + src_start = 1U; | ||
| 926 | + } | ||
| 927 | + for (size_t i = src_start; i < src_attr.repeats.size(); ++i) { | ||
| 928 | + dst_attr.repeats.push_back(src_attr.repeats[i]); | ||
| 929 | + } | ||
| 930 | + while (dst_attr.repeats.size() < dst_attr.axis.size()) { | ||
| 931 | + dst_attr.repeats.push_back(kSymbolOne); | ||
| 932 | + } | ||
| 933 | + if (dst_attr.repeats.size() > dst_attr.axis.size()) { | ||
| 934 | + dst_attr.repeats.resize(dst_attr.axis.size()); | ||
| 935 | + } | ||
| 936 | + GE_ASSERT_SUCCESS(UpdateStridesByReapeats(dst_attr.repeats, dst_attr.strides)); | ||
| 937 | + return SUCCESS; | ||
| 938 | +} | ||
| 939 | + | ||
| 940 | +inline Status UpdateLoadAndInputAttrsFromSplitOutput(const NodePtr &load_node, const AscTensorAttr &split_output_attr) { | ||
| 941 | + auto load_output_desc = load_node->GetOpDesc()->MutableOutputDesc(0U); | ||
| 942 | + GE_ASSERT_NOTNULL(load_output_desc); | ||
| 943 | + auto load_tensor_attr = load_output_desc->GetAttrsGroup<AscTensorAttr>(); | ||
| 944 | + GE_ASSERT_NOTNULL(load_tensor_attr); | ||
| 945 | + AscTensorAttr completed_load_attr = *load_tensor_attr; | ||
| 946 | + GE_ASSERT_SUCCESS(CompleteSplitInputTensorAttrs(*load_tensor_attr, split_output_attr, completed_load_attr)); | ||
| 947 | + CopyTensorAttrs(completed_load_attr, *load_tensor_attr); | ||
| 948 | + | ||
| 949 | + std::vector<NodePtr> peer_out_nodes; | ||
| 950 | + GE_ASSERT_SUCCESS(asc_adapt::GetPeerOutNodes(load_node, peer_out_nodes)); | ||
| 951 | + for (const auto &peer_out_node : peer_out_nodes) { | ||
| 952 | + GeTensorDescPtr peer_output_desc; | ||
| 953 | + GE_ASSERT_SUCCESS(asc_adapt::GetOutputTensorDesc(peer_out_node, peer_output_desc)); | ||
| 954 | + auto peer_tensor_attr = peer_output_desc->GetAttrsGroup<AscTensorAttr>(); | ||
| 955 | + GE_ASSERT_NOTNULL(peer_tensor_attr); | ||
| 956 | + CopyTensorAttrs(completed_load_attr, *peer_tensor_attr); | ||
| 957 | + } | ||
| 958 | + return SUCCESS; | ||
| 959 | +} | ||
| 960 | + | ||
| 961 | +inline Status UpdateLoadAttrsFromSplitOutputs(const AscGraph &asc_graph) { | ||
| 962 | + bool has_load_feeding_split = false; | ||
| 963 | + GE_ASSERT_SUCCESS(HasLoadFeedingSplit(asc_graph, has_load_feeding_split)); | ||
| 964 | + if (!has_load_feeding_split) { | ||
| 965 | + return SUCCESS; | ||
| 966 | + } | ||
| 967 | + for (const auto &node : AscGraphUtils::GetComputeGraph(asc_graph)->GetAllNodes()) { | ||
| 968 | + if (node->GetType() != kLoadType) { | ||
| 969 | + continue; | ||
| 970 | + } | ||
| 971 | + std::vector<NodePtr> peer_in_nodes; | ||
| 972 | + GE_ASSERT_SUCCESS(asc_adapt::GetPeerInNodes(node, peer_in_nodes, 0)); | ||
| 973 | + for (const auto &peer_in_node : peer_in_nodes) { | ||
| 974 | + if (peer_in_node->GetType() != kSplitType) { | ||
| 975 | + continue; | ||
| 976 | + } | ||
| 977 | + AscTensorAttr *split_output_attr = nullptr; | ||
| 978 | + GE_ASSERT_SUCCESS(asc_adapt::GetOutputTensorAttr(peer_in_node, split_output_attr)); | ||
| 979 | + GE_ASSERT_NOTNULL(split_output_attr); | ||
| 980 | + if (split_output_attr->axis.empty()) { | ||
| 981 | + continue; | ||
| 982 | + } | ||
| 983 | + GE_ASSERT_SUCCESS(UpdateLoadAndInputAttrsFromSplitOutput(node, *split_output_attr)); | ||
| 984 | + GELOGI("load node %s(%s) update tensor attrs from split output %s(%s).", node->GetName().c_str(), | ||
| 985 | + node->GetType().c_str(), peer_in_node->GetName().c_str(), peer_in_node->GetType().c_str()); | ||
| 986 | + break; | ||
| 987 | + } | ||
| 988 | + } | ||
| 989 | + return SUCCESS; | ||
| 990 | +} | ||
| 991 | + | ||
| 992 | +inline Status DumpPadLeadingUnitAxisResult(const AscGraph &asc_graph, const NodePtr &asc_node, const char *process_name, | ||
| 993 | + const ComputeGraphPtr &fused_graph) { | ||
| 994 | + GELOGI("AscBackendPostProcessor: End to run the process(%s) on the graph, graph: %s, parent node: %s(%s).", | ||
| 995 | + process_name, fused_graph->GetName().c_str(), asc_node->GetNamePtr(), asc_node->GetType().c_str()); | ||
| 996 | + GELOGD("dump node:%s(%s) asc graph info(with tensor attr info):", asc_node->GetNamePtr(), | ||
| 997 | + asc_node->GetType().c_str()); | ||
| 998 | + (void)asc_graph; | ||
| 999 | + BackendUtils::DumpAscGraph(asc_node); | ||
| 1000 | + return SUCCESS; | ||
| 1001 | +} | ||
| 1002 | + | ||
| 1003 | +inline Status PadLeadingUnitAxisByReshapeAxisChanges(AscGraph &asc_graph, const NodePtr &asc_node, | ||
| 1004 | + const std::vector<af::ReshapeAxisChangeInfo> &axis_changes) { | ||
| 1005 | + if (axis_changes.empty()) { | ||
| 1006 | + return SUCCESS; | ||
| 1007 | + } | ||
| 1008 | + constexpr const char *kPadLeadingUnitAxisProcName = "pad_leading_unit_axis"; | ||
| 1009 | + const auto fused_graph = AscGraphUtils::GetComputeGraph(asc_graph); | ||
| 1010 | + GE_ASSERT_NOTNULL(fused_graph); | ||
| 1011 | + GE_ASSERT_SUCCESS(BackendUtils::AddInputOutputNodesForAscGraph(fused_graph)); | ||
| 1012 | + GE_ASSERT_SUCCESS(CacheGraphBeforePostProcess(asc_node, kPadLeadingUnitAxisProcName, fused_graph)); | ||
| 1013 | + const auto graph_attr = AscGraphUtils::GetComputeGraph(asc_graph)->GetAttrsGroup<AscGraphAttr>(); | ||
| 1014 | + GE_ASSERT_NOTNULL(graph_attr); | ||
| 1015 | + ReorderGraphAxesToOriginalOrder(graph_attr->axis); | ||
| 1016 | + const auto target_repeats = BuildNoOpReshapeRepeats(axis_changes); | ||
| 1017 | + if (target_repeats.empty()) { | ||
| 1018 | + return SUCCESS; | ||
| 1019 | + } | ||
| 1020 | + GELOGD("node %s(%s) graph %s start to pad leading unit axes by %zu reshape axis changes, target repeats %s.", | ||
| 1021 | + asc_node->GetName().c_str(), asc_node->GetType().c_str(), asc_graph.GetName().c_str(), axis_changes.size(), | ||
| 1022 | + AutofuseUtils::VectorToStr(target_repeats).c_str()); | ||
| 1023 | + std::vector<int64_t> covered_axis; | ||
| 1024 | + GE_ASSERT_SUCCESS(CollectCoveredUnitAxes(asc_graph, *graph_attr, covered_axis)); | ||
| 1025 | + GE_ASSERT_SUCCESS(RestoreNoOpReshapeAxisWithSplitCoveredAxes(asc_graph, target_repeats, covered_axis, graph_attr)); | ||
| 1026 | + GE_ASSERT_SUCCESS(ReorderAscGraphAttrsByCurrentGraphOrder(asc_graph, *graph_attr)); | ||
| 1027 | + GELOGI("graph %s restore fused reshape axes by changes from fused AscBackend, covered axes %s before complete attrs.", | ||
| 1028 | + asc_graph.GetName().c_str(), AutofuseUtils::VectorToStr(covered_axis).c_str()); | ||
| 1029 | + GE_ASSERT_SUCCESS(UpdateLoadAttrsFromSplitOutputs(asc_graph)); | ||
| 1030 | + return SUCCESS; | ||
| 1031 | +} | ||
| 1032 | + | ||
| 1033 | +inline Status PadLeadingUnitAxisAndCompleteAttrs(AscGraph &asc_graph, const NodePtr &asc_node, | ||
| 1034 | + const std::vector<af::ReshapeAxisChangeInfo> &axis_changes) { | ||
| 1035 | + GE_ASSERT_SUCCESS(PadLeadingUnitAxisByReshapeAxisChanges(asc_graph, asc_node, axis_changes)); | ||
| 1036 | + if (axis_changes.empty()) { | ||
| 1037 | + return SUCCESS; | ||
| 1038 | + } | ||
| 1039 | + GE_ASSERT_SUCCESS(CompleteNodeAttrsOnAscGraphPreserveStrides(asc_graph, asc_node)); | ||
| 1040 | + const auto fused_graph = AscGraphUtils::GetComputeGraph(asc_graph); | ||
| 1041 | + GE_ASSERT_NOTNULL(fused_graph); | ||
| 1042 | + GE_ASSERT_SUCCESS(DumpPadLeadingUnitAxisResult(asc_graph, asc_node, "pad_leading_unit_axis", fused_graph)); | ||
| 1043 | + return SUCCESS; | ||
| 1044 | +} | ||
| 1045 | + | ||
| 1046 | +inline bool IsSameReshapeAxisChange(const af::ReshapeAxisChangeInfo &lhs, const af::ReshapeAxisChangeInfo &rhs) { | ||
| 1047 | + return (lhs.before_axis == rhs.before_axis) && (lhs.after_axis == rhs.after_axis) && | ||
| 1048 | + (lhs.before_repeats.size() == rhs.before_repeats.size()) && | ||
| 1049 | + (lhs.after_repeats.size() == rhs.after_repeats.size()) && | ||
| 1050 | + std::equal(lhs.before_repeats.begin(), lhs.before_repeats.end(), rhs.before_repeats.begin(), IsSameRepeat) && | ||
| 1051 | + std::equal(lhs.after_repeats.begin(), lhs.after_repeats.end(), rhs.after_repeats.begin(), IsSameRepeat); | ||
| 1052 | +} | ||
| 1053 | + | ||
| 1054 | +inline void AppendUniqueReshapeAxisChange(const af::ReshapeAxisChangeInfo &axis_change, | ||
| 1055 | + std::vector<af::ReshapeAxisChangeInfo> &axis_changes) { | ||
| 1056 | + const auto it = std::find_if(axis_changes.begin(), axis_changes.end(), [&axis_change](const auto &saved_change) { | ||
| 1057 | + return IsSameReshapeAxisChange(axis_change, saved_change); | ||
| 1058 | + }); | ||
| 1059 | + if (it == axis_changes.end()) { | ||
| 1060 | + axis_changes.push_back(axis_change); | ||
| 1061 | + } | ||
| 1062 | +} | ||
| 1063 | + | ||
| 1064 | +inline Status CollectNodeReshapeAxisChanges(const NodePtr &node, std::vector<af::ReshapeAxisChangeInfo> &axis_changes) { | ||
| 1065 | + if (!BackendUtils::IsBackendFuseNode(node)) { | ||
| 1066 | + return SUCCESS; | ||
| 1067 | + } | ||
| 1068 | + const auto attr = node->GetOpDescBarePtr()->GetAttrsGroup<AutoFuseAttrs>(); | ||
| 1069 | + GE_ASSERT_NOTNULL(attr); | ||
| 1070 | + if (node->GetType() == kAscBackendType) { | ||
| 1071 | + for (const auto &axis_change : attr->GetReshapeAxisChanges()) { | ||
| 1072 | + AppendUniqueReshapeAxisChange(axis_change, axis_changes); | ||
| 1073 | + } | ||
| 1074 | + return SUCCESS; | ||
| 1075 | + } | ||
| 1076 | + if (node->GetType() != kFusedAscBackendType) { | ||
| 1077 | + return SUCCESS; | ||
| 1078 | + } | ||
| 1079 | + GE_ASSERT_NOTNULL(attr->GetFuseComputeGraph()); | ||
| 1080 | + for (const auto &inner_node : attr->GetFuseComputeGraph()->GetAllNodes()) { | ||
| 1081 | + if ((inner_node == nullptr) || !BackendUtils::IsBackendFuseNode(inner_node) || | ||
| 1082 | + (inner_node->GetType() != kAscBackendType)) { | ||
| 1083 | + continue; | ||
| 1084 | + } | ||
| 1085 | + GE_ASSERT_SUCCESS(CollectNodeReshapeAxisChanges(inner_node, axis_changes)); | ||
| 1086 | + } | ||
| 1087 | + return SUCCESS; | ||
| 1088 | +} | ||
| 1089 | + | ||
| 1090 | +inline Status PadNodeLeadingUnitAxisByReshapeAxisChanges(const NodePtr &node, | ||
| 1091 | + const std::vector<af::ReshapeAxisChangeInfo> &axis_changes) { | ||
| 1092 | + if (axis_changes.empty() || !BackendUtils::IsBackendFuseNode(node)) { | ||
| 1093 | + return SUCCESS; | ||
| 1094 | + } | ||
| 1095 | + const auto attr = node->GetOpDescBarePtr()->GetAttrsGroup<AutoFuseAttrs>(); | ||
| 1096 | + GE_ASSERT_NOTNULL(attr); | ||
| 1097 | + if (node->GetType() == kAscBackendType) { | ||
| 1098 | + GE_ASSERT_NOTNULL(attr->GetAscGraph()); | ||
| 1099 | + GE_ASSERT_SUCCESS(PadLeadingUnitAxisByReshapeAxisChanges(*(attr->GetAscGraph()), node, axis_changes)); | ||
| 1100 | + return SUCCESS; | ||
| 1101 | + } | ||
| 1102 | + if (node->GetType() != kFusedAscBackendType) { | ||
| 1103 | + return SUCCESS; | ||
| 1104 | + } | ||
| 1105 | + GE_ASSERT_NOTNULL(attr->GetFuseComputeGraph()); | ||
| 1106 | + for (const auto &inner_node : attr->GetFuseComputeGraph()->GetAllNodes()) { | ||
| 1107 | + if ((inner_node == nullptr) || !BackendUtils::IsBackendFuseNode(inner_node) || | ||
| 1108 | + (inner_node->GetType() != kAscBackendType)) { | ||
| 1109 | + continue; | ||
| 1110 | + } | ||
| 1111 | + GE_ASSERT_SUCCESS(PadNodeLeadingUnitAxisByReshapeAxisChanges(inner_node, axis_changes)); | ||
| 1112 | + } | ||
| 1113 | + return SUCCESS; | ||
| 1114 | +} | ||
| 1115 | + | ||
| 1116 | +inline Status PadPairLeadingUnitAxisBeforeCompleteAttrs(const NodePtr &node1, const NodePtr &node2) { | ||
| 1117 | + std::vector<af::ReshapeAxisChangeInfo> axis_changes; | ||
| 1118 | + GE_ASSERT_SUCCESS(CollectNodeReshapeAxisChanges(node1, axis_changes)); | ||
| 1119 | + GE_ASSERT_SUCCESS(CollectNodeReshapeAxisChanges(node2, axis_changes)); | ||
| 1120 | + GE_ASSERT_SUCCESS(PadNodeLeadingUnitAxisByReshapeAxisChanges(node1, axis_changes)); | ||
| 1121 | + GE_ASSERT_SUCCESS(PadNodeLeadingUnitAxisByReshapeAxisChanges(node2, axis_changes)); | ||
| 1122 | + return SUCCESS; | ||
| 1123 | +} | ||
| 1124 | + | ||
| 1125 | +inline bool IsInnerAscBackendNode(const NodePtr &node) { | ||
| 1126 | + return (node != nullptr) && BackendUtils::IsBackendFuseNode(node) && (node->GetType() == kAscBackendType); | ||
| 1127 | +} | ||
| 1128 | + | ||
| 1129 | +inline Status KeepPaddedLeadingUnitAxis(const AscGraph &asc_graph, std::vector<int64_t> &graph_invalid_axis_id) { | ||
| 1130 | + const auto graph_attr = AscGraphUtils::GetComputeGraph(asc_graph)->GetAttrsGroup<AscGraphAttr>(); | ||
| 1131 | + GE_ASSERT_NOTNULL(graph_attr); | ||
| 1132 | + auto padded_axis_it = std::find_if(graph_attr->axis.begin(), graph_attr->axis.end(), [](const AxisPtr &axis_info) { | ||
| 1133 | + return (axis_info != nullptr) && (axis_info->name.rfind("axis_padding_", 0U) == 0U); | ||
| 1134 | + }); | ||
| 1135 | + if (padded_axis_it == graph_attr->axis.end()) { | ||
| 1136 | + return SUCCESS; | ||
| 1137 | + } | ||
| 1138 | + const auto padded_axis_id = (*padded_axis_it)->id; | ||
| 1139 | + auto it = std::find(graph_invalid_axis_id.begin(), graph_invalid_axis_id.end(), padded_axis_id); | ||
| 1140 | + if (it != graph_invalid_axis_id.end()) { | ||
| 1141 | + GELOGI("graph %s keep padded leading unit axis id %ld.", asc_graph.GetName().c_str(), padded_axis_id); | ||
| 1142 | + graph_invalid_axis_id.erase(it); | ||
| 1143 | + } | ||
| 1144 | + return SUCCESS; | ||
| 1145 | +} | ||
| 1146 | + | ||
| 204 | inline Status UpdateInvalidIndices(const NodePtr &node, std::vector<int64_t> &graph_invalid_axis_id) { | 1147 | inline Status UpdateInvalidIndices(const NodePtr &node, std::vector<int64_t> &graph_invalid_axis_id) { |
| 205 | const auto &op_desc = node->GetOpDesc(); | 1148 | const auto &op_desc = node->GetOpDesc(); |
| 206 | GE_ASSERT_NOTNULL(op_desc); | 1149 | GE_ASSERT_NOTNULL(op_desc); |
| @@ -290,6 +1233,26 @@ inline Status FlashContinueGraphAxis(std::vector<AxisPtr> &axis, const std::vect | |||
| 290 | return SUCCESS; | 1233 | return SUCCESS; |
| 291 | } | 1234 | } |
| 292 | 1235 | ||
| 1236 | +inline Status FlashContinueAxisId(const std::vector<int64_t> &graph_invalid_axis_id, int64_t &axis_id) { | ||
| 1237 | + if (axis_id == af::kIdNone) { | ||
| 1238 | + return SUCCESS; | ||
| 1239 | + } | ||
| 1240 | + if (std::find(graph_invalid_axis_id.begin(), graph_invalid_axis_id.end(), axis_id) != graph_invalid_axis_id.end()) { | ||
| 1241 | + axis_id = af::kIdNone; | ||
| 1242 | + return SUCCESS; | ||
| 1243 | + } | ||
| 1244 | + const auto less_axis_count = std::count_if(graph_invalid_axis_id.begin(), graph_invalid_axis_id.end(), | ||
| 1245 | + [axis_id](int64_t id) { return id < axis_id; }); | ||
| 1246 | + axis_id -= static_cast<int64_t>(less_axis_count); | ||
| 1247 | + return SUCCESS; | ||
| 1248 | +} | ||
| 1249 | + | ||
| 1250 | +inline void RemoveAxisIds(std::vector<int64_t> &axis, const std::vector<int64_t> &graph_invalid_axis_id) { | ||
| 1251 | + for (const auto axis_id : graph_invalid_axis_id) { | ||
| 1252 | + axis.erase(std::remove(axis.begin(), axis.end(), axis_id), axis.end()); | ||
| 1253 | + } | ||
| 1254 | +} | ||
| 1255 | + | ||
| 293 | inline Status RemoveReduceOriginalInvalidAxis(const NodePtr &asc_node, | 1256 | inline Status RemoveReduceOriginalInvalidAxis(const NodePtr &asc_node, |
| 294 | const std::vector<int64_t> &graph_invalid_axis_id) { | 1257 | const std::vector<int64_t> &graph_invalid_axis_id) { |
| 295 | auto attr = BackendUtils::GetNodeAutoFuseAttr(asc_node); | 1258 | auto attr = BackendUtils::GetNodeAutoFuseAttr(asc_node); |
| @@ -341,6 +1304,8 @@ inline Status RemoveNodeInvalidAxis(const NodePtr &node, const std::vector<int64 | |||
| 341 | GE_ASSERT_NOTNULL(op_desc); | 1304 | GE_ASSERT_NOTNULL(op_desc); |
| 342 | auto node_attr = op_desc->GetAttrsGroup<AscNodeAttr>(); | 1305 | auto node_attr = op_desc->GetAttrsGroup<AscNodeAttr>(); |
| 343 | GE_ASSERT_NOTNULL(node_attr); | 1306 | GE_ASSERT_NOTNULL(node_attr); |
| 1307 | + const bool loop_axis_removed = std::find(graph_invalid_axis_id.begin(), graph_invalid_axis_id.end(), | ||
| 1308 | + node_attr->sched.loop_axis) != graph_invalid_axis_id.end(); | ||
| 344 | 1309 | ||
| 345 | for (auto it = graph_invalid_axis_id.begin(); it != graph_invalid_axis_id.end(); ++it) { | 1310 | for (auto it = graph_invalid_axis_id.begin(); it != graph_invalid_axis_id.end(); ++it) { |
| 346 | auto axis_id = *it; | 1311 | auto axis_id = *it; |
| @@ -374,10 +1339,16 @@ inline Status RemoveNodeInvalidAxis(const NodePtr &node, const std::vector<int64 | |||
| 374 | tensor_attr->repeats.erase(tensor_attr->repeats.begin() + axis_idx); | 1339 | tensor_attr->repeats.erase(tensor_attr->repeats.begin() + axis_idx); |
| 375 | tensor_attr->strides.erase(tensor_attr->strides.begin() + axis_idx); | 1340 | tensor_attr->strides.erase(tensor_attr->strides.begin() + axis_idx); |
| 376 | } | 1341 | } |
| 1342 | + RemoveAxisIds(tensor_attr->vectorized_axis, graph_invalid_axis_id); | ||
| 377 | } | 1343 | } |
| 378 | } | 1344 | } |
| 379 | // 后端有连续轴约束,需要把删除后的剩余的轴从0开始重新变连续(但是轴的相对位置不变) | 1345 | // 后端有连续轴约束,需要把删除后的剩余的轴从0开始重新变连续(但是轴的相对位置不变) |
| 380 | GE_ASSERT_SUCCESS(FlashContinueNodeAxis(node_attr->sched.axis, graph_invalid_axis_id)); | 1346 | GE_ASSERT_SUCCESS(FlashContinueNodeAxis(node_attr->sched.axis, graph_invalid_axis_id)); |
| 1347 | + if (loop_axis_removed) { | ||
| 1348 | + node_attr->sched.loop_axis = node_attr->sched.axis.empty() ? af::kIdNone : node_attr->sched.axis.back(); | ||
| 1349 | + } else { | ||
| 1350 | + GE_ASSERT_SUCCESS(FlashContinueAxisId(graph_invalid_axis_id, node_attr->sched.loop_axis)); | ||
| 1351 | + } | ||
| 381 | if (BackendUtils::IsOutputNode(node)) { | 1352 | if (BackendUtils::IsOutputNode(node)) { |
| 382 | return SUCCESS; | 1353 | return SUCCESS; |
| 383 | } | 1354 | } |
| @@ -387,6 +1358,7 @@ inline Status RemoveNodeInvalidAxis(const NodePtr &node, const std::vector<int64 | |||
| 387 | auto tensor_attr = output_tensor_desc->GetAttrsGroup<AscTensorAttr>(); | 1358 | auto tensor_attr = output_tensor_desc->GetAttrsGroup<AscTensorAttr>(); |
| 388 | GE_ASSERT_NOTNULL(tensor_attr); | 1359 | GE_ASSERT_NOTNULL(tensor_attr); |
| 389 | GE_ASSERT_SUCCESS(FlashContinueNodeAxis(tensor_attr->axis, graph_invalid_axis_id)); | 1360 | GE_ASSERT_SUCCESS(FlashContinueNodeAxis(tensor_attr->axis, graph_invalid_axis_id)); |
| 1361 | + GE_ASSERT_SUCCESS(FlashContinueNodeAxis(tensor_attr->vectorized_axis, graph_invalid_axis_id)); | ||
| 390 | } | 1362 | } |
| 391 | return SUCCESS; | 1363 | return SUCCESS; |
| 392 | } | 1364 | } |
| @@ -612,6 +1584,7 @@ inline Status GetAndRemoveInvalidAxis(AscGraph &asc_graph, const NodePtr &asc_no | |||
| 612 | GE_ASSERT_SUCCESS(GetInvalidAxis(asc_graph, graph_invalid_axis_id)); | 1584 | GE_ASSERT_SUCCESS(GetInvalidAxis(asc_graph, graph_invalid_axis_id)); |
| 613 | // 3、gather data2如果全是无效轴需要保留一根轴 | 1585 | // 3、gather data2如果全是无效轴需要保留一根轴 |
| 614 | GE_ASSERT_SUCCESS(UpdateInvalidAxis(asc_graph, graph_invalid_axis_id, gather_data2_nodes)); | 1586 | GE_ASSERT_SUCCESS(UpdateInvalidAxis(asc_graph, graph_invalid_axis_id, gather_data2_nodes)); |
| 1587 | + GE_ASSERT_SUCCESS(KeepPaddedLeadingUnitAxis(asc_graph, graph_invalid_axis_id)); | ||
| 615 | // 4、根据需要删除的无效轴处理gather的替换轴index和gather data | 1588 | // 4、根据需要删除的无效轴处理gather的替换轴index和gather data |
| 616 | GE_ASSERT_SUCCESS(RemoveGatherInvalidAxis(asc_graph, graph_invalid_axis_id)); | 1589 | GE_ASSERT_SUCCESS(RemoveGatherInvalidAxis(asc_graph, graph_invalid_axis_id)); |
| 617 | // 5、删除和刷新无效轴(使用 std::greater<int64_t> | 1590 | // 5、删除和刷新无效轴(使用 std::greater<int64_t> |
| @@ -648,9 +1621,7 @@ inline Status RemoveInvalidAxisOnAscGraph(const ComputeGraphPtr &graph, bool is_ | |||
| 648 | GELOGD("after remove invalid axis, dump node:%s(%s) asc graph info(with tensor attr info):", node->GetNamePtr(), | 1621 | GELOGD("after remove invalid axis, dump node:%s(%s) asc graph info(with tensor attr info):", node->GetNamePtr(), |
| 649 | node->GetType().c_str()); | 1622 | node->GetType().c_str()); |
| 650 | BackendUtils::DumpAscGraph(node); | 1623 | BackendUtils::DumpAscGraph(node); |
| 651 | - } else if ( | 1624 | + } else if (node->GetType() == kFusedAscBackendType) { |
| 652 | - node->GetType() == | ||
| 653 | - kFusedAscBackendType) { // FusedAscBackend无效轴删除解决输出多引用给两个reshape,分别在不同的位置加size为1的轴,再后融合concat场景,会反推出transpose,需要删除无效轴 | ||
| 654 | GELOGI("FusedAscbackend node: %s(%s) start to run the process(%s).", node->GetName().c_str(), | 1625 | GELOGI("FusedAscbackend node: %s(%s) start to run the process(%s).", node->GetName().c_str(), |
| 655 | node->GetType().c_str(), proc_name.c_str()); | 1626 | node->GetType().c_str(), proc_name.c_str()); |
| 656 | GE_ASSERT_NOTNULL(node->GetOpDescBarePtr()); | 1627 | GE_ASSERT_NOTNULL(node->GetOpDescBarePtr()); |
| @@ -213,6 +213,7 @@ GE 的融合优化走两条路线: | |||
| 213 | **路线二:自动融合**(`compiler/graph/optimize/autofuse/`) | 213 | **路线二:自动融合**(`compiler/graph/optimize/autofuse/`) |
| 214 | 214 | ||
| 215 | 基于算子分类和依赖分析,自动识别可融合的算子组合。这个子系统(`AutofuseOptimize`)在 `AfterPrecisionRefine` 阶段被调用。 | 215 | 基于算子分类和依赖分析,自动识别可融合的算子组合。这个子系统(`AutofuseOptimize`)在 `AfterPrecisionRefine` 阶段被调用。 |
| 216 | +AutoFuse 会为 reshape 记录多组 before/after axis change,后续补轴流程按 `repeat` 相对位置恢复 reshape-only 的 `repeat=1` 轴,避免将纯 reshape 轴变化误判为 transpose。 | ||
| 216 | 217 | ||
| 217 | ### 3.2 Pattern Matcher 融合框架 | 218 | ### 3.2 Pattern Matcher 融合框架 |
| 218 | 219 | ||
| @@ -316,6 +317,8 @@ Python 层会自动创建 ES `GraphBuilder`、图输入、图输出和 pattern c | |||
| 316 | 317 | ||
| 317 | 自动融合子系统(`compiler/graph/optimize/autofuse/`)包含完整的子目录结构:`ascendc/`(AscendC 算子融合)、`ascir/`、`att/`、`codegen/`、`compiler/`、`optimize/` 等,表明它不仅做融合决策,还涉及融合后算子的代码生成——这是一条从算子分类到代码生成的完整路径。 | 318 | 自动融合子系统(`compiler/graph/optimize/autofuse/`)包含完整的子目录结构:`ascendc/`(AscendC 算子融合)、`ascir/`、`att/`、`codegen/`、`compiler/`、`optimize/` 等,表明它不仅做融合决策,还涉及融合后算子的代码生成——这是一条从算子分类到代码生成的完整路径。 |
| 318 | 319 | ||
| 320 | +AutoFuse 后处理会在 `AscBackendSchedulerAdapter::DoBeforePass()` 中补齐 `AscGraph` 节点调度轴和 tensor 轴。对于同一个 `FusedAscBackend` 内由 reshape 减轴/加轴连接的多个 `AscBackend`,轴补齐只在该 fused 容器内传播并迭代到收敛,确保相连 `AscBackend` 的 axis 数量一致;传播不能跨不同 `FusedAscBackend`,也不能退回通用 `complete_attrs` 兜底逻辑中处理。 | ||
| 321 | + | ||
| 319 | ## 4. 引擎分区 | 322 | ## 4. 引擎分区 |
| 320 | 323 | ||
| 321 | ### 4.1 引擎分区的必要性 | 324 | ### 4.1 引擎分区的必要性 |
| @@ -9,6 +9,7 @@ | |||
| 9 | */ | 9 | */ |
| 10 | 10 | ||
| 11 | 11 | ||
| 12 | + | ||
| 12 | 13 | ||
| 13 | 14 | ||
| 14 | 15 | ||
| @@ -23,7 +24,6 @@ | |||
| 23 | 24 | ||
| 24 | 25 | ||
| 25 | 26 | ||
| 26 | - | ||
| 27 | 27 | ||
| 28 | 28 | ||
| 29 | 29 | ||
| @@ -206,6 +206,128 @@ std::shared_ptr<AscGraph> CreatAddAscGraph(ge::AscGraph &graph) { | |||
| 206 | compute_graph->SetGraphOutNodesInfo(output_nodes); | 206 | compute_graph->SetGraphOutNodesInfo(output_nodes); |
| 207 | return std::shared_ptr<ge::AscGraph>(new ge::AscGraph(graph)); | 207 | return std::shared_ptr<ge::AscGraph>(new ge::AscGraph(graph)); |
| 208 | } | 208 | } |
| 209 | + | ||
| 210 | +std::shared_ptr<AscGraph> CreateReshapeAxisChangeAscGraph(ge::AscGraph &graph, std::vector<int64_t> &original_axis, | ||
| 211 | + std::vector<Expression> &original_repeats) { | ||
| 212 | + const auto one = Symbol(1); | ||
| 213 | + const Expression A = graph.CreateSizeVar("A"); | ||
| 214 | + const Expression C = graph.CreateSizeVar("C"); | ||
| 215 | + | ||
| 216 | + auto a = graph.CreateAxis("A", A); | ||
| 217 | + auto b = graph.CreateAxis("B", one); | ||
| 218 | + auto c = graph.CreateAxis("C", C); | ||
| 219 | + original_axis = {a.id, b.id, c.id}; | ||
| 220 | + original_repeats = {A, one, C}; | ||
| 221 | + | ||
| 222 | + auto graph_attr = AscGraphUtils::GetComputeGraph(graph)->GetAttrsGroup<AscGraphAttr>(); | ||
| 223 | + GE_ASSERT_NOTNULL(graph_attr); | ||
| 224 | + graph_attr->axis.erase(std::remove_if(graph_attr->axis.begin(), graph_attr->axis.end(), | ||
| 225 | + [&b](const AxisPtr &axis) { return (axis != nullptr) && (axis->id == b.id); }), | ||
| 226 | + graph_attr->axis.end()); | ||
| 227 | + | ||
| 228 | + af::ascir_op::Data x("x", graph); | ||
| 229 | + x.attr.sched.axis = {a.id, c.id}; | ||
| 230 | + x.attr.sched.loop_axis = c.id; | ||
| 231 | + x.y.dtype = DT_FLOAT16; | ||
| 232 | + *x.y.axis = {a.id, c.id}; | ||
| 233 | + *x.y.repeats = {A, C}; | ||
| 234 | + *x.y.strides = {C, one}; | ||
| 235 | + | ||
| 236 | + af::ascir_op::Load x_local("x_local"); | ||
| 237 | + x_local.x = x.y; | ||
| 238 | + x_local.attr.sched.axis = {a.id, c.id}; | ||
| 239 | + x_local.y.dtype = DT_FLOAT16; | ||
| 240 | + *x_local.y.axis = {a.id, c.id}; | ||
| 241 | + *x_local.y.repeats = {A, C}; | ||
| 242 | + *x_local.y.strides = {C, one}; | ||
| 243 | + | ||
| 244 | + af::ascir_op::Store x_out("x_out"); | ||
| 245 | + x_out.x = x_local.y; | ||
| 246 | + x_out.attr.sched.axis = {a.id, c.id}; | ||
| 247 | + x_out.attr.sched.loop_axis = c.id; | ||
| 248 | + x_out.y.dtype = DT_FLOAT16; | ||
| 249 | + *x_out.y.axis = {a.id, c.id}; | ||
| 250 | + *x_out.y.repeats = {A, C}; | ||
| 251 | + *x_out.y.strides = {C, one}; | ||
| 252 | + | ||
| 253 | + af::ascir_op::Output output("output"); | ||
| 254 | + output.x = x_out.y; | ||
| 255 | + output.attr.sched.axis = {a.id, c.id}; | ||
| 256 | + output.attr.sched.loop_axis = c.id; | ||
| 257 | + output.y.dtype = DT_FLOAT16; | ||
| 258 | + *output.y.axis = {a.id, c.id}; | ||
| 259 | + *output.y.repeats = {A, C}; | ||
| 260 | + *output.y.strides = {C, one}; | ||
| 261 | + | ||
| 262 | + auto output_node = graph.FindNode("output"); | ||
| 263 | + auto compute_graph = output_node->GetOwnerComputeGraph(); | ||
| 264 | + std::vector<std::pair<NodePtr, int32_t>> output_nodes{{output_node, 0}}; | ||
| 265 | + compute_graph->SetOutputSize(1U); | ||
| 266 | + compute_graph->SetGraphOutNodesInfo(output_nodes); | ||
| 267 | + return std::shared_ptr<ge::AscGraph>(new ge::AscGraph(graph)); | ||
| 268 | +} | ||
| 269 | + | ||
| 270 | +std::shared_ptr<AscGraph> CreateRestoredLeadingReshapeAxisGraph(ge::AscGraph &graph) { | ||
| 271 | + const auto one = Symbol(1); | ||
| 272 | + const auto size0 = Symbol(22); | ||
| 273 | + const auto size1 = Symbol(15120); | ||
| 274 | + auto z0 = graph.CreateAxis("z0", size0); | ||
| 275 | + auto z1 = graph.CreateAxis("z1", size1); | ||
| 276 | + | ||
| 277 | + auto reshape_padding = ComGraphMakeShared<Axis>(); | ||
| 278 | + GE_ASSERT_NOTNULL(reshape_padding); | ||
| 279 | + reshape_padding->id = 2; | ||
| 280 | + reshape_padding->name = "reshape_axis_padding_2"; | ||
| 281 | + reshape_padding->type = Axis::kAxisTypeOriginal; | ||
| 282 | + reshape_padding->size = one; | ||
| 283 | + auto graph_attr = AscGraphUtils::GetComputeGraph(graph)->GetAttrsGroup<AscGraphAttr>(); | ||
| 284 | + GE_ASSERT_NOTNULL(graph_attr); | ||
| 285 | + graph_attr->axis = {reshape_padding, graph_attr->axis[0], graph_attr->axis[1]}; | ||
| 286 | + | ||
| 287 | + const std::vector<int64_t> axis = {reshape_padding->id, z0.id, z1.id}; | ||
| 288 | + af::ascir_op::Data x("x", graph); | ||
| 289 | + x.attr.sched.axis = axis; | ||
| 290 | + x.attr.sched.loop_axis = z1.id; | ||
| 291 | + x.y.dtype = DT_FLOAT16; | ||
| 292 | + *x.y.axis = axis; | ||
| 293 | + *x.y.repeats = {one, size0, size1}; | ||
| 294 | + *x.y.strides = {Symbol(0), size1, one}; | ||
| 295 | + | ||
| 296 | + af::ascir_op::Load x_local("x_local"); | ||
| 297 | + x_local.x = x.y; | ||
| 298 | + x_local.attr.sched.axis = axis; | ||
| 299 | + x_local.attr.sched.loop_axis = z1.id; | ||
| 300 | + x_local.y.dtype = DT_FLOAT16; | ||
| 301 | + *x_local.y.axis = axis; | ||
| 302 | + *x_local.y.repeats = {one, size0, size1}; | ||
| 303 | + *x_local.y.strides = {Symbol(0), size1, one}; | ||
| 304 | + | ||
| 305 | + af::ascir_op::Store x_out("x_out"); | ||
| 306 | + x_out.x = x_local.y; | ||
| 307 | + x_out.attr.sched.axis = axis; | ||
| 308 | + x_out.attr.sched.loop_axis = z1.id; | ||
| 309 | + x_out.y.dtype = DT_FLOAT16; | ||
| 310 | + *x_out.y.axis = axis; | ||
| 311 | + *x_out.y.repeats = {one, size0, size1}; | ||
| 312 | + *x_out.y.strides = {Symbol(0), size1, one}; | ||
| 313 | + | ||
| 314 | + af::ascir_op::Output output("output"); | ||
| 315 | + output.x = x_out.y; | ||
| 316 | + output.attr.sched.axis = axis; | ||
| 317 | + output.attr.sched.loop_axis = z1.id; | ||
| 318 | + output.y.dtype = DT_FLOAT16; | ||
| 319 | + *output.y.axis = {}; | ||
| 320 | + *output.y.repeats = {}; | ||
| 321 | + *output.y.strides = {}; | ||
| 322 | + | ||
| 323 | + auto output_node = graph.FindNode("output"); | ||
| 324 | + auto compute_graph = output_node->GetOwnerComputeGraph(); | ||
| 325 | + std::vector<std::pair<NodePtr, int32_t>> output_nodes{{output_node, 0}}; | ||
| 326 | + compute_graph->SetOutputSize(1U); | ||
| 327 | + compute_graph->SetGraphOutNodesInfo(output_nodes); | ||
| 328 | + return std::shared_ptr<ge::AscGraph>(new ge::AscGraph(graph)); | ||
| 329 | +} | ||
| 330 | + | ||
| 209 | /* | 331 | /* |
| 210 | * data | 332 | * data |
| 211 | * / \ | 333 | * / \ |
| @@ -15862,6 +15984,595 @@ TEST_F(AscBackendPostProcessorTest, GatherInsertCastImproveprecision) { | |||
| 15862 | EXPECT_NE(cnt, 2); | 15984 | EXPECT_NE(cnt, 2); |
| 15863 | } | 15985 | } |
| 15864 | 15986 | ||
| 15987 | +TEST_F(AscBackendPostProcessorTest, CompleteAttrs_RestoreReshapeAxisChangeInfo) { | ||
| 15988 | + GraphBuilder builder("reshape_outer"); | ||
| 15989 | + auto asc_backend = builder.AddNode("reshape_backend", kAscBackendType, 1, 1, FORMAT_ND, DT_FLOAT16, {2, 3}); | ||
| 15990 | + ASSERT_NE(asc_backend, nullptr); | ||
| 15991 | + const auto attr = GetOrCreateAutoFuseAttrs(asc_backend->GetOpDesc()); | ||
| 15992 | + ASSERT_NE(attr, nullptr); | ||
| 15993 | + | ||
| 15994 | + ge::AscGraph reshape_graph("reshape_reduced_axis"); | ||
| 15995 | + std::vector<int64_t> original_axis; | ||
| 15996 | + std::vector<Expression> original_repeats; | ||
| 15997 | + attr->SetAscGraph(CreateReshapeAxisChangeAscGraph(reshape_graph, original_axis, original_repeats), | ||
| 15998 | + loop::FuseType::kReshape); | ||
| 15999 | + af::ReshapeAxisChangeInfo change; | ||
| 16000 | + change.before_axis = original_axis; | ||
| 16001 | + change.before_repeats = original_repeats; | ||
| 16002 | + change.after_axis = {original_axis[0], original_axis[2]}; | ||
| 16003 | + change.after_repeats = {original_repeats[0], original_repeats[2]}; | ||
| 16004 | + attr->AddReshapeAxisChange(change); | ||
| 16005 | + | ||
| 16006 | + const auto graph_attr = AscGraphUtils::GetComputeGraph(*(attr->GetAscGraph()))->GetAttrsGroup<AscGraphAttr>(); | ||
| 16007 | + ASSERT_NE(graph_attr, nullptr); | ||
| 16008 | + ASSERT_EQ(graph_attr->axis.size(), 2U); | ||
| 16009 | + | ||
| 16010 | + EXPECT_EQ( | ||
| 16011 | + asc_adapt::PadLeadingUnitAxisAndCompleteAttrs(*(attr->GetAscGraph()), asc_backend, attr->GetReshapeAxisChanges()), | ||
| 16012 | + SUCCESS); | ||
| 16013 | + | ||
| 16014 | + std::vector<int64_t> graph_axis; | ||
| 16015 | + for (const auto &axis : graph_attr->axis) { | ||
| 16016 | + ASSERT_NE(axis, nullptr); | ||
| 16017 | + graph_axis.push_back(axis->id); | ||
| 16018 | + } | ||
| 16019 | + ASSERT_EQ(graph_axis.size(), original_axis.size()); | ||
| 16020 | + EXPECT_EQ(graph_axis[0], original_axis[0]); | ||
| 16021 | + EXPECT_EQ(graph_axis[1], original_axis[1]); | ||
| 16022 | + EXPECT_EQ(graph_axis[2], original_axis[2]); | ||
| 16023 | + | ||
| 16024 | + const auto store = AscGraphUtils::GetComputeGraph(*(attr->GetAscGraph()))->FindNode("x_out"); | ||
| 16025 | + ASSERT_NE(store, nullptr); | ||
| 16026 | + AscTensorAttr *store_attr = nullptr; | ||
| 16027 | + ASSERT_EQ(asc_adapt::GetOutputTensorAttr(store, store_attr), SUCCESS); | ||
| 16028 | + ASSERT_NE(store_attr, nullptr); | ||
| 16029 | + EXPECT_EQ(store_attr->axis, graph_axis); | ||
| 16030 | + ASSERT_EQ(store_attr->repeats.size(), original_repeats.size()); | ||
| 16031 | + ASSERT_EQ(store_attr->strides.size(), original_repeats.size()); | ||
| 16032 | + EXPECT_TRUE(BackendUtils::IsEqOne(store_attr->repeats[1])); | ||
| 16033 | + EXPECT_TRUE(BackendUtils::IsEqZero(store_attr->strides[1])); | ||
| 16034 | +} | ||
| 16035 | + | ||
| 16036 | +TEST_F(AscBackendPostProcessorTest, CompleteAttrs_RestoreSingleLeadingUnitReshapeAsNoOp) { | ||
| 16037 | + GraphBuilder builder("single_leading_unit_reshape_outer"); | ||
| 16038 | + auto asc_backend = | ||
| 16039 | + builder.AddNode("single_leading_unit_reshape_backend", kAscBackendType, 1, 1, FORMAT_ND, DT_FLOAT16, {22, 15120}); | ||
| 16040 | + ASSERT_NE(asc_backend, nullptr); | ||
| 16041 | + const auto attr = GetOrCreateAutoFuseAttrs(asc_backend->GetOpDesc()); | ||
| 16042 | + ASSERT_NE(attr, nullptr); | ||
| 16043 | + | ||
| 16044 | + ge::AscGraph graph("single_leading_unit_reshape_graph"); | ||
| 16045 | + const auto one = Symbol(1); | ||
| 16046 | + const auto size0 = Symbol(22); | ||
| 16047 | + const auto size1 = Symbol(15120); | ||
| 16048 | + auto z0 = graph.CreateAxis("z0", size0); | ||
| 16049 | + auto z1 = graph.CreateAxis("z1", size1); | ||
| 16050 | + const std::vector<int64_t> graph_axis = {z0.id, z1.id}; | ||
| 16051 | + | ||
| 16052 | + af::ascir_op::Data data("single_data", graph); | ||
| 16053 | + data.attr.sched.axis = graph_axis; | ||
| 16054 | + data.y.dtype = DT_FLOAT16; | ||
| 16055 | + *data.y.axis = graph_axis; | ||
| 16056 | + *data.y.repeats = {size0, size1}; | ||
| 16057 | + *data.y.strides = {size1, one}; | ||
| 16058 | + | ||
| 16059 | + af::ascir_op::Load load("single_load"); | ||
| 16060 | + load.x = data.y; | ||
| 16061 | + load.attr.sched.axis = graph_axis; | ||
| 16062 | + load.y.dtype = DT_FLOAT16; | ||
| 16063 | + *load.y.axis = graph_axis; | ||
| 16064 | + *load.y.repeats = {size0, size1}; | ||
| 16065 | + *load.y.strides = {size1, one}; | ||
| 16066 | + | ||
| 16067 | + af::ascir_op::Store store("single_store"); | ||
| 16068 | + store.x = load.y; | ||
| 16069 | + store.attr.sched.axis = graph_axis; | ||
| 16070 | + store.y.dtype = DT_FLOAT16; | ||
| 16071 | + *store.y.axis = graph_axis; | ||
| 16072 | + *store.y.repeats = {size0, size1}; | ||
| 16073 | + *store.y.strides = {size1, one}; | ||
| 16074 | + | ||
| 16075 | + af::ascir_op::Output output("single_output"); | ||
| 16076 | + output.x = store.y; | ||
| 16077 | + output.attr.sched.axis = graph_axis; | ||
| 16078 | + auto output_node = graph.FindNode("single_output"); | ||
| 16079 | + ASSERT_NE(output_node, nullptr); | ||
| 16080 | + auto compute_graph = output_node->GetOwnerComputeGraph(); | ||
| 16081 | + std::vector<std::pair<NodePtr, int32_t>> output_nodes{{output_node, 0}}; | ||
| 16082 | + compute_graph->SetOutputSize(1U); | ||
| 16083 | + compute_graph->SetGraphOutNodesInfo(output_nodes); | ||
| 16084 | + attr->SetAscGraph(std::shared_ptr<ge::AscGraph>(new ge::AscGraph(graph)), loop::FuseType::kPointwise); | ||
| 16085 | + | ||
| 16086 | + af::ReshapeAxisChangeInfo change; | ||
| 16087 | + change.before_axis = {0, 1, 2}; | ||
| 16088 | + change.before_repeats = {one, size0, size1}; | ||
| 16089 | + change.after_axis = {0, 1}; | ||
| 16090 | + change.after_repeats = {size0, size1}; | ||
| 16091 | + attr->AddReshapeAxisChange(change); | ||
| 16092 | + | ||
| 16093 | + ASSERT_EQ( | ||
| 16094 | + asc_adapt::PadLeadingUnitAxisAndCompleteAttrs(*(attr->GetAscGraph()), asc_backend, attr->GetReshapeAxisChanges()), | ||
| 16095 | + SUCCESS); | ||
| 16096 | + | ||
| 16097 | + const auto completed_graph_attr = | ||
| 16098 | + AscGraphUtils::GetComputeGraph(*(attr->GetAscGraph()))->GetAttrsGroup<AscGraphAttr>(); | ||
| 16099 | + ASSERT_NE(completed_graph_attr, nullptr); | ||
| 16100 | + std::vector<int64_t> completed_graph_axis; | ||
| 16101 | + for (const auto &axis : completed_graph_attr->axis) { | ||
| 16102 | + ASSERT_NE(axis, nullptr); | ||
| 16103 | + completed_graph_axis.push_back(axis->id); | ||
| 16104 | + } | ||
| 16105 | + ASSERT_EQ(completed_graph_attr->axis.size(), 3U); | ||
| 16106 | + EXPECT_EQ(completed_graph_axis, std::vector<int64_t>({0, 1, 2})); | ||
| 16107 | + EXPECT_TRUE(BackendUtils::IsEqOne(completed_graph_attr->axis[0]->size)); | ||
| 16108 | + EXPECT_EQ(std::string(completed_graph_attr->axis[1]->size.Str().get()), "22"); | ||
| 16109 | + EXPECT_EQ(std::string(completed_graph_attr->axis[2]->size.Str().get()), "15120"); | ||
| 16110 | + | ||
| 16111 | + auto load_node = attr->GetAscGraph()->FindNode("single_load"); | ||
| 16112 | + ASSERT_NE(load_node, nullptr); | ||
| 16113 | + AscTensorAttr *load_attr = nullptr; | ||
| 16114 | + ASSERT_EQ(asc_adapt::GetOutputTensorAttr(load_node, load_attr), SUCCESS); | ||
| 16115 | + ASSERT_NE(load_attr, nullptr); | ||
| 16116 | + EXPECT_EQ(load_attr->axis, completed_graph_axis); | ||
| 16117 | + ASSERT_EQ(load_attr->repeats.size(), 3U); | ||
| 16118 | + EXPECT_TRUE(BackendUtils::IsEqOne(load_attr->repeats[0])); | ||
| 16119 | + EXPECT_EQ(std::string(load_attr->repeats[1].Str().get()), "22"); | ||
| 16120 | + EXPECT_EQ(std::string(load_attr->repeats[2].Str().get()), "15120"); | ||
| 16121 | + | ||
| 16122 | + auto store_node = attr->GetAscGraph()->FindNode("single_store"); | ||
| 16123 | + ASSERT_NE(store_node, nullptr); | ||
| 16124 | + AscTensorAttr *store_attr = nullptr; | ||
| 16125 | + ASSERT_EQ(asc_adapt::GetOutputTensorAttr(store_node, store_attr), SUCCESS); | ||
| 16126 | + ASSERT_NE(store_attr, nullptr); | ||
| 16127 | + EXPECT_EQ(store_attr->axis, completed_graph_axis); | ||
| 16128 | + ASSERT_EQ(store_attr->repeats.size(), 3U); | ||
| 16129 | + EXPECT_TRUE(BackendUtils::IsEqOne(store_attr->repeats[0])); | ||
| 16130 | + EXPECT_EQ(std::string(store_attr->repeats[1].Str().get()), "22"); | ||
| 16131 | + EXPECT_EQ(std::string(store_attr->repeats[2].Str().get()), "15120"); | ||
| 16132 | +} | ||
| 16133 | + | ||
| 16134 | +TEST_F(AscBackendPostProcessorTest, CompleteAttrs_RestoreReshapeAxisByBestOverlap) { | ||
| 16135 | + GraphBuilder builder("best_overlap_reshape_outer"); | ||
| 16136 | + auto asc_backend = | ||
| 16137 | + builder.AddNode("best_overlap_reshape_backend", kAscBackendType, 1, 1, FORMAT_ND, DT_FLOAT16, {4, 15120}); | ||
| 16138 | + ASSERT_NE(asc_backend, nullptr); | ||
| 16139 | + const auto attr = GetOrCreateAutoFuseAttrs(asc_backend->GetOpDesc()); | ||
| 16140 | + ASSERT_NE(attr, nullptr); | ||
| 16141 | + | ||
| 16142 | + ge::AscGraph graph("best_overlap_reshape_graph"); | ||
| 16143 | + const auto one = Symbol(1); | ||
| 16144 | + const auto size0 = Symbol(4); | ||
| 16145 | + const auto size1 = Symbol(15120); | ||
| 16146 | + auto z0 = graph.CreateAxis("z0", size0); | ||
| 16147 | + auto z1 = graph.CreateAxis("z1", size1); | ||
| 16148 | + const std::vector<int64_t> graph_axis = {z0.id, z1.id}; | ||
| 16149 | + | ||
| 16150 | + af::ascir_op::Data data("best_overlap_data", graph); | ||
| 16151 | + data.attr.sched.axis = graph_axis; | ||
| 16152 | + data.y.dtype = DT_FLOAT16; | ||
| 16153 | + *data.y.axis = graph_axis; | ||
| 16154 | + *data.y.repeats = {size0, size1}; | ||
| 16155 | + *data.y.strides = {size1, one}; | ||
| 16156 | + | ||
| 16157 | + af::ascir_op::Load load("best_overlap_load"); | ||
| 16158 | + load.x = data.y; | ||
| 16159 | + load.attr.sched.axis = graph_axis; | ||
| 16160 | + load.y.dtype = DT_FLOAT16; | ||
| 16161 | + *load.y.axis = graph_axis; | ||
| 16162 | + *load.y.repeats = {size0, size1}; | ||
| 16163 | + *load.y.strides = {size1, one}; | ||
| 16164 | + | ||
| 16165 | + af::ascir_op::Store store("best_overlap_store"); | ||
| 16166 | + store.x = load.y; | ||
| 16167 | + store.attr.sched.axis = graph_axis; | ||
| 16168 | + store.y.dtype = DT_FLOAT16; | ||
| 16169 | + *store.y.axis = graph_axis; | ||
| 16170 | + *store.y.repeats = {size0, size1}; | ||
| 16171 | + *store.y.strides = {size1, one}; | ||
| 16172 | + attr->SetAscGraph(std::shared_ptr<ge::AscGraph>(new ge::AscGraph(graph)), loop::FuseType::kPointwise); | ||
| 16173 | + | ||
| 16174 | + af::ReshapeAxisChangeInfo change; | ||
| 16175 | + change.before_axis = {0, 1, 2}; | ||
| 16176 | + change.before_repeats = {one, one, one}; | ||
| 16177 | + change.after_axis = {0, 1}; | ||
| 16178 | + change.after_repeats = {one, one}; | ||
| 16179 | + attr->AddReshapeAxisChange(change); | ||
| 16180 | + | ||
| 16181 | + ASSERT_EQ( | ||
| 16182 | + asc_adapt::PadLeadingUnitAxisAndCompleteAttrs(*(attr->GetAscGraph()), asc_backend, attr->GetReshapeAxisChanges()), | ||
| 16183 | + SUCCESS); | ||
| 16184 | + | ||
| 16185 | + const auto completed_graph_attr = | ||
| 16186 | + AscGraphUtils::GetComputeGraph(*(attr->GetAscGraph()))->GetAttrsGroup<AscGraphAttr>(); | ||
| 16187 | + ASSERT_NE(completed_graph_attr, nullptr); | ||
| 16188 | + ASSERT_EQ(completed_graph_attr->axis.size(), 3U); | ||
| 16189 | + EXPECT_EQ(completed_graph_attr->axis[0]->id, 0); | ||
| 16190 | + EXPECT_EQ(completed_graph_attr->axis[1]->id, 1); | ||
| 16191 | + EXPECT_EQ(completed_graph_attr->axis[2]->id, 2); | ||
| 16192 | + EXPECT_TRUE(BackendUtils::IsEqOne(completed_graph_attr->axis[0]->size)); | ||
| 16193 | + EXPECT_EQ(std::string(completed_graph_attr->axis[1]->size.Str().get()), "4"); | ||
| 16194 | + EXPECT_EQ(std::string(completed_graph_attr->axis[2]->size.Str().get()), "15120"); | ||
| 16195 | + | ||
| 16196 | + auto store_node = attr->GetAscGraph()->FindNode("best_overlap_store"); | ||
| 16197 | + ASSERT_NE(store_node, nullptr); | ||
| 16198 | + AscTensorAttr *store_attr = nullptr; | ||
| 16199 | + ASSERT_EQ(asc_adapt::GetOutputTensorAttr(store_node, store_attr), SUCCESS); | ||
| 16200 | + ASSERT_NE(store_attr, nullptr); | ||
| 16201 | + EXPECT_EQ(store_attr->axis, std::vector<int64_t>({0, 1, 2})); | ||
| 16202 | + ASSERT_EQ(store_attr->repeats.size(), 3U); | ||
| 16203 | + EXPECT_TRUE(BackendUtils::IsEqOne(store_attr->repeats[0])); | ||
| 16204 | + EXPECT_EQ(std::string(store_attr->repeats[1].Str().get()), "4"); | ||
| 16205 | + EXPECT_EQ(std::string(store_attr->repeats[2].Str().get()), "15120"); | ||
| 16206 | + ASSERT_EQ(store_attr->strides.size(), 3U); | ||
| 16207 | + EXPECT_TRUE(BackendUtils::IsEqZero(store_attr->strides[0])); | ||
| 16208 | + EXPECT_EQ(std::string(store_attr->strides[1].Str().get()), "15120"); | ||
| 16209 | + EXPECT_TRUE(BackendUtils::IsEqOne(store_attr->strides[2])); | ||
| 16210 | +} | ||
| 16211 | + | ||
| 16212 | +TEST_F(AscBackendPostProcessorTest, CompleteAttrs_RestoreMultipleReshapeAxisChangesIdempotently) { | ||
| 16213 | + GraphBuilder builder("multi_reshape_outer"); | ||
| 16214 | + auto asc_backend = | ||
| 16215 | + builder.AddNode("multi_reshape_backend", kAscBackendType, 1, 1, FORMAT_ND, DT_FLOAT16, {22, 15120, 1}); | ||
| 16216 | + ASSERT_NE(asc_backend, nullptr); | ||
| 16217 | + const auto attr = GetOrCreateAutoFuseAttrs(asc_backend->GetOpDesc()); | ||
| 16218 | + ASSERT_NE(attr, nullptr); | ||
| 16219 | + | ||
| 16220 | + ge::AscGraph graph("multi_reshape_axis_graph"); | ||
| 16221 | + auto z0 = graph.CreateAxis("z0", Symbol(22)); | ||
| 16222 | + auto z1 = graph.CreateAxis("z1", Symbol(15120)); | ||
| 16223 | + auto z2 = graph.CreateAxis("z2", Symbol(1)); | ||
| 16224 | + af::ascir_op::Data data("data", graph); | ||
| 16225 | + data.attr.sched.axis = {z0.id, z1.id, z2.id}; | ||
| 16226 | + data.y.dtype = DT_FLOAT16; | ||
| 16227 | + *data.y.axis = {z0.id, z1.id, z2.id}; | ||
| 16228 | + *data.y.repeats = {Symbol(22), Symbol(15120), Symbol(1)}; | ||
| 16229 | + *data.y.strides = {Symbol(15120), Symbol(1), Symbol(0)}; | ||
| 16230 | + | ||
| 16231 | + af::ascir_op::Load load("load"); | ||
| 16232 | + load.x = data.y; | ||
| 16233 | + load.attr.sched.axis = {z0.id, z1.id, z2.id}; | ||
| 16234 | + load.y.dtype = DT_FLOAT16; | ||
| 16235 | + *load.y.axis = {z0.id, z1.id, z2.id}; | ||
| 16236 | + *load.y.repeats = {Symbol(22), Symbol(15120), Symbol(1)}; | ||
| 16237 | + *load.y.strides = {Symbol(15120), Symbol(1), Symbol(0)}; | ||
| 16238 | + | ||
| 16239 | + af::ascir_op::Store store("store"); | ||
| 16240 | + store.x = load.y; | ||
| 16241 | + store.attr.sched.axis = {z0.id, z1.id, z2.id}; | ||
| 16242 | + store.y.dtype = DT_FLOAT16; | ||
| 16243 | + *store.y.axis = {z0.id, z1.id, z2.id}; | ||
| 16244 | + *store.y.repeats = {Symbol(22), Symbol(15120), Symbol(1)}; | ||
| 16245 | + *store.y.strides = {Symbol(15120), Symbol(1), Symbol(0)}; | ||
| 16246 | + attr->SetAscGraph(std::shared_ptr<ge::AscGraph>(new ge::AscGraph(graph)), loop::FuseType::kPointwise); | ||
| 16247 | + | ||
| 16248 | + af::ReshapeAxisChangeInfo squeeze_change; | ||
| 16249 | + squeeze_change.before_axis = {0, 1, 2}; | ||
| 16250 | + squeeze_change.before_repeats = {Symbol(1), Symbol(22), Symbol(15120)}; | ||
| 16251 | + squeeze_change.after_axis = {0, 1}; | ||
| 16252 | + squeeze_change.after_repeats = {Symbol(22), Symbol(15120)}; | ||
| 16253 | + attr->AddReshapeAxisChange(squeeze_change); | ||
| 16254 | + | ||
| 16255 | + af::ReshapeAxisChangeInfo unsqueeze_change; | ||
| 16256 | + unsqueeze_change.before_axis = {0, 1}; | ||
| 16257 | + unsqueeze_change.before_repeats = {Symbol(22), Symbol(15120)}; | ||
| 16258 | + unsqueeze_change.after_axis = {0, 1, 2}; | ||
| 16259 | + unsqueeze_change.after_repeats = {Symbol(22), Symbol(15120), Symbol(1)}; | ||
| 16260 | + attr->AddReshapeAxisChange(unsqueeze_change); | ||
| 16261 | + | ||
| 16262 | + ASSERT_EQ( | ||
| 16263 | + asc_adapt::PadLeadingUnitAxisAndCompleteAttrs(*(attr->GetAscGraph()), asc_backend, attr->GetReshapeAxisChanges()), | ||
| 16264 | + SUCCESS); | ||
| 16265 | + auto graph_attr = AscGraphUtils::GetComputeGraph(*(attr->GetAscGraph()))->GetAttrsGroup<AscGraphAttr>(); | ||
| 16266 | + ASSERT_NE(graph_attr, nullptr); | ||
| 16267 | + ASSERT_EQ(graph_attr->axis.size(), 4U); | ||
| 16268 | + | ||
| 16269 | + ASSERT_EQ( | ||
| 16270 | + asc_adapt::PadLeadingUnitAxisAndCompleteAttrs(*(attr->GetAscGraph()), asc_backend, attr->GetReshapeAxisChanges()), | ||
| 16271 | + SUCCESS); | ||
| 16272 | + graph_attr = AscGraphUtils::GetComputeGraph(*(attr->GetAscGraph()))->GetAttrsGroup<AscGraphAttr>(); | ||
| 16273 | + ASSERT_NE(graph_attr, nullptr); | ||
| 16274 | + EXPECT_EQ(graph_attr->axis.size(), 4U); | ||
| 16275 | + | ||
| 16276 | + std::vector<int64_t> graph_axis_after_second_pad; | ||
| 16277 | + for (const auto &axis : graph_attr->axis) { | ||
| 16278 | + ASSERT_NE(axis, nullptr); | ||
| 16279 | + graph_axis_after_second_pad.push_back(axis->id); | ||
| 16280 | + } | ||
| 16281 | + auto store_node = attr->GetAscGraph()->FindNode("store"); | ||
| 16282 | + ASSERT_NE(store_node, nullptr); | ||
| 16283 | + AscTensorAttr *store_attr = nullptr; | ||
| 16284 | + ASSERT_EQ(asc_adapt::GetOutputTensorAttr(store_node, store_attr), SUCCESS); | ||
| 16285 | + ASSERT_NE(store_attr, nullptr); | ||
| 16286 | + EXPECT_EQ(store_attr->axis, graph_axis_after_second_pad); | ||
| 16287 | + EXPECT_EQ(store_attr->axis.size(), 4U); | ||
| 16288 | + EXPECT_EQ(store_attr->repeats.size(), 4U); | ||
| 16289 | + EXPECT_EQ(store_attr->strides.size(), 4U); | ||
| 16290 | +} | ||
| 16291 | + | ||
| 16292 | +TEST_F(AscBackendPostProcessorTest, CompleteAttrs_RestoreMixedReshapeDoesNotDuplicateTensorAxis) { | ||
| 16293 | + GraphBuilder builder("mixed_reshape_outer"); | ||
| 16294 | + auto asc_backend = | ||
| 16295 | + builder.AddNode("mixed_reshape_backend", kAscBackendType, 2, 1, FORMAT_ND, DT_FLOAT16, {22, 15120, 1}); | ||
| 16296 | + ASSERT_NE(asc_backend, nullptr); | ||
| 16297 | + const auto attr = GetOrCreateAutoFuseAttrs(asc_backend->GetOpDesc()); | ||
| 16298 | + ASSERT_NE(attr, nullptr); | ||
| 16299 | + | ||
| 16300 | + ge::AscGraph graph("mixed_reshape_axis_graph"); | ||
| 16301 | + const auto one = Symbol(1); | ||
| 16302 | + const auto size0 = Symbol(22); | ||
| 16303 | + const auto size1 = Symbol(15120); | ||
| 16304 | + auto z0 = graph.CreateAxis("z0", size0); | ||
| 16305 | + auto z1 = graph.CreateAxis("z1", size1); | ||
| 16306 | + auto z2 = graph.CreateAxis("z2", one); | ||
| 16307 | + const std::vector<int64_t> graph_axis = {z0.id, z1.id, z2.id}; | ||
| 16308 | + | ||
| 16309 | + af::ascir_op::Data data0("mixed_data0", graph); | ||
| 16310 | + data0.attr.sched.axis = graph_axis; | ||
| 16311 | + data0.y.dtype = DT_FLOAT16; | ||
| 16312 | + *data0.y.axis = graph_axis; | ||
| 16313 | + *data0.y.repeats = {size0, size1, one}; | ||
| 16314 | + *data0.y.strides = {size1, one, Symbol(0)}; | ||
| 16315 | + | ||
| 16316 | + af::ascir_op::Load load0("mixed_load0"); | ||
| 16317 | + load0.x = data0.y; | ||
| 16318 | + load0.attr.sched.axis = graph_axis; | ||
| 16319 | + load0.y.dtype = DT_FLOAT16; | ||
| 16320 | + *load0.y.axis = graph_axis; | ||
| 16321 | + *load0.y.repeats = {size0, size1, one}; | ||
| 16322 | + *load0.y.strides = {size1, one, Symbol(0)}; | ||
| 16323 | + | ||
| 16324 | + af::ascir_op::Data data1("mixed_data1", graph); | ||
| 16325 | + data1.attr.sched.axis = graph_axis; | ||
| 16326 | + data1.y.dtype = DT_FLOAT16; | ||
| 16327 | + *data1.y.axis = graph_axis; | ||
| 16328 | + *data1.y.repeats = {one, size1, one}; | ||
| 16329 | + *data1.y.strides = {Symbol(0), one, Symbol(0)}; | ||
| 16330 | + | ||
| 16331 | + af::ascir_op::Load load1("mixed_load1"); | ||
| 16332 | + load1.x = data1.y; | ||
| 16333 | + load1.attr.sched.axis = graph_axis; | ||
| 16334 | + load1.y.dtype = DT_FLOAT16; | ||
| 16335 | + *load1.y.axis = graph_axis; | ||
| 16336 | + *load1.y.repeats = {one, size1, one}; | ||
| 16337 | + *load1.y.strides = {Symbol(0), one, Symbol(0)}; | ||
| 16338 | + | ||
| 16339 | + af::ascir_op::Add add("mixed_add"); | ||
| 16340 | + add.x1 = load1.y; | ||
| 16341 | + add.x2 = load0.y; | ||
| 16342 | + add.attr.sched.axis = graph_axis; | ||
| 16343 | + add.y.dtype = DT_FLOAT16; | ||
| 16344 | + *add.y.axis = {}; | ||
| 16345 | + *add.y.repeats = {}; | ||
| 16346 | + *add.y.strides = {}; | ||
| 16347 | + | ||
| 16348 | + af::ascir_op::Store store("mixed_store"); | ||
| 16349 | + store.x = add.y; | ||
| 16350 | + store.attr.sched.axis = graph_axis; | ||
| 16351 | + store.y.dtype = DT_FLOAT16; | ||
| 16352 | + *store.y.axis = graph_axis; | ||
| 16353 | + *store.y.repeats = {size0, size1, one}; | ||
| 16354 | + *store.y.strides = {size1, one, Symbol(0)}; | ||
| 16355 | + | ||
| 16356 | + af::ascir_op::Output output("mixed_output"); | ||
| 16357 | + output.x = store.y; | ||
| 16358 | + output.attr.sched.axis = graph_axis; | ||
| 16359 | + *output.y.axis = {}; | ||
| 16360 | + *output.y.repeats = {}; | ||
| 16361 | + *output.y.strides = {}; | ||
| 16362 | + auto output_node = graph.FindNode("mixed_output"); | ||
| 16363 | + ASSERT_NE(output_node, nullptr); | ||
| 16364 | + auto compute_graph = output_node->GetOwnerComputeGraph(); | ||
| 16365 | + std::vector<std::pair<NodePtr, int32_t>> output_nodes{{output_node, 0}}; | ||
| 16366 | + compute_graph->SetOutputSize(1U); | ||
| 16367 | + compute_graph->SetGraphOutNodesInfo(output_nodes); | ||
| 16368 | + attr->SetAscGraph(std::shared_ptr<ge::AscGraph>(new ge::AscGraph(graph)), loop::FuseType::kPointwise); | ||
| 16369 | + | ||
| 16370 | + af::ReshapeAxisChangeInfo squeeze_change; | ||
| 16371 | + squeeze_change.before_axis = {0, 1, 2}; | ||
| 16372 | + squeeze_change.before_repeats = {one, size0, size1}; | ||
| 16373 | + squeeze_change.after_axis = {0, 1}; | ||
| 16374 | + squeeze_change.after_repeats = {size0, size1}; | ||
| 16375 | + attr->AddReshapeAxisChange(squeeze_change); | ||
| 16376 | + | ||
| 16377 | + af::ReshapeAxisChangeInfo unsqueeze_change; | ||
| 16378 | + unsqueeze_change.before_axis = {0, 1}; | ||
| 16379 | + unsqueeze_change.before_repeats = {size0, size1}; | ||
| 16380 | + unsqueeze_change.after_axis = {0, 1, 2}; | ||
| 16381 | + unsqueeze_change.after_repeats = {size0, size1, one}; | ||
| 16382 | + attr->AddReshapeAxisChange(unsqueeze_change); | ||
| 16383 | + | ||
| 16384 | + ASSERT_EQ( | ||
| 16385 | + asc_adapt::PadLeadingUnitAxisAndCompleteAttrs(*(attr->GetAscGraph()), asc_backend, attr->GetReshapeAxisChanges()), | ||
| 16386 | + SUCCESS); | ||
| 16387 | + ASSERT_EQ(asc_adapt::CompleteNodeAttrsOnAscGraph(*(attr->GetAscGraph()), asc_backend), SUCCESS); | ||
| 16388 | + | ||
| 16389 | + const auto completed_graph_attr = | ||
| 16390 | + AscGraphUtils::GetComputeGraph(*(attr->GetAscGraph()))->GetAttrsGroup<AscGraphAttr>(); | ||
| 16391 | + ASSERT_NE(completed_graph_attr, nullptr); | ||
| 16392 | + std::vector<int64_t> completed_graph_axis; | ||
| 16393 | + for (const auto &axis : completed_graph_attr->axis) { | ||
| 16394 | + ASSERT_NE(axis, nullptr); | ||
| 16395 | + completed_graph_axis.push_back(axis->id); | ||
| 16396 | + } | ||
| 16397 | + ASSERT_EQ(completed_graph_attr->axis.size(), 4U); | ||
| 16398 | + EXPECT_TRUE(BackendUtils::IsEqOne(completed_graph_attr->axis[0]->size)); | ||
| 16399 | + EXPECT_EQ(std::string(completed_graph_attr->axis[1]->size.Str().get()), "22"); | ||
| 16400 | + EXPECT_EQ(std::string(completed_graph_attr->axis[2]->size.Str().get()), "15120"); | ||
| 16401 | + EXPECT_TRUE(BackendUtils::IsEqOne(completed_graph_attr->axis[3]->size)); | ||
| 16402 | + | ||
| 16403 | + auto load_node = attr->GetAscGraph()->FindNode("mixed_load0"); | ||
| 16404 | + ASSERT_NE(load_node, nullptr); | ||
| 16405 | + AscTensorAttr *load_attr = nullptr; | ||
| 16406 | + ASSERT_EQ(asc_adapt::GetOutputTensorAttr(load_node, load_attr), SUCCESS); | ||
| 16407 | + ASSERT_NE(load_attr, nullptr); | ||
| 16408 | + EXPECT_EQ(load_attr->axis, completed_graph_axis); | ||
| 16409 | + EXPECT_EQ(load_attr->axis.size(), load_attr->repeats.size()); | ||
| 16410 | + EXPECT_EQ(load_attr->axis.size(), load_attr->strides.size()); | ||
| 16411 | + ASSERT_EQ(load_attr->repeats.size(), 4U); | ||
| 16412 | + EXPECT_TRUE(BackendUtils::IsEqOne(load_attr->repeats[0])); | ||
| 16413 | + EXPECT_EQ(std::string(load_attr->repeats[1].Str().get()), "22"); | ||
| 16414 | + EXPECT_EQ(std::string(load_attr->repeats[2].Str().get()), "15120"); | ||
| 16415 | + EXPECT_TRUE(BackendUtils::IsEqOne(load_attr->repeats[3])); | ||
| 16416 | + | ||
| 16417 | + auto add_node = attr->GetAscGraph()->FindNode("mixed_add"); | ||
| 16418 | + ASSERT_NE(add_node, nullptr); | ||
| 16419 | + AscTensorAttr *add_attr = nullptr; | ||
| 16420 | + ASSERT_EQ(asc_adapt::GetOutputTensorAttr(add_node, add_attr), SUCCESS); | ||
| 16421 | + ASSERT_NE(add_attr, nullptr); | ||
| 16422 | + EXPECT_EQ(add_attr->axis, completed_graph_axis); | ||
| 16423 | + EXPECT_EQ(add_attr->axis.size(), add_attr->repeats.size()); | ||
| 16424 | + EXPECT_EQ(add_attr->axis.size(), add_attr->strides.size()); | ||
| 16425 | + ASSERT_EQ(add_attr->repeats.size(), 4U); | ||
| 16426 | + EXPECT_TRUE(BackendUtils::IsEqOne(add_attr->repeats[0])); | ||
| 16427 | + EXPECT_EQ(std::string(add_attr->repeats[1].Str().get()), "22"); | ||
| 16428 | + EXPECT_EQ(std::string(add_attr->repeats[2].Str().get()), "15120"); | ||
| 16429 | + EXPECT_TRUE(BackendUtils::IsEqOne(add_attr->repeats[3])); | ||
| 16430 | +} | ||
| 16431 | + | ||
| 16432 | +TEST_F(AscBackendPostProcessorTest, FlushSubGraphAxisInfo_MapsReshapePaddingAxisId) { | ||
| 16433 | + GraphBuilder builder("reshape_padding_flush_outer"); | ||
| 16434 | + auto asc_backend = builder.AddNode("reshape_backend", kAscBackendType, 1, 1, FORMAT_ND, DT_FLOAT16, {22, 15120}); | ||
| 16435 | + ASSERT_NE(asc_backend, nullptr); | ||
| 16436 | + const auto attr = GetOrCreateAutoFuseAttrs(asc_backend->GetOpDesc()); | ||
| 16437 | + ASSERT_NE(attr, nullptr); | ||
| 16438 | + | ||
| 16439 | + ge::AscGraph graph("reshape_padding_flush_graph"); | ||
| 16440 | + const auto one = Symbol(1); | ||
| 16441 | + const auto size0 = Symbol(22); | ||
| 16442 | + const auto size1 = Symbol(15120); | ||
| 16443 | + auto z0 = graph.CreateAxis("z0", size0); | ||
| 16444 | + auto z1 = graph.CreateAxis("z1", size1); | ||
| 16445 | + const int64_t reshape_padding_id = 3; | ||
| 16446 | + auto reshape_padding = ComGraphMakeShared<Axis>(); | ||
| 16447 | + ASSERT_NE(reshape_padding, nullptr); | ||
| 16448 | + reshape_padding->id = reshape_padding_id; | ||
| 16449 | + reshape_padding->name = "reshape_axis_padding_3"; | ||
| 16450 | + reshape_padding->type = Axis::kAxisTypeOriginal; | ||
| 16451 | + reshape_padding->size = one; | ||
| 16452 | + auto graph_attr = AscGraphUtils::GetComputeGraph(graph)->GetAttrsGroup<AscGraphAttr>(); | ||
| 16453 | + ASSERT_NE(graph_attr, nullptr); | ||
| 16454 | + graph_attr->axis = {reshape_padding, graph_attr->axis[0], graph_attr->axis[1]}; | ||
| 16455 | + const std::vector<int64_t> reshape_axis = {reshape_padding->id, z0.id, z1.id}; | ||
| 16456 | + | ||
| 16457 | + af::ascir_op::Data data("data", graph); | ||
| 16458 | + data.attr.sched.axis = reshape_axis; | ||
| 16459 | + data.attr.sched.loop_axis = reshape_padding->id; | ||
| 16460 | + data.y.dtype = DT_FLOAT16; | ||
| 16461 | + *data.y.axis = reshape_axis; | ||
| 16462 | + *data.y.repeats = {one, size0, size1}; | ||
| 16463 | + *data.y.strides = {Symbol(0), size1, one}; | ||
| 16464 | + *data.y.vectorized_axis = reshape_axis; | ||
| 16465 | + | ||
| 16466 | + af::ascir_op::Load load("load"); | ||
| 16467 | + load.x = data.y; | ||
| 16468 | + load.attr.sched.axis = reshape_axis; | ||
| 16469 | + load.attr.sched.loop_axis = reshape_padding->id; | ||
| 16470 | + load.y.dtype = DT_FLOAT16; | ||
| 16471 | + *load.y.axis = reshape_axis; | ||
| 16472 | + *load.y.repeats = {one, size0, size1}; | ||
| 16473 | + *load.y.strides = {Symbol(0), size1, one}; | ||
| 16474 | + *load.y.vectorized_axis = reshape_axis; | ||
| 16475 | + | ||
| 16476 | + af::ascir_op::Store store("store"); | ||
| 16477 | + store.x = load.y; | ||
| 16478 | + store.attr.sched.axis = reshape_axis; | ||
| 16479 | + store.attr.sched.loop_axis = reshape_padding->id; | ||
| 16480 | + store.y.dtype = DT_FLOAT16; | ||
| 16481 | + *store.y.axis = reshape_axis; | ||
| 16482 | + *store.y.repeats = {one, size0, size1}; | ||
| 16483 | + *store.y.strides = {Symbol(0), size1, one}; | ||
| 16484 | + *store.y.vectorized_axis = reshape_axis; | ||
| 16485 | + | ||
| 16486 | + af::ascir_op::Output output("output"); | ||
| 16487 | + output.x = store.y; | ||
| 16488 | + output.attr.sched.axis = reshape_axis; | ||
| 16489 | + output.attr.sched.loop_axis = reshape_padding->id; | ||
| 16490 | + output.y.dtype = DT_FLOAT16; | ||
| 16491 | + auto output_node = graph.FindNode("output"); | ||
| 16492 | + ASSERT_NE(output_node, nullptr); | ||
| 16493 | + auto compute_graph = output_node->GetOwnerComputeGraph(); | ||
| 16494 | + std::vector<std::pair<NodePtr, int32_t>> output_nodes{{output_node, 0}}; | ||
| 16495 | + compute_graph->SetOutputSize(1U); | ||
| 16496 | + compute_graph->SetGraphOutNodesInfo(output_nodes); | ||
| 16497 | + attr->SetAscGraph(std::shared_ptr<ge::AscGraph>(new ge::AscGraph(graph)), loop::FuseType::kReshape); | ||
| 16498 | + | ||
| 16499 | + AxisPairSet node_map; | ||
| 16500 | + node_map.insert({reshape_padding->id, 2}); | ||
| 16501 | + node_map.insert({z0.id, z0.id}); | ||
| 16502 | + node_map.insert({z1.id, z1.id}); | ||
| 16503 | + AscGraphAxisMapping graph_axis_map; | ||
| 16504 | + ASSERT_EQ(graph_axis_map.FlushSubGraphAxisInfo(asc_backend, node_map, true), SUCCESS); | ||
| 16505 | + | ||
| 16506 | + graph_attr = AscGraphUtils::GetComputeGraph(*(attr->GetAscGraph()))->GetAttrsGroup<AscGraphAttr>(); | ||
| 16507 | + ASSERT_NE(graph_attr, nullptr); | ||
| 16508 | + ASSERT_EQ(graph_attr->axis.size(), 3U); | ||
| 16509 | + EXPECT_EQ(graph_attr->axis[0]->id, 2); | ||
| 16510 | + EXPECT_EQ(graph_attr->axis[0]->name, "reshape_axis_padding_3"); | ||
| 16511 | + | ||
| 16512 | + auto load_node = attr->GetAscGraph()->FindNode("load"); | ||
| 16513 | + ASSERT_NE(load_node, nullptr); | ||
| 16514 | + const auto load_node_attr = load_node->GetOpDesc()->GetAttrsGroup<AscNodeAttr>(); | ||
| 16515 | + ASSERT_NE(load_node_attr, nullptr); | ||
| 16516 | + EXPECT_EQ(load_node_attr->sched.axis, std::vector<int64_t>({2, 0, 1})); | ||
| 16517 | + EXPECT_EQ(load_node_attr->sched.loop_axis, 2); | ||
| 16518 | + AscTensorAttr *load_attr = nullptr; | ||
| 16519 | + ASSERT_EQ(asc_adapt::GetOutputTensorAttr(load_node, load_attr), SUCCESS); | ||
| 16520 | + ASSERT_NE(load_attr, nullptr); | ||
| 16521 | + EXPECT_EQ(load_attr->axis, std::vector<int64_t>({2, 0, 1})); | ||
| 16522 | + EXPECT_EQ(load_attr->vectorized_axis, std::vector<int64_t>({2, 0, 1})); | ||
| 16523 | +} | ||
| 16524 | + | ||
| 16525 | +TEST_F(AscBackendPostProcessorTest, FlushReshapeAxisChanges_RemapMissingUnitAxisByPosition) { | ||
| 16526 | + GraphBuilder builder("reshape_flush_outer"); | ||
| 16527 | + auto asc_backend = builder.AddNode("reshape_backend", kAscBackendType, 1, 1, FORMAT_ND, DT_FLOAT16, {22, 15120}); | ||
| 16528 | + ASSERT_NE(asc_backend, nullptr); | ||
| 16529 | + const auto attr = GetOrCreateAutoFuseAttrs(asc_backend->GetOpDesc()); | ||
| 16530 | + ASSERT_NE(attr, nullptr); | ||
| 16531 | + | ||
| 16532 | + af::ReshapeAxisChangeInfo change; | ||
| 16533 | + change.before_axis = {2, 0, 1}; | ||
| 16534 | + change.before_repeats = {Symbol(1), Symbol(22), Symbol(15120)}; | ||
| 16535 | + change.after_axis = {0, 1}; | ||
| 16536 | + change.after_repeats = {Symbol(22), Symbol(15120)}; | ||
| 16537 | + attr->AddReshapeAxisChange(change); | ||
| 16538 | + | ||
| 16539 | + ASSERT_EQ(BackendUtils::FlushReshapeAxisChanges(asc_backend, asc_backend, {3, 0, 1}, {4, 0, 1}), SUCCESS); | ||
| 16540 | + | ||
| 16541 | + const auto &changes = attr->GetReshapeAxisChanges(); | ||
| 16542 | + ASSERT_EQ(changes.size(), 1U); | ||
| 16543 | + EXPECT_EQ(changes[0].before_axis, std::vector<int64_t>({4, 0, 1})); | ||
| 16544 | + EXPECT_EQ(changes[0].after_axis, std::vector<int64_t>({0, 1})); | ||
| 16545 | +} | ||
| 16546 | + | ||
| 16547 | +TEST_F(AscBackendPostProcessorTest, CompleteAttrs_KeepsLeadingReshapePaddingAfterConcatPadding) { | ||
| 16548 | + GraphBuilder builder("reshape_padding_outer"); | ||
| 16549 | + auto asc_backend = builder.AddNode("reshape_backend", kAscBackendType, 1, 1, FORMAT_ND, DT_FLOAT16, {22, 15120}); | ||
| 16550 | + ASSERT_NE(asc_backend, nullptr); | ||
| 16551 | + const auto attr = GetOrCreateAutoFuseAttrs(asc_backend->GetOpDesc()); | ||
| 16552 | + ASSERT_NE(attr, nullptr); | ||
| 16553 | + | ||
| 16554 | + ge::AscGraph graph("reshape_padding_graph"); | ||
| 16555 | + attr->SetAscGraph(CreateRestoredLeadingReshapeAxisGraph(graph), loop::FuseType::kReshape); | ||
| 16556 | + af::ReshapeAxisChangeInfo change; | ||
| 16557 | + change.before_axis = {2, 0, 1}; | ||
| 16558 | + change.before_repeats = {Symbol(1), Symbol(22), Symbol(15120)}; | ||
| 16559 | + change.after_axis = {0, 1}; | ||
| 16560 | + change.after_repeats = {Symbol(22), Symbol(15120)}; | ||
| 16561 | + attr->AddReshapeAxisChange(change); | ||
| 16562 | + | ||
| 16563 | + ASSERT_EQ( | ||
| 16564 | + asc_adapt::PadLeadingUnitAxisAndCompleteAttrs(*(attr->GetAscGraph()), asc_backend, attr->GetReshapeAxisChanges()), | ||
| 16565 | + SUCCESS); | ||
| 16566 | + ASSERT_EQ(asc_adapt::CompleteNodeAttrsOnAscGraph(*(attr->GetAscGraph()), asc_backend), SUCCESS); | ||
| 16567 | + | ||
| 16568 | + const auto graph_attr = AscGraphUtils::GetComputeGraph(*(attr->GetAscGraph()))->GetAttrsGroup<AscGraphAttr>(); | ||
| 16569 | + ASSERT_NE(graph_attr, nullptr); | ||
| 16570 | + ASSERT_EQ(graph_attr->axis.size(), 3U); | ||
| 16571 | + EXPECT_TRUE(BackendUtils::IsEqOne(graph_attr->axis[0]->size)); | ||
| 16572 | + EXPECT_EQ(std::string(graph_attr->axis[1]->size.Str().get()), "22"); | ||
| 16573 | + EXPECT_EQ(std::string(graph_attr->axis[2]->size.Str().get()), "15120"); | ||
| 16574 | +} | ||
| 16575 | + | ||
| 15865 | TEST_F(AscBackendPostProcessorTest, CompleteAttrWithGraphInvalidAxisNodeValidAxis) { | 16576 | TEST_F(AscBackendPostProcessorTest, CompleteAttrWithGraphInvalidAxisNodeValidAxis) { |
| 15866 | ComputeGraphPtr compute_graph = BuildGraph1("AscBackend"); | 16577 | ComputeGraphPtr compute_graph = BuildGraph1("AscBackend"); |
| 15867 | EXPECT_EQ(compute_graph->GetAllNodesSize(), 5); | 16578 | EXPECT_EQ(compute_graph->GetAllNodesSize(), 5); |
| @@ -20079,4 +20790,390 @@ TEST_F(AscBackendPostProcessorTest, Adaption_CyclicExternalLiftPass_DtypeNotSupp | |||
| 20079 | // 确保Broadcast节点数量符合预期 | 20790 | // 确保Broadcast节点数量符合预期 |
| 20080 | ASSERT_EQ(broadcast_cnt, 2); | 20791 | ASSERT_EQ(broadcast_cnt, 2); |
| 20081 | } | 20792 | } |
| 20793 | + | ||
| 20794 | +static std::shared_ptr<ge::AscGraph> CreatConcatGraphWithSqueezedLeadingAxis(ge::AscGraph &graph) { | ||
| 20795 | + const auto one = Symbol(1); | ||
| 20796 | + const auto axis0_size = Symbol(4); | ||
| 20797 | + const auto axis1_size = Symbol(22); | ||
| 20798 | + const auto axis2_size = Symbol(15120); | ||
| 20799 | + auto axis0 = graph.CreateAxis("A", axis0_size); | ||
| 20800 | + auto axis1 = graph.CreateAxis("B", axis1_size); | ||
| 20801 | + auto axis2 = graph.CreateAxis("C", axis2_size); | ||
| 20802 | + | ||
| 20803 | + std::vector<af::ascir_op::Load> loads; | ||
| 20804 | + loads.reserve(4U); | ||
| 20805 | + std::vector<ge::AscOpOutput> load_outputs; | ||
| 20806 | + for (size_t i = 0U; i < 4U; ++i) { | ||
| 20807 | + const auto data_name = "data" + std::to_string(i); | ||
| 20808 | + af::ascir_op::Data data(data_name.c_str(), graph); | ||
| 20809 | + data.attr.sched.axis = {axis1.id, axis2.id, axis0.id}; | ||
| 20810 | + data.y.dtype = DT_FLOAT16; | ||
| 20811 | + *data.y.axis = {axis1.id, axis2.id, axis0.id}; | ||
| 20812 | + *data.y.repeats = {axis1_size, axis2_size, one}; | ||
| 20813 | + *data.y.strides = {axis2_size, one, Symbol(0)}; | ||
| 20814 | + | ||
| 20815 | + const auto load_name = "load" + std::to_string(i); | ||
| 20816 | + loads.emplace_back(load_name.c_str()); | ||
| 20817 | + loads.back().x = data.y; | ||
| 20818 | + loads.back().attr.sched.axis = {axis1.id, axis2.id, axis0.id}; | ||
| 20819 | + loads.back().attr.sched.loop_axis = axis0.id; | ||
| 20820 | + loads.back().y.dtype = DT_FLOAT16; | ||
| 20821 | + *loads.back().y.axis = {axis1.id, axis2.id, axis0.id}; | ||
| 20822 | + *loads.back().y.repeats = {axis1_size, axis2_size, one}; | ||
| 20823 | + *loads.back().y.strides = {axis2_size, one, Symbol(0)}; | ||
| 20824 | + *loads.back().y.vectorized_axis = {axis1.id, axis2.id, axis0.id}; | ||
| 20825 | + load_outputs.emplace_back(loads.back().y); | ||
| 20826 | + } | ||
| 20827 | + | ||
| 20828 | + af::ascir_op::Concat concat("concat"); | ||
| 20829 | + concat.x = load_outputs; | ||
| 20830 | + concat.attr.sched.axis = {axis1.id, axis2.id, axis0.id}; | ||
| 20831 | + concat.attr.sched.loop_axis = axis0.id; | ||
| 20832 | + concat.y.dtype = DT_FLOAT16; | ||
| 20833 | + *concat.y.axis = {axis1.id, axis2.id, axis0.id}; | ||
| 20834 | + *concat.y.repeats = {axis1_size, axis2_size, axis0_size}; | ||
| 20835 | + *concat.y.strides = {axis2_size * axis0_size, axis0_size, one}; | ||
| 20836 | + *concat.y.vectorized_axis = {axis1.id, axis2.id, axis0.id}; | ||
| 20837 | + | ||
| 20838 | + af::ascir_op::Store store("store"); | ||
| 20839 | + store.x = concat.y; | ||
| 20840 | + store.attr.sched.axis = {axis1.id, axis2.id, axis0.id}; | ||
| 20841 | + store.attr.sched.loop_axis = axis0.id; | ||
| 20842 | + store.y.dtype = DT_FLOAT16; | ||
| 20843 | + *store.y.axis = {axis1.id, axis2.id, axis0.id}; | ||
| 20844 | + *store.y.repeats = {axis1_size, axis2_size, axis0_size}; | ||
| 20845 | + *store.y.strides = {axis2_size * axis0_size, axis0_size, one}; | ||
| 20846 | + *store.y.vectorized_axis = {axis1.id, axis2.id, axis0.id}; | ||
| 20847 | + | ||
| 20848 | + af::ascir_op::Output output("output"); | ||
| 20849 | + output.x = store.y; | ||
| 20850 | + output.attr.sched.axis = {axis1.id, axis2.id, axis0.id}; | ||
| 20851 | + *output.y.axis = {}; | ||
| 20852 | + *output.y.repeats = {}; | ||
| 20853 | + *output.y.strides = {}; | ||
| 20854 | + | ||
| 20855 | + auto output_node = graph.FindNode("output"); | ||
| 20856 | + auto compute_graph = output_node->GetOwnerComputeGraph(); | ||
| 20857 | + std::vector<std::pair<NodePtr, int32_t>> output_nodes{{output_node, 0}}; | ||
| 20858 | + compute_graph->SetOutputSize(1U); | ||
| 20859 | + compute_graph->SetGraphOutNodesInfo(output_nodes); | ||
| 20860 | + auto graph_attr = compute_graph->GetAttrsGroup<AscGraphAttr>(); | ||
| 20861 | + graph_attr->axis = {graph_attr->axis[1], graph_attr->axis[2], graph_attr->axis[0]}; | ||
| 20862 | + return std::shared_ptr<ge::AscGraph>(new ge::AscGraph(graph)); | ||
| 20863 | +} | ||
| 20864 | + | ||
| 20865 | +static std::shared_ptr<ge::AscGraph> CreatSplitGraphWithSqueezedLeadingAxis(ge::AscGraph &graph) { | ||
| 20866 | + const auto one = Symbol(1); | ||
| 20867 | + const auto axis0_size = Symbol(4); | ||
| 20868 | + const auto axis1_size = Symbol(22); | ||
| 20869 | + const auto axis2_size = Symbol(15120); | ||
| 20870 | + auto axis0 = graph.CreateAxis("A", axis0_size); | ||
| 20871 | + auto axis1 = graph.CreateAxis("B", axis1_size); | ||
| 20872 | + auto axis2 = graph.CreateAxis("C", axis2_size); | ||
| 20873 | + | ||
| 20874 | + af::ascir_op::Data data("split_data", graph); | ||
| 20875 | + data.attr.sched.axis = {axis0.id, axis1.id, axis2.id}; | ||
| 20876 | + data.y.dtype = DT_FLOAT16; | ||
| 20877 | + *data.y.axis = {axis0.id, axis1.id, axis2.id}; | ||
| 20878 | + *data.y.repeats = {axis0_size, axis1_size, axis2_size}; | ||
| 20879 | + *data.y.strides = {axis1_size * axis2_size, axis2_size, one}; | ||
| 20880 | + | ||
| 20881 | + af::ascir_op::Load load("split_load"); | ||
| 20882 | + load.x = data.y; | ||
| 20883 | + load.attr.sched.axis = {axis0.id, axis1.id, axis2.id}; | ||
| 20884 | + load.attr.sched.loop_axis = axis2.id; | ||
| 20885 | + load.y.dtype = DT_FLOAT16; | ||
| 20886 | + *load.y.axis = {axis0.id, axis1.id, axis2.id}; | ||
| 20887 | + *load.y.repeats = {axis0_size, axis1_size, axis2_size}; | ||
| 20888 | + *load.y.strides = {axis1_size * axis2_size, axis2_size, one}; | ||
| 20889 | + | ||
| 20890 | + af::ascir_op::Split split("split"); | ||
| 20891 | + split.InstanceOutputy(1); | ||
| 20892 | + split.ir_attr.SetIndex(0); | ||
| 20893 | + split.x = load.y; | ||
| 20894 | + split.attr.sched.axis = {axis1.id, axis2.id, axis0.id}; | ||
| 20895 | + split.attr.sched.loop_axis = axis0.id; | ||
| 20896 | + split.y[0].dtype = DT_FLOAT16; | ||
| 20897 | + AscOutputAttrDataType split_output_data_type(&split, 0); | ||
| 20898 | + split_output_data_type = ge::DT_FLOAT16; | ||
| 20899 | + *split.y[0].axis = {axis1.id, axis2.id, axis0.id}; | ||
| 20900 | + *split.y[0].repeats = {axis1_size, axis2_size, one}; | ||
| 20901 | + *split.y[0].strides = {axis2_size, one, Symbol(0)}; | ||
| 20902 | + | ||
| 20903 | + af::ascir_op::Store store("split_store"); | ||
| 20904 | + store.x = split.y[0]; | ||
| 20905 | + store.attr.sched.axis = {axis1.id, axis2.id, axis0.id}; | ||
| 20906 | + store.attr.sched.loop_axis = axis0.id; | ||
| 20907 | + store.y.dtype = DT_FLOAT16; | ||
| 20908 | + *store.y.axis = {axis1.id, axis2.id, axis0.id}; | ||
| 20909 | + *store.y.repeats = {axis1_size, axis2_size, one}; | ||
| 20910 | + *store.y.strides = {axis2_size, one, Symbol(0)}; | ||
| 20911 | + | ||
| 20912 | + af::ascir_op::Output output("split_output"); | ||
| 20913 | + output.x = store.y; | ||
| 20914 | + output.attr.sched.axis = {axis1.id, axis2.id, axis0.id}; | ||
| 20915 | + *output.y.axis = {}; | ||
| 20916 | + *output.y.repeats = {}; | ||
| 20917 | + *output.y.strides = {}; | ||
| 20918 | + | ||
| 20919 | + auto output_node = graph.FindNode("split_output"); | ||
| 20920 | + auto compute_graph = output_node->GetOwnerComputeGraph(); | ||
| 20921 | + std::vector<std::pair<NodePtr, int32_t>> output_nodes{{output_node, 0}}; | ||
| 20922 | + compute_graph->SetOutputSize(1U); | ||
| 20923 | + compute_graph->SetGraphOutNodesInfo(output_nodes); | ||
| 20924 | + auto graph_attr = compute_graph->GetAttrsGroup<AscGraphAttr>(); | ||
| 20925 | + graph_attr->axis = {graph_attr->axis[1], graph_attr->axis[2], graph_attr->axis[0]}; | ||
| 20926 | + return std::shared_ptr<ge::AscGraph>(new ge::AscGraph(graph)); | ||
| 20927 | +} | ||
| 20928 | + | ||
| 20929 | +static std::shared_ptr<ge::AscGraph> CreatConcatGraphWithInsertedAxisNotConcatAxis(ge::AscGraph &graph) { | ||
| 20930 | + const auto one = Symbol(1); | ||
| 20931 | + const auto concat_axis_size = Symbol(4); | ||
| 20932 | + const auto axis1_size = Symbol(22); | ||
| 20933 | + const auto axis2_size = Symbol(15120); | ||
| 20934 | + auto axis1 = graph.CreateAxis("B", axis1_size); | ||
| 20935 | + auto concat_axis = graph.CreateAxis("A", concat_axis_size); | ||
| 20936 | + auto inserted_axis = graph.CreateAxis("D", one); | ||
| 20937 | + auto axis2 = graph.CreateAxis("C", axis2_size); | ||
| 20938 | + const std::vector<int64_t> axis = {axis1.id, concat_axis.id, inserted_axis.id, axis2.id}; | ||
| 20939 | + | ||
| 20940 | + std::vector<af::ascir_op::Load> loads; | ||
| 20941 | + loads.reserve(4U); | ||
| 20942 | + std::vector<ge::AscOpOutput> load_outputs; | ||
| 20943 | + for (size_t i = 0U; i < 4U; ++i) { | ||
| 20944 | + const auto data_name = "data_not_tail" + std::to_string(i); | ||
| 20945 | + af::ascir_op::Data data(data_name.c_str(), graph); | ||
| 20946 | + data.attr.sched.axis = axis; | ||
| 20947 | + data.y.dtype = DT_FLOAT16; | ||
| 20948 | + *data.y.axis = axis; | ||
| 20949 | + *data.y.repeats = {axis1_size, one, one, axis2_size}; | ||
| 20950 | + *data.y.strides = {axis2_size, Symbol(0), Symbol(0), one}; | ||
| 20951 | + | ||
| 20952 | + const auto load_name = "load_not_tail" + std::to_string(i); | ||
| 20953 | + loads.emplace_back(load_name.c_str()); | ||
| 20954 | + loads.back().x = data.y; | ||
| 20955 | + loads.back().attr.sched.axis = axis; | ||
| 20956 | + loads.back().y.dtype = DT_FLOAT16; | ||
| 20957 | + *loads.back().y.axis = axis; | ||
| 20958 | + *loads.back().y.repeats = {axis1_size, one, one, axis2_size}; | ||
| 20959 | + *loads.back().y.strides = {axis2_size, Symbol(0), Symbol(0), one}; | ||
| 20960 | + load_outputs.emplace_back(loads.back().y); | ||
| 20961 | + } | ||
| 20962 | + | ||
| 20963 | + af::ascir_op::Concat concat("concat_not_tail"); | ||
| 20964 | + concat.x = load_outputs; | ||
| 20965 | + concat.attr.sched.axis = axis; | ||
| 20966 | + concat.y.dtype = DT_FLOAT16; | ||
| 20967 | + *concat.y.axis = axis; | ||
| 20968 | + *concat.y.repeats = {axis1_size, concat_axis_size, one, axis2_size}; | ||
| 20969 | + *concat.y.strides = {concat_axis_size * axis2_size, axis2_size, Symbol(0), one}; | ||
| 20970 | + | ||
| 20971 | + af::ascir_op::Store store("store_not_tail"); | ||
| 20972 | + store.x = concat.y; | ||
| 20973 | + store.attr.sched.axis = axis; | ||
| 20974 | + store.y.dtype = DT_FLOAT16; | ||
| 20975 | + *store.y.axis = axis; | ||
| 20976 | + *store.y.repeats = {axis1_size, concat_axis_size, one, axis2_size}; | ||
| 20977 | + *store.y.strides = {concat_axis_size * axis2_size, axis2_size, Symbol(0), one}; | ||
| 20978 | + | ||
| 20979 | + af::ascir_op::Output output("output_not_tail"); | ||
| 20980 | + output.x = store.y; | ||
| 20981 | + output.attr.sched.axis = axis; | ||
| 20982 | + *output.y.axis = {}; | ||
| 20983 | + *output.y.repeats = {}; | ||
| 20984 | + *output.y.strides = {}; | ||
| 20985 | + | ||
| 20986 | + auto output_node = graph.FindNode("output_not_tail"); | ||
| 20987 | + auto compute_graph = output_node->GetOwnerComputeGraph(); | ||
| 20988 | + std::vector<std::pair<NodePtr, int32_t>> output_nodes{{output_node, 0}}; | ||
| 20989 | + compute_graph->SetOutputSize(1U); | ||
| 20990 | + compute_graph->SetGraphOutNodesInfo(output_nodes); | ||
| 20991 | + return std::shared_ptr<ge::AscGraph>(new ge::AscGraph(graph)); | ||
| 20992 | +} | ||
| 20993 | + | ||
| 20994 | +TEST_F(AscBackendPostProcessorTest, CompleteAttrs_FusedConcatKeepsSqueezedLeadingAxis) { | ||
| 20995 | + ge::AscGraph concat_graph("concat_axis_padding"); | ||
| 20996 | + auto asc_graph = CreatConcatGraphWithSqueezedLeadingAxis(concat_graph); | ||
| 20997 | + ASSERT_NE(asc_graph, nullptr); | ||
| 20998 | + | ||
| 20999 | + GraphBuilder inner_builder("fused_inner"); | ||
| 21000 | + auto concat_backend = inner_builder.AddNode("concat_backend", kAscBackendType, 0, 1); | ||
| 21001 | + auto concat_backend_attr = GetOrCreateAutoFuseAttrs(concat_backend->GetOpDescBarePtr()); | ||
| 21002 | + ASSERT_NE(concat_backend_attr, nullptr); | ||
| 21003 | + concat_backend_attr->SetAscGraph(asc_graph, loop::FuseType::kConcat); | ||
| 21004 | + auto inner_graph = inner_builder.GetGraph(); | ||
| 21005 | + | ||
| 21006 | + GraphBuilder root_builder("root"); | ||
| 21007 | + auto fused_node = root_builder.AddNode("fused", kFusedAscBackendType, 0, 1); | ||
| 21008 | + auto fused_attr = GetOrCreateAutoFuseAttrs(fused_node->GetOpDescBarePtr()); | ||
| 21009 | + ASSERT_NE(fused_attr, nullptr); | ||
| 21010 | + fused_attr->SetFuseComputeGraph(inner_graph); | ||
| 21011 | + auto root_graph = root_builder.GetGraph(); | ||
| 21012 | + | ||
| 21013 | + EXPECT_EQ(asc_adapt::CompleteNodeAttrsOnAscGraphForSched(root_graph), SUCCESS); | ||
| 21014 | + | ||
| 21015 | + const auto graph_attr = AscGraphUtils::GetComputeGraph(*asc_graph)->GetAttrsGroup<AscGraphAttr>(); | ||
| 21016 | + ASSERT_NE(graph_attr, nullptr); | ||
| 21017 | + ASSERT_EQ(graph_attr->axis.size(), 4U); | ||
| 21018 | + EXPECT_EQ(std::string(graph_attr->axis[0]->size.Str().get()), "4"); | ||
| 21019 | + EXPECT_EQ(std::string(graph_attr->axis[1]->size.Str().get()), "22"); | ||
| 21020 | + EXPECT_EQ(std::string(graph_attr->axis[2]->size.Str().get()), "15120"); | ||
| 21021 | + EXPECT_TRUE(BackendUtils::IsEqOne(graph_attr->axis[3]->size)); | ||
| 21022 | + | ||
| 21023 | + AscTensorAttr *concat_attr = nullptr; | ||
| 21024 | + auto concat_node = asc_graph->FindNode("concat"); | ||
| 21025 | + ASSERT_NE(concat_node, nullptr); | ||
| 21026 | + const auto concat_node_attr = concat_node->GetOpDesc()->GetAttrsGroup<AscNodeAttr>(); | ||
| 21027 | + ASSERT_NE(concat_node_attr, nullptr); | ||
| 21028 | + EXPECT_EQ(concat_node_attr->sched.loop_axis, 0); | ||
| 21029 | + ASSERT_EQ(asc_adapt::GetOutputTensorAttr(concat_node, concat_attr), SUCCESS); | ||
| 21030 | + EXPECT_EQ(concat_attr->axis, std::vector<int64_t>({0, 1, 2, 3})); | ||
| 21031 | + EXPECT_EQ(concat_attr->vectorized_axis, std::vector<int64_t>({1, 2, 0})); | ||
| 21032 | + ASSERT_EQ(concat_attr->repeats.size(), 4U); | ||
| 21033 | + EXPECT_EQ(std::string(concat_attr->repeats[0].Str().get()), "4"); | ||
| 21034 | + EXPECT_EQ(std::string(concat_attr->repeats[1].Str().get()), "22"); | ||
| 21035 | + EXPECT_EQ(std::string(concat_attr->repeats[2].Str().get()), "15120"); | ||
| 21036 | + EXPECT_TRUE(BackendUtils::IsEqOne(concat_attr->repeats[3])); | ||
| 21037 | + ASSERT_EQ(concat_attr->strides.size(), 4U); | ||
| 21038 | + EXPECT_TRUE(BackendUtils::IsEqOne(concat_attr->strides[0])); | ||
| 21039 | + EXPECT_EQ(std::string(concat_attr->strides[1].Str().get()), "60480"); | ||
| 21040 | + EXPECT_EQ(std::string(concat_attr->strides[2].Str().get()), "4"); | ||
| 21041 | + EXPECT_TRUE(BackendUtils::IsEqZero(concat_attr->strides[3])); | ||
| 21042 | + | ||
| 21043 | + AscTensorAttr *store_attr = nullptr; | ||
| 21044 | + auto store_node = asc_graph->FindNode("store"); | ||
| 21045 | + ASSERT_NE(store_node, nullptr); | ||
| 21046 | + const auto store_node_attr = store_node->GetOpDesc()->GetAttrsGroup<AscNodeAttr>(); | ||
| 21047 | + ASSERT_NE(store_node_attr, nullptr); | ||
| 21048 | + EXPECT_EQ(store_node_attr->sched.loop_axis, 0); | ||
| 21049 | + ASSERT_EQ(asc_adapt::GetOutputTensorAttr(store_node, store_attr), SUCCESS); | ||
| 21050 | + EXPECT_EQ(store_attr->axis, std::vector<int64_t>({0, 1, 2, 3})); | ||
| 21051 | + EXPECT_EQ(store_attr->vectorized_axis, std::vector<int64_t>({1, 2, 0})); | ||
| 21052 | + ASSERT_EQ(store_attr->repeats.size(), 4U); | ||
| 21053 | + EXPECT_EQ(std::string(store_attr->repeats[0].Str().get()), "4"); | ||
| 21054 | + EXPECT_EQ(std::string(store_attr->repeats[1].Str().get()), "22"); | ||
| 21055 | + EXPECT_EQ(std::string(store_attr->repeats[2].Str().get()), "15120"); | ||
| 21056 | + EXPECT_TRUE(BackendUtils::IsEqOne(store_attr->repeats[3])); | ||
| 21057 | + ASSERT_EQ(store_attr->strides.size(), 4U); | ||
| 21058 | + EXPECT_TRUE(BackendUtils::IsEqOne(store_attr->strides[0])); | ||
| 21059 | + EXPECT_EQ(std::string(store_attr->strides[1].Str().get()), "60480"); | ||
| 21060 | + EXPECT_EQ(std::string(store_attr->strides[2].Str().get()), "4"); | ||
| 21061 | + EXPECT_TRUE(BackendUtils::IsEqZero(store_attr->strides[3])); | ||
| 21062 | +} | ||
| 21063 | + | ||
| 21064 | +TEST_F(AscBackendPostProcessorTest, CompleteAttrs_FusedConcatCompletesSplitLoadSqueezedAxis) { | ||
| 21065 | + ge::AscGraph split_graph("split_axis_padding"); | ||
| 21066 | + auto split_asc_graph = CreatSplitGraphWithSqueezedLeadingAxis(split_graph); | ||
| 21067 | + ASSERT_NE(split_asc_graph, nullptr); | ||
| 21068 | + ge::AscGraph concat_graph("concat_axis_padding_for_split"); | ||
| 21069 | + auto concat_asc_graph = CreatConcatGraphWithSqueezedLeadingAxis(concat_graph); | ||
| 21070 | + ASSERT_NE(concat_asc_graph, nullptr); | ||
| 21071 | + | ||
| 21072 | + GraphBuilder inner_builder("fused_inner_with_split"); | ||
| 21073 | + auto split_backend = inner_builder.AddNode("split_backend", kAscBackendType, 0, 1); | ||
| 21074 | + auto split_backend_attr = GetOrCreateAutoFuseAttrs(split_backend->GetOpDescBarePtr()); | ||
| 21075 | + ASSERT_NE(split_backend_attr, nullptr); | ||
| 21076 | + split_backend_attr->SetAscGraph(split_asc_graph, loop::FuseType::kSplit); | ||
| 21077 | + auto concat_backend = inner_builder.AddNode("concat_backend_for_split", kAscBackendType, 0, 1); | ||
| 21078 | + auto concat_backend_attr = GetOrCreateAutoFuseAttrs(concat_backend->GetOpDescBarePtr()); | ||
| 21079 | + ASSERT_NE(concat_backend_attr, nullptr); | ||
| 21080 | + concat_backend_attr->SetAscGraph(concat_asc_graph, loop::FuseType::kConcat); | ||
| 21081 | + auto inner_graph = inner_builder.GetGraph(); | ||
| 21082 | + | ||
| 21083 | + GraphBuilder root_builder("root_with_split"); | ||
| 21084 | + auto fused_node = root_builder.AddNode("fused_with_split", kFusedAscBackendType, 0, 1); | ||
| 21085 | + auto fused_attr = GetOrCreateAutoFuseAttrs(fused_node->GetOpDescBarePtr()); | ||
| 21086 | + ASSERT_NE(fused_attr, nullptr); | ||
| 21087 | + fused_attr->SetFuseComputeGraph(inner_graph); | ||
| 21088 | + auto root_graph = root_builder.GetGraph(); | ||
| 21089 | + | ||
| 21090 | + EXPECT_EQ(asc_adapt::CompleteNodeAttrsOnAscGraphForSched(root_graph), SUCCESS); | ||
| 21091 | + | ||
| 21092 | + AscTensorAttr *load_attr = nullptr; | ||
| 21093 | + auto load_node = split_asc_graph->FindNode("split_load"); | ||
| 21094 | + ASSERT_NE(load_node, nullptr); | ||
| 21095 | + ASSERT_EQ(asc_adapt::GetOutputTensorAttr(load_node, load_attr), SUCCESS); | ||
| 21096 | + EXPECT_EQ(load_attr->axis, std::vector<int64_t>({0, 1, 2, 3})); | ||
| 21097 | + ASSERT_EQ(load_attr->repeats.size(), 4U); | ||
| 21098 | + EXPECT_EQ(std::string(load_attr->repeats[0].Str().get()), "4"); | ||
| 21099 | + EXPECT_EQ(std::string(load_attr->repeats[1].Str().get()), "22"); | ||
| 21100 | + EXPECT_EQ(std::string(load_attr->repeats[2].Str().get()), "15120"); | ||
| 21101 | + EXPECT_TRUE(BackendUtils::IsEqOne(load_attr->repeats[3])); | ||
| 21102 | + | ||
| 21103 | + AscTensorAttr *data_attr = nullptr; | ||
| 21104 | + auto data_node = split_asc_graph->FindNode("split_data"); | ||
| 21105 | + ASSERT_NE(data_node, nullptr); | ||
| 21106 | + ASSERT_EQ(asc_adapt::GetOutputTensorAttr(data_node, data_attr), SUCCESS); | ||
| 21107 | + EXPECT_EQ(data_attr->axis, load_attr->axis); | ||
| 21108 | + ASSERT_EQ(data_attr->repeats.size(), load_attr->repeats.size()); | ||
| 21109 | + for (size_t i = 0U; i < data_attr->repeats.size(); ++i) { | ||
| 21110 | + EXPECT_EQ(std::string(data_attr->repeats[i].Str().get()), std::string(load_attr->repeats[i].Str().get())); | ||
| 21111 | + } | ||
| 21112 | + | ||
| 21113 | + AscTensorAttr *split_attr = nullptr; | ||
| 21114 | + auto split_node = split_asc_graph->FindNode("split"); | ||
| 21115 | + ASSERT_NE(split_node, nullptr); | ||
| 21116 | + ASSERT_EQ(asc_adapt::GetOutputTensorAttr(split_node, split_attr), SUCCESS); | ||
| 21117 | + EXPECT_EQ(split_attr->axis, std::vector<int64_t>({0, 1, 2, 3})); | ||
| 21118 | + ASSERT_EQ(split_attr->repeats.size(), 4U); | ||
| 21119 | + EXPECT_TRUE(BackendUtils::IsEqOne(split_attr->repeats[0])); | ||
| 21120 | + EXPECT_EQ(std::string(split_attr->repeats[1].Str().get()), "22"); | ||
| 21121 | + EXPECT_EQ(std::string(split_attr->repeats[2].Str().get()), "15120"); | ||
| 21122 | + EXPECT_TRUE(BackendUtils::IsEqOne(split_attr->repeats[3])); | ||
| 21123 | +} | ||
| 21124 | + | ||
| 21125 | +TEST_F(AscBackendPostProcessorTest, CompleteAttrs_FusedConcatKeepsInsertedAxisNotConcatAxis) { | ||
| 21126 | + ge::AscGraph concat_graph("concat_axis_padding_not_tail"); | ||
| 21127 | + auto asc_graph = CreatConcatGraphWithInsertedAxisNotConcatAxis(concat_graph); | ||
| 21128 | + ASSERT_NE(asc_graph, nullptr); | ||
| 21129 | + | ||
| 21130 | + GraphBuilder inner_builder("fused_inner_not_tail"); | ||
| 21131 | + auto concat_backend = inner_builder.AddNode("concat_backend_not_tail", kAscBackendType, 0, 1); | ||
| 21132 | + auto concat_backend_attr = GetOrCreateAutoFuseAttrs(concat_backend->GetOpDescBarePtr()); | ||
| 21133 | + ASSERT_NE(concat_backend_attr, nullptr); | ||
| 21134 | + concat_backend_attr->SetAscGraph(asc_graph, loop::FuseType::kConcat); | ||
| 21135 | + auto inner_graph = inner_builder.GetGraph(); | ||
| 21136 | + | ||
| 21137 | + GraphBuilder root_builder("root_not_tail"); | ||
| 21138 | + auto fused_node = root_builder.AddNode("fused_not_tail", kFusedAscBackendType, 0, 1); | ||
| 21139 | + auto fused_attr = GetOrCreateAutoFuseAttrs(fused_node->GetOpDescBarePtr()); | ||
| 21140 | + ASSERT_NE(fused_attr, nullptr); | ||
| 21141 | + fused_attr->SetFuseComputeGraph(inner_graph); | ||
| 21142 | + auto root_graph = root_builder.GetGraph(); | ||
| 21143 | + | ||
| 21144 | + EXPECT_EQ(asc_adapt::CompleteNodeAttrsOnAscGraphForSched(root_graph), SUCCESS); | ||
| 21145 | + | ||
| 21146 | + const auto graph_attr = AscGraphUtils::GetComputeGraph(*asc_graph)->GetAttrsGroup<AscGraphAttr>(); | ||
| 21147 | + ASSERT_NE(graph_attr, nullptr); | ||
| 21148 | + ASSERT_EQ(graph_attr->axis.size(), 5U); | ||
| 21149 | + EXPECT_EQ(graph_attr->axis[0]->id, 0); | ||
| 21150 | + EXPECT_EQ(graph_attr->axis[1]->id, 1); | ||
| 21151 | + EXPECT_EQ(graph_attr->axis[2]->id, 2); | ||
| 21152 | + EXPECT_EQ(graph_attr->axis[3]->id, 3); | ||
| 21153 | + EXPECT_EQ(graph_attr->axis[4]->id, 4); | ||
| 21154 | + | ||
| 21155 | + AscTensorAttr *concat_attr = nullptr; | ||
| 21156 | + auto concat_node = asc_graph->FindNode("concat_not_tail"); | ||
| 21157 | + ASSERT_NE(concat_node, nullptr); | ||
| 21158 | + ASSERT_EQ(asc_adapt::GetOutputTensorAttr(concat_node, concat_attr), SUCCESS); | ||
| 21159 | + EXPECT_EQ(concat_attr->axis, std::vector<int64_t>({0, 1, 2, 3, 4})); | ||
| 21160 | + ASSERT_EQ(concat_attr->repeats.size(), 5U); | ||
| 21161 | + EXPECT_EQ(std::string(concat_attr->repeats[0].Str().get()), "22"); | ||
| 21162 | + EXPECT_EQ(std::string(concat_attr->repeats[1].Str().get()), "4"); | ||
| 21163 | + EXPECT_TRUE(BackendUtils::IsEqOne(concat_attr->repeats[2])); | ||
| 21164 | + EXPECT_EQ(std::string(concat_attr->repeats[3].Str().get()), "15120"); | ||
| 21165 | + EXPECT_TRUE(BackendUtils::IsEqOne(concat_attr->repeats[4])); | ||
| 21166 | + | ||
| 21167 | + AscTensorAttr *store_attr = nullptr; | ||
| 21168 | + auto store_node = asc_graph->FindNode("store_not_tail"); | ||
| 21169 | + ASSERT_NE(store_node, nullptr); | ||
| 21170 | + ASSERT_EQ(asc_adapt::GetOutputTensorAttr(store_node, store_attr), SUCCESS); | ||
| 21171 | + EXPECT_EQ(store_attr->axis, std::vector<int64_t>({0, 1, 2, 3, 4})); | ||
| 21172 | + ASSERT_EQ(store_attr->repeats.size(), 5U); | ||
| 21173 | + EXPECT_EQ(std::string(store_attr->repeats[0].Str().get()), "22"); | ||
| 21174 | + EXPECT_EQ(std::string(store_attr->repeats[1].Str().get()), "4"); | ||
| 21175 | + EXPECT_TRUE(BackendUtils::IsEqOne(store_attr->repeats[2])); | ||
| 21176 | + EXPECT_EQ(std::string(store_attr->repeats[3].Str().get()), "15120"); | ||
| 21177 | + EXPECT_TRUE(BackendUtils::IsEqOne(store_attr->repeats[4])); | ||
| 21178 | +} | ||
| 20082 | } // namespace ge | 21179 | } // namespace ge |