集合通信
集合通信是指多个NPU共同参与进行数据传输,从而形成一次集体操作的通信模式,常用于大规模集群中不同NPU之间的梯度同步和参数更新等场景。
HCCL支持AllReduce、Broadcast、AllGather、Scatter、ReduceScatter、Reduce、AlltoAll和AlltoAllV等通信算子,并提供了对应的API供开发者调用,用于快速实现集合通信能力。
AllGather
AllGather操作是将通信域内所有节点的输入按照rank id重新排序(rank id按照从小到大的顺序排序),然后拼接起来,再将结果发送到所有节点的输出buffer。

针对AllGather操作,每个节点都接收按照rank id重新排序后的数据集合,即每个节点的AllGather输出都是一样的。
AllGatherV
AllGatherV操作是将通信域内所有节点的输入按照rank id重新排序(rank id按照从小到大的顺序排序),然后拼接起来,再将结果发送到所有节点的输出。与AllGather操作不同的是,AllGatherV操作支持通信域内不同节点的输入配置不同大小的数据量。

针对AllGatherV操作,每个节点都接收按照rank id重新排序后的数据集合,即每个节点的AllGatherV输出都是一样的。
Reduce
Reduce操作是将通信域内所有rank的输入数据进行归约操作后(支持sum、prod、max、min),再把结果发送到root节点的输出buffer。

注意:通信域内只能有一个root节点。
AllReduce
AllReduce操作是将通信域内所有节点的输入数据进行归约操作后(支持sum、prod、max、min),再把结果发送到所有节点的输出buffer。

注意:每个rank只能有一个输入。
ReduceScatter
ReduceScatter操作是将通信域内所有rank的输入进行归约操作后(支持sum、prod、max、min),再把结果按照rank编号均匀分散到各个rank的输出buffer,每个进程拿到其他进程1/rank_size份的数据进行归约操作。
如下图所示,有rank0、rank1、rank2、rank3四个rank,每个rank的输入数据切分成4份,每个进程分别取每个rank的1/4份数据进行sum操作(或其他操作),将结果发送到输出buffer。

ReduceScatterV
ReduceScatterV操作是将所有rank的输入进行归约操作后(支持sum、prod、max、min),再把结果按照rank编号分散到各个rank的输出buffer,每个进程拿到其他进程对应rank编号的数据进行归约操作。与ReduceScatter操作不同的是,ReduceScatterV操作支持为通信域内不同的节点配置不同大小的数据量。
如下图所示,有rank0、rank1、rank2、rank3四个rank,每个进程分别取其他进程对应rank编号的数据进行sum操作(或其他操作),将结果发送到输出buffer。

AlltoAll
AlltoAll操作是向通信域内所有rank发送相同数据量的数据,并从所有rank接收相同数据量的数据。

AlltoAll操作将输入数据在特定的维度切分成特定的块数,并按顺序发送给其他rank,同时从其他rank接收输入数据,按顺序在特定的维度拼接数据。
AlltoAllVC
AlltoAllVC操作是向通信域内所有rank发送数据(数据量可以定制),并从所有rank接收数据。相比于AlltoAllV,AlltoAllVC通过输入参数sendCountMatrix传入所有rank的收发参数。

接口调用
下面以HcclAllReduce接口为例,介绍其使用示例,HcclAllReduce接口的原型定义如下:
1
|
HcclResult HcclAllReduce(void *sendBuf, void *recvBuf, uint64_t count, HcclDataType dataType, HcclReduceOp op, HcclComm comm, aclrtStream stream) |
HcclAllReduce用于将通信域内所有节点的输入进行归约操作,再把结果发送到所有节点的输出,其中op参数用于指定归约的操作类型,当前版本支持的操作类型有sum、prod、max、min。HcclAllReduce允许每个节点只有一个输入。
如下代码片段所示,将通信域内所有输入内存中的数据,按照float32的数据格式执行加法操作(示例中每个rank中只有一个数据参与),然后把相加结果发送到所有节点的输出内存。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
void* hostBuf = nullptr; void* sendBuf = nullptr; void* recvBuf = nullptr; uint64_t count = 1; int malloc_kSize = count * sizeof(float); aclrtStream stream; aclrtCreateStream(&stream); //申请集合通信操作的内存 aclrtMalloc((void**)&sendbuff, malloc_kSize, ACL_MEM_MALLOC_HUGE_FIRST); aclrtMalloc((void**)&recvbuff, malloc_kSize, ACL_MEM_MALLOC_HUGE_FIRST); //初始化输入内存 aclrtMallocHost((void**)&hostBuf, malloc_kSize); aclrtMemcpy((void*)sendBuf, malloc_kSize, (void*)hostBuf, malloc_kSize, ACL_MEMCPY_HOST_TO_DEVICE); //执行集合通信操作 HcclAllReduce((void *)sendBuf, (void*)recvBuf, count, HCCL_DATA_TYPE_FP32, HCCL_REDUCE_SUM, hcclComm, stream); |
HcclAllReduce接口调用的完整示例可参见代码示例章节不同通信域初始化方式中的“HcclAllReduce操作代码样例”。


