错误处理和通信器中止
所有MCCL调用返回一个MCCL错误代码,如下表所总结。如果MCCL调用返回的错误代码与mcclSuccess和mcclInternalError不同,并且如果MCCL_DEBUG设置为WARN,MCCL将打印一个人类可读的消息来解释发生了什么。如果MCCL_DEBUG设置为INFO,MCCL还将打印导致错误的调用堆栈。此消息旨在帮助用户解决问题。
下表总结了如何理解和处理不同的错误。每个案例在以下部分中都有详细说明。
| 错误 | 描述 | 解决方案 | 错误处理 | 组行为 |
|---|---|---|---|---|
| mcclSuccess | 无错误 | 无 | 无 | 无 |
| mcclUnhandledmusaError | MUSA调用期间出错(1) | MUSA配置/使用(1) | 通信器中止(5) | 全局(6) |
| mcclSystemError | 系统调用期间出错(1) | 系统配置/使用(1) | 通信器中止(5) | 全局(6) |
| mcclInternalError | MCCL内部出错(2) | 在MCCL中修复(2) | 通信器中止(5) | 全局(6) |
| mcclInvalidArgument | MCCL调用的一个参数无效(3) | 在应用程序中修复(3) | 无(3) | 单独(3) |
| mcclInvalidUsage | MCCL调用的使用无效(4) | 在应用程序中修复(4) | 通信器中止(5) | 全局(6) |
| mcclInProgress | MCCL调用仍在进行中 | 使用mcclCommGetAsyncError轮询完成 | 无 | 无 |
(1) mcclUnhandledmusaError和mcclSystemError表明MCCL对外部组件的调用失败,导致MCCL操作失败。错误消息应该解释用户应该查看哪个组件并尝试修复,可能需要系统管理员的帮助。
(2) mcclInternalError表示MCCL错误。它可能不会在MCCL_DEBUG=WARN时报告消息,因为它需要在MCCL源代码中修复。MCCL_DEBUG=INFO将打印导致错误的回溯。
(3) mcclInvalidArgument表示参数值不正确,如空指针或越界值。当返回此错误时,MCCL调用没有效果。组状态保持不变,通信器仍然正常工作。应用程序可以调用mcclCommAbort或继续好像调用没有发生。此错误将立即返回对于组内发生的调用,并适用于该特定的MCCL调用。它不会被mcclGroupEnd返回,因为mcclGroupEnd不接受任何参数。
(4) mcclInvalidUsage在动态条件导致失败时返回,表示MCCL API的使用不正确。
(5) 这些错误对通信器是致命的。为了恢复,应用程序需要在通信器上调用mcclCommAbort并重新创建它。
(6) 组内操作的动态错误总是由mcclGroupEnd报告,并适用于组内的所有操作,这些操作可能已完成或未完成。应用程序必须在组内的所有通信器上调用mcclCommAbort。
异步错误和错误处理
一些通信错误,特别是网络错误,通过mcclCommGetAsyncError函数报告。经历异步错误的操作通常不会进展,也不会完成。当发生异步错误时,应该中止操作并使用mcclCommAbort销毁通信器。当等待MCCL操作完成时,应用程序应该调用mcclCommGetAsyncError并在发生错误时销毁通信器。
以下代码显示了如何等待MCCL操作并轮询异步错误,而不是使用musaStreamSynchronize。
int mcclStreamSynchronize(musaStream_t stream, mcclComm_t comm) {
musaError_t musaErr;
mcclResult_t mcclErr, mcclAsyncErr;
while (1) {
musaErr = musaStreamQuery(stream);
if (musaErr == musaSuccess)
return 0;
if (musaErr != musaErrorNotReady) {
printf("MUSA Error : musaStreamQuery returned %d\n", musaErr);
return 1;
}
mcclErr = mcclCommGetAsyncError(comm, &mcclAsyncErr);
if (mcclErr != mcclSuccess) {
printf("MCCL Error : mcclCommGetAsyncError returned %d\n", mcclErr);
return 1;
}
if (mcclAsyncErr != mcclSuccess) {
// 发生了异步错误。停止操作并销毁通信器
mcclErr = mcclCommAbort(comm);
if (mcclErr != mcclSuccess)
printf("MCCL Error : mcclCommDestroy returned %d\n", mcclErr);
// 调用者可以中止或尝试创建新的通信器。
return 2;
}
// 我们可能希望让其他线程(包括MCCL线程)使用CPU。
sched_yield();
}
}
相关链接:

