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 <algorithm>
12 : #include <array>
13 : #include "rank_graph_builder.h"
14 : #include "detour_service.h"
15 : #include "json_parser.h"
16 : #include "phy_topo_builder.h"
17 :
18 : namespace Hccl {
19 :
20 : using namespace std;
21 :
22 14 : unique_ptr<RankGraph> RankGraphBuilder::Build(const string &ranktableM, const string &topoPath, RankId myRank)
23 : {
24 14 : PhyTopoBuilder::GetInstance().Build(topoPath);
25 14 : topoInfo_ = PhyTopoBuilder::GetInstance().GetTopoInfo();
26 :
27 : JsonParser rankTableParser;
28 14 : RankTableInfo rankTableInfo;
29 14 : rankTableParser.ParseString(ranktableM, rankTableInfo);
30 14 : rankTable_ = make_unique<RankTableInfo>(rankTableInfo);
31 :
32 14 : this->myRank_ = myRank;
33 14 : BuildRankGraph();
34 :
35 42 : HCCL_INFO("[RankGraphBuilder] Build VirtualTopo success!");
36 14 : rankGraph_->Dump();
37 28 : return std::move(rankGraph_);
38 14 : }
39 :
40 1 : unique_ptr<RankGraph> RankGraphBuilder::Build(const RankTableInfo &ranktable, const string &topoPath, RankId myRank)
41 : {
42 1 : PhyTopoBuilder::GetInstance().Build(topoPath);
43 1 : topoInfo_ = PhyTopoBuilder::GetInstance().GetTopoInfo();
44 1 : rankTable_ = make_unique<RankTableInfo>(ranktable);
45 :
46 1 : myRank_ = myRank;
47 1 : BuildRankGraph();
48 :
49 0 : HCCL_INFO("[RankGraphBuilder] Build VirtualTopo success!");
50 0 : rankGraph_->Dump();
51 0 : return std::move(rankGraph_);
52 : }
53 :
54 60 : const RankLevelInfo &RankGraphBuilder::GetRankLevelInfoByNetLayer(const NewRankInfo &rankInfo, u32 netLayer) const
55 : {
56 60 : auto it = std::find_if(rankInfo.rankLevelInfos.begin(), rankInfo.rankLevelInfos.end(),
57 150 : [netLayer](const RankLevelInfo &levelInfo) {
58 150 : return levelInfo.netLayer == netLayer;
59 : });
60 60 : if (it == rankInfo.rankLevelInfos.end()) {
61 0 : THROW<InvalidParamsException>(StringFormat(
62 : "[RankGraphBuilder][GetRankLevelInfoByNetLayer] rankId[%u] netLayer[%u] does not exist in ranktable.",
63 0 : rankInfo.rankId, netLayer));
64 : }
65 120 : return *it;
66 : }
67 :
68 48 : std::vector<shared_ptr<PhyTopo::Link>> GetPeer2NetPhyLinks(u32 netLayer, LocalId localId)
69 : {
70 48 : const shared_ptr<Graph<PhyTopo::Node, PhyTopo::Link>> phyGraph = PhyTopo::GetInstance()->GetTopoGraph(netLayer);
71 48 : if (phyGraph == nullptr) {
72 0 : THROW<InvalidParamsException>(StringFormat("[RankGraphBuilder][GetPhyLink] localId[%d] is not level[%u] in"
73 : " topo.json, not match rankTable.",
74 : localId, netLayer));
75 : }
76 48 : std::vector<shared_ptr<PhyTopo::Link>> links;
77 48 : phyGraph->TraverseEdge(PhyTopo::Peer::GetId(localId), [&](shared_ptr<PhyTopo::Link> link) {
78 48 : if (link != nullptr) {
79 48 : links.push_back(link);
80 : }
81 48 : });
82 :
83 48 : if (links.empty()) {
84 0 : THROW<InvalidParamsException>(
85 0 : StringFormat("[RankGraphBuilder][GetPhyLink] SourceNode localId[%d] edge does not exist.", localId));
86 : }
87 48 : return links;
88 48 : }
89 :
90 48 : void RankGraphBuilder::AddPeer2NetLink(const u32 netLayer, const string &netInstId, RankId rankId, const AddressInfo &addrInfo,
91 : const shared_ptr<NetInstance::Fabric> &fabNode, const vector<shared_ptr<PhyTopo::Link>> &links)
92 : {
93 96 : for (shared_ptr<PhyTopo::Link> link : links) {
94 48 : if (link->GetSourceIFace() == nullptr) {
95 0 : continue;
96 : }
97 48 : std::set<std::string> ports = link->GetSourceIFace()->GetPorts();
98 48 : std::set<std::string> rankGraphPorts;
99 48 : std::set_intersection(ports.begin(), ports.end(), addrInfo.ports.begin(), addrInfo.ports.end(),
100 : std::inserter(rankGraphPorts, rankGraphPorts.begin()));
101 :
102 48 : if (rankGraphPorts.empty()) {
103 : // 该地址在topo里没有对应边
104 0 : continue;
105 : }
106 : // 获取topoInstId topoType
107 48 : u32 topoInstId = link->GetTopoInstId();
108 48 : auto topoType = link->GetTopoType();
109 :
110 : // 构造 RankGraph 的 PeerIface
111 : shared_ptr<NetInstance::ConnInterface> peerIface = make_shared<NetInstance::ConnInterface>(
112 48 : addrInfo.addr, rankGraphPorts, link->GetSourceIFace()->GetPos(), LinkType::PEER2NET, link->GetLinkProtocols(), topoType, topoInstId);
113 : // 获取 rankId 对应 PeerNode
114 48 : shared_ptr<NetInstance::Peer> peerNode = peers_.at(rankId);
115 48 : peerNode->AddConnInterface(netLayer, peerIface);
116 :
117 : // 构造 peer2netLink 和 net2peerLink 两条link
118 : shared_ptr<NetInstance::Link> peer2netLink =
119 0 : make_shared<NetInstance::Link>(peerNode, fabNode, peerIface, nullptr, LinkType::PEER2NET,
120 48 : link->GetLinkProtocols(), LinkDirection::BOTH, 2);
121 : shared_ptr<NetInstance::Link> net2peerLink =
122 0 : make_shared<NetInstance::Link>(fabNode, peerNode, nullptr, peerIface, LinkType::PEER2NET,
123 48 : link->GetLinkProtocols(), LinkDirection::BOTH, 2);
124 :
125 : // 插入 link
126 48 : tempNetInsts_[netLayer][netInstId]->AddLink(peer2netLink);
127 48 : tempNetInsts_[netLayer][netInstId]->AddLink(net2peerLink);
128 :
129 : // 将rank插入到当前netInstance对应的topoInstance中
130 48 : tempNetInsts_[netLayer][netInstId]->UpdateTopoInst(topoInstId, topoType, rankId);
131 :
132 : // 只打印当前卡的rank_id和eid对应关系
133 48 : if (rankId == myRank_) {
134 32 : HCCL_RUN_INFO("[RankGraphBuilder][AddPeer2NetLink] Add Peer2NetLink Net2PeerLink success. level[%u] "
135 : "netInstId[%s] rankId[%u] planeId[%s] AddrStr[%s],topoInstId[%u],topoType[%u]",
136 : netLayer, netInstId.c_str(), rankId, fabNode->GetPlaneId().c_str(), addrInfo.addr.Describe().c_str(),
137 : topoInstId, topoType);
138 : }
139 48 : }
140 48 : }
141 :
142 12 : void RankGraphBuilder::AddFabricInfo(u32 netLayer)
143 : {
144 12 : auto netInst = rankGraph_->GetNetInstanceByRankId(netLayer, myRank_);
145 12 : if (netInst == nullptr) {
146 0 : THROW<NullPtrException>(StringFormat("[RankGraphBuilder][AddFabricInfo] rankGraph->GetNetInstanceByRankId is nullptr"));
147 : }
148 :
149 12 : if (netInst->GetNetType() != NetType::CLOS) {
150 0 : THROW<NotSupportException>(StringFormat("[RankGraphBuilder][AddFabricInfo] NetInstance is not CLOS, not support add fabric."));
151 : }
152 12 : set<RankId> inRanks = netInst->GetRankIds();
153 12 : string netInstId = netInst->GetNetInstId();
154 12 : const auto &myLevelInfo = GetRankLevelInfoByNetLayer(rankTable_->ranks[myRank_], netLayer);
155 : // 根据planeId确认Fabric个数,每个fabricId对应一个planeId
156 12 : std::map<PlaneId, FabricId> planeId2Node = GetFabricsFromAddrInfo(myLevelInfo.rankAddrs);
157 :
158 12 : if (planeId2Node.size() == 0) {
159 0 : HCCL_WARNING("[RankGraphBuilder][AddFabricInfo] current rankId[%d] netLayer[%u] group no net plane", myRank_, netLayer);
160 0 : return;
161 : }
162 12 : vector<shared_ptr<NetInstance::Fabric>> fabNodes(planeId2Node.size(), nullptr);
163 :
164 : // 遍历每一个rankId,每个rankId都增加 peer2net 和 net2peer 两条链路
165 60 : for (RankId srcRankId : inRanks) {
166 48 : const auto &srcLevelInfo = GetRankLevelInfoByNetLayer(rankTable_->ranks[srcRankId], netLayer);
167 48 : const vector<AddressInfo> &addrs = srcLevelInfo.rankAddrs;
168 : // rankId对应的物理逻辑localId
169 48 : LocalId localId = rankGraph_->GetLocalId(srcRankId);
170 : // 从物理拓扑图中找出 localId在 netLayer 中所有的peer2Net的边。
171 48 : std::vector<shared_ptr<PhyTopo::Link>> links = GetPeer2NetPhyLinks(netLayer, localId);
172 : // 遍历ranktable中的addr,有几个addr就有几条peer2net的边
173 96 : for (AddressInfo addrInfo: addrs) {
174 48 : if (addrInfo.addr == IpAddress()) {
175 0 : continue;
176 : }
177 :
178 48 : if (planeId2Node.count(addrInfo.planeId) == 0) {
179 0 : continue;
180 : }
181 48 : FabricId fabId = planeId2Node[addrInfo.planeId];
182 : // 若 fabNodes[fabId] 不存在则创建 如果存在则获取fabNode
183 48 : shared_ptr<NetInstance::Fabric> fabNode;
184 48 : if (fabNodes[fabId] == nullptr) {
185 12 : fabNode = make_shared<NetInstance::Fabric>(fabId, addrInfo.planeId);
186 12 : tempNetInsts_[netLayer][netInstId]->AddNode(fabNode);
187 12 : fabNodes[fabId] = fabNode;
188 : } else {
189 36 : fabNode = fabNodes[fabId];
190 : }
191 : // 插入peer和fabric的peer2net和net2peer两条link
192 48 : AddPeer2NetLink(netLayer, netInstId, srcRankId, addrInfo, fabNode, links);
193 48 : }
194 48 : }
195 :
196 32 : HCCL_DEBUG("[RankGraphBuilder][AddFabricInfo] netLayer [%u] netInstId[%s] Add Fabric Info success!", netLayer,
197 : netInstId.c_str());
198 12 : }
199 :
200 18 : void RankGraphBuilder::AddTopoDescFabricInfo()
201 : {
202 : // 1. 获取物理拓扑图
203 18 : auto phyTopoGraph = PhyTopo::GetInstance()->GetTopoGraph(0);
204 18 : if (phyTopoGraph == nullptr) {
205 0 : THROW<NullPtrException>(StringFormat("[RankGraphBuilder][AddTopoDescFabricInfo] phyTopoGraph is nullptr"));
206 : }
207 46 : HCCL_INFO("[RankGraphBuilder][AddTopoDescFabricInfo] Successfully retrieved phyTopoGraph");
208 :
209 : // 2. 获取当前 NetInstance
210 18 : NetInstance* innerNetInstance = rankGraph_->GetNetInstanceByRankId(0, myRank_);
211 18 : if (innerNetInstance == nullptr) {
212 0 : THROW<NullPtrException>(
213 0 : StringFormat("[RankGraphBuilder][AddTopoDescFabricInfo] rankGraph->GetNetInstanceByRankId is nullptr"));
214 : }
215 18 : std::string netInstId = innerNetInstance->GetNetInstId();
216 18 : std::set<RankId> rankIds = innerNetInstance->GetRankIds();
217 :
218 : // 存储所有fabric节点,key为topoInstId
219 18 : std::map<u32, std::shared_ptr<NetInstance::Fabric>> fabNodes;
220 :
221 18 : auto peer = rankGraph_->GetPeer(rankGraph_->GetMyRank());
222 18 : auto localDeviceId = peer->GetDeviceId();
223 :
224 : // 3. 遍历所有rank节点,根据topoInstId创建fabric节点
225 68 : for (RankId rankId : rankIds) {
226 50 : LocalId localId = rankGraph_->GetLocalId(rankId);
227 50 : auto peer2netEdges = phyTopoGraph->GetEdges(localId, PhyTopo::Fabric::GetId());
228 :
229 134 : HCCL_RUN_INFO(
230 : "[RankGraphBuilder][AddTopoDescFabricInfo] Processing rank %d (localId: %u), found %zu peer2net edges",
231 : rankId, localId, peer2netEdges.size());
232 :
233 126 : for (const auto& link : peer2netEdges) {
234 76 : u32 topoInstId = link->GetTopoInstId();
235 76 : auto topoType = link->GetTopoType();
236 :
237 : // 创建Fabric节点
238 76 : if (fabNodes.find(topoInstId) == fabNodes.end()) {
239 34 : auto fabNodePtr = std::make_shared<NetInstance::Fabric>(topoInstId);
240 34 : innerNetInstance->AddNode(fabNodePtr);
241 34 : fabNodes[topoInstId] = fabNodePtr;
242 98 : HCCL_INFO("[RankGraphBuilder][AddTopoDescFabricInfo] Created new Fabric node for topoInstId: %u",
243 : topoInstId);
244 34 : }
245 :
246 : // 获取 peer 节点
247 76 : auto peerNode = peers_.at(rankId);
248 :
249 : // 构造连接接口
250 : auto peerIfaces =
251 76 : ConstructConnIFromPhyTopoConnIAndPortMap(link->GetSourceIFace(), peerNode->GetPortAddrMapLayer0(), topoType, topoInstId, localDeviceId);
252 :
253 136 : for (const auto& iface : peerIfaces) {
254 60 : peerNode->AddConnInterface(0, iface);
255 : }
256 76 : auto fabNodePtr = fabNodes[topoInstId];
257 : // 构造 peer2netLink 和 net2peerLink(双向)
258 136 : for (const auto& iface : peerIfaces) {
259 0 : auto peer2netLink = std::make_shared<NetInstance::Link>(peerNode, fabNodePtr, iface, nullptr,
260 120 : LinkType::PEER2NET, link->GetLinkProtocols(),
261 120 : LinkDirection::BOTH, 2);
262 :
263 0 : auto net2peerLink = std::make_shared<NetInstance::Link>(fabNodePtr, peerNode, nullptr, iface,
264 120 : LinkType::PEER2NET, link->GetLinkProtocols(),
265 120 : LinkDirection::BOTH, 2);
266 :
267 : // 插入 link
268 60 : tempNetInsts_[0][netInstId]->AddLink(peer2netLink);
269 60 : tempNetInsts_[0][netInstId]->AddLink(net2peerLink);
270 60 : tempNetInsts_[0][netInstId]->UpdateTopoInst(topoInstId, topoType, rankId);
271 172 : HCCL_RUN_INFO("[RankGraphBuilder][AddTopoDescFabricInfo] netLayer0 rankId[%u] netInstId[%s] Add Fabric "
272 : "Info success!",
273 : rankId, netInstId.c_str());
274 60 : }
275 76 : }
276 50 : }
277 46 : HCCL_INFO("[RankGraphBuilder][AddTopoDescFabricInfo] Successfully completed fabric link construction");
278 18 : }
279 :
280 12 : std::map<PlaneId, FabricId> GetFabricsFromAddrInfo(const std::vector<AddressInfo>& rankAddrs)
281 : {
282 12 : std::map<PlaneId, FabricId> planeId2FabricId;
283 24 : for (const auto& addrInfo : rankAddrs) {
284 12 : if (planeId2FabricId.count(addrInfo.planeId) == 0) {
285 12 : FabricId fabId = planeId2FabricId.size();
286 12 : planeId2FabricId[addrInfo.planeId] = fabId;
287 : }
288 : }
289 12 : return planeId2FabricId;
290 0 : }
291 :
292 99 : void RankGraphBuilder::CheckNetLayerFromPhyTopo(const u32 netLayer) const
293 : {
294 99 : if (!PhyTopo::GetInstance()->IsNetLayerExisted(netLayer)) {
295 1 : THROW<InvalidParamsException>(StringFormat("[RankGraphBuilder][CheckNetLayerFromPhyTopo]"
296 : "netLayer[%u] not exist in topo.", netLayer));
297 : }
298 98 : }
299 :
300 : // 根据ranktable构造添加peers和NetInstances, NetInstance添加nodes和links(peer2net)
301 : // 1. 创建NetInstance ( 每个NetInstance 添加 Rank, Node, Link);
302 : // 2. RankGraph中添加NetInstance, Peer, Fabric,
303 19 : void RankGraphBuilder::BuildFromRankTable()
304 : {
305 : // 保存NetInstance指针以便后续执行Add操作
306 19 : tempNetInsts_.resize(MAX_NET_LAYER); //为了方便修改RankGraph的NetInstance,共享指针。
307 :
308 : // 遍历rankTable每一个rank, virtualTopo添加Peers
309 69 : for (const auto &rankInfo : rankTable_->ranks) {
310 51 : updaterFor64Plus1_.SaveReplaceInfo(rankInfo); // 暂存备份替换信息
311 51 : RankId rankId = rankInfo.rankId;
312 51 : shared_ptr<NetInstance::Peer> peer = make_shared<NetInstance::Peer>(rankId, rankInfo.localId, rankInfo.replacedLocalId, rankInfo.deviceId, rankInfo.devicePort, rankInfo.hostPort);
313 51 : rankGraph_->AddPeer(peer);
314 51 : peers_.emplace(rankId, peer); // rankid2peer
315 :
316 : // 构造当前rank的每个LevelInfo所在NetInstance, 添加 RankId 和 Peer
317 149 : for (const auto &levelInfo : rankInfo.rankLevelInfos) {
318 : // 校验netLayer是否在topo中
319 99 : CheckNetLayerFromPhyTopo(levelInfo.netLayer);
320 : // rankLevelInfo.level、id对应NetInstance,若不存在则创建
321 98 : auto curNetInstance = GetOrCreateNetInstance(levelInfo.netLayer, levelInfo.netInstId, levelInfo.netType, tempNetInsts_, rankGraph_.get());
322 98 : if (curNetInstance == nullptr) {
323 0 : continue;
324 : }
325 : // NetInstance add Peer
326 98 : curNetInstance->AddRankId(rankId);
327 98 : curNetInstance->AddNode(peer);
328 : // Peer add NetInstance
329 98 : peer->AddNetInstance(curNetInstance);
330 98 : if (levelInfo.netLayer == 0) {
331 50 : peer->SetPortPortAddrMapLayer0(levelInfo.portAddrMap);
332 : }
333 262 : HCCL_DEBUG("[RankGraphBuilder][BuildFromRankTable] rankLevelInfo : rankId[%d] level[%u] "
334 : "netInstId[%s] fabricType[%s].",
335 : rankId, levelInfo.netLayer, levelInfo.netInstId.c_str(),
336 : levelInfo.netType.Describe().c_str());
337 98 : }
338 51 : }
339 :
340 : // 对 myrank 所在每个level的NetInstance 添加 Fabrics 和 links(peer2net)
341 18 : set<u32> myLevels = rankGraph_->GetLevels(myRank_);
342 46 : HCCL_DEBUG("myRank netType: level size %u", myLevels.size());
343 48 : for (u32 level : myLevels) {
344 30 : if (level == 0) {
345 18 : AddTopoDescFabricInfo();
346 : } else {
347 12 : AddFabricInfo(level);
348 : }
349 : }
350 :
351 : // 初始化innerRanks
352 18 : rankGraph_->InitInnerRanks();
353 :
354 46 : HCCL_DEBUG("[RankGraphBuilder][BuildFromRankTable] Build VirtualTopo from RankTable success!");
355 18 : }
356 :
357 18 : void RankGraphBuilder::SetEndpointDesc()
358 : {
359 18 : std::shared_ptr<NetInstance::Peer> peer = peers_[myRank_];
360 18 : CHK_PRT_THROW(peer == nullptr, HCCL_ERROR("[RankGraphBuilder::%s] fail", __func__), NullPtrException, "peer is null" );
361 : // 获取 peer 的 Iface
362 18 : std::set<u32> layers = peer->GetLevels();
363 48 : for (const auto& layer : layers) {
364 30 : auto ifacesVec = peer->GetIfacesByLayer(layer);
365 89 : for (const auto& iface : ifacesVec) {
366 59 : const auto& protocols = iface->GetLinkProtocols();
367 118 : for (const auto& protocol : protocols) {
368 59 : EndpointDesc desc{};
369 :
370 59 : HcclResult ret = GetCommAddr(desc.commAddr, iface->GetAddr());
371 59 : CHK_PRT_THROW(ret != HCCL_SUCCESS, HCCL_ERROR("[RankGraphBuilder::%s] fail", __func__), InternalException, "GetCommAddr fail" );
372 :
373 59 : desc.protocol = LinkProtocolToCommProtocol(protocol);
374 59 : desc.loc.locType = AddrPositionToEndpointLoc(iface->GetPos());
375 :
376 165 : HCCL_INFO("[RankGraphBuilder::SetEndpointDesc] local type[%d] protocol[%d]",
377 : desc.loc.locType, desc.protocol);
378 :
379 59 : peer->SetEndpointToIface(desc.commAddr, desc.protocol, iface);
380 : }
381 59 : }
382 30 : }
383 18 : }
384 :
385 0 : std::shared_ptr<NetInstance> RankGraphBuilder::GetNetInstance(const RankLevelInfo &levelInfo){
386 0 : auto it = tempNetInsts_[levelInfo.netLayer].find(levelInfo.netInstId);
387 0 : if (it == tempNetInsts_[levelInfo.netLayer].end()) {
388 0 : return nullptr;
389 : }
390 : // 若NetInstance存在, type不一致则报错
391 0 : NetType netType = it->second->GetNetType();
392 0 : if (netType != levelInfo.netType) {
393 0 : HCCL_WARNING("[CreateNetInstance]FabType [%s] and [%s] no match", netType.Describe().c_str(),
394 : levelInfo.netType.Describe().c_str());
395 0 : return nullptr;
396 : }
397 0 : return it->second;
398 : }
399 :
400 0 : std::shared_ptr<NetInstance> RankGraphBuilder::CreateNetInstance(const RankLevelInfo &levelInfo)
401 : {
402 0 : std::shared_ptr<NetInstance> netInst;
403 0 : if (levelInfo.netType == NetType::TOPO_FILE_DESC) {
404 0 : netInst = std::make_shared<InnerNetInstance>(levelInfo.netLayer, levelInfo.netInstId);
405 0 : } else if (levelInfo.netType == NetType::CLOS) {
406 0 : netInst = std::make_shared<ClosNetInstance>(levelInfo.netLayer, levelInfo.netInstId);
407 : } else {
408 0 : THROW<NotSupportException>(StringFormat("[RankGraphBuilder][CreateNetInstance] netType: %s is not support", levelInfo.netType));
409 : }
410 0 : return netInst;
411 0 : }
412 :
413 : // 从phytopo和ranktable中读取数据共同构建peer2peer的边。
414 18 : void RankGraphBuilder::BuildPeer2PeerLinks()
415 : {
416 18 : auto phyTopoGraph = PhyTopo::GetInstance()->GetTopoGraph(0);
417 18 : if (phyTopoGraph == nullptr) {
418 0 : THROW<NullPtrException>(StringFormat("[RankGraphBuilder][BuildPeer2PeerLinks] phyTopoGraph is nullptr"));
419 : }
420 : // 遍历innerNetInstance中的每两个rankId之间是否存在边,存在则添加peer2peerlink
421 18 : NetInstance *innerNetInstance = rankGraph_->GetNetInstanceByRankId(0, myRank_);
422 18 : if (innerNetInstance == nullptr) {
423 0 : THROW<NullPtrException>(StringFormat("[RankGraphBuilder][BuildPeer2PeerLinks] innerNetInstance is nullptr"));
424 : }
425 18 : set<RankId> rankIds = innerNetInstance->GetRankIds();
426 :
427 18 : auto peer = rankGraph_->GetPeer(rankGraph_->GetMyRank());
428 18 : auto localDeviceId = peer->GetDeviceId();
429 68 : for (const auto srcRankId : rankIds) {
430 212 : for (const auto dstRankId : rankIds) {
431 162 : if (srcRankId == dstRankId) {
432 56 : continue;
433 : }
434 :
435 : // 得到phyTopoGraph中对应的localId
436 112 : LocalId srcLocalId = rankGraph_->GetLocalId(srcRankId);
437 112 : LocalId dstLocalId = rankGraph_->GetLocalId(dstRankId);
438 112 : if (srcLocalId == BACKUP_LOCAL_ID || dstLocalId == BACKUP_LOCAL_ID) {
439 6 : continue;
440 : }
441 :
442 106 : std::vector<shared_ptr<PhyTopo::Link>> phyLinks = GetPeer2PeerPhyLinks(phyTopoGraph, srcLocalId, dstLocalId);
443 : // 根据ports在ranktable找对对应的地址,几个地址就有几条link。
444 :
445 106 : shared_ptr<NetInstance::Peer> srcPeer = peers_.at(srcRankId);
446 106 : shared_ptr<NetInstance::Peer> dstPeer = peers_.at(dstRankId);
447 :
448 200 : for (shared_ptr<PhyTopo::Link> phyLink : phyLinks) {
449 : auto sourceIfaces = ConstructConnIFromPhyTopoConnIAndPortMap(
450 94 : phyLink->GetSourceIFace(), srcPeer->GetPortAddrMapLayer0(), phyLink->GetTopoType(), phyLink->GetTopoInstId(), localDeviceId);
451 : auto targetIfaces = ConstructConnIFromPhyTopoConnIAndPortMap(
452 94 : phyLink->GetTargetIFace(), dstPeer->GetPortAddrMapLayer0(), phyLink->GetTopoType(), phyLink->GetTopoInstId(), localDeviceId);
453 94 : if (sourceIfaces.empty() || targetIfaces.empty()) {
454 : // 没有可用的接口。
455 0 : HCCL_WARNING("[RankGraphBuilder][BuildPeer2PeerLinks] no available interface, "
456 : "srcRankId[%u] dstRankId[%u].", srcRankId, dstRankId);
457 0 : continue;
458 0 : }
459 94 : srcPeer->AddConnInterfaces(0, sourceIfaces);
460 94 : dstPeer->AddConnInterfaces(0, targetIfaces);
461 : std::vector<shared_ptr<NetInstance::Link>> links =
462 94 : ConstructLinks(srcPeer, dstPeer, sourceIfaces, targetIfaces, phyLink);
463 188 : for (auto link : links) {
464 94 : innerNetInstance->AddLink(link);
465 94 : }
466 94 : }
467 106 : }
468 : }
469 18 : }
470 :
471 18 : void RankGraphBuilder::UpdateTopoInstForMyRankOnly()
472 : {
473 18 : auto innerNetInstance = rankGraph_->GetNetInstanceByRankId(0, myRank_);
474 18 : if (innerNetInstance == nullptr) {
475 0 : THROW<NullPtrException>(StringFormat("[RankGraphBuilder][UpdateTopoInstForMyRankOnly] innerNetInstance is nullptr"));
476 : }
477 :
478 18 : auto netInstId = innerNetInstance->GetNetInstId();
479 18 : set<RankId> rankIds = innerNetInstance->GetRankIds();
480 :
481 18 : auto phyTopoGraph = PhyTopo::GetInstance()->GetTopoGraph(0);
482 18 : if (phyTopoGraph == nullptr) {
483 0 : THROW<NullPtrException>(StringFormat("[RankGraphBuilder][UpdateTopoInstForMyRankOnly] phyTopoGraph is nullptr"));
484 : }
485 18 : if (rankIds.size() == 1) {
486 : // 单卡场景直接返回1DMESH
487 2 : RankId singleId = *rankIds.begin();
488 2 : tempNetInsts_[0][netInstId]->UpdateTopoInst(0, TopoType::MESH_1D, singleId);
489 2 : return;
490 : }
491 :
492 64 : for (const auto srcRankId : rankIds) {
493 208 : for (const auto dstRankId : rankIds) {
494 : // 只处理涉及 myRank_ 的边
495 160 : if (srcRankId != myRank_ && dstRankId != myRank_) {
496 80 : continue;
497 : }
498 :
499 80 : LocalId srcLocalId = rankGraph_->GetLocalId(srcRankId);
500 80 : LocalId dstLocalId = rankGraph_->GetLocalId(dstRankId);
501 :
502 80 : std::vector<shared_ptr<PhyTopo::Link>> phyLinks = GetPeer2PeerPhyLinks(phyTopoGraph, srcLocalId, dstLocalId);
503 :
504 134 : for (shared_ptr<PhyTopo::Link> phyLink : phyLinks) {
505 54 : u32 topoInstId = phyLink->GetTopoInstId();
506 54 : auto topoType = phyLink->GetTopoType();
507 54 : tempNetInsts_[0][netInstId]->UpdateTopoInst(topoInstId, topoType, dstRankId);
508 54 : }
509 80 : }
510 : }
511 22 : }
512 :
513 264 : std::vector<std::shared_ptr<NetInstance::ConnInterface>> ConstructConnIFromPhyTopoConnIAndPortMap(
514 : std::shared_ptr<PhyTopo::ConnInterface> phyConnIFace, const std::map<std::string, std::vector<IpAddress>>& portAddrMap,
515 : const TopoType topoType, const u32 topoInstId, u32 localDeviceId) {
516 264 : std::vector<std::shared_ptr<NetInstance::ConnInterface>> netConnIFaces;
517 264 : std::set<string> phyPorts = phyConnIFace->GetPorts();
518 264 : std::map<IpAddress, std::set<string>> addr2Ports;
519 544 : for (auto port: phyPorts) {
520 280 : if (*(phyConnIFace->GetLinkProtocols().begin()) == LinkProtocol::PCIE) {
521 0 : IpAddress tempIp;
522 0 : HrtRaSocketGetVnicIpInfos(localDeviceId, DeviceIdType::DEVICE_ID_TYPE_PHY_ID, localDeviceId, tempIp);
523 0 : auto it = addr2Ports.find(tempIp);
524 0 : if (it == addr2Ports.end()) {
525 0 : std::set<std::string> newPorts;
526 0 : newPorts.insert("d2h");
527 0 : addr2Ports[tempIp] = newPorts;
528 0 : } else {
529 0 : it->second.insert("d2h");
530 : }
531 : } else {
532 280 : auto itPort = portAddrMap.find(port);
533 280 : if (itPort == portAddrMap.end()) {
534 84 : HCCL_WARNING("[RankGraphBuilder][ConstructConnIFromPhyTopoConnIAndPortMap] topo use port [%s] not find addrs in ranktable.", port.c_str());
535 28 : continue;
536 28 : }
537 504 : for (auto addr : itPort->second) {
538 252 : auto it = addr2Ports.find(addr);
539 252 : if (it == addr2Ports.end()) {
540 248 : std::set<std::string> newPorts;
541 248 : newPorts.insert(port);
542 248 : addr2Ports[addr] = newPorts;
543 248 : } else {
544 12 : it->second.insert("8080");
545 : }
546 : }
547 : }
548 280 : }
549 :
550 512 : for (auto it = addr2Ports.begin(); it != addr2Ports.end(); ++it) {
551 248 : auto linkType = *(phyConnIFace->GetLinkProtocols().begin()) == LinkProtocol::PCIE ? LinkType::PEER2NET : LinkType::PEER2PEER;
552 : shared_ptr<NetInstance::ConnInterface> netConnIFace =
553 248 : make_shared<NetInstance::ConnInterface>(it->first, it->second, phyConnIFace->GetPos(), linkType,
554 496 : phyConnIFace->GetLinkProtocols(), topoType, topoInstId);
555 248 : netConnIFaces.push_back(netConnIFace);
556 248 : }
557 264 : return netConnIFaces;
558 264 : }
559 :
560 94 : std::vector<shared_ptr<NetInstance::Link>> ConstructLinks(shared_ptr<NetInstance::Peer> srcPeer, shared_ptr<NetInstance::Peer> dstPeer,
561 : std::vector<std::shared_ptr<NetInstance::ConnInterface>> sourceIfaces,
562 : std::vector<std::shared_ptr<NetInstance::ConnInterface>> targetIfaces, shared_ptr<PhyTopo::Link> phyLink)
563 : {
564 94 : std::vector<shared_ptr<NetInstance::Link>> links;
565 188 : for (auto sourceIFace : sourceIfaces) {
566 188 : for (auto targetIFace : targetIfaces) {
567 : shared_ptr<NetInstance::Link> link = make_shared<NetInstance::Link>(srcPeer, dstPeer, sourceIFace, targetIFace,
568 94 : LinkType::PEER2PEER, phyLink->GetLinkProtocols());
569 94 : links.push_back(link);
570 94 : }
571 94 : }
572 94 : return links;
573 0 : }
574 :
575 186 : std::vector<std::shared_ptr<PhyTopo::Link>> GetPeer2PeerPhyLinks(std::shared_ptr<Graph<PhyTopo::Node, PhyTopo::Link>> phyTopoGraph, LocalId srcLocalId, LocalId dstLocalId)
576 : {
577 186 : std::vector<shared_ptr<PhyTopo::Link>> links;
578 186 : if (!phyTopoGraph->HasNode(srcLocalId) || !phyTopoGraph->HasNode(dstLocalId)) {
579 0 : HCCL_WARNING("[RankGraphBuilder][BuildFromPhytopo] srcLocalId[%u] dstLocalId[%u] not exist in phyTopoGraph.",
580 : srcLocalId,
581 : dstLocalId);
582 0 : return links;
583 : }
584 : // 得到phyTopoGraph对应的NodeId
585 186 : NodeId srcNodeId = PhyTopo::Peer::GetId(srcLocalId);
586 186 : NodeId dstNodeId = PhyTopo::Peer::GetId(dstLocalId);
587 :
588 186 : phyTopoGraph->TraverseEdge(srcNodeId, dstNodeId, [&](shared_ptr<PhyTopo::Link> link) {
589 148 : if (link != nullptr) {
590 148 : links.push_back(link);
591 : }
592 148 : });
593 186 : if (links.empty()) {
594 90 : HCCL_WARNING(
595 : "[RankGraphBuilder][GetPeer2PeerPhyLinks] srcLocalId[%u] dstLocalId[%u] edge does not exist.", srcLocalId, dstLocalId);
596 : }
597 186 : return links;
598 0 : }
599 :
600 21 : void RankGraphBuilder::CheckMyRankInRankTable() const
601 : {
602 21 : if (myRank_ >= static_cast<s32>(rankTable_->rankCount)) {
603 1 : THROW<InvalidParamsException>(StringFormat("[RankGraphBuilder][CheckMyRankInRankTable]"
604 1 : "myRank[%d] is not in rankTable rankCount[%u].", myRank_, rankTable_->rankCount));
605 : }
606 20 : }
607 :
608 21 : void RankGraphBuilder::BuildRankGraph()
609 : {
610 : // 创建VirtualTopo
611 21 : rankGraph_ = make_unique<RankGraph>(myRank_);
612 :
613 : // 校验myRank在rankTable中
614 21 : CheckMyRankInRankTable();
615 :
616 : // 根据ranktable构造添加peers和NetInstances, 每个NetInstance添加nodes和links(peer2net)
617 20 : BuildFromRankTable();
618 :
619 : // 根据phytopo构造添加InnerGroup中的links(peer2peer), 不包括备份节点
620 19 : BuildPeer2PeerLinks();
621 :
622 : // 使用备份D时需要修改虚拟拓扑
623 19 : updaterFor64Plus1_.UpdateRankGraph(rankGraph_.get(), rankTable_.get());
624 :
625 : // 为myrank的peer2peer更新topoInst
626 19 : UpdateTopoInstForMyRankOnly();
627 :
628 : // 添加绕路 绕路获取
629 19 : DetourService::GetInstance().InsertDetourLinks(rankGraph_.get(), rankTable_.get());
630 :
631 : // 设置endpoint
632 19 : SetEndpointDesc();
633 :
634 : // 构造完成
635 19 : rankGraph_->InitFinish();
636 19 : }
637 :
638 6 : std::unique_ptr<RankTableInfo> RankGraphBuilder::GetRankTableInfo()
639 : {
640 6 : return move(rankTable_);
641 : }
642 :
643 5 : std::shared_ptr<TopoInfo> RankGraphBuilder::GetTopoInfo()
644 : {
645 5 : return topoInfo_;
646 : }
647 :
648 5 : unique_ptr<RankGraph> RankGraphBuilder::RecoverBuild(const RankTableInfo &rankTableInfo,const TopoInfo &topoInfo, RankId myRank)
649 : {
650 5 : topoInfo_ = std::make_shared<TopoInfo>(topoInfo);
651 5 : PhyTopoBuilder::GetInstance().RecoverBuild(*topoInfo_);
652 :
653 5 : rankTable_ = make_unique<RankTableInfo>(rankTableInfo);
654 5 : HCCL_INFO("[%s] RankTable[%s] RankTableInfo[%s]", __func__, rankTable_->Describe().c_str(),
655 : rankTableInfo.Describe().c_str());
656 :
657 5 : this->myRank_ = myRank;
658 5 : BuildRankGraph();
659 :
660 4 : HCCL_INFO("[RankGraphBuilder] Build VirtualTopo success!");
661 4 : rankGraph_->Dump();
662 4 : return std::move(rankGraph_);
663 : }
664 :
665 : } // namespace Hccl
|