错误传播
在分布式 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
创建的。否则其行为将无法确定。