1. 版本历史¶
文档版本 |
版本 |
作者 |
---|---|---|
V3.0 |
ECCL API参考 |
Enflame Tech |
2. ECCL API 参考¶
以下内容描述了 ECCL 集合通信库的对外接口以及相关的参数信息。包括了通信域生成与管理类接口、通信算子类接口
2.1. 通信域生成与管理类接口¶
下列接口主要负责生成通信域并进行管理
ecclGetVersion¶
ecclResult_t ecclGetVersion(int *version);
ecclGetVersion 返回当前链接的 ECCL 库的版本号。ECCL 版本号以整数形式返回在 version 中,编码包括 ECCL_MAJOR、ECCL_MINOR 和 ECCL_PATCH 级别。返回的版本号将与 eccl.h 中定义的 ECCL_VERSION_CODE 相同。ECCL 版本号可以使用提供的宏进行比较:ECCL_VERSION(MAJOR, MINOR, PATCH)。
ecclGetUniqueId¶
ecclResult_t ecclGetUniqueId(ecclUniqueId* uniqueId)
ecclGetUniqueId 接口返回通信域的独有身份信息用于接下来的初始化通信域。每创建一个新的通信域根 GCU 卡都应该调用此函数,并将身份信息广播给域内所有的卡。
ecclCommInitRank¶
ecclResult_t ecclCommInitRank(ecclComm_t* comm, int nranks, ecclUniqueId commId, int rank)
ecclCommInitRank 接口负责初始化指定的通信域,并返回对应的通信域信息给上层用户,上层用户将使用通信域信息调用集合通信接口。
ecclCommInitAll¶
ecclResult_t ecclCommInitAll(ecclComm_t* comms, int ndev, const int* devlist);
ecclCommInitAll 接口负责在单进程单线程模式下初始化指定的通信组,此接口将初始化 ndev 个通信域并将结果保存至 comms 结构体中。comms 应该预先分配大小至少为 ndev*sizeof(ecclComm_t)。 devlist 定义了每个 rank 跟 GCU 卡的绑定关系。如果 devlist 为空,则按顺序使用前 ndev 个 GCU 卡。
ecclCommDestroy¶
ecclResult_t ecclCommDestroy(ecclComm_t comm)
ecclCommDestroy 会在所有操作结束后释放相应通信域内的所有资源。
ecclCommCount¶
ecclResult_t ecclCommCount(const ecclComm_t comm, int* count);
ecclCommCount 将会获取通信域内总的进程数量,并将结果保存在参数 count 中。
ecclCommDevice¶
ecclResult_t ecclCommDevice(const ecclComm_t comm, int* devid);
ecclCommDevice 接口负责获取通信域内某张 GCU 卡的设备号,并将结果保存在参数 device 中。
ecclCommUserRank¶
ecclResult_t ecclCommUserRank(const ecclComm_t comm, int* rank);
ecclCommUserRank 接口负责获取通信域内某个进程的进程号,并将结果保存在参数 rank 中。
ecclCommAbort¶
ecclResult_t ecclCommAbort(ecclComm_t comm);
ecclCommAbort 释放分配给通信域对象 comm 的资源。在销毁通信域之前,将终止所有未完成的操作。
ecclCommGetAsyncError¶
ecclResult_t ecclCommGetAsyncError(ecclComm_t comm, ecclResult_t* asyncError);
ecclCommGetAsyncError 查询通信域是否遇到任何异步错误。如果通信域上发生错误,用户应使用 ecclCommAbort() 销毁通信域, 并且不能假设在该通信域上排队的操作可以正确完成。
ecclGetLastError¶
const char* ecclGetLastError(ecclComm_t comm);
ecclGetLastError 返回与 ECCL 最后发生的错误相对应的人类可读字符串。注意:调用此函数不会清除错误。ecclGetLastError 返回的字符串可能与当前调用无关,并且可能是之前启动的异步操作的结果(如果有)。
参数描述¶
参数 |
意义 |
---|---|
int nranks |
通信域内参与集合通信的进程(rank)数量,取值范围: 1 - n |
ecclUniqueId commId |
通信域的身份标号,总是唯一地标识一个通信域 |
int rank |
本进程(rank)在集合通信共nranks个进程中的编号,取值范围: 0 - nrank-1 |
ecclcomm_t* comm |
通信域创建成功后返回的通信域描述符 |
2.2. 通信算子类接口¶
下列接口实现了常见的集合通信操作
ecclBroadcast¶
ecclResult_t ecclBroadcast(const void* sendbuff, void* recvbuff, size_t count, ecclDataType_t datatype, int root, ecclComm_t comm, topsStream_t stream)
ecclBroadcast 将通信域内根 GCU 卡输出内存的数据广播到其他卡的输入内存上。输出内存只对根 GCU 卡起作用,其余 GCU 卡会忽略。输出内存和输入内存可以是同一块内存,此情况下不做任何处理。
ecclAllReduce¶
ecclResult_t ecclAllReduce(const void* sendbuff, void* recvbuff, size_t count, ecclDataType_t datatype, ecclRedOp_t op, ecclComm_t comm, topsStream_t stream)
ecclAllReduce 将通信域内所有 GCU 卡上输出内存的数据按照算子类型做规约操作,而每个卡的输入内存将会保存规约后的结果。输出内存和输入内存可以是同一块内存,此情况下不做任何处理。
ecclReduceScatter¶
ecclResult_t ecclReduceScatter(const void* sendbuff, void* recvbuff, size_t recvcount, ecclDataType_t datatype, ecclRedOp_t op, ecclComm_t comm, topsStream_t stream)
ecclReduceScatter 将通信域内所有 GCU 卡上输出内存的数据按照算子类型做规约操作,并将得到的结果均匀分片后分发到每一张卡的输入内存上,第 i 张卡上保存规约后的第 i 片数据。 此集合通信方式要求输出内存上数据大小为输入内存数据大小的 nranks 倍。
ecclAllGather¶
ecclResult_t ecclAllGather(const void* sendbuff, void* recvbuff, size_t sendcount, ecclDataType_t datatype, ecclComm_t comm, topsStream_t stream)
ecclAllGather 将通信域内所有 GCU 卡上输出内存的数据做聚合操作,而每个卡的输入内存将会保存聚合后的结果。每张卡上数据大小需要一致,输入内存上第 i 个位置保存第 i 张卡的数据。输出内存和输入内存可以是同一块内存,此情况下不做任何处理。 此集合通信方式要求输入内存上数据大小为输出内存数据大小的 nranks 倍。
2.3. 组操作接口¶
组操作定义了当前线程的行为以避免阻塞,因此可以在多个独立线程上使用该接口
ecclGroupStart¶
ecclResult_t ecclGroupStart();
ecclGroupStart 开启组操作,接下的通信操作不会因为 CPU 之间的同步而阻塞。
ecclGroupEnd¶
ecclResult_t ecclGroupEnd();
ecclGroupEnd 结束组操作。当从上个 ecclGroupStart 之间的通信操作都被处理后返回。这意味着通信算子都被排入了流中,并不代表通信操作已经完成。
Attention
ecclGroupStart/End 暂不支持不同通信类型的聚合(例如 Allreduce 和 Allgather 聚合)。
2.4. 点对点通信接口¶
通信域内指定多张卡之间进行数据接发
ecclSend¶
ecclResult_t ecclSend(const void* sendbuff, size_t count, ecclDataType_t datatype, int peer, ecclComm_t comm, topsStream_t stream);
ecclSend 将输出内存上的数据传输给指定的卡,同时被指定的卡需要运行 ecclRecv 来接受数据(数据类型和位数需要一致)。
ecclRecv¶
ecclResult_t ecclRecv(void* recvbuff, size_t count, ecclDataType_t datatype, int peer, ecclComm_t comm, topsStream_t stream);
ecclRecv 将从指定的卡上接收到的数据存入输入内存中,同时被指定的卡需要运行 ecclSend 来发送数据(数据类型和位数需要一致)。
2.5. 接口参数描述¶
参数 |
意义 |
---|---|
const void* sendbuff |
输出内存区地址 |
void* recvbuff |
输入内存区地址 |
size_t count |
需要进行通信运算的元素个数 |
size_t sendcount |
输出数据元素个数 |
size_t recvcount |
输入数据元素个数 |
ecclDataType_t datatype |
需要进行通信运算的元素数据类型 |
ecclRedOp_t op |
规约通信算子的类型 |
ecclComm_t comm |
本次通信域的描述符,ecclCommInitRank完成后得到该描述符 |
int peer |
点对点通信指定卡的rank号 |
const size_t* displs |
记录接收数据在输入内存上的偏移 |
2.6. 返回值以及枚举类参数取值¶
ecclResult_t¶
下表枚举了 ecclResult_t 可能的返回值
返回值 |
对应数值 |
返回值描述 |
---|---|---|
ecclSuccess |
0 |
集合通信初始化成功,或者算子下发完成 |
ecclUnhandledTopsError |
1 |
调用topsruntime或者驱动接口返回失败 |
ecclSystemError |
2 |
操作系统的功能返回失败。如初始化socket失败,读写文件失败等 |
ecclInternalError |
3 |
ECCL内部流程失败 |
ecclInvalidArgument |
4 |
上层输入无效的参数 |
ecclInvalidUsage |
5 |
上层使用方式有误 |
ecclNumResults |
6 |
无效的返回值 |
ecclRedOp_t¶
下表枚举了 ecclRedOp_t 可能出现的类型
通信类型 |
对应数值 |
类型描述 |
---|---|---|
ecclSum |
0 |
实现加(+)操作 |
ecclProd |
1 |
实现乘(*)操作 |
ecclMax |
2 |
实现取最大值操作 |
ecclMin |
3 |
实现取最小值操作 |
ecclAvg |
4 |
实现取平均值操作 |
ecclNumOps |
5 |
无效的类型 |
ecclDataType_t¶
下表枚举了 ecclDataType_t 可能出现的类型
数据类型 |
对应数值 |
类型描述 |
---|---|---|
ecclInt8,ecclChar |
0 |
8位符号整数 |
ecclUint8 |
1 |
8位无符号整数 |
ecclInt32,ecclInt |
2 |
32位符号整数 |
ecclUint32 |
3 |
32位无符号整数 |
ecclInt64 |
4 |
64位符号整数 |
ecclUint64 |
5 |
64位无符号整数 |
ecclFloat16,ecclHalf |
6 |
16位浮点数 |
ecclFloat32,ecclFloat |
7 |
32位浮点数 |
ecclFloat64,ecclDouble |
8 |
64位浮点数 |
ecclBFloat16 |
9 |
16位截断浮点数 |
ecclNumTypes |
10 |
无效的类型 |
Attention
ecclBroadcast,ecclAllGather 算子支持上述所有数据类型。ecclAllReduce 算子不支持64位宽数据类型,包括 ecclInt64,ecclUint64,ecclFloat64/ecclDouble。