已合并
[fix]远端内存实例级管理 #5149
littlemons创建于 9月8日
[fix]远端内存实例级管理 #5149
已合并
littlemons创建于 9月8日
littlemons
9月8日

描述

改动原因:多个 endpointHandle/endpoint 实例若持有相同的 endpointDesc,对相同远端内存执行 HcommMemImport 时会误判为重复导入而报 HCCL_E_INTERNAL(原 E_AGAIN),且进程级共享 mgr 的引用计数跨实例串账,存在 ref 泄漏。

改动方法:将内存管理的"本端"与"远端"两条线拆开,各自回到正确的归属层:

  1. 接口拆分:RegedMemMgr 拆为 LocalRegedMemMgr(注册/注销/导出/枚举)、RemoteRegedMemMgr(导入/关闭)两个独立接口。hccs/aicpu_ts/NIC 插件等本远端操作天然耦合的形态只继承 LocalRegedMemMgr(消除多继承的菱形风险),其远端接口经 RemoteRegedMemMgrForwarder(RemoteRegedMemMgr 派生的纯转发视图)包装后由 GetRemoteRegMemMgr() 对外暴露,转发到同一 mgr 对象的同一实现,行为与拆分前一致。
  2. 远端内存下沉到 Endpoint 实例级:新增实例级 EndpointRemoteRegedMemMgr(RemoteRegedMemMgr 的唯一实现,RoCE/Ub 两族差异通过 MemDescParser/RemoteBufferCreator 注入适配),远端导入的引用计数收缩到 Endpoint 实例内;相同 endpointDesc 的不同实例互不干扰,重复导入在本实例内幂等成功(ref+1),不再报错。进程级 mgr(RoceRegedMemMgr/UbRegedMemMgr/UbMemRegedMemMgr)瘦身为只管本端内存。
  3. 远端内存 key 增加进程维度:memDesc 尾部追加 8 字节 pid,远端内存 key 变为 {endpointDesc, pid, BufferKey},区分同一 endpointDesc 下不同远端进程的内存;旧格式 memDesc 导入直接报错,强制两端同版本。
  4. Endpoint 访问入口拆分:Endpoint::GetRegedMemMgr() 拆为 GetLocalRegMemMgr()(纯虚)+ GetRemoteRegMemMgr()(默认 nullptr,不支持远端导入的 endpoint 无需 override),C API 适配层按操作类型分发到对应 mgr。
  5. memDesc 序列化/反序列化收敛:memDesc 布局(DTO + EndpointDesc + pid)的构建与解析收敛为 reged_mem_mgr.h 中的 BuildMemDesc/ParseMemDesc 一对函数,同文件成对维护,RoCE/Ub 的导出与导入路径统一复用;解析侧保留长度校验、DTO 回读校验(拦截旧格式错位)与异常兜底。

本变更为内部实现重构 + 行为修复,对外 C API 签名无变化,include/ 头文件无变更,不涉及 API 兼容性问题。

变更类型

请选择本次引入的变更类型:

关联的Issue

NA

测试

已完成的测试用例和场景:

  1. 全量RDV测试(A2、A3、A5)
  2. 新增 ut_endpoint_remote_mem_mgr.cc,覆盖实例级远端内存管理核心场景:
    • 同 {endpointDesc, pid} 重复导入:幂等成功、引用计数叠加,不报 E_AGAIN
    • 同 endpointDesc 不同 pid:各自独立管理,互不冲突
    • 两次导入后逐次 unimport:第一次仅减引用,最后一次才真正删除并清理
    • 旧格式 memDesc(无 pid):导入报 HCCL_E_INTERNAL(含长度不足、长度达标但格式错位两种场景)
    • import/unimport 参数判空、owner 不存在返回 NOT_FOUND
    • 重复导入跳过 creator_(Ut_MemoryImport_When_Duplicate_Expect_CreatorCalledOnce)
  3. 存量 UT 适配:stub endpoint 统一改为实现 GetLocalMemMgr(),mock 按 Local/Remote 接口分别打桩,C API 转发路径用例全部适配。
  4. 验证方法:bash build.sh -u(编译并运行 UT)。

补充的UT用例:

  • test/ut/framework/next/comms/endpoints/reged_mems/ut_endpoint_remote_reged_mem_mgr.cc(新增 10 个用例)

文档更新

  • HcommMemUnimport.md
  • HcommMemImport.md

合入检查

likedislike
Pull Request已成功合入, 合并人@CANN-robot
(感谢 littlemons 的贡献)
Llittlemons
9月8日 创建了 pull request,commit 84189d48
atomgit-bot
atomgit-bot
9月8日 评论:

变更摘要

本 PR 重构远端内存(远端导入/注销)的管理归属:将原位于进程级 RoceRegedMemMgr/UbRegedMemMgr 中的 MemoryImport/MemoryUnimport 逻辑整体迁移到新增的 Endpoint 实例级 wrapper RemoteMemMgrBase(派生 RoceRemoteMemMgr/UbRemoteMemMgr),进程级 mgr 只保留本端注册/注销/导出能力。各 Endpoint(cpu_roce_endpoint、cpu_urma_endpoint、uboe_endpoint、urma_endpoint、ub_rtp_endpoint)不再将 regedMemMgr_ 强转为具体进程级类型,而是将进程级 mgr 包成实例级 wrapper 后以 RegedMemMgr 基类指针持有。远端内存归属键由仅 endpointDesc 扩展为 {endpointDesc, pid}(新增 RemoteMemOwnerKey),内存描述符(memDesc)尾部追加 u64 pid 字段,同描述符重复导入改为幂等叠加实例内引用计数(不再返回 HCCL_E_AGAIN),以解决多个 Endpoint 实例共享进程级 mgr 时的重复导入报错与引用泄漏问题。

主要改动

  • 新增实例级远端内存管理 wrapper(endpoint_remote_mem_mgr.h): 新增模板类 RemoteMemMgrBase 及 RoceRemoteMemMgr/UbRemoteMemMgr 两个具体类,本端接口(RegisterMemory/UnregisterMemory/MemoryExport/GetAllMemHandles)纯转发进程级 mgr,远端接口(MemoryImport/MemoryUnimport)由实例自管,按 {endpointDesc, pid} 键管理远端缓冲并支持幂等导入与引用计数递减。
  • 远端内存职责从进程级 mgr 剥离: roce_reged_mem_mgr.cc/h 与 ub_reged_mem_mgr.cc/h 删除 MemoryImport、MemoryUnimport、GetParamsFromMemDesc 实现及 remoteRdmaRmaBufferMgrs_/remoteUbRmaBufferMgrs_ 成员,reged_mem_mgr.h 中这两个接口改为带默认"不支持"实现(返回 HCCL_E_INTERNAL)的非纯虚函数。
  • 内存描述符布局新增 pid 字段: RoceRegedMemMgr::GetMemDesc 与 UbRegedMemMgr::GetMemDesc 在 DTO 序列化 + EndpointDesc 之后追加 u64 getpid(),旧格式(不带 pid)的 desc 在解析时直接报错,强制两端同版本。
  • 各 Endpoint 接入实例级 wrapper: cpu_roce_endpoint.cc、cpu_urma_endpoint.cc、uboe_endpoint.cc、urma_endpoint.cc 改为先取进程级 mgr 再 std::make_shared<RoceRemoteMemMgr>/<UbRemoteMemMgr>(procMgr, ctxHandle_),ub_rtp_endpoint.cc 由实例自建 UbRegedMemMgr 后同样包 wrapper;对应头文件中 regedMemMgr_ 类型统一改为 std::shared_ptr<RegedMemMgr>。
  • 补充/调整单元测试: 新增 ut_endpoint_remote_mem_mgr.cc 覆盖空指针校验、旧格式 desc 报错、同键幂等导入引用叠加、不同 pid 独立管理、末次 unimport 擦除 owner、本端接口纯转发等场景;ut_roce_mem_test.cc 删除随旧实现移除的 GetParamsFromMemDesc 用例,ut_hcomm_mem_test.cc、ut_cpu_urma_endpoint.cc 相应更新注释与 mock 描述。
likedislike
不准确?
atomgit-bot
atomgit-bot
9月8日 评论:

代码审查

已完成对全部 20 个变更文件的逐一审查。以下为结论。

审查结论

发现 4 项问题(1 项 P0、1 项 P2、2 项 P3):

  • P0(高置信 0.85):src/base_comm/resources/endpoints/cpu_roce_endpoint.cc:72 将 std::make_shared<RoceRemoteMemMgr> 赋给成员 regedMemMgr_,但同 PR 未修改 cpu_roce_endpoint.h(不在变更清单内),其成员声明仍为 std::shared_ptr<RoceRegedMemMgr>;RoceRemoteMemMgr 与 RoceRegedMemMgr 无继承关系,shared_ptr 无法转换,属直接编译失败。其余四个 endpoint 头文件均已同步改为 shared_ptr<RegedMemMgr>,唯独 RoCE 头被遗漏。
  • P2(置信 0.55):endpoint_remote_mem_mgr.h 新解析器只校验 descLen 下限,旧版本无 pid 的 desc(DTO 长度 ≥8 时)可绕过检查被静默错位解析(pid/desc/DTO 偏移全错),混合版本滚动升级时导致导入记账错误、注销 E_NOT_FOUND 泄漏或 Deserialize 异常穿出 C-API。
  • P3(置信 0.70):GetParamsFromMemDesc 中 resize(TRANSPORT_EMD_ESC_SIZE) 后立即被 assign 覆盖,无用预分配(可选优化)。
  • P3(置信 0.40):RemoteMemOwnerKey::operator== 对 EndpointDesc 整结构体(含 padding)memcmp,与仓库内既有"字段级 hash/compare 规避 padding 误判"的做法相悖,padding 不稳定时同一远端内存可能被识别为不同 owner。

逐文件核对:

  • cpu_roce_endpoint.cc — 发现 P0(见上)
  • cpu_urma_endpoint.cc / cpu_urma_endpoint.h — 无问题(AttachCache/Init 与头文件类型一致,ctxHandle_ 先于 wrapper 构造赋值)
  • ub_rtp_endpoint.cc / ub_rtp_endpoint.h — 无问题(两次 EXCEPTION_CATCH 覆盖两个分配步骤,失败均回滚 ReleaseEndpointCtx)
  • uboe_endpoint.cc / uboe_endpoint.h — 无问题
  • urma_endpoint.cc / urma_endpoint.h — 无问题
  • endpoint_remote_mem_mgr.h(新增)— 发现 P2 + 2 项 P3(见上)
  • reged_mem_mgr.h — 无问题(MemoryImport/Unimport 改为带默认报错实现的虚函数,Hccs/AicpuTs/UbMem 等派生类仍自行覆盖,无行为回归)
  • roce_reged_mem_mgr.cc / roce_reged_mem_mgr.h — 无问题(pid 追加有 memcpy_s 校验;远端逻辑已正确迁移至 wrapper)
  • ub_reged_mem_mgr.cc / ub_reged_mem_mgr.h — 无问题
  • test/ut/framework/next/CMakeLists.txt — 无问题(新增 UT 源文件路径与文件存在性一致)
  • ut_hcomm_mem_test.cc — 无问题(仅注释修改)
  • ut_endpoint_remote_mem_mgr.cc(新增)— 无确认问题(用例覆盖幂等导入/分 pid 管理/最后引用注销等关键路径;测试以 nullptr rdmaHandle 构造 RemoteRdmaRmaBuffer 的可行性依赖其构造函数实现,未能静态确认,但生产路径同构)
  • ut_roce_mem_test.cc — 无问题(删除的用例与被移除的 GetParamsFromMemDesc API 配套)
  • ut_cpu_urma_endpoint.cc — 无问题(mock 派生自 UbRegedMemMgr,可赋给基类指针成员)

总体风险判断: 本次改动(远端内存导入/注销从进程级 mgr 下移到 Endpoint 实例级 wrapper)设计方向清晰,本端接口转发与实例级 refcount 语义自洽,测试覆盖了核心路径。但存在一个必须修复的 P0 编译问题(cpu_roce_endpoint.h 类型未同步),以及一个影响混合版本部署的 desc 格式兼容性缺口(P2),建议修复后再合入。

类型 数量
🔴 阻塞 1
🟡 建议 0

⛔ 需要修改

likedislike
不准确?
CANN-robotCANN-robot成员
9月8日 添加了label:cann-cla/yes
CANN-robot
CANN-robot成员
9月8日 评论:

Thanks for your pull-request.
The full list of commands accepted by me can be found at here.
You can get sig-info at here.
You can self-configure the PR merge rules for this repository. For more details, please refer to Here.
For more, you also can visit HICANN.


PR Approval Progress

✅ Congratulations! All modules have met the lgtm and approve requirements.

Module Approval Details

module lgtm status approve status
docs ✅ 颜业峰, 严正行 (2/2) ✅ 颜业峰 (1/1)
src/base_comm ✅ 孙哲芃, 颜业峰, 严正行 (3/2) ✅ 孙哲芃, 颜业峰 (2/1)
src/base_comm/resources/endpoints/endpoint.h ✅ 严正行, 颜业峰 (2/2) ✅ 颜业峰 (1/1)
src/base_comm/resources/reged_mems/reged_mem_mgr.h ✅ 颜业峰, 严正行 (2/2) ✅ 颜业峰 (1/1)
test ✅ 颜业峰, 严正行, 孙哲芃 (3/2) ✅ 孙哲芃, 颜业峰 (2/1)

💡 Tip:

  • Committer can comment /approve or /lgtm
  • Commenting /approve implies both code review (lgtm) and intent to merge (approve)

CLA Signature Pass

littlemons, thanks for your pull request. All authors of the commits have signed the CLA. 👍

likedislike
此处折叠了260条消息 查看更多
严正行严正行成员
9月15日 解决了最后一个问题
CANN-robotCANN-robot成员
9月15日 添加了label:lgtm
严正行
严正行成员
9月15日 评论:

/lgtm

likedislike
CANN-robotCANN-robot成员
9月15日 合入了pull request
LLeewis成员
9月17日 关联了issue:[Bug-Report|缺陷反馈]: 两个独立的endpoint import同一块远端内存,底层UbRegedMemMgr拒绝重复注册