目錄算法
幾個簡單場景:網絡
一個CPU須要處理不斷到達的程序。如何安排程序處理的順序,最小化程序的平均處理時間(任務到達至完成的時間)。app
考慮一隊五個宇航員準備重返太空。有一些任務須要在出發前完成。每一個任務必須被分配給一個宇航員,且有的任務須要在其餘任務完成後才能開始。如何安排任務分配,使得全部任務的完成時間最小。ide
考慮一個生產不一樣類型產品的工廠。不一樣產品須要不一樣機器上的不一樣處理時間,須要首先在機器1處理,而後是機器2,最後機器3,不一樣產品在不一樣機器上處理時間不一樣。工廠會收到訂單,每一個訂單有額定的完成時間,必須在此以前完成。如何安排機器的生產順序,使得工廠完成儘量多的訂單。函數
更通常地說,調度問題一般指一系列任務須要分配到一些機器上,知足某些約束,而且優化一個特定的目標函數。從各類各樣的應用課題中能夠挖掘出成千上萬的調度問題建模,所以幾乎不可能徹底覆蓋這些問題。所以,咱們將從一些基本問題出發,介紹一些對解決調度問題有用的算法設計技術。優化
咱們僅聚焦於多項式時間算法,可是實際上許多這類問題都是NP難問題,顯然很難有肯定性的多項式時間算法來得出最優解。在這些問題中,咱們一般對相關的近似算法感興趣。spa
一個調度問題一般有三個元素:機器環境,最優條件,其他邊界約束。咱們首先從最簡單的機器環境開始,而後再討論更復雜的。設計
假設有\(n\)個任務的任務集合\(J\),在單機環境中,有一個在同一時間只能處理單個任務的處理機。任務\(j\)須要的處理時間爲\(p_j\),若是一個任務一旦開始就必須直接執行完,則稱該調度環境是非搶佔式的,不然是搶佔式調度。對任務集\(J\)的一個調度\(S\),指定機器什麼時候調出\(p_j\)的時間來執行任務\(j\),任務\(j\)在調度\(S\)中的完成時間記爲\(C_j^S\)。orm
一個調度算法的目標是計算一個「好」的調度策略,可是「好」的定義取決於不一樣的應用。必需要肯定一個最優性條件,調度算法的最終目標是給出知足該條件的調度策略。下面考慮一些邊界約束,每一個任務\(j\)具備發佈時間\(r_j\),只有在任務發佈後才能被處理。同時任務之間還有偏序\(<\),只有全部知足\(j'<j\)的任務\(j'\)被完成後,\(j\)才能被處理。排序
如今能夠考慮一個簡單的問題模型\(\alpha|\beta|\gamma\),在單機問題中,\(\alpha=1\)表明單機環境,\(\beta\)指邊界約束,\(\gamma\)指優化目標。若是要優化全部任務的平均完成時間,則\(\gamma=\sum C_j\),如果追求全部任務的完成時間,\(\gamma=C_{max}\)。在當前環境下,\(\beta\)是\(r_j,prec,pmtn\)的子集,分別表明發佈時間,任務間的偏序約束,是否搶佔式調度。上面提到的場景1就能夠用\(1||\sum C_j\)來建模。
此外,還有兩個其餘可能的元素會影響單機調度環境。
最後,咱們考慮一個更通常的優化條件。對任務\(j\),定義\(f_j(t)\)爲隨完成時間\(t\)的非減函數。對調度策略\(S\),定義\(f_{max}=\max_{j=1}^nf_j(C_j^S)\)。後面會考慮到的一個問題建模就是\(1|prec|f_{max}\)。
如今咱們考慮一些更復雜的環境,首先是並行機器環境。假設有\(m\)個機器,任務\(j\)可被任意一個機器處理,固然若是容許搶佔式調度,那麼一個任務能夠先在一個機器上處理,再轉移到另外一個。單個機器同時只能處理很少於一個任務,單個任務同時只能在很少於一個機器上運行。
在等價(identical)並行環境中,每一個處理機徹底相等。在均勻相關(uniformly related)並行環境中,每一個機器\(i\)具備速度\(s_i\),所以任務\(j\)在機器\(i\)上的運行時間將是\(p_j/s_i\)。在不相關(unrelated)環境中,每一個機器的速度還和任務相關,即\(s_{ij}\),表示機器\(i\)運行任務\(j\)的速度,此時運行時間將爲\(p_{ij}=p_j/s_{ij}\)。
在工廠環境中,也有\(m\)個機器,可是任務由不一樣的操做組成,每個操做須要在特定的機器上完成,不一樣操做可能須要不一樣的時間來完成。在開放工廠(open shop)中,每一個商品的不一樣處理操做能夠以任意順序完成,只要保證兩個操做不是同時在不一樣機器上處理的。而在任務工廠(job shop)中,不一樣的操做之間具備一個全序關係,一個操做必須在其全部前驅操做完成後才被執行。任務工廠的一個特殊例子是流水線工廠(flow shop),它還要求不一樣任務在機器上的處理時間不一樣。在流工廠和開放工廠中,每一個任務都須要在每一個機器上處理一次,完成特定操做。
上面介紹的等價並行,均勻相關,不相關環境分別用\(P\), \(Q\)和\(R\)來表示,開放工廠,流水線工廠,任務工廠分別用\(O\),\(F\),\(J\)表示。至此前面提到的簡單場景2能夠用\(P5|prec|C_{max}\)建模,場景3可用\(F3|r_j|\sum U_j\)建模。
最顯然的解決上述問題的調度算法就是貪心選擇:每當一個機器空閒下來,就分配給它一個任務。咱們把算法再稍微設計的精緻一點的話,就爲每一個任務定義一個優先級函數(根據最優條件\(\gamma\)),而後分配時分配最高優先級的任務。在這一章節,咱們討論單機環境,多機並行環境,工廠環境下如何設計這樣的貪心策略。在設計的時候,優先級函數僅與當前任務\(j\)相關,這樣的話調度算法僅須要兩步:計算優先級,排序。顯然時間複雜度爲\(O(n\log n)\)。咱們也將探討這樣設計的一些缺陷。
首先關注單機調度問題下的優先級策略:按照優先級對任務進行排序,然後以此順序做爲調度策略。若是要證實此類算法的最優性,一般採用交換的方法來論證:若是存在一個最優策略,其執行順序不符合按照優先級排序的結果,也就說明這個順序中存在兩個任務順序與優先級不符,咱們證實交換這兩個任務能帶來更好的結果,以此說明這樣的最優策略不存在(也就是常見的反證)。
這大概是最簡單的模型了,優化全部任務的完成時間之和\(\sum C_j\)。直覺上看,咱們應該把花費時間最長的任務放在最後作,這樣其花費就不會累加在其他任務之上,這就是最短任務優先算法(shortest processing time):按處理時間\(p_i\)非減地排序全部任務,按照這個順序來調度任務。
定理3.1.1:\(SPT\)算法能夠最優的解決\(1||\sum C_j\)調度問題。
證實:假設存在兩個任務\(j\)和\(k\)按照相鄰順序參與調度,可是\(p_j>p_k\),造成了一個最優調度。如今咱們將兩個任務對調,此時因爲\(j\)和\(k\)相鄰,其餘任務的完成時間不變,惟一變化的是\(j\)和\(k\),假設兩個任務開始於時間\(t\),則對調前,兩個任務的完成時間之和爲\((t+p_j)+(t+p_j+p_k)\),對調後,完成時間爲\((t+p_k)+(t+p_k+p_j)\),變化爲\(p_k-p_j\),因爲\(p_j>p_k\),所以對調後完成時間更優,與假設的最優性矛盾。
實際上對於帶權的問題\(1||\sum w_jC_j\)也能夠按照這個思路來證實,直覺上咱們要充分利用每一段單位時間的權重,單位時間內得到的權重越大越好,也就是按照\(w_j/p_j\)升序排列。其證實能夠簡單地由上面的證實推演出。
一個很天然的想法是,首先調度最緊迫的任務,這催生出最先截止算法(earliest due date)EDD:按任務的截止時間升序排列並調度之。能夠證實,EDD對於\(1||L_{max}\)是最優的。
定理3.1.2:\(EDD\)算法對於\(1||L_{max}\)是最優的。
證實:一樣適用交換論證法。不失通常性,假設全部任務的截止時間不重複,且\(d_1<d_2<...<d_n\)。在全部可能的最優調度中選擇具備最少逆序的一個調度,其中有一些任務對\(j\)和\(k\),\(j<k\)可是調度順序相反,顯然它不是EDD調度。假設\(j\)和\(k\)是相鄰的(必然存在這樣的任務對),咱們替換二者不改變其餘任務的完成時間,一樣也不改變其延時。惟二變化的就是這兩個任務,下面證實的目標是交換後下降了\(\max(L_j,L_k)\),不改變調度的最優性。因爲在替換前,\(j\)後於\(k\)調度,意味着\(C_j^S>C_k^S\),可是\(d_j<d_k\),故\(\max(L_j,L_k)=C_j^S-d_j\),替換後任務\(j\)的完成時間減小了,可是任務\(k\)的上升到原來的\(C_j^S\),所以二者之間最大延時不大於\(C_j^S-d_k\),這小於替換前的結果。這樣的話,因爲交換了\(j\)和\(k\),咱們減小了這個調度中的逆序,可是它依然至少是最優的,這和假設矛盾。
如今考慮更復雜點的單機調度,不一樣的任務會在不一樣的時間到達,即發佈時間\(r_j\),顯然上面提到的貪心策略不能直接使用,由於優先級高的任務不必定會早於優先級低的任務被髮布。要處理這樣的狀況,最直接的方法就是無論他,每次調度都處理當前已發佈的任務中優先級最高的任務。在搶佔式調度中,這意味着一旦一個更高優先級的任務發佈,當前正在執行的任務就要掛起,把處理器資源讓出來。咱們將會證實這個策略在搶佔式調度中是最優的。
定義最短剩餘時間優先算法(shortest remaining processing time, \(SRPT\)):每一個時間點按照最短剩餘時間調度,當有剩餘時間小於當前任務時,搶佔處理機。同時定義新的EDD算法:按照當前已發佈的最先截止時間任務搶佔式調度。能夠證實,\(SRPT\)是調度\(1|r_j,pmtn|\sum C_j\)問題的最優算法,\(EDD\)也是\(1|r_j,pmtn|L_{max}\)的最優解。
證實:和以前同樣採用反證法導出矛盾,不一樣的是咱們此次交換的是不一樣任務的片斷(考慮到搶佔式調度)。首先咱們考慮\(1|r_j,pmtn|\sum C_j\)問題,假設一個最優調度中具備最短剩餘時間的已發佈任務\(j\)沒有在\(t\)時刻被調度,而是任務\(k\)被調度,且剩餘時間\(p_j'<p_k'\)。總的來講,時間\(p_j'+p_k'\)將在\(t\)時刻以後被佔用。如今進行一次替換:將\(p_j'+p_k'\)的前\(p_j'\)時間片用於執行任務\(j\)而不是任務\(k\),剩餘時間用於任務\(k\)。在新的調度策略中,\(j\)和\(k\)之外的任務完成時間均不變,可是對於\(j\)和\(k\),因爲\(j\)剩餘時間小,替換後\(C_j+C_k\)下降了,矛盾,從而\(SRPT\)是最優的。對於\(EDD\)的證實一模一樣,將前面的時間片用於截止時間更早的任務\(j\)後,不增長最大延遲(分析方法和以前相似)。
以前考慮的都是搶佔式調度下,具備發佈時間\(R\)的調度策略,分別是\(SRPT\)和\(EDD\)。可是對於非搶佔式調度,因爲不能簡單地掛起當前任務執行新任務,咱們必須決定要不要停機等待一個更高優先級任務,仍是直接執行面前的低優先級任務,這在直覺上很難計算最優解。實際上,\(1|r_j|\sum C_j\)和\(1|r_j|L_{max}\)都已被證實爲\(NP\)難問題,咱們將在後續介紹相關的近似算法。
一樣地,上面的貪心策略也不適用於帶權重的任務調度,\(1|r_j,pmtm|\sum w_jC_j\)也被證實爲\(NPH\)問題。同時\(SRPT\)和\(EDD\)稱爲在線調度算法,由於它們不依賴於當前時刻未知的條件,僅依賴當前已發佈的任務的優先級來進行調度。文獻[38]是一個完整的在線調度綜述。
另外一個更復雜的問題是在流水線工廠中最小化任務的最終完成時間,通常來講,對於大於等於3個機器,這個問題是\(NP\)難的。可是特殊狀況,對於雙機流水線\(F2||C_{max}\),存在一個基於優先級的最優算法。記\((a_j,b_j)\)爲任務\(j\)須要在兩個機器上進行處理的時間。直覺上,咱們應該讓第一個機器儘量快地處理短任務,以讓第二個機器減小等待;同時應該讓第二個機器先處理長任務,由於這些任務自己就表明着較大的完成時間,縮小它們有助於縮小最終的\(C_{max}\)。
下面將這個想法形式化:將全部任務分紅兩個集合,\(A\)表示\(a_j\le b_j\)的任務集合,\(B\)表示\(a_j>b_j\)的任務集合。定義一個\(Johnson\)規則:首先將\(A\)集合中的任務按照\(a_j\)升序排列,再將\(B\)集合中的任務按照\(b_j\)降序排列,按這個順序調度兩個機器上的全部任務。
注意:咱們並無在第二個機器上重排任務,全部任務的兩個操做在兩個處理機上都是按相同順序執行,這種調度稱爲排列調度(permutation schedule)。注意:超過2個機器就不必定有最優排列調度了,可能須要在第二個機器上重排。
定理3.2.1:\(F2||C_{max}\)問題的實例老是存在一個最優的排列調度。
證實:考慮任意一個最優調度\(S\),按照任務在機器1上完成的時間對任務進行編號。假設存在任務對\(j<k\)(這意味着在機器1上\(j\)先於\(k\)完成),在機器2上,任務\(j\)緊接着\(k\)被執行,而且\(k\)在機器2上開始執行的時間爲\(t\),這說明任務\(j\)在機器1上完成的時間早於\(t\),在時間\(t\)時,兩個任務均可以在機器2上執行。所以咱們替換任務\(j\)和\(k\)在機器2上的執行順序,這不改變最終完成時間。所以能夠不斷進行這樣的替換並保持最優性,直到不存在知足條件的任務對,最終全部任務在機器2上的執行順序等同於機器1,咱們就將這個最優調度替換成了排列調度,證畢。
如今咱們能夠將問題的解空間限制在排列調度上了(由於存在最優的排列調度)。
定理3.2.2:經過\(Johnson\)規則造成的任務排列是雙機流水線模式的最優調度。
證實:注意到,在一個排列調度中,必然存在一個任務\(k\)在機器1的操做完成後能夠不通過等待直接開始在機器2上的操做。所以\(n\)個任務的完成時間包含前\(k\)個任務在機器1上的處理時間和\(n-k+1\)個任務在機器2上的處理時間。這些加起來一共包含\(n+1\)個任務的處理時間(\(n+1\)個\(a_i\)或\(b_j\)的組合),所以若是把全部的\(a_i\)和\(b_i\)減去相同的時間\(p\),那麼在排列調度下,最終完成時間將減小\((n+1)p\)。
同時,還注意到,若是一個任務的\(a_i\)等於0,它必然在某個最優排列調度中被最優先調度,由於它不佔用機器1的時間,反而能夠填充機器2可能的空閒等待時間,充分利用機器2。相似的,若是一個任務的\(b_i\)等於0,它必然在某些最優排列中被放在最後執行(由於機器1是無空閒的,而在機器2上不佔時間,不能提升機器2的利用率)。
所以,咱們能夠這樣構造一個最優的排列調度:不斷尋找未調度任務中具備最小\(a_j\)或\(b_j\)的任務\(j\),而後將全部未調度任務的處理時間減去這個最小值,此時任務\(j\)的\(a_j\)或\(b_j\)爲0,按照上面的分析將其置於排列的最前或最後。
容易看出,這樣的構造產生的最優排列知足\(Johnson\)規則。
如今咱們考慮等價並行環境\(P\),機器一旦多起來,不少原先在單機環境下很簡單的問題變成了\(NP\)難問題。所以咱們傾向於尋找問題的近似算法。實際上,在一些狀況下,單機環境下簡單的優先級調度也可以在並行環境下獲得不錯的效果。這類算法的一般步驟是:每當一臺機器變得空閒,就把當前優先級最高的任務分配給它。這種不聽任任何機器空閒的調度策略被稱爲「繁忙」調度(busy schedule)。
在這一節,咱們還將介紹一個新的分析方法。咱們將給出一個最優調度策略質量的下界,而再也不使用交換法論證策略最優性。然後咱們將論證提出的近似算法可以達到最優策略下界的附近,好比差一個因子。這是分析近似算法的常見技術,保證了近似算法的解可以以比例逼近最優解,雖然咱們並不知道最優解的位置。有時咱們甚至能論證新的貪心算法可以到達最優的下界,這就意味着該貪心算法其實是最優的。
首先聚焦於最小化\(m\)個並行機上的平均完成時間,即\(P_m||\sum C_j\)。在這個問題下,貪心的\(SPT\)算法依然是最優的。後面會進行證實。
然後考慮最小化最終完成時間\(C_{max}\),在單機環境下,\(1||C_{max}\)基本不是一個問題,只要保證機器不空閒,隨便怎麼調度結果都同樣。可是機器一旦多起來,問題就很複雜了。若是容許搶佔式調度,存在一個最優的多項式時間的貪心算法。可是在非搶佔式條件下就不行了,它已被證實是\(NPC\)問題[7],咱們將給出一個它的近似算法,首先咱們證實任何繁忙調度是2-近似的,而後咱們介紹一個更聰明的4/3-近似算法——\(LPT\)算法,最後咱們將給出一個更優但也更復雜的算法。
咱們對這些算法的分析是基於比較它的解與最優解下界的差距,所以和最優解的差距會更小。下面是兩個簡單的\(C_{max}\)的下界:
\[ C_{max}^*\ge \sum_{j=1}^n p_j/m \]
\[ C_{max}^*\ge \max_jp_j \]
第一個下界說明,最優調度策略獲得的完成時間至少是每一個機器的平均負載,第二個下界說明,最終完成時間至少是任何一個任務的完成時間。這兩個下界都是很顯然的,且對於搶佔式和非搶佔式都有效。首先對於搶佔式問題\(P|pmtn|C_{max}\),咱們將給出一個最優調度算法,它可以達到上面兩個下界的最大值;後續對於非搶佔式調度,咱們將使用這個下界來肯定近似解。
\(McNaughton’s\)規則是一個簡單的構造\(P|pmtn|C_{max}\)問題最優解的方法,它最多須要\(m-1\)次搶佔。這個算法和許多其餘調度算法不一樣,以機器爲單位調度任務,而非時間。
定理3.3.1:用\(McNaughton’s\)規則構造\(P|pmtn|C_{max}\)的策略,其最終完成時間達到最優下界。
證實:首先定義\(D\)是最優下界,它等於上述的兩個下界的最大值:\(D=max\{\sum_jp_j/m,\max_jp_j\}\)。然後,咱們準備把任務片斷分配給各個機器:按順序從機器\(1\)至\(m\),任務\(1\)至\(j\)進行分配,每一個機器分配的處理時間都不超過\(D\),機器\(i\)分配滿\(D\)時間後才能開始機器\(i+1\)的分配。每一個任務\(j\)有最後的\(t\)時間片在機器\(i\)上執行,前\(p_j-t\)時間片在機器\(i+1\)上運行。因爲\(D\)不小於單個任務的處理時間,所以一個任務最多被搶佔一次分在兩個機器上執行。又因爲\(mD\)不小於全部任務的總處理時間,按照這種方法分配,全部任務都必定可以被分配成功,這說明會有一個任務不須要搶佔(不然須要\(m+1\)個機器),所以該算法共搶佔\(m-1\)次。
\(P||C_{max}\)是已證實的\(NP\)難問題,咱們給出幾個簡單的近似算法。
這是一個極其簡單的貪心策略:每當有新的機器空閒,就爲其分配任意一個未處理的任務,但它居然是\(2\)-近似的。
定理3.3.2:\(LS\)算法是\(P||C_{max}\)的\(2\)-近似算法。
證實:假設任務\(j\)是在一次\(LS\)調度中最後完成的任務,那麼它的完成時間就是最終完成時間\(C_{max}\),設它的處理時間爲\(p_j\),開始時間爲\(s_j\),則\(C_{max}=s_{j}+p_j\)。注意到在時間點\(s_j\)以前,全部的機器應該都是繁忙的,不然任務\(j\)將更早開始。而全部機器同時保持繁忙的時間不會超過\(\sum_{j=1}^n p_j/m\),不然的話全部任務都完成了。所以咱們有:
\[ C_{max}^{LS}\le s_j+p_j\le \sum_{j=1}^n p_j/m+p_j\le 2C_{max}^* \]
這個算法很簡單,其獲得的完成時間不超過最優解的兩倍,實際上即便任務有發佈時間\(r_j\),即對於\(P|r_j|C_{max}\),這個算法也是\(2\)-近似的,證實方法相似,就不贅述了。
在上面的\(LS\)算法中,咱們每次分配任務都是任意選擇的,咱們在分析的時候選擇的瓶頸值是最後一個處理完成的任務,所以其完成時間不超過\(\sum_{j=1}^n p_j/m+p_j\),一個很天然的想法是,讓最後一個完成的任務儘量短,這樣完成時間的上界是否是就更接近最優呢?這就是最長處理時間優先調度\(LPT\):在\(LS\)調度的基礎上,每次選擇處理時間最長的任務進行分配。
定理3.3.3:\(LPT\)算法是\(P||C_{max}\)的\(4/3\)-近似算法。
證實:依然選取最後完成的任務\(j\),它開始於時間點\(s_j\),但它並不必定是最短任務,由於可能有其餘任務在\(s_j\)以後開始可是在\(s_j+p_j\)以前完成。所以,咱們把全部在\(s_j\)以後開始的任務移除,這不改變最終完成時間。只要對移除後的問題實例分析便可,在新的問題中,任務\(j\)同時也是最後開始的任務,這說明\(p_j=p_{min}\)。
參照\(LS\)算法的分析,\(LPT\)的調度結果\(C_{max}^{LPT}\le C_{max}^*+p_{min}\),若是\(p_{min}\le C_{max}^*/3\),不證自明,所以只需證實\(p_{min}>C_{max}^*/3\)的情形下,\(LPT\)就是最優調度:
在這種狀況下,任意的\(p_j>C_{max}^*/3\),意味着最優調度中,每一個機器分配的任務數不超過2,假設有\(m\)個機器,\(n\)個任務,這說明\(n\le 2m\),當\(n\le m\),顯然最優調度就是每一個機器分配一個任務,這和\(LPT\)是一致的,所以考慮另外一種狀況\(m<n\le 2m\),在這種狀況下,\(LPT\)調度是將任務按照處理時間降序排列,前\(m\)個任務按順序分配給\(m\)個機器,後續任務\(k\)將與\(2m+1-k\)配對在同一機器上。考慮一個非\(LPT\)的最優調度,存在機器\(i\)和機器\(j\)均被分配了2個任務,假設先分配了\(p_1\)和\(p_2\),其中\(p_1>p_2\),後續分配的任務\(p_i\)與\(p_j\)分別於其配對,可是\(p_i>p_j\),不符合\(LPT\)調度,咱們能夠簡單地替換\(i\)和\(j\)來下降兩個機器的完成時間,產生矛盾。所以\(LPT\)調度就是這種狀況下的最優解。
當輸入的任務存在依賴關係時,\(LS\)調度依然是非搶佔式調度的一個選擇,固然會有一些小修改。咱們說一個任務在\(t\)時刻是可運行的,若是其全部前驅均已在\(t\)時刻被完成。在這種狀況下,\(LS\)調度將每次選擇任意可運行的任務調度給空閒機器。同時,假設任務集中存在的任意一條任務鏈爲\(j_{i_1}<j_{i_2}<...<j_{i_k}\),則任意最優的調度策略的完成時間必然不會小於任務鏈上任務的處理時長:
\[ C_{max}^*\ge \max_i\sum_{l=1}^k p_{i_l} \]
這是有依賴關係的任務調度中新增長的下界。
定理3.3.4:\(LS\)算法是\(P|prec|C_{max}\)的\(2\)-近似算法。
證實:假設\(j_1\)是調度策略中最晚完成的任務,定義\(j_2\)是\(j_1\)的前驅任務中最晚完成的任務,如此遞歸地定義\(j_l\),直到任務\(j_k\)不存在前驅,構成集合\(C=\{j_1,j_2...,j_k\}\),咱們把\(LS\)調度策略的時間消耗分紅兩部分,\(A\)表示全部\(C\)中任務正在某個機器上運行的時間點,\(B\)表示其他的時間點,則\(C_{max}=|A|+|B|\)。注意到:\(B\)中全部時間點上,\(m\)個機器必然都是繁忙狀態,不然,若是有機器處於空閒狀態,而此時必然存在\(C\)中可運行的任務(\(C\)中沒有任務在運行),則該機器應當直接運行該任務。所以根據前面的分析,全部機器同時保持繁忙的時間不會超過\(\sum_{j=1}^n p_j/m\),從而\(C_{max}=|A|+|B|\le \sum_{j\in C}p_j+\sum_{j=1}^n p_j/m\le 2C_{max}^*\)。
\(LS\)調度還能夠應用於\(O||C_{max}\)問題,開放工廠問題下,每一個任務須要在不相交的時間區間內在不一樣機器上進行處理。設\(P_{max}\)是單個任務在全部機器上的處理時間之和的最大值,\(\Pi_{max}\)指單個機器上全部任務的處理時間之和的最大值,顯然二者均是最優調度的下界。
定理3.3.5:\(LS\)算法是\(O||C_{max}\)的\(2\)-近似算法。
證實:假設機器\(M\)是最後完成處理的機器,\(j\)是機器\(M\)上最後處理的任務。在任什麼時候間點,要麼機器\(M\)在處理中,要麼任務\(j\)在某個機器上處理,不然任務\(j\)將在機器\(M\)上處理。\(j\)的總處理時間不超過\(P_{max}\),而\(M\)的總處理時間不超過\(\Pi_{max}\),所以\(LS\)調度中,總處理時間最多不超過\(P_{max}+\Pi_{max}\),從而不超過\(2C_{max}^*\)。
對許多問題,簡單的調度策略並不能達到很好的效果,所以咱們在設計算法的時候,必須當心地選擇策略組合。實際上對於不少問題,特別是任務之間存在依賴關係,或是有發佈時間的狀況,最優調度一般容許機器有空閒時間。而應用貪心策略獲得的調度一般是繁忙調度,每每致使次優解。
考慮\(Q||C_{max}\)問題的簡單實例:兩個任務,兩個機器,機器1的運行速度爲1,機器2的速度爲\(x\),其中\(x>2\),兩個任務的處理時間均爲1。應用任何貪心調度策略,都會將兩個任務分在兩個機器上,完成時間爲1。但很顯然的是,若是咱們將兩個任務都分在機器2上,完成時間是\(2/x\),更優。當\(x\)無限擴大時,沒有任何貪心策略的解可以達到固定的近似比。實際上對於這個問題,咱們仍是能找到簡單的\(2\)-近似啓發式算法來解決問題,可是對於相似\(R||C_{max}\)和\(Q|prec|C_{max}\)這類複雜問題,就沒有簡單的近似算法。
基於優先級的調度算法把任務分開來單獨看待,在不少問題上會錯過最優解。在這一節,咱們考慮更復雜的策略,同時考慮其餘任務的信息來輔助決策,而不只僅按照優先級排序。這些算法是遞增迭代的,一般從一個空集開始,每次調度一個任務,直到達到最優解。每次任務的選擇是根據已分配的任務上下文來計算的。咱們將給出兩個經典的動態規劃算法,以及另外幾個更特別的算法。
咱們解決的第一個問題是\(1||f_{max}\),這是以前定義過的一大類問題,每一個任務存在一個非減的懲罰函數\(f_j(C_j)\),問題的目標是最小化全部任務的最大懲罰值,例如\(1||L_{max}\)中,\(f_j(t)=t-d_j\)。
咱們定義\(p(J)=\sum_{j\in J}p_j\)爲全部剩餘任務的處理時間之和,\(J\)是未調度的任務集合,任何任務都在\(p(J)\)時間以前完成,算法的主體是找到使\(f_j(p(J))\)最小的任務\(j\),將其放在最後執行,然後遞歸地對剩餘任務應用上述步驟,這個算法稱爲Least-Cost-Last。
注意到此算法和咱們以前的幾個貪心算法的不一樣之處,以前的貪心策略能夠按照同一個標準直接對\(n\)個任務排序,所以能夠應用\(O(n\log n)\)的排序算法完成,可是此算法必須調度任務\(j\)後,才能根據新的\(p(J)\)值肯定下一個被調度的任務,所以其時間複雜度爲\(O(n^2)\)。此算法最優性的證實依然是經過最優解的下界來設計。
定義\(f_{max}^*(J)\)爲任務集\(J\)的最優調度下的懲罰函數值,能夠推導出兩個下界:
\[ f_{max}^*(J)\ge \min_{j\in J}f_j(p(J)) \]
\[ f_{max}^*(J)\ge f_{max}^*(J-\{j\}) \]
第一個下界的來源是,必然有一個任務\(k\)最晚完成,它的懲罰函數參數剛好是\(p(J)\),從而有\(f_{max}^*(J)\ge f_k(p(J))\ge \min_{j\in J}f_j(p(J))\)。第二個下界來自於這樣一個事實:若是從任務集中去掉一個任務,不會增長任何任務的完成時間,而懲罰函數是完成時間的非減函數,這意味着新的任務集的最優調度懲罰不增。
定理4.1.1:\(LCL\)算法是\(1||f_{max}\)的最優解。
證實:根據算法步驟,咱們首先選取使得\(f_j(p(J))\)最小的\(j\)放在最後,其懲罰爲\(\min_{j\in J}f_j(p(J))\),然後剩餘任務集爲\(J-\{j\}\),在這個任務集上的最優解爲\(f_{max}^*(J-\{j\})\),所以\(LCL\)調度的懲罰值爲\(\max\{\min_{j\in J}f_j(p(J)),f_{max}^*(J-\{j\})\}\),剛好是前面導出的最優解的下界。
即便引入任務間依賴,Least-Cost-Last算法依然是最優的。在\(1|prec|f_{max}\)問題中,因爲任務間存在依賴,所以稍微修改一下算法描述:咱們將從當前未調度的無後繼任務集\(L\)中,選擇使\(f_j(p(J))\)最小的任務。這樣的話,能夠推導出一個新的下界:
\[ f_{max}^*(J)\ge \min_{j\in L}f_j(p(J)) \]
所以其最優性的證實徹底相似上一節的證實,再也不贅述。
\(Moore\)[33]給出過另外一種\(1||f_{max}\)的解法,他的策略基於前面提到過的針對\(L_{max}\)的\(EDD\)算法。假設咱們想知道是否存在一個調度可以使得\(f_{max}\le B\),能夠給任務\(j\)分配一個截止時間\(d_j\),使得\(d_j=argmax_t\{f_j(t)\le B\}\),易知,若是每一個任務都能在截止時間以前完成,那麼該調度的\(f_{max}\le B\)等價於\(L_{max}\le 0\)(不然只要有一個任務晚於截止時間,懲罰就超過\(B\)),所以咱們將\(f_{max}\)問題擴充了截止時間後,轉化爲了最小化最大延遲問題。所以一個想法是:對\(B\)進行二分查找,而後構造相應的截止時間,應用\(EDD\)來計算\(L_{max}\),從而逼近最優解。
如今咱們考慮\(1||\sum w_jU_j\)問題,其優化目標是最小化已超時任務的總權重。此問題是弱\(NPC\)問題,即具備僞多項式時間算法,該算法複雜度爲\(O(n\sum w_j)\),也就是說若是任務權重和能被一個\(n\)的多項式約束,那麼算法能夠在多項式時間內結束。實際上,若是全部權重都爲1,那麼問題\(1||\sum U_j\)能夠直接用該算法解決,且時間複雜度退化爲\(O(n^2)\)。並且,這個算法還能夠用來導出一個此問題的\((1+\epsilon)\)-近似算法,該算法複雜度是關於\(n\)和\(1/\epsilon\)的多項式。
首先注意到,在這個問題中,任務集被劃分爲兩種,一是在截止時間以前完成的任務,一是超時完成的任務。若是存在一個調度策略,使得一個任務集中全部任務都能在截止時間以前完成,則稱這個任務集是可行的。顯然,當一個任務集是可行的,那麼其調度策略能夠直接使用\(EDD\),由於\(EDD\)最小化最大延遲,在可行任務集下必然存在最大延遲不超過0的調度,從而使全部任務能按時完成。調度完成後,該可行任務集的完成時間就是全部任務的處理時間之和\(\sum p_j\)。
如今咱們考慮\(1||\sum w_jU_j\)問題,它其實是在尋找任務集\(\{1,2,...n\}\)中權重和最大的可行子集。首先將全部任務按照截止時間升序排列並編號,定義\(T_{wj}\)爲任務集\(\{1,2,...j\}\)的權重和不小於\(w\)的可行子集族中,具備最小完成時間的子集的完成時間。若是不存在任何可行子集,則記爲\(\infty\)。邊界條件:記\(T_{w0}=\infty,\ T_{0j}=0\)。如今嘗試計算\(T_{w,j+1}\),考慮\(\{1,2,...,j+1\}\)中權重和不小於\(w\)的完成時間最小的可行子集\(S\):
狀態方程總結以下:
\[ \begin{equation}T_{w,j+1}=\left\{\begin{array}\ min(T_{w,j},T_{w-w_{j+1},j}+p_{j+1})&if\ T_{w-w_{j+1},j}+p_{j+1}\le d_{j+1}\\T_{w,j}&otherwise\end{array}\right.\end{equation} \]
顯然,不存在權重超過\(\sum w_j\)的可行子集,所以一旦\(w\)超過該值就能夠終止程序。覆蓋全部\(w\)值的時間複雜度爲\(O(n\sum w_j)\),一旦計算完全部的\(T_{wj}\),咱們只須要找到使得\(T_{wn}<\infty\)的最大的\(w\)對應的可行子集,對該子集進行\(EDD\)調度,然後將其他任務最後調度,這就是\(1||\sum w_jU_j\)的最優調度策略。
咱們前面已經介紹過一些\(P||C_{max}\)的近似算法,其中最長任務優先算法\(LPT\)可以達到\(4/3\)的近似比,同時咱們也知道這個問題是\(NP\)難的。這一節咱們假設全部任務的處理時間都在一個有限集中選擇,則問題能夠在多項式時間內解決。
定理4.2.1:\(P||C_{max}\)問題中,任務數\(n\),機器數爲\(m\),\(p_j\)是任務\(j\)的處理時間,若是知足\(\{p_1,p_2,...p_j\}\subseteq S\)且\(|S|=s\le \infin\),則存在一個最優調度算法,其時間複雜度不超過\(n^{O(s)}\)。
證實:一樣適用動態規劃的思路,設\(S=\{z_1,z_2,...,z_s\}\),注意到在上面的約束下,一臺機器上運行的任務集能夠用一個\(s\)維向量來表示:\(v=(v_1,v_2,...,v_s)\),其中\(v_k\)表示在此機器上執行的處理時間爲\(z_k\)的任務的數量。同時因爲共有\(n\)個任務,意味着這樣的\(s\)維向量共有\(n^s\)個。設\(T\)是目標完成時間,也就是說全部機器須要在\(T\)時刻以前完成全部分配的任務。設\(V\)是全部處理時間小於\(T\)的(即\(\sum v_iz_i\le T\))的向量集合。在知足目標完成時間\(T\)的調度策略中,每一個機器必然都從\(V\)中選擇一個任務集來執行。定義\(M(x_1,...,x_s)\)是完成任務集\((x_1,x_2,...x_s)\)的最小機器數量。容易看出下面的等式成立:
\[ M(x_1,...,x_s)=1+\min_{v\in V}M(x_1-v_1,...,x_s-v_s). \]
實際上就是從中去除一個機器承擔的任務後,遞歸地計算剩餘任務所需的最小機器數,最終計算最小值。完整的執行這個動態規劃算法須要首先遍歷\(n^s\)個向量組合,每一個向量須要遍歷\(n^s\)次剩餘任務,所以時間複雜度爲\(O(n^{2s})\)。
還須要考慮的是\(T\)的選擇,能夠在全部可能的任務向量對應的處理時間中選擇\(T\),應用算法肯定最小機器數目,若是數目大於機器數\(m\)則減少\(T\),不然增長\(T\),據此能夠應用二分查找。最終獲得使得\(M=m\)的最小的\(T\)對應的調度策略就是最優調度。
網絡圖算法和線性規劃算法是組合優化問題的核心主題。可以用來解決許多難題,固然也能用於調度算法的設計。在這一節,咱們考慮應用二分圖匹配和線性規劃算法來解決調度問題。
一個二分圖包含兩個點集\(A\)和\(B\),以及邊集\(E\subseteq A\times B\),它的一個匹配\(M\)定義爲\(E\)的子集,且任何一個頂點都至多在\(M\)中的一條邊上。咱們能夠考慮將任務和機器進行匹配,這樣的話根據上面的定義,每一個任務最多隻會被分配給一臺機器,同時一臺機器最多隻會被分配一個任務。若是\(|A|\le |B|\),則若是\(A\)中全部結點都在匹配\(M\)的一條邊上,則稱這個匹配是完美匹配。固然,也能夠爲每條邊賦權重,然後定義匹配的權重爲其中全部邊的權重之和。一個很重要的事實是,二分圖的最小完美匹配是有多項式時間算法的。
在不相關並行環境下優化調度的平均完成時間,彷佛是一個挺難的問題,本節將給出一個多項式時間算法。對任何調度,設\(\kappa_{ik}\)爲在機器\(i\)上倒數第\(k\)個運行的任務,\(l_i\)爲機器\(i\)上運行的任務數量。注意到,一個任務的完成時間等於在該任務以前(包括自身)運行的任務處理時間之和,咱們有:
\[ \sum_j C_j=\sum_{i=1}^m\sum_{k=1}^{l_i}C_{\kappa_{ik}}=\sum_{i=1}^m\sum_{k=1}^{l_i}\sum_{x=k}^{l_i}p_{i,\kappa_{ix}}=\sum_{i=1}^m\sum_{k=1}^{l_i}kp_{i,\kappa_{ik}}. \]
其中\(p_{i,j}\)爲機器\(i\)上運行任務\(j\)須要的處理時間,實際上最後一個等號的意思是:倒數第\(k\)個任務對機器\(i\)上的全部任務完成時間和的貢獻是其處理時間的\(k\)倍(很容易理解的)。
如今咱們定義一個二分圖\(G=(V,E)\),其中\(V=A\cup B\),\(A\)包含\(n\)個頂點,對應於\(n\)個任務\(v_j\),\(B\)包含\(nm\)個頂點\(w_{ik}\),表明機器\(i\)上倒數第\(k\)個處理的任務,顯然\(i=1...m,k=1...n\)。邊集\(E\)包含全部\((v_j,w_{ik})\),爲每條邊賦予權重:\((v_j,w_{ik})\rightarrow kp_{ij}\)。下面證實在這個二分圖上尋找到的最小完美匹配對應於最優調度。
證實:首先,每個有效的調度策略都對應一個完美匹配(這是顯然的),其次,並非每一個完美匹配都對應一個有效的調度策略,由於一個任務可能被指定爲倒數第\(k\)個運行可是該機器上並無滿\(k\)個任務。但顯然這樣的匹配不是最小匹配,由於咱們能夠將\(k\)減少,以得到更小的權重。所以最小完美匹配必定對應一個有效的調度策略,且根據以前的分析,該匹配的權重和等於全部任務的完成時間總和,從而該策略是最優的。
關於這個問題的簡化版\(P||\sum C_j\),也能夠經過上面的分析看出,每一個機器上倒數第\(k\)個完成的任務\(j\)致使時間和增長了\(kp_j\),所以基本思路就是長任務儘可能晚地在機器上執行,也就是先將前\(m\)長的任務分配給各機器處理隊列的尾部,重複上述步驟。這和最短任務優先\(SPT\)算法的結果一致,所以\(SPT\)算法不只是\(1||\sum C_j\)的最優解,仍是\(P||\sum C_j\)的最優解。
第二個使用二分圖匹配來設計算法的是\(O|pmtn|C_{max}\)問題。未完待續......