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 : desc_.level1SupportedAlgos
21 0 : = {AlgTypeLevel1::ALG_LEVEL1_NHR, AlgTypeLevel1::ALG_LEVEL1_NB, AlgTypeLevel1::ALG_LEVEL1_RING};
22 0 : }
23 :
24 0 : bool CollAlignedAllGatherVDoubleRingFor91093Executor::IsSmallData(const u64 size)
25 : {
26 : (void)size;
27 0 : return false;
28 : }
29 :
30 0 : u64 CollAlignedAllGatherVDoubleRingFor91093Executor::CalcDstMemOffset(
31 : const OpParam& param, u32 perDataSize, u64 inputMemSize) const
32 : {
33 : (void)inputMemSize;
34 0 : const auto* counts = static_cast<const u64*>(param.VDataDes.counts);
35 0 : const u64 offset = std::accumulate(counts, counts + topoAttr_.userRank, 0ULL);
36 0 : return offset * perDataSize;
37 : }
38 :
39 : HcomCollOpInfo
40 0 : CollAlignedAllGatherVDoubleRingFor91093Executor::GetHcomCollOpInfo(const OpParam& param, const ExecMem& execMem) const
41 : {
42 0 : HcomCollOpInfo opInfo = {
43 0 : "", execMem.inputPtr, execMem.outputPtr, execMem.count, param.VDataDes.dataType, param.root, param.reduceType,
44 : 0 // 暂不支持MC2的strideCount特性
45 0 : };
46 0 : if (!DMAReduceFlag_) {
47 0 : opInfo.inputAddr = execMem.inputMem.ptr();
48 0 : opInfo.outputAddr = execMem.outputMem.ptr();
49 : }
50 0 : return opInfo;
51 : }
52 :
53 0 : std::vector<Slice> CollAlignedAllGatherVDoubleRingFor91093Executor::PrepareSlicesL2(
54 : const OpParam& param, const SubCommInfo& level2CommInfo, const SubCommInfo& level1CommInfo,
55 : const SubCommInfo& level0CommInfo, u32 perDataSize, u64 inputMemSize) const
56 : {
57 : (void)inputMemSize;
58 0 : const auto* counts = static_cast<u64*>(param.VDataDes.counts);
59 0 : const u32 level0RankSize = level0CommInfo.localRankSize;
60 0 : const u32 level0ServerIndex = level0CommInfo.localRank;
61 0 : const u32 level1RankSize = level1CommInfo.localRankSize;
62 0 : const u32 level1ServerIndex = level1CommInfo.localRank;
63 0 : const u32 level2RankSize = level2CommInfo.localRankSize;
64 0 : std::vector<Slice> level2DataSegsSlice;
65 0 : for (u32 i = 0; i < level2RankSize; i++) {
66 0 : Slice sliceTemp;
67 0 : const u32 rank = i * level1RankSize * level0RankSize + level1ServerIndex * level0RankSize + level0ServerIndex;
68 0 : sliceTemp.size = counts[rank] * perDataSize;
69 0 : const u64 offset = std::accumulate(counts, counts + rank, 0ULL);
70 0 : sliceTemp.offset = offset * perDataSize;
71 0 : level2DataSegsSlice.push_back(sliceTemp);
72 : }
73 0 : return level2DataSegsSlice;
74 0 : }
75 :
76 0 : std::vector<Slice> CollAlignedAllGatherVDoubleRingFor91093Executor::PrepareSlicesL1(
77 : const OpParam& param, const SubCommInfo& level2CommInfo, const SubCommInfo& level1CommInfo,
78 : const SubCommInfo& level0CommInfo, u32 perDataSize, u64 inputMemSize) const
79 : {
80 : (void)inputMemSize;
81 0 : const auto* counts = static_cast<u64*>(param.VDataDes.counts);
82 0 : const u32 level0RankSize = level0CommInfo.localRankSize;
83 0 : const u32 level0ServerIndex = level0CommInfo.localRank;
84 0 : const u32 level1RankSize = level1CommInfo.localRankSize;
85 0 : const u32 level2RankSize = level2CommInfo.localRankSize;
86 0 : std::vector<Slice> level1DataSegsSlice;
87 0 : for (u32 j = 0; j < level1RankSize; j++) {
88 0 : for (u32 i = 0; i < level2RankSize; i++) {
89 0 : Slice level1Slice;
90 0 : const u32 rank = i * level1RankSize * level0RankSize + j * level0RankSize + level0ServerIndex;
91 0 : level1Slice.size = counts[rank] * perDataSize;
92 0 : const u64 offset = std::accumulate(counts, counts + rank, 0ULL);
93 0 : level1Slice.offset = offset * perDataSize;
94 0 : level1DataSegsSlice.push_back(level1Slice);
95 : }
96 : }
97 0 : return level1DataSegsSlice;
98 0 : }
99 :
100 0 : HcclResult CollAlignedAllGatherVDoubleRingFor91093Executor::PrepareSlicesL0(
101 : std::vector<std::vector<Slice>>& multRingsSlice, const OpParam& param, const SubCommInfo& level2CommInfo,
102 : const SubCommInfo& level1CommInfo, const SubCommInfo& level0CommInfo, u32 perDataSize, u64 inputMemSize)
103 : {
104 : (void)inputMemSize;
105 0 : HCCL_CONFIG_INFO(
106 : HCCL_ALG, "[CollAlignedAllGatherVDoubleRingFor91093Executor][PrepareSlicesL0] userRank[%u] starts.",
107 : topoAttr_.userRank);
108 0 : const auto* counts = static_cast<u64*>(param.VDataDes.counts);
109 0 : const u32 level0RankSize = level0CommInfo.localRankSize;
110 0 : const u32 level1RankSize = level1CommInfo.localRankSize;
111 0 : const u32 level2RankSize = level2CommInfo.localRankSize;
112 0 : u32 ringSize = 0;
113 0 : std::vector<std::vector<std::vector<Slice>>> multRingsSliceZeroServers;
114 0 : for (u32 i = 0; i < level2RankSize; i++) {
115 0 : for (u32 j = 0; j < level1RankSize; j++) {
116 0 : std::vector<Slice> dataSegsSlice;
117 0 : for (u32 k = 0; k < level0RankSize; k++) { // 根据数据量计算每个环上数据的偏移和大小
118 0 : Slice sliceTemp;
119 0 : const u32 rank = i * level1RankSize * level0RankSize + j * level0RankSize + k;
120 0 : sliceTemp.size = counts[rank] * perDataSize;
121 0 : const u64 offset = std::accumulate(counts, counts + rank, 0ULL);
122 0 : sliceTemp.offset = offset * perDataSize; // no displs
123 0 : dataSegsSlice.push_back(sliceTemp);
124 : }
125 : // 机内多环数据切分
126 0 : auto multRingsSliceZeroServer = PrepareMultiRingSlice(dataSegsSlice, param.tag, false, topoAttr_.nicList);
127 0 : if (ringSize == 0) {
128 0 : ringSize = multRingsSliceZeroServer.size();
129 : } else {
130 0 : CHK_PRT_RET(
131 : multRingsSliceZeroServer.size() != ringSize,
132 : HCCL_ERROR(
133 : "[CollAlignedAllGatherVDoubleRingFor91093Executor][PrepareSlicesL0]mismatch "
134 : "ringSize[%u], expect[%u]",
135 : multRingsSliceZeroServer.size(), ringSize),
136 : HCCL_E_PARA);
137 : }
138 0 : multRingsSliceZeroServers.push_back(multRingsSliceZeroServer);
139 0 : }
140 : }
141 0 : multRingsSlice.resize(ringSize);
142 0 : for (u32 k = 0; k < level0RankSize; k++) {
143 0 : for (u32 i = 0; i < level2RankSize; i++) {
144 0 : for (u32 j = 0; j < level1RankSize; j++) { // 按照机内rank的顺序调整数据分片的排布
145 0 : const u32 serverIndex = i * level1RankSize + j;
146 0 : const auto& multRingsSliceZeroServer = multRingsSliceZeroServers[serverIndex];
147 0 : for (u32 ringIndex = 0; ringIndex < ringSize; ringIndex++) {
148 0 : multRingsSlice[ringIndex].push_back(multRingsSliceZeroServer[ringIndex][k]);
149 : }
150 : }
151 : }
152 : }
153 0 : return HCCL_SUCCESS;
154 0 : }
155 :
156 : // AGV不支持MC2的strideCount特性
157 0 : HcclResult CollAlignedAllGatherVDoubleRingFor91093Executor::PrepareUserMemSlices(
158 : std::vector<std::vector<Slice>>& userMemSlices, const std::vector<std::vector<Slice>>& multRingsSlice,
159 : const OpParam& param, const SubCommInfo& level2CommInfo, const SubCommInfo& level1CommInfo,
160 : const SubCommInfo& level0CommInfo, u32 perDataSize, u64 inputMemSize)
161 : {
162 : (void)multRingsSlice;
163 : (void)inputMemSize;
164 0 : const auto* counts = static_cast<u64*>(param.VDataDes.counts);
165 0 : const auto* displs = static_cast<u64*>(param.VDataDes.displs);
166 0 : const u32 level0RankSize = level0CommInfo.localRankSize;
167 0 : const u32 level1RankSize = level1CommInfo.localRankSize;
168 0 : const u32 level2RankSize = level2CommInfo.localRankSize;
169 0 : u32 ringSize = 0;
170 0 : std::vector<std::vector<std::vector<Slice>>> userMemSlicesServers;
171 0 : for (u32 i = 0; i < level2RankSize; i++) {
172 0 : for (u32 j = 0; j < level1RankSize; j++) {
173 0 : std::vector<Slice> dataSegsSlice;
174 0 : for (u32 k = 0; k < level0RankSize; k++) { // 根据数据量计算每个环上数据的偏移和大小
175 0 : Slice sliceTemp;
176 0 : const u32 rank = i * level1RankSize * level0RankSize + j * level0RankSize + k;
177 0 : sliceTemp.size = counts[rank] * perDataSize;
178 0 : sliceTemp.offset = displs[rank] * perDataSize; // with displs
179 0 : dataSegsSlice.push_back(sliceTemp);
180 : }
181 : // 多环数据切分
182 0 : auto userMemSlicesServer = PrepareMultiRingSlice(dataSegsSlice, param.tag, false, topoAttr_.nicList);
183 0 : if (ringSize == 0) {
184 0 : ringSize = userMemSlicesServer.size();
185 : } else {
186 0 : CHK_PRT_RET(
187 : userMemSlicesServer.size() != ringSize,
188 : HCCL_ERROR(
189 : "[CollAlignedAllGatherVDoubleRingFor91093Executor][PrepareUserMemSlices]mismatch "
190 : "ringSize[%u], expect[%u]",
191 : userMemSlicesServer.size(), ringSize),
192 : HCCL_E_PARA);
193 : }
194 0 : userMemSlicesServers.push_back(userMemSlicesServer);
195 0 : }
196 : }
197 0 : userMemSlices.resize(ringSize);
198 0 : for (u32 k = 0; k < level0RankSize; k++) {
199 0 : for (u32 i = 0; i < level2RankSize; i++) {
200 0 : for (u32 j = 0; j < level1RankSize; j++) { // 按照机内rank的顺序调整数据分片的排布
201 0 : const u32 serverIndex = i * level1RankSize + j;
202 0 : const auto& userMemSlicesServer = userMemSlicesServers[serverIndex];
203 0 : for (u32 ringIndex = 0; ringIndex < ringSize; ringIndex++) {
204 0 : userMemSlices[ringIndex].push_back(userMemSlicesServer[ringIndex][k]);
205 : }
206 : }
207 : }
208 : }
209 0 : return HCCL_SUCCESS;
210 0 : }
211 :
212 : REGISTER_EXEC(
213 : "AlignedAllGatherVDoubleRingFor91093Executor", AlignedAllGatherVDoubleRingFor91093,
214 : CollAlignedAllGatherVDoubleRingFor91093Executor);
215 :
216 : } // namespace hccl
|