通信抽象库用法#
通信抽象库 (CAL) 是 cuSOLVERMp 库的辅助模块,使其能够高效地执行不同 GPU 之间的通信。cuSOLVERMp 网格创建 API 接受 cal_comm_t
通信器对象,并要求在任何 cuSOLVERMp 调用之前创建它。目前,CAL 仅支持每个参与进程使用单个 GPU,并且每个参与 GPU 只能由单个进程使用的用例。
通信抽象库#
通信描述#
为了初始化通信器句柄 cal_comm_t
,您需要遵循引导过程 - 请参阅相应的 cal_comm_create() 函数或示例 如何使用 MPI 创建通信器句柄。
cuSOLVERMp 使用的主要通信后端是模块化 OpenUCC 库。OpenUCC 传输模块(例如 OpenUCX、NCCL 等)将在运行时使用,它们的配置可以通过各种方式进行控制(即,影响 NCCL 的环境变量:https://docs.nvda.net.cn/deeplearning/nccl/user-guide/docs/env.html,影响 OpenUCX 的环境变量:https://openucx.readthedocs.io/en/master/faq.html)- 如果平台提供商提供这些依赖项的已知优化设置,请咨询他们。否则,cuSOLVERMp 和 UCC 将使用默认值。
根据底层通信的性质,在使用 cuSOLVERMp 时需要记住一些限制
在进程的任何时间点,只能有一个 cuSOLVERMp 例程在运行。但是,可以创建并保留多个通信/cuSOLVERMp 句柄,但用户有责任确保 cuSOLVERMp 例程的执行不重叠。
如果您正在使用 NCCL 通信库,则 NCCL 集体调用不应与 cuSOLVERMp 调用重叠,以避免可能的死锁。
配置通信子模块#
有一些环境变量可以更改通信模块的行为。
变量 |
描述 |
---|---|
CAL_LOG_LEVEL |
通信模块的详细程度, |
UCC_CONFIG_FILE |
UCC 库的自定义配置文件。它可以控制底层传输和集体参数。有关配置语法的详细信息,请参阅 UCC 文档。默认值 - 内置 cuSOLVERMp UCC 配置。 |
默认情况下,cuSOLVERMp 将使用发行包中提供的 UCC 配置文件:share/ucc.conf
,库将使用相对于 cusolverMp 共享对象位置的路径加载它。
使用 MPI 创建通信器句柄#
如果您的应用程序使用消息传递接口 (MPI) 进行分布式通信,则此处介绍如何使用它来引导通信抽象库通信器
#include "cal.h"
#include "cusolverMp.h"
#include "mpi.h"
calError_t allgather(void* src_buf, void* recv_buf, size_t size, void* data, void** request)
{
MPI_Request req;
int err = MPI_Iallgather(src_buf, size, MPI_BYTE, recv_buf, size, MPI_BYTE, (MPI_Comm)data, &req);
if (err != MPI_SUCCESS)
{
return CAL_ERROR;
}
*request = (void*)req;
return CAL_OK;
}
calError_t request_test(void* request)
{
MPI_Request req = (MPI_Request)request;
int completed;
int err = MPI_Test(&req, &completed, MPI_STATUS_IGNORE);
if (err != MPI_SUCCESS)
{
return CAL_ERROR;
}
return completed ? CAL_OK : CAL_ERROR_INPROGRESS;
}
calError_t request_free(void* request)
{
return CAL_OK;
}
calError_t cal_comm_create_mpi(MPI_Comm mpi_comm, int rank, int nranks, int local_device, cal_comm_t* comm)
{
cal_comm_create_params_t params;
params.allgather = allgather;
params.req_test = request_test;
params.req_free = request_free;
params.data = (void*)mpi_comm;
params.rank = rank;
params.nranks = nranks;
params.local_device = local_device;
return cal_comm_create(params, comm);
}
void main()
{
// Initialize MPI, create some distribute data
MPI_Init(...);
int rank, size;
MPI_Comm mpi_comm = MPI_COMM_WORLD;
MPI_Comm_rank(mpi_comm, &rank);
MPI_Comm_size(mpi_comm, &size);
cal_comm_t cal_comm;
// creating communicator handle with MPI communicator
cal_comm_create_mpi(mpi_comm, rank, size, &cal_comm);
// using cuSOLVERMp with cal_comm handle
cusolverMpCreateDeviceGrid(..., cal_comm, ...);
// destroying communicator handle
cal_comm_destroy(cal_comm);
MPI_Finalize();
}
为方便起见,这些带有 MPI 的辅助函数也以源代码形式在发行包的 src
文件夹中提供。
通信抽象库数据类型#
calError_t
#
来自通信抽象库 API 的返回值。这些值在下表中描述
值 |
描述 |
---|---|
CAL_OK |
成功。 |
CAL_ERROR |
通用错误。 |
CAL_ERROR_INVALID_PARAMETER |
接口函数的无效参数。 |
CAL_ERROR_INTERNAL |
无效错误。 |
CAL_ERROR_CUDA |
CUDA 运行时或驱动程序 API 中的错误。 |
CAL_ERROR_IPC |
系统 IPC 通信调用中的错误。 |
CAL_ERROR_UCC |
UCC 调用中的错误。 |
CAL_ERROR_NOT_SUPPORTED |
不支持请求的配置或参数。 |
CAL_ERROR_BACKEND |
通用后端依赖项中的错误,以详细日志级别运行以查看详细错误消息 |
CAL_ERROR_INPROGRESS |
操作仍在进行中 |
cal_comm_t
#
cal_comm_create_params_t
#
typedef struct cal_comm_create_params
{
calError_t (*allgather)(void* src_buf, void* recv_buf, size_t size, void* data, void** request);
calError_t (*req_test)(void* request);
calError_t (*req_free)(void* request);
void* data;
int nranks;
int rank;
int local_device;
} cal_comm_create_params_t;
cal_comm_create_params_t
结构是通信模块创建函数的参数。此结构必须由用户在调用 cal_comm_create() 之前填写。此结构的字段描述字段 |
描述 |
---|---|
allgather |
指向在主机内存上实现 |
req_test |
如果 allgather 函数是异步的,则此函数将用于查询是否已交换数据,并且可以由通信器使用。如果交换完成,则应返回 |
req_free |
如果 allgather 函数是异步的,则在 |
data |
指向将在调用时提供给 |
nranks |
将要创建的通信器中参与的 ranks 数量 |
rank |
将分配给新通信器中调用进程的 Rank。应为 |
local_device |
cusolverMp 使用此通信器将使用的本地设备。请注意,用户应在 CAL 或 cusolverMp 调用中使用此设备之前创建设备上下文。 |
通信抽象库 API#
cal_comm_create
#
calError_t cal_comm_create(
cal_comm_create_params_t params,
cal_comm_t* new_comm)
cudaSetDevice(device_id); cudaFree(0)
。有关如何填写此结构的说明,请参阅 cal_comm_create_params_t 文档。您可以在 MPI 示例 或 cuSOLVERMp 示例 中查看如何创建 CAL 通信器。参数 |
描述 |
---|---|
params |
一个结构体,其中包含初始化通信器所需的参数。请参阅 cal_comm_create_params_t。 |
new_comm |
用于存储新通信器句柄的指针。 |
有关返回值的描述,请参阅 calError_t。
cal_comm_destroy
#
calError_t cal_comm_destroy(
cal_comm_t comm)
参数 |
描述 |
---|---|
comm |
要释放的通信器句柄。 |
有关返回值的描述,请参阅 calError_t。
cal_stream_sync
#
calError_t cal_stream_sync(
cal_comm_t comm,
cudaStream_t stream)
stream
中所有未完成的设备操作都完成。使用此函数代替 cudaStreamSynchronize
,以便为通信器推进可能的未完成的通信操作。参数 |
描述 |
---|---|
comm |
通信器句柄。 |
stream |
要同步的 CUDA 流。 |
有关返回值的描述,请参阅 calError_t。
cal_comm_get_size
#
calError_t cal_comm_get_size(
cal_comm_t comm,
int* size )
参数 |
描述 |
---|---|
comm |
通信器句柄。 |
size |
处理元素的数量。 |
有关返回值的描述,请参阅 calError_t。
cal_comm_get_rank
#
calError_t cal_comm_get_rank(
cal_comm_t comm,
int* rank )
参数 |
描述 |
---|---|
comm |
通信器句柄。 |
rank |
调用进程的 Rank Id。 |
有关返回值的描述,请参阅 calError_t。