本文为您介绍如何使用PAI-DLC提供的基于AIMaster的容错监控功能。

背景信息

如今,深度学习已被广泛使用,随着模型和数据规模越来越大,常采用分布式方式运行深度学习任务。当同一个任务运行实例个数增大后,由于依赖的软件栈和硬件环境都有可能出现偶发异常,会导致任务停止运行。

为了保障大规模分布式深度学习任务稳定运行,PAI-DLC提供了基于AIMaster的容错监控功能。AIMaster是一个任务级别的组件,当任务开启AIMaster的容错监控功能后,会拉起一个AIMaster实例和任务其他实例一起运行,起到任务监控、容错判断、资源控制的作用。

使用流程

  1. 步骤一:配置容错监控参数

    首先根据AIMaster支持的全量参数说明,并参考容错监控参数配置示例,来配置额外参数。

  2. 步骤二:开启容错监控功能

    您可以在提交PAI-DLC训练任务时,通过控制台或SDK的方式开启容错监控功能。任务运行异常时,会根据配置的额外参数,对任务进行相应的处理,从而保障任务能正常运行。

  3. 步骤三:配置容错监控增强功能

    如果当前的容错监控配置不能满足您的要求,您可以使用容错监控增强功能,通过AIMaster SDK自定义容错关键字。任务运行过程中,AIMaster会自动扫描出错节点的日志,并和自定义容错信息对比,如果满足容错条件,也会触发容错。

步骤一:配置容错监控参数

当前容错监控功能支持配置的参数如下,您可以参考常用参数配置示例,提前规划好要为任务配置的容错监控内容。后续开启容错监控功能时,将已规划的容错监控内容配置到额外参数即可。

全量参数说明

容错监控支持配置以下参数。
配置分类 功能介绍 配置参数 参数说明 默认值
通用配置 任务运行类型 --job-execution-mode 配置任务运行类型,取值如下:
  • Sync:同步任务。
  • Async:异步任务。
不同任务类型容错行为不同。对于可重试错误(请参见步骤三:配置容错监控增强功能):
  • 同步任务需要重启任务。
  • 异步任务一般只需重启失败的Worker实例。
Sync
任务最大运行时长 --job-max-running-time 配置任务允许的最大运行时长,正整数,单位为分钟。
如果任务运行时长超过该值后,则将任务标记为失败。默认值为-1,表示不开启该功能。
说明
  • 当该参数取值为-1时,任务最大运行时长以控制台配置时间为准。
  • 当控制台和容错监控参数均配置了任务最大运行时长时,以最短的时长为准。
-1
任务重启设置 --enable-job-restart 在满足容错条件或检测到运行时异常(请参见步骤三:配置容错监控增强功能)时,是否允许任务重启。取值如下:
  • False:不重启任务。
  • True:重启任务。
False
--max-num-of-job-restart 配置任务最大重启次数。超过最大重启次数后,会将任务标记为失败。 3
运行时配置
说明 针对没有Worker实例失败的场景。
任务Hang(停止执行)异常检测 --enable-job-hang-detection 是否开启任务Hang异常检测,只支持同步任务。取值如下:
  • False:表示不开启。
  • True:表示开启。如果所有Worker实例的Stdout和Stderr日志在指定时间内没有更新,将触发任务重启。
False
--job-hang-interval 配置任务暂停执行的持续时长,正整数,单位为秒。

当任务停止时长超过该值时,则将任务标记为异常,并触发任务重启。

1800
任务退出时Hang(停止执行)异常检测 --enable-job-exit-hang-detection 是否开启任务退出时Hang异常检测,只支持同步任务。取值如下:
  • False:表示不开启。
  • True:表示开启。当任务某个Worker实例执行成功后,如果在指定时间内任务没有结束,将触发任务重启。
False
--job-exit-hang-interval 配置任务退出时停止执行的持续时长,正整数,单位为秒。

当任务退出时长超过该值时,则将任务标记为异常,并触发任务重启。

600
容错配置
说明 针对有Worker实例失败的场景。
容错策略 --fault-tolerant-policy 容错策略参数取值如下:
  • OnFailure:任务出现异常时:
    • 异步任务会无条件重启失败的Worker实例。
    • 同步任务会无条件重启任务。
  • ExitCodeAndErrorMsg:任务出现异常时,判断失败Worker实例的退出码及错误日志信息(请参见步骤三:配置容错监控增强功能),如果满足重试条件:
    • 异步任务会重启失败的Worker实例。
    • 同步任务会重启任务。
  • Never:对失败任务不做任何处理,直接将任务标记为失败。
Never
相同错误最大允许出现次数 --max-num-of-same-error 配置单个Worker实例上同一错误允许出现的最大次数。

当错误出现次数超过该值时,直接将任务标记为失败。

10
最大容错率 --max-tolerated-failure-rate 配置最大容错率。

当失败Worker实例比例超过该值时,直接将任务标记为失败。

1

常用参数配置示例

针对不同的训练任务,常用的容错监控参数配置示例如下。
  • TensorFlow异步训练任务
    对于可重试的错误,如果Worker实例运行异常,则会重启运行异常的Worker实例。当PS或Chief实例出错时,下面的配置默认不允许重启任务。如果您希望重启任务,可以将--enable-job-restart参数配置为True
    --job-execution-mode=Async --fault-tolerant-policy=OnFailure
  • 离线推理任务
    各个Worker实例之间不存在依赖关系,相当于异步任务。当Worker实例运行异常时,则会重启运行异常的Worker实例。
    --job-execution-mode=Async --fault-tolerant-policy=OnFailure
  • 同步训练任务
    当某个Worker实例运行异常时,如果退出码或错误日志信息满足容错条件,例如:抢占发生,则会重启任务。
    --job-execution-mode=Sync --enable-job-restart=True --max-num-of-job-restart=3 --fault-tolerant-policy=ExitCodeAndErrorMsg

步骤二:开启容错监控功能

您可以在提交PAI-DLC训练任务时,开启容错监控功能。
  • 通过控制台开启容错监控功能
    在控制台提交PAI-DLC训练任务时,您可以在基本信息区域,打开容错监控开关,并配置额外参数,详情请参见提交任务(通过控制台)打开容错开关其中:额外参数的配置详情,请参见步骤一:配置容错监控参数
  • 通过SDK开启容错监控功能
    • 通过GO SDK提交任务时打开容错开关。
      createJobRequest := &client.CreateJobRequest{}
      settings := &client.JobSettings{
          EnableErrorMonitoringInAIMaster: tea.Bool(true),
          ErrorMonitoringArgs: tea.String("--job-execution-mode=Sync --enable-job-restart=True --enable-job-hang-detection=True --job-hang-interval=3600"),
      }
      createJobRequest.SetSettings(settings)
      其中:
      • EnableErrorMonitoringInAIMaster:表示是否打开容错监控功能。
      • ErrorMonitoringArgs:表示容错监控额外参数。
    • 通过Python SDK提交任务时打开容错开关。
      from alibabacloud_pai_dlc20201203.models import CreateJobRequest, JobSettings
      
      settings = JobSettings(
          enable_error_monitoring_in_aimaster = True,
          error_monitoring_args = "--job-execution-mode=Sync --enable-job-restart=True --enable-job-hang-detection=True --job-hang-interval=30"
      )
      create_job_req = CreateJobRequest(
          ...
          settings = settings,
      )
      其中:
      • enable_error_monitoring_in_aimaster:表示是否打开容错监控功能。
      • error_monitoring_args:表示容错监控额外参数。

您也可以在提交任务时自定义容错信息,任务运行过程中,AIMaster会自动扫描出错节点的日志,并和自定义容错信息对比,如果满足容错条件,也会触发容错。具体配置方法,详情请参见步骤三:配置容错监控增强功能

步骤三:配置容错监控增强功能

您可以通过AIMaster的SDK,在您自己的代码里根据不同的场景配置容错监控增强功能。

  1. 使用以下命令安装AIMaster SDK。
    pip install -U https://pai-dlc.oss-cn-zhangjiakou.aliyuncs.com/aimaster/aimaster-1.1.6-cp36-cp36m-linux_x86_64.whl
  2. 配置容错监控增强功能。
    • 配置自定义容错关键字
      容错监控功能已内置了常见的可重试错误的监控模块,如果您希望异常Worker实例日志中出现某些关键字时也进行容错,则可以在您的代码中使用以下方法进行配置。配置完成后,容错监控模块会扫描失败的Worker实例尾部日志进行关键信息匹配。
      说明 容错策略需要配置为ExitCodeAndErrorMsg
      • PyTorch任务自定义容错关键字配置示例。
        from aimaster import job_monitor as jm
        
        jm_config_params = {}
        jm_config = jm.PyTorchConfig(**jm_config_params)
        monitor = jm.Monitor(config=jm_config)
        monitor.set_retryable_errors(["connect timeout", "error_yyy", "error_zzz"])
        其中:monitor.set_retryable_errors中配置的参数即为自定义容错关键字。
      • TF任务自定义容错关键字配置示例
        from aimaster import job_monitor as jm
        
        jm_config_params = {}
        jm_config = jm.TFConfig(**jm_config_params)
        monitor = jm.Monitor(config=jm_config)
        monitor.set_retryable_errors(["connect timeout", "error_yyy", "error_zzz"])
    • 分阶段自定义任务Hang异常检测
      目前任务Hang异常检测的配置是针对整个任务的,但是任务状态是分阶段的。例如:构建通信训练任务时,规模大且耗时长,但训练阶段日志更新比较快。为了在训练过程中能快速发现任务Hang异常的节点,PAI-DLC提供了分阶段自定义任务Hang异常检测功能,支持您在不同训练阶段配置不同的任务Hang异常检测时长,具体配置方法如下。
      monitor.reset_config(jm_config_params)
      
      # Example:
      #     monitor.reset_config(job_hang_interval=10)
      #     or
      #     config_params = {"job_hang_interval": 10, }
      #     monitor.reset_config(**config_params)
      PyTorch任务分阶段自定义任务Hang异常检测示例如下。
      import torch
      import torch.distributed as dist
      from aimaster import job_monitor as jm
      
      jm_config_params = {
          "job_hang_interval": 1800 # 全局30min检测
      }
      jm_config = jm.PyTorchConfig(**jm_config_params)
      monitor = jm.Monitor(config=jm_config)
      
      dist.init_process_group('nccl')
      
      ...
      
      # impl these two funcs in aimaster sdk
      # user just need to add annotations to their func
      def reset_hang_detect(hang_seconds):
          jm_config_params = {
              "job_hang_interval": hang_seconds
          }
          monitor.reset_config(**jm_config_params)
      
      def hang_detect(interval):
          reset_hang_detect(interval)
          ...
      
      @hang_detect(180) # reset hang detect to 3 min, only for func scope
      def train():
          ...
      
      @hang_detect(-1) # disable hang detect temperally, only for func scope
      def test():
          ...
      
      for epoch in range(0, 100):
          train(epoch)
          test(epoch)
          self.scheduler.step()