HIXL C++ 数据结构详解:内存描述、传输请求与异步状态机

HIXL C++ 数据结构详解:内存描述、传输请求与异步状态机 HIXL C 数据结构详解内存描述、传输请求与异步状态机【免费下载链接】hixlHIXLHuawei Xfer Library是一个灵活、高效的昇腾单边通信库面向集群场景提供简单、可靠、高效的点对点数据传输能力。项目地址: https://gitcode.com/cann/hixlHIXLHuawei Xfer Library是昇腾平台面向集群场景的单边通信库其 C 接口依赖一组精确定义的数据结构完成内存注册、建链、读写传输与异步状态查询。本文以 HIXL C API 的数据结构为核心逐个讲解MemDesc、TransferOpDesc、TransferArgs、GetTransferStatusArgs、NotifyDesc、FeatureType等类型的字段语义、与对应接口的配合方式及底层实现行为并结合仓库源码与单元测试给出可验证的依据。读完本文你将能准确构造 HIXL 各类接口的参数对象理解异步传输请求从下发、查询到资源释放的完整生命周期并能在业务代码中正确使用预留字段与能力探测机制。一、数据结构在 HIXL 中的定位HIXL 对外暴露的 C 接口构造函数、Initialize、RegisterMem、TransferSync、TransferAsync、GetTransferStatus等定义在 include/hixl/hixl.h而所有接口涉及的数据结构统一声明在头文件 include/hixl/hixl_types.h 的hixl命名空间中。该头文件同时定义了Statusuint32_t、AscendString、OPTION_*初始化选项常量以及SUCCESS、PARAM_INVALID等错误码常量。从源码结构看HIXL 的数据结构可归为四类本文按此组织内存描述类MemDesc、MemHandle、MemType——服务于RegisterMem/DeregisterMem传输请求类TransferOp、TransferOpDesc、TransferArgs、TransferReq——服务于TransferSync/TransferAsync异步状态类TransferStatus、GetTransferStatusArgs、TransferResult、AsyncConnectStatus——服务于GetTransferStatus/GetAsyncConnectStatus通知与能力类NotifyDesc、FeatureType、FEATURE_SUPPORTED/FEATURE_NOT_SUPPORTED——服务于SendNotify/GetNotifies/GetCapability。这些类型在头文件中均以 ABI 稳定为导向设计绝大多数结构体末尾带有reserved预留数组便于后续版本在不破坏二进制兼容的前提下扩展字段。二、内存描述类MemDesc、MemHandle、MemType2.1 MemDesc内存的描述信息MemDesc用于向 HIXL 描述一块待注册的内存区域定义如下struct MemDesc { uintptr_t addr; size_t len; uint8_t reserved[128] {}; };字段类型说明addruintptr_t内存起始地址。Device 内存通常来自aclrtMalloc的返回指针Host 内存通常来自aclrtMallocHostHDK 25.5 之前约束场景或malloc等lensize_t内存长度单位字节reserveduint8_t[128]预留字段保持结构体 ABI 稳定使用默认值即可MemDesc的典型用法出现在 examples/cpp/hixl_example_quickstart.cpp先用aclrtMalloc申请 Device 内存再把指针与长度填入MemDescACL_EXIT_ON_FAILURE(aclrtMalloc(ctx.buf, kBufSize, ACL_MEM_MALLOC_HUGE_ONLY)); ctx.desc.addr reinterpret_castuintptr_t(ctx.buf); ctx.desc.len kBufSize;之后将desc传入RegisterMem完成注册。需要注意的是接口文档 HIXL-interface.md 对注册内存有明确约束建议单个 Hixl 实例注册的内存个数不超过 4KDevice 内存建议使用aclrtMalloc申请若通过 HCCS 传输则内存分配规则需配置为ACL_MEM_MALLOC_HUGE_ONLYHost 内存按型号不同有 20GB1TB 的注册上限。2.2 MemHandle内存的 HandleMemHandle是内存注册成功后的句柄类型用于后续解注册using MemHandle void *;RegisterMem成功后输出该句柄DeregisterMem接收该句柄进行解注册。接口文档给出了两个幂等语义对同一内存区域相同 addr 和相同 len重复调用RegisterMem会返回 SUCCESS 并返回与首次注册相同的mem_handle不会创建新的底层资源对同一mem_handle重复调用DeregisterMem第一次正确释放资源后续调用返回 SUCCESS 但不执行实际操作传入nullptr则返回PARAM_INVALID。2.3 MemType内存的类型enum MemType { MEM_DEVICE, MEM_HOST };枚举值说明MEM_DEVICEDevice 侧内存MEM_HOSTHost 侧内存MemType决定内存注册的路径。在 quickstart 示例中两端均注册 Device 内存HixlExitOnFailure(ctx.engine.RegisterMem(ctx.desc, MEM_DEVICE, ctx.handle), RegisterMem);从仓库测试 tests/cpp/hixl/engine/hixl_engine_uboe_unittest.cc 可以看到测试用例会分别构造src_memHost、device_memDevice等不同MemDesc并配合MEM_HOST/MEM_DEVICE注册以覆盖不同传输路径。三、传输请求类TransferOp、TransferOpDesc、TransferArgs、TransferReq3.1 TransferOp传输操作的类型enum TransferOp { READ, WRITE };枚举值说明READ将远端内存读到本地WRITE将本地内存写到远端该枚举直接决定TransferSync/TransferAsync的数据方向。quickstart 中 Client 用READ从 Server 读取数据HixlExitOnFailure(ctx.engine.TransferSync(kServerEngine, READ, {ctx.op}, kTimeoutMs), TransferSync);3.2 TransferOpDesc传输操作的描述信息struct TransferOpDesc { uintptr_t local_addr; uintptr_t remote_addr; size_t len; };字段类型说明local_addruintptr_t本地内存地址需在当前 HIXL 注册或在中转模式下合法remote_addruintptr_t远端内存地址需在远端 HIXL 注册lensize_t传输长度单位字节TransferOpDesc是单次传输的地址描述而TransferSync/TransferAsync接收std::vectorTransferOpDesc支持批量传输。quickstart 中通过 socket 交换远端地址后构造该结构体ctx.op.local_addr ctx.desc.addr; ctx.op.remote_addr remote_addr; ctx.op.len kBufSize;接口文档对TransferSync的约束包括op_desc中的本地内存和远端内存有一个未注册就会判断为需要走中转传输模式中转传输模式下所有op_desc的传输类型需相同Fabric Mem 传输模式下系统会根据第一个op_desc的内存类型判定传输方向。TransferAsync当前仅支持直传暂不支持中转传输。3.3 TransferArgs传输操作的可选参数struct TransferArgs { const void *user_data nullptr; // 用户自定义信息需配合获取全部异步传输请求状态接口使用 uint8_t reserved[120] {}; // 预留参数 };字段类型说明user_dataconst void *用户自定义信息随请求注册批量查询状态时原样带回见TransferResultreserveduint8_t[120]预留参数user_data是异步传输请求与业务上下文关联的关键通道。从实现看src/hixl/engine/hixl_engine.cc 在TransferAsync内部会调用client_manager_.RegisterTransferReq(req, client_ptr, optional_args.user_data)将user_data与请求句柄绑定保存后续通过GetTransferStatus(GetTransferStatusArgs, std::vectorTransferResult)批量查询时TransferResult会携带该user_data原样返回从而让调用方无需维护req - 业务对象的映射表。3.4 TransferReq传输请求的 Handleusing TransferReq void *;TransferReq是TransferAsync输出的请求句柄也是单请求查询接口GetTransferStatus(const TransferReq req, TransferStatus status)的输入。其生命周期与异步请求绑定查询到COMPLETED或FAILED后资源被释放该场景下不支持再次查询若用户判断任务超时需要调用Disconnect销毁链路并清理相关资源。四、异步状态类TransferStatus、GetTransferStatusArgs、TransferResult、AsyncConnectStatus4.1 TransferStatus异步传输的状态enum class TransferStatus { WAITING, COMPLETED, TIMEOUT, //暂不支持 FAILED };枚举值说明WAITING传输等待中COMPLETED传输完成TIMEOUT超时当前版本暂不支持预留FAILED传输失败4.2 GetTransferStatusArgs获取全部异步传输请求状态时的参数struct GetTransferStatusArgs { uint32_t max_query_count UINT32_MAX; // 最大查询出的传输请求状态的个数 bool skip_waiting false; // 查询是否跳过状态为TransferStatus::WAITING的传输请求 uint8_t reserved[123] {}; // 预留参数 };字段类型默认值说明max_query_countuint32_tUINT32_MAX单次最多返回的传输请求状态个数用于控制批量结果规模skip_waitingboolfalse是否跳过WAITING状态的请求便于快速收敛到已完成/失败的结果reserveduint8_t[123]{}预留参数接口文档给出了批量查询的调用示例GetTransferStatusArgs args { .max_query_count 4, .skip_waiting true }; std::vectorTransferResult results; Status query_status client_engine.GetTransferStatus(args, results);批量查询接口的返回值中有一个值得注意的UNSUPPORTED分支当 Hixl 初始化 options 未配置 LocalCommRes 的 version 为 1.3且未配置GlobalResourceConfig的comm_resource_config.protocol_desc包含uboe:device或ub_rtp:device时不支持通过该接口查询。4.3 TransferResult每一个请求的结果信息struct TransferResult { TransferReq req nullptr; // 传输请求的Handle const void *user_data nullptr; // 用户自定义信息 TransferStatus status TransferStatus::WAITING; // 传输请求状态 uint8_t reserved[108] {}; // 预留参数 };字段类型说明reqTransferReq传输请求句柄对应TransferAsync的输出user_dataconst void *下发请求时TransferArgs.user_data中原样带回的用户信息statusTransferStatus该请求当前的传输状态reserveduint8_t[108]预留参数4.4 批量查询的底层行为源码级验证GetTransferStatus(const GetTransferStatusArgs args, std::vectorTransferResult results)的实现在 src/hixl/engine/hixl_engine.cc。从实现看可以确认以下行为当args.max_query_count 0时直接返回不产出结果对已断链引擎上残留的请求会以TransferStatus::FAILED产出结果当args.skip_waiting为 true 时状态为WAITING的请求会被跳过不放入 results但仍在内部保留每收集一个结果即检查results.size() max_query_count达到上限立即停止保证批量查询有界返回的TransferResult携带req与user_data其中req与内部注册的请求一一对应。单元测试 tests/cpp/hixl/engine/hixl_engine_unittest.cc 从三个维度验证了上述语义ReturnsResultsInSubmitOrderWithUserData结果按提交顺序返回且user_data原样带回状态为COMPLETED的请求查询后即释放GetClientByReq返回 nullptrWAITING的请求仍保留SkipWaitingAndMaxQueryCountFilterResultsskip_waiting true且max_query_count 1时只返回第一个非 WAITING 结果DisconnectedEngineStopsAtMaxQueryCount引擎断链后查询请求以FAILED返回且受max_query_count限制。注意单请求查询与批量查询在资源释放语义上一致——某请求状态为COMPLETED或FAILED后相关资源即被释放再次查询将不再返回该请求状态。4.5 AsyncConnectStatus异步建链/拆链的状态enum class AsyncConnectStatus { NOT_CONNECT, // 未连接 CONNECT_PENDING, // 建链待执行 CONNECTING, // 建链执行中 CONNECTED, // 建链成功 CONNECT_FAILED, // 建链失败 DISCONNECT_PENDING, // 断链待执行 DISCONNECTING // 断链执行中 };枚举值说明NOT_CONNECT未连接CONNECT_PENDING建链任务已入队待执行CONNECTING建链执行中CONNECTED建链成功CONNECT_FAILED建链失败DISCONNECT_PENDING断链任务已入队待执行DISCONNECTING断链执行中该枚举用于GetAsyncConnectStatus的两个重载单查询版本GetAsyncConnectStatus(const AscendString remote_engine, AsyncConnectStatus status)与全量查询版本GetAsyncConnectStatus(std::mapAscendString, AsyncConnectStatus statuses)。接口文档的约束说明指出接口返回值仅表示调用是否成功异步建链/断链任务状态由输出参数表示ConnectAsync/DisconnectAsync不与同步版Connect/Disconnect混用对同一 remote_engine 下发多个任务时按下发顺序执行不同 remote_engine 的任务允许并发执行获取的状态为最新下发任务的状态。五、通知与能力类NotifyDesc、FeatureType、能力常量5.1 NotifyDescNotify 的描述信息struct NotifyDesc { AscendString name; AscendString notify_msg; };字段类型说明nameAscendStringNotify 名称长度上限 1024 字符notify_msgAscendStringNotify 消息内容长度上限 1024 字符NotifyDesc服务于SendNotify/GetNotifies这对接口Client 通过SendNotify(remote_engine, notify, timeout)向 Server 发送通知Server 通过GetNotifies(std::vectorNotifyDesc notifies)一次性取回并清空已收到的全部 Notify。接口文档给出的示例NotifyDesc notify; notify.name AscendString(cache_ready); notify.notify_msg AscendString(block_0); Status ret client_engine.SendNotify(remote_engine, notify, 1000);约束要点notify.name/notify_msg长度超过 1024 或timeout_in_millis 0时返回PARAM_INVALID每条链路最多存在 4096 条 Notify需要远端及时调用GetNotifies消费防止触发上限导致发送失败。单元测试 tests/cpp/hixl/engine/hixl_engine_unittest.cc 中大量用例覆盖了SendNotify成功、超时、GetNotifies取回并清空等路径。5.2 FeatureType库能力特性类型enum FeatureType : int32_t { AUTO_CONNECT 0, CLIENT_SERVER_COMM 1, };枚举值描述AUTO_CONNECTAuto Connect 模式对应 Initialize 时 OPTION_AUTO_CONNECT 选项CLIENT_SERVER_COMMClient/Server 通信模式即 Server 端监听端口、Client 端发起建链的能力FeatureType专用于Hixl::GetCapability(FeatureType, int32_t value)能力探测接口。该枚举有一项硬性约定枚举值必须显式赋值新增能力仅允许在末尾扩展这与 include/hixl/hixl_types.h 头文件中的注释一致目的是保证新旧库版本间的 ABI 兼容。5.3 FEATURE_SUPPORTED / FEATURE_NOT_SUPPORTEDconstexpr int32_t FEATURE_SUPPORTED 1; constexpr int32_t FEATURE_NOT_SUPPORTED 0;这两个常量是GetCapability输出参数value的取值1 表示支持0 表示不支持含未知特性。接口文档给出的探测示例int32_t value FEATURE_NOT_SUPPORTED; Status ret Hixl::GetCapability(AUTO_CONNECT, value); bool supports_auto_connect (value FEATURE_SUPPORTED);GetCapability是静态方法无需调用Initialize即可使用适合上层在初始化前探测当前库版本是否支持 Auto Connect、Client/Server 通信等能力避免硬编码默认值或与旧版.so不兼容。当feature_type为负数时返回PARAM_INVALID未知或不支持的特性类型返回 SUCCESS 且value为FEATURE_NOT_SUPPORTED。六、数据结构与错误码的关联Status在 include/hixl/hixl_types.h 中被定义为uint32_t其取值常量与各接口的返回语义详见 HIXL-error-code.md。与本文数据结构直接相关的典型错误码包括错误码含义与数据结构的关联场景PARAM_INVALID (103900)参数错误MemDesc地址非法、DeregisterMem(nullptr)、notify.name/notify_msg超长、timeout_in_millis 0等NOT_CONNECTED (103902)没有建链TransferSync/TransferAsync在未建链时下发请求ALREADY_CONNECTED (103903)已经建链对已建链对端重复ConnectUNSUPPORTED (103905)不支持的参数或接口批量GetTransferStatus在未满足 LocalCommRes 1.3 等条件时返回RESOURCE_EXHAUSTED (203900)资源耗尽ConnectAsync/DisconnectAsync任务队列已满FAILED (503900)通用失败通用传输失败七、实战数据结构在完整流程中的串联以 examples/cpp/hixl_example_quickstart.cpp 的 Client/Server 流程为例可以看到本文所有传输类数据结构的完整配合方式初始化aclrtSetDevice后构造std::mapAscendString, AscendString opts如配置OPTION_GLOBAL_RESOURCE_CONFIG为{comm_resource_config.protocol_desc: [hccs:device]}调用engine.Initialize(local, opts)申请与描述内存aclrtMalloc申请 Device 内存后填充MemDesc{addr, len}注册内存RegisterMem(desc, MEM_DEVICE, handle)得到MemHandle交换地址通过 socket 交换远端地址构造TransferOpDesc{local_addr, remote_addr, len}建链Connect(remote_engine, timeout_in_millis)传输TransferSync(remote_engine, READ, {op}, timeout)完成远端读异步场景则改用TransferAsync(remote_engine, operation, op_descs, TransferArgs{user_data}, req)获得TransferReq再用GetTransferStatus单请求或批量轮询断链与清理Disconnect→DeregisterMem(handle)→aclrtFree→Finalize()。上述流程中MemDesc、MemType、MemHandle构成内存生命周期TransferOp、TransferOpDesc、TransferArgs、TransferReq构成请求生命周期TransferStatus、GetTransferStatusArgs、TransferResult构成状态查询链路各司其职且环环相扣。八、快速参考表数据结构类型关联接口核心字段MemDescstructRegisterMemaddr、lenMemHandlevoid *RegisterMem / DeregisterMem—MemTypeenumRegisterMemMEM_DEVICE / MEM_HOSTTransferOpenumTransferSync / TransferAsyncREAD / WRITETransferOpDescstructTransferSync / TransferAsynclocal_addr、remote_addr、lenTransferArgsstructTransferAsyncuser_dataTransferReqvoid *TransferAsync / GetTransferStatus—TransferStatusenum classGetTransferStatusWAITING / COMPLETED / TIMEOUT / FAILEDGetTransferStatusArgsstructGetTransferStatus批量max_query_count、skip_waitingTransferResultstructGetTransferStatus批量req、user_data、statusAsyncConnectStatusenum classGetAsyncConnectStatus7 种建链/断链状态NotifyDescstructSendNotify / GetNotifiesname、notify_msgFeatureTypeenumGetCapabilityAUTO_CONNECT、CLIENT_SERVER_COMM如需查看各数据结构在真实接口签名中的用法与完整约束可进一步阅读 HIXL-interface.md如需确认错误码语义可参考 HIXL-error-code.md完整可运行示例位于 examples/cpp 目录。【免费下载链接】hixlHIXLHuawei Xfer Library是一个灵活、高效的昇腾单边通信库面向集群场景提供简单、可靠、高效的点对点数据传输能力。项目地址: https://gitcode.com/cann/hixl创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考