评价此页

错误传播#

创建于:2021 年 5 月 4 日 | 最后更新于:2021 年 7 月 8 日

在分布式 PyTorch 作业中的每个主机都运行一个 TorchElastic 代理,以及多个工作进程(作为 TorchElastic 代理的子进程)。由于工作进程是用户提供的(你的 PyTorch 脚本/作业),TorchElastic 有一种方法可以将训练器上的错误通过代理传播到调度器,最终通知终端用户作业的状态并应用任何重试策略。

TorchElastic 将错误分为 3 类

类别

子类别

描述

用户错误

输入错误

TorchElastic API 的无效输入(例如 min > max 节点)

工作进程故障

工作进程子进程上的任何故障

平台错误

不适用

由代理引起的故障

基础设施错误

不适用

代理和工作进程领域之外的故障(例如,主机故障)

除了“工作进程故障”之外的所有错误,要么是从代理进程规范地引发,要么隐式或显式地导致代理进程崩溃。因此,标准的 Python 异常处理策略适用。

工作进程故障比较特殊,因为异常/故障源于与代理不同的进程,因此错误需要进程间传播(例如,代理不能简单地 `try-catch` 工作进程中引发的异常)。

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

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

方法和类#

torch.distributed.elastic.multiprocessing.errors.record(fn, error_handler=None)[source]#

使用提供的 `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_exception(e)
    raise

重要提示

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

示例

@record
def main():
    pass


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

Callable[[~_P], Optional[_R]]

class torch.distributed.elastic.multiprocessing.errors.ChildFailedError(name, failures)[source]#

可以从用 `@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)是根本原因,应该报告给调度器的 init 进程。torchelastic 代理在检测到训练器 1 的故障时会引发 `ChildFailedError("trainer", {1: "trainer_1/error.json"})`,这将把训练器 1 错误文件的内容传播到调度器的 init 进程。

class torch.distributed.elastic.multiprocessing.errors.ErrorHandler[source]#

以结构化的 JSON 格式将提供的异常对象以及有关错误的更多元数据写入由环境变量 `TORCHELASTIC_ERROR_FILE` 指定的错误文件。如果未设置此环境变量,则仅记录将写入错误文件的内容。

此处理程序可以被子类化以自定义错误处理。子类应重写 `initialize()` 和 `record_exception()`。

class torch.distributed.elastic.multiprocessing.errors.ProcessFailure(local_rank, pid, exitcode, error_file)[source]#

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

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

`message` 字段是对失败的简洁解释。如果错误文件存在,则消息从错误文件中获取。否则,将根据失败签名生成一条消息。

注意

假定 `error_file` 是由 `torch.distributed.elastic.multiprocessing.errors.error_handler.ErrorHandler` 编写的。否则行为未定义。