Line data Source code
1 : /**
2 : * Copyright (c) 2026 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 "rank_graph_builder_bridge.h"
12 :
13 : #include <exception>
14 : #include <new>
15 :
16 : #include "hccl_exception.h"
17 : #include "log.h"
18 : #include "rank_graph_builder.h"
19 :
20 : namespace Hccl {
21 : namespace {
22 :
23 : // RankGraph 的实现和分配均位于 hcomm,跨 SO 持有时也必须回到 hcomm 执行析构。
24 8 : void DestroyRankGraphImpl(RankGraph *rankGraph)
25 : {
26 8 : delete rankGraph;
27 8 : }
28 :
29 8 : HcclResult AdoptRankGraphImpl(std::unique_ptr<RankGraph> rankGraph, std::shared_ptr<RankGraph> &sharedRankGraph)
30 : {
31 8 : if (rankGraph == nullptr) {
32 0 : HCCL_ERROR("[%s] input rankGraph is nullptr.", __func__);
33 0 : return HCCL_E_PTR;
34 : }
35 :
36 8 : RankGraph *rawRankGraph = rankGraph.release();
37 : try {
38 : // shared_ptr 构造失败时会自行调用 deleter,禁止在 catch 中再次释放 rawRankGraph。
39 8 : std::shared_ptr<RankGraph> adoptedRankGraph(rawRankGraph, DestroyRankGraphImpl);
40 8 : sharedRankGraph = std::move(adoptedRankGraph);
41 8 : } catch (const std::bad_alloc &e) {
42 0 : HCCL_ERROR("[%s] create shared RankGraph failed: %s", __func__, e.what());
43 0 : return HCCL_E_MEMORY;
44 0 : }
45 8 : return HCCL_SUCCESS;
46 : }
47 :
48 5 : HcclResult FillBuildResult(RankGraphBuilder &rankGraphBuilder, std::unique_ptr<RankGraph> rankGraph,
49 : RankGraphBuildResult &result)
50 : {
51 : // 在栈上 builder 析构前转移完整结果,保证 RankGraph、RankTableInfo 与 TopoInfo 来自同一次构建。
52 5 : std::unique_ptr<RankTableInfo> rankTableInfo = rankGraphBuilder.GetRankTableInfo();
53 5 : std::shared_ptr<TopoInfo> topoInfo = rankGraphBuilder.GetTopoInfo();
54 5 : if (rankGraph == nullptr || rankTableInfo == nullptr || topoInfo == nullptr) {
55 0 : HCCL_ERROR("[%s] rank graph build result is invalid.", __func__);
56 0 : return HCCL_E_INTERNAL;
57 : }
58 :
59 5 : CHK_RET(AdoptRankGraphImpl(std::move(rankGraph), result.rankGraph));
60 5 : result.rankTableInfo = std::move(*rankTableInfo);
61 5 : result.topoInfo = *topoInfo;
62 5 : return HCCL_SUCCESS;
63 5 : }
64 :
65 : // BuildRankGraph 是三个 provider 入口共享的构建骨架,BuildFunc 表示各入口不同的构建动作:
66 : template <typename BuildFunc>
67 5 : HcclResult BuildRankGraph(BuildFunc &&buildFunc, RankGraphBuildResult &result)
68 : {
69 5 : RankGraphBuilder rankGraphBuilder;
70 10 : return FillBuildResult(rankGraphBuilder, buildFunc(rankGraphBuilder), result);
71 5 : }
72 :
73 : template <typename BuildFunc>
74 5 : HcclResult RunBuild(const char *funcName, BuildFunc &&buildFunc, RankGraphBuildResult &result)
75 : {
76 : try {
77 5 : return BuildRankGraph(buildFunc, result);
78 0 : } catch (const HcclException &e) {
79 0 : HCCL_ERROR("[%s] failed: %s", funcName, e.what());
80 0 : return e.GetErrorCode();
81 0 : } catch (const std::bad_alloc &e) {
82 0 : HCCL_ERROR("[%s] failed: %s", funcName, e.what());
83 0 : return HCCL_E_MEMORY;
84 0 : } catch (const std::exception &e) {
85 0 : HCCL_ERROR("[%s] failed: %s", funcName, e.what());
86 0 : return HCCL_E_INTERNAL;
87 0 : } catch (...) {
88 0 : HCCL_ERROR("[%s] failed: unknown exception", funcName);
89 0 : return HCCL_E_INTERNAL;
90 : }
91 : }
92 :
93 : // 三个窄入口分别承接字符串初始化、RootInfoDetect 结果初始化和故障恢复,
94 5 : HcclResult BuildFromStringImpl(const std::string &rankTable, const std::string &topoPath, RankId myRank,
95 : RankGraphBuildResult &result)
96 : {
97 10 : return RunBuild(__func__,
98 10 : [&](RankGraphBuilder &rankGraphBuilder) {
99 5 : return rankGraphBuilder.Build(rankTable, topoPath, myRank);
100 : },
101 10 : result);
102 : }
103 :
104 0 : HcclResult BuildFromRankTableImpl(const RankTableInfo &rankTable, const std::string &topoPath, RankId myRank,
105 : RankGraphBuildResult &result)
106 : {
107 0 : return RunBuild(__func__,
108 0 : [&](RankGraphBuilder &rankGraphBuilder) {
109 0 : return rankGraphBuilder.Build(rankTable, topoPath, myRank);
110 : },
111 0 : result);
112 : }
113 :
114 0 : HcclResult RecoverBuildImpl(const RankTableInfo &rankTable, const TopoInfo &topoInfo, RankId myRank,
115 : RankGraphBuildResult &result)
116 : {
117 0 : return RunBuild(__func__,
118 0 : [&](RankGraphBuilder &rankGraphBuilder) {
119 0 : return rankGraphBuilder.RecoverBuild(rankTable, topoInfo, myRank);
120 : },
121 0 : result);
122 : }
123 :
124 : // 将 bridge 的四个字段绑定到本文件中的 provider 实现;调用函数指针等价于调用对应的 Impl 函数。
125 : const RankGraphBuilderBridge RANK_GRAPH_BUILDER_BRIDGE = {
126 : BuildFromStringImpl,
127 : BuildFromRankTableImpl,
128 : RecoverBuildImpl,
129 : AdoptRankGraphImpl,
130 : };
131 :
132 : // hcomm 装载时向 hccl_v2 发布窄回调接口,legacy 调用方无需链接 RankGraphBuilder 的具体实现。
133 : struct RankGraphBuilderBridgeRegistrar {
134 42 : RankGraphBuilderBridgeRegistrar()
135 : {
136 42 : HcclResult ret = RegisterRankGraphBuilderBridge(RANK_GRAPH_BUILDER_BRIDGE);
137 42 : if (ret != HCCL_SUCCESS) {
138 0 : HCCL_ERROR("[%s] register RankGraphBuilder bridge failed, ret[%d].", __func__, static_cast<int>(ret));
139 : }
140 42 : }
141 : };
142 :
143 : RankGraphBuilderBridgeRegistrar g_rankGraphBuilderBridgeRegistrar;
144 :
145 : } // namespace
146 : } // namespace Hccl
|