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 <algorithm>
12 : #include "nonuniform_hierarchical_ring_base.h"
13 :
14 : namespace hccl {
15 :
16 16 : NHRBase::NHRBase(const HcclDispatcher dispatcher)
17 16 : : AlgTemplateBase(dispatcher)
18 : {
19 16 : }
20 :
21 16 : NHRBase::~NHRBase()
22 : {
23 16 : }
24 :
25 0 : void NHRBase::GetRankMapping(const u32 rankSize, bool keepOrder)
26 : {
27 0 : std::vector<u32> tree;
28 0 : for (u32 i = 0; i < rankSize; i++) {
29 0 : tree.push_back(i);
30 : }
31 :
32 0 : if (keepOrder) {
33 0 : HCCL_DEBUG("[NHRBase][GetRankMapping] keep order and disable tree mapping, just return");
34 0 : sliceMap_ = tree;
35 0 : return;
36 : }
37 :
38 : // 其他的再进行计算
39 0 : std::vector<u32> tmp(rankSize);
40 0 : u32 nSteps = GetStepNumInterServer(rankSize);
41 :
42 0 : u32 len = rankSize;
43 :
44 0 : for (u32 step = 0; step < nSteps; step++) {
45 0 : u32 nSlices = (rankSize - 1 + (1 << step)) / (1 << (step + 1));
46 0 : if (nSlices <= 1) {
47 0 : break;
48 : }
49 :
50 0 : bool endFlag = false;
51 :
52 0 : for (u32 part = 0; part * len < rankSize; part++) {
53 0 : u32 start = part * len;
54 0 : u32 end = std::min(start + len, rankSize);
55 0 : ReorderSequence(start, end, len, tree, tmp);
56 :
57 0 : if (((end - start) & 1) == 1) {
58 0 : endFlag = true;
59 : }
60 : }
61 :
62 0 : for (u32 i = 0; i < rankSize; i++) {
63 0 : tree[i] = tmp[i];
64 : }
65 :
66 0 : if (endFlag) {
67 0 : break;
68 : }
69 :
70 0 : len >>= 1;
71 : }
72 :
73 : // 因为取的是tree中rank的idx,所以直接返回反向的映射
74 0 : sliceMap_.resize(rankSize);
75 0 : for (u32 i = 0; i < rankSize; i++) {
76 0 : sliceMap_[tree[i]] = i;
77 : }
78 :
79 0 : return;
80 0 : }
81 :
82 0 : void NHRBase::FetchRankMapping(std::vector<u32> &sliceMap)
83 : {
84 0 : sliceMap = sliceMap_;
85 0 : }
86 :
87 0 : void NHRBase::ReorderSequence(u32 start, u32 end, u32 len, std::vector<u32> &tree, std::vector<u32> &tmp)
88 : {
89 0 : const u32 DIVIDE_TWO = 2;
90 :
91 0 : for (u32 i = start; i < end; i++) {
92 0 : u32 offset = i - start;
93 0 : if ((offset & 1) == 0) {
94 0 : tmp[start + offset / DIVIDE_TWO] = tree[i];
95 : } else {
96 0 : tmp[start + (offset + len) / DIVIDE_TWO] = tree[i];
97 : }
98 : }
99 0 : }
100 :
101 : // 合并连续的内存块,slice数量可能会因此减少
102 0 : void NHRBase::MergeSlices(std::vector<Slice> &slices)
103 : {
104 0 : if (!isNeedMerge) {
105 0 : return;
106 : }
107 :
108 0 : if (slices.size() <= 1) {
109 0 : return;
110 : }
111 :
112 0 : std::sort(slices.begin(), slices.end(), [](const Slice &s1, const Slice &s2) {
113 0 : return s1.offset == s2.offset ? s1.size < s2.size : s1.offset < s2.offset;
114 : });
115 :
116 0 : u32 mergedIdx = 0;
117 0 : u64 tmpSliceOffset = slices[0].offset;
118 0 : u64 tmpSliceSize = slices[0].size;
119 0 : for (u32 i = 1; i < slices.size(); i++) {
120 0 : if (tmpSliceOffset + tmpSliceSize == slices[i].offset) {
121 : // 合并到上一块中
122 0 : tmpSliceSize += slices[i].size;
123 : } else {
124 : // 上一块先存储
125 0 : slices[mergedIdx].size = tmpSliceSize;
126 0 : slices[mergedIdx].offset = tmpSliceOffset;
127 0 : mergedIdx += 1;
128 :
129 : // 记录当前新的一块
130 0 : tmpSliceSize = slices[i].size;
131 0 : tmpSliceOffset = slices[i].offset;
132 : }
133 : }
134 :
135 : // 可能有size为0的片段,不判断slicesize > 0
136 0 : slices[mergedIdx].size = tmpSliceSize;
137 0 : slices[mergedIdx].offset = tmpSliceOffset;
138 0 : mergedIdx += 1;
139 :
140 : // 原地清理
141 0 : slices.erase(slices.begin() + mergedIdx, slices.end());
142 :
143 0 : return;
144 : }
145 :
146 : // NHR的算法步数
147 6 : u32 NHRBase::GetStepNumInterServer(u32 rankSize)
148 : {
149 6 : u32 nSteps = 0;
150 24 : for (u32 tmp = rankSize - 1; tmp != 0; tmp >>= 1, nSteps++) {
151 : }
152 6 : HCCL_DEBUG("[NHRBase][GetStepNumInterServer] rankSize[%u] nSteps[%u]", rankSize, nSteps);
153 :
154 6 : return nSteps;
155 : }
156 :
157 : // NHR每步的算法描述原理函数
158 0 : HcclResult NHRBase::GetStepInfo(u32 step, u32 nSteps, u32 rank, u32 rankSize, InterServerAlgoStep &stepInfo)
159 : {
160 : (void)step;
161 : (void)nSteps;
162 : (void)rank;
163 : (void)rankSize;
164 : (void)stepInfo;
165 0 : return HCCL_SUCCESS;
166 : }
167 :
168 0 : HcclResult NHRBase::ExecuteBarrier(const std::shared_ptr<Transport> &preLink, const std::shared_ptr<Transport> &aftLink)
169 : {
170 0 : CHK_RET(preLink->TxAck(stream_));
171 0 : CHK_RET(aftLink->RxAck(stream_));
172 :
173 0 : CHK_RET(aftLink->TxDataSignal(stream_));
174 0 : CHK_RET(preLink->RxDataSignal(stream_));
175 :
176 0 : CHK_RET(preLink->PostFinAck(stream_));
177 0 : CHK_RET(aftLink->WaitFinAck(stream_));
178 :
179 0 : return HCCL_SUCCESS;
180 : }
181 : } // ~~ namespace hccl
|