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 334 : std::unique_ptr<PhyTopo>& PhyTopo::GetInstance()
17 : {
18 334 : static std::unique_ptr<PhyTopo> topo = std::make_unique<PhyTopo>();
19 334 : return topo;
20 : }
21 :
22 23 : void PhyTopo::InitFinish() { initFlag = true; }
23 :
24 34 : bool PhyTopo::IsInitFinished() const { return initFlag; }
25 :
26 116 : void PhyTopo::Clear()
27 : {
28 116 : topo_.reset();
29 116 : initFlag = false;
30 116 : }
31 :
32 28 : void PhyTopo::AddTopoGraph(std::shared_ptr<Graph<PhyTopo::Node, PhyTopo::Link>> topo)
33 : {
34 28 : if (!initFlag) {
35 : // 物理拓扑只保存一张无逻辑层级的图。
36 28 : topo_ = topo;
37 40 : HCCL_DEBUG("[PhyTopo] add physical topo graph success.");
38 : } else {
39 0 : THROW<InternalException>("PhyTopo AddTopoGraph fail. PhyTopo has been initialized "
40 : "and cannot be changed, please check.");
41 : }
42 28 : }
43 :
44 124 : std::shared_ptr<Graph<PhyTopo::Node, PhyTopo::Link>> PhyTopo::GetTopoGraph() const { return topo_; }
45 :
46 21 : void PhyTopo::Dump() const
47 : {
48 33 : HCCL_DEBUG("PhyTopo Dump:");
49 21 : if (topo_ == nullptr) {
50 0 : HCCL_DEBUG("physical topo graph is nullptr.");
51 0 : return;
52 : }
53 33 : HCCL_DEBUG("nodes:");
54 21 : std::set<NodeId> nodeIds{};
55 21 : topo_->TraverseNode([&](NodeId nodeId, std::shared_ptr<PhyTopo::Node> node) {
56 60 : nodeIds.insert(nodeId);
57 108 : HCCL_DEBUG("%s", node->Describe().c_str());
58 60 : });
59 33 : HCCL_DEBUG("links:");
60 81 : for (NodeId nodeId : nodeIds) {
61 60 : topo_->TraverseEdge(nodeId, [&](std::shared_ptr<Link> link) {
62 506 : HCCL_DEBUG("%s", link->Describe().c_str());
63 230 : });
64 : }
65 21 : }
66 :
67 509 : PhyTopo::ConnInterface::ConnInterface(
68 : const std::set<std::string> inputPorts, const AddrPosition inputPos, const LinkType inputLinkType,
69 509 : const std::set<LinkProtocol> inputLinkProtocols)
70 509 : : ports(inputPorts),
71 509 : pos(inputPos),
72 509 : linkType(inputLinkType),
73 509 : linkProtocols(inputLinkProtocols)
74 509 : {}
75 :
76 739 : std::set<std::string> PhyTopo::ConnInterface::GetPorts() const { return ports; }
77 :
78 510 : AddrPosition PhyTopo::ConnInterface::GetPos() const { return pos; }
79 :
80 1 : LinkType PhyTopo::ConnInterface::GetLinkType() const { return linkType; }
81 :
82 1467 : std::set<LinkProtocol> PhyTopo::ConnInterface::GetLinkProtocols() const { return linkProtocols; }
83 :
84 752 : std::string PhyTopo::ConnInterface::Describe() const
85 : {
86 752 : std::string portsStr;
87 1164 : for (auto it = ports.begin(); it != ports.end(); ++it) {
88 412 : if (it != ports.begin()) {
89 137 : portsStr += ",";
90 : }
91 412 : portsStr += *it;
92 : }
93 752 : std::string protocolStr;
94 1564 : for (auto it = linkProtocols.begin(); it != linkProtocols.end(); ++it) {
95 812 : if (!protocolStr.empty()) {
96 60 : protocolStr += ", ";
97 : }
98 812 : protocolStr += it->Describe();
99 : }
100 :
101 : return StringFormat(
102 1504 : "ConnInterface[ports={%s}, pos=%s, protocols={%s}, linkType=%s]", portsStr.c_str(), pos.Describe().c_str(),
103 3008 : protocolStr.c_str(), linkType.Describe().c_str());
104 752 : }
105 :
106 868 : bool PhyTopo::ConnInterface::operator==(const ConnInterface& rhs) const
107 : {
108 868 : return ports == rhs.ports && pos == rhs.pos && linkType == rhs.linkType && linkProtocols == rhs.linkProtocols;
109 : }
110 :
111 1 : bool PhyTopo::ConnInterface::operator!=(const ConnInterface& rhs) const { return !(rhs == *this); }
112 :
113 102 : PhyTopo::Node::Node(const PhyTopo::Node::NodeType inputType) : type(inputType) {}
114 :
115 26 : PhyTopo::Node::NodeType PhyTopo::Node::GetType() const { return type; }
116 :
117 500 : void PhyTopo::Node::AddConnInterface(const std::shared_ptr<PhyTopo::ConnInterface>& interface)
118 : {
119 1080 : for (const auto& iface : interfaces) {
120 850 : if (*iface == *interface) {
121 600 : HCCL_WARNING("[PhyTopo][Node][AddConnInterface] %s has existed.", interface->Describe().c_str());
122 270 : return;
123 : }
124 : }
125 230 : interfaces.emplace_back(interface);
126 : }
127 :
128 0 : PhyTopo::Node::IfaceIterator PhyTopo::Node::IterIfaces() const { return PhyTopo::Node::IfaceIterator(interfaces); }
129 :
130 0 : std::string PhyTopo::Node::Describe() const { return "PhyTopo::Node[]"; }
131 :
132 59 : PhyTopo::Peer::Peer(const LocalId localId) : Node(PhyTopo::Node::NodeType::PEER), localId(localId) {}
133 :
134 2 : LocalId PhyTopo::Peer::GetLocalId() const { return localId; }
135 :
136 627 : NodeId PhyTopo::Peer::GetId(const LocalId localId) { return static_cast<NodeId>(localId); }
137 :
138 340 : std::string PhyTopo::Peer::Describe() const { return StringFormat("PhyTopo::Peer[localId=%u]", localId); }
139 :
140 18 : PhyTopo::Fabric::Fabric() : Node(PhyTopo::Node::NodeType::FABRIC) {}
141 :
142 : constexpr s32 FABRIC_ID_OFFSET = 32;
143 361 : NodeId PhyTopo::Fabric::GetId()
144 : {
145 361 : NodeId res = static_cast<NodeId>(0);
146 361 : res |= (1ULL << FABRIC_ID_OFFSET);
147 361 : return res;
148 : }
149 :
150 202 : std::string PhyTopo::Fabric::Describe() const { return StringFormat("PhyTopo::Fabric[NodeId=%llu]", GetId()); }
151 :
152 261 : PhyTopo::Link::Link(
153 : std::shared_ptr<PhyTopo::Node> inputSource, std::shared_ptr<PhyTopo::Node> inputTarget,
154 261 : const LinkAttributes& properties, const TopoType inputTopoType, const u32 inputTopoInstId)
155 261 : : sourceIface(nullptr),
156 261 : targetIface(nullptr),
157 261 : source(inputSource),
158 261 : target(inputTarget),
159 261 : linkProtocols(properties.protocols),
160 261 : linkType(properties.linktype),
161 261 : direction(LinkDirection::BOTH),
162 261 : topoType(inputTopoType),
163 261 : topoInstId(inputTopoInstId),
164 261 : hop{1}
165 261 : {}
166 :
167 250 : void PhyTopo::Link::SetSourceIface(std::shared_ptr<PhyTopo::ConnInterface> inputSourceIface)
168 : {
169 250 : sourceIface = inputSourceIface;
170 250 : }
171 :
172 252 : void PhyTopo::Link::SetTargetIface(std::shared_ptr<PhyTopo::ConnInterface> inputTargetIface)
173 : {
174 252 : targetIface = inputTargetIface;
175 252 : }
176 :
177 637 : LinkType PhyTopo::Link::GetType() const { return linkType; }
178 :
179 414 : std::set<LinkProtocol> PhyTopo::Link::GetLinkProtocols() const { return linkProtocols; }
180 :
181 17 : LinkDirection PhyTopo::Link::GetLinkDirection() const { return direction; }
182 :
183 640 : TopoType PhyTopo::Link::GetTopoType() const { return topoType; }
184 :
185 688 : u32 PhyTopo::Link::GetTopoInstId() const { return topoInstId; }
186 :
187 17 : u32 PhyTopo::Link::GetHop() const { return hop; }
188 :
189 1071 : std::shared_ptr<PhyTopo::ConnInterface> PhyTopo::Link::GetSourceIFace() { return sourceIface; }
190 :
191 186 : std::shared_ptr<PhyTopo::ConnInterface> PhyTopo::Link::GetTargetIFace() { return targetIface; }
192 :
193 25 : std::shared_ptr<PhyTopo::Node> PhyTopo::Link::GetSourceNode() { return source; }
194 :
195 25 : std::shared_ptr<PhyTopo::Node> PhyTopo::Link::GetTargetNode() { return target; }
196 :
197 241 : std::string PhyTopo::Link::Describe() const
198 : {
199 241 : std::stringstream iFace;
200 241 : if (sourceIface != nullptr) {
201 241 : iFace << ", sourceIface=" << sourceIface->Describe();
202 : }
203 241 : if (targetIface != nullptr) {
204 241 : iFace << ", targetIface=" << targetIface->Describe();
205 : }
206 :
207 : // 将 linkProtocol 转换为字符串
208 241 : std::string protocolStr;
209 502 : for (auto it = linkProtocols.begin(); it != linkProtocols.end(); ++it) {
210 261 : if (!protocolStr.empty()) {
211 20 : protocolStr += ", ";
212 : }
213 261 : protocolStr += it->Describe();
214 : }
215 :
216 : return StringFormat(
217 : "PhyTopo::Link[type=%s, protocol=%s, source=%s, target=%s%s, topoInstId=%u, topoType=%d]",
218 964 : linkType.Describe().c_str(), protocolStr.c_str(), source->Describe().c_str(), target->Describe().c_str(),
219 1446 : iFace.str().c_str(), topoInstId, topoType);
220 241 : }
221 : } // namespace Hccl
|