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) { delete rankGraph; }
25 :
26 8 : HcclResult AdoptRankGraphImpl(std::unique_ptr<RankGraph> rankGraph, std::shared_ptr<RankGraph>& sharedRankGraph)
27 : {
28 8 : if (rankGraph == nullptr) {
29 0 : HCCL_ERROR("[%s] input rankGraph is nullptr.", __func__);
30 0 : return HCCL_E_PTR;
31 : }
32 :
33 8 : RankGraph* rawRankGraph = rankGraph.release();
34 : try {
35 : // shared_ptr 构造失败时会自行调用 deleter,禁止在 catch 中再次释放 rawRankGraph。
36 8 : std::shared_ptr<RankGraph> adoptedRankGraph(rawRankGraph, DestroyRankGraphImpl);
37 8 : sharedRankGraph = std::move(adoptedRankGraph);
38 8 : } catch (const std::bad_alloc& e) {
39 0 : HCCL_ERROR("[%s] create shared RankGraph failed: %s", __func__, e.what());
40 0 : return HCCL_E_MEMORY;
41 0 : }
42 8 : return HCCL_SUCCESS;
43 : }
44 :
45 5 : HcclResult FillBuildResult(
46 : RankGraphBuilder& rankGraphBuilder, std::unique_ptr<RankGraph> rankGraph, RankGraphBuildResult& result)
47 : {
48 : // 在栈上 builder 析构前转移完整结果,保证 RankGraph、RankTableInfo 与 TopoInfo 来自同一次构建。
49 5 : std::unique_ptr<RankTableInfo> rankTableInfo = rankGraphBuilder.GetRankTableInfo();
50 5 : std::shared_ptr<TopoInfo> topoInfo = rankGraphBuilder.GetTopoInfo();
51 5 : if (rankGraph == nullptr || rankTableInfo == nullptr || topoInfo == nullptr) {
52 0 : HCCL_ERROR("[%s] rank graph build result is invalid.", __func__);
53 0 : return HCCL_E_INTERNAL;
54 : }
55 :
56 5 : CHK_RET(AdoptRankGraphImpl(std::move(rankGraph), result.rankGraph));
57 5 : result.rankTableInfo = std::move(*rankTableInfo);
58 5 : result.topoInfo = *topoInfo;
59 5 : return HCCL_SUCCESS;
60 5 : }
61 :
62 : // BuildRankGraph 是三个 provider 入口共享的构建骨架,BuildFunc 表示各入口不同的构建动作:
63 : template <typename BuildFunc>
64 5 : HcclResult BuildRankGraph(BuildFunc&& buildFunc, RankGraphBuildResult& result)
65 : {
66 5 : RankGraphBuilder rankGraphBuilder;
67 10 : return FillBuildResult(rankGraphBuilder, buildFunc(rankGraphBuilder), result);
68 5 : }
69 :
70 : template <typename BuildFunc>
71 5 : HcclResult RunBuild(const char* funcName, BuildFunc&& buildFunc, RankGraphBuildResult& result)
72 : {
73 : try {
74 5 : return BuildRankGraph(buildFunc, result);
75 0 : } catch (const HcclException& e) {
76 0 : HCCL_ERROR("[%s] failed: %s", funcName, e.what());
77 0 : return e.GetErrorCode();
78 0 : } catch (const std::bad_alloc& e) {
79 0 : HCCL_ERROR("[%s] failed: %s", funcName, e.what());
80 0 : return HCCL_E_MEMORY;
81 0 : } catch (const std::exception& e) {
82 0 : HCCL_ERROR("[%s] failed: %s", funcName, e.what());
83 0 : return HCCL_E_INTERNAL;
84 0 : } catch (...) {
85 0 : HCCL_ERROR("[%s] failed: unknown exception", funcName);
86 0 : return HCCL_E_INTERNAL;
87 : }
88 : }
89 :
90 : // 三个窄入口分别承接字符串初始化、RootInfoDetect 结果初始化和故障恢复,
91 5 : HcclResult BuildFromStringImpl(
92 : const std::string& rankTable, const std::string& topoPath, RankId myRank, RankGraphBuildResult& result)
93 : {
94 10 : return RunBuild(
95 : __func__,
96 10 : [&](RankGraphBuilder& rankGraphBuilder) {
97 5 : return rankGraphBuilder.Build(rankTable, topoPath, myRank);
98 : },
99 10 : result);
100 : }
101 :
102 0 : HcclResult BuildFromRankTableImpl(
103 : const RankTableInfo& rankTable, const std::string& topoPath, RankId myRank, RankGraphBuildResult& result)
104 : {
105 0 : return RunBuild(
106 : __func__,
107 0 : [&](RankGraphBuilder& rankGraphBuilder) {
108 0 : return rankGraphBuilder.Build(rankTable, topoPath, myRank);
109 : },
110 0 : result);
111 : }
112 :
113 0 : HcclResult RecoverBuildImpl(
114 : const RankTableInfo& rankTable, const TopoInfo& topoInfo, RankId myRank, RankGraphBuildResult& result)
115 : {
116 0 : return RunBuild(
117 : __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 48 : RankGraphBuilderBridgeRegistrar()
135 : {
136 48 : HcclResult ret = RegisterRankGraphBuilderBridge(RANK_GRAPH_BUILDER_BRIDGE);
137 48 : if (ret != HCCL_SUCCESS) {
138 0 : HCCL_ERROR("[%s] register RankGraphBuilder bridge failed, ret[%d].", __func__, static_cast<int>(ret));
139 : }
140 48 : }
141 : };
142 :
143 : RankGraphBuilderBridgeRegistrar g_rankGraphBuilderBridgeRegistrar;
144 :
145 : } // namespace
146 : } // namespace Hccl
|