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 "phy_topo.h"
12 : #include "exception_util.h"
13 : #include "internal_exception.h"
14 : namespace Hccl {
15 :
16 438 : std::unique_ptr<PhyTopo> &PhyTopo::GetInstance()
17 : {
18 438 : static std::unique_ptr<PhyTopo> topo = std::make_unique<PhyTopo>();
19 438 : return topo;
20 : }
21 :
22 19 : void PhyTopo::InitFinish()
23 : {
24 19 : initFlag = true;
25 19 : }
26 :
27 33 : bool PhyTopo::IsInitFinished() const
28 : {
29 33 : return initFlag;
30 : }
31 :
32 26 : void PhyTopo::Clear()
33 : {
34 26 : topos.clear();
35 26 : initFlag = false;
36 26 : }
37 :
38 42 : void PhyTopo::AddTopoGraph(const u32 netLayer, std::shared_ptr<Graph<PhyTopo::Node, PhyTopo::Link>> topo)
39 : {
40 42 : if (!initFlag) {
41 42 : topos[netLayer] = topo;
42 126 : HCCL_DEBUG("[PhyTopo]add topo success, netLayer [%u], topo size is [%zu]", netLayer, topos.size());
43 : } else {
44 0 : THROW<InternalException>("PhyTopo AddTopoGraph fail. PhyTopo has been initialized "
45 : "and cannot be changed, please check.");
46 : }
47 42 : }
48 :
49 173 : std::shared_ptr<Graph<PhyTopo::Node, PhyTopo::Link>> PhyTopo::GetTopoGraph(const u32 netLayer) const
50 : {
51 173 : if (topos.find(netLayer) == topos.end()) {
52 5 : return nullptr;
53 : }
54 168 : return topos.at(netLayer);
55 : }
56 :
57 136 : bool PhyTopo::IsNetLayerExisted(const u32 netLayer) const
58 : {
59 136 : if (topos.find(netLayer) == topos.end()) {
60 1 : return false;
61 : }
62 135 : return true;
63 : }
64 :
65 19 : void PhyTopo::Dump() const
66 : {
67 57 : HCCL_DEBUG("PhyTopo Dump:");
68 54 : for (auto &pair : topos) {
69 105 : HCCL_DEBUG("netLayer[%u]:", pair.first);
70 105 : HCCL_DEBUG("nodes:");
71 35 : std::set<NodeId> nodeIds{};
72 35 : pair.second->TraverseNode([&](NodeId nodeId, std::shared_ptr<PhyTopo::Node> node) {
73 140 : nodeIds.insert(nodeId);
74 420 : HCCL_DEBUG("%s", node->Describe().c_str());
75 140 : });
76 105 : HCCL_DEBUG("links:");
77 175 : for (NodeId nodeId : nodeIds) {
78 140 : pair.second->TraverseEdge(nodeId,
79 1884 : [&](std::shared_ptr<Link> link) { HCCL_DEBUG("%s", link->Describe().c_str()); });
80 : }
81 35 : }
82 19 : }
83 :
84 911 : PhyTopo::ConnInterface::ConnInterface(const std::set<std::string> inputPorts, const AddrPosition inputPos,
85 911 : const LinkType inputLinkType, const std::set<LinkProtocol> inputLinkProtocols)
86 911 : : ports(inputPorts),
87 911 : pos(inputPos),
88 911 : linkType(inputLinkType),
89 911 : linkProtocols(inputLinkProtocols)
90 : {
91 911 : }
92 :
93 479 : std::set<std::string> PhyTopo::ConnInterface::GetPorts() const
94 : {
95 479 : return ports;
96 : }
97 :
98 475 : AddrPosition PhyTopo::ConnInterface::GetPos() const
99 : {
100 475 : return pos;
101 : }
102 :
103 1 : LinkType PhyTopo::ConnInterface::GetLinkType() const
104 : {
105 1 : return linkType;
106 : }
107 :
108 1197 : std::set<LinkProtocol> PhyTopo::ConnInterface::GetLinkProtocols() const
109 : {
110 1197 : return linkProtocols;
111 : }
112 :
113 1394 : std::string PhyTopo::ConnInterface::Describe() const
114 : {
115 1394 : std::string portsStr;
116 1984 : for (auto it = ports.begin(); it != ports.end(); ++it) {
117 590 : if (it != ports.begin()) {
118 84 : portsStr += ",";
119 : }
120 590 : portsStr += *it;
121 : }
122 1394 : std::string protocolStr;
123 2788 : for (auto it = linkProtocols.begin(); it != linkProtocols.end(); ++it) {
124 1394 : if (!protocolStr.empty()) {
125 0 : protocolStr += ", ";
126 : }
127 1394 : protocolStr += it->Describe();
128 : }
129 :
130 : return StringFormat("ConnInterface[ports={%s}, pos=%s, protocols={%s}, linkType=%s]", portsStr.c_str(),
131 2788 : pos.Describe().c_str(), protocolStr.c_str(), linkType.Describe().c_str());
132 1394 : }
133 :
134 1397 : bool PhyTopo::ConnInterface::operator==(const ConnInterface &rhs) const
135 : {
136 1397 : return ports == rhs.ports && pos == rhs.pos && linkType == rhs.linkType && linkProtocols == rhs.linkProtocols;
137 : }
138 :
139 1 : bool PhyTopo::ConnInterface::operator!=(const ConnInterface &rhs) const
140 : {
141 1 : return !(rhs == *this);
142 : }
143 :
144 164 : PhyTopo::Node::Node(const PhyTopo::Node::NodeType inputType) : type(inputType) {}
145 :
146 4 : PhyTopo::Node::NodeType PhyTopo::Node::GetType() const
147 : {
148 4 : return type;
149 : }
150 :
151 904 : void PhyTopo::Node::AddConnInterface(const std::shared_ptr<PhyTopo::ConnInterface> &interface)
152 : {
153 1791 : for (const auto &iface : interfaces) {
154 1395 : if (*iface == *interface) {
155 1524 : HCCL_WARNING("[PhyTopo][Node][AddConnInterface] %s has existed.",
156 : interface->Describe().c_str());
157 508 : return;
158 : }
159 : }
160 396 : interfaces.emplace_back(interface);
161 : }
162 :
163 0 : PhyTopo::Node::IfaceIterator PhyTopo::Node::IterIfaces() const
164 : {
165 0 : return PhyTopo::Node::IfaceIterator(interfaces);
166 : }
167 :
168 0 : std::string PhyTopo::Node::Describe() const
169 : {
170 0 : return "PhyTopo::Node[]";
171 : }
172 :
173 127 : PhyTopo::Peer::Peer(const LocalId localId) : Node(PhyTopo::Node::NodeType::PEER), localId(localId) {}
174 :
175 2 : LocalId PhyTopo::Peer::GetLocalId() const
176 : {
177 2 : return localId;
178 : }
179 :
180 889 : NodeId PhyTopo::Peer::GetId(const LocalId localId)
181 : {
182 889 : return static_cast<NodeId>(localId);
183 : }
184 :
185 671 : std::string PhyTopo::Peer::Describe() const
186 : {
187 671 : return StringFormat("PhyTopo::Peer[localId=%u]", localId);
188 : }
189 :
190 26 : PhyTopo::Fabric::Fabric() : Node(PhyTopo::Node::NodeType::FABRIC) {}
191 :
192 : constexpr s32 FABRIC_ID_OFFSET = 32;
193 612 : NodeId PhyTopo::Fabric::GetId()
194 : {
195 612 : NodeId res = static_cast<NodeId>(0);
196 612 : res |= (1ULL << FABRIC_ID_OFFSET);
197 612 : return res;
198 : }
199 :
200 355 : std::string PhyTopo::Fabric::Describe() const
201 : {
202 355 : return StringFormat("PhyTopo::Fabric[NodeId=%llu]", GetId());
203 : }
204 :
205 457 : PhyTopo::Link::Link(std::shared_ptr<PhyTopo::Node> inputSource, std::shared_ptr<PhyTopo::Node> inputTarget,
206 : const LinkAttributes& properties,
207 457 : const TopoType inputTopoType, const u32 inputTopoInstId)
208 457 : : sourceIface(nullptr),
209 457 : targetIface(nullptr),
210 457 : source(inputSource),
211 457 : target(inputTarget),
212 457 : linkProtocols(properties.protocols),
213 457 : linkType(properties.linktype),
214 457 : direction(LinkDirection::BOTH),
215 457 : topoType(inputTopoType),
216 457 : topoInstId(inputTopoInstId),
217 457 : hop{1}
218 : {
219 457 : }
220 :
221 452 : void PhyTopo::Link::SetSourceIface(std::shared_ptr<PhyTopo::ConnInterface> inputSourceIface)
222 : {
223 452 : sourceIface = inputSourceIface;
224 452 : }
225 :
226 454 : void PhyTopo::Link::SetTargetIface(std::shared_ptr<PhyTopo::ConnInterface> inputTargetIface)
227 : {
228 454 : targetIface = inputTargetIface;
229 454 : }
230 :
231 1 : LinkType PhyTopo::Link::GetType() const
232 : {
233 1 : return linkType;
234 : }
235 :
236 617 : std::set<LinkProtocol> PhyTopo::Link::GetLinkProtocols() const
237 : {
238 617 : return linkProtocols;
239 : }
240 :
241 1 : LinkDirection PhyTopo::Link::GetLinkDirection() const
242 : {
243 1 : return direction;
244 : }
245 :
246 545 : TopoType PhyTopo::Link::GetTopoType() const
247 : {
248 545 : return topoType;
249 : }
250 :
251 593 : u32 PhyTopo::Link::GetTopoInstId() const
252 : {
253 593 : return topoInstId;
254 : }
255 :
256 1 : u32 PhyTopo::Link::GetHop() const
257 : {
258 1 : return hop;
259 : }
260 :
261 520 : std::shared_ptr<PhyTopo::ConnInterface> PhyTopo::Link::GetSourceIFace()
262 : {
263 520 : return sourceIface;
264 : }
265 :
266 128 : std::shared_ptr<PhyTopo::ConnInterface> PhyTopo::Link::GetTargetIFace()
267 : {
268 128 : return targetIface;
269 : }
270 :
271 1 : std::shared_ptr<PhyTopo::Node> PhyTopo::Link::GetSourceNode()
272 : {
273 1 : return source;
274 : }
275 :
276 1 : std::shared_ptr<PhyTopo::Node> PhyTopo::Link::GetTargetNode()
277 : {
278 1 : return target;
279 : }
280 :
281 443 : std::string PhyTopo::Link::Describe() const
282 : {
283 443 : std::stringstream iFace;
284 443 : if (sourceIface != nullptr) {
285 443 : iFace << ", sourceIface=" << sourceIface->Describe();
286 : }
287 443 : if (targetIface != nullptr) {
288 443 : iFace << ", targetIface=" << targetIface->Describe();
289 : }
290 :
291 : // 将 linkProtocol 转换为字符串
292 443 : std::string protocolStr;
293 886 : for (auto it = linkProtocols.begin(); it != linkProtocols.end(); ++it) {
294 443 : if (!protocolStr.empty()) {
295 0 : protocolStr += ", ";
296 : }
297 443 : protocolStr += it->Describe();
298 : }
299 :
300 886 : return StringFormat("PhyTopo::Link[type=%s, protocol=%s, source=%s, target=%s%s, topoInstId=%u, topoType=%d]", linkType.Describe().c_str(),
301 1329 : protocolStr.c_str(), source->Describe().c_str(), target->Describe().c_str(),
302 2658 : iFace.str().c_str(), topoInstId, topoType);
303 443 : }
304 : } // namespace Hccl
|