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 : #ifndef HCCLV2_VIRTUAL_TOPO_H
12 : #define HCCLV2_VIRTUAL_TOPO_H
13 :
14 : #include <cassert>
15 : #include <map>
16 : #include <set>
17 : #include <cstdint>
18 : #include "port.h"
19 : #include "iterator.h"
20 : #include "dev_type.h"
21 : #include "log.h"
22 : #include "net_instance.h"
23 : #include "rank_gph.h"
24 :
25 : namespace Hccl {
26 :
27 : using namespace std;
28 :
29 : MAKE_ENUM(PeerType, CPU, NPU)
30 :
31 : static constexpr u32 MAX_LINK_PATH_NUM = 2;
32 :
33 : class LinkData {
34 : public:
35 : // 待修改 构造函数不对外开发,LinkData只能由Link生成
36 577 : LinkData(BasePortType portType, RankId localRankId, RankId remoteRankId, u32 localPortId, u32 remotePortId)
37 577 : : type(portType.GetType()), linkProtocol_(ConnProto2LinkProtocol(portType.GetProto())), localRankId_(localRankId),
38 577 : remoteRankId_(remoteRankId), localPortId_(localPortId), remotePortId_(remotePortId){};
39 166 : LinkData(PortDeploymentType portDeploymentType, LinkProtocol linkProtocol, RankId localRankId,
40 : RankId remoteRankId, IpAddress localAddr, IpAddress remoteAddr, u32 devicePhyId = 0, u32 remoteDevicePhyId = 0, u32 reuseIdx = 0)
41 166 : : type(portDeploymentType), linkProtocol_(linkProtocol), localRankId_(localRankId), remoteRankId_(remoteRankId),
42 166 : localAddr_(localAddr), remoteAddr_(remoteAddr), localDeviceId_(devicePhyId), remoteDeviceId_(remoteDevicePhyId), reuseIdx_(reuseIdx) {};
43 :
44 42 : explicit LinkData(const NetInstance::Path &path)
45 42 : {
46 42 : if (path.links.size() == 1) {
47 42 : auto link = path.links[0];
48 42 : auto srcPeer = link.GetSourceNode();
49 42 : auto targetPeer = link.GetTargetNode();
50 42 : shared_ptr<NetInstance::ConnInterface> srcConnIface = link.GetSourceIface();
51 42 : auto targetConnIface = link.GetTargetIface();
52 42 : linkProtocol_ = *link.GetLinkProtocols().begin();
53 42 : type = AddrPos2PortDeploymentType(srcConnIface->GetPos(), linkProtocol_);
54 42 : localRankId_ = std::dynamic_pointer_cast<NetInstance::Peer>(srcPeer)->GetRankId();
55 42 : remoteRankId_ = std::dynamic_pointer_cast<NetInstance::Peer>(targetPeer)->GetRankId();
56 42 : localDeviceId_ = std::dynamic_pointer_cast<NetInstance::Peer>(srcPeer)->GetDeviceId();
57 42 : remoteDeviceId_ = std::dynamic_pointer_cast<NetInstance::Peer>(targetPeer)->GetDeviceId();
58 42 : localAddr_ = srcConnIface->GetAddr();
59 42 : remoteAddr_ = targetConnIface->GetAddr();
60 42 : localDieId_ = srcConnIface->GetLocalDieId();
61 42 : hop = path.links[0].GetHop();
62 42 : fullmesh = true; // 单链路场景,标识为fullmesh
63 42 : } else if (path.links.size() == MAX_LINK_PATH_NUM) {
64 0 : auto link0 = path.links[0];
65 0 : auto link1 = path.links[1];
66 0 : auto srcPeer = link0.GetSourceNode();
67 0 : auto targetPeer = link1.GetTargetNode();
68 0 : auto srcConnIface = link0.GetSourceIface();
69 0 : auto targetConnIface = link1.GetTargetIface();
70 0 : linkProtocol_ = *link0.GetLinkProtocols().begin();
71 0 : type = AddrPos2PortDeploymentType(srcConnIface->GetPos(), linkProtocol_);
72 0 : localRankId_ = std::dynamic_pointer_cast<NetInstance::Peer>(srcPeer)->GetRankId();
73 0 : remoteRankId_ = std::dynamic_pointer_cast<NetInstance::Peer>(targetPeer)->GetRankId();
74 0 : localDeviceId_ = std::dynamic_pointer_cast<NetInstance::Peer>(srcPeer)->GetDeviceId();
75 0 : remoteDeviceId_ = std::dynamic_pointer_cast<NetInstance::Peer>(targetPeer)->GetDeviceId();
76 0 : localAddr_ = srcConnIface->GetAddr();
77 0 : remoteAddr_ = targetConnIface->GetAddr();
78 0 : localDieId_ = srcConnIface->GetLocalDieId();
79 0 : hop = path.links[0].GetHop();
80 0 : portGroupSize = static_cast<u8>(srcConnIface->GetPorts().size());
81 0 : auto tgtPortGroupSize = static_cast<u8>(targetConnIface->GetPorts().size());
82 0 : if (portGroupSize != tgtPortGroupSize) {
83 0 : HCCL_WARNING("[LinkData][Constructor]srcConnIface.portGroupSize[%u] \
84 : is not euqal to targetConnIface.portGroupSize[%u]",static_cast<u32>(portGroupSize),
85 : static_cast<u32>(tgtPortGroupSize));
86 : }
87 0 : fullmesh = false; // 多链路场景,非fullmesh
88 0 : } else {
89 0 : HCCL_ERROR("[LinkData][Constructor]path.links.size()[%u] is invalid", path.links.size());
90 0 : fullmesh = false; // 无效场景,默认为false
91 : }
92 42 : UpdateIpAddrWithPCIE();
93 42 : direction = path.direction;
94 :
95 42 : localPortId_ = 0;
96 42 : remotePortId_ = 0;
97 42 : }
98 :
99 : explicit LinkData(vector<char> &data);
100 :
101 : std::vector<char> GetUniqueId() const;
102 :
103 453 : bool operator==(const LinkData &rhs) const
104 : {
105 906 : return type == rhs.type && linkProtocol_ == rhs.linkProtocol_ && localRankId_ == rhs.localRankId_
106 453 : && remoteRankId_ == rhs.remoteRankId_ && localAddr_ == rhs.localAddr_
107 453 : && remoteAddr_ == rhs.remoteAddr_ && hop == rhs.hop && direction == rhs.direction
108 906 : && portGroupSize == rhs.portGroupSize && fullmesh == rhs.fullmesh && reuseIdx_ == rhs.reuseIdx_;
109 : }
110 :
111 : bool operator!=(const LinkData &rhs) const
112 : {
113 : return !(rhs == *this);
114 : }
115 :
116 32 : bool operator<(const LinkData &rhs) const
117 : {
118 32 : if (type < rhs.type) {
119 0 : return true;
120 : }
121 32 : if (rhs.type < type) {
122 0 : return false;
123 : }
124 32 : if (linkProtocol_ < rhs.linkProtocol_) {
125 0 : return true;
126 : }
127 32 : if (rhs.linkProtocol_ < linkProtocol_) {
128 0 : return false;
129 : }
130 32 : if (localRankId_ < rhs.localRankId_) {
131 0 : return true;
132 : }
133 32 : if (rhs.localRankId_ < localRankId_) {
134 0 : return false;
135 : }
136 32 : if (remoteRankId_ < rhs.remoteRankId_) {
137 16 : return true;
138 : }
139 16 : if (rhs.remoteRankId_ < remoteRankId_) {
140 6 : return false;
141 : }
142 10 : if (localAddr_ < rhs.localAddr_) {
143 0 : return true;
144 : }
145 10 : if (rhs.localAddr_ < localAddr_) {
146 0 : return false;
147 : }
148 10 : if (remoteAddr_ < rhs.remoteAddr_) {
149 0 : return true;
150 : }
151 10 : if (rhs.remoteAddr_ < remoteAddr_) {
152 0 : return false;
153 : }
154 10 : if (hop < rhs.hop) {
155 0 : return true;
156 : }
157 10 : if (rhs.hop < hop) {
158 0 : return false;
159 : }
160 10 : if (direction < rhs.direction) {
161 0 : return true;
162 : }
163 10 : if (rhs.direction < direction) {
164 0 : return false;
165 : }
166 10 : if (rhs.portGroupSize < portGroupSize) {
167 0 : return false;
168 : }
169 10 : if (fullmesh == false && rhs.fullmesh == true) {
170 0 : return true;
171 : }
172 10 : if (rhs.fullmesh == false && fullmesh == true) {
173 0 : return false;
174 : }
175 10 : if (localPortId_ < rhs.localPortId_) {
176 0 : return true;
177 : }
178 10 : if (rhs.localPortId_ < localPortId_) {
179 0 : return false;
180 : }
181 10 : if (reuseIdx_ < rhs.reuseIdx_) {
182 0 : return true;
183 : }
184 10 : if (rhs.reuseIdx_ < reuseIdx_) {
185 0 : return false;
186 : }
187 10 : return remotePortId_ < rhs.remotePortId_;
188 : }
189 :
190 1564 : string Describe() const
191 : {
192 : return StringFormat("LinkData:type=%s, protocol=%s, localRankId=%d, localAddr=%s, remoteRankId=%d, "
193 : "remoteAddr=%s, reuseIdx=%u",
194 4692 : type.Describe().c_str(), linkProtocol_.Describe().c_str(), localRankId_,
195 6256 : localAddr_.Describe().c_str(), remoteRankId_, remoteAddr_.Describe().c_str(), reuseIdx_);
196 : };
197 :
198 340 : PortData GetLocalPort() const
199 : {
200 340 : return {localRankId_, type, LinkProtocol2LinkProtoType(linkProtocol_), localPortId_, localAddr_};
201 : };
202 :
203 243 : PortData GetRemotePort() const
204 : {
205 243 : return {remoteRankId_, type, LinkProtocol2LinkProtoType(linkProtocol_), remotePortId_, remoteAddr_};
206 : };
207 :
208 : bool IsSymetric(const LinkData &rhs) const
209 : {
210 : return (type == rhs.type) && (linkProtocol_ == rhs.linkProtocol_) && (localRankId_ == rhs.remoteRankId_)
211 : && (remoteRankId_ == rhs.localRankId_) && (localAddr_ == rhs.remoteAddr_)
212 : && (remoteAddr_ == rhs.localAddr_) && (hop == rhs.hop) && (direction == rhs.direction);
213 : };
214 :
215 1381 : const PortDeploymentType &GetType() const
216 : {
217 1381 : return type;
218 : };
219 :
220 1388 : const LinkProtocol &GetLinkProtocol() const
221 : {
222 1388 : return linkProtocol_;
223 : }
224 :
225 2 : u32 GetHop() const
226 : {
227 2 : return hop;
228 : }
229 :
230 0 : LinkDirection GetDirection() const
231 : {
232 0 : return direction;
233 : }
234 :
235 2308 : RankId GetLocalRankId() const
236 : {
237 2308 : return localRankId_;
238 : };
239 :
240 2667 : RankId GetRemoteRankId() const
241 : {
242 2667 : return remoteRankId_;
243 : };
244 :
245 0 : DeviceId GetRemoteDeviceId() const
246 : {
247 0 : return remoteDeviceId_;
248 : };
249 :
250 1173 : u32 GetLocalPortId() const
251 : {
252 1173 : return localPortId_;
253 : };
254 :
255 1173 : u32 GetRemotePortId() const
256 : {
257 1173 : return remotePortId_;
258 : };
259 :
260 2167 : const IpAddress &GetLocalAddr() const
261 : {
262 2167 : return localAddr_;
263 : };
264 :
265 1943 : const IpAddress &GetRemoteAddr() const
266 : {
267 1943 : return remoteAddr_;
268 : };
269 :
270 16 : u32 GetLocalDieId() const
271 : {
272 16 : return localDieId_;
273 : };
274 :
275 1173 : u8 GetPortGroupSize() const
276 : {
277 1173 : return portGroupSize;
278 : };
279 :
280 : bool Readable() const
281 : {
282 : return readable;
283 : };
284 :
285 : bool Writable() const
286 : {
287 : return writable;
288 : };
289 : void UpdateIpAddrWithPCIE();
290 :
291 1392 : bool GetFullmesh() const
292 : {
293 1392 : return fullmesh;
294 : };
295 :
296 25 : std::string GetReuseIdx() const
297 : {
298 25 : return std::to_string(reuseIdx_);
299 : };
300 :
301 : private:
302 : PortDeploymentType type;
303 : LinkProtocol linkProtocol_;
304 : RankId localRankId_{0};
305 : RankId remoteRankId_{0};
306 : u32 localPortId_{0};
307 : u32 remotePortId_{0};
308 : IpAddress localAddr_;
309 : IpAddress remoteAddr_;
310 : bool readable{true};
311 : bool writable{true};
312 : u32 hop{0};
313 : LinkDirection direction;
314 : u32 localDieId_{};
315 : u8 portGroupSize{1};
316 : DeviceId localDeviceId_{UINT32_MAX};
317 : DeviceId remoteDeviceId_{UINT32_MAX};
318 : bool fullmesh{false}; // 标识是否为全互联单链路场景
319 : u32 reuseIdx_{0}; // socket复用idx,加在socket建链tag后面
320 : };
321 : } // namespace Hccl
322 :
323 : namespace std {
324 :
325 : template <> class hash<Hccl::LinkData> {
326 : public:
327 1173 : size_t operator()(const Hccl::LinkData &linkData) const
328 : {
329 1173 : auto typeHash = hash<uint8_t>{}(linkData.GetType());
330 1173 : auto linkProtoHash = hash<uint8_t>{}(linkData.GetLinkProtocol());
331 1173 : auto localRankIdHash = hash<Hccl::RankId>{}(linkData.GetLocalRankId());
332 1173 : auto remoteRankIdHash = hash<Hccl::RankId>{}(linkData.GetRemoteRankId());
333 1173 : auto localPortIdHash = hash<u32>{}(linkData.GetLocalPortId());
334 1173 : auto remotePortIdHash = hash<u32>{}(linkData.GetRemotePortId());
335 1173 : auto localAddrHash = hash<Hccl::IpAddress>{}(linkData.GetLocalAddr());
336 1173 : auto remoteAddrHash = hash<Hccl::IpAddress>{}(linkData.GetRemoteAddr());
337 1173 : auto portGrpSizeHash = hash<uint8_t>{}(linkData.GetPortGroupSize());
338 1173 : auto fullmeshHash = hash<bool>{}(linkData.GetFullmesh());
339 :
340 2346 : return Hccl::HashCombine({typeHash, linkProtoHash, localRankIdHash, remoteRankIdHash,
341 : localPortIdHash, remotePortIdHash, localAddrHash, remoteAddrHash, portGrpSizeHash,
342 2346 : fullmeshHash});
343 : }
344 : };
345 : } // namespace std
346 :
347 : #endif // HCCLV2_VIRTUAL_TOPO_H
|