错误传播

在分布式 PyTorch 作业中,每个主机运行一个 TorchElastic 代理,并且有多个作为该代理子进程的工作者。由于这些工作者是由用户提供的(即你的 PyTorch 脚本或作业),TorchElastic 可以通过代理将训练器中的错误传播到调度程序,从而告知最终用户作业的状态并应用任何重试策略。

TorchElastic 将错误分类为三大类:

分类

子类别

描述

用户错误

输入错误

向TorchElastic API提供的无效输入(例如,min大于max节点)

工人失败

worker子进程中的任何失败

平台错误

n/a

由代理导致的失败

基础设施错误

n/a

代理和工作者以外领域的故障(例如主机故障)

除“Worker Failure”外,其他所有错误要么由代理进程抛出,要么会直接导致代理进程崩溃。因此,像 Python 这样的标准语言所提供的异常处理策略同样适用于这种情况。

Worker 失败是特殊的,因为异常或失败起源于与代理不同的进程。因此,错误需要在进程之间传播(例如,代理不能简单地通过 try-catch 捕获 Worker 进程中引发的异常)。

TorchElastic 代理使用torch.distributed.elastic.multiprocessing.start_processes()来启动工作者进程,该方法内置了简单的基于文件的进程间错误传播机制。

任何使用record()装饰的函数或二进制入口点,都会将未捕获的异常及其跟踪信息写入由环境变量TORCHELASTIC_ERROR_FILE指定的文件中。父进程(例如代理)在启动每个子进程时设置此环境变量,并聚合所有子进程的错误文件,然后传播具有最小时间戳的那个错误文件(即第一个出现的错误)。

方法和类

torch.distributed.elastic.multiprocessing.errors.record(fn, error_handler=None)[源代码]

用于记录装饰函数中发生错误/异常的语法糖,使用提供的 error_handler

使用这个装饰器相当于:

error_handler = get_error_handler()
error_handler.initialize()
try:
   foobar()
except ChildFailedError as e:
   _, failure = e.get_first_failure()
   error_handler.dump_error_file(failure.error_file, failure.exitcode)
   raise
except Exception as e:
   error_handler.record(e)
   raise

重要内容

在每个进程的顶层方法中使用一次此装饰器,通常这是主方法。

示例

@record
def main():
    pass

if __name__=="__main__":
   main()
返回类型

Callable [[…], T]

torch.distributed.elastic.multiprocessing.errors.ChildFailedError(name, failures)[源代码]

一种特殊的异常类型,可以在使用 @record 装饰器标记的函数中抛出,使子进程中的根异常直接在调用栈中向上传播(而不是被父进程中捕获和包裹)。

在这种情况下,父进程只是一个简单的监视器进程,而子(工作)进程则在进行实际的计算任务。由于父进程本身不会出现复杂的问题,因此错误通常发生在子进程中。为了准确地诊断问题根源,需要将子进程中的错误传递给调度程序。

注意

传播依赖于错误文件而非异常处理,以支持函数和二进制文件的启动。

示例:

# process tree on a host (container)
0: scheduler-init-process:
           |- 1: torchelastic_agent:
                    |- 2: trainer_0 (ok)
                    |- 3: trainer_1 (fail) -> error.json
                    |- ...
                    |- n+2: trainer_n (ok)
           |- n+3: other processes
           |- ...

在上述示例中,训练器 1 的失败(记录在 error.json 文件中)是根本原因,并应报告给调度程序的初始化进程。torchelastic 代理检测到训练器 1 失败后会引发 ChildFailedError("trainer", {1: "trainer_1/error.json"}),并将训练器 1 的错误文件内容传递给调度程序的初始化进程。

torch.distributed.elastic.multiprocessing.errors.ErrorHandler[源代码]

将提供的异常对象以及一些其他关于错误的元数据以结构化的JSON格式写入由环境变量 TORCHELASTIC_ERROR_FILE 指定的错误文件。如果此环境变量未设置,则简单地记录原本会写入错误文件的内容。

此处理器可以被子类化以自定义错误处理方式。子类应该重写 initialize()record_exception() 方法。

torch.distributed.elastic.multiprocessing.errors.ProcessFailure(local_rank, pid, exitcode, error_file)[源代码]

表示失败的进程结果。当工作进程失败时,可以将其根本原因记录到文件中。

尝试从提供的error_file中读取失败的时间戳。如果error_file不存在,那么时间戳就是当前时间戳(自纪元以来的秒数)。

message 字段是对失败原因的简洁描述。如果有错误文件存在,那么消息将从中获取;如果没有,则会根据失败特征自动生成一条消息。

注意

假设 error_file 是由 torch.distributed.elastic.multiprocessing.errors.error_handler.ErrorHandler 创建的。否则其行为将无法确定。

本页目录