跳到主要内容

错误处理和通信器中止

所有MCCL调用返回一个MCCL错误代码,如下表所总结。如果MCCL调用返回的错误代码与mcclSuccess和mcclInternalError不同,并且如果MCCL_DEBUG设置为WARN,MCCL将打印一个人类可读的消息来解释发生了什么。如果MCCL_DEBUG设置为INFO,MCCL还将打印导致错误的调用堆栈。此消息旨在帮助用户解决问题。

下表总结了如何理解和处理不同的错误。每个案例在以下部分中都有详细说明。

错误描述解决方案错误处理组行为
mcclSuccess无错误
mcclUnhandledmusaErrorMUSA调用期间出错(1)MUSA配置/使用(1)通信器中止(5)全局(6)
mcclSystemError系统调用期间出错(1)系统配置/使用(1)通信器中止(5)全局(6)
mcclInternalErrorMCCL内部出错(2)在MCCL中修复(2)通信器中止(5)全局(6)
mcclInvalidArgumentMCCL调用的一个参数无效(3)在应用程序中修复(3)无(3)单独(3)
mcclInvalidUsageMCCL调用的使用无效(4)在应用程序中修复(4)通信器中止(5)全局(6)
mcclInProgressMCCL调用仍在进行中使用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();
}
}

相关链接: