调度问题(二)

1,126 阅读14分钟

续前文调度问题(一)

O|pmtn|C_{max}问题

第二个使用二分图匹配来设计算法的是O|pmtn|C_{max}问题,即开放车间下的抢占式调度优化最终完成时间。我们在之前使用LS算法解决过O||C_{max}问题,其中提到两个下界:\Pi_{max}是单个机器的最大负载时间(每个任务在单个机器上需求的处理时间之和),P_{max}是单个任务的最大处理时长。这两者仍然是抢占式调度下该问题的下界。实际上,允许抢占式调度的情况下,使用二分图匹配算法能够达到最优策略,其完成时间等于\max(P_{max},\Pi_{max})

我们考虑对此问题的一个调度的任意时间点,在这个时间点,每个机器至多在处理一个任务,也就是说,在每个时间点,调度策略都指定了一个任务到机器的匹配。我们的目的是找到任意时间点的一个符合最优调度的匹配,并按照这个匹配来执行任务。

我们称总剩余处理时长等于P_{max}的任务为j_{max},称机器负载时间达到\Pi_{max}的机器为m_{max},也称它们是紧迫的,注意随着时间的推进,这两个值是变化的(有的任务可能不在匹配中,因为没执行)。如果能够让某时间点的匹配包含j_{max}m_{max},那么在这个匹配下执行t时间,我们就可以将这个调度的理论下界\max(P_{max},\Pi_{max})降低t。如果任意时间点的匹配均满足这一条件,那么最终能够将这个下界降低到零,这说明此时最大负载的机器已经处理完毕,所有任务都执行完毕,而处理时间恰好等于\max(P_{max},\Pi_{max}),这就是最优调度策略。同时这个匹配还必须满足所有边的剩余执行时间为正(这样才能继续执行),满足这些条件的匹配称为decrementing\ set,它的存在性证明较难,超出本文范畴,有兴趣的读者可以去读Lawler和Labetoulle的原论文[28]。

下面我们构造一个二分匹配问题来寻找它,这里比上一节的图简单。点集只需包含所有的任务i和机器j,同时包含每条边满足如下条件:连接一个机器i和一个任务j,且任务j在机器i上剩余所需的处理时间大于零。显然,根据上一段的分析我们需要这些边中包含进j_{max}m_{max},应用一些传统匹配算法很容易保证这一点。

现在我们找到了一个时间下的满足条件的匹配,只需按照这一匹配执行t时间,直到其中某个机器上的任务剩余时间等于零,或者某个机器剩余处理时间达到零,或者有新的任务或机器变紧迫(这是因为一个匹配可能不会包含所有任务和机器,导致其剩余处理时间没变),才寻找新的匹配。因此需要在许多时间点运行匹配算法,这会不会导致最终时间复杂度超过多项式时间呢?答案是不会。

证明:我们只会在特定条件(见上一段)满足时才寻找匹配,每个任务-机器对只会完成一次,因此最多需要运行nm次匹配,同时每个任务或机器只会变紧迫一次,因此最多n+m次。两者加起来不超过多项式时间。

线性规划

现在我们介绍线性规划算法在调度问题中的应用。一个线性规划问题通常以如下形式出现:

寻找长度为n的解向量x=(x_1,...,x_n),满足m个线性约束a_{i1}x1+a_{i2}x_2+...+a_{in}x_n\le b_i,其中1\le i\le n,并使得c_1x_1+c_2x_2+...+c_nx_n最小化,其中c=(c_1,...c_n)为成本向量。

有的时候,上面的一些约束可能是等式而非不等式,也有的时候甚至不存在需要最小化的目标函数,也就是说目标函数是任意的,我们只需要寻找到满足约束条件的解x即可。这些都算是线性规划问题的不同形式。许多优化问题都可以转化为线性规划求解,而线性规划问题存在多项式时间算法。本节主要考虑R|pmtn|C_{max}问题的线性规划模型。

R|pmtn|C_{max}问题

在不相关并行环境下进行抢占式调度,优化最终完成时间,不熟悉问题定义的建议回顾一下前面章节。抢占式调度下,单个任务可能在任何机器上运行一部分,为了形式化这个问题,我们使用nm个变量x_{ij},代表任务j的总任务量在机器i上执行的比例。例如,如果x_{1j}=x_{2j}=1/2,则说明任务j在机器1和机器2上各完成了一半的任务量。

现在我们考虑怎样的线性约束能够使x_{ij}的解符合R|pmtn|C_{max}问题的定义。显然,每部分任务的比例必须是非负的,从而有:

x_{ij}\ge 0, \ 1\le i\le m,\ 1\le j\le n.

同时,任意有效调度下,每个任务都必须被完成,这意味着:

\sum_{i=1}^m x_{ij}=1,\ 1\le j\le n.

我们的设计目标是最小化调度的最终完成时间D,显然任何机器上的总处理时间不超过D,根据之前的定义,不相关并行环境下,任务j在机器i上的处理时间记为p_{ij}

\sum_{j=1}^n p_{ij}x_{ij}\le D,\ 1\le i\le m.

最后,我们还需要保证,所有任务的总处理时间都不超过D

\sum_{i=1}^m x_{ij}p_{ij}\le D,\ 1\le j\le n.

我们需要在满足上述约束条件下最小化D。显然,任何一个有效调度下的x_{ij}必然满足这样的约束,但是有一事不明:一个满足约束条件的解并没有确切指定具体的调度策略——x_{ij}仅能指定任务在不同机器上运行的比例,而不能保证调度时同一时刻只能在一个机器上运行(这一条件无法写成线性约束)。

有趣的是,这个问题可以通过定义一个开放车间问题O来解决。我们为每个x_{ij}创建一个任务j在机器i上的操作,操作的处理时间为o_{ij}=x_{ij}p_{ij},现在对于已经通过线性规划求出的最优的x_{ij},我们构造了一个抢占式的开放车间问题,优化目标仍是C_{max},此问题概括为O|pmtn|C_{max},此问题已在上一节通过一个二分图匹配的形式化问题解决了,同时由于有D约束了任务的最长处理时间和机器的最长负载时间,也就是说P_{max},\Pi_{max} \le D,新问题的解就是原问题的最优调度。

线性规划问题不止这点应用,它还能用于设计NP难问题的近似算法,这将在下一节介绍。

使用松弛法设计近似算法

现在我们转向设计一些NP难的调度难题的近似算法。近似算法的设计通常基于相应的NP难问题的松弛版本。问题的松弛指的是从原问题中去除一些约束形成的新问题。例如1|r_j,pmtn|\sum C_j就是1|r_j|\sum C_j的松弛版本,因为实际上抢占式调度比非抢占式调度简单多了,更容易计算最优解。另一种松弛的思路是移除“一个机器只能同时处理一个任务”的条件,让一个机器可以在同一时间运行多个任务。

显然,原问题的解一定是松弛问题的解,反之不一定。我们在上面章节提到的所有非抢占式调度算法都能用于解决抢占式调度,其解虽然可能不最优,但合法。同样地,松弛问题的最优解即使是合法的,也不一定达到原问题的最优解。

在这一课题上一个有效的想法是:设计一个可以在多项式时间内解决的松弛问题,然后再设计一个将松弛问题的解转化为原问题可行解的算法,并保证解尽量接近最优解。问题的关键是设计的松弛问题尽可能包含原问题较多的信息,使得松弛问题的最优解与原问题最优解尽可能接近。

本节将介绍两种对调度问题的松弛方法,一是通过非抢占式到抢占式的松弛,二是通过构造线性规划问题,松弛某些线性约束来实现。将松弛解转化为原问题解的方法也有两种,一是根据任务与机器的配对,二是根据任务在机器上的执行顺序。后面会详细介绍。

在开始本节内容之前,我们先介绍一个概念:松弛决策过程(relaxed decision procedure, RDP)。一个最小化问题的\rho-RDP定义为,接受一个目标值T,如果松弛问题没有小于等于T的解则返回None,否则返回一个不超过\rho T的原问题解。一个多项式时间的\rho-RDP能够很容易的转化为原问题的\rho-近似算法:通过对T进行二分查找,寻找最小的T,使得松弛问题有解并将此解转化为原问题的解。

为什么是\rho-近似的呢?逻辑是这样:假如原问题有最优解T^*,则松弛问题在T^*下必有解,将这个解转化为不超过\rho T的原问题解,这个过程构成\rho-近似算法。下面将应用这个设计思路。

R||C_{max}问题

本节给出一个R||C_{max}2-近似算法。我们刚刚用线性规划解决过的R|pmtn|C_{max}问题,是这个问题的抢占式松弛版本,实际上,如果我们加一条约束x_{ij}\in \{0,1\},就是非抢占式调度的线性规划模型了。实际上加上这个条件后,原先的第3条约束可以使得第4条约束多余,因此同样的建模下,本问题的线性约束为:

\sum_{i-1}^m x_{ij}=1,\ for\ j=1,...,n \\\sum_{j=1}^n p_{ij}x_{ij}\le D,\ for\ i=1,...,m \\x_{ij}\in \{0,1\},\ for\ i=1,...,m,\ j=1,...,n

这是一个整数线性规划问题,相比于一般的线性规划问题,整数线性规划是NP难的,因此问题并没有变简单。但是,我们提出的模型是有用的,可以用来松弛某些约束,例如得到一个非整数解,然后舍入到整数。

现在我们再次将整数约束松弛为x_{ij}\ge 0,但这就太松了一点,我们还要添加一个约束:如果一个任务j在机器i上的效率过慢,即p_{ij}\ge D,就不把这个任务分配到机器i

x_{ij}=0,\ if\ p_{ij}\ge D. \tag{4}

这个约束在原来的整数线性规划模型中是天然成立的,但我们移除整数约束后就需要手动添加。注意到,当D固定时,这是个简单的只有线性约束的规划问题(没有成本函数),我们只要找可行解即可。如果对于给定的D,问题没有解,则输出None,如果有解,我们就尝试将非整数解转化为原问题的可行整数解。

根据一个线性规划问题的基本结论:我们可以找到一个此问题的可行解,其中最多只有n+m个正值。这n+m个正的x_{ij}指定了n个任务的去向,假设这些x_{ij}中等于1的数量为k,则k个任务已经被完全指定去向,剩余n-k个任务需要至少2(n-k)x_{ij}指定去向(因为非整数意味着至少被分配在两台机器上),故k+2n-2k\le m+n,故n-k\le m,意味着至多有m个任务被分配在不止一台机器上。

现在,我们将所有x_{ij}=1的任务j直接分配到机器i,这部分调度记为S_1,剩余还有至多m个任务需要调度。我们简单地按照x_{ij}>0的解将任务j匹配到机器i,且保证每个机器至多一个任务(因为这部分任务不超过m个),这部分任务的调度记为S_2。关于S_2的存在性证明稍微有点复杂,感兴趣的请读[1]。

我们分析一下这样形成的调度策略的完成时间,它显然不超过S_1的完成时间加上S_2的完成时间。而由于x_{ij}是松弛问题的可行解,因此S_1的完成时间是\le D的,在S_2中,由于每个机器至多一个任务,且由于约束(4)x_{ij}>0意味着p_{ij}\le D,从而S_2的完成时间也是不超过D的,故这样调度的时间不超过2D。因此假设原问题的最优解是D,则该松弛问题必有解,且该解不超过2D

1|r_j|\sum C_j问题

前面已经提到,带发布时间的单机调度问题是NP难问题,本节将设计一个解决此问题的近似算法。对于此问题的抢占式版本,前面已经证明了最短剩余时间优先算法SRPT的最优性。利用这个松弛,我们将从其最优解中找出各任务的完成时间顺序,然后以相同的顺序构建非抢占式调度策略。此算法称为Convert-Preempt-Schedule,反转抢占式调度。

我们首先使用SRPT算法构建抢占式调度版本的最优解,然后按照该最优解中各任务的完成时间排序,按照C_1^P\le ...\le C_n^P给这些任务重新编号。而后按照相同顺序非抢占式的调度这些任务,如果某个时间点后继任务还未发布,就让机器空闲即可。可以证明,这个算法是2-近似的。

证明:对于任务j,由于其在抢占式调度中能在C_j^P时完成,因此假如没有其他任务,则它最晚也能在C_j^P时完成,当存在其他任务后,我们在其完成前插入了排在它前面的任务,因此它的最晚完成时间延长为:

C_j\le C_j^P+\sum_{k\le j}p_k

而由于在抢占式调度中,所有k\le j的任务都在C_j^P之前完成了,因此\sum_{k\le j}p_k\le C_j^P,从而有:

\sum_{j=1}^n C_j \le 2\sum_{j=1}^n C_j^P

假设非抢占式调度的最优解是\sum C_j^P,则对于抢占式的松弛版本必然有不超过\sum C_j^P的最优解,而通过上述分析可知此算法给出的解不超过抢占式最优解的两倍,证毕。

1|r_j,prec|\sum w_jC_j问题

这一节依然使用松弛法来解决这个难题(基本上是目前遇到的最难的单机调度问题了),我们采用线性规划来设计一个2-近似算法。

首先我们描述这个问题的线性规划约束,和之前不同,我们不从整数/非整数的角度松弛,而是从问题定义中寻找必要条件,形成一个线性规划问题。

对这个问题来说,任务运行的顺序极其重要,因此我们要寻找一种能表示任务顺序的形式化描述。很容易想到用时间来表示:定义C_j为任务j在调度策略中的完成时间。实际上这就能够完确定一个调度了(比之前的x_{ij}更清晰)。显然,最小化的成本函数是\sum w_jC_j。并且满足如下条件:

C_j \ge r_j+p_j,\ j=1,...,n.\\C_k \ge C_j+p_k,\ for\ each\ j<k.\\C_k \ge C_j+p_k \ or\ C_j \ge C_k+p_j,\ for\ each\ j \not= k.

这三个条件很容易理解,首先任务必须在发布时间后才能开始,其次需要等待任务所有的前驱任务完成才能开始,最后,任意两个不同的任务存在先后关系(处理时间不重叠)。

不幸的是,最后一个约束有“或”运算,不是一个确定的线性约束,这导致这个问题不是线性规划问题。我们尝试用不等式代替它。定义任务集J=\{1,...,n\},对任意子集S\subseteq J,定义p(S)=\sum_{j\in S}p_jp^2(S)=\sum_{j\in S}p_j^2。对任何可行的单机调度策略,可以证明下面的不等式成立:

\sum_{j\in S}p_jC_j\ge \frac{1}{2}(p^2(S)+p(S)^2),\ for\ each\ S\subseteq J.\tag{*}

证明:假设S中的任务按照完成时间升序编号。由于任意的任务j的完成时间大于在其前面完成的所有任务的处理时间之和,即C_j\ge \sum_{k=1}^j p_k,代入上式左边得:

\sum_{j\in S}p_jC_j\ge\sum_{j\in S}p_j\sum_{k=1}^jp_k=\frac{1}{2}(p^2(S)+p(S)^2)

对于没有发布时间,没有任务依赖的问题1||\sum w_jC_j问题,上面这个不等式的约束是完备的[37,41],可以形成一个可行解。现在把上面这个不等式加上原先的第一个和第二个不等式,组成1|r_j,prec|\sum w_jC_j的线性约束,这个新的线性规划问题是原问题的松弛问题。

注意到我们新提出来的不等式似乎有2^n个,但是它仍然可以被线性规划的椭圆算法[37,41]在多项式时间内解决。

现在为了简单起见,我们移除发布时间约束,只探讨1|prec|\sum w_jC_j问题,其对应的松弛问题将移除上面提到的第一个不等式。解上面的线性规划问题得到的解为C_1\le C_2\le...\le C_n,我们将证明按照这个顺序来调度任务是2-近似的。

假设上面的调度形成的新的完成时间为\tilde{C_j},按照惯例,我们只需证明\tilde{C_j}\le 2C_j就行。首先,设S=\{1,...,j\},没有了发布时间机器是没有空闲的,因此\tilde{C_j}=p(S)。同时根据上面提到的不等式(*),我们有:

\sum_{k=1}^jp_jC_j\ge \frac{1}{2}(p^2(S)+p(S)^2)\ge \frac{1}{2} p(S)^2

又因为C_1\le C_2\le...\le C_n,我们有:

C_jp(S)=C_j\sum_{k=1}^j p_k\ge\sum_{k=1}^j C_kp_k\ge \frac{1}{2} p(S)^2

\tilde{C_j}=p(S)\le 2C_j,证毕。