3.2 Paralleles Mergesort mit naivem Merge

Wenn wir kein Netzwerk bauen wollen, sondern einen allgemeinen PRAM-Algorithmus zulassen wollen, dann können wir merge einfacher implementieren.

Lemma 3.2.1 Gegeben seien zwei sortierte Arrays L und R mit je n Elementen. Mit 2n Prozessoren können wir merge(L,R) in O(logn) Zeit berechnen.

Beweis. Sei L=[x1,,xn] und R=[y1,,yn]. Wir nehmen an, dass alle Elemente verschieden sind. Wir ordnen jedem Index i{1,,n}) einen Prozessor Pi zu. Mittels binärer Suche findet Pi das eindeutige j{0,,n} mit yjxi<yj+1; in anderen Worten: den Rang ri:=rank(xi,R). Hierfür braucht er log(n+1) Schritte. Nun kann er den Rang von xi in LR berechnen:

rank(xi,LR)=rank(xi,L)+rank(xi,R)=i+j=:ri .

Nun kopiert er das Element an die passende Stelle des Ergebnis-Arrays: result[ri] := xi. Dies alles tun die Prozessoren P1,,Pn parallel in O(logn) Schritten. Parallel dazu bestimmen die Prozessoren P1,,Pn die Ränge von jedem yi in L und kopieren es an die richtige Stelle von result.

Theorem 3.2.2(Naives paralleles Mergesort). Wir können mit n Prozessoren ein Array A der Länge n in Zeit O(log2n) sortieren.

Beweis. Wir teilen A in zwei Hälften L und R von je n/2 Elementen; gleichzeitig teilen wir die Prozessoren in zwei Hälften. Wir sortieren nach gleichem Schema (also rekursiv) die jeweiligen Hälften und führen anschließend merge durch. Wenn die Teilarrays Größe 1 erreicht haben, sind wir fertig.

Da Rekursion im Zusammenhang von parallelen Algorithmen immer etwas mit Vorsicht zu genießen ist, stellen wir uns den Mergesort-Algorithmus eher als Binärbaum vor, in dem jeder innere Knoten für eine Merge-Operation zuständig ist und jedes Blatt einem Array-Element entspricht:

Besser noch stellen wir es uns als Tabelle mit n=2d Spalten und d+1 Zeilen vor:

Prozessor P12 kann anhand seines Indexes 12 und dem Zeitpunkt t=3 leicht errechnen, dass sein Element in dem zweiten von insgesamt vier Achter-Blöcken liegt; dass es sich also um ein "R" handelt und sein Element y in diesem den Rang 4 hat. Auch weiß er, dass er mit binärer Suche den Rang von y in A[1..8] bestimmen muss. Mit ein paar einfachen arithmetischen Operationen (oder Bitshifts) von t und i kann er also bestimmen, was zu tun ist.

Laufzeitanalyse. Wir nehmen der Einfachheit halber an, dass n=2d eine Zweierpotenz ist. Im Schritt t für 1td werden zwei sortierte Arrays mit je 2t1 Elementen mittels merge zu einem Array von 2t Elementen verschmolzen; dafür brauchen wir nach Lemma 3.2.1 O(log2t)=O(t) Schritte. Insgesamt brauchen wir also

O(1+2++d)=O(d2)

Schritte. Die Zeitkomplexität ist somit O(log2n).