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 355 : std::unique_ptr<PhyTopo> &PhyTopo::GetInstance()
17 : {
18 355 : static std::unique_ptr<PhyTopo> topo = std::make_unique<PhyTopo>();
19 355 : return topo;
20 : }
21 :
22 15 : void PhyTopo::InitFinish()
23 : {
24 15 : initFlag = true;
25 15 : }
26 :
27 26 : bool PhyTopo::IsInitFinished() const
28 : {
29 26 : return initFlag;
30 : }
31 :
32 64 : void PhyTopo::Clear()
33 : {
34 64 : topos.clear();
35 64 : initFlag = false;
36 64 : }
37 :
38 26 : void PhyTopo::AddTopoGraph(const u32 netLayer, std::shared_ptr<Graph<PhyTopo::Node, PhyTopo::Link>> topo)
39 : {
40 26 : if (!initFlag) {
41 26 : topos[netLayer] = topo;
42 38 : 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 26 : }
48 :
49 124 : std::shared_ptr<Graph<PhyTopo::Node, PhyTopo::Link>> PhyTopo::GetTopoGraph(const u32 netLayer) const
50 : {
51 124 : if (topos.find(netLayer) == topos.end()) {
52 5 : return nullptr;
53 : }
54 119 : return topos.at(netLayer);
55 : }
56 :
57 99 : bool PhyTopo::IsNetLayerExisted(const u32 netLayer) const
58 : {
59 99 : if (topos.find(netLayer) == topos.end()) {
60 1 : return false;
61 : }
62 98 : return true;
63 : }
64 :
65 14 : void PhyTopo::Dump() const
66 : {
67 22 : HCCL_DEBUG("PhyTopo Dump:");
68 31 : for (auto &pair : topos) {
69 29 : HCCL_DEBUG("netLayer[%u]:", pair.first);
70 29 : HCCL_DEBUG("nodes:");
71 17 : std::set<NodeId> nodeIds{};
72 17 : pair.second->TraverseNode([&](NodeId nodeId, std::shared_ptr<PhyTopo::Node> node) {
73 58 : nodeIds.insert(nodeId);
74 112 : HCCL_DEBUG("%s", node->Describe().c_str());
75 58 : });
76 29 : HCCL_DEBUG("links:");
77 75 : for (NodeId nodeId : nodeIds) {
78 58 : pair.second->TraverseEdge(nodeId,
79 512 : [&](std::shared_ptr<Link> link) { HCCL_DEBUG("%s", link->Describe().c_str()); });
80 : }
81 17 : }
82 14 : }
83 :
84 343 : PhyTopo::ConnInterface::ConnInterface(const std::set<std::string> inputPorts, const AddrPosition inputPos,
85 343 : const LinkType inputLinkType, const std::set<LinkProtocol> inputLinkProtocols)
86 343 : : ports(inputPorts),
87 343 : pos(inputPos),
88 343 : linkType(inputLinkType),
89 343 : linkProtocols(inputLinkProtocols)
90 : {
91 343 : }
92 :
93 323 : std::set<std::string> PhyTopo::ConnInterface::GetPorts() const
94 : {
95 323 : return ports;
96 : }
97 :
98 316 : AddrPosition PhyTopo::ConnInterface::GetPos() const
99 : {
100 316 : return pos;
101 : }
102 :
103 1 : LinkType PhyTopo::ConnInterface::GetLinkType() const
104 : {
105 1 : return linkType;
106 : }
107 :
108 777 : std::set<LinkProtocol> PhyTopo::ConnInterface::GetLinkProtocols() const
109 : {
110 777 : return linkProtocols;
111 : }
112 :
113 487 : std::string PhyTopo::ConnInterface::Describe() const
114 : {
115 487 : std::string portsStr;
116 717 : for (auto it = ports.begin(); it != ports.end(); ++it) {
117 230 : if (it != ports.begin()) {
118 32 : portsStr += ",";
119 : }
120 230 : portsStr += *it;
121 : }
122 487 : std::string protocolStr;
123 974 : for (auto it = linkProtocols.begin(); it != linkProtocols.end(); ++it) {
124 487 : if (!protocolStr.empty()) {
125 0 : protocolStr += ", ";
126 : }
127 487 : protocolStr += it->Describe();
128 : }
129 :
130 : return StringFormat("ConnInterface[ports={%s}, pos=%s, protocols={%s}, linkType=%s]", portsStr.c_str(),
131 974 : pos.Describe().c_str(), protocolStr.c_str(), linkType.Describe().c_str());
132 487 : }
133 :
134 444 : bool PhyTopo::ConnInterface::operator==(const ConnInterface &rhs) const
135 : {
136 444 : 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 99 : PhyTopo::Node::Node(const PhyTopo::Node::NodeType inputType) : type(inputType) {}
145 :
146 26 : PhyTopo::Node::NodeType PhyTopo::Node::GetType() const
147 : {
148 26 : return type;
149 : }
150 :
151 336 : void PhyTopo::Node::AddConnInterface(const std::shared_ptr<PhyTopo::ConnInterface> &interface)
152 : {
153 601 : for (const auto &iface : interfaces) {
154 442 : if (*iface == *interface) {
155 415 : HCCL_WARNING("[PhyTopo][Node][AddConnInterface] %s has existed.",
156 : interface->Describe().c_str());
157 177 : return;
158 : }
159 : }
160 159 : 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 57 : 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 542 : NodeId PhyTopo::Peer::GetId(const LocalId localId)
181 : {
182 542 : return static_cast<NodeId>(localId);
183 : }
184 :
185 242 : std::string PhyTopo::Peer::Describe() const
186 : {
187 242 : return StringFormat("PhyTopo::Peer[localId=%u]", localId);
188 : }
189 :
190 17 : PhyTopo::Fabric::Fabric() : Node(PhyTopo::Node::NodeType::FABRIC) {}
191 :
192 : constexpr s32 FABRIC_ID_OFFSET = 32;
193 241 : NodeId PhyTopo::Fabric::GetId()
194 : {
195 241 : NodeId res = static_cast<NodeId>(0);
196 241 : res |= (1ULL << FABRIC_ID_OFFSET);
197 241 : return res;
198 : }
199 :
200 126 : std::string PhyTopo::Fabric::Describe() const
201 : {
202 126 : return StringFormat("PhyTopo::Fabric[NodeId=%llu]", GetId());
203 : }
204 :
205 179 : PhyTopo::Link::Link(std::shared_ptr<PhyTopo::Node> inputSource, std::shared_ptr<PhyTopo::Node> inputTarget,
206 : const LinkAttributes& properties,
207 179 : const TopoType inputTopoType, const u32 inputTopoInstId)
208 179 : : sourceIface(nullptr),
209 179 : targetIface(nullptr),
210 179 : source(inputSource),
211 179 : target(inputTarget),
212 179 : linkProtocols(properties.protocols),
213 179 : linkType(properties.linktype),
214 179 : direction(LinkDirection::BOTH),
215 179 : topoType(inputTopoType),
216 179 : topoInstId(inputTopoInstId),
217 179 : hop{1}
218 : {
219 179 : }
220 :
221 168 : void PhyTopo::Link::SetSourceIface(std::shared_ptr<PhyTopo::ConnInterface> inputSourceIface)
222 : {
223 168 : sourceIface = inputSourceIface;
224 168 : }
225 :
226 170 : void PhyTopo::Link::SetTargetIface(std::shared_ptr<PhyTopo::ConnInterface> inputTargetIface)
227 : {
228 170 : targetIface = inputTargetIface;
229 170 : }
230 :
231 1 : LinkType PhyTopo::Link::GetType() const
232 : {
233 1 : return linkType;
234 : }
235 :
236 375 : std::set<LinkProtocol> PhyTopo::Link::GetLinkProtocols() const
237 : {
238 375 : return linkProtocols;
239 : }
240 :
241 1 : LinkDirection PhyTopo::Link::GetLinkDirection() const
242 : {
243 1 : return direction;
244 : }
245 :
246 371 : TopoType PhyTopo::Link::GetTopoType() const
247 : {
248 371 : return topoType;
249 : }
250 :
251 387 : u32 PhyTopo::Link::GetTopoInstId() const
252 : {
253 387 : return topoInstId;
254 : }
255 :
256 1 : u32 PhyTopo::Link::GetHop() const
257 : {
258 1 : return hop;
259 : }
260 :
261 347 : std::shared_ptr<PhyTopo::ConnInterface> PhyTopo::Link::GetSourceIFace()
262 : {
263 347 : return sourceIface;
264 : }
265 :
266 96 : std::shared_ptr<PhyTopo::ConnInterface> PhyTopo::Link::GetTargetIFace()
267 : {
268 96 : return targetIface;
269 : }
270 :
271 9 : std::shared_ptr<PhyTopo::Node> PhyTopo::Link::GetSourceNode()
272 : {
273 9 : return source;
274 : }
275 :
276 9 : std::shared_ptr<PhyTopo::Node> PhyTopo::Link::GetTargetNode()
277 : {
278 9 : return target;
279 : }
280 :
281 155 : std::string PhyTopo::Link::Describe() const
282 : {
283 155 : std::stringstream iFace;
284 155 : if (sourceIface != nullptr) {
285 155 : iFace << ", sourceIface=" << sourceIface->Describe();
286 : }
287 155 : if (targetIface != nullptr) {
288 155 : iFace << ", targetIface=" << targetIface->Describe();
289 : }
290 :
291 : // 将 linkProtocol 转换为字符串
292 155 : std::string protocolStr;
293 310 : for (auto it = linkProtocols.begin(); it != linkProtocols.end(); ++it) {
294 155 : if (!protocolStr.empty()) {
295 0 : protocolStr += ", ";
296 : }
297 155 : protocolStr += it->Describe();
298 : }
299 :
300 310 : return StringFormat("PhyTopo::Link[type=%s, protocol=%s, source=%s, target=%s%s, topoInstId=%u, topoType=%d]", linkType.Describe().c_str(),
301 465 : protocolStr.c_str(), source->Describe().c_str(), target->Describe().c_str(),
302 930 : iFace.str().c_str(), topoInstId, topoType);
303 155 : }
304 : } // namespace Hccl
|