概述
流水作業是並行處理技術領域的一項關鍵技術,它是以專業化爲基礎,將不同處理對象的同一施工工序交給專業處理部件執行,各處理部件在統一計劃安排下,依次在各個作業面上完成指定的操作。
流水作業調度問題是一個非常重要的問題,其直接關係到計算機處理器的工作效率。然而由於牽扯到數據相關、資源相關、控制相關等許多問題,最優流水作業調度問題處理起來非常複雜。已經證明,當機器數(或稱工序數)大於等於3時, 流水作業調度問題是一個NP-hard問題(e.g分佈式任務調度)。粗糙地說,即該問題至少在目前基本上沒有可能找到多項式時間的算法。只有當機器數爲2時,該問題可有多項式時間的算法(機器數爲1時該問題是平凡的)。
我們先給出流水作業調度的定義:
設有n個作業,每一個作業i均被分解爲m項任務: Ti1,Ti2,…,Tim(1≤i≤n,故共有m∗n個任務), 要把這些任務安排到m臺機器上進行加工。 如果任務的安排滿足下列3個條件, 則稱該安排爲流水作業調度:
- 每個作業 i 的第 j 項任務Tij (1⩽i⩽n,1⩽j⩽m) 只能安排在機器 Pj 上進行加工
- 作業 i 的第 j 項任務 Tij(1≤i≤n,2≤j≤m) 的開始加工時間均安排在第 j−1 項任務Tij−1 加工完畢之後,任何一個作業的任務必須依次完成,前一項任務完成之後才能開 始着手下一項任務:
- 任何一臺機器在任何一個時刻最多隻能承擔一項任務。
最優流水作業調度是指:
設任務τij在機器Pj上進行加工需要的時間爲tij。 如果所有的tij(1⩽i⩽n,1⩽j⩽m)均已給出, 要找出一種安排任務的方法, 使得完成這 n個作業的加工時間爲最少。 這個安排稱之爲最優流水作業調度。
前面已經說過,當m≥3時該問題是NP問題,這裏我們只給出m=2時時間複雜度在多項式以內的Johnson算法。
求解流水作業調度問題的Johnson算法具體描述如下:
1、設 a[i]和 b[i] (0≤i<n)分別爲作業 i 在兩臺設備上的處理時間。建立由三元組 (作業
號,處理時間,設備號)組成的三元組表 d。其中,處理時間是指每個作業所包含的兩 個任務中時間較少的處理時間。
設 n=4,(a0,a1,a2,a3)=(3,4,8,10) 和 (b0,b1,b2,b3)=(6,2,9,15) 的作業 0 的三元組爲 (0,3,0), 作業 1 的三元組爲 (1,2,1) 。 如圖 (a) 所示。
(a)三元組表
作業號 0123 處理時間 32810 設備號 0100
2、對三元組表按處理時間排序,得到排序後的三元組表 d。如圖(b)所示。
(b)按處理時間排序
作業號 1023 處理時間 23810 設備號 1000
3、對三元組表的每一項 d[i](0≤i<n), 從左右兩端生成最優作業排列 c[j](0≤j<n),c[j]是作業號。如果 d[i]設備號爲 1,則將作業 i 置於 c 的左端末尾,否則置於 c 的右端 末尾。如圖©所示,由兩端向中間存放。
(c)最優作業排列
(0,2,3,1)
(d)最優調度方案
p1p23689101542
例題:
下面是北大PKU POJ 第2751題Saving Endeavour
有2臺機器,n件任務,必須先在S1上做,再在S2上做。任務之間先做後做任意。求最早的完工時間。
雙機調度問題Johnson算法簡析:
(1)把作業按工序加工時間分成兩個子集,第一個集合中在S1上做的時間比在S2上少,其它的作業放到第二個集合。先完成第一個集合裏面的作業,再完成第二個集合裏的作業。
(2)對於第一個集合,其中的作業順序是按在S1上的時間的不減排列;對於第二個集合,其中的作業順序是按在S2上的時間的不增排列。
Johnson算法的時間取決於對作業集合的排序,因此,在最懷情況下算法的時間複雜度爲0( nlogn ),所需的空間複雜度爲0( n )。
c語言代碼如下:
#include <stdio.h>
#include <memory.h>
#include <algorithm>
using namespace std;
const int MAXN=10005;
struct TNode
{
int s1,s2;
}ws[MAXN];
int topf,tops;
int n;
bool operator<(TNode x,TNode y)
{
if (x.s1<x.s2&&y.s1>=y.s2) return true;
if (x.s1<x.s2&&y.s1<y.s2) return x.s1<y.s1;
if (x.s1>=x.s2&&y.s1>=y.s2) return x.s2>y.s2;
return false;
}
int max(int x,int y)
{
return x>y?x:y;
}
void Work()
{
sort(ws,ws+n);
int i,t1=0,t2=0;
for (i=0;i<n;i++)
{
t1+=ws.s1;
t2=max(t1,t2)+ws.s2;
}
printf("%dn",t2);
}
void Read()
{
int i;
while (scanf("%d",&n)&&n)
{
for (i=0;i<n;i++)
scanf("%d%d",&ws.s1,&ws.s2);
Work();
}
}
int main()
{
Read();
return 1;
}