开发者
资源

HcclCommSymWinRegister

产品支持情况

产品

是否支持

Atlas 350 加速卡

Atlas A3 训练系列产品 / Atlas A3 推理系列产品

Atlas A2 训练系列产品 / Atlas A2 推理系列产品

Atlas 200I/500 A2 推理产品

Atlas 推理系列产品

Atlas 训练系列产品

功能说明

用户在申请虚拟内存和物理内存并完成映射后,可调用此接口将虚拟内存注册为对称内存。

对称内存是一种内存管理模型,允许并行处理单元(例如每个rank)以一种“全局可见”但“无需显式地址交换”的方式访问彼此的内存。

对称内存的基本实现模型如下图所示,每个rank通过提前预留相同大小、相同布局的虚拟地址来实现。

  • 为每个rank申请虚拟内存,假设每个rank对应的虚拟内存大小为heap_size,通信域中的rank数量为rank_size,则通信域中总虚拟内存大小为heap_size*rank_size。
  • 每个rank的虚拟地址布局都是相同的。
  • 不同rank的物理地址映射到每个rank对应位置的虚拟地址,实现对其他rank内存的访问。

对称内存功能使得HCCL可以直接对业务传入的内存进行操作,无需经过中间缓冲区(HCCL buffer),从而减少内存拷贝开销。

函数原型

1
HcclResult HcclCommSymWinRegister(HcclComm comm, void *addr, uint64_t size, CommSymWindow *winHandle, uint32_t flag)

参数说明

参数名

输入/输出

说明

comm

输入

HCCL通信域,建议使用超节点内最大的通信域,即覆盖最大卡数的通信域。

初始化通信域时可以通过HcclCommConfig的hcclSymWinMaxMemSizePerRank参数设置每个rank预留的对称内存大小,若不设置hcclSymWinMaxMemSizePerRank,使用默认值16GB。

当前通信域预留的总虚拟对称内存大小为:rankSize * HcclCommConfig.hcclSymWinMaxMemSizePerRank。

addr

输入

预留的虚拟内存地址。

虚拟内存需要调用aclrtReserveMemAddress接口预留。

size

输入

对称内存窗口的大小,0 < size <= HcclCommConfig.hcclSymWinMaxMemSizePerRank,并且size不能超过“与addr做映射的物理内存”大小(即调用aclrtMallocPhysical接口申请的Device物理内存)。

注:对称内存注册按物理内存的大小对齐,实际注册的对称内存窗口大小等于“与addr做映射的物理内存”的大小。

winHandle

输出

存放“对称内存窗口资源句柄“的指针。

CommSymWindow类型的定义请参见CommSymWindow

flag

输入

symmetricMemoryFlag类型,是否启用对称内存。

返回值

HcclResult:接口成功返回HCCL_SUCCESS,其他失败。

约束说明

  • 仅支持 Atlas A3 训练系列产品 / Atlas A3 推理系列产品 的超节点内通信。
  • 仅支持通信算子展开模式为AI CPU的场景。
  • 该接口仅支持集合通信算子AllGather、ReduceScatter、AllReduce。
  • 需确保通信域中的所有rank同时调用该注册接口。
  • 所有rank的输入地址映射的物理内存大小一致(对称内存注册按物理内存的大小对齐)。
  • 所有rank调用该接口时,输入的size参数需要保持一致。
  • 使用对称内存功能时,算子的输入、输出内存必须调用此接口注册为对称内存。
  • 调用该接口注册的内存需要使用HcclCommSymWinDeregister接口解注册。

调用示例

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
// 创建并初始化通信域配置项
HcclCommConfig config;
HcclCommConfigInit(&config);
// 按需修改通信域配置
config.hcclSymWinMaxMemSizePerRank = 10; //单位GB, 默认值为16。设置对称堆预留的虚拟内存大小 = rankSize * config.hcclSymWinMaxMemSizePerRank;
// 初始化集合通信域
HcclComm hcclComm;
HCCLCHECK(HcclCommInitRootInfoConfig(rankSize, &rootInfo, deviceId, &config, &hcclComm));
// 创建任务流
aclrtStream stream;
aclrtCreateStream(&stream);
// 物理内存属性配置
int32_t deviceId;
aclrtGetDevice(&deviceId);
aclrtPhysicalMemProp prop;
prop.handleType = ACL_MEM_HANDLE_TYPE_NONE;
prop.allocationType = ACL_MEM_ALLOCATION_TYPE_PINNED;
prop.memAttr = ACL_HBM_MEM_HUGE;
prop.location.id = deviceId;
prop.location.type = ACL_MEM_LOCATION_TYPE_DEVICE;
prop.reserve = 0;
// 获取对齐粒度,通常为2M
size_t granularity = 0;
aclrtMemGetAllocationGranularity(&prop, ACL_RT_MEM_ALLOC_GRANULARITY_RECOMMENDED, &granularity);
// size按粒度对齐
size_t size = 2 * 1024 * 1024;
size_t allocSize = (size + granularity - 1) / granularity * granularity;
// 预留虚拟内存
void *virPtr = nullptr;
aclrtReserveMemAddress(&virPtr, allocSize, 0, nullptr, 1);
// 申请物理内存
aclrtDrvMemHandle handle;
aclrtMallocPhysical(&handle, allocSize, &prop, 0);
// 建立物理到虚拟的映射
aclrtMapMem(virPtr, allocSize, 0, handle, 0);

size_t send_bytes = 4*1024;
size_t recv_bytes = 8*1024;
CommSymWindow sym_win;
// 注册对称内存
HcclCommSymWinRegister(hcclComm, virPtr, send_bytes + recv_bytes, &sym_win, HCCL_WIN_COLL_SYMMETRIC);
// 使用对称内存
void *send_buff = virPtr;    
void *recv_buff = static_cast<char*>(send_buff) + send_bytes;
// 调用集合通信算子
HCCLCHECK(HcclAllGather(send_buff, recv_buff, 1024, HCCL_DATA_TYPE_FP32, hcclComm, stream));
// 阻塞等待任务流中的集合通信任务执行完成
ACLCHECK(aclrtSynchronizeStream(stream));
// 解注册对称内存
HcclCommSymWinDeregister(sym_win);
// 释放内存
aclrtUnmapMem(virPtr);
aclrtFreePhysical(handle);
aclrtReleaseMemAddress(virPtr);
// 销毁任务流
aclrtDestroyStream(stream);
// 销毁通信域
HcclCommDestroy(hcclComm);