1. 程式人生 > >陣列的字首和(Prefix Sum)問題及其並行演算法

陣列的字首和(Prefix Sum)問題及其並行演算法

一、問題簡介

首先,我們來看一下什麼是字首和(Prefix Sum)問題。對於一個長度為N的陣列(假設下標從1到N),那麼字首和(有時也稱累加和cumulative sum)演算法的虛擬碼是下面這樣的

for(i=2;i<=N;i++)
V[i] = V[i-1] + V[i];
也就是說,對於一個輸入的陣列,我們所得之結果是一個等長的陣列,而結果陣列中的每個元素(假設是第x個元素)都是原陣列中對應位置的前x項和。例如:


下圖所示為Prefix Sum問題的序列演算法的示意:


可見,序列版本的Prefix Sum問題的規模(size)是N-1,因為我們一共需要執行N-1次(加和)計算。而這個問題的深度(depth)也是N-1,因為

它需要N-1個時間步(time steps)來完成。可見,size對depth的比是1,這其實表示我們可以做一些並行化的考慮(並行化執行時,同一time上完成的steps,僅算一個time step)。事實上,我們確實可以把Prefix Sum問題的depth降下來,不過這要以增大其size為代價。

二、Upper/Lower 並行演算法

Upper/Lower演算法是一種基於分治法設計的用於解決Prefix Sum問題的並行化演算法。具體來說,Upper/Lower演算法會把數組裡的元素分成兩半,即lower half和high half。然後Prefix Sum會在lower half和high half

上分別遞迴地(通過分治法)來進行計算。最後再high half的所有結果要加上lower half輸出結果中的最大值即可。如下圖所示為遞迴執行的最後一層的示意。


下圖給出的是包含逐層遞迴的全部執行過程。


如果我們用來表示在長度為N的輸入上執行的用於求解Prefix Sum問題的Upper/Lower演算法,那麼我們則有如下定理:


此外,如果N不是2的若干次冪,我們則可以用下面這個上下界來給出S(N)的範圍:


由於採用了二分法,所以我們可以知道的depth等於 t = log2N,其中N=2^t。

三、Odd/Even並行演算法

另外一種用於解決Prefix Sum問題的並行化演算法就是Odd/Even演算法,記作

。這個方法和前面介紹的Upper/Lower演算法非常相像,也是基於分治法設計的。只是這回,我們在每層迭代時,是根據陣列元素下標的奇偶性來將元素分成兩組。下圖所示為一個簡單的示例:


Odd/Even演算法的執行中有個主要的步驟往復交替。首先,prefix sum的操作總是在偶數項上執行,如下圖所示:


其次,一旦偶數項上的操作執行完畢,那麼偶數上的結果就將被加到下一個(相鄰的)奇數項上,如下圖所示:

所以我們不難發現,在執行過程中,每次將輸入二分,都會使得操作的depth增加2層,一層是做相鄰兩個元素的加和,一層是將中間結果累加到相應的位置上去。當N=4時,的執行需要用到2層操作。現在考慮當N=2^t時,的depth為多少。根據之前的分析易得:


同樣地,我們還可以計算所涉及的size為(注意我們在計算時用到了等比數列的求和公式):


可見的size要比的size小很多,但同時的depth也要比的depth大很多

四、Ladner-Fischer並行演算法

最後要介紹的這種並行演算法是由Ladner和Fischer在1980年左右提出的。Ladner-Fischer演算法使得我們可以在depth和size之間進行更加精細的平衡,它在很大程度上是Upper/Lower演算法和Odd/Even演算法的結合。例如下面是當N=8時,Ladner-Fischer演算法的執行示例:

下面是當N=16時,Ladner-Fischer演算法的執行示例:


此處我們也不再對Ladner-Fischer演算法的具體細節做過多的涉及,有興趣的讀者可以參閱相關資料以瞭解更多。

Ladner-Fischer演算法的size和depth分析比較複雜,我們這裡也不詳細討論(其中用到了斐波那契數的一些性質),下表總結對比了本文中提到的幾種並行演算法的情況:


(本文完)