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