6.2 Sortieren
Die Eingabe besteht aus einer Menge von Items aus einem
geordneten Universum. Das Ziel ist es, diese Menge zu sortieren.
Was heißt das im MPC-Kontext? Wir betrachten die Menge
als sortiert, wenn jeder Item durch einen Item
ersetzt worden ist, wobei ist.
Dann hätten wir in ein Array im Sinne von
Übungsaufgabe 6.1.2 umgewandelt
und somit in jedem vernünftigen Sinne sortiert.
In Worten: am Ende des Algorithmus soll jedes Element seinen Rang kennen.
Unser Algorithmus ist eine MPC-Version von Quicksort. Die Idee ist es,
nicht ein Pivot, sondern eine ganze Menge von Pivots zu wählen.
Die Pivots zerteilen die Menge in mehrere Teilintervalle oder
Unterprobleme.
Über einen Baum ähnlich wie in Theorem 6.1.2
senden wir dann alle Pivots zu einer zentralen Maschine, welche sie
lokal sortiert (was als ein Schritt zählt) und als sortierte Menge
wieder an alle Maschinen aussendet. Jede Maschine bestimmt dann (lokal, also in einem
Schritt) für jedes ihrer Items, zu welchem Unterproblem es gehört.
Nun lösen wir rekursiv jedes Unterproblem.
Eine Schwierigkeit besteht darin, dass wir die Maschinen irgendwie den Unterproblemen
zuordnen müssen; also (1) bestimmen, an welchem Unterproblem die Maschine arbeiten soll
und
(2) erreichen müssen, dass alle Items, die zu Unterproblem gehören, auf den
zuständigen Maschinen landen. Problem (1) wird einen weiteren "Baum-Broadcast" erfordern;
Problem (2) lösen wir mit Randomisierung.
MPC-Quicksort
Als erstes wollen wir eine Menge von zufällig Pivots wählen,
und zwar in einem Schritt, also ohne Kommunikation. Dies geht näherungsweise und
mit Randomisierung: wenn wir jeden Item mit Wahrscheinlich markieren, dann
gilt für die Menge von markierten Items:
Wir wollen erreichen: die Menge der Pivots soll auf keinen
Fall mehr als Elemente enthalten, und der Faktor dient
als Sicherheitsabstand. Wir wählen also .
Behauptung 6.2.1 Sei .
Wenn wir jeden Item mit Wahrscheinlichkeit markieren, dann
haben wir mit großer Wahrscheinlichkeit höchstens Items markiert.
Warum die Behauptung gilt und was überhaupt "mit großer Wahrscheinlichkeit" heißt, das
schauen wir uns weiter unten genauer an. Im Moment gehen wir einfach davon
aus, dass gilt. Die Pivots liegen über alle
Maschinen verteilt. Wir wollen sie auf einer bestimmte Maschine, zum Beispiel
Maschine 1, sammeln.
Übungsaufgabe 6.2.1
Zeigen Sie, wie man in Runden (merke: )
erreichen kann, dass alle Items auf Maschine liegen.
Gehen Sie hierbei davon aus, dass jede Maschine anfangs noch mindestens freien
Speicherplatz hat.
Maschine hält nun (neben ihren "normalen" Eingabe-Items) die Menge .
Sie sortiert sie lokal, bestimmt somit für jedes seinen Rang
und bildet den "indizierten" Item . Wir bezeichnen
diese indizierte Menge als . Dann
sendet Maschine die Menge an alle Maschinen; dies
geht wiederum in Runden, analog zu
Übungsaufgabe 6.2.1.
Alle Maschinen kennen nun also die Pivots in
aufsteigender Reihenfolge (mit .
Dies unterteilt in Teilintervalle / Unterprobleme.
Formal: das Teilproblem ( für ) ist
die Menge
Jede Maschine bestimmt nun für jeden ihrer Items und weiß nun, zu welchem
Teilproblem
gehört; ganz konkret ersetzt sie durch .
Dies geht lokal, also in einer Runde.
Jede Maschine kennt nun die Anzahl ihrer Items, die zu Teilproblem
gehören. Wir wollen nun
bestimmen, also die Größe des Teilproblems .
Übungsaufgabe 6.2.2
Zeigen Sie, wie wir in Runden erreichen können, dass jede Maschine
alle Zahlen kennt.
Wir wollen nun die Maschinen den Unterproblemen zuteilen und
dann auf die zuständigen Maschinen aufteilen. Hierfür
brauchen wir mindestens Maschinen. Um etwas "Sicherheitsabstand" zu haben,
setzen wir . Jede Maschine kennt die Zahlen und weiß somit,
welche Maschinen für Teilproblem zuständig sind: mit
sind das die Maschinen mit Index in
Beachten Sie, dass die Berechnung der Präfixsummen kein
Präfixsummenproblem im MPC-Sinne darstellt, weil es lokal ausgeführt werden kann: jede
Maschine kennt alle Zahlen . Wir müssen nun alle Items,
die zum Teilproblem gehöhren, auf die Maschinen mit Index in aufteilen.
Damit dies in einer Runde gelingt, verwenden wir wiederum Randomisierung:
Maschine schickt jeden ihrer Items an eine
Maschine , wobei sie zufällig aus wählt.
Wieviele Items empfängt eine Maschine in dieser Runde? Die Maschinen
in Menge empfangen insgesamt Items; da die Items zufällig veretilt
werden, erhält Maschine im Erwartungswert viele Items.
Behauptung 6.2.2 Mit hoher Wahrscheinlichkeit
gibt es keine Maschine, die in diesem Schritt mehr als Items empfängt.
Wenn bisher kein "Unfall" geschehen ist (also keines der schlimmen Ereignisse
von kleiner Wahrscheinlichkeit eingetreten ist), dann hält nun
jede Maschine eine Menge von Items, die alle zu einem Teilproblem gehören,
und jede Maschine weiß auch, an welchem Teilproblem sie arbeiten soll und welche
anderen mit ihr. Wir können nun also rekursiv auf jedem Teilproblem weiterarbeiten.
Laufzeitanalyse
Die gerade beschriebene Phase von MPC-Quicksort benötigt Runden.
Es bleibt zu untersuchen, wie viele Phasen der rekursive Aufruf erzeugt.
Hierzu untersuchen wir, wie groß die Teilprobleme werden.
Da wir in Teilprobleme unterteilen (mit die Anzahl
der Pivots), sollte jedes Teilproblem "im Durchschnitt" Elemente enthalten.
Die Anzahl der Pivots ist wiederum im Erwartungswert , so
dass
wir wohl bei ungefährt erwarten.
Warnung. Es ist nicht korrekt, Erwartungswerte zu dividieren, also
zu rechnen. Dennoch ist es legitim, quasi als Bierdeckelrechnung mal zu schauen,
was dabei rauskommt, um zu sehen, ob man auf dem richtigen Weg ist.
Wir "erwarten" also, dass die Größe eines Teilproblems bei ungefähr liegt.
Nach dieser Rechnung würde in jedem rekursiven Level die Anzahl der Elemente
ungefähr durch geteilt. Nach
Rekursionsleveln wären wir fertig;
sogar noch etwas früher: sobald ein Teilproblem kleiner als ist,
können wir es auf einer Maschine sortieren.
Behauptung 6.2.3
Mit hoher Wahrscheinlichkeit gilt für jedes .
Wahrscheinlichkeitsrechnung: Beweise der Behauptungen
Schneller sortieren in Runden
Ich beschreibe nun einen schnelleren Sortieralgorithmus, der auch auf Quicksort
beruht. Er stammt aus dem Paper Sorting, Searching, and Simulation in the MapReduce
Framework von Michael T. Goodrich, Nodari Sitchinava und Qin Zhang.