Tune 如何工作?#

本页概述了 Tune 的内部工作原理。我们将详细描述调用 Tuner.fit() 时发生的情况、Tune 试验的生命周期以及 Tune 的架构组件。

提示

在继续之前,请务必阅读Tune 关键概念页面

Tuner.fit 中发生了什么?#

调用以下代码时

space = {"x": tune.uniform(0, 1)}
tuner = tune.Tuner(
    my_trainable,
    param_space=space,
    tune_config=tune.TuneConfig(num_samples=10),
)
results = tuner.fit()

提供的 my_trainable 会使用不同的超参数(从 uniform(0, 1) 中采样)进行多次并行评估。

每次 Tune 运行都由“驱动进程”和许多“工作进程”组成。驱动进程是调用 Tuner.fit() 的 python 进程(其底层会调用 ray.init())。Tune 驱动进程在你运行脚本(其中调用了 Tuner.fit())的节点上运行,而 Ray Tune 可训练的“actor”可以在任何节点上运行(可以是同一节点,也可以是工作节点(仅限分布式 Ray))。

注意

Ray Actor 允许你在 Python 中并行化类的实例。当你实例化一个 Ray actor 类时,Ray 会在单独的进程中启动该类的一个实例,该进程可以在同一机器上运行(如果运行的是 Ray 集群,则可以在另一台分布式机器上)。该 actor 可以异步执行方法调用并维护其自己的内部状态。

驱动程序会生成并行的 worker 进程(Ray Actor),这些进程负责使用每个试验的超参数配置和提供的可训练对象进行评估。

当可训练对象正在执行时(参见Tune 中可训练对象的执行),Tune 驱动程序会通过 actor 方法与每个 actor 通信,以接收中间训练结果并暂停/停止 actor(参见Tune 试验的生命周期)。

当可训练对象终止(或停止)时,actor 也被终止。

Tune 中可训练对象的执行#

Tune 使用Ray actor 来并行化多个超参数配置的评估。每个 actor 是一个 Python 进程,执行用户提供的可训练对象的一个实例。

用户提供的可训练对象的定义将通过 cloudpickle 序列化并发送到每个 actor 进程。每个 Ray actor 将启动可训练对象的一个实例来执行。

如果可训练对象是一个类,它将通过调用 train/step 迭代执行。每次调用后,驱动程序会收到通知,“结果字典”已就绪。然后驱动程序将通过 ray.get 拉取结果。

如果可训练对象是可调用对象或函数,它将在 Ray actor 进程上的一个单独执行线程中执行。每当调用 session.report 时,执行线程会暂停并等待驱动程序拉取结果(参见 function_trainable.py)。拉取后,actor 的执行线程将自动恢复。

Tune 中的资源管理#

在运行试验之前,Ray Tune 驱动程序将检查集群上是否有可用资源(参见指定任务或 Actor 的资源需求)。它会将可用资源与试验所需的资源进行比较。

如果集群上有可用空间,Tune 驱动程序将启动一个 Ray actor(工作者)。这个 actor 将被调度并在资源可用的某个节点上执行。有关更多信息,请参见Ray Tune 并行和资源指南

Tune 试验的生命周期#

试验的生命周期包括 6 个阶段

  • 初始化 (生成): 首先生成一个试验作为超参数样本,并根据 Tuner 中提供的内容配置其参数。然后将试验放入队列中等待执行(状态为 PENDING)。

  • PENDING (待处理): 待处理试验是等待在机器上执行的试验。每个试验都配置了资源值。每当试验的资源值可用时,Tune 将运行该试验(通过启动一个持有配置和训练函数的 ray actor)。

  • RUNNING (运行中): 运行中的试验分配有一个 Ray Actor。可以有多个并行运行的试验。有关更多详细信息,请参见可训练对象执行部分。

  • ERRORED (出错): 如果正在运行的试验抛出异常,Tune 将捕获该异常并将试验标记为出错。请注意,异常可以从 actor 传播到主 Tune 驱动进程。如果设置了 max_retries,Tune 将把试验状态重新设置为“PENDING”,稍后从上一个检查点开始重新运行。

  • TERMINATED (已终止): 如果试验被 Stopper/Scheduler 停止,则试验终止。如果使用 Function API,当函数停止时,试验也会终止。

  • PAUSED (已暂停): 试验调度器可以暂停试验。这意味着试验的 actor 将被停止。暂停的试验稍后可以从最近的检查点恢复。

Tune 的架构#

../../_images/tune-arch.png

蓝色框表示内部组件,绿色框表示面向公众的组件。

Tune 的主要组件包括 TuneControllerTrial 对象、一个 SearchAlgorithm、一个TrialScheduler 和一个Trainable

这是高级训练流程以及一些组件如何交互的图示

注意:此图可水平滚动

../../_images/tune-trial-runner-flow-horizontal.png

TuneController#

[源代码] 这是训练循环的主要驱动程序。该组件使用 TrialScheduler 来确定试验的优先级并执行试验,向 SearchAlgorithm 查询要评估的新配置,并处理容错逻辑。

容错:如果设置了 checkpoint_freq,TuneController 会执行检查点操作,并在试验失败时自动重新启动试验(如果设置了 max_failures)。例如,如果在试验(特别是试验对应的 Trainable)仍在节点上执行且启用了检查点时,节点丢失,那么试验将被恢复到 "PENDING" 状态,并在运行时从最后一个可用检查点恢复。TuneController 还负责在每次循环迭代时保存整个实验执行状态的检查点。这允许用户在机器故障时重新启动实验。

请参阅 TuneController 的 docstring。

Trial 对象#

[源代码] 这是一个内部数据结构,包含每个训练运行的元数据。每个 Trial 对象与一个 Trainable 对象一一对应,但本身不是分布式/远程的。Trial 对象在以下状态之间转换:"PENDING" (待处理)、"RUNNING" (运行中)、"PAUSED" (已暂停)、"ERRORED" (出错) 和 "TERMINATED" (已终止)。

请参阅Trial 的 docstring。

SearchAlg#

[源代码] SearchAlgorithm 是一个用户提供的对象,用于查询要评估的新超参数配置。

每当试验完成执行一个训练步骤(即 train())、每次试验出错以及每次试验完成时,SearchAlgorithm 都会收到通知。

TrialScheduler#

[源代码] TrialScheduler 对一组可运行的试验进行操作,根据可用的集群资源对试验执行进行优先级排序。

TrialScheduler 具有终止或暂停试验的能力,还具有重新排序/优先处理传入试验的能力。

Trainable 对象#

[源代码] 这些是用户提供的对象,用于训练过程。如果提供的是类,则期望其符合 Trainable 接口。如果提供的是函数,则将其包装到 Trainable 类中,函数本身在单独的线程中执行。

可训练对象将执行 train() 的一个步骤,然后通知 TrialRunner。