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 NET_INSTANCE_H
12 : #define NET_INSTANCE_H
13 :
14 : #include <set>
15 : #include <vector>
16 : #include <string>
17 : #include <memory>
18 : #include <unordered_map>
19 : #include <map>
20 : #include <utility>
21 :
22 : #include "graph.h"
23 : #include "ip_address.h"
24 : #include "iterator.h"
25 : #include "types.h"
26 : #include "securec.h"
27 : #include "topo_common_types.h"
28 :
29 : namespace Hccl {
30 : constexpr u32 DEFAULT_LISTENING_PORT = 60001;
31 : // HCCL构建ChannelDesc时会完整复制EndpointLoc,使用其未占用的尾部字节传递拓扑定位信息。
32 : struct EndpointTopoInfo {
33 : u32 magic;
34 : u32 netLayer;
35 : u32 topoInstId;
36 : };
37 :
38 : constexpr u32 ENDPOINT_TOPO_INFO_MAGIC = 0x544F504FU;
39 : constexpr size_t ENDPOINT_LOC_RAW_SIZE = sizeof(((EndpointLoc*)nullptr)->raws);
40 : static_assert(ENDPOINT_LOC_RAW_SIZE >= sizeof(EndpointTopoInfo), "EndpointLoc reserved space is insufficient");
41 : static_assert(
42 : ENDPOINT_LOC_RAW_SIZE - sizeof(EndpointTopoInfo) >= sizeof(((EndpointLoc*)nullptr)->device),
43 : "Endpoint topology info overlaps device location fields");
44 : constexpr size_t ENDPOINT_TOPO_INFO_OFFSET = ENDPOINT_LOC_RAW_SIZE - sizeof(EndpointTopoInfo);
45 :
46 40 : inline HcclResult SetEndpointTopoInfo(EndpointDesc& endpointDesc, u32 netLayer, u32 topoInstId)
47 : {
48 40 : const EndpointTopoInfo topoInfo{ENDPOINT_TOPO_INFO_MAGIC, netLayer, topoInstId};
49 : const errno_t ret
50 40 : = memcpy_s(endpointDesc.loc.raws + ENDPOINT_TOPO_INFO_OFFSET, sizeof(topoInfo), &topoInfo, sizeof(topoInfo));
51 80 : return ret == EOK ? HCCL_SUCCESS : HCCL_E_MEMORY;
52 : }
53 :
54 10 : inline bool GetEndpointTopoInfo(const EndpointDesc& endpointDesc, u32& netLayer, u32& topoInstId)
55 : {
56 10 : EndpointTopoInfo topoInfo{};
57 : const errno_t ret
58 10 : = memcpy_s(&topoInfo, sizeof(topoInfo), endpointDesc.loc.raws + ENDPOINT_TOPO_INFO_OFFSET, sizeof(topoInfo));
59 10 : if (ret != EOK) {
60 0 : return false;
61 : }
62 10 : if (topoInfo.magic != ENDPOINT_TOPO_INFO_MAGIC) {
63 1 : return false;
64 : }
65 :
66 9 : netLayer = topoInfo.netLayer;
67 9 : topoInstId = topoInfo.topoInstId;
68 9 : return true;
69 : }
70 :
71 : // 同一地址和协议可属于不同网络层或拓扑实例,需共同参与Endpoint定位。
72 : struct EndpointKey {
73 : u32 netLayer;
74 : u32 topoInstId;
75 : CommAddr commAddr;
76 : CommProtocol protocol;
77 :
78 0 : bool operator==(const EndpointKey& other) const
79 : {
80 0 : return netLayer == other.netLayer && topoInstId == other.topoInstId && commAddr == other.commAddr
81 0 : && protocol == other.protocol;
82 : }
83 : };
84 :
85 : struct EndpointKeyHash {
86 98 : size_t operator()(const EndpointKey& key) const
87 : {
88 98 : return std::hash<u32>()(key.netLayer) ^ (std::hash<u32>()(key.topoInstId) << 1)
89 98 : ^ (std::hash<CommAddr>()(key.commAddr) << 2) ^ (std::hash<CommProtocol>()(key.protocol) << 3);
90 : }
91 : };
92 : class NetInstance {
93 : public:
94 : class ConnInterface {
95 : public:
96 : // 使用地址信息、位置信息、链路类型、链路协议构造接口
97 1240 : explicit ConnInterface(
98 : const IpAddress inputAddr, const std::set<string> inputPorts, const AddrPosition inputPos,
99 : const LinkType inputLinkType, const std::set<LinkProtocol> inputLinkProtocol,
100 385 : TopoType inputTopoType = TopoType::CLOS, u32 intputTopoInstId = 0)
101 1240 : : addr(inputAddr),
102 1240 : ports(inputPorts),
103 1240 : pos(inputPos),
104 1240 : linkType(inputLinkType),
105 1240 : linkProtocols(inputLinkProtocol),
106 1240 : topoType(inputTopoType),
107 1240 : topoInstId(intputTopoInstId)
108 1240 : {}
109 : IpAddress GetAddr() const;
110 : AddrPosition GetPos() const;
111 : std::set<string> GetPorts() const;
112 : LinkType GetLinkType() const;
113 : std::set<LinkProtocol> GetLinkProtocols() const;
114 : void SetLocalDieId(u32 dieId);
115 : u32 GetLocalDieId() const;
116 : TopoType GetTopoType() const;
117 : u32 GetTopoInstId() const;
118 : std::string Describe() const;
119 : bool operator==(const ConnInterface& rhs) const;
120 : bool operator!=(const ConnInterface& rhs) const;
121 :
122 : private:
123 : IpAddress addr{};
124 : std::set<string> ports{};
125 : AddrPosition pos{};
126 : LinkType linkType{};
127 : std::set<LinkProtocol> linkProtocols{};
128 : u32 localDieId_{};
129 : TopoType topoType{TopoType::CLOS};
130 : u32 topoInstId{0};
131 : };
132 :
133 : class Node {
134 : public:
135 : using EndpointToIfaceMap
136 : = std::unordered_map<EndpointKey, std::shared_ptr<NetInstance::ConnInterface>, EndpointKeyHash>;
137 :
138 1591 : MAKE_ENUM(NodeType, PEER, FABRIC)
139 869 : explicit Node(NodeType nodeType) : type_(nodeType) {}
140 1091 : virtual ~Node() = default;
141 :
142 : void AddConnInterface(u32 layer, const shared_ptr<NetInstance::ConnInterface>& interface);
143 : void AddConnInterfaces(u32 layer, const std::vector<std::shared_ptr<NetInstance::ConnInterface>>& interfaces);
144 : NodeType GetType() const;
145 : std::vector<std::shared_ptr<NetInstance::ConnInterface>> GetIfacesByLayer(u32 layer) const;
146 : std::vector<std::shared_ptr<NetInstance::ConnInterface>> GetIfaces() const;
147 : void SetEndpointToIface(
148 : u32 netLayer, u32 topoInstId, const CommAddr& commAddr, CommProtocol protocol,
149 : const std::shared_ptr<NetInstance::ConnInterface>& iface);
150 : const EndpointToIfaceMap& GetEndpointToIfaceMap() const;
151 : NodeId GetNodeId() const;
152 : string GetNodeIdStr() const;
153 : const std::unordered_map<u32, std::vector<std::shared_ptr<NetInstance::ConnInterface>>>
154 : GetInterfacesMap() const;
155 : virtual std::string Describe() const = 0;
156 :
157 : protected:
158 : NodeId nodeId_{0};
159 :
160 : private:
161 : std::unordered_map<u32, std::vector<std::shared_ptr<NetInstance::ConnInterface>>> interfacesMap_;
162 : EndpointToIfaceMap endpointToIfaceMap_;
163 : NodeType type_;
164 : };
165 :
166 : class Peer : public Node {
167 : public:
168 : using NetInstancePtr = const NetInstance*;
169 805 : Peer(
170 : RankId rankId, LocalId localId, LocalId replacedLocalId, DeviceId deviceId,
171 : u32 devicePort = DEFAULT_LISTENING_PORT, u32 hostPort = DEFAULT_LISTENING_PORT)
172 805 : : Node(NodeType::PEER),
173 805 : rankId_(rankId),
174 805 : localId_(localId),
175 805 : replacedLocalId_(replacedLocalId),
176 805 : deviceId_(deviceId),
177 805 : devicePort_(devicePort),
178 805 : hostPort_(hostPort)
179 : {
180 805 : nodeId_ = GenerateNodeId(rankId);
181 805 : }
182 : static NodeId GenerateNodeId(RankId rankId);
183 : void AddNetInstance(const std::shared_ptr<NetInstance>& NetInstance);
184 : LocalId GetLocalId() const;
185 : LocalId GetReplacedLocalId() const;
186 : RankId GetRankId() const;
187 : DeviceId GetDeviceId() const;
188 : u32 GetDevicePort() const;
189 : u32 GetHostPort() const;
190 : std::set<u32> GetLevels() const;
191 : NetInstancePtr GetNetInstance(u32 level) const;
192 : std::map<std::string, std::vector<IpAddress>> GetPortAddrMapLayer0() const;
193 : bool TryGetLayer0Address(const std::string& port, IpAddress& addr) const;
194 : void SetPortPortAddrMapLayer0(std::map<std::string, std::vector<IpAddress>> portAddrMap);
195 : std::string Describe() const override;
196 :
197 : private:
198 : RankId rankId_;
199 : LocalId localId_;
200 : LocalId replacedLocalId_;
201 : DeviceId deviceId_;
202 : u32 devicePort_;
203 : u32 hostPort_;
204 : std::set<u32> netLayers_;
205 : std::map<std::string, std::vector<IpAddress>> portAddrMapLayer0_{}; // layer0 层端口与IpAddress的映射。
206 : std::vector<NetInstancePtr> netInsts_; // 下标为level,约束:level从0递增
207 : };
208 :
209 : class Fabric : public Node {
210 : public:
211 31 : explicit Fabric(FabricId fabricId, PlaneId planeId)
212 31 : : Node(NodeType::FABRIC),
213 31 : fabricId_(fabricId),
214 31 : planeId_(planeId)
215 : {
216 31 : nodeId_ = GenerateNodeId(fabricId);
217 31 : }
218 :
219 66 : explicit Fabric(FabricId fabricId) : Node(NodeType::FABRIC), fabricId_(fabricId), planeId_("")
220 : {
221 33 : nodeId_ = GenerateNodeId(fabricId);
222 33 : }
223 :
224 : PlaneId GetPlaneId() const;
225 : std::string Describe() const override;
226 :
227 : private:
228 : FabricId fabricId_;
229 : PlaneId planeId_;
230 : NodeId GenerateNodeId(FabricId fabricId) const;
231 : };
232 :
233 : class Link {
234 : public:
235 702 : Link(
236 : std::shared_ptr<NetInstance::Node> source, std::shared_ptr<NetInstance::Node> target,
237 : std::shared_ptr<NetInstance::ConnInterface> sourceIface,
238 : std::shared_ptr<NetInstance::ConnInterface> targetIface, LinkType type,
239 310 : std::set<LinkProtocol> linkProtocols, LinkDirection direction = LinkDirection::BOTH, u32 hop = 1)
240 702 : : source_(source),
241 702 : target_(target),
242 702 : sourceIface_(sourceIface),
243 702 : targetIface_(targetIface),
244 702 : type_(type),
245 702 : linkProtocols_(linkProtocols),
246 702 : direction_(direction),
247 702 : hop_(hop)
248 702 : {}
249 368 : Link() = default;
250 :
251 : u32 GetHop() const;
252 : LinkType GetType() const;
253 : std::set<LinkProtocol> GetLinkProtocols() const;
254 : LinkDirection GetLinkDirection() const;
255 : std::shared_ptr<NetInstance::ConnInterface> GetSourceIface() const;
256 : std::shared_ptr<NetInstance::ConnInterface> GetTargetIface() const;
257 : std::shared_ptr<NetInstance::Node> GetSourceNode() const;
258 : std::shared_ptr<NetInstance::Node> GetTargetNode() const;
259 : std::string Describe() const;
260 : bool IsEmpty() const;
261 :
262 : bool operator==(const Link& rhs) const;
263 : bool operator!=(const Link& rhs) const;
264 :
265 : private:
266 : std::shared_ptr<NetInstance::Node> source_{nullptr};
267 : std::shared_ptr<NetInstance::Node> target_{nullptr};
268 : std::shared_ptr<NetInstance::ConnInterface> sourceIface_{nullptr};
269 : std::shared_ptr<NetInstance::ConnInterface> targetIface_{nullptr}; // 如果target为Fabric节点,则为空
270 : LinkType type_{};
271 : set<LinkProtocol> linkProtocols_{};
272 : LinkDirection direction_{LinkDirection::BOTH};
273 : u32 hop_{1};
274 : };
275 :
276 : struct Path {
277 : std::vector<Link> links;
278 : LinkDirection direction{LinkDirection::BOTH};
279 : };
280 :
281 : struct TopoInstance {
282 : u32 topoInstId{0};
283 : TopoType topoType;
284 : std::set<RankId> ranks;
285 73 : TopoInstance() = default;
286 :
287 186 : TopoInstance(u32 instId) : topoInstId(instId) {}
288 : };
289 :
290 : // FabType: Fabric Group的拓扑类型,目前仅支持INNER与CLOS类型
291 : // INNER: 同Inner Group内Rank间互联
292 : // CLOS: 不同Rank经Fabric互联
293 : MAKE_ENUM(FabType, INNER, CLOS);
294 : std::unordered_map<u32, std::shared_ptr<TopoInstance>> topoInsts_;
295 :
296 : NetInstance(const u32 netLayer, const std::string& netInstId, const NetType netType);
297 312 : virtual ~NetInstance() = default;
298 :
299 : u32 GetNetLayer() const;
300 : std::string GetNetInstId() const;
301 : NetType GetNetType() const;
302 : std::set<RankId> GetRankIds() const;
303 : u32 GetRankSize() const;
304 : bool HasNode(const NodeId nodeId) const;
305 : const std::unordered_map<RankId, std::shared_ptr<Peer>>& GetPeers() const;
306 : const std::vector<std::shared_ptr<Fabric>>& GetFabrics() const;
307 : Graph<Node, Link>& GetGraph();
308 : void AddRankId(const RankId rankId);
309 : void AddNode(const std::shared_ptr<Node>& node);
310 : void AddLink(const std::shared_ptr<Link>& link);
311 : void DeleteLink(const NodeId srcNodeId, const NodeId dstNodeId);
312 :
313 : void UpdateTopoInst(u32 topoInstId, TopoType topoType, RankId rankId);
314 : void GetTopoInstsByLayer(std::vector<u32>& topoInsts, u32& topoInstNum) const;
315 : HcclResult GetTopoType(const u32 topoInstId, TopoType& topoType) const;
316 : HcclResult GetRanksByTopoInst(const u32 topoInstId, std::vector<u32>& ranks, u32& rankNum) const;
317 : virtual std::vector<Path> GetPaths(const RankId srcRankId, const RankId dstRankId) const = 0;
318 : std::string Describe() const;
319 :
320 : protected:
321 : u32 netLayer{0};
322 : std::string netInstId{""};
323 : NetType netType{NetType::CLOS};
324 : std::set<RankId> rankIds;
325 : std::unordered_map<RankId, std::shared_ptr<Peer>> peers;
326 : std::unordered_map<LocalId, RankId> localIdsMap;
327 : std::vector<std::shared_ptr<Fabric>> fabrics;
328 : std::unordered_map<PlaneId, NodeId> planeId2Node; // 除了创建时,其他是否需要使用
329 : Graph<Node, Link> vGraph;
330 :
331 : void AddPeer(const std::shared_ptr<Peer>& peer);
332 : void AddFabric(const std::shared_ptr<Fabric>& fabric);
333 : };
334 :
335 : class InnerNetInstance : public NetInstance {
336 : public:
337 256 : InnerNetInstance(const u32 netLayer, const std::string& netInstId)
338 256 : : NetInstance(netLayer, netInstId, NetType::TOPO_FILE_DESC) {};
339 :
340 257 : ~InnerNetInstance() override = default;
341 :
342 : std::vector<Path> GetPaths(const RankId srcRankId, const RankId dstRankId) const override;
343 : };
344 :
345 : class ClosNetInstance : public NetInstance {
346 : public:
347 56 : ClosNetInstance(const u32 netLayer, const std::string& netInstId)
348 56 : : NetInstance(netLayer, netInstId, NetType::CLOS) {};
349 :
350 57 : ~ClosNetInstance() override = default;
351 :
352 : std::vector<Path> GetPaths(const RankId srcRankId, const RankId dstRankId) const override;
353 : };
354 :
355 : } // namespace Hccl
356 :
357 : #endif // NET_INSTANCE_H
|