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 PROC_REGED_MEM_MGR_CACHE_H
12 : #define PROC_REGED_MEM_MGR_CACHE_H
13 :
14 : #include <cstdint>
15 : #include <functional>
16 : #include <memory>
17 : #include <mutex>
18 : #include <unordered_map>
19 : #include "reged_mem_mgr.h"
20 : #include "ip_address.h"
21 : #include "port.h"
22 : #include "hcomm_res_defs.h"
23 :
24 : namespace hcomm {
25 :
26 : struct MemMgrCacheKey {
27 : u32 devPhyId{0};
28 : CommProtocol protocol{COMM_PROTOCOL_ROCE};
29 : Hccl::IpAddress ip{};
30 : Hccl::PortDeploymentType portType{Hccl::PortDeploymentType::HOST_NET};
31 :
32 335 : bool operator==(const MemMgrCacheKey& other) const
33 : {
34 335 : return devPhyId == other.devPhyId && protocol == other.protocol && ip == other.ip && portType == other.portType;
35 : }
36 : };
37 :
38 : struct MemMgrCacheKeyHash {
39 446 : size_t operator()(const MemMgrCacheKey& k) const
40 : {
41 446 : return Hccl::HashCombine({
42 446 : std::hash<u32>{}(k.devPhyId),
43 446 : std::hash<int>{}(static_cast<int>(k.protocol)),
44 446 : std::hash<Hccl::IpAddress>{}(k.ip),
45 892 : std::hash<int>{}(static_cast<int>(k.portType)),
46 892 : });
47 : }
48 : };
49 :
50 : // 由 endpointDesc.loc.locType 推导 PortDeploymentType
51 200 : inline Hccl::PortDeploymentType LocTypeToPortType(EndpointLocType locType)
52 : {
53 200 : return (locType == ENDPOINT_LOC_TYPE_DEVICE) ? Hccl::PortDeploymentType::DEV_NET :
54 200 : Hccl::PortDeploymentType::HOST_NET;
55 : }
56 :
57 : struct MemMgrEntry {
58 : std::shared_ptr<RegedMemMgr> mgrPtr{nullptr};
59 : u64 refCount{0};
60 : };
61 :
62 : /**
63 : * @note 进程级 RegedMemMgr 复用缓存。同一网卡跨 EndpointHandle 复用实例,跳过冗余硬件注册。
64 : *
65 : * 仍是单例。构造 private、禁止拷贝,GetHolder() 里 static shared_ptr 只 new 一次,
66 : * 之后每次调用返回同一对象的 shared_ptr 拷贝。变的是生命周期,不是实例个数。
67 : * 旧写法是 Meyers 单例(static T + GetInstance 返回 T&),寿命绑在静态析构上;
68 : * 静态对象先构造的晚析构。GetHolder 往往比其它静态对象更晚才第一次调用,
69 : * 退出时自己的 static 会先拆。Endpoint 多持有一份,就能活过那些先构造的静态对象的析构。
70 : *
71 : * 用法:
72 : * 1. Init:把 GetHolder() 存进成员,再用这份指针 GetOrCreate。不要把返回值当临时量用完即弃。
73 : * 2. Destroy / 析构:走持有的指针 Release,再 reset。
74 : * 3. 析构路径不要再调 GetHolder()。函数内那份 static shared_ptr 拆掉后,入口已悬空。
75 : */
76 : class ProcRegedMemMgrCache {
77 : public:
78 : static std::shared_ptr<ProcRegedMemMgrCache> GetHolder();
79 :
80 : // hit: refCount++ 返已有 shared_ptr; miss: 调 creator() 建实例 insert refCount=1
81 : std::shared_ptr<RegedMemMgr>
82 : GetOrCreate(const MemMgrCacheKey& key, std::function<std::shared_ptr<RegedMemMgr>()> creator);
83 :
84 : // refCount--, 归 0 则 erase cacheMap_ 条目
85 : void Release(const MemMgrCacheKey& key);
86 :
87 : ProcRegedMemMgrCache(const ProcRegedMemMgrCache&) = delete;
88 : ProcRegedMemMgrCache& operator=(const ProcRegedMemMgrCache&) = delete;
89 : // shared_ptr 默认删除器在类外 delete,析构必须可访问;构造仍 private,外部不能直接 new。
90 3 : ~ProcRegedMemMgrCache() = default;
91 :
92 : private:
93 3 : ProcRegedMemMgrCache() = default;
94 :
95 : std::mutex mtx_;
96 : std::unordered_map<MemMgrCacheKey, MemMgrEntry, MemMgrCacheKeyHash> cacheMap_;
97 : };
98 :
99 : } // namespace hcomm
100 :
101 : #endif // PROC_REGED_MEM_MGR_CACHE_H
|