system: [SYSTEM]

user: 4. 算法设计 本文使用深度强化学习方法来解决资源调度问题。设计深度强化学习模型时首先需要对三个主要要素进行设计，分别是状态、动作和奖励函数。状态是指对智能体所处环境的表示，是智能体对外界环境的感知，动作是智能体在所处环境下所做出的决策，根据该决策环境将进行相应变化，奖励则是对智能体所做决策优劣的反馈。 4.1. 状态设计 Deepk8s仿真环境中的状态包括集群机器状态和集群中待调度任务状态，如图2所示，图中状态空间分为3个部分，顶部为机器状态，图中包括3台机器的状态，图中所有机器CPU资源有8个，内存资源有10个。其中机器1已经分配的CPU资源为5个，剩余CPU资源为3个，已分配内存资源8个，剩余内存资源2个。中间部分为集群中待调度任务状态，其中在任务状态中多了一个维度，即纵轴表示时间。图中纵轴则表示任务的实际执行时间，横轴同样为任务对资源的需求。例如图中任务1的实际执行时间为2个单位时间，其中对CPU资源的需求为4个，而内存资源的需求为1个。就图中状态而言，可以将任务1调度到机器2和机器3上，而不能调度到机器1，因为机器1的剩余CPU资源不能满足任务1的CPU资源需求。图中底部为积压队列状态，设计积压队列状态的目的是固定待调度任务状态的大小。在不同调度时刻，我们无法得知系统中待调度任务的数量，而神经网络的输入需要固定维度的向量，因此这里固定待调度任务长度为n，图中n = 3。对于待调度任务数量超出n的情况，将超出的任务按照任务到达先后顺序存储在积压队列中。积压队列状态仅包含积压队列的长度以及积压队列队首任务的基本信息。 图2. Deepk8s状态空间设计 4.2. 动作设计 动作是智能体所做的决策，智能体根据当前环境的状态给出对应的动作。本文设计的调度系统中，智能体需要从k个待调度任务中选择任意数量任务调度到m个机器中的一个，其动作空间大小为m × 2 k 。这个空间大小与任务数量成指数关系，为了减小动作空间的大小，本文忽略系统每次调度的计算开销，即认为在同一时刻可以进行多次调度。每次调度从n个待调度任务中选择其中一个进行调度，而在每次调度结束之后可以立即进行下一次调度，这样在同一时刻一样可以进行多次调度动作，采用这种设计方法其动作空间大小变为m × n，极大减小了动作空间。 除此之外在上述动作中补充动作 ϕ 用来表示在当前调度时刻不做任何调度或者调度决策不合理。当动作为 ϕ 时，仿真环境执行t个单位时间之后进入下次调度决策过程。而两次调度的间隔t取3.2节中几种事件时间的较小值，同时为了控制调度间隔 的大小，人为规定t的最大值取16，这样做可以控制两次调度之间的时间间隔不至于太大。 4.3. 奖励函数设计 奖励函数是智能体用于评价动作好坏的标准，因此设计的奖励函数需要与优化目标息息相关。对于单个任务而言，比较关注任务本身的完成时间。本文设计相应的奖励函数来优化任务的平均带权周转时间，任务的带权周转时间为任务完成时间(任务完成时刻 − 任务提交时刻)除以任务的实际执行时间。 因为每个任务的实际执行时间不同，因此他们对于在系统中的等待时间容忍也不同。对于长任务来说由于会占用较久系统资源，因此能够接受较长时间的等待，而对于短任务来说如果等待太长时间会大大降低这类任务的效率。因此考虑使用任务的带权周转时间作为优化目标，可以同时兼顾长任务和短任务。对于优化任务带权周转时间的奖励函数设计如下： r = − ∑ j ∈ J t d j (1) 式中的t为两次调度之间的时间间隔，d j 为任务j的实际执行时间。将所有 t / d j 加起来得到的就是所有任务的带权周转时间之和。强化学习中通常是最大化奖励的，因此为了最小化任务的带权周转时间在奖励函数中加入一个负号即可。使用该奖励函数可以优化任务的带权周转时间，提高集群的资源利用率。 4.4. 深度强化学习模型结构设计 深度强化学习方法通过智能体和环境的不断交互来优化智能体的策略，深度强化学习模型结构如图3所示。智能体从环境中获取当前时刻的系统状态，用向量对系统状态进行表示，将获取到的状态向量输入到智能体的神经网络中，网络输出该状态对应的动作决策到环境中，此时环境状态会发生变化，同时会得到一个关于状态和动作的奖励反馈给智能体，智能体根据奖励可以知道所做决策正确与否，从而不断优化神经网络。 图3所示的模型结构中智能体使用的网络结构为经典的Actor-Critic框架。Actor-Critic框架包含Actor网络和Critic网络，其中Actor网络和Critic网络的输入都是环境的状态，Actor网络输出智能体的动作，Critic网络输出状态的值函数，用于评价动作的好坏。因为Actor网络和Critic网络都是从状态中提取集群信息，因此两个网络前两层结构相同。实验时将前两层网络的参数进行共享，这样有效减少了模型的参数个数，加速网络的优化收敛，同时其性能基本不会下降。 图3. 深度强化学习模型结构 4.5. 算法实现 本文对深度强化学习中的A3C算法和PPO算法进行实现并对比，然后使用Dagger方法实现模仿学习来模仿短任务优先调度算法。 4.5.1. A3C算法 A3C算法 [ 9 ] 是众多Actor-Critic算法中常用的一种，在Actor-Critic框架下，A3C算法通过将Actor-Critic网络放到多个线程中进行同步训练，有效提高了模型的训练速度。同时由于每个线程在训练过程中是独立的，减弱了事件的相关性，使得模型更容易收敛。Actor网络更新时使用的公式如下： d θ = Δ θ log π ( a | s ; θ ) ( R − V ( s ; θ ) ) + β Δ θ H ( π ( a | s ; θ ) ) (2) 其中 π ( a | s ; θ ) 是智能体的策略，R是交互过程中的累积奖励，而 V ( s ; θ ) 是Critic网络的输出，除此之外还加上了策略的熵，通过将策略的熵加入损失函数的方法，一定程度上可以防止策略变为确定性策略，增加所有动作遍历到的可能。Critic网络是对累积奖励的预测，使用均方误差作为损失函数，因此Critic网络梯度计算公式如下： d θ v = ∂ ( R − V ( s ; θ v ) ) 2 ∂ θ v (3) 4.5.2. PPO算法 深度强化学习方法需要智能体和环境不断进行交互，这个过程耗费很大一部分时间，即使使用A3C算法并行进行训练，整体训练效率依然不高效，主要原因是这些算法都是同策略的强化学习方法，用来更新策略的数据必须是当前策略和环境进行交互采集得到，而每次完成参数更新之后的数据不可以再次使用，这导致采集的数据利用效率很低。 PPO算法 [ 10 ] 使用重要性采样原理，将一次采样得到的数据用来多次更新策略，这让模型可以重复使用以往采样得到的“经验”，大大提升了数据利用率。同时PPO算法为了控制每次参数更新的幅度，使用裁剪的方法来控制新旧策略的差异，使策略可以更稳定进行更新。 PPO算法同样是基于Actor-Critic框架的，只是在Actor网络的更新上较A3C算法有所不同。PPO算法因使用了重要性采样原理，使得其可以使用一次采样得到的数据进行多次策略参数更新，其Actor网络更新的目标函数如下： J = ∑ ​ min ( π θ ( a | s ) π θ ′ ( a | s ) ， clip ( π θ ( a | s ) π θ ′ ( a | s ) ， 1 − ϵ ， 1 + ϵ ) ) A π θ ′ ( s ， a ) (4) 4.5.3. 模仿学习 传统深度强化学习方法是通过计算累积奖励来评估策略好坏，然后对策略进行更新以达到预期优化目的。模仿学习则是通过模仿专家做决策的方法来学习很好的决策策略。因为模仿学习不再需要累积奖励来判断动作优劣，因此也就不需要Critic网络来预测状态的值函数。而Actor网络作为输出策略的网络，只需要对Actor网络进行适当修改即可，其更新公式如下： J = ∑ ​ A ^ log π ( a | s ; θ ) + β H ( π ( a | s ; θ ) ) (5) 其中 A ^ 为专家给出的状态s下各个动作的概率，相当于专家对状态s下各动作的评价。为了应对模仿学习中复合误差问题，使用Dagger [ 11 ] 的方式来解决。在智能体和环境进行交互时，根据智能体的策略 π ( a | s ; θ ) 来得到状态s下模型执行的动作a，同时根据专家 E ( s ) 得到专家在状态s下的动作 a ^ = E ( s ) 。在交互中使用根据模型策略得到的动作a，同时将状态s和专家动作 a ^ 作为状态–动作对存储到经验池中。训练时从经验池中随机采样部分样本进行Actor网络的更新。