Line data Source code
1 : /**
2 : * Copyright (c) 2025 Huawei Technologies Co., Ltd.
3 : * This program is free software, you can redistribute it and/or modify it under the terms and conditions of
4 : * CANN Open Software License Agreement Version 2.0 (the "License").
5 : * Please refer to the License for details. You may not use this file except in compliance with the License.
6 : * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED,
7 : * INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.
8 : * See LICENSE in the root of the software repository for the full text of the License.
9 : */
10 :
11 : #include "coll_aligned_all_gather_v_double_ring_for_910_93_executor.h"
12 : #include <numeric>
13 :
14 : namespace hccl {
15 0 : CollAlignedAllGatherVDoubleRingFor91093Executor::CollAlignedAllGatherVDoubleRingFor91093Executor(
16 0 : const HcclDispatcher dispatcher, std::unique_ptr<TopoMatcher> &topoMatcher)
17 0 : : CollAlignedAllGatherDoubleRingFor91093Executor(dispatcher, topoMatcher)
18 : {
19 0 : isAllGatherV_ = true;
20 0 : desc_.level1SupportedAlgos = {
21 : AlgTypeLevel1::ALG_LEVEL1_NHR,
22 : AlgTypeLevel1::ALG_LEVEL1_NB,
23 : AlgTypeLevel1::ALG_LEVEL1_RING
24 0 : };
25 0 : }
26 :
27 0 : bool CollAlignedAllGatherVDoubleRingFor91093Executor::IsSmallData(const u64 size)
28 : {
29 : (void) size;
30 0 : return false;
31 : }
32 :
33 0 : u64 CollAlignedAllGatherVDoubleRingFor91093Executor::CalcDstMemOffset(const OpParam ¶m, u32 perDataSize,
34 : u64 inputMemSize) const
35 : {
36 : (void) inputMemSize;
37 0 : const auto *counts = static_cast<const u64 *>(param.VDataDes.counts);
38 0 : const u64 offset = std::accumulate(counts, counts + topoAttr_.userRank, 0ULL);
39 0 : return offset * perDataSize;
40 : }
41 :
42 0 : HcomCollOpInfo CollAlignedAllGatherVDoubleRingFor91093Executor::GetHcomCollOpInfo(const OpParam ¶m,
43 : const ExecMem &execMem) const
44 : {
45 0 : HcomCollOpInfo opInfo = {
46 0 : "", execMem.inputPtr, execMem.outputPtr, execMem.count, param.VDataDes.dataType, param.root,
47 0 : param.reduceType, 0 // 暂不支持MC2的strideCount特性
48 0 : };
49 0 : if (!DMAReduceFlag_) {
50 0 : opInfo.inputAddr = execMem.inputMem.ptr();
51 0 : opInfo.outputAddr = execMem.outputMem.ptr();
52 : }
53 0 : return opInfo;
54 : }
55 :
56 0 : std::vector<Slice> CollAlignedAllGatherVDoubleRingFor91093Executor::PrepareSlicesL2(const OpParam ¶m,
57 : const SubCommInfo &level2CommInfo, const SubCommInfo &level1CommInfo, const SubCommInfo &level0CommInfo,
58 : u32 perDataSize, u64 inputMemSize) const
59 : {
60 : (void) inputMemSize;
61 0 : const auto *counts = static_cast<u64 *>(param.VDataDes.counts);
62 0 : const u32 level0RankSize = level0CommInfo.localRankSize;
63 0 : const u32 level0ServerIndex = level0CommInfo.localRank;
64 0 : const u32 level1RankSize = level1CommInfo.localRankSize;
65 0 : const u32 level1ServerIndex = level1CommInfo.localRank;
66 0 : const u32 level2RankSize = level2CommInfo.localRankSize;
67 0 : std::vector<Slice> level2DataSegsSlice;
68 0 : for (u32 i = 0; i < level2RankSize; i++) {
69 0 : Slice sliceTemp;
70 0 : const u32 rank = i * level1RankSize * level0RankSize + level1ServerIndex * level0RankSize + level0ServerIndex;
71 0 : sliceTemp.size = counts[rank] * perDataSize;
72 0 : const u64 offset = std::accumulate(counts, counts + rank, 0ULL);
73 0 : sliceTemp.offset = offset * perDataSize;
74 0 : level2DataSegsSlice.push_back(sliceTemp);
75 : }
76 0 : return level2DataSegsSlice;
77 0 : }
78 :
79 0 : std::vector<Slice> CollAlignedAllGatherVDoubleRingFor91093Executor::PrepareSlicesL1(const OpParam ¶m,
80 : const SubCommInfo &level2CommInfo, const SubCommInfo &level1CommInfo, const SubCommInfo &level0CommInfo,
81 : u32 perDataSize, u64 inputMemSize) const
82 : {
83 : (void) inputMemSize;
84 0 : const auto *counts = static_cast<u64 *>(param.VDataDes.counts);
85 0 : const u32 level0RankSize = level0CommInfo.localRankSize;
86 0 : const u32 level0ServerIndex = level0CommInfo.localRank;
87 0 : const u32 level1RankSize = level1CommInfo.localRankSize;
88 0 : const u32 level2RankSize = level2CommInfo.localRankSize;
89 0 : std::vector<Slice> level1DataSegsSlice;
90 0 : for (u32 j = 0; j < level1RankSize; j++) {
91 0 : for (u32 i = 0; i < level2RankSize; i++) {
92 0 : Slice level1Slice;
93 0 : const u32 rank = i * level1RankSize * level0RankSize + j * level0RankSize + level0ServerIndex;
94 0 : level1Slice.size = counts[rank] * perDataSize;
95 0 : const u64 offset = std::accumulate(counts, counts + rank, 0ULL);
96 0 : level1Slice.offset = offset * perDataSize;
97 0 : level1DataSegsSlice.push_back(level1Slice);
98 : }
99 : }
100 0 : return level1DataSegsSlice;
101 0 : }
102 :
103 0 : HcclResult CollAlignedAllGatherVDoubleRingFor91093Executor::PrepareSlicesL0(
104 : std::vector<std::vector<Slice>> &multRingsSlice, const OpParam ¶m, const SubCommInfo &level2CommInfo,
105 : const SubCommInfo &level1CommInfo, const SubCommInfo &level0CommInfo, u32 perDataSize, u64 inputMemSize)
106 : {
107 : (void) inputMemSize;
108 0 : HCCL_CONFIG_INFO(HCCL_ALG,
109 : "[CollAlignedAllGatherVDoubleRingFor91093Executor][PrepareSlicesL0] userRank[%u] starts.", topoAttr_.userRank);
110 0 : const auto *counts = static_cast<u64 *>(param.VDataDes.counts);
111 0 : const u32 level0RankSize = level0CommInfo.localRankSize;
112 0 : const u32 level1RankSize = level1CommInfo.localRankSize;
113 0 : const u32 level2RankSize = level2CommInfo.localRankSize;
114 0 : u32 ringSize = 0;
115 0 : std::vector<std::vector<std::vector<Slice>>> multRingsSliceZeroServers;
116 0 : for (u32 i = 0; i < level2RankSize; i++) {
117 0 : for (u32 j = 0; j < level1RankSize; j++) {
118 0 : std::vector<Slice> dataSegsSlice;
119 0 : for (u32 k = 0; k < level0RankSize; k++) { // 根据数据量计算每个环上数据的偏移和大小
120 0 : Slice sliceTemp;
121 0 : const u32 rank = i * level1RankSize * level0RankSize + j * level0RankSize + k;
122 0 : sliceTemp.size = counts[rank] * perDataSize;
123 0 : const u64 offset = std::accumulate(counts, counts + rank, 0ULL);
124 0 : sliceTemp.offset = offset * perDataSize; // no displs
125 0 : dataSegsSlice.push_back(sliceTemp);
126 : }
127 : // 机内多环数据切分
128 0 : auto multRingsSliceZeroServer = PrepareMultiRingSlice(dataSegsSlice, param.tag, false, topoAttr_.nicList);
129 0 : if (ringSize == 0) {
130 0 : ringSize = multRingsSliceZeroServer.size();
131 : } else {
132 0 : CHK_PRT_RET(multRingsSliceZeroServer.size() != ringSize,
133 : HCCL_ERROR("[CollAlignedAllGatherVDoubleRingFor91093Executor][PrepareSlicesL0]mismatch "
134 : "ringSize[%u], expect[%u]", multRingsSliceZeroServer.size(), ringSize),
135 : HCCL_E_PARA);
136 : }
137 0 : multRingsSliceZeroServers.push_back(multRingsSliceZeroServer);
138 0 : }
139 : }
140 0 : multRingsSlice.resize(ringSize);
141 0 : for (u32 k = 0; k < level0RankSize; k++) {
142 0 : for (u32 i = 0; i < level2RankSize; i++) {
143 0 : for (u32 j = 0; j < level1RankSize; j++) { // 按照机内rank的顺序调整数据分片的排布
144 0 : const u32 serverIndex = i * level1RankSize + j;
145 0 : const auto &multRingsSliceZeroServer = multRingsSliceZeroServers[serverIndex];
146 0 : for (u32 ringIndex = 0; ringIndex < ringSize; ringIndex++) {
147 0 : multRingsSlice[ringIndex].push_back(multRingsSliceZeroServer[ringIndex][k]);
148 : }
149 : }
150 : }
151 : }
152 0 : return HCCL_SUCCESS;
153 0 : }
154 :
155 : // AGV不支持MC2的strideCount特性
156 0 : HcclResult CollAlignedAllGatherVDoubleRingFor91093Executor::PrepareUserMemSlices(
157 : std::vector<std::vector<Slice>> &userMemSlices, const std::vector<std::vector<Slice>> &multRingsSlice,
158 : const OpParam ¶m, const SubCommInfo &level2CommInfo, const SubCommInfo &level1CommInfo,
159 : const SubCommInfo &level0CommInfo, u32 perDataSize, u64 inputMemSize)
160 : {
161 : (void) multRingsSlice;
162 : (void) inputMemSize;
163 0 : const auto *counts = static_cast<u64 *>(param.VDataDes.counts);
164 0 : const auto *displs = static_cast<u64 *>(param.VDataDes.displs);
165 0 : const u32 level0RankSize = level0CommInfo.localRankSize;
166 0 : const u32 level1RankSize = level1CommInfo.localRankSize;
167 0 : const u32 level2RankSize = level2CommInfo.localRankSize;
168 0 : u32 ringSize = 0;
169 0 : std::vector<std::vector<std::vector<Slice>>> userMemSlicesServers;
170 0 : for (u32 i = 0; i < level2RankSize; i++) {
171 0 : for (u32 j = 0; j < level1RankSize; j++) {
172 0 : std::vector<Slice> dataSegsSlice;
173 0 : for (u32 k = 0; k < level0RankSize; k++) { // 根据数据量计算每个环上数据的偏移和大小
174 0 : Slice sliceTemp;
175 0 : const u32 rank = i * level1RankSize * level0RankSize + j * level0RankSize + k;
176 0 : sliceTemp.size = counts[rank] * perDataSize;
177 0 : sliceTemp.offset = displs[rank] * perDataSize; // with displs
178 0 : dataSegsSlice.push_back(sliceTemp);
179 : }
180 : // 多环数据切分
181 0 : auto userMemSlicesServer = PrepareMultiRingSlice(dataSegsSlice, param.tag, false, topoAttr_.nicList);
182 0 : if (ringSize == 0) {
183 0 : ringSize = userMemSlicesServer.size();
184 : } else {
185 0 : CHK_PRT_RET(userMemSlicesServer.size() != ringSize,
186 : HCCL_ERROR("[CollAlignedAllGatherVDoubleRingFor91093Executor][PrepareUserMemSlices]mismatch "
187 : "ringSize[%u], expect[%u]", userMemSlicesServer.size(), ringSize),
188 : HCCL_E_PARA);
189 : }
190 0 : userMemSlicesServers.push_back(userMemSlicesServer);
191 0 : }
192 : }
193 0 : userMemSlices.resize(ringSize);
194 0 : for (u32 k = 0; k < level0RankSize; k++) {
195 0 : for (u32 i = 0; i < level2RankSize; i++) {
196 0 : for (u32 j = 0; j < level1RankSize; j++) { // 按照机内rank的顺序调整数据分片的排布
197 0 : const u32 serverIndex = i * level1RankSize + j;
198 0 : const auto &userMemSlicesServer = userMemSlicesServers[serverIndex];
199 0 : for (u32 ringIndex = 0; ringIndex < ringSize; ringIndex++) {
200 0 : userMemSlices[ringIndex].push_back(userMemSlicesServer[ringIndex][k]);
201 : }
202 : }
203 : }
204 : }
205 0 : return HCCL_SUCCESS;
206 0 : }
207 :
208 : REGISTER_EXEC("AlignedAllGatherVDoubleRingFor91093Executor", AlignedAllGatherVDoubleRingFor91093,
209 : CollAlignedAllGatherVDoubleRingFor91093Executor);
210 :
211 : } // namespace hccl
|