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 : #ifndef ENDPOINT_PAIR_H
12 : #define ENDPOINT_PAIR_H
13 :
14 : #include <memory>
15 : #include <mutex>
16 : #include <unordered_map>
17 : #include <utility>
18 : #include <vector>
19 : #include "channels/channel.h"
20 : #include "endpoint.h"
21 : #include "socket_mgr.h"
22 : #include "../../../../legacy/ascend950/unified_platform/resource/socket/socket.h"
23 : #include "../../../../legacy/ascend950/framework/resource_manager/socket/socket_manager.h"
24 :
25 : using EndpointDescPair = std::pair<EndpointDesc, EndpointDesc>;
26 :
27 : // 重载 == 操作符,用于 EndpointDesc 在 std::unordered_map 比较
28 367 : inline bool operator==(const EndpointDesc& a, const EndpointDesc& b) noexcept
29 : {
30 367 : return std::memcmp(&a, &b, sizeof(EndpointDesc)) == 0;
31 : }
32 :
33 : namespace std {
34 :
35 : template <>
36 : struct hash<EndpointDesc> {
37 491 : size_t operator()(const EndpointDesc& e) const noexcept
38 : {
39 : // FNV-1a(64位)对字节序列做hash
40 491 : const uint8_t* p = reinterpret_cast<const uint8_t*>(&e);
41 491 : size_t h
42 : = sizeof(size_t) == 8 ? static_cast<size_t>(14695981039346656037ull) : static_cast<size_t>(2166136261u);
43 :
44 491 : const size_t prime
45 : = sizeof(size_t) == 8 ? static_cast<size_t>(1099511628211ull) : static_cast<size_t>(16777619u);
46 :
47 79051 : for (size_t i = 0; i < sizeof(EndpointDesc); ++i) {
48 78560 : h ^= static_cast<size_t>(p[i]);
49 78560 : h *= prime;
50 : }
51 491 : return h;
52 : }
53 : };
54 :
55 : template <>
56 : struct hash<EndpointDescPair> {
57 225 : size_t operator()(const EndpointDescPair& p) const noexcept
58 : {
59 225 : size_t h1 = std::hash<EndpointDesc>{}(p.first);
60 225 : size_t h2 = std::hash<EndpointDesc>{}(p.second);
61 225 : size_t h = h1;
62 225 : h ^= h2 + 0x9e3779b97f4a7c15ULL + (h << 6) + (h >> 2);
63 225 : return h;
64 : }
65 : };
66 :
67 : } // namespace std
68 :
69 : namespace hcomm {
70 : /**
71 : * @note 职责:通信设备Endpoint对(EndpointPair,或连接)的C++类声明,
72 : * 管理该Endpoint对上的本地和远端注册内存、多个Channel、以及socket等。两个Endpoint的通信协议一致。
73 : */
74 : class EndpointPair {
75 : public:
76 39 : EndpointPair(
77 : EndpointDesc localEndpointDesc, EndpointDesc remoteEndpointDesc, const Hccl::RankIpPortMapPtr& rankIpPortMap)
78 39 : : localEndpointDesc_(localEndpointDesc),
79 39 : remoteEndpointDesc_(remoteEndpointDesc),
80 39 : rankIpPortMap_(rankIpPortMap)
81 39 : {}
82 : ~EndpointPair();
83 :
84 : HcclResult Init();
85 :
86 : // 临时方案:新增临时接口用于支持混跑
87 : HcclResult GetSocket(
88 : const uint32_t myRank, const uint32_t rmtRank, const std::string& socketTag, u32 reuseIdx,
89 : const uint32_t listenPort, Hccl::Socket*& socket, uint32_t devicePhyId, uint32_t remoteDevicePhyId);
90 : HcclResult GetHostSocketWithRank(
91 : const uint32_t myRank, const uint32_t rmtRank, const std::string& socketTag, const uint32_t listenPort,
92 : u32 reuseIdx, Hccl::Socket*& socket);
93 :
94 : HcclResult ServerInit(
95 : const uint32_t myRank, const uint32_t rmtRank, const std::string& socketTag, u32 reuseIdx, uint32_t devicePhyId,
96 : uint32_t remoteDevicePhyId);
97 : HcclResult GetConnectedSocket(
98 : const uint32_t myRank, const uint32_t rmtRank, const std::string& socketTag, u32 reuseIdx,
99 : const uint32_t listenPort, Hccl::Socket*& socket, uint32_t devicePhyId, uint32_t remoteDevicePhyId);
100 :
101 : HcclResult CreateChannel(
102 : EndpointHandle endpointHandle, CommEngine engine, u32 reuseIdx, HcommChannelDesc* channelDescs,
103 : ChannelHandle* channels);
104 :
105 : HcclResult DestroyChannel(CommEngine engine, u32 reuseIdx);
106 :
107 : bool IsChannelNotExist(CommEngine engine, u32 reuseIdx);
108 :
109 : // 持锁返回 channelHandles_ 副本,避免外部持有引用时与 CreateChannel/DestroyChannel 并发修改产生数据竞争
110 : std::unordered_map<CommEngine, std::vector<ChannelHandle>> GetChannelHandles() const;
111 :
112 : // 持锁读取指定引擎指定槽位的句柄,避免外部引用内部向量造成并发读写
113 : bool GetChannelHandle(CommEngine engine, u32 reuseIdx, ChannelHandle& handle) const;
114 :
115 : // 反查 handle -> (engine, 真实槽位)
116 : bool FindChannelLoc(ChannelHandle handle, CommEngine& engine, u32& reuseIdx) const;
117 :
118 : private:
119 : HcclResult EnsureSocketMgrCompat(const uint32_t myRank, const std::string& socketTag);
120 : Hccl::SocketConfig BuildSocketConfig(const Hccl::LinkData& linkData, const std::string& socketTag);
121 : HcclResult HandleHostSocketOrBuildLinkData(
122 : const uint32_t myRank, const uint32_t rmtRank, const std::string& socketTag, u32 reuseIdx,
123 : const uint32_t listenPort, Hccl::Socket*& socket, uint32_t devicePhyId, uint32_t remoteDevicePhyId,
124 : Hccl::LinkData& linkData, bool& isHost);
125 : HcclResult GetSocketInternal(
126 : const uint32_t myRank, const uint32_t rmtRank, const std::string& socketTag, u32 reuseIdx,
127 : const uint32_t listenPort, Hccl::Socket*& socket, uint32_t devicePhyId, uint32_t remoteDevicePhyId,
128 : bool connectMode);
129 :
130 : EndpointDesc localEndpointDesc_{};
131 : EndpointDesc remoteEndpointDesc_{};
132 : std::unique_ptr<Hccl::SocketManager> socketMgrCompat_;
133 : std::mutex socketMgrMtx_;
134 : std::unordered_map<CommEngine, std::vector<ChannelHandle>> channelHandles_{};
135 : // handle -> (engine, 真实槽位) 反查索引
136 : std::unordered_map<ChannelHandle, std::pair<CommEngine, u32>> handleToLoc_{};
137 : // 保护 channelHandles_ 与 handleToLoc_ 的并发访问
138 : mutable std::mutex channelMtx_{};
139 : Hccl::RankIpPortMapPtr rankIpPortMap_;
140 : uint32_t devicePhyId_{};
141 : std::unique_ptr<SocketMgr> socketMgr_;
142 : };
143 :
144 : } // namespace hcomm
145 :
146 : #endif // ENDPOINT_PAIR_H
|