HEINZ NIXDORF INSTITUT Fakultät für Elektrotechnik ... Pottmeyer Memory Limitations in Artificial...

226
HEINZ NIXDORF INSTITUT Fakultät für Elektrotechnik, Informatik und Mathematik Seminar »Verteilte Algorithmen« Wintersemester 2006/2007 Veranstalter Prof. Dr. Friedhelm Meyer auf der Heide Dr. Matthias Fischer Fachgruppe: Algorithmen und Komplexität

Transcript of HEINZ NIXDORF INSTITUT Fakultät für Elektrotechnik ... Pottmeyer Memory Limitations in Artificial...

Page 1: HEINZ NIXDORF INSTITUT Fakultät für Elektrotechnik ... Pottmeyer Memory Limitations in Artificial Intelligence ... Vitter hat gezeigt, dass viele in diesem Modell effiziente Entwicklungen

HEINZ NIXDORF INSTITUT Fakultät für Elektrotechnik, Informatik und Mathematik

Seminar »Verteilte Algorithmen«

Wintersemester 2006/2007 Veranstalter Prof. Dr. Friedhelm Meyer auf der Heide Dr. Matthias Fischer Fachgruppe: Algorithmen und Komplexität

Page 2: HEINZ NIXDORF INSTITUT Fakultät für Elektrotechnik ... Pottmeyer Memory Limitations in Artificial Intelligence ... Vitter hat gezeigt, dass viele in diesem Modell effiziente Entwicklungen
Page 3: HEINZ NIXDORF INSTITUT Fakultät für Elektrotechnik ... Pottmeyer Memory Limitations in Artificial Intelligence ... Vitter hat gezeigt, dass viele in diesem Modell effiziente Entwicklungen

Inhaltsverzeichnis Jonas Schulte Grundlegende Datenstrukturen für Externe Speicherung ........... 1 Oliver Buschjost A Survey of Techniques for Designing I/O-Efficient Algorithms ......................................................................................... 53 Christoph Horstmann I/O effiziente Algorithmen auf dünnen Graphen ......................... 65 Raphael Golombek Algorithmische Geometrie im externen Speicher ....................... 79 André Braun Volltextindizes im externen Speicher ........................................... 97 Stefan Frank Algorithmen für Hardware Caches und TLBs ........................... 109 Tobias Berghoff Cacheoptimierungen für Numerische Algorithmen .................. 121 Felix Pottmeyer Memory Limitations in Artificial Intelligence .............................. 137 Elmar Köhler Algorithmen für Speichernetzwerke ............................................ 151 David Brucholder An Overview of File System Architectures - Multiple Disk Prefetching Strategies for External Merging ............................. 167 Michael Blank Exploitation of the Memory Hierarchy in Relational DBMSs . 179 Martin Klose Parallel Bridging Models und ihre Emulation ........................... 193 Stefan Finke Fallstudie: Speicherbewußtes, paralleles Sortieren ................ 205

Page 4: HEINZ NIXDORF INSTITUT Fakultät für Elektrotechnik ... Pottmeyer Memory Limitations in Artificial Intelligence ... Vitter hat gezeigt, dass viele in diesem Modell effiziente Entwicklungen
Page 5: HEINZ NIXDORF INSTITUT Fakultät für Elektrotechnik ... Pottmeyer Memory Limitations in Artificial Intelligence ... Vitter hat gezeigt, dass viele in diesem Modell effiziente Entwicklungen

Grundlegende Datenstrukturen für Externe Speicherung

Jonas Schulte

1 Einleitung

Eine Vielzahl unterschiedlicher Applikationen, wie zum Beispiel Data-Warehouse An-wendungen oder umfangreiche Simulationen, verwenden oder produzieren enorme Da-tenmengen. Die fortschrittliche Weltraumforschung der NASA ist als weiteres Beispielzu nennen, die es ermöglicht, detaillierte Satellitenbilder der Erde aufzunehmen. Je mehrDetails ein Satellitenbild beinhaltet, desto mehr Speicherbedarf benötigt es. So liegt derinsgesamte Speicherbedarf der NASA für die Satellitenbilder zur Zeit bei einigen Peta-bytes. Eine Speicherung dieser Daten im Speicher eines Prozessors ist nicht realisierbar,die Nutzung von Arbeitsspeicher würde bei aktuellen Preisen pro Petabyte etwa 1 Milli-arde Euro kosten.1 Eine deutlich preiswertere Lösung mit etwa 2,85 Millionen Euro proPetabyte ist die Nutzung von Festplattenspeicher.2 Da der insgesamte Speicherbedarffür die Satellitenbilder enorm hoch ist und zudem verschiedene Applikationen die Datenverwenden, ist es gegenbenenfalls erforderlich, zusätzliche Speichermedien zu verwen-den, die sich nicht im ausführenden Rechner befinden (in einem solchen Fall erfolgt derDatenzugriff über ein Intranet oder das Internet). Dieser Aspekt verdeutlicht, dass Da-tenzugriffe auf externe Speichermedien in einer höhere Latenzeit resultieren, welche zumEinen von der Bandbreite zwischen Speichermedium und Prozesssor und zum Anderenauch von der Datenbereitstellungszeit des Mediums abhängt. Wird eine Festplatte imgleichen Rechner genutzt, so kann die Latenzzeit verursacht durch die Übertragung derDaten vernachlässigt werden, da mehrere aufeinanderfolgende Bits gleichzeitig übertra-gen werden. Die korrekte Positionierung des Lese-/Schreibkopfes für den Datenzugriff istdeutlich zeitintensiver. Folglich ist das Ziel der Datenorganisation und der Algorithmenauf externen Speichermedien die Minimierung der Zugriffszeit auf die benötigten Daten,und damit der Anzahl der erforderlichen Positionierungen des Lese-/Schreibkopfes. DieAbbildung 1 verdeutlicht, dass eine „geschickte“ Verteilung der benötigten Daten we-niger Positionierungsvorgänge erfordert als eine willkürliche Verteilung. Folglich ist dieAnzahl der erforderlichen Repositionierungen ein erhebliches Kriterium für die Effizienzvon Datenstrukturen und Algorithmen.

1dabei wird angenommen, dass 1GB Arbeitsspeicher etwa 100 Euro kosten2unter der Annahme, dass 350 GB etwa 100 Euro kosten

1

Page 6: HEINZ NIXDORF INSTITUT Fakultät für Elektrotechnik ... Pottmeyer Memory Limitations in Artificial Intelligence ... Vitter hat gezeigt, dass viele in diesem Modell effiziente Entwicklungen

Abbildung 1: Nicht aufwendige und aufwendige Repositionierung für den Datenzugriff

Datenstrukturen, die im internen Speicher einen effizienten Datenzugriff ermöglichen,sind in den meisten Fällen im externen Speicher nicht leistungsstark. Diese Seminararbeitzeigt für verschiedene Datenstrukturen (Stack, Queue, B-Bäume und Hashtabellen) wiesie effizient in externen Speicher realisiert werden können. Das Schlüsselkonzept ist dabeioftmals eine Datenspeicherung ähnlicher Daten in physikalischer Nähe.

Diese Seminararbeit stellt zunächst in Kapitel 2 die Grundlagen der Speicherkomponen-ten sowie das externe Speichermodell vor, welches bei den entwickelten Datenstrukturenzu Grunde gelegt wurde. Die optimalen Grenzen für Datenzugriffe beim Lesen oderSchreiben werden ebenfalls präsentiert. Anschließend werden in Kapitel 3 die Daten-strukturen externer Stack und externe Queue im Vergleich zu ihren Realisierungen iminternen Speicher vorgestellt. Das Kapitel verdeutlicht, dass bereits für solche elemen-taren Datenstrukturen die im Hauptspeicher performante Realisierung sich im externenSpeicher als außerordentlich ineffizient erweist.Die Implementierung von Wörterbüchern kann mit Hilfe von Bäumen oder Hashtabellenerfolgen. Folglich behandeln Kapitel 4 sowie 5 diese beiden Datenstrukturen für dieRealisierung im externen Speicher. Abschließend fasst Kapitel 6 die Ergebnisse dieserSeminararbeit zusammen.

2

Page 7: HEINZ NIXDORF INSTITUT Fakultät für Elektrotechnik ... Pottmeyer Memory Limitations in Artificial Intelligence ... Vitter hat gezeigt, dass viele in diesem Modell effiziente Entwicklungen

2 Grundlagen

Dieses Kapitel stellt die Grundlagen für die Seminararbeit vor. Dabei wird zunächstdie Speicherhierarchie sowie der aktuelle Stand der Technik von Speicherkomponetenbeschrieben (siehe Abschnitt 2.1). Die entwickelten Datenstrukturen basieren auf einemin der Theorie häufig verwendeten externen Speichermodell, welches in Abschnitt 2.2präsentiert wird. Zum Leistungsvergleich der entwickelten Datenstrukturen ist es not-wendig, die optimalen Grenzen zu kennen. Abschnitt 2.3 gibt dazu einen Überblick überdie optimalen Werte, das heißt die unteren Grenzen.Soweit nicht anders verwiesen, basieren die Informationen auf [MSS03, Kapitel 1-2].

2.1 Speicherkomponenten

In der Einleitung wurden vor allem der Hauptspeicher und der Festplattenspeicher fo-kussiert. Jedoch werden die Speicherkomponenten gemäß der Speicherhierarchie (sieheAbbildung 2) unterschieden in Register, Cache, Hauptspeicher sowie Festplattenspeicher.Je schneller der Datenzugriff desto teurer ist der Speicherplatz. Die Notwendigkeit ei-ner Speicherhierachie folgt somit daraus, dass Daten preiswert gespeichert werden sollenaber auch ein schneller Zugriff erforderlich ist.Der Prozessor besitzt verschiedene Caches für Befehle und Daten. Die meisten aktuellenProzessoren verfügen über einen L1 und L2 Cache, einige sind zudem mit einem L3Cache ausgestattet. Die Größe der Caches sind unterschiedlich für verschiedene Prozes-sormodelle, jedoch wächst die Größe von L1 über L2 zu L3 Cache wie sich im Gegenzugdie Latenzzeit erhöht. In den meisten Fällen sind die L1 Caches nur wenige Kilobytegroß, ermöglichen jedoch ein oder zwei Zugriffe pro CPU-Takt. Ein Datenzugriff auf denL1 Cache verursacht eine Latenzzeit von einigen Takten, da mehrere Schritte der befehls-durchführenden Pipelines durchschritten werden müssen. Der L2 Cache ist bei heutigenProzessoren 2 oder 4 MB groß und hat eine Zugangslatenz von etwa 10 Takten. L3 Ca-ches befinden sich nicht mehr auf dem gleichen Chip wie der Prozessor und bestehen ausschnellen statischen RAM-Zellen. Der L3 Cache kann im Prinzip sehr groß sein. Oftmalsist ein großer L3 Cache aus Kostengründen jedoch nicht effizient. Der Arbeitsspeicher,auch Hauptspeicher genannt, besteht aus günstigen dynamischen RAM Zellen.

3

Page 8: HEINZ NIXDORF INSTITUT Fakultät für Elektrotechnik ... Pottmeyer Memory Limitations in Artificial Intelligence ... Vitter hat gezeigt, dass viele in diesem Modell effiziente Entwicklungen

Abbildung 2: Speicherhierarchie

Es ist nicht notwendig, dass Programmierer den detailierten Speicheraufbau kennen müs-sen. Die Hardware teilt den Hauptspeicher in Blöcke und weist eine Teilmenge dieserautomatisch dem L3 Cache zu. Eine Teilmenge der Daten im L3 Cache werden demL2 Cache übermittelt, für den L1 Cache gilt dieses analog. Als Hintergrundspeicherungwerden Festplatten angesehen, da sie sehr kostengünstige und permanente Speicherungermöglichen. Die Schnelligkeit von Festplattenzugriffen hat sich in den letzten Jahrenzunehmend erhöht, so dass sich die Latenzzeit bei Speicherung auf Festplatten fortlau-fend reduziert. Jedoch ist ein Festplattenzugriff immer noch 1017 mal langsamer als einRegisterzugriff [MSS03].Die beschriebenen Speicherkomponenten sind in der Speicherhierarchie (siehe Abbil-dung 2) eingeordnet. Die Abbildung zeigt, dass mit höherer Latenzzeit für den Da-tenzugriff der Preis pro Byte sinkt. Das Ausmaß des Preisunterschiedes wurde in derEinleitung anhand des NASA Beispiels verdeutlicht: 1 Millarden Euro pro Petabyte fürSpeicherung im Arbeitsspeicher stehen im Gegensatz zu 2,85 Millionen Euro bei Fest-plattennutzung. Es sei angemerkt, dass trotz der höheren Latenzzeit bei Nutzung vonFestplattenkapazität dieser Speicherplatz oftmals als SWAP-Bereich verwendet wird,um den virtuellen Speicher eines Rechners zu vergrößern. Dies zeigt, dass die Band-breite zwischen Arbeitsspeicher und Hauptspeicher eine genügende Effizienz bietet unddie Datenorganisation auf dem externen Medium ausschlaggebend für die Performanceist. Wird Festplattenkapazität als SWAP-Bereich verwendet, erfolgt das Mapping vonvirtuellen Speicheradressen mittels Translation Lookaside Buffer (TLB) [MSS03, Kapi-

4

Page 9: HEINZ NIXDORF INSTITUT Fakultät für Elektrotechnik ... Pottmeyer Memory Limitations in Artificial Intelligence ... Vitter hat gezeigt, dass viele in diesem Modell effiziente Entwicklungen

tel 8] in physikalische Speicheradressen. Abschnitt 3.4.1 geht auf die Realisierung desvirtuellen Arbeitsspeichers mit Hilfe von Wörterbüchern ein.

2.2 Externes Speichermodell

Der vorige Abschnitt verdeutlicht, dass die Speicherhierarchie sehr komplex ist und vie-le Abstufungen besitzt. Zudem verfügen Hardware Caches über verschiedene komplexeErsetzungsstrategien [FHL+01] und Festplatten über positionsabhängige Zugriffsverzö-gerungen. Für die Entwicklung von Datenstrukturen können solche Eigenschaften nurschwer in Betracht genommen werden, da schwierige Modelle in komplexen Realisierun-gen und Analysen von Datenstrukturen resultieren. Ein Vergleich verschiedener Daten-strukturen, welche auf unterschiedlichen Modellen basieren, ist bei komplexen Modellennicht möglich, da eine Vielzahl von Parametern die Effizienz und Implementierung be-einflussen können. Aus diesen Gründen wurden einfache Modelle entwickelt, so dass beider Entwicklung von Datenstrukturen nicht viele verschiedene Parameter berücksichtigtwerden müssen. Es gilt zu beachten, dass das zu Grunde gelegte Modell nicht zu einfachsein darf, da sich die im Modell effizienten Datenstrukturen auch in der Praxis bewährensollen. Die Entwicklungen dieser Seminararbeit basieren auf dem am weitesten verbreite-ten Modell (siehe Abbildung 3). Es wird das externe Speichermodell genannt und ist einekleine Erweiterung der Random Access Machine (RAM)/ von Neumann Model [vN45].Trotz seiner starken Abstraktion der Speicherhierarchie auf 2 Ebenen, wird dieses Mo-dell für die theoretische Analyse und Entwicklung von Algorithmen und Datenstrukturenhäufig verwendet (es ist in mehr als in 100 veröffentlichten wissenschaftlichen Arbeitenzu finden). Vitter hat gezeigt, dass viele in diesem Modell effiziente Entwicklungen eben-falls in der Praxis performant waren [Vit01]. Folglich ist die starke Abstraktion keineschwerwiegende Einschränkung der realen Umgebung.

Definition 2.1.

Die in der Seminararbeit verwendete Notation entspricht der von Aggarwal, Vitter undShriver Eingeführten [AV88, VS94]:

N Anzahl der Datenelemente

M Anzahl der Datenelemente, die im internen Speicher gehalten werden können

5

Page 10: HEINZ NIXDORF INSTITUT Fakultät für Elektrotechnik ... Pottmeyer Memory Limitations in Artificial Intelligence ... Vitter hat gezeigt, dass viele in diesem Modell effiziente Entwicklungen

B Anzahl der aufeinanderfolgende Datenelemente, die mit einer Ein-/ oder Ausgabe-operation (I/O) zwischen internem und externem Speicher ausgetauscht werdenkönnen. Dies entspricht zudem der Kapazität eines externen Speicherblocks, ge-messen in Datenelementen

Abbildung 3 zeigt eine grafische Darstellung des externen Speichermodells. Für diePerformanceanalyse von externen Speicheralgorithmen wird die Anzahl der I/O-Operationen gemessen, da die Bandbreite nicht der Flaschenhals der Auslagerung ist.Des Weiteren wird angenommen, dass der Datenzugriff im internen Speicher sowie arith-metische Operationen konstante Zeit benötigen.

Abbildung 3: Externes Speichermodell [MSS03, S.6]

Das Modell besagt, dass mit einer I/O-Operation B Datenelemente zwischen internemund externem Speicher ausgetauscht werden können. Jedoch kann diese Aussage trü-gerisch sein, da der externe Speicher nicht zwanghaft mit einer Festplatte gleichgesetztwerden soll. Das externe Speichermodell hat keine Restriktionen, welche Level der Spei-cherhierarchie mit dem Modell abgebildet werden. Folglich könnte ebenfalls der L2 Cachemit dem schnellen internen Speicher und der Arbeitsspeicher mit dem großen Speicherabgebildet werden. Ungenauigkeiten des Modells sind meistens mit Hilfe von konstantenFaktoren anzupassen. Ebenso sei angemerkt, dass Festplatten auch über lokale Cachesverfügen. Jedoch sind diese so klein, dass sie für die meisten Algorithmen keine Effizi-enzsteigerung bedeuten.Die Zugriffszeit auf eine Festplatte besteht zum einen aus der Latenzzeit den Lese-/Schreibkopf an die korrekte Position zu setzen und zum anderen aus eine Übermitt-lungszeit, welche proportional zur Datenmenge ist. Die Latenzzeit für die Positionie-rung des Lese-/Schreibkopfes hängt von der aktuellen Position sowie von der Position

6

Page 11: HEINZ NIXDORF INSTITUT Fakultät für Elektrotechnik ... Pottmeyer Memory Limitations in Artificial Intelligence ... Vitter hat gezeigt, dass viele in diesem Modell effiziente Entwicklungen

des Speicherblocks auf der Festplatte ab. Wie zuvor erwähnt, ist die Übermittlungszeitdurch einen ausreichend hohe Bandbreite für mehrere Elemente performant und zudemgleich für gleiche Datenmengen. Damit ist die Übermittlungszeit kein Effizienzkriteriumbei der Analyse von externen Datenstrukturen.

Die in dieser Seminararbeit vorgestellten Datenstrukturen basieren nicht nur auf demexternen Speichermodell. Es wird zudem folgende Bedingung angenommen (verdeutlichtin den Abbildungen 4 und 5):

Annahme 2.1.

Beim Auslagern eines Speicherblocks beliebiger Größe können die Daten im externenSpeicher so abgelegt werden, dass der Zugriff auf diesen Speicherblock nur eine I/O-Operation benötigt.

Abbildung 4: Diese Situation darf beider Auslagerung einesSpeicherblocks nichtexistieren.

Abbildung 5: Bei der Auslagerung ei-nes Speicherblocks ist die-se Situation gefordert.

Annahme 2.2.

Bei der Analyse der Datenstrukturen in dieser Seminararbeit wird angenommen, dass proI/O-Operation B Datenelemente aus bzw. in einen Speicherblock gelesen bzw. geschriebenwerden können. Der Flaschenhals der Effizienz ist somit die Anzahl von Positionierun-gen, um alle erforderlichen Daten für den Datenaustausch bereitzustellen, folglich solldie Anzahl an I/O-Operationen minimiert werden.Zur Vereinfachung der Notation wird zudem angenommen, dass der Logarithmus einerZahl mindestens Eins ergibt, d.h. loga b sollte gelesen werden als max(loga b, 1).

7

Page 12: HEINZ NIXDORF INSTITUT Fakultät für Elektrotechnik ... Pottmeyer Memory Limitations in Artificial Intelligence ... Vitter hat gezeigt, dass viele in diesem Modell effiziente Entwicklungen

2.3 Untere Leistungsgrenzen

Viele Algorithmen für externe Speicher können aus den drei Grundoperationen Scan-nen, Sortieren und Suchen gebildet werden. [MSS03, Kapitel 1] stellt die in diesemAbschnitt enthaltenen untere Grenzen vor. Dabei gilt es Folgendes zu beachten: Fürdie Speicherung von N Datenelementen und einer Speicherblockgröße von maximal B

Datenelementen ist dN/Be die minimale Anzahl von benötigten Speicherblöcken für dieHaltung von N Datenelementen. Für eine detaillierte Analyse von unteren Grenzen wirdauf Lars Arge and Peter Bro Miltersen [AM99] verwiesen.

Scannen bedeutet, dass die enthaltenen Daten der Datenstruktur einmal in der Reihen-folge durchlaufen werden, in welcher sie abgespeichert sind. Folglich basiert die untereGrenze für das Scannen auf der minimalen Anzahl von Speicherblöcken um N Daten-elemente abzulegen:

scan(N) = Θ

(N

B

)I/Os (1)

Permutation und Sortieren ist oftmals erforderlich, um die Daten für das Scannenin eine nützliche Reihenfolge zu bringen. Eine Permutation erfolgt, wenn die neue Posi-tion des Elementes bereits bekannt ist. Ist die neue Position nur implizit anhand einerOrdnung, wie zum Beispiel „<“, bestimmt, so entspricht dies der Sortierung von Datenbezüglich „< “. [MSS03, Kapitel 3] zeigt den optimalen Aufwand für das Sortieren:

sort(N) = Θ

(N

BlogM

B

N

B

)I/Os (2)

Das Permutieren besitzt eine ähnliche untere Schranke.

Suchen in einer Datenstruktur mit N Elementen im externen Speicher, deren Zugriffüber Zeiger erfolgt, wird im Folgenden analysiert. Die Zeigeradressierung bedeutet, dassauf einen Block i nur zugegriffen werden darf, wenn seine Adresse wirklich irgendwogespeichert ist. Es ist notwendig die Anzahl der unterschiedlichen Blöcke Ct zu zählen,

8

Page 13: HEINZ NIXDORF INSTITUT Fakultät für Elektrotechnik ... Pottmeyer Memory Limitations in Artificial Intelligence ... Vitter hat gezeigt, dass viele in diesem Modell effiziente Entwicklungen

auf die nach t I/O-Operationen zugegriffen werden darf. Um auf alle Elemente zugrei-fen zu können, wird diese Anzahl gemäß der minimalen Blockanzahl den Wert N/B

übersteigen.Bei der Initiierung sei der schnelle interne Speicher vollständig mit Zeigern ausgefüllt,folglich ist C0 = M . Das Lesen jedes zusätzlichen Blockes erhöht die Anzahl um B

Möglichkeiten, so dass Ct = MBt gilt. Unter Betrachtung der minimalen Blockanzahlkann Ct ≥ N/B gelöst werden, welches zu der Ungleichung N ≥ logB

NMB

führt. Da einzusätzlicher Zugriff notwending ist, um ein Element zu erhalten, ergibt sich eine untereGrenze von logB

NM

I/Os um N Elemente zu betrachten. Die minimale Zugriffszeit füreine Suche in N Elementen ist somit

search(N) = Ω

(logB

N

M

)I/Os (3)

Die Effizienz der Datenstrukturen dieser Seminararbeit wird in den meisten Fällen mitHilfe der amortisierten Laufzeitanalyse bestimmt:

Definition 2.2.

Die amortisierte Laufzeitanalyse wird in der theoretischen Informatik verwendet, um diedurschnittliche Zeit von einer Folge von Operationen zu bestimmen [RL90, Kapitel 18].Die amortisierte Laufzeit kann aufweisen, dass die durschnittlichen Kosten einer Opera-tion gering sind, auch wenn eine einzelne Operation teuer sein kann. Sie unterscheidetsich von der durchschnittlichen Laufzeitanalyse (average case), da in der amortisiertenLaufzeitanalyse der durschnittliche Aufwand einer Operation im worst case betrachtetwird.

9

Page 14: HEINZ NIXDORF INSTITUT Fakultät für Elektrotechnik ... Pottmeyer Memory Limitations in Artificial Intelligence ... Vitter hat gezeigt, dass viele in diesem Modell effiziente Entwicklungen

3 Elementare Datenstrukturen

Effiziente Realisierungen der elementaren Datenstrukturen Stack (Abschnitt 3.1), Queue(siehe Abschnitt 3.2) und verkettete Liste (Abschnitt 3.3) für die Verwendung im ex-ternen Speicher werden in diesem Kapitel vorgestellt. Dabei werden die Unterschiedezu den Implementierungen im internen Speicher und ihre ineffiziente Nutzung im ex-ternen Speicher herausgestellt. Zudem werden in Abschnitt 3.4 das Konzept sowie einAnwendungsbeispiel von Wörterbüchern vorgestellt. Die Implementierung eines Wörter-buches kann mit Hilfe von B-Bäumen oder Hashtabellen realisiert werden, welche in denKapiteln 4 und 5 behandelt werden.

3.1 Stack

Der Stack verwaltet eine dynamische Menge von Elementen und unterstützt die Opera-tionen des Hinzufügens/Schreibens und des Auslesens, welches ein Löschen beinhaltet.Das Lesen (Löschen) erfolgt nach dem LIFO-Prinzip (Last In First Out). Bei einer festenmaximalen Datenanzahl N kann als effiziente Implementierung für den internen Speicherder Stack als Array implementiert werden. Wird diese Realisierung ebenfalls im exter-nen Speicher verwendet, so kann im worst case eine Stack-Operation eine I/O-Operationkosten: Beim abwechselnden Schreiben und Lesen kann nämlich nicht ausgenutzt wer-den, dass eine I/O-Operation B Elemente schreiben oder lesen kann. Das Ausnutzen derBandbreite von B Elementen durch Integration der oft verwendeten Technik des Buffersführt zu einer deutlichen Leistungssteigerung.Der externe Stack wird mit Hilfe eines Buffers realisiert, der ein Array im internen Spei-cher zur Aufnahme von 2B Elementen entspricht. Dieser Buffer beinhaltet die k zuletztim Stack eingefügten Elemente, wobei k ≤ 2B gelten muss. Das Auslesen/Löschen einesElementes kann somit direkt das entsprechende Element aus dem Buffer im internenSpeicher lesen, außer wenn der Buffer leer ist. Ist der Buffer nicht leer, wird folglichkeine I/O-Operation für das Löschen benötigt. Ist der Buffer leer, werden B Elementeaus dem externen Speicher ausgelesen und in den Buffer gelesen. Folglich kostet dasAuslesen von mindestens B Elementen eine I/O-Operation. Mit einer I/O-Operationenkönnen gegebenenfalls mehr als B Elemente gelesen werden, wenn zwischen den Lösch-operationen weitere Elemente eingefügt werden. Das Einfügen von Elementen erfolgt

10

Page 15: HEINZ NIXDORF INSTITUT Fakultät für Elektrotechnik ... Pottmeyer Memory Limitations in Artificial Intelligence ... Vitter hat gezeigt, dass viele in diesem Modell effiziente Entwicklungen

Abbildung 6: Konzept des externen Stacks

direkt im internen Speicher. Ist also der Buffer vor dem Schreiben nicht mit 2B Ele-menten vollständig belegt, so wird keine I/O-Operation benötigt, da lediglich auf deninternen Speicher zugegriffen wird. Ist der Buffer vollständig belegt und ein weiteres Ele-ment soll eingefügt werden, so müssen Elemente in den externen Speicher ausgelagertwerden. Die Auslagerung nutzt die Bandbreite zum externen Speicher aus, und es wer-den B Elemente gleichzeitig aus dem Buffer in den externen Speicher transferiert. Somitkönnen mit einer I/O-Operation mindestens B Elemente in den Stack gelesen werden.Die Mindestanzahl resultiert aus der gleichen Argumentation wie beim Auslesen.Abbildung 6 verdeutlicht die Nutzung des Buffers und die Auslagerung der Daten imexternen Speicher.

Laufzeitanalyse 3.1.

Im worst case kosten B Einfügeoperationen (oder B Löschoperationen) eine I/O-Operation. Damit hat eine Einfüge- oder Ausleseoperation die amortisierte Laufzeit von1B

I/O-Operationen.

Da nicht mehr als B Elemente mit einer I/O-Operation gelesen oder geschrieben werdenkönnen, entspricht diese Laufzeit der optimalen Effizienz. Es sei angemerkt, dass vieleDatenstrukturen für externe Speicher bei der Übermittlung von B Elementen darauf ab-zielen, O( 1

B) I/O-Operationen zu erreichen. Die Optimalität der gewählten Buffergröße

2B wird in Abschnitt 3.1.1 untersucht.

11

Page 16: HEINZ NIXDORF INSTITUT Fakultät für Elektrotechnik ... Pottmeyer Memory Limitations in Artificial Intelligence ... Vitter hat gezeigt, dass viele in diesem Modell effiziente Entwicklungen

Eine alternative Beschreibung der Vorgehensweise des externen Stacks ist, dass ein StackSpeicherblöcke wie Datenelemente behandelt. Schließlich werden beim Aus- oder Einle-sen immer B Elemente zwischen internen und externen Speicher verschoben. Der externeSpeicher besitzt folglich eine „Makroskropische Sicht“ auf die Daten, wohingegen der in-terne Speicher eine „Mikroskopische Sicht“ hat.

3.1.1 Wahl der Buffergröße

Der externe Stack verwendet einen Buffer der Größe 2B und erreicht eine amortisierteLaufzeit von 1

BI/O-Operationen. Diese Effizienz ist optimal und kann nicht verbessert

werden, jedoch soll dieser Abschnitt verdeutlichen, warum eine größere Buffergröße vonxB (mit x > 2) oder eine kleinere Buffergröße von B keine bessere Performanz ermög-licht.Eine größere Buffergröße ruft keinen Leistungszuwachs hervor, da maximal B Elementezwischen internen und externem Speicher ausgestauscht werden können. Folglich ist einebessere amortisierte Laufzeit nicht erreichbar und ein größerer Buffer überflüssig.

Abbildung 7: Worst Case bei Buffergröße B

Habe der Buffer eine Größe von B, dann tritt der worst case bei folgender Reihenfolge derauszuführenden Operationen auf: 1x Schreiben – 2x Lesen – 2 x Schreiben – . . . (sieheAbbildung 7). Es ist zu erkennen, dass eine I/O-Operation für 2 Stack-Operationenbenötigt wird. Dies ist bei B >> 2 deutlich schlechter als bei einer Buffergröße von 2B.

12

Page 17: HEINZ NIXDORF INSTITUT Fakultät für Elektrotechnik ... Pottmeyer Memory Limitations in Artificial Intelligence ... Vitter hat gezeigt, dass viele in diesem Modell effiziente Entwicklungen

3.2 Queue

Die Queue ist dem Stack sehr ähnlich, lediglich wird für das Lesen und Schreiben dasFIFO-Prinzip (First-In-First-Out) verfolgt (siehe Abbildung 8). So werden beim Lesendie Elemente ausgegeben (und gelöscht), welche am längsten in der Queue gespeichertwurden. Die Queue wird im internen Speicher bei einer maximalen Eingabemenge von N

Elementen wie der Stack als Array implementiert. Das Konzept des Buffers ermöglichtauch für die externe Queue eine gute Effizienz. Jedoch wird nicht ein Buffer der Größe2B gehalten, da die Schreiboperationen einen anderen Teil der Daten effektieren als dieLeseoperationen. Es werden zwei Buffer, jeweils der Größe B, im internen Speicher ein-gerichtet. Ein Buffer ist zuständig für den „Anfang“ der Queue und hält die k Elemente,welche am frühesten eingefügt wurden. Der andere Buffer hält das „Ende “ der Queue,kann Schreibbuffer genannt werden, und beinhaltet die k zuletzt eingefügten Elemente.Dabei gilt in beiden Fällen k ≤ B.

Abbildung 8: FIFO-Prinzip der Queue

Die Auslagerung von Elementen aus dem Schreibbuffer des internen Speichers in den ex-ternen Speicher erfolgt, wenn der Schreibbuffer überläuft. Ist der Lesebuffer leer, werdendie nächsten B Elemente aus dem externen Speicher in den internen Speicher geladen.Beinhaltet der externe Speicher beim Nachladen des Lesebuffers keine Elemente derQueue, so werden die Elemente des Schreibbuffers in den Lesebuffer geladen.

Laufzeitanalyse 3.2.

Der worst case entspricht allen Fällen, in denen Daten im externen Speicher ent-halten sind. Dann kosten B Einfügeoperationen (oder B Löschoperationen) eine I/O-Operation. Damit ergibt sich die amortisierte Laufzeit für das Schreiben oder Lesen von1B

I/O-Operationen. Sind keine Daten im externen Speicher und nur in den Lese- undSchreibbuffer enthalten, resultieren Queue-Operationen in keiner I/O-Operation. DerDatenzugriff im internen Speicher wird als konstant angesehen.

13

Page 18: HEINZ NIXDORF INSTITUT Fakultät für Elektrotechnik ... Pottmeyer Memory Limitations in Artificial Intelligence ... Vitter hat gezeigt, dass viele in diesem Modell effiziente Entwicklungen

Es ist zu beachten, dass für die vorgestellten Realisierungen des externen Stacks undder externen Queue eine maximale Eingabegröße N definiert sein muss, da die Daten imexternen Speicher in einem Array von Speicherblöcken der Länge dN/Be−2 gespeichertwerden. Um eine beliebige Anzahl von Elementen zu sichern, bedarf es der Verwendungvon Pointern. Der nächste Abschnitt stellt verkettete Listen vor, welche Pointer nutzen,um eine Verbindung zu den nächsten Speicherblöcken herstellen zu können. Wird der ex-terne Stack oder die externe Queue nicht mit einem Array, sondern mit einer verkettetenListe realisiert, ist die Festlegung der maximalen Eingabedaten nicht erforderlich.

3.3 Verkettete Liste

Verkette Listen ermöglichen eine effiziente Speicherung von Elementen, die einer Ord-nung zu Grunde liegen. Sie unterstützen die sequentielle Suche sowie das Löschen oderEinfügen von Elementen an einer beliebigen Postition der Liste. Wie auch beim Stackund der Queue kann die interne Realisierung bei Anwendung im externen Speicher zueiner I/O-Operation pro Listenoperation führen. Folglich ist es auch für diese elementareDatenstruktur erforderlich, eine effiziente Implementierung für den externen Speicher zuentwickeln.Die Schlüsselidee ist wie bei vielen anderen externen Datenstrukturen die Bewahrung vonLokalität. Lokalität bedeutet, dass Elemente, die in der Liste eine geringe Distanz haben,auch im externen Speicher nah beieinander sein sollen. Die erste Idee ist es, B aufeinanderfolgende Elemente in einem Speicherblock im externen Speicher zu sichern. In diesemFall würde ein Durchlaufen einer Liste der Länge N dN/Be I/Os kosten. Es ist jedochschwierig und aufwendig bei einem Einfügen oder Löschen die Invariante sicherzustellen,dass genau B Elemente in einem Speicherblock enthalten sind. Die Wiederherstellungder Invariante kostet schließlich O (dN/Be) I/Os, da im worst case alle Speicherblöckemodifiziert werden müssen. Eine effizientere Realisierung ist unter der Nutzung von mehrSpeicherplatz im externen Speicher sowie einer Abschwächung der Invariante möglich.

14

Page 19: HEINZ NIXDORF INSTITUT Fakultät für Elektrotechnik ... Pottmeyer Memory Limitations in Artificial Intelligence ... Vitter hat gezeigt, dass viele in diesem Modell effiziente Entwicklungen

Abbildung 9: Einfügen ohne Anpassung der Speicherblöcke

In dieser Seminararbeit wird die Invariante als Beispiel so abgeschwächt, dass in jeweilszwei aufeinander folgenden Blöcken insgesamt mehr als 2

3B Elemente enthalten sein müs-

sen. Durch diese Invariante erhöht sich die Gesamtanzahl aller genutzten Speicherblöckehöchstens um den Faktor 3, welches mit der Erhöhung von I/Os für einen sequentiel-len Scan einhergeht. Der Faktor 3 ergibt sich dadurch, dass zwei aufeinander folgendeBlöcke nur 2

3B statt bei Ausnutzung der vollen Kapazität 2B Elemente beinhalten. Das

Einfügen in einen Block kostet eine I/O, wenn der Block noch freie Kapazität besitzt(siehe Abbildung 9). Falls der gewählte Block Si die maximale Kapazität ausgeschöpfthat und einer seiner Nachbarn Sj weniger als B Elemente besitzt, wird ein entsprechen-des Element von Si nach Sj verlegt (siehe Abbildung 10). Dabei gilt es zu beachten, dassdie Ordnung der Elemente durch die Verlegung nicht verletzt werden darf. Folglich istdas Element, welches dem anderen Speicherblock zugewiesen wird, entweder das kleinste(Sj ist Vorgänger von Si) oder das größte Element (Sj ist Nachfolger von Si) in Si. DieInvariante wird in keiner dieser beiden Fällen verletzt, da die Speicherblöcke lediglichein weiteres Element erhalten.

15

Page 20: HEINZ NIXDORF INSTITUT Fakultät für Elektrotechnik ... Pottmeyer Memory Limitations in Artificial Intelligence ... Vitter hat gezeigt, dass viele in diesem Modell effiziente Entwicklungen

Abbildung 10: Einfügen mit Verlegung von einem Element

In dem Fall, dass beide Nachbarn von Sj ebenfalls keine Elemente mehr aufnehmenkönnen, wird Si in zwei gleich große Blöcke Si1 und Si2 aufgeteilt, die beide etwa B/2-Elemente besitzen (siehe Abbildung 11). Durch das Aufteilen wird die Invariante nichtverletzt, da der Vorgängerblock von Si1 sowie der Nachfolgeblock von Si2 jeweils B

Elemente besitzen und die Summe der Elemente in beiden Blöcken somit etwa B + B2

entspricht. Die Invariante gilt zudem für Si1 und Si2, da diese dadurch entstanden, dassSi mehr als B Elemente aufnehmen sollte.

Abbildung 11: Einfügen mit Aufteilen des Blockes

16

Page 21: HEINZ NIXDORF INSTITUT Fakultät für Elektrotechnik ... Pottmeyer Memory Limitations in Artificial Intelligence ... Vitter hat gezeigt, dass viele in diesem Modell effiziente Entwicklungen

In allen Fällen werden nur eine konstante Anzahl von I/O-Operationen für den betroffe-nen Block Si und seine direkten Nachbarblöcke aufgebracht. Sind beide Nachbarblöckevoll, so wird Si gesplittet, um eine rekursive Bearbeitung der Speicherblöcke zu vermei-den.Das Löschen eines Elementes erfolgt mit Hilfe einer I/O-Operation, falls die Invariantenicht verletzt wird. Nach dem Löschen eines Elementes aus Block Si wird überprüft,ob die Summe der Elemente mit beiden Nachbarn jeweils 2

3B Elemente übersteigt. Ist

die Invariante mit einem Blocknachbarn Sj nicht erfüllt, werden die Elemente beiderBlöcke in einem Speicherblock S ′

i zusammengefasst. Da nun S ′i mehr Elemente besitzt

als Sj und Si einzeln, sind die Invarianten mit den neuen Nachbarn von S ′i erfüllt. Das

Zusammenfassen der Speicherblöcke zu einem einzigen Speicherblock ist möglich, da diesnur erfolgt, wenn beide Blöcke zusammen nicht mehr als 2

3B Elemente besitzen (welches

kleiner als B ist).

Beim Löschen oder Einfügen in eine verkettete Liste kann es erforderlich sein, Speicher-blöcke zu splitten oder zusammenzufassen. Da die Elemente zu einer Liste mit einergeordneten Reihenfolge gehören, kann diese Operation in O(1) I/O-Operationen erfol-gen. Bei der Verknüpfung von zwei Speicherblöcken Si und Si+1 werden die Daten ausSi+1 in den Speicher gelesen und anschließend in den Block Si geschrieben. Da Si+1 we-niger als B Elemente besitzt, können alle Daten mit jeweils einer I/O-Operation gelesenund geschrieben werden. Die Anpassung der Pointer der Nachbarblöcke Si−1 und Si+2

ist nicht erforderlich.Das Aufteilen eines Blockes Si in zwei Speicherblöcke Si1 und Si2 beginnt mit dem Aus-lesen der größten B/2 Elemente von Si und der Abspeicherung in einem neuen Speicher-block Si2. Nach der Belegung des neuen Speicherblocks bedarf es noch der Anpassungdes Pointers vom alten Block Si auf Si2.

Laufzeitanalyse 3.3.

Das Einfügen oder Löschen eines Elementes in der verketteten Liste inklusive gegebe-nenfalls der Wiederherstellung der Invariante ist mit einer konstanten Anzahl von I/O-Operationen möglich, da höchstens der betroffene Block sowie seine direkten Nachbarnangepasst werden müssen.

17

Page 22: HEINZ NIXDORF INSTITUT Fakultät für Elektrotechnik ... Pottmeyer Memory Limitations in Artificial Intelligence ... Vitter hat gezeigt, dass viele in diesem Modell effiziente Entwicklungen

3.4 Wörterbuch

Ein Wörterbuch ist eine abstrakte Datenstruktur, welches auf Anfragen nach einemSchlüssel k einen zugehörigen Wert ausgibt. Diese Anfragen werden Lookup genannt. DieSchlüssel gehören zu einer begrenzten Schlüsselmenge K. Dynamische Veränderungen(Einfügen und Löschen) des Datenbestandes eines Wörterbuchs sind oftmals erwünscht.Für die Implementierung von Wörterbüchern können entweder B-Bäume oder Hashingverwendet werden. Wörterbücher, die Hashing verwenden, können die elementaren An-fragen im Wörterbuch wie Einfügen, Löschen und Lookup, in O(1) I/O-Operationendurchführen [DKM+94]. B-Bäume verlangen zwar eine Gesamtordnung der Schlüssel-werte und haben eine schlechtere Performance bei den elementaren Operationen, ermög-lichen jedoch, dass neben dem Lookup andere Anfragen effizient beantwortet werdenkönnen. Details werden dazu in Kapitel 4 gegeben.Wörterbücher sind eine effiziente Datenstruktur zur Verwaltung von vielen Anwendun-gen wie zum Beispiel von virtuellem Speicher oder von robusten Zeigern. Der folgendeAbschnitt stellt die Nutzung eines Wörterbuches für die Verwaltung vom virtuellemSpeicher vor. Die Verwendung für die robuste Speicherung von Zeigern wird in [MSS03,S.18f] erläutert.

3.4.1 Anwendungsgebiet Virtueller Speicher

In Algorithmen, die Arrays im externen Speicher verwenden, erfolgt oftmals eine Nut-zung und Freigabe von Bereichen von Speicherblöcken. Wie auch im internen Speicherkann aus dieser dynamischen Nutzung eine Zerstückelung sowie eine schlechte Nutz-barkeit des Speichers resultieren. Im externen Speicher kann es soweit gehen, dass zu-sammengehörige Speicherblöcke nicht mehr aufeinanderfolgend allokiert werden kön-nen und folglich für den Datenzugriff eine längere Bearbeitungszeit erforderlich ist.Falls ein konstanter Faktor an zusätzlichen I/Os akzeptiert wird, kann mit Hilfe vonWörterbüchern ein virtueller Speicher realisiert werden. Dazu wird die SchlüsselmengeK = 1, . . . , C × 1, . . . , L definiert, wobei C die maximale Anzahl unterschiedlicherArrays ist und L die maximale Länge eines Arrays. Mit dem Schlüssel (c, i) wird das i-teElement des c-ten Arrays geliefert, falls dieses zuvor geschrieben wurde.Benötigt die Implementierung des Wörterbuches eine (durchschnittlich) konstante An-zahl von I/O-Operationen für das Einfügen, Löschen und Lookup, wird die Verwaltung

18

Page 23: HEINZ NIXDORF INSTITUT Fakultät für Elektrotechnik ... Pottmeyer Memory Limitations in Artificial Intelligence ... Vitter hat gezeigt, dass viele in diesem Modell effiziente Entwicklungen

des virtuellen Speichers lediglich um eine konstante Anzahl von I/O-Operationen erhöht.Für eine detaillierte Beschreibung der Realisierung anhand des Wörterbuches wird auf[MSS03, S.18] verwiesen.

19

Page 24: HEINZ NIXDORF INSTITUT Fakultät für Elektrotechnik ... Pottmeyer Memory Limitations in Artificial Intelligence ... Vitter hat gezeigt, dass viele in diesem Modell effiziente Entwicklungen

4 B-Bäume

Bäume sind eine geeignete Datenstruktur, um Elemente zu verwalten, die einer tota-len Ordnung unterliegen. Die Daten werden in den Blättern gespeichert und die inter-nen Knoten dienen dem Auffinden der Elemente. In diesem Kapitel ist N die Größeder Schlüsselmenge und B die Anzahl der Schlüssel oder Zeiger, die maximal in einenSpeicherblock abgelegt werden können.

Abbildung 12: Nutzung von Speicherblöcken beim Binärbaum

Aus zwei Gründen eignen sich Binärbäume nicht für die Nutzung im externen Speicher.Zum einen ist das Datenvolumen eines Knotens zu gering im Vergleich zur Blockgröße.Da die internen Knoten nur zwei Ausgänge und einen Schlüssel besitzen, sind entwederdie Speicherblöcke nicht vollkommen belegt oder die Informationen eines Knotens werdenin verschiedenen Speicherblöcken gesichert (siehe Abbildung 12). Zum anderen habenKnoten in einem Binärbaum nur zwei Kinder und damit eine Tiefe vonO(log N), welchesmit der Anzahl von I/O-Operationen übereinstimmt, die für die Suche eines Elementes x

aufgebracht werden müssen. Idealerweise wird der Ausgangsgrad des Knoten so erhöht,dass ein Speicherblock durch genau einen Knoten ausgefüllt wird. Damit ergeben sichje nach Blockgröße sehr flache Bäume und es werden Ω(logB N) I/O-Operationen fürdie Suche nach einem Element x benötigt. B-Bäume sind eine Verallgemeinerung derbinären Suchbäume, welche einen Ausgangsgrad von Θ(B) Kindern besitzen [BM72,Com79, HM82, Knu73, RL90] und eignen sich für die Realisierung im externen Speicher.

Der folgende Abschnitt stellt das Konzept von gewichteten B-Bäumen vor sowie eini-ge Eigenschaften, welche bedeutend für die Laufzeitanalyse der Operationen sind. Dieelementaren Operationen im gewichteten B-Baum werden in Abschnitt 4.2 vorgestellt.

20

Page 25: HEINZ NIXDORF INSTITUT Fakultät für Elektrotechnik ... Pottmeyer Memory Limitations in Artificial Intelligence ... Vitter hat gezeigt, dass viele in diesem Modell effiziente Entwicklungen

Eine Effizienzsteigerung kann durch Buffer Bäume erreicht werden, wenn eine verzögerteAntwortzeit erlaubt ist (siehe Abschnitt 4.3). Ein Überblick über weitere Varianten vonB-Bäumen wird in Abschnitt 4.4 gegeben.

4.1 Konzept der gewichteten B-Bäume

Für die Vorstellung und Analyse von gewichteten B-Bäumen soll folgende Annahme er-füllt sein. Sie dient lediglich der Vereinfachung von Abschätzungen und aus ihr resultiertkeine Beeinschränkung der Allgemeinheit.

Annahme 4.1.

Es gelte, dass B8

eine ganze Zahl ist, mit B8≥ 4. Folglich soll die Kapazität eines Speicher-

block mindestens 32 Schlüssel oder Zeiger fassen können.

Gewichtete B-Bäume sind eine spezielle Art von B-Bäumen, deren Balancierungsinvari-ante auf der Anzahl der einem Knoten untergeordneten Blätter beruht. Dieses Konzeptwurde von Arge und Vitter [AV96] für B-Bäume eingeführt, um die Anzahl von Re-balancierungen gegenüber Invarianten des Augangsgrades zu reduzieren. Sie forderten,dass eine Rebalancierung eines Knotens v mit Gewicht w(v) nur alle Ω (w(v)) Update-operationen von darunterliegenden Elementen notwendig sein soll [Arg04]. Jedoch habengewöhnliche B-Bäume oder auch (a, b)-Bäume diese Eigenschaft nicht und sie entwickel-ten die gewichteten B-Bäume.Im Vergleich zu den originalen B-Bäumen sind einige Eigenschaften bewahrt und einigeverschärft worden. In gewichteten B-Bäumen haben - wie auch in originalen B-Bäumen- alle Blätter die gleiche Distanz zum Wurzelknoten, welches der Höhe des Baumesentspricht. Des Weiteren hat die Wurzel eine Sonderstellung und darf einen beliebigenAusgangsgrad größer zwei besitzen. Darüber hinaus werden folgende Begriffe definiert:

Definition 4.1.

Das Level eines Knotens i im B-Baum ist die Distanz zu den Blättern seiner unterge-ordneten Teilbäume. Da alle Blätter die gleiche Distanz zur Wurzel haben, ist der Werteindeutig definiert. Die Anzahl der Blätter in den untergeordneten Teilbäumen wird Ge-wicht des Knotens i genannt.

21

Page 26: HEINZ NIXDORF INSTITUT Fakultät für Elektrotechnik ... Pottmeyer Memory Limitations in Artificial Intelligence ... Vitter hat gezeigt, dass viele in diesem Modell effiziente Entwicklungen

Abbildung 13: Gewichteter B-Baum

Blätter befinden sich auf dem Level Null und haben Gewicht Eins. Da jeder interneKnoten (bis auf die Wurzel) Θ(B) Kinder besitzt, wird in einem internen Knoten eineSuchanfrage unter Nutzung der totalen Ordnung der Schlüssel in einen der Θ(B) Teil-bäume weitergeleitet. Ein interner Knoten hält somit eine Menge von Schlüsseln, um dieSuche in den korrekten Teilbäumen ermöglichen zu können (siehe Abbildung 13). DieAnzahl der Blätter, die sich unter einem Knoten eines niedrigeren Levels befinden, sinktfolglich um den Faktor Θ(B). Diese Eigenschaft wurde in einer Gewichtsinvariante fürdie Balancierung genutzt:

Definition 4.2. [AV96]Jeder Knoten mit Level i - außer der Wurzel - hat ein Gewicht von mindestens (B/8)i.3

Eine maximale Gewichtsbeschränkung von 4(B/8)i gilt für jeden beliebigen Knoten desgewichteten B-Baums.

Die sich aus dieser Gewichtsinvariante ergebenen Eigenschaften werden im folgendenAbschnitt beschrieben.

4.1.1 Eigenschaften

Dieser Abschnitt präsentiert die Eigenschaften eines gewichteten B-Baums, welcher dieGewichtsinvariante aus Defintion 4.2 erfüllt. Zunächst wird die minimale und maximaleAnzahl von Kindern eines Knotens untersucht, anschließend erfolgt die Berechnung derHöhe des gewichteten B-Baumes. Die Berechnungen der Kinderanzahl folgen analog zu[Arg04].

1. Maximale Kinderanzahl eines beliebigen KnotensEin Knoten a auf Level i hat den höchsten Ausgangsgrad, wenn der Knoten a das

3Dies gilt für alle Knoten mit Level i < h, wobei h die Höhe des Baumes ist

22

Page 27: HEINZ NIXDORF INSTITUT Fakultät für Elektrotechnik ... Pottmeyer Memory Limitations in Artificial Intelligence ... Vitter hat gezeigt, dass viele in diesem Modell effiziente Entwicklungen

Maximalgewicht von 4(B/8)i und jedes Kind minimales Gewicht (B/8)i−1 besitzt. Esgilt, dass das Gewicht von Knoten a der Summe der Gewichte seiner Kinder entspricht.Damit folgt:

4(

B8

)i(B8

)i−1 = 4 · B

8=

B

2(4)

2. Minimale Kinderanzahl eines beliebigen Knotens (außer der Wurzel)Ein Knoten a auf Level i hat den kleinsten Ausgangsgrad, wenn der Knoten a dasminimale Gewicht von (B/8)i besitzt und jedes Kind das Maximalgewicht von 4(B/8)i−1

angenommen hat. Damit folgt: (B8

)i

4(

B8

)i−1 =1

4· B

8=

B

32(5)

3. Maximale Höhe eines gewichteten B-BaumsDie Wurzel hat beim gewichteten B-Baum wie auch beim gewöhnlichen B-Baum eineSonderstellung und darf auch weniger als B

32Kinder besitzen. Folglich wird bei der Be-

rechnung der Höhe die Wurzel zunächst außer Betracht gelassen und anschließend umEins inkrementiert. Der gewichtete B-Baum erreicht die größte Höhe, wenn jeder KnotenMinimalgewicht besitzt. Hat der Knoten a auf Level i das Minimalgewicht von (B/8)i

und alle seine Kinder haben ebenfalls minimales Gewicht (B/8)i−1, so ergibt sich fürden Ausgangsgrad: (

B8

)i(B8

)i−1 =B

8(6)

Hat jeder Knoten B8

Kinder, so besitzt der Baum inklusive der Wurzel höchstens 1 +

dlogB/8 Ne Ebenen (= Höhe des Baumes).

4. Untere Grenze für Baumhöhe eines gewichteten B-BaumsDer gewichtete B-Baum soll einen Ausgangsgrad von Θ(B) besitzen. Hat jeder Knoten imBaum B Kinder, so ist die Höhe des Baumes dlogB Ne. Laut (4) ist jedoch die maximale

23

Page 28: HEINZ NIXDORF INSTITUT Fakultät für Elektrotechnik ... Pottmeyer Memory Limitations in Artificial Intelligence ... Vitter hat gezeigt, dass viele in diesem Modell effiziente Entwicklungen

Anzahl von Kindern B2. Eine eine untere Grenze für die Baumhöhe ist demnach

Ω(logB N) (7)

Folgerung 4.1.

Die Anzahl der untergeordneten Teilbäume eines jeden Knotens, abgesehen von der Wur-zel, liegt im Interval

[B32

, B2

]. Hat ein Knoten B

2Kinder, so ist es erforderlich für diesen

Knoten B2

Zeiger zu den Teilbäumen sowie B2− 1 Schlüssel für die Navigation im Baum

abzuspeichern. Zusätzlich wird die Anzahl der untergeordneten Blätter gesichert, um dieInvariante effizient überprüfen zu können. Der Speicherplatz für diese Daten beträgt ins-gesamt:

B

2︸︷︷︸ +B

2− 1︸ ︷︷ ︸ + 1︸︷︷︸ = B (8)

Zeiger Schlüssel Zähler

Wie zuvor erwähnt, werden die Daten mit ihren Schlüsseln in den Blättern gespeichert.Diese Blätter sind als verkettete Liste verknüpft wie in Abbildung 14 dargestellt. DieVerkettung ermöglicht die effiziente Bearbeitung von Anfragen wie Range Reporting,welches in Abschnitt 4.2.4 vorgestellt wird. Es gilt zu beachten, dass in einem Speicher-block der verketteten Liste weniger als Θ(B) Elemente enthalten sein können, falls dieeigentlichen Daten des Wörterbuches mehr Platz benötigen als ihre Schlüssel. Schließ-lich bestimmt B die Anzahl von Schlüsseln oder Zeigern, die in einen Speicherblockgespeichert sein können, und stellt keine Beziehung zu der eigentlichen Datengröße dar.

Abbildung 14: Blätter im B-Baum als verkettete Liste

24

Page 29: HEINZ NIXDORF INSTITUT Fakultät für Elektrotechnik ... Pottmeyer Memory Limitations in Artificial Intelligence ... Vitter hat gezeigt, dass viele in diesem Modell effiziente Entwicklungen

4.2 Operationen im gewichteten B-Baum

Dieser Abschnitt stellt die Funktionsweisen der elementaren Operationen Suchen, Ein-fügen und Löschen vor. Die Operationen werden mit Hilfe der Eigenschaften aus Ab-schnitt 4.1.1 bezüglich ihrer Laufzeit analysiert.Darüber hinaus wird auf das Range Reporting eingegangen (siehe Abschnitt 4.2.4), wel-ches eine spezielle Datenanfrage ist und effizient im B-Baum durchgeführt werden kann.Diese Operation zeigt beispielhaft, dass B-Bäume auch bei einer schlechteren Leistungbei den elementaren Operationen gegenüber dem Hashing für die Realisierung von Wör-terbüchern vorteilhaft sind, falls weitere Anfragetypen unterstützt werden sollen.

4.2.1 Suchen

Die internen Knoten eines B-Baumes speichern abhängig von der Anzahl ihrer Kindereine Menge von Schlüsseln für die Navigation im Baum. Ein Knoten v hält die Schlüsselk1, . . . , kdv−1, wobei der i-te Teilbaum die Schlüssel k mit ki−1 ≤ k < ki abspeichert.Dabei seien k0 = −∞ und kdv = ∞ definiert.

Beispiel 4.1.

Im Beispielbaum der Abbildung 14 hat die Wurzel zwei Teilbäume und hält den Schlüsselk1. Die Schlüssel im linken Teilbaum sind alle kleiner als k1. Der Schlüssel k2 gehörtzum zweiten Datenelement und der Schlüssel k3 zum dritten Datenelement. Der rechteTeilbaum beinhaltet das Element, welches zum Schlüssel k1 gehört. Im Detail gehört k1

zu dem kleinsten Element des rechten Teilbaums, welches das Datenelement 4 ist.

Da sich alle Daten in den Blättern des Baumes befinden und jeder interne Knoten ineinem eigenen Speicherblock gesichert wird, entspricht die Anzahl der I/O-Operationenfür eine Suche nicht nur im worst case sondern auch im best und average case der Baum-höhe. Gemäß (6) ist die maximale Baumhöhe 1 + dlogB/8 Ne. Der Binärbaum hat eineHöhe von O(log N), folglich wird durch die Nutzung eines gewichteten B-Baums etwa einFaktor von log B I/O-Operationen gespart. Das folgende Beispiel 4.2 soll veranschauli-chen, dass bei realistischen Größen von B und N die Anzahl der I/O-Operationen geringsind.

Beispiel 4.2.

Ist B = 212 und N ≤ 227 ist die Höhe des Baumes begrenzt durch 4. Da die Wurzel

25

Page 30: HEINZ NIXDORF INSTITUT Fakultät für Elektrotechnik ... Pottmeyer Memory Limitations in Artificial Intelligence ... Vitter hat gezeigt, dass viele in diesem Modell effiziente Entwicklungen

im internen Speicher gesichert werden kann, benötigt eine Suche somit nur drei I/O-Operationen, um eins von maximal 227 Elementen zu finden.

4.2.2 Einfügen

Das Einfügen im gewichteten B-Baum entspricht der Methode im Binärbaum außer wenndie Invariante verletzt wird und eine Rebalancierung notwendig ist. Das Einfügen wirdin diesem Abschnitt mit Hilfe eines Beispieles verdeutlicht, in welchem das Datenelement7 eingefügt werden soll (Abbildungen 15 - 17).

Abbildung 15: Auffinden der korrekten Position

Für das Einfügen eines Elementes x, wird zunächst nach x gesucht, um den internen Kno-ten zu finden, welcher der Elternknoten von x werden soll. Wie in Abbildung 15 darge-stellt, wird im Beispielbaum für das Datenelement 7 der rechte Teilbaum der Wurzel alsElternknoten gefunden. Der Elternknoten erhält ein weiteres Blatt für das Datenelement7, welches die Aufnahme eines weiteren Schlüssels (k8) einschließt (siehe Abbildung 16).

Abbildung 16: Erzeugung eines neuen Blattes und Modifikation des Elternknotens

26

Page 31: HEINZ NIXDORF INSTITUT Fakultät für Elektrotechnik ... Pottmeyer Memory Limitations in Artificial Intelligence ... Vitter hat gezeigt, dass viele in diesem Modell effiziente Entwicklungen

Im Beispielbaum sei für das Level 1 ein Gewicht zwischen 3 und 5 erlaubt. Dieses stimmtzwar nicht mit der Gewichtsinvariante aus Definition 4.2 unter der Annahme 4.1 überein.Da die Komplexität des Beispiels jedoch anschaulich bleiben soll, wurde die Gewicht-sinvariante auf diese Art vereinfacht, um das Prinzip der Rebalancierung zu erläutern.Gemäß des erlaubten Gewichtes im Intervall [3, 5], ist es erforderlich nach dem Einfügendes Datenelementes 7 den rechten Teilbaum zu rebalancieren.Die Rebalancierung beginnt von unten nach oben und teilt alle übergewichtigen Knotenin zwei neue Knoten auf. Es sei angemerkt, dass durch das Einfügen bei einem Knotenv auf Level i sich das Gewicht auf 4

(B8

)i+ 1 erhöht, falls er das zulässige Maximalge-

wicht überschritten hat. Um einen Knoten v in zwei neue Knoten v1 und v2 aufzuteilen,werden die Kinder von v in zwei Gruppen eingeteilt. Habe v die Schlüssel k1, . . . kdv ,dann erfolgt die Gruppenaufteilung auf Basis eines Schlüssels k′ ∈ k1, . . . kdv so dass∀ki des Teilbaumes von v1 ki < k′ gilt und ∀kj des Teilbaumes von v2 kj ≥ k′ erfüllt ist.Diese Aufteilung ist erforderlich, um die totale Ordnung im Baum auch mit den neuenKnoten zu gewährleisten. Nach der Aufteilung des Knoten v wird dieser durch die bei-den neuen Knoten ersetzt und der Schlüssel k′ in den Elternknoten aufgenommen (sieheAbbildung 17). Ist die Gewichtsinvariante des Elternknotens verletzt, wird auch dieserin zwei Knoten aufgeteilt. Die Überprüfung auf die Gültigkeit der Gewichtsinvariantewird gestoppt, sobald bei einem Elternknoten die Invariante nicht mehr verletzt ist.

Abbildung 17: B-Baum nach Rebalancierung des rechten Teilbaums

Ziel bei der Bildung der neuen Knoten v1 und v2 ist es, einen möglichst balanciertenBaum zu erhalten, damit nach Möglichkeit sehr wenige Rebalancierungen bei weite-ren Einfüge- oder Löschoperationen notwendig sind. Folglich sollen die Gewichte derKnoten v1 und v2 weitestgehend identisch sein. Jedoch dürfen bereits existierendeTeilbäume nicht gesplittet werden und daher ist oftmals die Erzeugung gleichschwe-rer Knoten v1 und v2 nicht möglich. Da ein untergeordneter Teilbaum von v maxi-

27

Page 32: HEINZ NIXDORF INSTITUT Fakultät für Elektrotechnik ... Pottmeyer Memory Limitations in Artificial Intelligence ... Vitter hat gezeigt, dass viele in diesem Modell effiziente Entwicklungen

mal Gewicht 4(

B8

)i−1 besitzt, können v1 und v2 höchstens um 2(

B8

)i−1 Gewichtsein-heiten differieren. Damit befinden sich die Gewichte der neuen Knoten im Interval[2(

B8

)i − 2(

B8

)i−1, 2

(B8

)i+ 2

(B8

)i−1+ 1

]. Da nach Annahme 4.1 B/8 ≥ 4 ist, haben

v1 und v2 Gewichte im Bereich 32

(B8

)i und 52

(B8

)i+ 1, wie die folgenden Berechnungen

zeigen. Die untere Grenze von 32

(B8

)i für Knoten v1 und v2 ist gültig für B8≥ 4:

3

2

(B8

)i ≤ 2

(B

8

)i

− 2

(B

8

)i−1

⇔ 3

4

(B8

)i ≤(

B

8

)i

−(

B

8

)i−1

⇔ 3

4

(B8

)≤

(B

8

)− 1 (9)

⇒ gültig fürB

8≥ 4

Die obere Grenze von 52

(B8

)i+ 1 für Knoten v1 und v2 ist gültig für B

8≥ 4:

5

2

(B8

)i+ 1 ≤ 2

(B

8

)i

+ 2

(B

8

)i−1

+ 1

⇔ 5

4

(B8

)i ≤(

B

8

)i

+

(B

8

)i−1

⇔ 5

4

(B8

)≤

(B

8

)+ 1 (10)

⇒ gültig fürB

8≥ 4

Mit (9) und (10) wurde gezeigt, dass die neuen Knoten ein Gewicht zwischen 32

(B8

)i und52

(B8

)i+1 besitzen und somit Ω

((B

8)i)

Gewichtseinheiten vom minimalen und maximalenGewicht differieren. Diese Beobachtung wird benötigt, um die Anzahl der Einfüge- undLöschoperationen abzuschätzen, nach welchen eine Rebalancierung der neuen Knoten v1

und v2 erforderlich ist.

Laufzeitanalyse 4.1.

Die erforderlichen I/O-Operationen einer Rebalancierung für einen Knoten v sind ko-stant, da nur eine konstante Anzahl an internen Knoten betroffen sind (Knoten v, El-ternknoten von v sowie die neuen Knoten v1 und v2). Mit der vorhergehenden Suchope-

28

Page 33: HEINZ NIXDORF INSTITUT Fakultät für Elektrotechnik ... Pottmeyer Memory Limitations in Artificial Intelligence ... Vitter hat gezeigt, dass viele in diesem Modell effiziente Entwicklungen

ration benötigt das Einfügen somit O(logB N)- I/O-Operationen.[MSS03, S.22] zeigt, dass amortisierte Kosten von lediglich O

(1B

logB N)

I/Os pro Än-derungsoperation im Baum benötigt werden. Genutzt wird bei dieser Berechnung, dassnach einer Rebalancierung die neuen Knoten Ω

((B

8)i)

Gewichtseinheiten entfernt vonder minimalen und der maximalen Gewichtsgrenze sind.

4.2.3 Löschen

Die Durchführung einer Löschoperation ist der Einfügeoperation sehr ähnlich. Das zulöschende Element x wird gesucht, das entsprechende Blatt gelöscht und der Elternkno-ten v modifiziert. Der neue Elternknoten v′ besitzt ein Kind und einen Schlüssel wenigerals vor der Löschoperation. Da sich das Gewicht des Elternknotens v um Eins reduziert,kann die untere Gewichtsgrenze von B

8verletzt werden. Diese Gewichtsgrenze ist fest auf

B8

gesetzt, da Elternknoten eines Blattes sich auf dem Level Eins befinden. Durch die Lö-schoperation können jedoch die Gewichtsinvarianten mehrerer Knoten auf dem Pfad zurWurzel verletzt worden sein, so dass für die Rebalancierung allgemein ein Knoten v aufLevel i betrachtet wird. Wie beim Einfügen werden Rebalancierungsoperationen beimKnoten des unteresten Level gestartet und, falls notwendig, auf dem Pfad zur Wurzelfortgesetzt.Die Rebalancierung eines Knotens v erfolgt mit Hilfe einer seiner direkten Nachbarn w.Da alle Blätter sich auf dem gleichen Level befinden, existiert für einen internen Knotenv ein anderer interner Knoten w als Nachbar. Für diesen Nachbarn ist die Gewichtsin-variante erfüllt, da seine Kinder nicht durch die Löschoperation verändert wurden. Fürdie Rebalancierung ist es notwendig, zwei Fälle für die Summe S der Gewichte von v

und w zu betrachten:

1. S ≤ 72

(B8

)i

2. 72

(B8

)i< S < 5

(B8

)i

Die Rebalancierung des ersten Falles wird mit Hilfe der Abbildungen 18 und 19 veran-schaulicht. Diese Abbildungen dienen lediglich dem Verständnis der Rebalancierung undgenügen nicht der definierten Gewichtsinvariante aus Definition 4.2 mit Annahme 4.1.In den Beispielabbildungen wird die Gewichtsinvariante erfüllt, wenn Knoten auf Le-vel 1 ein Gewicht zwischen 3 und 5 besitzen. Abbildung 18 zeigt einen Beispielbaumvor dem Löschen von dem Datenelement 3, in welchem der erste Fall angewendet wird.

29

Page 34: HEINZ NIXDORF INSTITUT Fakultät für Elektrotechnik ... Pottmeyer Memory Limitations in Artificial Intelligence ... Vitter hat gezeigt, dass viele in diesem Modell effiziente Entwicklungen

Die Löschung des Datenelementes 3 im zweiten Fall wird an Hand von Abbildung 20dargestellt.

Abbildung 18: 1. Fall: B-Baum vor dem Löschen des Datenelementes 3

Im ersten Fall werden die beiden Knoten v und w zu einem Knoten v′ verschmolzen. Fallsv und w die einzigen Kinder der Wurzel waren, wird v′ die neue Wurzel des gewichtetenB-Baumes. Das Zusammenfügen zu einem neuen Knoten v′ ist effizient realisierbar, dalediglich ein neuer Schlüssel in v für den ersten bzw. letzten Teilbaum von w aufge-nommen werden muss und anschließend die restlichen Schlüssel sowie die Zeiger von w

übernommen werden.

Abbildung 19: Zusammengefügte Knoten nach der Rebalancierung

Möglich wäre es, für den ersten Fall nicht S ≤ 72

(B8

)i sondern gemäß der Gewichtsin-variante S ≤ 4

(B8

)i zu definieren. Jedoch würde dann eine einzige Einfügeoperation ineinen Teilbaum von v′ in einer erneuten Rebalancierung resultieren. Aus diesem Grundwird die maximale Grenze des gemeinsamen Gewichtes von v und w auf 7

2

(B8

)i gesetzt,welches wiederum wie beim Einfügen um Ω((B/8)i) Gewichtseinheiten von den Grenzender Gewichtsinvariante differiert.

30

Page 35: HEINZ NIXDORF INSTITUT Fakultät für Elektrotechnik ... Pottmeyer Memory Limitations in Artificial Intelligence ... Vitter hat gezeigt, dass viele in diesem Modell effiziente Entwicklungen

Abbildung 20: 2. Fall: B-Baum vor dem Löschen des Datenelementes 3

Das gemeinsame Gewicht von v und w ist nach oben begrenzt durch 5(

B8

)i, da v unter-gewichtig ist. Dieses maximale Gewicht wird angenommen, wenn Knoten w Maximal-gewicht 4

(B8

)i besitzt. Im Rahmen der Rebalancierung im zweiten Fall werden einigeKinder von w dem Knoten v übertragen. Wie beim Einfügen wird dabei das Ziel ver-folgt, einen möglichst balancierten Baum zu erreichen. Folglich werden alle Kinder von v

und w in zwei aufeinanderfolgende Gruppen aufgeteilt. Da ein Kind höchstens Gewicht4(

B8

)i−1 besitzen kann, sind die Gewichte der Gruppen begrenzt durch 74

(B8

)i−2(

B8

)i−1

sowie 52

(B8

)i+2

(B8

)i−1. Die Kinder der einen Gruppe werden dem neuen Knoten w′ unddie anderen Kinder dem neuen Knoten v′ zugeordnet (siehe Abbildung 21). Auch nachdieser Rebalancierung unterscheiden sich die Gewichte der neuen Knoten um Ω((B/8)i)

Gewichtseinheiten von den Grenzen der Gewichtsinvariante.

Abbildung 21: Aufgeteilte Kinder zwischen erstem und zweitem Teilbaum

Laufzeitanalyse 4.2.

Analog zur Laufzeitanalyse 4.1 benötigt die Rebalancierung O(1) I/O-Operationen undder gesamte Löschvorgang inklusive der vorhergehenden Suchoperation O(logB N) I/O-Operationen. Die amortisierten Kosten pro Änderungsoperation sind O

(1B

logB N)

I/Os.

31

Page 36: HEINZ NIXDORF INSTITUT Fakultät für Elektrotechnik ... Pottmeyer Memory Limitations in Artificial Intelligence ... Vitter hat gezeigt, dass viele in diesem Modell effiziente Entwicklungen

4.2.4 Range Reporting

B-Bäume eignen sich als Implementierung eines Wörterbuches, da sie neben Lookup-Anfragen auch weitere Anfragetypen effizient bearbeiten können. In diesem Abschnittwird das Range Reporting vorgestellt, welches die Daten in einem Bereich [a, b] zurück-liefert.Die Bearbeitung einer Range Anfrage nach allen Daten mit Schlüsseln im Intervall [a, b]

beginnt zunächst mit der Suche des Schlüssels a im B-Baum. Da die Blätter im B-Baumüber eine verkettete Liste verbunden sind, erfolgt ein sequentieller Durchlauf der Listebis der Schlüssel b und sein zugehöriges Datenelement erreicht werden. Beim Durchlaufwerden alle Schlüssel mit zugehörigen Daten ausgegeben, so dass die Bereichsanfragebeantwortet ist. Die Anzahl der I/O-Operationen für ein Range Reporting ist zum einenabhängig von der Größe der gesicherten Datenelemente und zum anderen von der Schlüs-selanzahl im Bereich [a, b].Sollen im B-Baum keine Nutzdaten und lediglich die Schlüssel abgespeichert werden undes befinden sich Z Schlüssel im Bereich [a, b], so erfordert der Listendurchlauf O

(ZB

)I/O-Operationen. Für die gesamte Bearbeitung des Range Reportings kommen zudemO(logB N) I/Os für die Suche des Schlüssels a hinzu.

4.3 Buffer Bäume

Buffer Bäume [Arg95] können verwendet werden, wenn Anfragen mit einer gewissenVerzögerungszeit – und nicht online – beantwortet werden dürfen. Bei der Stapelver-arbeitung von Anfragen und Updateoperationen ist diese Voraussetzung zum Beispielgegeben. Erst nachdem alle Anfragen und Operationen des Stapels durchgeführt wurden,werden die Antworten der Anfragen bereitgestellt.Abschnitt 4.3.1 stellt das grobe Konzept der Buffer Bäume vor. Die Datenstruktur eig-net sich vor allem für eine effiziente Realisierung der Priority-Queue, welches im Ab-schnitt 4.3.2 erläutert wird. In beiden Abschnitten wird vorausgesetzt, dass die abzu-speichernden Werte die gleiche Größe wie die Schlüssel besitzen.

32

Page 37: HEINZ NIXDORF INSTITUT Fakultät für Elektrotechnik ... Pottmeyer Memory Limitations in Artificial Intelligence ... Vitter hat gezeigt, dass viele in diesem Modell effiziente Entwicklungen

4.3.1 Konzept

Buffer Bäume sind gewöhnliche B-Bäume mit Ausgangsgrad Θ(M/B). Jeder interneKnoten des Baumes ist mit einer Queue ausgestattet, in welcher die letzten M Upda-teoperationen und Anfragen gesichert sind, die auf einen der Teilbäume unter dem in-ternen Knoten ausgeführt werden müssen. Es ist wichtig, die Methoden in einer Queuezu sichern, um ihre Bearbeitung in der korrekten Reihenfolge ausführen zu können. DieWurzel wird aus dem internen Speicher schubweise über die durchzuführenden Operatio-nen informiert. Dies geschieht durch eine Datenhaltung im internen Speicher, so dass dasSchreiben in den Wurzelknoten pro Methode durchschnittlich O(1/B) I/O-Operationenkostet. Ist der Buffer des (Wurzel-)knotens v voll, so wird dieser ausgeschüttet (engl. flus-hed): Der Inhalt der Queue von v wird in den internen Speicher geladen und gemäß derverantwortlichen Teilbäume sortiert. Anschließend werden die zugehörigen Methoden indie Buffer jedes Kindes des ausgeschütteten Knotens v geschrieben. Ist durch diese Zu-weisung die Bufferkapazität des Kindknotens ausgeschöpft, so wird dieser anschließendausgeschüttet usw. Wird ein Knoten v geflusht, dessen Kinder Blätter des B-Baumessind, so werden seine M/B Kinder in den internen Speicher geladen und die auszu-führenden Methoden (Anfragen und Updateoperationen) nach und nach durchgeführt.Nach der kompletten Verarbeitung aller Methoden kann die Invariante des Knotens v

verletzt sein, so dass eine Rebalancierung notwendig ist. Wird der einem Blatt überge-ordnete Knoten v geflusht, ist dies eine Folge der Ausschüttung des Elternknotens vonv usw. Somit existiert eine sequentielle Ausschüttung der Knoten auf dem Pfad zwi-schen Wurzel und Blatt, falls alle Buffer voll werden, und alle in einer Rebalancierunginvolvierten Knoten haben einen leeren Buffer. Folglich muss der Buffer bei der Rebalan-cierung nicht betrachtet werden und die Rebalancierung eines Buffer Baums entsprichtder Vorgehensweise eines gewöhnlichen B-Baums.Für die Laufzeiten wird auf eine detaillierte Analyse verzichtet, da lediglich die Idee derBuffer Bäume vorgestellt werden soll.

Laufzeitanalyse 4.3.

Ein Ausschütten kostet O(1/B) I/O-Operationen pro Methode, die im Buffer gehaltenwird. Da alle Operationen an den Blättern durchgeführt werden, entspricht die Anzahlder benötigten Ausschüttungen pro Methode der Baumhöhe O

(logM

B

(NM

)). Die Gesamt-

kosten belaufen sich damit auf O(

1B

logMB

(NM

))I/O-Operationen pro auszuführende Me-

33

Page 38: HEINZ NIXDORF INSTITUT Fakultät für Elektrotechnik ... Pottmeyer Memory Limitations in Artificial Intelligence ... Vitter hat gezeigt, dass viele in diesem Modell effiziente Entwicklungen

thode.Das Rebalancieren eines Knotens benötigt O(M/B) I/O-Operationen. Die erforder-lichen Rebalancierungen bei N Updates kosten jedoch zusammen nur O(N/B) I/O-Operationen, da bei N Updates nur O(N/M) Rebalancierungen notwendig sind [HM82].

4.3.2 Realisierung der Priority-Queue

Daten einer Priority-Queue sind gemäß eines Schlüssels sortiert, welcher mit ihrer Prio-rität übereinstimmt. Elementare Operationen sind das Einfügen eines Schlüssels mit zu-gehörigen Daten und die Suche und Löschung des kleinsten Schlüssels.4 Die effizientesteRealisierung einer Priority-Queue erfolgt mit einem Buffer Baum, falls O(M) internerSpeicher zu Verfügung steht. Der interne Speicher beinhaltet zum einen den Buffer desWurzelknotens. Zum anderen werden die linkesten O

(MB

)Blätter gespeichert, welche

den Kindern des linkesten internen Knotens v entsprechen.Als Invariante wird definiert, dass alle Buffer auf dem Pfad von der Wurzel zum linkes-ten Knoten v leer sind. Dies geht damit einher, dass beim Ausschütten der Wurzel nacheinander jeweils das linkeste Kind auf jedem Level geflusht wird. Zur Erfüllung der Invari-ante werden zusätzliche Flushes benötigt, die aufgrund des Füllstandes der Buffer nichtunbedingt erforderlich wären. Sie belaufen sich auf durchschnittlich O

(1B

logMB

(NM

))I/O-Operationen pro Updateoperation im Baum.

Abbildung 22: Priority-Queue nach Löschung der M kleinsten Elemente mit M = 5

4Stacks und Queues sind spezielle Fälle der Priority-Queue.

34

Page 39: HEINZ NIXDORF INSTITUT Fakultät für Elektrotechnik ... Pottmeyer Memory Limitations in Artificial Intelligence ... Vitter hat gezeigt, dass viele in diesem Modell effiziente Entwicklungen

Da im internen Speicher die linkesten O(

MB

)Blätter gesichert sind, befinden sich im in-

ternen Speicher die M kleinsten Elemente der Datenstruktur. Das Auslesen des kleinstenElementes benötigt somit keine I/O-Operation. Werden die M kleinsten Elemente ge-löscht, sind mindestens M Operationen erforderlich. Zwar könnte der interne Speicherin diesem Fall das Lesen des kleinsten Elementes nicht mehr ohne eine I/O-Operationdurchführen, aber nach M Operationen wird der Buffer der Wurzel ausgeschüttet. Dar-aus folgt, dass der linkeste Pfad des B-Baumes vollständig aktualisiert wird und an-schließend die neuen M kleinsten Elemente im internen Speicher vorhanden sind.

Abbildung 22 zeigt eine Priority-Queue mit M = 5, in welcher gerade der Buffer aus-geschüttet wurde. In diesem Beispiel wurden hintereinander alle kleinsten Elemente derPriority-Queue gelöscht, so dass der linkeste Teilbaum vollständig verschwunden ist unddie neuen fünf kleinsten Elemente in den internen Speicher geladen wurden.

Laufzeitanalyse 4.4.

Eine Priority-Queue realisiert mit einem Buffer Baum benötigt eine amortisierte Lauf-zeit von O

(1B

logMB

(NM

))I/O-Operationen für das Einfügen und Löschen eines belie-

bigen Elementes. Das kleinste Element wird redundant im internen Speicher gehalten,so dass Leseoperationen ohne I/O-Operationen durchgeführt werden können. Da es sichjedoch nur um eine redundante Kopie des kleinsten Elementes handelt, ist das Löschendes kleinsten Elementes genauso aufwendig wie für alle anderen Elemente.

4.4 Varianten von B-Bäumen

In diesem Abschnitt wird ein Überblick über weitere Varianten von originalen B-Bäumengegeben. Jeder Abschnitt gibt einen Überblick der Modifikationsidee. Abschnitt 4.4.1 be-trachtet zusätzliche Zeiger, Abschnitt 4.4.2 Persistenz und Abschnitt 4.4.3 unbeschränkteStringgrößen.

35

Page 40: HEINZ NIXDORF INSTITUT Fakultät für Elektrotechnik ... Pottmeyer Memory Limitations in Artificial Intelligence ... Vitter hat gezeigt, dass viele in diesem Modell effiziente Entwicklungen

4.4.1 B-Bäume mit zustätzlichen Zeigern

In gewöhnlichen B-Bäumen können zusätzliche Zeiger hinzugefügt werden, um spezielleAnfragen effizient bearbeiten zu können (siehe Abbildung 23). Die Aktualisierung vonZeigern auf den Elternknoten kann ohne zusätzliche Kosten durchgeführt werden.

Abbildung 23: B-Baum mit Zeigern auf Elternknoten

Des Weiteren können Zeiger auf Nachbarknoten des gleichen Levels eingefügt werden,wodurch eine doppelt verketteten Liste entsteht (siehe Abbildung 24). Derartige zusätz-liche Zeiger ermöglichen so genannte finger -Suchen effizient zu beantworten. In einerfinger -Suche wird von einem Blatt v aus in einem B-Baum ein anderes Blatt w gesucht.Bei B-Bäumen mit zusätzlichen Zeigern auf die Elternknoten sowie auf die Nachbar-knoten kann der Suchalgorithmus von Knoten v den Pfad zur Wurzel verfolgen bis deraktuelle Knoten oder einer seiner Nachbarknoten das Blatt w in einem seiner Teilbäu-me hat. Zum Finden des Blattes w bedarf es dann der gewöhnlichen Suche beginnendim identifizierten übergeordneten Knoten der finger -Suche. Diese Suche spart Kosten,wenn die Blätter v und w relativ nah aneinanderliegen. Die Anzahl der I/O-Operationenfür die finger -Suche liegt bei O(logB Q), wobei Q der Blätteranzahl zwischen v und w

entspricht. Folglich kann eine finger -Suche I/O-Operationen sparen anstatt das Blatt w

(ebenfalls wie das Blatt v) von der Wurzel aus zu suchen.

Abbildung 24: B-Baum mit Zeigern auf Nachbarknoten

36

Page 41: HEINZ NIXDORF INSTITUT Fakultät für Elektrotechnik ... Pottmeyer Memory Limitations in Artificial Intelligence ... Vitter hat gezeigt, dass viele in diesem Modell effiziente Entwicklungen

4.4.2 Teilweise persistente B-Bäume

Teilweise persistente B-Bäume werden manchmal auch Multiversionen B-Bäume ge-nannt. Ihre Besonderheit liegt darin, dass der modifizierte B-Baum nach einer Update-operation (Einfügen oder Löschen) als eine neue Version des B-Baumes gespeichert wird.Anfragen können an beliebige Versionen des B-Baumes gestellt werden. Die Sicherungverschiedener Versionen ist nützlich, wenn eine Historie der Datenstruktur für Anfragenbenötigt wird.Mit Hilfe von Standardtechniken zur Realisierung von Persistenz im internen Speicher[DSST89, ST86] können auch persistente B-Bäume im externen Speicher effizient reali-siert werden. Eine Folge von N Updateoperationen führt zu einer Datenstruktur, welcheO

(NB

)externe Speicherblöcke benötigt. Anfragen in einer beliebigen Version des B-

Baums erfordern O(logB N) I/O-Operationen. Range Anfragen (siehe Abschnitt 4.2.4)werden ebenfalls unterstützt. Details zu diesen Varianten können in [BGO+96, ST86]gefunden werden.

4.4.3 String B-Bäume

In diesem Kapitel wurde angenommen, dass die Schlüssel des B-Baums eine maxima-le Länge besitzen. Andernfalls könnte schließlich kein B definiert werden, welches dieMaximalanzahl der Schlüssel in einem Speicherblock beschreibt. Falls die Schlüssellängenicht begrenzt ist, können String B-Bäume [FG99] verwendet werden. Untersuchungenhaben gezeigt, dass die Baumoperationen effizient in String B-Bäumen realisiert werdenkönnen. Weiterführende Informationen werden in [MSS03, Kapitel 7] gegeben.

37

Page 42: HEINZ NIXDORF INSTITUT Fakultät für Elektrotechnik ... Pottmeyer Memory Limitations in Artificial Intelligence ... Vitter hat gezeigt, dass viele in diesem Modell effiziente Entwicklungen

5 Wörterbücher mit Hashing

Werden Wörterbücher mit Hilfe von Hashing realisiert, wird die bestmögliche Perfor-mance für die elementaren Operationen (Einfügen, Löschen, Lookup) erreicht. In diesemKapitel wird vorausgesetzt, dass eine Hashfunktion h(x) existiert, so dass jeder möglicheHashwert mit der gleichen Wahrscheinlichkeit angenommen wird und er lediglich vomEingabeparameter x (und keinem anderen Element) abhängt. Da der errechnete Has-hwert beim Einfügen und Suchen eines Elementes verwendet wird, ist es erforderlich,dass die Hashfunktion für ein bestimmtes x stets den gleichen Hashwert liefert. Folglichwerden in der Praxis pseudozufällige Funktionen verwendet.Abschnitt 5.1 stellt Realisierungen für Wörterücher mit Hashing vor, welche im Erwar-tungswert eine gute Performance aufweisen. Bei einigen Anwendungen genügt jedochnicht die Effizienz im Erwartungswert und die schlechtest mögliche Performance wirdbetrachtet. Realisierung mit einer I/O-Operation im worst case werden in Abschnitt 5.2beschrieben. Sie nutzen den internen Speicher so aus, dass elementare Operationen auchim worst case mit nur einer I/O-Operation durchgeführt werden können.Bei wachsender Datenanzahl im Wörterbuch ist es erforderlich, die Anzahl der Hashwertezu erhöhen, die angenommen werden können. Abschnitt 5.3 stellt ein Möglichkeit für diedynamische Größenveränderung von Hashtabellen vor.

5.1 Effiziente Realisierungen im Erwartungswert

Klassische Hashingverfahren wie Linear Probing oder Hashing mit verketteten Listenweisen im Erwartungsfall auch eine gute Performance im externen Speicher auf. DieserAbschnitt liefert einen Überblick der zuvor genannten Verfahren. Für eine Übersichtweiterer Verfahren wird auf [Knu73, Abschnitt 6.4] verwiesen.Für beide Realisierungen wird im internen Speicher lediglich eine pseudozufällige Hash-funktion h gehalten, welche ein paar Bits an Speicherplatz benötigt.

5.1.1 Linear Probing

Das Einfügeverfahren von Linear Probing im internen Speicher verfährt so, dass derHashwert h(x) eine Position im Array bestimmt und das neue Element x in die erst freie

38

Page 43: HEINZ NIXDORF INSTITUT Fakultät für Elektrotechnik ... Pottmeyer Memory Limitations in Artificial Intelligence ... Vitter hat gezeigt, dass viele in diesem Modell effiziente Entwicklungen

Position ab dem berechneten Hashwert gesetzt wird. Analog dazu bestimmt im externenSpeicher der Hashwert den Speicherblock, welcher das Element aufnehmen soll. Hatdieser Block bereits seine Kapazitätsgrenze erreicht, wird versucht, das neue Element imdarauf folgenden Block einzufügen usw. Die Suche verläuft ähnlich, so dass der Hashwertberechnet wird und sukzessive jeder Block nach x durchsucht wird bis ein Block gefundenist, welcher nicht die volle Kapazität besitzt. Wurde ein nicht vollständig ausgefüllterSpeicherblock gefunden, der das gesuchte Element nicht enthält, impliziert dies, dassdas Element x nicht abgespeichert ist. Beim Löschen von Elementen, sind gegebenfallseinige Modifikationen erforderlich, da die Speicherblöcke nach einer Löschoperation denZustand besitzen sollen, welchen sie ohne dem vorigen Einfügen des gelöschten Elementesbesäßen.Da die Hashfunktion jeden Wert mit gleicher Wahrscheinlichkeit annimmt, sollten dieElemente auf den Speicherblöcken gleichverteilt sein. Das Ereignis, dass ein Block Bi

zuviele Elemente aufnehmen soll, scheint damit intuitiv als selten. Des Weiteren ist esnoch unwahrscheinlicher, dass der darauf folgende Block ebenfalls die volle Kapazitätbesitzt. Um die Gefahr zu reduzieren, dass ein Speicherblock voll ist, werden mehr alsdN/Be Blöcke verwendet. So hat jeder Block im Erwartungswert weniger als B Elementeund damit stets freie Kapazität für die Speicherung weiterer Elemente. Für diesen Aspektwird der Auslastungsfaktor verwendet:

Definition 5.1.

α mit 0 < α < 1 ist der Auslastungsfaktor einer Hashtabelle, wenn im Erwartungswertjeder Speicherblock der Hashtablle zu α% gefüllt ist. α wird an Hand der Größe derHashtabelle und den einzufügenden Elementen berechnet: Es gilt

Anzahl der Speicherblöcke in der Hashtabelle =N

αB. (11)

Der Aufwand für Lookups steht in Abhängigkeit zum Auslastungsfaktor, da dieserschließlich die Wahrscheinlichkeit bestimmt, dass ein Block überläuft.

Laufzeitanalyse 5.1.

Bei einem Auslastungsfaktor 0 < α < 1 beträgt die erwartete Anzahl von I/O-

39

Page 44: HEINZ NIXDORF INSTITUT Fakultät für Elektrotechnik ... Pottmeyer Memory Limitations in Artificial Intelligence ... Vitter hat gezeigt, dass viele in diesem Modell effiziente Entwicklungen

Operationen für ein Lookup gemäß [Knu73]

1 +1

(1− α)2 · 2Ω(B)(12)

Falls α − ε < 1, mit ε > 0 und B nicht zu klein ist, ist die erwartete Anzahl von I/O-Operationen nahezu 1. Die asymptotische Wahrscheinlichkeit, dass für ein Lookup k > 1

I/O-Operationen erforderlich sind, ist 2−Ω(B(k−1)).

Falls die maximale Anzahl von Elementen des Wörterbuches nicht bekannt ist, wird dieHashtabelle vergrößert, wenn der Auslastungsfaktor zu hoch wird. Abschnitt 5.3 stellteine Technik für die dynamische Vergrößerung von Hashtabellen vor.

5.1.2 Verkettete Listen

Beim Hashing mit verketteten Listen wird im internen Speicher das Arrayfeld mit Hilfeder Hashfunktion bestimmt. Jedes Arrayfeld verweist auf eine verkettete Liste, welchealle Elemente aufnimmt, die dem Arrayfeld zugewiesen wurden (siehe Abbildung 25).

Abbildung 25: Hashing mit verketteten Listen

Dieses Konzept wird im externen Speicher übernommen, so dass die Hashwerte einenSpeicherblock identifizieren, in dem eine verkettete Liste beginnt. Bei einem Lookupist dann eine I/O-Operation erforderlich, wenn jede verkettete Liste nicht mehr als B

Elemente besitzt. Die pseudozufällige Hashfunktion soll die Elemente gleichmäßig aufalle Speicherblöcke der Hashtabelle verteilen. Um die Wahrscheinlichkeit gering zu hal-ten, dass eine verkettete Liste mehr als B Elemente besitzt, werden wie beim LinearProbing N/(αB) Speicherblöcke genutzt, um einen Auslastungsfaktor α zu erreichen.

40

Page 45: HEINZ NIXDORF INSTITUT Fakultät für Elektrotechnik ... Pottmeyer Memory Limitations in Artificial Intelligence ... Vitter hat gezeigt, dass viele in diesem Modell effiziente Entwicklungen

Unter Verwendung des Auslastungsfaktors ist die verkettete Liste jedes Hashwertes imErwartungsfall so klein, dass sie nur einen einzigen Speicherblock benötigt (und damitein Lookup, Löschen oder Einfügen nur eine I/O-Operation kostet).

Laufzeitanalyse 5.2.

Für die Anzahl von I/O-Operationen ist die Wahrscheinlichkeit essentiell, dass bei k ≥1 zu einem beliebigen Speicherblock der Hashtabelle mit Größe N/(αB) mehr als kB

Schlüssel gehasht werden. Mit Hilfe von Chernoff Grenzen [HR90, Eq. 6] kann gezeigtwerden, dass diese Wahrscheinlichkeit höchstens

e−αB(k/α−1)2

3 (13)

beträgt.

Falls B groß ist und der Auslastungsfaktor α − ε < 1, mit ε > 0 , sind Überläufe sehrselten und im Erwartungsfall kostet eine Operation lediglich eine I/O-Operation. ImVergleich der Laufzeit für Linear Probing (siehe Laufzeit 5.1) mit der für verkettete Lis-ten, verkleinern sich die Wahrscheinlichkeiten mit k bei den verketteten Listen schnellerals beim Linear Probing. Jedoch existiert für die Verwaltung der verketteten Listen einMehraufwand.

5.2 Realisierungen mit einer I/O im Worst Case

Um eine Hashtabelle zu realisieren, die im worst case lediglich eine I/O-Operation be-nötigt, ist es erforderlich, den internen Speicher auszunutzen. Abschnitt 5.2.1 gibt einenÜberblick über zwei Ansätze, welche mit Hilfe des internen Speichers für die elementarenMethoden nie mehr als eine I/O-Operation benötigen. Ist eine höhrere Berechnungszeitvor dem Datenzugriff erlaubt, bieten Vorgänger-Wörterbücher (siehe Abschnitt 5.2.2)eine geeignete Alternative.Da meistens die Zeit für die Ausführung einer I/O-Operation und nicht die Anzahlvon I/O-Operationen ausschlaggebend ist, können als dritte Alternative zwei I/O-Operationen parallel ausgeführt werden. Zwar führt dies zu doppelten Kosten, jedochwird nicht mehr Zeit als für eine I/O-Operation benötigt. Abschnitt 5.2.3 stellt eineRealisierung mit diesem Konzept vor.

41

Page 46: HEINZ NIXDORF INSTITUT Fakultät für Elektrotechnik ... Pottmeyer Memory Limitations in Artificial Intelligence ... Vitter hat gezeigt, dass viele in diesem Modell effiziente Entwicklungen

5.2.1 Ausnutzung von internen Speicher

Oftmals kann eine gute Effizienz für die Datenhaltung im externen Speicher erreicht wer-den, wenn der interne Speicher verwendet wird. Im Kapitel 3 wurde der interne Speicherals Buffer verwendet, um Elemente zwischenzuspeichern und nicht direkt in den externenSpeicher auszulagern. Eine andere Alternative für die Nutzung des internen Speichersist es, darin Verwaltungsdaten zu halten, um einen effizienten Zugriff auf die Daten imexternen Speicher zu ermöglichen. Steht ausreichend interner Speicher zur Verfügung,kann ein Lookup im Wörterbuch stets mit nur einer einzigen I/O-Operation durchge-führt werden. Die Konzepte „Überlaufgebiete“ sowie „Perfektes Hashing“ ermöglichendiese bestmögliche Effizienz.

Überlaufgebiete

Die Idee der Überlaufgebiete ist es, die Schlüssel in einem Wörterbuch im internenSpeicher zu halten, welche einem bereits vollen Speicherblock zugeordnet wurden. Sowerden Überläufe vermieden, indem die betreffenden Daten im internen Speicher abge-legt werden. Es ist offensichtlich, dass der interne verfügbare Speicher eine gewisse Größebesitzen muss, um alle möglichen Überläufe auffangen zu können. Kann der verfügbareinterne Speicher 2−Ω(B)N Schlüssel-Wert Paare aufnehmen, so wird bei einem konstan-ten Auslastungsfaktor α < 1 nur eine I/O-Operation für einen Lookup benötigt. Dennfür eine Konstante c(α) = Ω(1−α) ist die Wahrscheinlichkeit für die Abspeicherung vonmehr als 2−Ω(B)N Schlüssel-Wert Paaren im internen Speicher so gering, dass der Auf-wand akzeptabel ist, beim Überlauf des internen Speichers alle Daten mit einer neuenHashfunktion neu zu verteilen.Die Überlaufgebiete können auch im externen Speicher gehalten werden. Um Lookupsmit nur einer I/O-Operation durchführen zu können, bedarf es Datenstrukturen im in-ternen Speicher, die zum einen die übergelaufenen Blöcke identifizieren und zum anderenden Datenzugriff auf Elemente von übergelaufenen Blöcken mit nur einer I/O-Operationermöglichen. Die Identifizierung von übergelaufenen Blöcken kann mit Hilfe eines Wör-terbuches im internen Speicher erfolgen, welches die betreffenden Blocknummern bein-haltet. Da die Wahrscheinlichkeit, dass ein Block überläuft, bei O

(2−c(α)B

)liegt, ist

es im Erwartungswert erforderlich, O(2−c(α)B

)Indizes von übergelaufenen Speicherblö-

cken zu halten. Der benötigte interne Speicherplatz hängt von der Länge der Indizes ab,welche wiederum auf der Anzahl der Daten N des Wörterbuches basiert. Somit werden

42

Page 47: HEINZ NIXDORF INSTITUT Fakultät für Elektrotechnik ... Pottmeyer Memory Limitations in Artificial Intelligence ... Vitter hat gezeigt, dass viele in diesem Modell effiziente Entwicklungen

im Erwartungswert O(2−c(α)BN log N

)Bits für die Sicherung der Indizes im internen

Speicher benötigt. Die zweite Anforderung, den Datenzugriff auf übergelaufene Blöckemit nur einer I/O-Operation zu realisieren, kann durch ein zusätzliches Wörterbuch er-möglicht werden. Die Daten, welche zu einem übergelaufenen Block zugeordnet wurden,werden in einem anderen Wörterbuch gehalten, welches ein Lookup mit nur einer I/O-Operation durchführt. Die Daten übergelaufener Blöcke im ursprünglichen Wörterbuchwerden in diesem Fall nicht mehr betrachtet. Die Anzahl der im zusätzlichen Wörterbuchabzuspeichernden Elemente liegt mit einer hohen Wahrscheinlichkeit bei O

(2−c(α)BN

).

Perfektes Hashing

Beim perfekten Hashing existieren keine Überläufe. Mairson [Mai83] entwickelte eineB−perfekte Hashfunktion p : K → 1, . . . , dN/Be, welche höchstens B Eingabepara-meter einem Hashwert zuordnet. Damit erhält jeder Speicherblock höchstens B Elementeund die Kapazität keines Blockes ist zu gering. Liegt die Hashfunktion im internen Spei-cher, so bedarf es für einen Lookup lediglich einer I/O-Operation, da jedes Element indem Speicherblock zu finden ist, welches die Hashfunktion berechnet. Es wurde gezeigt,dass B-perfekte Hashfunktionen existieren und in vereinfachter SchreibweiseO

(N log(B)

B

)Bits internen Speicherplatz benötigt. Dies ist optimal, wenn dN/Be Speicherblöcke undeine beliebige Schlüsselmenge verwendet werden. Dieses Konzept hat jedoch einige signi-fikante Nachteile, da sowohl der benötigte Platz als auch die Zeit für die Berechnung derHashfunktion extrem hoch sind. Zudem scheint es schwierig, eine dynamische Versionbezüglich der Datenanzahl N zu entwickeln. Aus diesen Gründen ist Mairsons Verfah-ren praktisch kaum einsetzbar. Fagin et al. [FNPS79] haben ein B-perfektes Hashingentwickelt, welches praktisch einsetzbar ist und nah an die untere Grenze von Mairsongelangt. Dieses Verfahren wird erweiterbares Hashing genannt.

5.2.2 Vorgänger-Wörterbuch

Vorgänger-Wörterbücher benötigen weniger internen und externen Speicherplatz alsB-perfekte Hashingmethoden. Jedoch ist der Berechnungsaufwand des zugehörigenSpeicherblocks nicht konstant sondern beträgt O(log log N) pro Wörterbuchmethode.Das Vorgänger-Wörterbuch unterstützt Vorgänger-Anfragen in einer SchlüsselmengeP ⊆ 0, 1r, welche für jeden Schlüssel x ∈ 0, 1r den größten Schlüssel y ∈ P mit

43

Page 48: HEINZ NIXDORF INSTITUT Fakultät für Elektrotechnik ... Pottmeyer Memory Limitations in Artificial Intelligence ... Vitter hat gezeigt, dass viele in diesem Modell effiziente Entwicklungen

y ≤ x zuzüglich weiteren Informationen über den Speicherort zurückgibt. Für die Reali-sierung des Wörterbuches im externen Speicher werden die Schlüssel der abzuspeichern-den Daten in einer verketteten Liste abgelegt. Die Sortierung in der Liste erfolgt aufBasis der Hashwerte. Für jeden Speicherblock Bi der verketteten Liste wird im internenVorgänger-Wörterbuch das Element mit dem kleinsten Schlüssel in Bi abgespeichert.Als zugehörige Informationen des Schlüssels wird im Vorgänger-Wörterbuch ein Zeigerauf den Speicherblock gesichert. Die Schlüsselmenge P ist somit eine Teilmenge derSchlüsselmenge des externen Wörterbuches.Für ein Lookup des Elementes x wird eine Vorgänger-Anfrage durchgeführt, um auf Basisvon h(x) den kleinsten Schlüssel des gleichen Speicherblockes zu finden. Der zugehörigeZeiger des Vorgängers von x ermöglicht einen Zugriff auf den gesuchten Speicherblockmit einer I/O-Operation. Einfügen und Löschen erfordern eine Modifikation der Datenin einem Speicherblock der verketteten Liste. Falls das eingefügte oder gelöschte Elementder kleinste Schlüssel in einem Block ist, ist zudem eine konstanten Anzahl von Updatesdes Vorgänger-Wörterbuches erforderlich.

Laufzeitanalyse 5.3.

Das interne Vorgänger-Wörterbuch benötigt höchstens⌈

N(1−ε)B

⌉Schlüssel mit ε > 0.

Wenn die Hashwerte in einem Intervall liegen, so dass 3 log N ≤ r = O(log N), be-nötigen die Hashwerte O(log N) Bits. Unter Verwendung von van Emde Boas Bäumenkönnen Vorgänger-Anfragen in O(log log N) Zeit ausgeführt werden [Wil83]. Modifika-tionen benötigen im Erwartungswert die gleiche Zeit.Für ein Lookup wird nur eine I/O-Operation benötigt, jedoch geht dem Datenzugriffeine Berechnungszeit von O(log log N) voraus. Diese Zeit ist in der Praxis meistensvernachlässigbar. Die Nutzung des externen Speichers ist gewöhnlich sehr nah an derOptimalität und O(N/B) interner Speicherplatz werden verbraucht.

5.2.3 2 Parallele I/O-Operationen

Da in den meisten Fällen die Zeitspanne und nicht der Aufwand für die Durchführungvon I/O-Operationen betrachtet wird, ist ein anderer Ansatz zwei I/O-Operationen par-allel auszuführen. Schließlich benötigt eine parallele Ausführung zweier I/O-Operationen

44

Page 49: HEINZ NIXDORF INSTITUT Fakultät für Elektrotechnik ... Pottmeyer Memory Limitations in Artificial Intelligence ... Vitter hat gezeigt, dass viele in diesem Modell effiziente Entwicklungen

genauso viel Zeit wie eine einzige I/O-Operation. Ein paralleler Zugriff auf externen Spei-cher ist möglich, wenn er in mindestens zwei Teile aufgeteilt wird, wie zum Beispiel durchunabhängige Festplatten oder Arbeitsspeicherbänke. Azar et al [ABKU00] entwickeltendas so genannte two-way chaining, welches auf parallelen I/O-Operationen basiert. Dabeiwerden zwei pseudozufällige Hashfunktionen h1 und h2 für zwei Hashtabellen verwendet.Die Hashtabellen werden in den getrennten Teilen des externen Speichers gehalten. Fürdie Suche nach Schlüssel x werden parallel die Blöcke h1(x) und h2(x) untersucht. Beieinem Ladefaktor α << 1 und einer angemessenen Blockgröße, ist die Wahrscheinlich-keit groß, dass sich das Element x in einen dieser Blöcke befindet und somit eine derparallelen I/O-Operationen erfolgreich ist. Um eine ausgewogene Verteilung der Datenin beide Hashtabellen zu erreichen, wird ein neues Element y in den Block hi(y) miti ∈ 1, 2 eingefügt, welches weniger Elemente besitzt. In [BCSV00] haben Berenbrinket al. gezeigt, dass die Wahrscheinlichkeit für einen Überlauf bei einer EinfügeoperationN/22Ω((1−α)B) beträgt. Da im Nenner 22Ω((1−α)B) steht, sinkt die Fehlerwahrscheinlichkeitdoppelt exponentiell mit der durchschnittlichen Anzahl von freien Plätzen in jedem Block.Der konstante Faktor (1 − α)B ist größer als Eins. Experimentell wurde gezeigt, dasssogar für wenig freie Plätze in jedem Block, die Wahrscheinlichkeit für einen Üerlaufsehr klein ist [MB].

5.3 Anpassung der Hashtabellengröße

Ein wichtiges Konzept der vorigen Abschnitten ist die Nutzung eines Auslastungsfak-tors α, um eine geringe Wahrscheinlichkeit von Überläufen zu erhalten. So werden mehrSpeicherblöcke für die Hashtabelle allokiert als minimal für die Sicherung der Eingabeda-ten benötigt werden. Da mit Hilfe des Auslastungsfaktors α < 1 die Wahrscheinlichkeitfür Überläufe sehr gering ist, können Hashtabellenoperation mit einer I/O-Operationdurchgeführt werden. Ist die Anzahl von Eingabedaten konstant und bekannt, kann derLadefaktor bei der Erzeugung der Hashtabelle berechnet werden. Wenn die Anzahl derEingabedaten signifikant schwankt, ist es aus Speichergründen nicht effizient, die ma-ximale Anzahl von Eingabedaten für die Hashtabellengröße zu Grunde zu legen. Einedynamische Anpassung der Hashtabellengröße ist eine in Bezug auf den Speicherplatzeffizientere Vorgehensweise. Die dynamische Vergrößerung oder Verkleinerung ist eben-so notwendig, wenn die maximale Anzahl der Eingabedaten nicht vor der Initialisierung

45

Page 50: HEINZ NIXDORF INSTITUT Fakultät für Elektrotechnik ... Pottmeyer Memory Limitations in Artificial Intelligence ... Vitter hat gezeigt, dass viele in diesem Modell effiziente Entwicklungen

der Hashtabelle definiert werden kann. Dieser Abschnitt stellt eine Möglichkeit für dieAnpassung der Hashtabellengröße dar. Eine Vergrößerung der Hashtabelle ist notwen-dig, wenn der Auslastungsfaktors überschritten wird und damit die Wahrscheinlichkeitfür Überläufe anwächst. Steigt diese Wahrscheinlichkeit, ist es unwahrscheinlicher nureine I/O-Operation pro Hashtabellenmethode zu benötigen. Wird der Auslastungsfak-tors deutlich unterschritten, beeinflusst dieses nicht die Zugriffsperformance. Jedoch wirdmehr Speicherplatz verbraucht, als benötigt wird. Folglich soll dieser Fall ebenfalls durcheine Anpassung der Hashtabellengröße behandelt werden.Die trivialste Lösung für die Änderung der Hashtabellengröße ist es, die Größe anzupas-sen, eine andere Hashfunktion zu wählen und alle Elemente mit einem rehash neu einzu-fügen. Diese Vorgehensweise ist jedoch nicht effizient, da beim rehash für viele Elementeder Hashtabelle eine I/O-Operation für das Einfügen in einem anderen Speicherblockbenötigt wird. In [AV88] wurde dieses Permutationsverfahren mit dem Ergebnis unter-sucht, dass Θ

(NB

logMB

(NB

))I/O-Operationen erforderlich sind. Wenn N nicht extrem

groß ist, entspricht diese Performance O(N) I/O-Operationen. Um eine effiziente Lösungbeim der Größenanpassung für beliebig große Datenmengen zu erreichen, wäre ein kon-stanter Aufwand wünschenswert. Folgich liegt die Herausforderung bei der Anpassungder Hashtabelle darin, eine Reorganization aller bereits enthaltenen Daten zu vermeidenund die Anpassung effizient durchzuführen.Das lineare Hashing von Litwin [Lit80] realisiert eine schrittweise Vergrößerung oderVerkleinerung von Hashtabellen. Dei Berechnung des Hashwertes erfolgt mit einer über-geordneten Mutterfunktion die eine Vielzahl von Hashwerten liefert. Dieser Hashwertwird entweder übernommen, wenn er nicht größer als die aktuelle Tabellengröße ist. An-dernfalls wird der Hashwert k verkleinert mit Hilfe von k − 2b−1, wobei b = dlog re gilt.Für eine effiziente Realisierung der Vergrößerung wird ausgenutzt, dass der Rückgabe-wert bei größeren Werten als r der Form k− 2b−1 erfolgte. Da der neue Block k = r + 1

entspricht, müssen lediglich Elemente im Block (r + 1) − 2b−1 neu zugeordnet werden.Es ist wichtig zu beachten, dass nicht alle Elemente des Blockes (r + 1) − 2b−1 in denneuen Block r + 1 verlagert werden. Es werden nur die Elemente in Block r + 1 gesetzt,die dort eingefügt worden wären, falls zuvor die Tabelle r + 1 Blöcke gehabt hätte.Das Verkleinern der Hashtabelle verläuft ähnlich. Lediglich die Elemente im letzten Blockr müssen auf die anderen r − 1 Blöcke verteilt werden. Dazu wird von allen Elementender Wert der Stamm-Hashfunktion berechnet, mit r − 1 verglichen und die Daten demBlock zugeordnet, der dem neuen Rückgabewert entspricht.

46

Page 51: HEINZ NIXDORF INSTITUT Fakultät für Elektrotechnik ... Pottmeyer Memory Limitations in Artificial Intelligence ... Vitter hat gezeigt, dass viele in diesem Modell effiziente Entwicklungen

Dieses Verfahren für die Anpassung der Hashtabellengröße ist problematisch, wenn r

keine Potenz von 2 ist. Da die Tabellengröße immer um Eins erhöht oder reduziertwird, ist die aktuelle Tabellengröße oftmals keine 2er Potenz. Liegt keine 2er Potenz zuGrunde, dann werden die Elemente nicht gleichmäßig auf die Blöcke der Hashtabelleverteilt. Damit ist die Wahrscheinlichkeit für Überläufe deutlich höher, was vermiedenwerden sollte. Um stets eine Gleichverteilung auf die Blöcke zu erhalten, bedarf es ei-ner uniformen Hashfunktion bei jeder Tabellengröße. Dafür erfolgt die Anpassung derHashtabellengröße nicht um Eins, sondern um einen Faktor 1 + ε mit ε > 0 [sP02].

47

Page 52: HEINZ NIXDORF INSTITUT Fakultät für Elektrotechnik ... Pottmeyer Memory Limitations in Artificial Intelligence ... Vitter hat gezeigt, dass viele in diesem Modell effiziente Entwicklungen

6 Zusammenfassung

Da sich die verschiedenen Speichertypen in Schnelligkeit und Kosten deutlich unterschei-den, werden für das Ablegen von Daten oftmals verschiedene Speichertypen verwendet(zum Beispiel Arbeitsspeicher und Hauptspeicher). Um beliebige Kombinationen ver-schiedener Speichertypen einfach zu modellieren, hat sich das externe Speichermodell alsgeeignet erwiesen, da seine geringe Komplexität Vergleiche mehrere Entwürfe ermöglicht.Die Datenbereitstellung des externen Speichermedium wird als Flaschenhals der Perfor-mance angesehen, da die Bandbreite es erlaubt, mehrere Datenelemente gleichzeitig zuübermitteln. In dieser Seminararbeit wurde ein Datentransfer von B Datenelementenmit einer I/O-Operation definiert. Das Ziel für die Datenauslagerung im externen Spei-cher ist es somit, möglichst wenige I/O-Operation zu benötigen. Aus dieser Zielsetzungfolgt, dass bei der Nutzung von internen Datenstrukturen für die externe Speicherung invielen Fällen eine I/O-Operation pro Datenelement erforderlich ist. Jedoch können proI/O-Operation B Elemente ausgetauscht werden, so dass die internen Implementierun-gen von Stack, Queue und Wörterbuch durch effizientere Lösungen im externen Speicherersetzt werden können. Diese Seminararbeit stellt Realisierungen dieser Datenstrukturenfür die Nutzung von externem Speicher vor. Der externe Stack und die externe Queuenutzen einen Teilbereich des internen Speichers als Buffer, um eine amortisierte Laufzeitvon 1

BI/O-Operationen zu benötigen. Dieser Wert ist auf Grund der Bandbreite von B

die bestmögliche Performance.Für die Implementierung eines Wörterbuches können B-Bäume oder Hashing verwendetwerden. Die Realisierung mit Hashing nutzt ebenfalls einen Teil des internen Speichersund ist sehr effizient, da für jedes Lookup lediglich eine I/O-Operation aufgebrachtwerden muss. Dies wird dadurch erreicht, dass uniforme Hashfunktionen verwendet wer-den und zudem mehr Blöcke als die minimale erforderliche Anzahl genutzt werden. EinAuslastungsfaktor α wird definiert, um die Wahrscheinlichkeit gering zu halten, dassÜberläufe auftreten. Sind insgesamt deutlich mehr oder weniger Elemente in der Hash-tabelle enthalten als durch den Auslastungsfaktor definiert, kann die Hashtabellengrößedynamisch angepasst werden.Bei der Realisierung eines Wörterbuches mit einem B-Baum entspricht die Anzahl derI/O-Operationen der Baumtiefe. Es ist wichtig, dass bei der Nutzung von B-Bäumeneine Gesamtordnung der Schlüsselwerte gefordert wird, da das Einfügen der Elementedieser Ordnung unterliegt. In der Seminararbeit wurden der Fokus auf gewichtete B-

48

Page 53: HEINZ NIXDORF INSTITUT Fakultät für Elektrotechnik ... Pottmeyer Memory Limitations in Artificial Intelligence ... Vitter hat gezeigt, dass viele in diesem Modell effiziente Entwicklungen

Bäume gelegt, die bei einer Speicherung von N Datenelemente und einer Blockgröße B

eine maximale Baumhöhe von 1 +⌈logB/8 N

⌉besitzen. Für einzelne Lookup Operatio-

nen und große N ist die Realisierung mit Hashing effizienter, jedoch bieten B-Bäume dieOption andere Anfragetypen, wie das Range Reporting (siehe Abschnitt 4.2.4), schnellerauszuführen. Wird die Wurzel im internen Speicher gehalten, ist die Anzahl von I/O-Operationen auch bei vielen Datenelementen gering, da ein Knoten einen Ausgangsgradzwischen B

32und B

2besitzt. Folglich sollte die genutzte Implementierung des Wörterbu-

ches abhängig von den gefordertem Funktionsumfang gewählt werden.

49

Page 54: HEINZ NIXDORF INSTITUT Fakultät für Elektrotechnik ... Pottmeyer Memory Limitations in Artificial Intelligence ... Vitter hat gezeigt, dass viele in diesem Modell effiziente Entwicklungen

Literatur

[ABKU00] Azar, Yossi, Andrei Z. Broder, Anna R. Karlin und Eli Upfal:Balanced Allocations. SIAM Journal on Computing, 29(1):180–200, 2000.

[AM99] Arge, Lars und Peter Bro Miltersen: On showing lower bounds forexternal-memory computational geometry problems. Seiten 139–159, 1999.

[Arg95] Arge, Lars: The Buffer Tree: A New Technique for Optimal I/O-Algorithms (Extended Abstract). In: WADS ’95: Proceedings of the 4th In-ternational Workshop on Algorithms and Data Structures, Seiten 334–345,London, UK, 1995. Springer-Verlag.

[Arg04] Arge, Lars: External Geometric Data Structures. In: COCOON, Seite 1,2004.

[AV88] Aggarwal, Alok und Jeffrey S. Vitter: The input/output complexityof sorting and related problems. Commun. ACM, 31(9):1116–1127, 1988.

[AV96] Arge, Lars und Jeffrey Scott Vitter: Optimal Dynamic Interval Ma-nagement in External Memory (extended abstract). In: IEEE Symposium onFoundations of Computer Science, Seiten 560–569, 1996.

[BCSV00] Berenbrink, Petra, Artur Czumaj, Angelika Steger und Bert-hold Vöcking: Balanced allocations: the heavily loaded case. Seiten 745–754, 2000.

[BGO+96] Becker, Bruno, Stephan Gschwind, Thomas Ohler, BernhardSeeger und Peter Widmayer: An asymptotically optimal multiversionB-tree. The VLDB Journal, 5(4):264–275, 1996.

[BM72] Bayer, Rudolf und Edward M. McCreight: Organization and Main-tenance of Large Ordered Indices. Acta Inf., 1:173–189, 1972.

[Com79] Comer, Douglas: The Ubiquitous B-Tree. ACM Comput. Surv.,11(2):121–137, 1979.

[DKM+94] Dietzfelbinger, Martin, Anna Karlin, Kurt Mehlhorn, Fried-helm Meyer auf der Heide, Hans Rohnert und Robert EndreTarjan: Dynamic Perfect Hashing: Upper and Lower Bounds. SIAM J.Comput., 23(4):738–761, 1994.

[DSST89] Driscoll, James R., Neil Sarnak, Daniel D. Sleator und Ro-bert E. Tarjan: Making data structures persistent. J. Comput. Syst. Sci.,38(1):86–124, 1989.

50

Page 55: HEINZ NIXDORF INSTITUT Fakultät für Elektrotechnik ... Pottmeyer Memory Limitations in Artificial Intelligence ... Vitter hat gezeigt, dass viele in diesem Modell effiziente Entwicklungen

[FG99] Ferragina, Paolo und Roberto Grossi: The string B-tree: a new datastructure for string search in external memory and its applications. Journalof the ACM, 46(2):236–280, 1999.

[FHL+01] Ferdinand, Christian, Reinhold Heckmann, Marc Langenbach,Florian Martin, Michael Schmidt, Henrik Theiling, StephanThesing und Reinhard Wilhelm: Reliable and Precise WCET Deter-mination for a Real-Life Processor. In: EMSOFT ’01: Proceedings of theFirst International Workshop on Embedded Software, Seiten 469–485, Lon-don, UK, 2001. Springer-Verlag.

[FNPS79] Fagin, Ronald, Jürg Nievergelt, Nicholas Pippenger und H. Ray-mond Strong: Extendible Hashing - A Fast Access Method for DynamicFiles. ACM Trans. Database Syst., 4(3):315–344, 1979.

[HM82] Huddleston, Scott und Kurt Mehlhorn: A New Data Structure forRepresenting Sorted Lists. Acta Inf., 17:157–184, 1982.

[HR90] Hagerup, Torben und C. R&#252;b: A guided tour of Chernoff bounds.Inf. Process. Lett., 33(6):305–308, 1990.

[Knu73] Knuth, Donald E.: The Art of Computer Programming, Volume I: Fun-damental Algorithms, 2nd Edition. Addison-Wesley, 1973.

[Lit80] Litwin, W.: Linear hashing: A new tool for files and tables addressing. In:Proceedings of International Conference On Very Large Data Bases (VLDB’80), Seiten 212–223. IEEE Computer Society Press, 1980.

[Mai83] Mairson, Harry G.: The Program Complexity of Searching a Table. In:FOCS, Seiten 40–47, 1983.

[MB] Mitzenmacher, Michael und Andrei Broder: Using Multiple HashFunctions to Improve IP Lookups. Seiten 1454–1463.

[MSS03] Meyer, Ulrich, Peter Sanders und Jop F. Sibeyn (Herausgeber):Algorithms for Memory Hierarchies, Advanced Lectures [Dagstuhl ResearchSeminar, March 10-14, 2002], Band 2625 der Reihe Lecture Notes in Com-puter Science. Springer, 2003.

[RL90] Rivest, Ronald L. und Charles E. Leiserson: Introduction to Algo-rithms. McGraw-Hill, Inc., New York, NY, USA, 1990.

[sP02] Östlin, A. und R. Pagh: Rehashing rehashed. Technischer Bericht, 2002.

[ST86] Sarnak, Neil und Robert E. Tarjan: Planar point location using per-sistent search trees. Commun. ACM, 29(7):669–679, 1986.

51

Page 56: HEINZ NIXDORF INSTITUT Fakultät für Elektrotechnik ... Pottmeyer Memory Limitations in Artificial Intelligence ... Vitter hat gezeigt, dass viele in diesem Modell effiziente Entwicklungen

[Vit01] Vitter, Jeffrey Scott: External memory algorithms and data structu-res: dealing with massive data. ACM Computing Surveys, 33(2):209–271,2001.

[vN45] Neumann, John von: First Draft of a Report on the EDVAC. TechnischerBericht, 1945.

[VS94] Vitter, Jeffrey Scott und E. A. M. Shriver: Algorithms for parallelmemory, I: Two-level memories. Algorithmica, 12(2/3):110–147, 1994.

[Wil83] Willard, Dan E.: Log-Logarithmic Worst-Case Range Queries are Possiblein Space Theta(N). Inf. Process. Lett., 17(2):81–84, 1983.

52

Page 57: HEINZ NIXDORF INSTITUT Fakultät für Elektrotechnik ... Pottmeyer Memory Limitations in Artificial Intelligence ... Vitter hat gezeigt, dass viele in diesem Modell effiziente Entwicklungen

A Survey of Techniques forDesigning I/O-Efficient Algorithms

Oliver Buschjost

4. Februar 2007

1 Einleitung

Bei der Arbeit mit großen Datenmengen treten Geschwindigkeitsprobleme auf, diedurch zu haufige I/O-Zugriffe verursacht werden. Das Problem entsteht, da nichtalle relevanten Daten im Hauptspeicher vorgehalten werden konnen und immerwieder neu von den langsamen Massenspeichern angefordert werden mussen.

Um dieses Problem zu verringern kann an mehreren Stellen angesetzt werden:einerseits bei den Algorithmen selber, indem der Ablauf mehr auf die Struktur derDaten auf dem Massenspeicher eingeht. Andererseits lasst sich durch eine intelli-gente Speicherung der Daten dem zu haufigen nachladen entgegenwirken.

Im Folgenden sollen zwei Methoden, das List-Ranking und das Graph-Blocking,exemplarisch herausgegriffen werden, um I/O Effiziente Algorithmen zu entwickeln.Fur die Grundlagen wie das effiziente Sortieren von externen Daten mit einem mo-difizierten Merge-Sort sowie Techniken wie die Simulation von PRAM-Algorithmenfur externe Daten und den Ansatz des Time-Forward Processing sei auf das Paper[1] verwiesen.

Es wird mit dieser Notation gearbeitet:

N Große der Eingabedaten

B Große eine Blocks auf dem Massenspeicher

M Große des zur Verfugung stehenden internen Speichers

2 List Ranking

Haufig wird die Reihenfolge von Daten in einer Liste benotigt. Dies entspricht demProblem des List Ranking, bei welchem der Abstand von allen Elementen zum Endeder Liste berechnet wird. Intuitiv denkt man bei Listen meist daran, dass die Ele-mente geordnet in Reihenfolge der Liste vorliegen und mit einfachem Durchlaufennummeriert werden konnen (siehe Abbildung 1). Dies ist leider in der Praxis nichtder Fall.

1 2 3 4 5 6

Abbildung 1: optimal angeordnete verkettete Liste

Fur kleine Datenmengen, die im internen Speicher vorgehalten werden konnen,kann der naive Ansatz des Durchlaufens das Problem (auf einer Ein-Prozessor Ma-schine) effizient losen. In diesem Fall wird die Arbeit O(n) (Zeitdauer und Anzahlbenotigter Operationen) aufgewendet. Dies Verfahren skaliert aber nicht, lasst sich

53

Page 58: HEINZ NIXDORF INSTITUT Fakultät für Elektrotechnik ... Pottmeyer Memory Limitations in Artificial Intelligence ... Vitter hat gezeigt, dass viele in diesem Modell effiziente Entwicklungen

also nicht auf mehrere Prozessoren verteilen, um die Verarbeitungszeit zu reduzie-ren. Es gibt daher mehrere Algorithmen, die das List-Ranking Problem auf andereWeise parallelisiert losen und dafur Zeit O(log(n)) (bei allerdings mit O(n log(n))insgesamt mehr auszufuhrenden Operationen) benotigen.

Das Problem den naiven Algorithmus auf grosse extern gespeicherte Datenmen-gen anzuwenden ist ein anderes, die Losung aber ahnlich zu den parallelisiertenVerfahren.

Das Problem bei den externen Daten ist, dass im besten Fall theoretisch nurO(N/B) I/O Operationen benotigt werden (wenn die Daten korrekt als Sequenzvorliegen), was aber meist nicht der Fall ist. Die Daten konnen so platziert sein,dass fur jeden nachsten Knoten ein neuer Block gelesen werden muss, also ganzeO(N) I/O Operationen stattfinden mussen. Ein Beispiel fur eine solche Anordnungist in Abbildung 2 dargestellt.

5 2 6 4 1 3

Abbildung 2: in Blocken schlecht angeordnete verkettete Liste

Das hier vorgestellte Verfahren lost nicht nur das List-Ranking Problem, sondernein Allgemeineres Problem, welches haufig als List-Ranking bezeichnet wird, dabei der Losung die Ergebnisse fur das List-Ranking gleich mitgeliefert werden. Eswerden dabei zur Losung die Techniken des Pointer-Jumping und das zeitweiseEntfernen von unabhangigen Mengen angewendet, um eine Laufzeit von O(sort(N))I/O-Zugriffen zu erreichen.

Die Verallgemeinerung des Problems fuhrt eine Funktion λ ein, welche definiertist als: x1, · · · , xn → X, und die Knoten beschriftet. Zusatzlich wird eine Multi-plikation uber X definiert als: ⊗ : X ×X → X. Zusatzlich wird eine Permutationder Knoten definiert als σ : [1, N ] → [1, N ] so, dass der Kopf der Liste als xσ(1)

bezeichnet wird und fur alle anderen Knoten gilt, dass Nachfolger(xσi) = xσi+1 (∀1 ≤ i < N).

Auf Basis dieser Funktionen wird jedem Knoten eine Beschriftung mit der Funk-tion φ(xi) so zugewiesen, dass die folgenden Bedingungen erfullt sind:

• φ(xσ(1)) = λ(xσ(1))

• φ(xσ(i)) = φ(xσ(i−1))⊗ λ(xσ(i)) ∀ 1 < i ≤ N

Die Funktion φ(xi) ist also so definiert, dass der erste Knoten der Liste seinLabel behalt und nachfolgende Knoten das Label ihres Vorgangers multipliziert mitIhrem eigenen bekommen.

Dieses verallgemeinerte Problem kann durch das Wechseln der initialen Knoten-label und der Berechnungsfunktion zum Losen von einer Vielzahl von Problemenverwendet werden: die Nutzung zur Berechnung von Prafix- und Suffix-Summenoder von beliebigen Funktionen, die uber die komplette Liste angewendet werden,ist ebenso moglich, wie die Nutzung zum Durchlaufen von Baumen, um eine Pre-Order Nummerierung der Knoten zu bestimmen.

54

Page 59: HEINZ NIXDORF INSTITUT Fakultät für Elektrotechnik ... Pottmeyer Memory Limitations in Artificial Intelligence ... Vitter hat gezeigt, dass viele in diesem Modell effiziente Entwicklungen

Der Ablauf des dafur notigen Algorithmus lasst sich in drei Teile gliedern:

1. Aufteilen in kleinere Probleme durch Herauslosen von Knoten

2. Losen der Teilprobleme

3. Zusammenfugen der Teilprobleme zur Gesamtllosung

Es wird davon ausgegangen, dass die Multiplikationsfunktion assoziativ ist - dieReihenfolge in der die Knoten verarbeitet werden also fur das Endergebnis keineRolle spielt. Der Beweis hierfur wird am Ende nachgeliefert. Fur die Aufteilung desProblems in kleine Teilprobleme ist diese Eigenschaft wichtig. Hier wird die Ver-fahren der Graph-Verkleinerung1 in Kombination Pointer-Jumping verwendet. DasPointer-Jumping ist wichtig, da in fruheren Ansatzen bei der Parallelisierung Pro-bleme beim gleichmaßigen Verteilen der Daten auf die Prozessoren auftraten, weildie bei der Graph-Verkleinerung ’entfernten’ Knoten teilweise dennoch von den Pro-zessoren angefasst werden mussten, was zu Laufzeitverlusten fuhrte. In Abbildung3 ist das Pointer-Jumping dargestellt. Es wird dabei ein alternativer Pfad durchdie Knoten aufgebaut, der die gerade nicht benotigten Knoten direkt uberspringt.Weitere Informationen zu den durch das Pointer-Jumping eingefuhrten Vorteilenlassen sich [4] entnehmen.

Abbildung 3: Uberbrucken von großeren Strecken beim Pointer-Jumping

Die aus dem Gesamtsystem zu entfernenden Knoten mussen einer vom Rest un-abhangigen Teilmenge angehoren. Eine unabhangige Menge in einer Liste bedeutet,dass der Nachfolger jedes Knotens sich in der jeweils anderen Menge befinden muss(Abbildung 4).

Abbildung 4: Zwei unabhangige Mengen in einer Liste

Ein Ziel bei der Bestimmung der unabhangigen Menge I ist eine bestimmteMindestgroße, namlich |I| = Ω(N). Zur Bestimmung dieser unabhangigen Mengekonnen verschiedene Verfahren mit unterschiedlichen Laufzeiten verwendet werden.

1engl.: graph contraction

55

Page 60: HEINZ NIXDORF INSTITUT Fakultät für Elektrotechnik ... Pottmeyer Memory Limitations in Artificial Intelligence ... Vitter hat gezeigt, dass viele in diesem Modell effiziente Entwicklungen

Hierbei wurden oft randomisierte Verfahren oder eine 3-Farbung eingesetzt (siehe[2, 5.2ff] ). Es gibt aber auch die Moglichkeit das Problem in O(sort(N)) I/O-Operationen zu losen durch Verwendung des in [1, 3.5.1] beschriebenen Algorithmuszur Berechnung der großten unabhangigen Menge, da eine solche in einer Listeimmer mindestens N/3 betragt2.

Nun werden die so bestimmten Knoten der Teilmenge I mittels Pointer-Jumpingaus der Liste entfernt. Angenommen die Knoten X, Y und Z mit Y ∈ I sind indieser Reihenfolge in der Liste verknupft, so ist der Knoten Y der zu entfernende.Es wird jetzt der Next Zeiger des Knoten X mit dem Inhalt des Next-Zeigers vonKnoten Y uberschrieben. Damit zeigt X fortan auf Z. Gleichzeitig wird das Labeldes Knoten Z aktualisiert: auf den eigenen Wert multipliziert mit dem Wert desentfernten Knotens Y . Die Aktualisierung der Zeiger erfolgt nicht auf den Origi-naldaten, sondern diese Pointer werden als separate Liste verwaltet, da sonst dieInformationen uber die Originalliste verloren gingen. Auf diese Weise wird die Langeder Liste verkleinert.

Die in der neuen, verkleinerten Liste L− I enthaltenen Knoten haben sich auf-grund der Assoziativitat der Funktion im Endergebnis uber die Liste nicht im Wertverandert, obwohl Knoten aus der Liste entfernt wurden. Dies liegt daran, dass dieLabel der entfernten Knoten in die Label Ihrer Nachfolger in die verkleinerte Listeeingearbeitet wurden. Die neue Liste L− I kann also berechnet werden, indem dasVerfahren rekursiv auf sie angewendet wird. Sobald nach mehreren Durchlaufen dieWerte fur alle Knoten aus L − I bekannt sind kann damit begonnen werden, alleentfernten Knoten wieder in die Liste einzufugen, bis L rekonstruiert ist. Dies wirderreicht, indem die Label aller Knoten aus der Menge I jeweils mit den Labeln Ih-rer Vorganger aus der ursprunglichen Liste berechnet werden: Wieder angenommendie Knoten X, Y und Z mit Y ∈ I sind in dieser Reihenfolge in der Ursprungsli-ste verknupft. Nun enthalt die aktuelle Liste die Knoten X und Z zwischen die derKnoten Y wieder eingefugt werden soll. Es wird jetzt der Next Zeiger des Knoten Xmit dem Knoten Y uberschrieben. Damit zeigt X fortan wieder auf Y . Gleichzeitigwird das Label des Knoten Y aktualisiert: auf den eigenen Wert multipliziert mitdem Wert des Vorganger-Knotens X. Nachdem alle Knoten wieder eingefugt sindist das Verfahren beendet und die Ergebnisse konnen aus den Labeln der Knotenausgelesen werden.

Sobald der unabhangige Menge bekannt ist, ist die verkleinerte Liste schnellerstellt: O(sort(N)) I/O Operationen werden dafur benotigt. In diesen Operationenwerden die Knoten von I nach ihren Vorgangerknoten und die in L− I nach ihreneigenen IDs sortiert und danach einmal durchlaufen, um die Beschriftungen vonallen Nachfolgern der in I enthaltenen Knoten zu aktualisieren. Auf die selbe Weiseerfolgt die Aktualisierung der Pointer, um diese Knoten fortan zu uberspringen:hier wird L − I nach den Nachfolgern und I nach den eigenen IDs sortiert. Unddanach in einem einzelnen Scan uber die beiden Listen jeweils die Next-Pointer derElemente in L− I mit denen der Elemente aus I ersetzt.

Auf die Laufzeit hat die Rekursion naturlich einen sehr starken Einfluss. Oh-ne die Rekursion benotigte der Algorithmus fur einen Schritt die eben gezeig-ten O(sort(N)) I/Os. Die die Rekursion beschreibende Rekurrenz-Gleichung lautetI(N) = I(cN) + O(sort(N)) (mit einem festen c unter der Bedingung 0 < c <1). Diese lasst sich mit Hilfe des 3. Falls des Master-Theorems zu dem Ergeb-nis O(sort(N)) auflosen. Damit benotigt der Algorithmus insgesamt O(sort(N))I/O-Operationen, was eine starke Verbesserung gegenuber den O(N) benotigtenI/O-Operationen des internen Algorithmus auf externen Daten darstellt.

2Gegeben: Liste mit drei Knoten. Zwei Knoten befinden sich in der ersten und ein Knoten inder zweiten Menge. Bei großeren oder kleineren Listen nahert sich die unabhangige Menge eherN/2 an.

56

Page 61: HEINZ NIXDORF INSTITUT Fakultät für Elektrotechnik ... Pottmeyer Memory Limitations in Artificial Intelligence ... Vitter hat gezeigt, dass viele in diesem Modell effiziente Entwicklungen

Als letztes soll der oben angesprochene Beweis uber die angenommene Asso-ziativitat nachgereicht werden. Die angesprochene Assoziativitat uber X kann an-genommen werden, da sie bei nicht Vorhandensein ohne eine Verschlechterung derLaufzeit simuliert werden kann. Um dieses zu Beweisen dient eine beliebige Liste Lals Input. Von dieser Liste wird der Abstand eines jeden Knoten zum Kopf der Li-ste per List-Ranking bestimmt und anschließend werden die ungeordneten Knotenin die soeben bestimmte Reihenfolge aufsteigend sortiert. Auf dieser vorhandenenListe kann nun mit dem internen-Speicher Algorithmus mit einem einzelnen Scanuber die Liste die gewunschte Funktion bestimmt werden. Der Scan hat dabei eineLaufzeit von O(scan(N)) I/O Operationen. Die Herstellung der sortierten Folgehatte einen Zeitaufwand von O(sort(N)). Damit liegt auch die Laufzeit des Ge-samtverfahrens bei O(sort(N)) und es gibt keine Veranderung der Laufzeit durchdie Annahme der Assoziativitat.

3 Graph Blocking

Unter Graph-Blocking versteht man das effiziente Verteilen der Graphinformationenin Blocke, so dass moglichst wenig I/O Zugriffe fur das traversieren des Graphennotig sind. Es wird hierbei von so grossen Graphen ausgegangen, dass ein vollstandi-ges Laden in den Speicher nicht moglich ist. Um die Effizienz von Graph-Blockingzu untersuchen wird mit der Anzahl der auftretenden Page-Faults (Seitenzugriffs-Fehlern) gearbeitet. Ein solcher tritt auf, sobald auf einen Knoten des Graphenzugegriffen wird, der sich nicht im Speicher befindet.

Es wird beim Graph Blocking davon ausgegangen, dass sich der Graph nichtverandert. Dieses ermoglicht es, auf effiziente Updates des Graphen keine Ruck-sicht zu nehmen. Durch diese Einschrankung wird vieles erleichtert, da der Graphnun redundant auf dem Speicher abgelegt werden kann. Es wird festgelegt, dasses beim traversieren genugt einen der gespeicherten Knoten zu besuchen, dass alsokeine bestimmte fest definierte Kopie benotigt wird. Dies ist moglich, da jede KopieInformationen uber Vorganger und Nachfolger mit sich bringt und keine Verande-rung von Attributen stattfindet. Diese Beschrankung der Anforderungen ermoglichtgrosse Freiheiten bei der Wahl des Blockings.

Beim Graph Blocking wird also mehr Speicherplatz auf dem externen Speicherbenutzt, um die Anzahl der I/O Zugriffe und damit die Laufzeit des Algorithmus zuverbessern. Daher ist fur die Bewertung von moglichen Blockings auch der zusatzlichverwendete Speicher relevant. Um diesen greifbar zu machen wird betrachtet, umein wie hohes Vielfaches sich der benotigte Speicher erhoht. Diese Zahl nennt sichStorage-Blowup. Wenn zum Beispiel fur das Speichern von N Elementen, die inBlocken der Große B gespeichert werden, statt N/B fur das Graph-Blocking nunganze 3N/B Blocke benotigt werden, so betragt der Storage-Blowup 3.

Um die Worst-Case Performance des Blockings fur alle potentiell moglichenAlgorithmen zu bestimmen wird bei der Betrachtung der Gute davon ausgegangen,das kein spezieller, vorher bekannter, Algorithmus uber den Graph lauft, sonderndas als nachstes immer der Knoten ausgewahlt wird, der als fruhestes einen weiterenPage-Fault verursacht. Der Angreifer kennt also die Strategie des Blockings undwird dieser stetig entgegenarbeiten. Dies erschwert die Suche nach einem optimalenBlocking, dafur ist ein gefundenes in der Praxis spater universell einsetzbar.

Die beiden Zielgroßen fur die Effizienz eines Graphblockings lassen sich nichtgleichzeitig minimieren, da sie einander entgegenwirken. Aus diesem Grund mussfur den Einzelfall entschieden werden, welcher der beiden Parameter (Anzahl auf-tretender Page-Faults oder benotigter Speicherplatz) kritischer ist.

57

Page 62: HEINZ NIXDORF INSTITUT Fakultät für Elektrotechnik ... Pottmeyer Memory Limitations in Artificial Intelligence ... Vitter hat gezeigt, dass viele in diesem Modell effiziente Entwicklungen

3.1 Eindimensional

Im eindimensionalen Fall, also bei einer Linearen Liste, ist das optimale Blockingtrivial, sofern diese nur in eine Richtung durchlaufen werden darf. In diesem Fallmussen einfach alle Knoten nach ihrer Reihenfolge sortiert abgelegt werden. DieseListe wird nun einfach in die Blocke aufgeteilt.

Bei dem Durchlauf wird nun immer ein neuer Block geladen, wenn einer durch-laufen wurde. In diesem Fall ist der Storage-Blowup 1 und es sind immer B − 1Schritte moglich bis zum nachsten Page-Fault.

Sobald die Liste beliebig durchlaufen werden darf, wird es schwieriger: der An-greifer kann nach dem Laden eines neuen Blocks sofort wieder zum vorherigen Kno-ten zuruck und damit einen weiteren Page-Fault (nach nur einem weiteren Schritt)provozieren. Bei ausreichend internem Speicher konnte man alte Blocke im Speicherbehalten. Da dies in unserem Fall nicht gegeben ist (es passt genau ein Block in denSpeicher: M = B) wird nun ein verandertes Blocking benotigt.

Das Blocking wird nun wie in Abbildung 5 aufgebaut. Die Daten werden einmalkomplett kopiert und die Position der Blocke wird um B/2 nach hinten verschoben.Wenn nun der Graph traversiert wird, fangt man bei den Ursprungsblocken mit demLesen an. Sobald ein Pagefault auftritt, wird der nachste Block allerdings aus derzweiten Partition gelesen. Durch die Verschiebung um B/2 sind in dieser Partitionnun der gesuchte anzusprechende Block vorhanden, sowie die B/2 − 1 Nachfolger-und B/2 Vorgangerknoten des aktuellen Blockes. Daher kann der Angreifer nichtmit dem nachsten Schritt, sondern fruhestens in B/2 − 1 Schritten den nachstenPage Fault provozieren. Der nachste Block wird nun wieder aus der ersten Partitiongelesen, wodurch erneut die Verschiebung ausgenutzt wird. Der Storage Blowup furdieses Blocking betragt 2 und die Zeit bis zum nachsten Page Fault betragt zu jederZeit mindestens B/2− 1 Schritte.

1 2 1211109876543

109876543

Abbildung 5: Blocking fur eine lineare Liste mit einem Storage Blowup von 2 beiNutzung einer Blockgroße von 4

3.2 Baume

Ein effizientes Graph Blocking von allgemeinen Baumen ist interessanterweise nichtmoglich. Es sind hingegen weitere Beschrankungen notig, die entweder die erlaubteTraversierung des Graphen beschranken oder die Struktur des Baumes selber. Diesresultiert daraus, dass immer ein Baum existieren kann, bei dem nicht alle Kindereines Knotens in den internen Speicher passen.

In dem Fall das die Anzahl der Kinder (hier K genannt) eines Knoten die Be-dingung K ≥ M erfullt muss mindestens ein Knoten (der aktuelle muss ja auch imSpeicher vorgehalten werden) auf den externen Speicher ausgelagert werden. Da derAngreifer diesen Knoten kennt, kann er nun immer auf den gerade nicht vorgehal-tenen Knoten zugreifen und damit in jedem Schritt einen Page Fault verursachen.

Aus diesem Grund wird, um beliebige Traversierungen zu erlauben, im Folgen-den der Knotengrad eines jeden Knoten des Baumes auf einen konstanten Wert dbegrenzt.

58

Page 63: HEINZ NIXDORF INSTITUT Fakultät für Elektrotechnik ... Pottmeyer Memory Limitations in Artificial Intelligence ... Vitter hat gezeigt, dass viele in diesem Modell effiziente Entwicklungen

Die Konstruktion des Blockings beginnt analog wie im eindimensionalen Fallmit der Aufteilung in zwei Partitionen. Diese Partitionen werden in Ihrer Hohe imBaum begrenzt. Dazu wird der Baum in mehrere Layer mit einer jeweiligen Hohevon logdB aufgeteilt. Nun gibt es im Graphen Aufteilungen in der Breite und in derHohe des Baumes. Diese sind in Abbildung 6 dargestellt.

3. A Survey of Techniques for Designing I/O-E!cient Algorithms 57

logd B

logd B

Fig. 3.4. A blocking of a binary tree with block size 7. The subtrees in the firstpartition are outlined with dashed lines. The subtrees in the second partition areoutlined with solid lines.

shown in Fig. 3.3, we choose one vertex r of T as the root and construct twopartitions of T into layers of height logd B (see Fig. 3.4). In the first partition,the i-th layer contains all vertices at distance between (i ! 1) logd B andi logd B!1 from r. In the second partition, the i-th layer contains all verticesat distance between (i ! 1/2) logd B and (i + 1/2) logd B = 1 from r. Eachlayer in both partitions consists of subtrees of size at most B, so that eachsubtree can be stored in a block. Moreover, small subtrees can be packed intoblocks so that no block is less than half full. Hence, both partitions togetheruse at most 4N/B blocks, and the storage blow-up is at most four.

The paging algorithm now alternates between the two partitions similar tothe above paging algorithm for lists. Consider the traversal of a path, and letv be a vertex that causes a page fault. Assume that the tree currently held inmain memory is from the first partition. Then v is the root or a leaf of a treein the first partition. Hence, the tree in the second partition that contains vcontains all vertices that can be reached from v in (logd B)/2!1 steps. Thus,by loading this block into main memory, the algorithm guarantees that thenext page fault occurs after at least (logd B)/2 ! 1 steps, and traversing apath of length L causes at most 2L/(logd B) page faults.

If all traversed paths are restricted to travel away from the root of T ,the storage blow-up can be reduced to two, and the number of page faultscan be reduced to L/ logd B. To see this, observe that only the first of theabove partitions is needed, and for any traversed path, the vertices causingpage faults are the roots of subtrees in the partition. After loading the blockcontaining that root into main memory, logd B ! 1 steps are necessary inorder to reach a leaf of the subtree, and the next page fault occurs afterlogd B steps. For traversals towards the root, Hutchinson et al. [419] showthat using O(N/B) disk blocks, a page fault occurs every !(B) steps, so thata path of length L can be traversed in O(L/B) I/Os.

Abbildung 6: Blocking eines binaren Baums mit einer Blockgroße von 7. Der StorageBlowup betragt hierbei maximal 4. Die erste Partition besteht aus den mit gestri-chelten Linien umrandeten und die zweite aus den mit den durchgezogenen Linienumrandeten Teilbaumen. (Bildquelle: [1])

Durch diese Aufteilung kann man nun bestimmen, welche Knoten in welchenLayern und Partitionen vorhanden sind. Ausgehend von der Wurzel r gesehen sinddas in der ersten Partition im i-ten Layer die Knoten mit Entfernungen im Bereichvon (i − 1) logd B bis zu i logd B − 1. In der zweiten Partition sind es im i-tenLayer die Knoten mit Entfernungen von (i−1/2) logd B bis zu (i+1/2) logd − 1B.

Jeder Layer besitzt also Teilbaume in einer Große von maximal B - kann alsoproblemlos in einem Block gespeichert werden. Ein Problem besteht in den Fransendes Baumes, die sehr kleine Teilbaume sein konnen. In diesem Fall konnen meh-rere Teilbaume gemeinsam in einem Block gespeichert werden, um einen Fullgradvon mindestens mehr als der Halfte eines Blockes zu erreichen. Mit diesen Parame-tern ergibt sich, dass zum Speichern der beiden Partitionen maximal 4N/B Blockebenotigt werden, was einem Storage-Blowup von 4 entspricht.

Damit wurde allerdings noch nichts uber die Effizienz dieses Blockings ausge-sagt. Um diese zu Berechnen ist das Verhalten beim Laden der Blocke relevant. Hierwird wieder bei jedem Lesezugriff zwischen den einzelnen Partitionen gewechselt.Das Verhalten des Systems kann am besten bei Betrachtung von Abbildung 6 nach-vollzogen werden. Angenommen der aktuelle Knoten ist v, ein beliebiger Knotendes Graphen, und hat beim Zugriff soeben einen Page Fault verursacht. Die aktu-ellen Daten werden als aus Partition 1 gelesen angenommen (der Fall fur Partition2 ist analog). Dann befindet sich dieser Knoten im Speicher und stellt entweder dieWurzel dieses Teilbaumes dar oder befindet sich als Blatt am Ende des Teilbaumes.Wenn nun der gewunschte Knoten aus der zweiten Partition geladen wird, so befin-det sich dieser nicht am Rand des geladenen Teilbaumes, sondern mitten drin. Essind dadurch mindestens weitere (logdB)/2− 1 Schritte moglich, bis zum nachstenPage-Fault (am Rand der zweiten Partition). Damit lasst sich ein Pfad der LangeL mit maximal 2L/(logdB) Page Faults traversieren.

Wenn man nun den Pfad beschrankt, der durch den Baum genommen werdenkann, so sind Einsparungen beim Storage-Blowup moglich. Angenommen ausgehendvon der Wurzel des ganzen Baumes sind nur Traversierungen erlaubt, welche sichvon der Wurzel entfernen. Dann kann man den Baum traversieren, ohne die zweite

59

Page 64: HEINZ NIXDORF INSTITUT Fakultät für Elektrotechnik ... Pottmeyer Memory Limitations in Artificial Intelligence ... Vitter hat gezeigt, dass viele in diesem Modell effiziente Entwicklungen

Partition nutzen zu mussen. Wenn hier beim Laden des Knoten v ein Page Faultauftritt, so kann dieser beruhigt aus der ersten Partition gelesen werden, da diezweite nur fur Schritte zuruck in Richtung Wurzel Vorteile bringen wurde. In diesemFall hat das Nutzen nur der ersten Partition den weiteren Vorteil, dass der Knotenv immer die Wurzel eines neuen Teilbaumes darstellt. Dadurch sind in Richtungder Blatter des Teilbaumes mehr Schritte moglich, als es in der zweiten Partitionwaren. Dies sind hier namlich logdB−1 Schritte statt (logdB)/2−1. Da der nachstePage Fault also erst nach logdB Schritten auftritt und eine Partition eingespart wirdkann der Storage Blowup auf 2 reduziert werden bei gleichzeitiger Reduzierung derPage Faults fur einen Weg der Lange L auf L/logbB.

Fur den umgekehrten Weg von den Blattern in Richtung der Wurzel lasst sichsogar eine maximale Anzahl von O(L/B) I/O-Zugriffen zeigen.

3.3 Zweidimensionale Gitter

Das Blocken von zweidimensionalen Gittern hat viel Ahnlichkeit mit dem Verfahrenzum Blocken von Listen. Dies resultiert daraus, dass eine lineare Liste im Grundeein Spezialfall von allgemeinen Gittern, namlich ein eindimensionales Gitter, ist.Beim zweidimensionalen Gitter wird das Gitter mit kleinen Sub-Gittern uberzogen.Diese Sub-Gitter, Tesselation3 genannt, werden in einer Große von

√B∗

√B = B

erzeugt.

42

31

Abbildung 7: 2D Graph.Blocking mit 2 Tesselationen

Wenn M = B ist, ist es nicht moglich mit zwei Tesselationen auszukommen.Gegeben sind zwei Tesselationen, um die Daten zu uberdecken. Diese beginnen miteinem Offset von k (auf der X-Achse) und einem Offset von l (auf der Y-Achse)von den Originaldaten ausgehend gesehen. Ferner werden die folgenden vier Punktegenauer betrachtet: (i

√B + k, j

√B), (i

√B + k + 1, j

√B), (i

√B + k, j

√B + 1) und

(i√

B + k + 1, j√

B + 1). Diese konnen auf einem Pfad des Angreifers liegen - esliegen allerdings maximal zwei dieser Punkte gemeinsam in einer Tesselation (sieheAbbildung 7). Nun ist es fur einen Angreifer moglich, immer den nicht im Speichervorgehaltenen Knoten anzuspringen und damit in jedem Schritt einen Page Faultzu verursachen.

3Mosaik

60

Page 65: HEINZ NIXDORF INSTITUT Fakultät für Elektrotechnik ... Pottmeyer Memory Limitations in Artificial Intelligence ... Vitter hat gezeigt, dass viele in diesem Modell effiziente Entwicklungen

Mit der Nutzung von drei Tesselationen ist es moglich eine Verringerung derPage Faults zu erreichen. Um diese anzuordnen bekommen die Tesselationen eineVerschiebung von

√B/3 zueinander. Die Erste beginnt also ohne Verschiebung,

die Zweite mit einem Offset von√

B/3 und die Dritte mit einer Verschiebung von2∗√

B/3. Dies gilt fur beide Achsen und ist in Abbildung 8 visualisiert. Durch dieseneue Anordnung kann nun fur jeden Knoten eine passende Tesselation gefundenwerden, damit der Knoten mindestens einen Abstand von

√B/6 zum Rand der neu

geladenen Tesselation hat. Der Paging Algorithmus sucht nun jeweils die passendeTesselation aus und kann

√B/6 weitere Schritte garantieren. Das Ergebnis ist das

Auftreten von Page Faults maximal alle√

B/6 Schritte im Graphen. Der Storage-Blowup betragt hierbei durch die drei Tesselationen: 3.3. A Survey of Techniques for Designing I/O-E!cient Algorithms 59

Fig. 3.5. A blocking for M = B.

Finally, if M ! 3B, the storage blow-up can be brought down to onewhile keeping the number of page faults incurred by the traversal of a pathof length L at 4L/

"B. To achieve this, the tessellation shown in Fig. 3.6 is

used. To prove that the traversal of a path of length L incurs at most 4L/"

Bpage faults, we show that at most two page faults can occur within

"B/2

steps. So assume the opposite. Then let v be a vertex that causes a page fault,and let u be the vertex visited immediately before v. Let u be in the solid boldsubgrid in Fig. 3.6 and assume that it is in the top left quarter of the subgrid.Then all vertices that can be reached from u in

"B/2 steps are contained in

the solid thin subgrids. In particular, v is contained in one of these subgrids.If v is in subgrid A, it takes at least

"B/2 steps after visiting v to reach a

vertex in subgrid C. If v is in subgrid C, it takes at least"

B/2 steps aftervisiting v to reach a vertex in subgrid A. Hence, in both cases only a vertexin subgrid B can cause another page fault within

"B/2 steps after visiting

vertex u. If v is in subgrid B, consider the next vertex w after v that causesa page fault and is at most

"B/2 steps away from u. Vertex w is either in

subgrid A, or in subgrid C. W.l.o.g. let w be in subgrid A. Then it takesat least

"B/2 steps to reach a vertex in subgrid C, so that again only two

page faults can occur within"

B/2 steps after visiting u. This shows that thetraversal of a path of length L incurs at most 4L/

"B page faults.

Blocking Planar Graphs. The final result we discuss here concerns theblocking of planar graphs of bounded degree. Quite surprisingly, planar graphsallow blockings with the same performance as for trees, up to constant factors.That is, with constant storage blow-up it can be guaranteed that traversinga path of length L incurs at most 4L/ logd B page faults, where d is themaximal degree of the vertices in the graph. To achieve this, Agarwal etal. [7] make use of separator results due to Frederickson [315]. In particular,

Abbildung 8: 2D Graph-Blocking mit 3 Tesselationen (Bildquelle: [1])

Sofern doch mehr interner Speicher zur Verfugung stehen sollte, so kann dasSystem weiter verbessert werden - sowohl in Hinsicht auf Speicherplatz, als auchauf die Zahl der benotigten I/O-Operationen. Wenn der interne Speicher mehr alsdoppelt so viel Platz bietet, also M ≥ 2B, ergibt sich folgende Situation:

Das Gitter wird wieder von zwei Tesselationen uberdeckt (siehe auch Abbildung7). Das oben beschriebene Problem wurde verursacht durch das Verdrangen des ak-tuellen Blocks aus dem Speicher. Nun kann aber ein zusatzlicher Block, nach demfolgenden Schema, im internen Speicher vorgehalten werden: Betrachtet wird derKnoten v der soeben, auf dem Pfad vom Knoten u kommend, einen Page Faultverursacht hat. Nun ist es wichtig den Block mit dem Knoten u gleichzeitig imSpeicher zu behalten und den anderen Block zu verwerfen. Gleichzeitig muss beimLaden des neuen Blockes darauf geachtet werden, die korrekte Tesselation zu laden.Es ergibt sich die Situation, dass einer der beiden Blocke (die den Knoten v enthal-ten) zusammen mit dem Block des Knotens u einen

√B/4 großen Teilbereich um v

herum abdeckt, mit der Folge, dass nun mindestens√

B/4 weitere Schritte bis zumnachsten Page Fault moglich sind. Also hat man beim Durchlaufen eines Pfades derLange L maximal 4L/

√B Page Faults zu erwarten.

Das Ergebnis ist eine Reduzierung des Storage-Blowup auf 2 bei gleichzeitigerVerbesserung der Schrittanzahl bis zum nachsten Page Fault auf mindestens

√B/4.

Falls der interne Speicher sogar in einer Grosse von M ≥ 3B zur Verfugungsteht, so ist eine weitere Verbesserung des Storage-Blowup moglich.

61

Page 66: HEINZ NIXDORF INSTITUT Fakultät für Elektrotechnik ... Pottmeyer Memory Limitations in Artificial Intelligence ... Vitter hat gezeigt, dass viele in diesem Modell effiziente Entwicklungen

B

C

A

u

Abbildung 9: Graph-Blocking mit Storage-Blowup von 1 und√

B/4 garantiertenSchritten (bei M ≥ 3B internem Speicher)

3.4 Planare Graphen

Ein effizientes Blocking fur einen planaren Graphen resultiert in Ergebnissen, dieden vorangegangen der Baume sehr ahneln: die Gute unterscheidet sich nur in kon-stanten Faktoren. Wichtig ist hierbei wieder, dass die Graphen nur einen festenmaximalen Knotengrad besitzen durfen.

Der Ansatz baut auf einem Beweis von Frederickson (in [3]) auf in welchembewiesen wird, dass sich in jedem planaren Graphen G eine Gruppe S von Knoten(mit Anzahl O(N/

√B)) finden lasst, so dass bei Betrachtung von G − S keine

Zusammenhangskomponenten existieren, welche großer sind als ein Block B.Auf Basis dieses Wissens kann nun ein gutes Blocking in folgender Art zusam-

mengebaut werden: Es wird als Erstes fur jede Zusammenhangskomponente ausG − S ein einzelner Block vorgesehen. Falls sich beim Erstellen herausstellt, dassBlocke zu weniger als 1/2 gefullt sind, so werden mehrere Zusammenhangskompo-nente in einem Block zusammengefasst. Durch dieses Verfahren wird eine maximaleAnzahl von 2N/B Blocken benotigt. Als Nachstes mussen die von den Knoten inS aus erreichbaren weiteren Knoten gespeichert werden. Hierbei werden fur jedenKnoten v ∈ S die Knoten der nachsten Nachbarschaft gespeichert. Namlich ge-nau alle, die in wenigen Schritten erreichbar sind und gemeinsam in einen Blockpassen. Dies lasst sich durch eine Beschrankung auf (logdB)/2 Schritte Entfernungvom Knoten erreichen.Bei (logdB)/2 Schritten sind maximal d(logdB)/2 =

√B neue

Knoten von jedem Knoten aus erreichbar. Hier findet wieder das Verpacken von zukleinen Teilen gemeinsam in einen Block statt, so dass ein Fullgrad von mehr als50% auch fur diese Blocke garantiert werden kann. Hieraus ergibt sich ein Storage-Blowup von nur O(1), da der Gesamtbedarf im zweiten Teil des Blockings O(

√B|S|)B )

betragt, was O(N/B) entspricht.Nun fehlt noch die Garantie der Schritte bis zum nachsten Page Fault, um

die Gute von maximal 4L/√

B Page Faults entlang eines Pfades der Lange L zuerreichen, welche der Gute entspricht, die fur 2-dimensionale Gitter bereits gezeigtwurde.

Wahrend der Angreifer den Pfad traversiert und sich im Knoten u aufhalt verur-sacht er einen Page Fault beim Zugriff auf den Knoten v. Fur diesen Knoten konnen

62

Page 67: HEINZ NIXDORF INSTITUT Fakultät für Elektrotechnik ... Pottmeyer Memory Limitations in Artificial Intelligence ... Vitter hat gezeigt, dass viele in diesem Modell effiziente Entwicklungen

nun zwei Falle aufteten:

1. v ∈ S

2. v ∈ G− S

Angenommen der Knoten befindet sich nicht in S, so wird die Zusammenhangs-komponente mit dem Knoten v in den Speicher geladen. Nun sind beliebige Bewe-gungen innerhalb dieser Zusammenhangskomponente moglich. Sobald diese verlas-sen wird, tritt ein Page Fault auf. Dieser Knoten w muss sich nun in dem Set Sbefinden. Also wird der Block mit den in (logdB)/2 Schritten erreichbaren Nach-barknoten geladen. In diesem Szenario sind nun 2 Page Faults aufgetreten und diegeladenen Daten lassen mindestens (logdB)/2 Schritte bis zum nachsten Page Faultzu. Dies sind also fur einen Pfad der Lange L maximal 4L/

√B Page Faults.

Literatur

[1] A Survey of Techniques for Designing I/O-Efficient Algorithms, Anil Mahes-hwari und Norbert Zeh, in: Algorithms for Memory Hierarchies: AdvancedLectures, Serie: Lecture Notes in Computer Science, Springer Berlin / Heidel-berg, Volume 2625/2003, Seiten 36-61,http://www.springerlink.com/content/1f5erbmjwpep46r9/

[2] External-memory graph algorithms, Yi-Jen Chiang and Michael T. Goodrichand Edward F. Grove and Roberto Tamassia and Darren Erik Vengroff andJeffrey Scott Vitter, in: SODA ’95: Proceedings of the sixth annual ACM-SIAMsymposium on Discrete algorithms, Pages 139–149, Society for Industrial andApplied Mathematics, 1995, ISBN: 0-89871-349-8http://portal.acm.org/citation.cfm?coll=GUIDE&dl=GUIDE&id=313681

[3] Fast algorithms for shortest paths in planar graphs, with applications, GregN. Frederickson, SIAM J. Comput., Volume 16, Number 6, 1987, p. 1004-5397

[4] Deterministic parallel list ranking, R. J. Anderson and G. L. Miller, VLSIAlgorithms and Architectures, Springer-Verlag, 1988, pages 81-90, ISBN: 0-387-96818-0http://portal.acm.org/citation.cfm?coll=GUIDE&dl=GUIDE&id=61173#

[5] I/O-efficient algorithms for contour-line extraction and planar graph blocking,Agarwal, P. K., Arge, L., Murali, T. M., Varadarajan, K. R., and Vitter,J. S. 1998, In Proceedings of the Ninth Annual ACM-SIAM Symposium onDiscrete Algorithms (San Francisco, California, United States, January 25 - 27,1998). Symposium on Discrete Algorithms. Society for Industrial and AppliedMathematics, Philadelphia, PA, 117-126.http://portal.acm.org/citation.cfm?id=314691#

[6] Dr. Amitava Datta, Uni Freiburg, Parallel Algorithms and Applications, SS2001,Lecture 5http://ad.informatik.uni-freiburg.de/lehre/ss01/paa/vorlesung-uebungen/

63

Page 68: HEINZ NIXDORF INSTITUT Fakultät für Elektrotechnik ... Pottmeyer Memory Limitations in Artificial Intelligence ... Vitter hat gezeigt, dass viele in diesem Modell effiziente Entwicklungen

64

Page 69: HEINZ NIXDORF INSTITUT Fakultät für Elektrotechnik ... Pottmeyer Memory Limitations in Artificial Intelligence ... Vitter hat gezeigt, dass viele in diesem Modell effiziente Entwicklungen

I/O eziente Algorithmen auf dünnenGraphen

Christoph Horstmann

1 Einleitung

Vor allem in der Umgebung des Internets kann es heute zu sehr groÿen Datenmengenkommen. So kann es zum Beispiel sein, dass eine Suche in einem Graphen mit 200 Mil-lionen Knoten und 2 Milliarden Kanten stattndet. Graphen dieser Gröÿe können nichtmehr im Hauptspeicher eines Systems gehalten werden. Es müssen also Algorithmen ge-nutzt werden, welche solche Graphen I/O ezient bearbeiten. Im folgenden werden nuneinige solcher Algorithmen vorgestellt, welche auf eine speziellen Klasse von Graphenarbeiten, den sogenannten dünnen Graphen.

1.1 Graph Klassen

Ein Graph G = (V,E) gilt als dünn, wenn die Anzahl der Kanten |E| nur linear zu derAnzahl der Knoten |V | wächst, also |E| = O(|V |) gilt. In Abbildung 1 werden die ver-

Dünn

PlanarOuter-planar begrenzte

Baumweite

Gitter

Dünn

PlanarOuter-planar begrenzte

Baumweite

Gitter

Abbildung 1: Unterklassen von dünnen Graphen

schiedenen Unterklassen der dünnen Graphen gezeigt. Beispiele für einzelne Graphklassenwerden in Abbildung 2 gezeigt und im folgenden erklärt.Bei einem planaren Graphen handelt es sich um einen Graphen, welcher so gezeichnet

werden kann, dass keine Kante sich mit einer anderen kreuzt. Diese Zeichenart wirdplanare Einbettung genannt. Der linke Graph in Abbildung 2 ist also planar, da, wiedarunter zu sehen, alle Kanten so gelegt werden können, dass sich keine Kante mit eineranderen kreuzt.Ein Outerplanarer Graph besitzt, zusätzlich zur Eigenschaft, dass er planar ist, noch

die Bedingung, dass sich alle Knoten auf dem äuÿeren Rand der planaren Einbettung

65

Page 70: HEINZ NIXDORF INSTITUT Fakultät für Elektrotechnik ... Pottmeyer Memory Limitations in Artificial Intelligence ... Vitter hat gezeigt, dass viele in diesem Modell effiziente Entwicklungen

planar outerplanar Gitter

Abbildung 2: Beispiele für einige Graphklassen

benden. Es verläuft hier also keine Kante auÿerhalb dieses Knoten-Randes. Der pla-nare Graph aus Abbildung 2 ist zum Beispiel nicht outerplanar, da es bei der planarenEinbettung unten, nicht möglich ist, dass alle Kanten innerhalb der Knoten verlaufen.Von Gitter Graphen ist es die Haupteigenschaft, dass die Knoten eine Gitter-Struktur

bilden. Kanten sind hier nur von einem Knoten zu seinen Nachbarn zugelassen. Darausergibt sich, dass ein Knoten nur maximal acht Kanten zu seinen Nachbarn haben kann.

1.2 Algorithmen I/O ezient gestalten

Eine Möglichkeit um einen Algorithmus für ein Problem I/O Ezient zu gestalten ist es,bestimmte Eigenschaften einer Graphklasse auszunutzen. So läÿt sich zum Beispiel dieEigenschaft von Gittergraphen ausnutzen, dass jeder Knoten nur maximal acht Nachbarnhaben kann.Ein weiteres Verfahren ist die Kontraktion eines Graphen. Hier wird der Ausgangs-

graph zuerst in mehreren Schritten kontrahiert, so dass ein Graph entsteht, auf dem dasProblem mit sehr wenigen I/O Schritten gelöst werden kann. Beim Kontrahieren wird imallgemeinen so vorgegangen, dass in einem Schritt mehrere Kanten aus dem Ausgangs-graphen zum Kontrahieren ausgewählt werden. In Abbildung 3 ist zu sehen, was bei

1 2

63

4

5 8

7

1,2

63

4

5 8

7

Abbildung 3: Kontrahieren eines Knotens

dem Kontrahieren einer Kante passiert. Die Kante zwischen Knoten 1 und 2 soll kontra-hiert werden. Hierzu werden die beiden Knoten zu einem zusammengefasst. Alle Kanten,welche von Knoten 1 oder 2 zu einem anderen Knoten des Graphen verliefen, werdennun Kanten zu dem zusammengefassten Knoten. Diese Kanten-Kontraktionen werden ineinem Kontraktions-Schritt auf einem Graphen G in der Regel auf vielen Kanten ausge-führt, so dass der Ergebnis-Graph nach einem Schritt nur noch eine Gröÿe von O( |G|

2 )

66

Page 71: HEINZ NIXDORF INSTITUT Fakultät für Elektrotechnik ... Pottmeyer Memory Limitations in Artificial Intelligence ... Vitter hat gezeigt, dass viele in diesem Modell effiziente Entwicklungen

besitzt. Hierbei ist N = |G| die Anzahl der Knoten in G. Die Gröÿe des Graphen nach derKontraktion halbiert sich also asyptotisch im Gegensatz zum Ausgangs-Graphen. Nachmehreren dieser Kontraktions-Schritte ergibt sich dann ein Graph, auf dem das eigent-liche Problem in wenigen I/O Schritten gelöst werden kann, da dieser Graph deutlichweniger Knoten besitzt, als der Ausgangs-Graph.Als nächstes muss dann die Lösung für den kontrahierten Graphen wieder schrittweise

auf die vorherigen Kontraktions-Schritte übertragen werden. Hierzu werden im Allgemei-nen die einzelnen Kontraktionen eines Schrittes wieder rückgängig gemacht. Allerdingsist die Erweiterung der Lösung auch sehr speziell von dem Problem abhängig. Wie soetwas in einem konkreten Algorithmus abläuft wird in Abschnitt 2.1.3 gezeigt.

1.3 Abhängigkeiten der Algorithmen

In dieser Arbeit werden exemplarisch Algorithmen vorgestellt, welche verschiedene Pro-bleme auf Planaren Graphen lösen. Einige dieser Algorithmen haben das Ergebnis ei-nes anderen Algorithmus als Voraussetzung, da sie mit Hilfe dessen Lösung ihr eigenesProblem lösen. Weiterhin gilt bei diesen Abhängigkeiten, dass der Algorithmus eine be-stimmte Laufzeitschranke nur einhalten kann, wenn auch der Algorithmus, dessen Lösungbenötigt wird eine bestimmte Laufzeitschranke einhält. So ergab sich für mehrere Algo-rithmen auf planaren Graphen eine gegenseitige Abhängigkeit[1], da alle Algorithmen dieLösung eines anderen Algorithmus benötigen, um eine bestimmte Laufzeit einzuhalten.Diese Abhängigkeiten werden in Abbildung 4 dargestellt. Es zeigt jeweils ein Pfeil von

Tiefensuche

Kürzeste Wege

Graph PartitionierungBreitensuche

Abbildung 4: Abhängigkeiten verschiedener Algorithmen auf planaren Graphen

von einem Problem zu einem anderen, wenn dieses Problem eine Lösung des anderen Pro-blems benötigt. Um also zum Beispiel das Kürzeste Wege Problem auf planaren Graphenzu lösen, wird eine eine Partitionierung dieses Graphen benötigt.Um diese Abhängigkeiten aufzubrechen muss also eines der genannten Probleme, ohne

die Lösung eines anderen Probelms zu verwenden, gelöst werden. Der Durchbruch hierzuwurde 2001 von Maheshwari und Zeh erreicht[2]. Hier wurde ein Algorithmus entwickelt,welcher eine optimale h Partition(siehe Abschnitt2 ohne die Lösung eines anderen Pro-blems berechnet werde konnte.Im Folgenden geht es nun um diesen Algorithmus zur Berechnung einer Partitioin eines

planaren Graphen. Danach wird ein Algorithmus vorgestellt, welcher auf einem planarenGraphen das Kürzeste Wege Problem löst. Zuletzt wird dann ein Algorithmus gezeigt,der eine Tiefensuche auf einem planaren Graphen durchführt.

67

Page 72: HEINZ NIXDORF INSTITUT Fakultät für Elektrotechnik ... Pottmeyer Memory Limitations in Artificial Intelligence ... Vitter hat gezeigt, dass viele in diesem Modell effiziente Entwicklungen

2 Partition von Graphen

In diesem Abschnitt geht es um einen Algorithmus, welcher eine optimale h Partitioneines Graphen G berechnet. Um eine h Partition zu nden wird eine Menge von KnotenS gesucht, welche, wenn sie entfernt wird, den Graphen G in k = O(N/h) TeilgraphenG1, . . . , Gk aufteilt. Jeder dieser Teilgraphen enthält höchstens h Knoten. Die Knotenin der Menge S sind nicht Teil dieser Teilgraphen. Die Partition mit Seperator undTeilgraphen wird als P = (S, G1, . . . , Gk) geschrieben. Abbildung 5 zeigt ein Beispiel

G1

G2

G3

SG

N Knoten O(N/h) viele Teilgraphenmit maximal h Knoten

...

G1

G2

G3

S

zusätzlich in derGröße beschränkt

h Partition optimale h Partition

...

Abbildung 5: Beispiel für eine Partition eines Graphen

für die Partition eines beliebigen Graphen G mit N Knoten. In dem mittleren Teil istdie Partition des Graphen mit den entsprechenden Eigenschaften zu sehen. Es gibt hierO(N/h) Teilgraphen, welche durch den Seperator S getrennt werden. Diese Teilgraphenbesitzen maximal h Knoten.Eine optimale h Partition stellt, zusätzlich zu den bisher Genannten, noch eine Bedin-

gung an die Gröÿe des Seperators S. Der Seperator muss bei einer optimalen Partiotion sogroÿ sein, wie das Maximum über die minimalen Seperatoren von allen N Knoten groÿenGraphen welche zu einer bestimmten Graph Klasse gehören. In diesem Fall ist die GraphKlasse die Klasse der planaren Graphen. Formal wird zur Begrenzung der Gröÿe von Sfestgelegt: σ(C,N, h) = maxG minS |S| : Seperator S erzeugt eine h Partition von G.Es muss dann |S| = O(σ(C, |G|, h)) gelten. S darf also nur asymptotisch so viele Knotenenthalten, wie der maximale kleinste Seperator eines Graphen aus der Klasse C mit |G|vielen Knoten.

2.1 Planare Graphen

Um eine optimale h-Partition auf Planaren Graphen zu nden, wurde von Maheshwa-ri und Zeth[2] ein Algorithmus vorgestellt, welcher keine vorherige Bearbeitung durcheinen anderen Algorithms benötigt. So kann dieser Algorithmus als Ausgang für weite-re Algorithmen verwendet werden, welche als Teil ihrer Lösung eine h Partition ihresEingabe-Graphen bilden. Weiterhin nutzt dieser Algorithmus das grundsätzliche Prinzipder Graph-Kontraktion, um so den Algorithmus I/O ezient ausführen zu können.Das grundsätzliche Vorgehen des Algorithmus ist es zuerst den Eingabegraphen G

68

Page 73: HEINZ NIXDORF INSTITUT Fakultät für Elektrotechnik ... Pottmeyer Memory Limitations in Artificial Intelligence ... Vitter hat gezeigt, dass viele in diesem Modell effiziente Entwicklungen

in mehreren Schritten zu kontrahieren. Die in jedem kontraktions-Schritt entstehendenGraphen werden im folgenden H0, . . . ,Hr genannt. Hierbei gilt einmal G = H0 und|Hi+1| ≤ 1

2 |Hi|, was bedeuted, dass der Graph Hi+1 weniger oder genau halb so vieleKnoten enthalten muss, wie Hi. Diese Kontraktionen werden r = log(B) mal ausgeführt,da so der der Graph Hr die Gröÿe |Hr| = O(N/B) erreicht.Als nächstes wird auf Hr ein Algorithmus angewandt, welcher eine optimale Partition,

mit den Seperator-Knoten Sr, berechnet. Ein solcher Algorithmus wird in [3] vorgestellt.Dieser Algorithmus benötigt zur Berechnung eines h′ Seperators auf einem Graphen mitN ′ Knoten O(N ′) Schritte. Da Hr nur O(N/B) Knoten besitzt, ergibt sich also für diesenAlgorithmus eine Laufzeit von O(N/B) = O(scan(N)) I/O Schritten.Zuletzt wird dann über die Graphen Hr−1, . . . ,H0 iteriert um jeweils die Partition von

Hi aus Hi+1 zu berechnen. Hier wird von den Knoten S′i, welche die Knoten sind, die in

Hi+1 zu Si+1 kontrahiert waren, ausgegangen. Si induziert schon eine Partition von Hi.Diese wird nun noch weiter verfeinert, indem weitere Seperator-Knoten zu Si hinzugefügtwerden.Im Folgenden wird nun erklärt, wie zuerst der Graph G zu dem Graphen Hr kontrahiert

wird. Danach wird vorgestellt, wie der auf Hr gefundene Knotenseperator Sr schrittweisezu einem Seperator S für G erweitert wird.

2.1.1 Kontrahieren des Graphen

Zuerst werden für die einzelnen Knoten folgende Eigenschaften fest gelegt. Das Gewicht

eines Knotens ω(v) stellt die Anzahl der Knoten dar, welche der Knoten v aus G reprä-sentiert. Die Gröÿe σ(v) gibt an, wie viele Knoten aus Hi−1 zu dem Knoten v kontrahiertwurden.

vω(v) σ(v)

H0 p

0=2 H'

1 p

1=4

s

s

s

l

l

l

H''1 p

1=4

4 4

4 4

4 4

1 11 1

1 1

H1 p

1=4

4 4

4 4

4 4

1 1

2 2

(a) (b) (c) (d)

Abbildung 6: Beispiel für Kontraktion des Graphen

In Abbildung 6 ist ein Beispiel für den ersten Schritt der Kontraktion eines Graphenzu sehen. Der Ausgangsgraph ist unter (a) zu sehen. Für den ersten Kontraktions-Schrittwird zuerst von H0 = G ausgegangen. In H0 gilt ω(v) = 1 für alle Knoten. In Abbildung6 (a) und (b) wird ω(v) der Übersicht wegen nicht dargestellt. Um nun aus Hi,Hi+1 zu

69

Page 74: HEINZ NIXDORF INSTITUT Fakultät für Elektrotechnik ... Pottmeyer Memory Limitations in Artificial Intelligence ... Vitter hat gezeigt, dass viele in diesem Modell effiziente Entwicklungen

berechnen wird zuerst ein Zwischengraph H ′i+1 = Hi gebildet (Schritt (b) in Abbildung

6). In diesem Graphen gilt σ(v) = 1 und ω(v)H′i+1

= ω(v)Hi für alle v ∈ H ′i+1.

Aus dem Graphen H ′i+1 wird nun der Graph H ′′

i+1 gebildet, indem so lange Kan-ten v, w kontrahiert werden, wie noch eine Kante v, w existiert, für welche gilt:ω(v) + ω(w) ≤ pi+1 oder σ(v) + σ(w) ≤ 56. pi = 2i+1 stellt hierbei einen Grenzwertfür das maximale Gewicht ω eines Knotens für den jeweiligen Iterationsschritt dar. Die56, welche die Obergrenze für σ(v) + σ(w) ist, ergibt sich aus den Eigenschaften vonPlanaren Graphen. In Abbildung 6 ist unter (c) das Ergebnis dieser Kontraktionen zusehen. Es wurden jeweils die in (b) markierten Kanten, zu dem verbundenen Knoten in(c), kontrahiert. Die Reihenfolge der Kontraktionen ist nicht deterministisch und wurdefür das Beispiel so gewählt.Als nächstes werden die Knoten aus H ′′

i+1 in leichte und schwere Knoten eingeordnet.Ein Knoten v ist schwer, wenn gilt: ω(v) ≥ pi/2 oder σ(v) ≥ 28. In Abbildung 6 sindin (c) die Knoten entsprechend mit l für leicht und s für schwer markiert. In H ′′

i+1 kön-nen keine zwei leichte Knoten nebeneinander liegen, da die Kante zwischen zwei leichtenKnoten noch die Voraussetzungen für eine Kontraktion erfüllen würde, es aber alle Kan-ten, welche diese Voraussetzungen erfüllen schon vorher kontrahiert wurden. Die leichtenKnoten, dessen Grad höchstens 2 ist, werden jetzt in Klassen C1, . . . , Cq eingeteilt. Undzwar so, dass alle Knoten einer Klasse die gleiche Gruppe von Schweren Knoten alsNachbarn haben. Weiterhin werden die Knoten einer Klasse Cj in eine minimale Anzahlvon Unterklassen Cj,1, . . . , Cj,kj

aufgeteilt. Für das Gewicht jeder Unterklasse Cj,l mit1 ≤ l ≤ kj muss ω(Cj,l) ≤ pi+1 und für die Gröÿe muss σ(Cj,l) ≤ 56 gelten. In Abbildung6 werden in (c) die Knoten markiert, welche zu einer Klasse zusammengeführt werdenkönnen. Da diese Knoten zusammen nicht die Grenzwerte überschreiten gehören sie auchzu einer Unterklasse.Der nale Graph Hi+1 wird nun aus H ′′

i+1 wie folgt konstruiert. Einmal besteht eraus allen schweren Knoten und allen Leichten Knoten dessen Grad gröÿer als 2 ist. DasGewicht dieser Knoten wird aus H ′′

i+1 übernommen. Weiterhin wird Hi+1 jeweils einKnoten für jede Klasse Cj,l der leichten Knoten hinzugefügt. Hier ist das Gewicht einesKnotens die Summe der Gewichte der Knoten in Cj,l. Der Graph Hi+1 ist in Abbildung6 in (d) zu sehen.

2.1.2 Laufzeit des Kontrahierens

Für das Finden der kontrahierbaren Kanten in H ′i+1 benötigt der Algorithmus O(sort(

∣∣H ′i+1

∣∣))Schritte, da alle Kanten danach geordnet werden müssen, ob sie kontrahierbar sind. Umdie leichten Knoten in die Klassen zusammenzufassen muss der Graph auch einmal sor-tiert werden, was O(sort(

∣∣H ′′i+1

∣∣)) Schritte benötigt. Da H ′′i+1 höchstens so viele Knoten

besitzt wie H ′i+1 und H ′

i+1 = Hi ist lässt sich die Laufzeit eines Kontraktoinsschrittesmit O(sort(|Hi|)) abschätzen. Da bei der ersten Kontraktion von G = H0 ausgegangenwird und sich die Gröÿe des Graphen in den einzelnen Kontraktionsschritten geome-trisch verringert(die Grenze pi verdoppelt sich in jedem Schritt), kann die Laufzeit desKontrahierens mit O(sort(|G|)) abgeschätzt werden.

70

Page 75: HEINZ NIXDORF INSTITUT Fakultät für Elektrotechnik ... Pottmeyer Memory Limitations in Artificial Intelligence ... Vitter hat gezeigt, dass viele in diesem Modell effiziente Entwicklungen

2.1.3 Erweitern des Seperators

Auf dem Graphen Hr kann nun ein Knotenseperator gebildet werden, welcher den Gra-phen in Teilgraphen der Gröÿe h ∗ log(B) aufteilt und dabei einen Seperaotr S erzeugt,welcher O(N/

√h) Knoten enthält.

Um nun den Seperator auf die vorhergehenden Kontratktionsschritte zu übertragenwird von einem Schritt Hj+1 mit den Seperatorknoten Sj+1 ausgehend der Seperatordes Schrittes Hj gebildet. Zuerst werden die Kontraktionen aller Knoten aus Sj+1 rück-gängig gemacht, welche bei dem Kontrahieren von Hj auf Hj+1 durchgeführt wurden.Die so entstehende Knotenmenge wird als S′

j bezeichnet. Diese Knotenmenge ist der vor-läuge Seperator des Graphen Hj . In Abbildung 7 ist dieser Schritt an einem Beispiel

Hj+1

Sj+1

Hj

S'j

Abbildung 7: Erweitern des Seperators

dargestellt. Weiterhin sind die dort im Graphen Hj die einzelnen, durch den Seperatorerzeugten, Teilgraphen zu sehen(gestrichelt umrahmt). Weiterhin kann es vorkommen,dass die Teilgraphen in Hj gröÿer als eine bestimmte Grenze sind. In diesem Fall wirdder entsprechende Teilgraph so weit aufgeteilt, dass jeder Teil diese Grenze unterschrei-tet. Die zusätzlichen Seperatorknoten, welche dabei entstehen, werden dem bisherigenSeperator S′

j hinzugefügt. Hieraus ergibt sich dann der endgültige Seperator Sj für denSchritt Hj .Diese Schritte werden für alle Kontraktionsschritte Hr, . . . ,H0 durchgeführt. So ent-

steht dann ein Seperator für den Graphen H0, welcher gleich dem Eingabegraphen G ist.Dieser Seperator muss aber noch nicht zwangsläug G in Teile aufteilen, dessen Gröÿekleiner oder gleich h ist. Hierzu wird jeder Teilgraph von G, welcher durch den SeperatorS0 entsteht in Teilgraphen partitioniert, welche kleiner oder gleich h groÿ sind. Weiter-hin müssen die so entstandenen Teilgraphen so umgeformt werden, dass sie nur

√h viele

Knoten als Nachbarknoten im Seperator S haben.

2.1.4 Laufzeit des Erweiterns

Um den erweiterten Seperator S′i aus Si+1 zu konstruieren werden O(sort(|Hi|)) Schritte

benötigt, da die entsprechenden Knoten in Hi gefunden werden müssen. Für die Partitio-nierung der entstehenden Teilgraphen, werden O(scan(|Hi|)) Schtitte benötigt, da jederTeilgraph mit konstanter Zahl von I/O Operationen in den Speicher eingelesen werden

71

Page 76: HEINZ NIXDORF INSTITUT Fakultät für Elektrotechnik ... Pottmeyer Memory Limitations in Artificial Intelligence ... Vitter hat gezeigt, dass viele in diesem Modell effiziente Entwicklungen

kann, da die Teilgraphen eine bestimmte Gröÿe nicht überschreiten. Insgesamt ergibt sichalso für das Erweitern eine Laufzeit von O(sort(N)), da der gröÿte Schritt H0 = G ist.Für den Gesamten Algorithmus, ergibt sich dann eine Laufzeit von O(sort(N)), da

das Kontrahieren, das Finden des Seperators auf dem kontrahierten Graphen und dasErweitern des Seperators jeweils O(sort(N)) I/O Operationen benötigen.

3 Kürzeste Wege und Breitensuche

Bei dem Kürzeste Wege Problem geht es darum die kürzesten Wege von einem Aus-gangsknoten s zu allen anderen Knoten des Graphen zu nden. In Abbildung 8 ist links

3s

1

5

1

3

21

62

2

1 23

35 1

2 s

3

3

6

4

9

4

81

5

1

3

21

62

2

61 23

Abbildung 8: Beispiel für Kürzeste Wege

ein Beispiel für einen Graphen zu sehen, auf welchem das Kürzeste Wege Problem gelöstwerden soll. Die Kanten des Graphen sind in diesem Fall gewichtet mit der Länge desWeges über die entsprechende Kante. Auf dem Graphen rechts sind dann die kürzestenWege zu den einzelnen Knoten, von der Quelle s aus, eingezeichnet.Bei der Breitensuche werden von dem Quellknoten s ausgehend die Nachbarknoten

gesucht. Hierbei werden die direkten Nachbarn von s besucht, danach die Knoten, wel-che zwei Kanten von s entfernt sind und so weiter. Die Einzelnen Knoten werden dannmit der kürzesten Entfernung zu s markiert. Aufgrund dieser Eigenschaften ist es ein-

1s

1

1

1

1

11

11

1

1 11

12 1

1 s

2

1

2

2

3

2

31

1

1

1

11

11

1

31 11

Abbildung 9: Beispiel für Breitensuche

fach die Breitensuche auf das Kürzeste Wege Problem zu reduzieren. Dazu müssen dieKantenlängen im Graphen alle auf das Gewicht 1 gesetzt werden. In Abbildung 9 ist einBeispiel hierfür zu sehen. Werden jetzt auf diesem Graphen die kürzesten Wege gesucht,

72

Page 77: HEINZ NIXDORF INSTITUT Fakultät für Elektrotechnik ... Pottmeyer Memory Limitations in Artificial Intelligence ... Vitter hat gezeigt, dass viele in diesem Modell effiziente Entwicklungen

so enthält jeder Knoten, als Entfernung zu s genau die Anzahl von Kanten, die er von sentfernt ist, da jede Kante nur das Gewicht 1 besitzt. Dies ist in Abbildung 9 rechts zusehen.

3.1 Planare Graphen und Gitter Graphen

Der folgende Algorithmus kann das Kürzeste Wege Problem auf Gitter und PlanarenGraphen lösen. Eingabe ist hier der Graph G = (V,E) sowie ein Ausgangsknoten s vonwelchem aus die küzesten Wege gesucht werden sollen. Um eine I/O eziente Lösung desProblem zu erreichen teilt der Algorithmus den Graphen zuerst in mehrere Teilgraphenauf. Auf diesen Teilgraphen kann mit wenigen I/O Schritten eine Teillösung berechnetwerden. Im nächsten Schritt wird dann jeder Teilgraph auf wenige Knoten reduziert.Aus diesen Knoten wird ein, im Gegensatz zu G reduzierter Graph gebildet, auf demdas Kürzeste Wege Problem gelöst werden kann. Zuletzt muss noch die Lösung auf demreduzierten Graphen mit der Lösung der Teilgraphen zu einer Gesamtlösung des Problemskombiniert werden. Wie sich die einzelnen Schritte im Detail gestalten wird im Folgendenerklärt.Um den Graphen aufzuteilen, wird mit dem Algorithmus aus Abschnitt 2.1 eine B2

Partition des Graphen G gesucht. Bei der Partitionierung entstehen O(N/B2) Teilgra-phen und O(N/B) Seperatorknoten. In Abbildung 10 ist einmal links ein Beispielgraphzu sehen, welcher als Eingabe für den Algorithmus verwendet wird. Der Übersichtlichkeithalber haben alle Kanten eine Länge von 1. Weiterhin ist in der Abbildung eine gefunde-ne Partition des Graphen in die Teilgraphen G1, . . . , Gk zu sehen. Für dieses Beispiel giltB = 2. Ein Teilgraph Gi darf also nicht gröÿer sein als 4 Knoten. Jeder dieser Teilgraphen

s sG1

G2

G3

G4

G5

s

3

3

3

2

2

Abbildung 10: Aufteilen des Graphen

hat bestimmte Knoten aus dem Seperator S, welcher die Partition des Graphen erzeugt,als Grenzknoten zu anderen Teilgraphen. Diese Grenzknoten werden mit den Knoten desentsprechenden Teilgraphen Gi zu Ri vereinigt.Die Teilgraphen Ri werden nun unabhängig voneinander betrachtet. Innerhalb eines

Teilgraphen wird nun der Kürzeste Weg von jedem, in Ri hinzugefügtem, Seperatorkno-ten zu allen anderen Seperatorknoten berechnet. Weiterhin wird aus den Seperatorknotenein Graph GR konstruiert. GR ist in Abbildung 10 rechts zu sehen. In GR gibt es eineKante zwischen einem Paar von Seperatorknoten, wenn es ein Ri gibt, welches die beiden

73

Page 78: HEINZ NIXDORF INSTITUT Fakultät für Elektrotechnik ... Pottmeyer Memory Limitations in Artificial Intelligence ... Vitter hat gezeigt, dass viele in diesem Modell effiziente Entwicklungen

Knoten enthält. Das Gewicht dieser Kante ist die, innerhalb von Ri berechnete, Entfer-nung. Bendet sich ein Paar von Seperatorknoten in mehreren Treilgraphen Ri, . . . , Rj

so wird das Gewicht der Kante zwischen den Knoten auf das geringste Gewicht aus denTeilgraphen gesetzt.Als nächstes wird auf GR das kürzeste Wege Problem gelöst. Es wird also zu jedem

Seperator Knoten die Entfernung zu s berechnet. Da GR aus den Sepertorknoten be-steht, benden sich O(N/B) Knoten in GR. Das Problem läst sich auf GR generell nichtI/O ezient schnell lösen. Aber da die Anzahl der Knoten O(N/B) ist, ergibt sich füreinen Algorithmus, welcher das kürzeste Wege Problem allgemein löst, eine Laufzeit vonO(sort(N)). Die kürzesten Wege auf GR sind in Abbildung 11 links zu sehen.

2

s

3 2

3

3

3

2

22

s

3 2

G2

G3

G4

G5

G1

2 1 2 3

1 s 4 3

2 3 1 2

3 2 3 3

G2

G3

G4

G5

G1

Abbildung 11: Übertragen der küzesten Wege auf die Teilgraphen

Mit den Entfernungen der Seperatorknoten zu s können nun innerhalb der TeilgraphenG1, . . . , Gk die Entfernungen zu den einzelnen Knoten berechnet werden. In Abbildung 11ist in der Mitte der Graph mit den Entfernungen der Seperaotrknoten zu sehen. Es wirdjetzt innerhalb eines jeden Teigraphen Gi der kürzeste Weg von einem Seperatorknotenu zu jedem Knoten v berechnet. Der letztendliche kürzeste Weg von s zu v ist dann derkleinste Wert für die Summe aus der Entfernung von s nach u und von u nach v. DieWerte für die küzesten Wege des Beispiels sind in Abbildung 11 rechts zu sehen.

3.1.1 Laufzeit des Algorithmus

Für das Finden der Partition wird der Algorithmus aus Abschnitt 2.1 verwendet, eswerden also O(sort(N) Schritte benötigt. Das Konstruieren der Teilgraphen benötigtO(scan(N)) I/O Operationen, da hier nur die einzelnen Teilgraphen G1, . . . , Gk nur ein-mal ausgelesen und mit den entsprechenden Seperatorknoten in den Speicher geschriebenwerden müssen. Um den Graphen GR zu erstellen und die Entfernungen zwischen denKnoten zu berechen werden O(scan(N)) Schritte benötigt, da hier jeweils nur die Teil-graphen G1, . . . , Gk in den Speicher eingelesen werden müssen, um die kürzesten Wegeinnerhalb des Speichers zu nden. Um die kürzesten Wege in GR zu berechnen, werdenwie oben schon erwähnt, O(sort(N)) Schritte benötigt. Für die kürzesten Wege inner-halb der Teilgraphen wird wieder jeder Teilgraph in den Speicher eingelesen, um diekürzesten Wege zu berechnen. Dies benötigt wieder O(scan(N)) Schritte. Da die lang-samste Laufzeit der einzelnen Schritte O(sort(N)) ist, ergibt sich eine Gesamtlaufzeit

74

Page 79: HEINZ NIXDORF INSTITUT Fakultät für Elektrotechnik ... Pottmeyer Memory Limitations in Artificial Intelligence ... Vitter hat gezeigt, dass viele in diesem Modell effiziente Entwicklungen

von O(sort(N)).

4 Tiefensuche

Bei der Tiefensuche werden auch die Knoten eines Graphen durchlaufen. Allerdings wirdhierbei nicht wie bei der Breitensuche alle Knoten in einer Entfernungsebene sofort be-sucht, sondern es wird zuerst versucht, in die Tiefe des Graphen zu gehen. In Abbildung12 ist ein Beispiel für den Durchlauf der Tiefensuche zu sehen. Die Knoten wurden in

11 6

10 s

9

1

5

8

4

2

7

3

Abbildung 12: Beispiel für Tiefensuche

der Reihenfolge ihrer Numerierung besucht. Hier wurde zunächst versucht eine Reihevon Knoten möglichst Tief in den Graphen hinein zu nden, bis ein Knoten keinen un-besuchten Nachbarknoten mehr besitzt. Dies ist im Beispiel bei Knoten 6 der Fall. Trittdies auf, so wird von dem entsprechenden Vorgängerknoten aus ein weiterer unbesuchterNachfolgeknoten gesucht. Dieser Ablauf wird so lange ausgeführt, bis alle Knoten desGraphen besucht wurden.

4.1 Planare Graphen

Um die Tiefensuche auf einem planaren Graphen I/O ezient zu gestalten wir die Struk-tur eines solchen Graphen ausgenutzt. Eine besondere Eigenschaft eines planaren Gra-phen ist es, dass es keine sich überkreuzenden Kanten gibt. Jede Fläche des Graphenist also nur auÿen durch Knoten und Kanten begrenzt. So ist es möglich die einzelnenFlächen den Graphen zu betrachten und diese in Ebenen zu ordnen.Der I/O eziente Tiefensuch-Algorithmus geht so vor, dass zuerst die Flächen des

Eingabe-Graphen G in Ebenen um eine anliegende Fläche des Startknotens s angeordnetwerden. Danach wird anhand dieser Ebenen ein Tiefensuch-Pfad durch den Graphenkonstruiert.Um zuerst den Graphen in die Ebenen zu partitionieren wird der in Abschnitt 3.1

vorgestellte Algorithmus zur Suche von küzesten Wegen bzw. zur Breitensuche verwendet.Zuerst wird aber in dem Graphen eine Fläche als die zentrale Fläche festgelegt. Danachmuss aus der Graph G zu einem sogenannten face-on-vertex Graphen erweitert werden.In Abbildung 13 ist einmal links ein Beispiel für einen Graphen zu sehen. Die ZentraleFläche ist die jenige, welche sich rechts unterhalb von dem Knoten s bendet. In der

75

Page 80: HEINZ NIXDORF INSTITUT Fakultät für Elektrotechnik ... Pottmeyer Memory Limitations in Artificial Intelligence ... Vitter hat gezeigt, dass viele in diesem Modell effiziente Entwicklungen

Mitte von Abbildung 13 ist der face-on-vertex Graph zu sehen. Hier wird einmal zujeder Fläche des Graphen ein Knoten hinzugefügt(weiÿe Kästchen) und dieser Knotenwird mit jeden Knoten von G verbunden, welcher die entsprechende Fläche begrenzt.Auf diesem Graphen wird nun die Tiefensuche gestartet und zwar ausgehend von dem

s

Abbildung 13: Patitionieren der Flächen in Ebenen

zu der zentralen Fläche hinzugefügten Knoten. Dieser ist in Abbildung 13 markiert. Mitdem Ergebnis der Tiefensuche lassen sich die die Flächen in die entsprechenden Ebeneneinteilen. Hierbei ist die Ebene i einer Fläche die DFS-Entfernung j/2 des face-on-vertexKnotens.Aus dieser Partitionierung heraus werden Teilgraphen H0, . . . ,Hk gebildet. Hierbei ent-

hält ein Teilgraph Hi alle Kanten aus der i-ten Ebene der Partition, welche mit keinemKnoten verbunden sind, welcher die Fläche einer tiefer liegenden Ebene begrenzt. In Ab-

H0

H1

H2H0

H1

H2E1

E2

E1

E2

s

Abbildung 14: Ermitteln des Tiefensuch Durchlaufs

bildung 14 sind links die Teilgraphen H1,H2,H3 des Beispielgraphen zu sehen. Weiterhinwerden Verbindungskanten E′′

1 , . . . , E′′k festgelegt, wobie E′′

i die Kanten sind, welche denTeilgraphen Hi mit der nächst niedrigeren Ebene verbinden. Diese Verbindungskantensind in Abbildung 14 in der Mitte zu sehen.Zuletzt wird nun der Tiefensuchbaum mit Hilfe der Teilgraphen H0, . . . ,Hk und den

Verbindungskanten E′′1 , . . . , E′′

k gebildet. Hierzu wird in dem untersten Teilgraphen H0

zuerst ausgehend von s ein ein Pfad um die Ebene 0 herum gelegt. Allerdings gehört dieletzte Kante nicht mehr zu dem Pfad, da sie sonst einen Kreis schlieÿen würde. Dies ist inAbbildung 14 rechts zu sehen. Um nun auf die nächst höhere Ebene i+1 zu gelangen wird

76

Page 81: HEINZ NIXDORF INSTITUT Fakultät für Elektrotechnik ... Pottmeyer Memory Limitations in Artificial Intelligence ... Vitter hat gezeigt, dass viele in diesem Modell effiziente Entwicklungen

aus den Verbindungskanten E′′i+1 der nächsten Ebene die Kante ausgewählt, welche den

Knoten aus der Ebene i, welcher am tiefsten in dem bisherigen Baum liegt, mit einemKnoten aus dem Teilgraphen Hi+1 verbindet. Danach werden dem Baum alle Kantenaus Hi+1 hinzugefügt, auÿer die letzte, welche einen Kreis schlieÿen würde. Dies ist inAbbildung 14 rechts in der zweiten Ebene zu sehen. Ist Hi+1 nicht zusammenhängend, sowird für jede zusammenhängende Komponente eine Kante aus den Verbindungskantenausgewählt. Dies ist in Abbildung 14 rechts in der ditten Ebene zu sehen. Wurden dieseAktionen für jede Ebene durchgeführt, ergibt sich ein Tiefensuch-Baum für den GraphenG.Laufzeit Um den Graphen in die Ebenen zu partitionieren wurde einmal der face-on-

vertex Graph konstruiert, was O(sort(N)) I/O Operationen benötigt, da zuerst in G dieFlächen gefunden werden und die entsprechenden Knoten ihnen zugeordnet werden müs-sen. Der Tiefensuch Durchlauf benötigt auch O(sort(N)) Schritte, wie in Abschnitt 3.1beschrieben. Um den Tiefensuch-Baum zu nden muss zu jedem Übergang zwischen denEbenen die Verbindungskante gefunden werden, wozu die Teilgraphen Hi und Hi+1 un-tersucht werden müssen. Es ergibt sich hierfür also eine Laufzeit von O(sort(|Hi|+|Hi+1|.Da insgesamt jedes Hi nur zwei mal betrachtet wird, lässt sich die Gesamtlaufzeit fürdas Finden des Tiefensuch-Baumes auf O(sort(N)) abschätzen. Für die Gesamtlaufzeitergibt sich also eine Laufzeit von O(sort(N)).

Literatur

[1] L. Toma, N. Zeh. I/O-Ecient Algorithms for Sparse Graphs. In Algorithms forMemory Hierarchies, pages 85109. 2003.

[2] A. Maheshwari and N. Zeh. I/O-ecient algorithms for graphs of bounded tree-width. In Proc. 12th Ann. Symp. on Discrete Algorithms, pages 89-90. ACMSIAM,2001.

[3] L. Aleksandrov and H. Djidjev. Linear algorithms for partitioning embedded graphsof bounded genus. SIAM Journal of Discrete Mathematics, pages 129-150, 1996.

77

Page 82: HEINZ NIXDORF INSTITUT Fakultät für Elektrotechnik ... Pottmeyer Memory Limitations in Artificial Intelligence ... Vitter hat gezeigt, dass viele in diesem Modell effiziente Entwicklungen

78

Page 83: HEINZ NIXDORF INSTITUT Fakultät für Elektrotechnik ... Pottmeyer Memory Limitations in Artificial Intelligence ... Vitter hat gezeigt, dass viele in diesem Modell effiziente Entwicklungen

Algorithmische Geometrie im externen Speicher

Raphael Golombek

1 Einleitung

Algorithmische Geometrie ist ein Bereich der Informatik, der sich mit der Entwicklungeffizienter Algorithmen zur Lösung geometrischer Probleme und deren Analyse beschäf-tigt.Seit den Anfängen in den 70er Jahren entwickelte sich dieser Bereich zu einer übergreifen-den Disziplin, die in Bereiche wie Komplexitätstheorie oder Algorithmenentwurf Einzugerhielt. Das Einsatzfeld für geometrische Algorithmen ist vielfältig, und viele Problem-stellungen basieren auf realen Anwendungsbereichen.In der Computergrafik werden räumliche Datenstrukturen im Zusammenspiel mit Ver-deckungsalgorithmen eingesetzt. Die so mögliche frühe Datenreduktion beschleunigt dieBerechnung der Einzelnen Bilder einer Szene.Im Bereich der Datenbanken werden große Datensätze über ihre Attribute als Punkte ineinem mehrdimensionalen Raum interpretiert. Mit Hilfe von geometrischen Algorithmenkönnen hier Bereichsanfragen effizient beantwortet werden.Durch den rasanten technischen Fortschritt wuchs die Speicherkapazität der Computerund somit auch die Einsatzmöglichkeiten. Hochauflösende Bilder nun in hoher Anzahlgespeichert werden. Die NASA z.B. stellt mit ihrem Programm „World Wind“ insgesamt4.6 Terabyte Bildmaterial, unserer Erdoberfläche in verschiedenen Auflösungen, zur Ver-fügung. Daten mit diesen Ausmaß können zur Verarbeitungszeit nicht mehr komplett iminternen Speicher gehalten werden und müssen auf, den deutlich langsameren, externenSpeicher ausgelagert werden. In solch einem Fall wird die Laufzeit eines Algorithmusnicht mehr durch die Anzahl seiner Rechenschritte dominiert, sondern durch die Anzahlder Datenzugriffe(im weiteren I/O´s) auf den Externen Speicher. Diese Erkenntnis führteAnfang der 90er Jahre zur Intensivierung der Forschung im Bereich der geometrischenAlgorithmen im externen Speicher.In dieser Seminararbeit werden Algorithmen zur Lösung geometrischer Probleme im ex-ternen Speicher vorgestellt. Aufgrund der Komplexität der Algorithmen und den Ein-schränkungen bezüglich der Ausmaße dieser Ausarbeitung, werden nur drei der 22 Pro-blemstellungen in aller Ausführlichkeit beschrieben Tabelle 1 auf der nächsten Seite zuallen Anderen wird eine kurze Zusammenfassung der Problemstellung und Lösung vor-gestellt.

2 Das Externe Speichermodell

Bevor die einzelnen Problemstellungen genauer betrachtet werden, wird in diesem Kapiteldas, der Analyse zu Grunde liegende Speichermodell [3] vorgestellt. Eine grundlegendeEigenschaft des hier betrachteten externen Speichers ist die extrem lange Zugriffszeit

Page 84: HEINZ NIXDORF INSTITUT Fakultät für Elektrotechnik ... Pottmeyer Memory Limitations in Artificial Intelligence ... Vitter hat gezeigt, dass viele in diesem Modell effiziente Entwicklungen

No. Name des Problems No. Name des Problems

1 Convex Hull 12 Segmentstabbing2 Halfspace Intersection 13 Segment Sorting3 Closest Pair 14 Endpoint Dominance

4 K-Bichromatic Closest Pairs 15 Trapezoidal Decomposition

5 Nearest Neighbor 16 Polygon Triangulation6 All Nearest Neighbors 17 Vertical Ray-Shooting7 Reverse Nearest Neighbors 18 Planar Point Location8 K-Nearest Neighbors 19 Bichromatic Segment Intersection9 Halfspace Range Searching 20 Segment Intersection10 Orthogonal Range Searching 21 Rectangle Intersection11 Voronoi Diagram 22 Polygon Intersection

Tabelle 1: Markierte Probleme werden detaillierter erklärt

in Relation zu der Zugriffszeit auf den internen Speicher. Es basiert darauf, dass Da-ten zwischen den verschiedenen Speicherschichten blockweise übertragen werden, dabeiist im Rahmen dieser Seminararbeit die Betrachtung des Hauptspeichers und externerMassenspeicher (Festplatten) ausreichend. Das Modell besitzt folgenden Parameter:

N = Anzahl Elemente im ProblembereichM = Anzahl Elemente, die gleichzeitig in den Hauptspeicher passenB = Anzahl Elemente, die in einen Block passenD = Anzahl unabhängiger FestplattenP = Anzahl parallel arbeitender ProzessorenQ = Anzahl gleichzeitiger AnfragenZ = Anzahl Elemente im Antwortset

Die Parameter D und P sind bei den hier vorgestellten Problemen immer mit 1 vorbe-legt. Die letzten zwei Parameter sind Zusätze für Algorithmen, die mehrere gleichzeitigeAnfragen erlauben.

Da bei einem I/O-Zugriff stets ein Block gelesen wird, führen wir weitere Variablenein um die Laufzeitanalyse lesbarer zu gestalten.

n = NB , k = K

B , t = TB , m = M

B .

Abbildung 1 auf der nächsten Seite verdeutlicht nochmals den Modellaufbau.Das Modell erlaubt nur Operationen auf Elementen im Hauptspeicher, falls weitere Ele-mente zur Berechnung gebraucht werden, muss eine I/O-Operation durchgeführt werden.Die Leistung eines externen Algorithmus wird hier anhand der I/O-Zugriffe und demSpeicherverbrauch während seiner Laufzeit gemessen.Im Folgenden werden einige oft verwendete Techniken zum Lösen geometrischer Proble-me vorgestellt. Diese können mit kleinen Anpassungen auch für geometrische Problemeim externen Speicher genutzt werden. Als erstes wird das Konzept der Reduktion vor-gestellt, ein Beispiel einer Reduktion mittels geometrischer Dualität ist im Kapitel 5 auf

Page 85: HEINZ NIXDORF INSTITUT Fakultät für Elektrotechnik ... Pottmeyer Memory Limitations in Artificial Intelligence ... Vitter hat gezeigt, dass viele in diesem Modell effiziente Entwicklungen

Large Memory

CPU

Fast Memory

M

B

Abbildung 1: Externes Speichermodell

Seite 13 gegeben. Eine weitere, oft angewendete Technik, ist das „Plane Sweeping“. Fürden externen Speicher angepasst, wird es als „Distribution Sweeping“ bezeichnet.

2.1 Reduktion

Die Reduktion ist eine gängige Methode um Algorithmen für Probleme, aus bereits ge-lösten Problemstellungen, abzuleiten. Das Vorgehen dabei sieht wie folgt aus.Gegeben seien zwei Probleme A und B. Für das Problem B ist die Lösung bekannt, wei-terhin kennen wir die Laufzeit O(fB(N)) eines Algorithmus, der das Problem B löst. Wirwollen nun das Problem A mit Hilfe von B lösen und gehen dazu in zwei Schritten vor:

1. Zuerst transformiere die Eingabe des Problems A in eine Eingabe vom Typ B.

2. Früher den Algorithmus für das Problem B mit der transformierten Eingabe aus.

3. Transformiere die Ausgabe vom Typ in eine Ausgabe vom Typ A und gebe sie Aus.

Dabei gilt die Bedingung, dass die Transformationen zwischen den Eingaben bzw. Aus-gaben der zwei Typen nicht mehr Zeit in Anspruch nehmen, als der Algorithmus für dasProblem B zur Berechung des Ergebnisses benötigt.

2.2 Distribution Sweeping

Viele effiziente, interne Algorithmen basieren auf der „plane sweeping“ [9] Technik. DieGrundidee ist es ein statisches d+1-Dimensionales Problem in endlich viele dynamischkonfigurierte d-Dimensionale Probleme aufzuteilen und diese zu Lösen. Dabei lassen sichdamit die 2-Dimensionalen Problemstellungen am effektivsten lösen, daher wird im Fol-genden auch nur dieser Fall betrachtet.Bei der plane Sweeping Technik wird eine gedachte Linie, senkrecht zu der x-Achse, überdie Datenmenge geführt, jedes Element das zum Zeitpunkt t von der gedachten Liniegeschnitten wird, gilt als aktiv zum Zeitpunkt t. Nur aktive Objekte werden in den Be-rechnungen einbezogen. Das Problem muss dabei so modelliert werden, dass die aktivenElemente ausreichen um eine gültige Lösung zu ermitteln. Alle aktiven Elemente wer-den in einer „sweep-line“ Struktur verwaltet, die bei jedem Ereignis aktualisiert wird.

Page 86: HEINZ NIXDORF INSTITUT Fakultät für Elektrotechnik ... Pottmeyer Memory Limitations in Artificial Intelligence ... Vitter hat gezeigt, dass viele in diesem Modell effiziente Entwicklungen

Diese Datenstruktur kann in logarithmischer Zeit verwaltet werden, wenn die Elmentedes Problems sortierbar sind z.B. bezüglich der y-Achsenwerte. Ereignisse sind Zustands-wechsel bezüglich des Schnittes eines Elements mit der gedachten Linie und werden ineiner Prioritätswarteschlange verwaltet. Auch die Warteschlange kann in logarithmischerZeit verwaltet werden, falls die Liste der aktiven Elemente sortierbar ist. Aufgrund dieserEigenschaften sind viele Algorithmen aufbauend auf der plane sweeping Technik optimal.Eine direkte Umsetzung dieser Technik im externen Speicher würde bei Algorithmen miteiner Laufzeit von O(N ∗ log2N) zu O(N ∗ logBN) vielen externen Speicherzugriffen füh-ren. Bei Problemen mit einer externen unteren Schranke von Ω(n ∗ logmn) könnte mandamit also keine optimale Lösung finden. Die externe Variante wird verbessert indemman den Algorithmus rekursiv anwendet und den Problemraum in Θ(m) viele vertika-le Streifen unterteilt. In jeder Rekursionstiefe werden nur Elemente verarbeitet, die mitElementen anderer Streifen interagieren. Interaktionen innerhalb eines Streifens werdenin späteren Rekursionsschritten behandelt. Die Rekursion bricht ab, wenn das Subpro-blem komplett in den Hauptspeicher passt. Durch die Unterteilung kann pro Streifenimmer ein Datenblock im Hauptspeicher gehalten werden. Da die Steifen Senkrecht sind,wird auch die sweeping line Senkrecht geführt. Falls nun eine Rekursionstiefe mit einerlinearen Anzahl von I/Os auskommt, ist die gesamte Laufzeit des Distribution SweepingO((n)logm(n)). Diese Aufteilungstechnik wurde ursprünglich in dem „distribution sort“[17] Algorithmus verwendet, daher wird diese externe Variante des „plane sweeping“ Algo-rithmus auch „distribution sweeping“ genannt. Abbildung 2 soll das distribution sweepinggraphisch verdeutlichen.

M/B viele Streifen in jeder Rekursionstiefe

Abbildung 2: Distribution sweeping

Page 87: HEINZ NIXDORF INSTITUT Fakultät für Elektrotechnik ... Pottmeyer Memory Limitations in Artificial Intelligence ... Vitter hat gezeigt, dass viele in diesem Modell effiziente Entwicklungen

3 Endpoint Dominance Problem

Problemdefinition: Sei S eine Menge von N sich nicht überschneidender Segmente inder Ebene. Finde für jeden Endpunkt eines Segments in S das dominante Segment (fallsexistent). Als dominantes Segment bezüglich eines Punktes p wird das direkt darüberliegende Segment bezeichnet.Abbildung 3 zeigt die dominanten Elemente einiger Segmente.

Abbildung 3: Endpunkte und ihre dominanten Segmente

Grundidee der Lösung:

1. Baue einen Segmentbaum auf, der die Menge S der Segmente „anfragefreundlich“abspeichert.

2. Durchlaufe den Baum gleichzeitig für alle Segmentendpunkte, berechne das domi-nante Segment für jeden Anfragepunkt und gebe es aus.

Bei dem Endpoint Dominance Problem (EDP) wird zur Datenverwaltung einer, andie Problemstellung angepasster externer Segmentbaum verwendet. Um viele Anfragengleichzeitig und effizient zu beantworten werden die Segmente im Baum ähnlich der Tech-nik der fraktionalen Kaskadierung [5] vorverarbeitet.

3.1 Externer Segmentbaum:

Ein Segmentbaum ist eine dynamische Datenstruktur zum Abspeichern einer Menge vonSegmenten bezüglich einer Dimension. Er ist so aufgebaut, dass bei gegebenem Anfra-gepunkt alle Segmente, die diesen enthalten, effizient ausgegeben werden können. DerSegmentbaum ist perfekt balanciert, alle inneren Knoten haben einen Ausgangsgrad von√

(m/4). Die Blätter enthalten jeweils M/2 viele aufeinander folgende Segmentendpunk-te, die Tiefe des Baumes beträgt O(logmn). Abbildung 4 auf der nächsten Seite zeigt

Page 88: HEINZ NIXDORF INSTITUT Fakultät für Elektrotechnik ... Pottmeyer Memory Limitations in Artificial Intelligence ... Vitter hat gezeigt, dass viele in diesem Modell effiziente Entwicklungen

einen Segmentbaum.

slab_1 slab_2 slab_3 slab_4 slab_5

multislab_3-4

multislab_2-4

multislab_1-5

........ ........ ........ ........ ........

....

....

....

....

....

.......................

O(logmN/B)

Abbildung 4: Segmentbaum mit Slabs und Multislabs

3.1.1 Slabs und Multislabs:

Jeder Knoten im Baum ist mit einem Bereich des Problemraumes assoziiert in dem al-le Segmentendpunkte liegen, die im Baum unter diesem Knoten eingeordnet sind. Wirbezeichnen solch einen Bereich als Slab, in der Abbildung 4 sind Slabs durch gepunk-tete Linien dargestellt. Zusammenhängende Slabs werden als Multislabs bezeichnet, dieAnzahl der Multislabs pro Knoten beläuft sich auf m/8−

(m/4). Eine wichtige Beob-achtung ist hier, dass die Anzahl der Multislabs quadratisch von dem Verzweigungsgraddes Baumes abhängt. Dies ist auch der Grund den Verzweigungsgrad als

(m/4) zuwählen, da dadurch die Anzahl der Multislabs pro Knoten in O(m) liegt und somit min-destens ein Block pro Multislabliste gleichzeitig im Hauptspeicher gehalten werden kann.

3.1.2 Klassifizierung der Segmente

Beim Aufbau des Segmentbaums unterscheiden wir zwei Typen von Segmenten, langeund kurze Segmente. Diese Unterscheidung wird im Algorithmus verwendet um die Seg-mente in der richtigen Baumtiefe abzulegen. Lange Segmente sind Segmente, die ein odermehrere Slabs überlappen, eine Kopie eines solchen Segment wird in der Multislabliste,des größten Multislabs das es überlappt, gespeichert. Kurze Segmente sind alle Segmente,die nicht als Lange Segmente bezeichnet werden. Diese Segmente werden tiefer in denBaum geschickt, wo sie vielleicht als lang klassifiziert werden und abgespeichert werden.Die Teile langer Segmente, die ein Slab nur teilweise überlappen, also überstehende Be-reiche, werden kopiert und als kurze Segmente behandelt. Da maximal 2 solcher Teile proSegment und pro Baumtiefe anfallen, ergibt sich eine maximale Anzahl abzuspeichernder

Page 89: HEINZ NIXDORF INSTITUT Fakultät für Elektrotechnik ... Pottmeyer Memory Limitations in Artificial Intelligence ... Vitter hat gezeigt, dass viele in diesem Modell effiziente Entwicklungen

Segmente von O(n ∗ logmn).

3.1.3 Aufbau eines Externen Segmentbaumes

Die Baumstruktur wird nun mit Segmenten gefüllt, dabei sollen die Segmente, wie in 3.1.1 aufder vorherigen Seite beschrieben im Baum abgelegt werden. Zusätzlich wird verlangt,dass die Segmente in den Multislablisten, in denen sie referenziert sind, bezüglich ihrery-Koordinate sortiert sind. Da wird beim EDP nur mit sich nicht schneidenden Segmentenarbeiten, ergibt sich eine solche eindeutige Sortierung indem man Segmente bezüglich dery-Werte an einer der Grenzen des Multislabs sortiert. Diese Sortierung wird im weiterenTeilen des EDP-Algorithmus immer wieder verlangt um effizient zu arbeiten, dazu mussjedoch noch gezeigt werden, dass die bereits sortierten Multislablisten eines Knotens aufeffizientem Wege zu einer sortierten Multislabliste gemischt werden können.

Lemma 1: Die N Segmente, die in den Multislablisten eines internen Knotens in ei-nem Externen Segmentbaum gespeichert sind, können mit O(n) vielen I/O-Operationensortiert werden.Beweis: Wir behaupten, dass man die Sortierte Liste aller Segmente aufbauen kann,indem man wiederholt die obersten Elemente, der bereits sortierten Multistablisten, be-trachtet und stets das Höchste, bezüglich der y-Koordinate, als nächstes auswählt. Wirnehmen widersprüchlich an, es gibt ein oberstes Segment s in einer der Multistablistenwelches über allen anderen oberstes Segmenten der anderen Multistablisten liegt, jedochunter einem noch nicht verarbeiteten Segment t liegt. So existiert eine Reihe von Seg-menten s1, s2, ..., si für die gilt t liegt über s1, s1 über s2 und si über s. Aber wenn si

über s liegt, wird die Bedingung, dass s über allen anderen obersten Segmenten liegt,verletzt.Da es O(m) viele Multislablisten gibt, kann pro Liste ein Block im Speicher gehalten wer-den. Somit lässt sich die sortierte Liste mit O(n) vielen I/O-Operationen durch einemstandard externen Sortieralgorithmus aus O(m) vielen Multislab Listen erstellen.

¤

Um nun den externen Segmentbaum aus N Segmenten aufzubauen wird als erstes eine,bezüglich der x-Achse, sortierte Liste aller Segmentendpunkte berechnet. Dies geschiehtmit einem standard Sortieralgorithmus mit O(n∗ logmn) externen I/Os. Diese Liste wirdim Algorithmus benutzt um die Intervallgrenzen für die

(m/4) vielen Slabs eines Kno-tens zu berechnen. Danach werden die O(m) vielen Multislablisten eines Knotens wie folgterstellt. Durch einen Scan werden die langen Segmente auf die entsprechenden Multisla-blisten verteilt. Danach werden alle Multislablisten bezüglich der y-Koordinate sortiert.Bis auf die Wurzel haben alle Knoten einen Elternknoten, von diesem erhält jeder zweisortierte Listen von Segmenten. Diese Listen werden auf die sortierten Multistablistenverteilt. Die Kinder des aktuellen Knotens erwarten auch zwei sortierte Listen als Ein-gabe. Die erste Liste enthält alle langen Segmente, die einen Endpunkt in dem Slab desjeweiligen Kindknotens hat und den anderen Endpunkt links von diesem Slab. Die zweite

Page 90: HEINZ NIXDORF INSTITUT Fakultät für Elektrotechnik ... Pottmeyer Memory Limitations in Artificial Intelligence ... Vitter hat gezeigt, dass viele in diesem Modell effiziente Entwicklungen

Liste wird genauso aufgebaut, diesmal ist jedoch der zweite Endpunkt rechts vom Slab.Da beide Listen aus den bereits sortieren Multislablisten Konstruiert werden, sind siebezüglich des y-Wertes sortiert. Abbildung 5 verdeutlicht die Aufteilung der Segmente.

Elternknoten berechnet 2 Listen pro Kindknoten

k

v(k)

Slab von klinke Segmentliste

von Kind k

rechte Segmentliste

von Kind k

Abbildung 5: Endpunkte und ihre dominanten Segmente

Das einmalige Sortieren der Endpunkte kostet O(n ∗ logmn) I/Os. Die Segmente in einerTiefer können in O(n) I/Os auf die Multistablisten verteilt werden, insgesamt kostestdas in allen Tiefen zusammen O(n ∗ logmn) I/Os. Das Sortieren der Segmente in denMultistablisten eines Segmentbaums der Tiefe O(logmn) kostet zusammen O(n ∗ logmn)I/Os, dies ist nur möglich durch die Wiederverwendung der Vorsortierung mittels derzwei Listen, dadurch wird jedes Segment nur einmal in irgendeiner Tiefe sortiert. Wür-de man den Segmentbaum ohne diese Listen aufbauen, müssten in jeder RekursionstiefeO(n ∗ logmn) I/O-Operationen ausgeführt werden. Die Verwendung der zwei Listen ver-bessert die Laufzeit des Aufbaus von O(n*log2

mn) auf O(n ∗ logmn) I/Os.

3.1.4 Anfragen im Externen Segmentbaum

Der im vorherigen Kapitel aufgebaute externe Segmentbaum kann nun verwendet werdenum die 2N vielen dominanten Segmente zu berechnen. Der folgende einfache Algorithmusfindet das dominante Segment für einen Anfragepunkt p:

1. Untersuche jeden Knoten von der Wurzel aus auf dem Weg zu den Blatt, dass diex-Koordinate des Punktes p enthält.

2. An jedem Knoten, suche in allen Multislablisten, die p enthalten, nach dem lo-kal dominanten Segment und vergleiche es mit dem bisher global dominantestenSegment.

Page 91: HEINZ NIXDORF INSTITUT Fakultät für Elektrotechnik ... Pottmeyer Memory Limitations in Artificial Intelligence ... Vitter hat gezeigt, dass viele in diesem Modell effiziente Entwicklungen

3. Bei dem Blatt das p enthält angekommen gebe das global dominante Segment aus.

Um alle 2N Anfragepunkte gleichzeitig zu verarbeiten, kann eine, dem „batch filtering“ähnliche, Technik [8] verwendet werden. Dabei werden alle Anfragepunkte erst in einerBaumtiefe verarbeitet, bevor sie in die Nächste verschoben werden. Bei diesem Vorgehenwird die zeitliche Lokalität ausgenutzt um die Anzahl der I/Os zu reduzieren.Trotz der erwähnten Optimierung erzielt dieser Algorithmus nicht die gewünschte Lauf-zeit von O(n ∗ logmn). Maßgebend ist hier, dass pro Anfragepunkt O(m) viele Multisla-blisten eines Knotens geprüft werden müssen und jede dieser Listen O(n) viele Elementeenthält. Bei O(n) Anfragepunkten und einer Segmentbaumtiefe von O(logmn) brauchtder Algorithmus ungünstige O(n2 ∗ logmn) I/O-Operationen.Gesucht wird ein Algorithmus der mit O(n ∗ logmn) I/O-Operationen auskommt, dazudürfen in jeder Tiefe des Segmentbaumes nur linear viele Operationen, für alle Anfra-gepunkte zusammen, durchgeführt werden. Der hier gemachte Ansatz basiert auf einerder fraktionalen Kaskadierung [4, 5] ähnlichen Technik als Vorverarbeitungsschritt undeinem gleichzeitigen propagieren aller Anfragepunkte durch den Segmentbaum von denBlättern aus.Im Vorverarbeitungsschritt werden einige Segmente aus den Elternknoten in die Kinder-knoten verteilt, startend mit der Wurzel wird für jedes der

(m/4) vielen slabs eineSampleliste erstellt. In die Samplelisten legen wir jedes 2 ∗

(m/4)- te Segment rein,das das entsprechende Slab überlappt und schneiden dies auf die Größe des Slabs zu.Die so verteilten Segmente werden im Folgenden Samples genannt. Die relevanten Seg-mente werden durch Scannen der sortierten Liste aller Segmente des aktuellen Knotensermittelt, nach Lemma 3.1.3 auf Seite 7 gelingt das in O(n). Zusätzlich werden

(m/4)viele Zähler verwaltet um die Segmente auszuwählen. Die Samples eines Slabs werden inseine Multislabliste, die die Segmente enthält die das ganze Slab überlappen, eingefügt.Die Samples werden auch an die Blätter verteilt. Dadurch werden Informationen überSegmente des Elternknotens an die Kinder weitergegeben. Im Späterem Verlauf werdenwir sehen wie dies ausgenutzt werden kann, um nur noch potentiell dominante Segmentebezüglich eines Anfragepunktes zu betrachten. Zunächst muss ein Lemma bezüglich derLaufzeit, des Speicherverbrauchs und der Ausgabe der Vorverarbeitung bewiesen werden.

Lemma 2: Die beschriebene Vorverarbeitung kann in O(n ∗ logmn) I/O-Operationendurchgeführt werden. Danach sind immer noch O(N) Segmente in jeder Schicht des Seg-mentbaums gespeichert. Die Blätter enthalten weniger als M viele Segmente.Beweis: Bevor irgendwelche Samples im Baum nach unten gereicht werden, sind in je-der Tiefe maximal 2N viel Segmente. Sei Ni die Anzahl langer Segmente, Originale undSamples, aller Knoten in einer Tiefe i nach der Vorverarbeitung. Für die Wurzel giltN0 ≤ 2N .

Es werden maximal Ni/(2 ∗√

m/4) ∗√

(m/4) = Ni/2 viele Samples in die (i+1)-teTiefe geschickt. Es gilt also Ni+1 ≤ 2N + Ni/2. Durch Induktion können wir zeigen dassfür alle i gilt, Ni = (4 − (1/2)i − 1) ∗ N = O(N).

Nach Lemma 3.1.3 auf Seite 7 und weil es O(m) viele Multislablisten gibt folgt, dasswir auf jedem Segment konstant viele I/O-Operationen durchführen. Die Anzahl von

Page 92: HEINZ NIXDORF INSTITUT Fakultät für Elektrotechnik ... Pottmeyer Memory Limitations in Artificial Intelligence ... Vitter hat gezeigt, dass viele in diesem Modell effiziente Entwicklungen

Operationen in einer Tiefe i ist dann O(ni) mit ni = Ni/B. Somit folgt, dass die Vorver-arbeitung O(n ∗ logmn) viele I/O-Operationen benötigt.

Vor der Vorverarbeitung ist die Anzahl der Segmente in einem Knoten einer Baum-tiefe i kleiner als die Summe aller Endpunkte die in den Blättern unter diesem Knoten

gespeichert sind d.h. es sind weniger als M/2 ∗√

(m/4)i. Betrachten wir die Anzahl der

Segmente die ein Blatt in der Tiefe l nach der Vorverarbeitung besitzt. Da wir jedes√

2 ∗ (m/4)-te Segment samplen, sind weniger als M/2 + Nl−1/2 ∗√

(m/4) Segmentein einem Blatt der Tiefe l vorhanden, wobei Nl−1 die maximale Anzahl von Segmenteneines Knotens der Tiefe l − 1 ist. Daraus folgt,

Nl ≤ M/2 + M/4 +Nl−2

2 ∗√

(m/4)2.

Lösen wir die Reihe bis zur Wurzel auf, ergibt sich Nl < M.

¤

Nach der Vorverarbeitung sollen nun die 2N vielen Anfragen durch den Segmentbaumpropagiert werden. Beim fraktionalen Kaskadierung werden die Elternknoten mit Infor-mationen aus den Kinderknoten angereichert und der Baum von der Wurzel an durch-laufen. Hier jedoch haben wir die Informationen von „Oben nach Unten“ geschickt, somüssen wir die Anfragen von den Blättern aus bis hin zur Wurzel propagieren.Im ersten Schritt werden Alle 2N Anfragepunkte bezüglich ihrer x-Koordinate mit O(n∗logmn) I/Os sortiert und mit einem Scan in O(n) I/Os den entsprechenden Blätternzugeordnet. Dies ergibt für jedes Blatt eine unsortierte Liste von Anfragepunkten. Alsnächstes wird über alle Blätter iteriert und in jedem Blatt die lokal dominanten Segmen-te, der dort enthaltenen Anfragepunkte, berechnet. Alle Segmente eines Blattes Passenlaut Lemma 3.1.4 auf der vorherigen Seite auf einmal in den Hauptspeicher, daher könnenwir sie alle dort einladen und einen internen Algorithmus zum Suchen der lokal dominan-ten Segmente verwenden. Da es in den Blättern O(N) viele Segmente gibt, kann dies inO(2n + n) I/O-Operationen geschehen. Nun werden die Anfragepunkte in den Blätternbezüglich ihrer lokal dominanten Segmente in O(n ∗ logmn) sortiert.Die Daten sollen von den Kindern an die Eltern weitergereicht werden, dazu muss einKindknoten eine einzelne Liste an den Vaterknoten weitergeben. Dieser Schritt wird als„Filtern“ bezeichnet. Beim Filtern werden die

(m/4) (Verzweigungsgrad des Segment-baums) vielen sortierten Listen von Anfragepunkten zu einer sortieren Liste zusammen-gefügt. Weiterhin werden wieder

(m/4) Listen benötigt, diesmal enthalten sie aberSegmente, von denen das jeweilige Slab überspannt wird. Überspannt z.B. ein Segment4 slabs, so taucht er in ihren Listen auf. Wir Scannen nun die Liste aller Segmente undverteilen die überspannenden Segmente, falls wir auf ein Segment stoßen welches in denSlab s als Sample vorkommt, halten wir an und verarbeiten alle Anfragepunkte zwi-schen diesem Segment und dem davor in s gesampelten Segment. Diese Anfragepunktekommen in der sortieren Anfrageliste des Slabs s hintereinander vor. Danach wird dieSegmentliste, die s überspannt, geleert. Wichtig ist hierbei, dass wir zur keiner Zeit mehrals 2 ∗

(m/4) Segmente pro Slab im Speicher halten, bei√

(m/4) vielen Slabs, reicht

Page 93: HEINZ NIXDORF INSTITUT Fakultät für Elektrotechnik ... Pottmeyer Memory Limitations in Artificial Intelligence ... Vitter hat gezeigt, dass viele in diesem Modell effiziente Entwicklungen

unser interner Speicher also aus um den Scan, ohne die Verarbeitung der Anfragepunktezwischen zwei Samples, in linearer Anzahl von I/Os durchzuführen.Um die Anfragepunkte zwischen zwei Samples zu verarbeiten, reservieren wir 2∗

(m/4)Blöcke Speicher, für jedes Segment zwischen den zwei Samples jeweils einen Block. DieBlöcke dienen zum Abspeichern der Anfragepunkte, für die das entsprechende Segmentein lokal dominantes Segment ist. Die Anfragen werden aus der sortierten Liste betrach-teten Slabs ausgelesen und auf die Blöcke verteilt, danach werden die Listen konkateniertund an die Ausgabeliste des Slabs angehängt.Ist der Scan der Multislabliste durchgelaufen, mischen wir die Ausgabelisten der Slabs zueiner Eingabeliste für den Elternknoten. Das Mischen der O(m) sortieren Listen geschiehtnach Lemma 3.1.3 auf Seite 7 in O(n). In der Wurzel angekommen, die dominanten Seg-mente aller 2N Anfragepunkte ermittelt.Fassen wir die verbrauchten Ressourcen noch mal zusammen:

Teilaufgaben Speicher Anz. I/OsAufbau des Segmentbaums

Segmente vorsortieren bezüglich x-Achse O(n ∗ logmn) O(n ∗ logmn)Verteilen der Segmente auf Multislabs O(n ∗ logmn) O(n ∗ logmn)Multislablisten in O(logmn) Ebenen sortieren O(n ∗ logmn) O(n ∗ logmn)Vorverarbeitung des Segmentbaums

Erstellen und Verteilen der Samples O(n ∗ logmn) O(n ∗ logmn)2n Anfragen im Segmentbaum

Anfragen bez. x-Koordinate sortieren1 O(n ∗ logmn) O(n ∗ logmn)Zu den Blättern zuordnen1 O(n) O(n)Lokal dominante Segmente ermitteln 1 O(n) O(n)Anfragen bez. der lokal dominanten Segmente sortieren1 O(n ∗ logmn) O(n ∗ logmn)Filterschritte O(n ∗ logmn) O(n ∗ logmn)Gesamt O(n ∗ logmn) O(n ∗ logmn)

Der hier vorgestellte Algorithmus löst das Endpoint Dominance Problem in O(n∗ logmn)I/Os und braucht dazu zu keinem Zeitpunkt mehr als O(n ∗ logmn) Speicherblöcke.

4 Trapezoidal Decomposition Problem

Das Trapezoidal Decomposition Problem ist stark mit dem Endpoint Dominance Pro-blem verwandt, trotzdem ist es als eigenständige Problemstellung von Interesse. Es wirdoft als ein Vorverarbeitungsschritt benutzt z.B. beim Lösen des Planar Point LocationProblem [11, 15] oder bei einem Algorithmus zur Polygon Triangulation.

Problemdefinition: Gegeben sei eine Menge N sich nicht schneidernder Segmente in

1Einmalig zu Beginn des Anfragealgorithmus

Page 94: HEINZ NIXDORF INSTITUT Fakultät für Elektrotechnik ... Pottmeyer Memory Limitations in Artificial Intelligence ... Vitter hat gezeigt, dass viele in diesem Modell effiziente Entwicklungen

der Ebene, berechne die Ebenenzerlegung, die durch das Erweitern von Linien in ± y-Richtung durch die Endpunkte des Segmente entsteht und solange fortgesetzt wird bissie das direkt drüber bzw. drunter liegende Segment trifft (falls existent). Abbildung 6verdeutlicht die Partitionierung.

Abbildung 6: Partitionierung des Raumes beim Trapezoidal Decomposition Problem

Das Trapezoidal Decomposition Problem ist ein Beispiel für die Anwendung der Reduk-tionstechnik. Mit Hilfe des EDP-Algorithmus wird eine Ebene mit Segmenten bezüglichder Segmentendpunkte Partitioniert.Grundidee der Lösung:

1. Berechne EDP auf der Menge der Segmente

2. Invertiere die Y-Koordinatenwerte der Segmente und berechne eine zweite Instanzdes EDP

3. Setze die Ergebnisse der zwei EDP Lösungen zu einer Trapezoidal Decompositionzusammen

Die ersten beiden Schritte sind einfach durchzuführen und kosten zusammen O(n∗logmn)I/Os. Im dritten Schritt berechnen wir den Verlauf der O(N) vielen vertikalen Trape-zoidkanten. Die Endpunkte einer vertikalen Trapezkante lassen sich, während eines Scansder zwei Ausgaben, als Schnittpunkte zwischen der vertikalen Geraden durch einen End-punkt mit den zwei dominanten Segmenten dieses Endpunktes in O(n) I/Os berechnen.Ein anschließendes Sortieren der Trapezkanten in O(n ∗ logmn) I/Os bringt diese in dierichtige Reihenfolge für die Zerlegung der Ebene. Mit einem weiteren Scan lassen sichdie Kanten nacheinander ausgeben.

Page 95: HEINZ NIXDORF INSTITUT Fakultät für Elektrotechnik ... Pottmeyer Memory Limitations in Artificial Intelligence ... Vitter hat gezeigt, dass viele in diesem Modell effiziente Entwicklungen

5 K-Nearest Neighbors Problem

Auch das Problem der K-nächsten Nachbarn wird mit Hilfe einer Reduktion gelöst. Ge-nauer gesagt ist dies hier ein Beispiel für die Anwendung des Dualitätsprinzips. DieLösung basiert auf einen Algorithmus zur Berechnung der k-niedrigsten Ebenen entlangeiner vertikalen Linie indem zusätzliche Datenstrukturen benutzt werden um den Raumgeschickt in Cluster einzuteilen.Problemdefinition: Gegeben sei eine Menge S von N punkten im R2 und eine Zahl Kmit 1 ≤ K ≤ N , sowie ein Anfragepunkt p in R2. Gebe alle K Punkte aus S aus, die pam nächsten sind.

Abbildung 8 auf der nächsten Seite zeigt den Fall für K = 4. Die Definition ist nor-

K-Nearest Neighbors mit K=4

Abbildung 7: KNN Problem, Rot eingezeichnete der Anfragepunkt p

malerweise nicht auf R2 beschränkt, jedoch wird hier nur ein Algorithmus für diesen Fallvorgestellt.Grundidee der Lösung:

1. Mittels einer Dualität überführe das Problem in R3, indem jeder Punkt p einerEbene z in R3 zugeordnet wird.

2. Berechne bezüglich des Anfragepunktes q die K niedrigsten Ebenen in R3. Die zudiesen Ebenen zugehörigen Punkte im R2 sind die K-nächsten Nachbarn von p.

Das Problem der K-nächsten Nachbarn wird hier auf ein anderes Problem, das findender K-niedrigsten Ebenen bezüglich eines Anfragepunktes q, reduziert. Die Reduktiongeschieht anhand der Dualität p = (a1, a2) → z = a2

1 + a22 − 2a1x − a2y. Die Ebene z ist

tangential zu einer Parabel im Punkt (a1, a2,−a21 − a2

2). Abbildung 8 auf der nächstenSeite zeigt die Dualität anhand eines eindimensionalen Falles. Das Berechnen der dualen

Page 96: HEINZ NIXDORF INSTITUT Fakultät für Elektrotechnik ... Pottmeyer Memory Limitations in Artificial Intelligence ... Vitter hat gezeigt, dass viele in diesem Modell effiziente Entwicklungen

oa b c

2-tiefsten Ebenen

bezüglich der Geraden

durch (ox,0)

Abbildung 8: Dualität im eindimensionalem Fall

Ebenen zu den N Punkte kann während eines Scans in O(n) I/Os gemacht werden.Können nun die K-niedrigsten Ebenen bezüglich eines Anfragepunktes q in O(n∗ logmn)I/Os und verbraucht der Algorithmus nicht mehr als O(n ∗ logmn) viel Speicher, dannkann auch das KNN Problem mit diesem Ressourcenverbrauch gelöst werden.

5.1 K-lowest Planes Problem

Wir untersuchen nun einen Algorithmus für das „K-lowest Planes“ Problem.Problemdefinition: Sei H eine Menge von N Ebenen im R3. Für jeder vertikale Linie lund jedes k sind die k niedrigsten Ebenen in H entlang l die Ebenen, deren Schnitte mitl die k kleinsten z-Koordinatenwerte haben.Grundidee der Lösung:

1. Erstelle eine Datenstruktur um die N Ebenen aus H abzuspeichern so, dass Anfra-gen effizient beantwortet werden können.

2. Berechne bezüglich des Anfragepunktes q die K niedrigsten Ebenen in R3. Die zudiesen Ebenen zugehörigen Punkte im R2 sind die K-nächsten Nachbarn von p.

5.2 Geschichtete Datenstruktur

Um eine effiziente Datenstruktur aufzubauen, bedienen wir uns der Technik des „buttom-up sampling“ von Mulmuley [14]. Es wird eine zufällige Permutation h1, ..., hN derEbenen in H gewählt. Sei β = BlogBn, für alle i ∈ [1, ⌈(log2(N/β)⌉] definierten wir

Page 97: HEINZ NIXDORF INSTITUT Fakultät für Elektrotechnik ... Pottmeyer Memory Limitations in Artificial Intelligence ... Vitter hat gezeigt, dass viele in diesem Modell effiziente Entwicklungen

Ri = h1, h2, ..., h2i. Es entsteht dadurch eine Hierarchie zufällig gewählter Teilmengen

R0 ⊂ R1 ⊂ ... ⊂ Rlog2(N/β ⊂ H,

der Größe 2i. Die Datenstruktur besteht nun aus O(log2n) vielen Schichten, jeweils einepro Ri. Im weiteren schrieben wird ri = 2i/B und meinen damit die Anzahl Blöcke dieRi braucht.Die i-te Schicht bauen wir wie folgt zusammen. Als erstes bauen wir für Ri das „lowerenvelope“ in O(rilogBri) I/Os mit dem externen "3D-halfspace intersectionÄlgorithmusvon Crauser [6]. Das „lower envelope“ ist das 0-te Level des Arrangements [1] der Ebenenin Ri. Der Algorithmus liefert das 0-te Level bereits trianguliert zurück, die Menge derDreiecke von Ri nennen wir ∆Ri. ∆Ri enthält O(2i) viele Dreiecke und kann somit inO(ri) vielen Blöcken gespeichert werden.

Als nächstes wird eine Datenstruktur zur Punktlokation aufgebaut (point-locationStruktur). Diese Wird aus der orthogonalen Projektion von ∆Ri auf die x/y-Ebene ge-wonnen. Dadurch ist es möglich ein Dreieck aus ∆Ri über oder unter einem Anfragepunktp in O(logBn) I/Os zu ermitteln. Diese Struktur kann in O(rilogBri) I/Os aufgebaut wer-den und verbraucht O(ri) Blöcke Speicher [8, 2].

Zuletzt bauen wir für jedes Dreieck eine Konfliktliste K(∆). Ein Konflikt zwischeneinem Dreieck und einer Ebene aus H entsteht dann, wenn die Ebene unter einem Punktdes Dreiecks liegt. Wir speichern jede Konfliktliste in hintereinander liegenden Blöcken so,dass wir sie in ⌈|K(∆)|/B⌉ I/Os scannen können. Der „halspace intersection“ Algorithmusvon Crauser et al. [6] kann genutzt werden die Konfliktlisten der ∆Ri in O(nlogBri) zuberechnen.

Das folgende Lemma ist elementar für die wahrscheinlichkeitstheoretische Betrachtungder Laufzeit des K-lowest Planes Algorithmus.

Lemma 3: Sei 1 ≤ r ≤ N und R eine zufällige Menge der Ebenen aus H der Größe r.

1. E[∑

∆∈∆(R) |K(∆)|] = O(N)

2. Für jede vertikale Linie l, ist die erwartete Größe von K(∆), mit ∆ ∈ ∆(R) wobeidie Linie ∆ schneidet, O(N/r).

Aus dem ersten Teil des Lemmas resultiert, dass die erwartete Anzahl benötigter Blöckeum alle Konfliktlisten für eine Teilmenge ∆Ri abzuspeichern O(n) ist. Da diese den Spei-cherverbrauch von ∆Ri dominitert, ist die erwartete Anzahl von Blöcken um eine Sichtunserer Struktur zu verwalten O(n), insgesamt also nlog2n. Die erwarte Anzahl von I/OZugriffen in der Vorverarbeitung der Datenstruktur ist O(log2n)logBn). Bei gegebenemk, einer Linie l und einer Fehlerwahrscheinlichkeit 0 < δ < 1, findet der folgende Algo-rithmus für gewöhnlich die k tiefsten Ebenen in H bezüglich l.

Page 98: HEINZ NIXDORF INSTITUT Fakultät für Elektrotechnik ... Pottmeyer Memory Limitations in Artificial Intelligence ... Vitter hat gezeigt, dass viele in diesem Modell effiziente Entwicklungen

TryLowerPlanes (k , l , δ ) :p=⌈log2(Nδ/k)⌉Find the t r i a n g l e ∆ ∈ ∆(Rp) i n t e r s e c t i n g li f | K(∆)| ≤ k

δ2 thenscan K(∆)i f ≥ k planes in K(∆) c r o s s l below k ∩ ∆ thenreturn k lowest p lanes in K(∆) along l

else f a i lelse f a i l

Rp ist eine zufällig gewählte Menge aus H der Größe 2p < 2Nδ/k. Das von l geschnitteneDreieck kann in O(logB2p = O(logBn) I/Os mit Hilfe unserer point-location Strukturgefunden werden. Wir scannen die Konfliktliste K∆ nur, wenn sie weniger als k/δ2 so,dass der scan maximal

k/(δ2B)⌉

I/Os kostet. Die gesamte Laufzeit von TRYLOWEST-PLANES ist O(logBn + k/Bδ2) unabhängig ob eine Lösung gefunden wurde oder nicht.

Nach Lemma 5.2 auf der vorherigen Seite ist die erwartete Größe von K(∆) O(N/2p)setzt man dies in die Markovsche Ungleichung [12] ein, ist die Wahrscheinlichkeit dasdie Größe von K(∆) k/δ2 überschreitet in O(δ). Weiterhin tritt der Fall das wenigerEbenen in K(∆) unter dem Schnitt von l und ∆ sind, nur dann ein, wenn die Ebene,die ∆ beinhaltet, eine der k niedrigsten Ebenen entlang l ist. Dieser Fall tritt k mal mitder Wahrscheinlichkeit 2p/n ein da jede Ebene gerade diese Wahrscheinlichkeit hat in derTeilmenge Rp zu sein. Die Wahrscheinlichkeit, dass TRYLOWESTPLANES fehlschlägtist also O(δ).Um nun eine optimale erwartete Laufzeit von O(logBn + k/B) zu erreichen wird nocheine Modifikation vorgenommen. Es werden insgesamt drei unabhängige Datenstruktu-ren aufgebaut und Verarbeitet. Dadurch reduziert sich die Wahrscheinlichkeit für einenFehler auf O(δ3). Die Berechnung findet wie folgt statt, man ruft wiederholend auf al-len drei Datenstrukturen TRYLOWESTPLANES, mit jeweils δ = 2−1, 2−2, ..... auf,bis irgendein Aufruf erfolgreich war. Wir definieren Xi ∈ 0, 1 als eine Zufallsvariabledessen Wert 1 ist, wenn alle drei Aufrufe von TRYLOWESTPLANES mit δ = 2−i

fehlgeschlagen sind. Dann ist die Gesamtanzahl I/Os maximal

i ≥Xi−1 ∗ O(logBn + 4ik/B)

Die Wahrscheinlichkeit für ein Fehlschlag war δ = 2−i hier also δ3 = 2−3i = 8−i, damitist die erwartete Anzahl von I/O-Operationen

i≥0

O(logBn + 4i+1k/B)

8i=

i≥0

O

(

logBn

8i+

4k/B

2i

)

= O(logBn + k/B).

Page 99: HEINZ NIXDORF INSTITUT Fakultät für Elektrotechnik ... Pottmeyer Memory Limitations in Artificial Intelligence ... Vitter hat gezeigt, dass viele in diesem Modell effiziente Entwicklungen

6 Zusammenfassung

In dieser Seminararbeit wurden geometrische Problemstellungen für den externen Spei-cher vorgestellt. Die besondere Behandlung geometrischer Probleme in Hinsicht auf denexternen Speicher ergibt sich aus dem Speichermodell der heutigen PC-Hardware. Einedirekte Umsetzung der Konzepte von Algorithmen für den internen Speicher hat gezeigt,dass sich so nur selten (in unseren drei Beispielproblemen gar nicht) I/O-optimale ex-terne Algorithmen erstellen lassen. Die zentrale Eigenschaft, die zur optimalen externenAlgorithmen führt, ist hierbei das Ausnutzen oder Optimieren des blockweisen Lesensaus dem externen Speicher. Die hier vorgestellten Lösungen wurden so aufgebaut, dassDaten, die zusammenhängend zu bearbeiten sind auch gleichzeitig im Hauptspeicher ge-halten werden können. Betrachten wir noch mal das Endpoint Domination Problem ausdem Kapitel 3 auf Seite 5, so wurde dort der Problemraum so Partitioniert, dass stetsgenug Blöcke für die gerade relevanten Daten im Hauptspeicher zur Verfügung standen.Bei Problemen, die sich nicht so günstig partitionieren lassen, kann der Zufall helfen. Wieim Kapitel 5 auf Seite 13 (K-nearest Neighbors Problem) ergibt sich dann eine erwarteLaufzeit für den optimalen Algorithmus.

Page 100: HEINZ NIXDORF INSTITUT Fakultät für Elektrotechnik ... Pottmeyer Memory Limitations in Artificial Intelligence ... Vitter hat gezeigt, dass viele in diesem Modell effiziente Entwicklungen

Literatur

[1] Pankaj K. Agarwal, Lars Arge, Jeff Erickson, Paolo G. Franciosa, and Jeffry ScottVitter. Efficient searching with linear constraints. pages 169–178, 1998.

[2] Lars Arge, Darren Erik Vengroff, and Jeffrey Scott Vitter. External-memory al-gorithms for processing line segments in geographic information systems (extendedabstract). In ESA ’95: Proceedings of the Third Annual European Symposium onAlgorithms, pages 295–310, London, UK, 1995. Springer-Verlag.

[3] Christian Breimann and Jan Vahrenhold. Algorithms for Memory Hierarchies: Ad-vanced Lectures, chapter 6. External Memory Computational Geometry Revisited.Lecture Notes in Computer Science. Springer Berlin / Heidelberg, 2004.

[4] Chazelle, Edelsbrunner, Guibas, and Sharir. Algorithms for bichromatic line-segment problems and polyhedral terrains. ALGRTHMICA: Algorithmica, 11, 1994.

[5] Bernard Chazelle and Leonidas J. Guibas. Fractional cascading: I. a data structuringtechnique. Algorithmica, 1(2):133–162, 1986.

[6] Andreas Crauser, Paolo Ferragina, Kurt Mehlhorn, Ulrich Meyer, and Edgar A.Ramos. Randomized external-memory algorithms for some geometric problems. InSymposium on Computational Geometry, pages 259–268, 1998.

[7] Herbert Edelsbrunner. Algorithms in combinatorial geometry. Springer-Verlag NewYork, Inc., New York, NY, USA, 1987.

[8] Michael T. Goodrich, Jyh-Jong Tsay, Darren E. Vengroff, and Jeffrey Scott Vit-ter. External-memory computational geometry. In Proceedings of the 34th AnnualSymposium on Foundations of Computer Science, pages 714–723, 1993.

[9] T.G. Graf and K.H. Hinrichs. Plane-sweep construction of proximity graphs. PhDthesis, Fachbereich Mathematik, Westfälische Wilhelms-Universität Münster, Ger-many, 1994.

[10] Massachusetts Joseph O’Rourke Smith College. Data structures and algorithms 3.Springer-Verlag New York, Inc., New York, NY, USA, second edition, 1984.

[11] David G. Kirkpatrick. Optimal search in planar subdivisions. SIAM J. Comput.,12(1):28–35, 1983.

[12] Ulrich Krengel. Einführung in die Wahrscheinlichkeitstheorie und Statistik. Vieweg,Wiesbaden, Deutschland, sixth edition, 2002.

[13] Germany Kurt Mehlhorn Universität des Saarlandes, Saarbrücken. ComputationalGeometry in C. Springer-Verlag New York, Inc., New York, NY, USA, 1994.

[14] K. Mulmuley. Computational Geometry. An Introduction Through Randomized Al-gorithms. Prentice Hall, 1994.

Page 101: HEINZ NIXDORF INSTITUT Fakultät für Elektrotechnik ... Pottmeyer Memory Limitations in Artificial Intelligence ... Vitter hat gezeigt, dass viele in diesem Modell effiziente Entwicklungen

[15] Raimund Seidel. A simple and fast incremental randomized algorithm for computingtrapezoidal decompositions and for triangulating polygons. Comput. Geom., 1:51–64, 1991.

Page 102: HEINZ NIXDORF INSTITUT Fakultät für Elektrotechnik ... Pottmeyer Memory Limitations in Artificial Intelligence ... Vitter hat gezeigt, dass viele in diesem Modell effiziente Entwicklungen
Page 103: HEINZ NIXDORF INSTITUT Fakultät für Elektrotechnik ... Pottmeyer Memory Limitations in Artificial Intelligence ... Vitter hat gezeigt, dass viele in diesem Modell effiziente Entwicklungen

Volltextindizes im externen Speicher

Andre Braun

1 Einleitung

In der heutigen Zeit haben wir oft mit sehr großen Texten oder Textsamm-lungen zu tun. Einige Beispiele dafur sind digitale Bibliotheken, Lexika oderBiosequenzen. Fur das schnelle Extrahieren von benotigter Information isteine effiziente Stringsuche notwendig. Eine Moglichkeit dafur stellen die sogenannten Volltextindizes dar. Die Grundidee ist das Speichern aller Suffixeeines Textes in einer Indexstruktur, z.B. einem sortierten Array oder einemBaum. In diesem Index kann dann effizient nach Substrings gesucht werden.

Die meisten Volltextindizes wurden fur das RAM-Modell entwickelt. Oftpassen die Texte aber nicht komplett in den Hauptspeicher. Außerdem mussman bedenken, dass die Große eines Volltextindexes etwa das 4- bis 20-fachedes Originaltextes betragt. Auch eine dauerhafte Besetzung eines Teils desHauptspeichers durch einen Volltextindex ware ungunstig. Aufgrund dessensind Anpassungen der Volltextindizes an den externen Speicher notwendig.Man versucht eine moglichst gute Speicherlokalitat zu gewahrleisten und somitdie Anzahl der sehr kostspieligen I/O-Zugriffe zu minimieren.

In dieser Ausarbeitung werde ich einige solche Volltextindizes fur den ex-ternen Speicher und die Suche darin vorstellen. Außerdem werde ich einenAlgorithmus fur den effizienten Aufbau solcher Indizes im externen Speichervorstellen. Fur das Verstandnis dieser Algorithmen werden einige Grundlagenbenotigt, die ich in den ersten Kapiteln vorstellen werde.

2 Formale Beschreibung des Problems

Das Rechenmodell, welches in dieser Arbeit benutzt wird, ist das Standard-modell, welches in [1] beschrieben wird. Hier gebe ich nur eine kurze Beschrei-bung.

Als erstes werden einige Notationen eingefuhrt. Ein Alphabet Σ ist einegeordnete Menge von Symbolen. Ein String S ist ein Array von Symbolen,S[1, n] = S[1]S[2]...S[n]. Ferner definieren wir i und j, mit 1 ≤ i ≤ j ≤ N . Esgilt:

S[1, j] ist Prafix von S

97

Page 104: HEINZ NIXDORF INSTITUT Fakultät für Elektrotechnik ... Pottmeyer Memory Limitations in Artificial Intelligence ... Vitter hat gezeigt, dass viele in diesem Modell effiziente Entwicklungen

S[i, |S|] ist Suffix von S

S[i, j] ist Substring von S

Mit Σ∗ werden alle Zeichenkette uber dem Alphabet Σ bezeichnet. FolgendeParameter werden benutzt:

N = Anzahl der Symbole im TextM = Anzahl der Symbole, die in den internen Speicher passenB = Anzahl der Symbole, die in einen Speicherblock im externen Speicherpassen

Außerdem werden folgende Kurznotationen benutzt:

scan(N) = Θ(N/B)sort(N) = Θ((N/B) logM/B (N/B))search(N) = Θ(logB N)

Zusatzlich verwenden wir folgende Parameter:

K = Anzahl der Strings im TextZ = Große des Abfrageergebnisses (Anzahl der Treffer)|P | = Anzahl der Symbole in einem Suchstring P|S| = Anzahl der Symbole in einem eingefugten/geloschten String S

Aufgabe (exaktes Stringmatching): Sei T eine Menge von K Strings inΣ∗, N ist die totale Lange aller Strings in T. Gegeben ein Musterstring P, findealle Vorkommen von P in den Strings von T. Bei der statischen Version desProblems wird nur die Stringsuche betrachtet, bei der dynamischen Versionbraucht man zusatzlich eine Unterstutzung fur das Einfugen/Loschen vonStrings.

Alle in dieser Arbeit betrachteten Volltextindizes haben eine lineare Spei-cherkomplexitat. Der Schwerpunkt wird dementsprechend auf der Zeitkom-plexitat der Stringsuche bzw. der Updates von Indizes liegen.

3 Basistechniken fur den internen Speicher

Die meisten Volltextindizes sind Varianten der drei Datenstrukturen: derSuffixarrays [2, 4], der Suffixbaume [3] und der direkten azyklischen Wort-graphen (DAWGs), wobei es meines Wissens bis heute keine Anpassungender DAWGs an den externen Speicher gibt. Die Suffixarrays und Suffixbaumebilden demzufolge die Basis fur Datenstrukturen fur den externen Speicher,die in dieser Arbeit beschrieben werden.

Lassen Sie mich mit einer Beobachtung starten, die der Benutzung allerVolltextindizes zugrunde liegt. Ein Substring ist immer ein Prafix von einemSuffix. Oder formaler: Wenn ein Vorkommen von einem Musterstring P ineinem String an der Position i beginnt, dann ist P ein Prafix vom SuffixS[i, |S|]. Somit konnen wir alle Vorkommen von P durch eine Prafixsuche

98

Page 105: HEINZ NIXDORF INSTITUT Fakultät für Elektrotechnik ... Pottmeyer Memory Limitations in Artificial Intelligence ... Vitter hat gezeigt, dass viele in diesem Modell effiziente Entwicklungen

auf der Menge aller Suffixe des Textes finden. Also ist eine Datenstruktur,die die Menge der Suffixe eines Textes speichert und die Prafixsuche daraufunterstutzt, ein Volltextindex.

3.1 Suffixarrays

Die einfachste Datenstruktur, die eine effiziente Prafixsuche unterstutzt, istein lexikographisch sortiertes Array. Ein sortiertes Array SAT von Zeigernauf die Suffixe von T nennt man ein Suffixarray. Fur die Stringsuche in einemSuffixarray verwendet man die binare Suche, die bekannterweise O(log2 N)Vergleiche benotigt. Insgesamt benotigt man die Zeit O(|P | log2 N) im WorstCase, da bei jedem Stringvergleich der Musterstring Zeichen fur Zeichen mitdem jeweiligen String aus dem Array verglichen wird. In [4] zeigen Manberund Myers, wie man mit Hilfe der langsten gemeinsamen Prafixe eine bessereZeitkomplexitat von O(|P |+log2 N) erreichen kann. Dieselben Autoren zeigen,wie man ein Suffix-Array in Zeit O(N log2 N) konstruieren kann. Der Nachteilvon Suffixarrays ist, dass sie keine effizienten Updates unterstutzen und somitnur fur statische Dokumente verwendbar sind.

3.2 Tries und Suffixbaume

Eine andere einfache Datenstruktur zum Speichern von Strings ist ein so ge-nannter Trie (von retrieval). Ein Trie ist ein Baum, an dessen Kanten Zeichengespeichert werden (siehe Abb. 1). Ein Knoten reprasentiert die Konkatenati-on der Kantenlabels auf dem Pfad von der Wurzel bis zu diesem Knoten. Fureine prafixfreie Menge von Strings sind alle Knoten, die Strings reprasentieren,die Blatter des Trie.

Abbildung 1. Ein Trie fur T = index, inline, tattoo, tempo

Eine Modifikation des Trie ist ein kompakter Trie. Der Unterschied zueinem Trie ist, dass man Knoten, die jeweils nur einen Nachfolger besitzen, zujeweils einem Knoten zusammenfasst (siehe Abb. 2). An einer Kante werdenalso auch Zeichenketten anstatt nur einzelner Zeichen gespeichert. Somit wirddie Anzahl der Knoten und dementsprechend der Speicherbedarf reduziert.

Ein Suffixbaum fur einen Text T ist ein kompakter Trie fur die Menge derSuffixe von T (siehe. Abb. 3). Dabei ist es ublich, dass man ans Ende jedes

99

Page 106: HEINZ NIXDORF INSTITUT Fakultät für Elektrotechnik ... Pottmeyer Memory Limitations in Artificial Intelligence ... Vitter hat gezeigt, dass viele in diesem Modell effiziente Entwicklungen

Abbildung 2. Ein Kompakter Trie fur T = index, inline, tattoo, tempo

Strings ein spezielles Zeichen, z.B. $ setzt, damit die Stringmenge prafixfreiwird. Die Suche in dem Suffixbaum geschieht, indem man in dem Baum vonder Wurzel aus nach unten wandert und dabei die Zeichenketten an den Kan-ten mit den entsprechenden Zeichen in dem Suchstring vergleicht. Erreichtman das Ende des Suchstrings, so ist der Knoten, in dem man sich befindet,die Wurzel des Unterbaumes, dessen Blatter die Suffixe reprasentieren, welcheden Suchstring als einen gemeinsamen Prafix enthalten. Also entspricht dieAnzahl dieser Blatter der Anzahl der Treffer in T (falls man sich am Ende derSuche in einem Blatt befindet, hat man als Sonderfall genau einen Treffer).

Die Zeitkomplexitat der Suche ist O(P ) fur das Durchlaufen des Baumesvon der Wurzel aus unter der Bedingung, dass das Alphabet konstant ist, plusO(Z) fur das Absuchen des Unterbaumes.

Abbildung 3. Suffixbaum fur T = banana$ mit SA(banana$) = $, a$, ana$,anana$, banana$, na$, nana$

4 Basistechniken fur den externen Speicher

In diesem Kapitel beschreibe ich einige Erweiterungen der bisher vorgestelltenTechniken fur eine effizientere Nutzung im externen Speicher.

Die Suffixarrays und -Baume speichern keine Strings, sondern nur Zeigerdarauf. Jedes Mal wenn die Strings gebraucht werden, wird auf den Text

100

Page 107: HEINZ NIXDORF INSTITUT Fakultät für Elektrotechnik ... Pottmeyer Memory Limitations in Artificial Intelligence ... Vitter hat gezeigt, dass viele in diesem Modell effiziente Entwicklungen

zugegriffen (wahlfreie Zugriffe). Das heißt, die Performance der Algorithmenist ziemlich schlecht, falls der Text sich auf dem externen Speicher befindet.Die zwei im Weiteren vorgestellten Techniken versuchen diesen Nachteil zubeheben.

Die erste Technik ist ein so genannter Patricia Trie, welche den kompaktenTrie auf den externen Speicher anpasst [5]. Der Unterschied zwischen einemPatricia Trie und einem kompakten Trie ist, dass in dem Patricia Trie dieKantenbeschriftung nur den ersten Buchstaben und die Lange (ubersprunge-ne Zeichen) der zugehorigen Beschriftung des kompakten Trie enthalt. DerPatricia Trie PTT fur die Menge der Suffixe des Textes T heißt Pat-Baum(Abb. 4).

Abbildung 4. Pat-Baum fur T = banana$

Die Grundidee der Patricia Tries bzw. der Pat-Baume ist es, den Zugriffauf den Text so lange wie moglich hinauszuzogern. Man hat dann keine wahl-freien Zugriffe mehr, sondern nur einen kontinuierlichen Zugriff am Ende derSuche. Die Suche selber ist ahnlich der Suche in einem Suffixbaum mit demUnteschied, dass hier nur das erste Zeichen an einer Kante mit dem entspre-chenden Zeichen im Suchstring verglichen wird. Das heißt, man vergleichtnur die Zeichen die tatsachlich im Patricia Trie gespeichert werden, also imHauptspeicher zur Verfugung stehen. Die anderen Zeichen werden zunachstubersprungen. Falls die erste Phase der Suche erfolgreich verlaufen ist, d.h.man hat das Ende des Suchstrings erreicht, betrachtet man den Knoten indem man sich nun befindet als Wurzel eines Unterbaums. Man weiß, dassalle Strings (Blatter) dieses Unterbaums ein gemeinsames Prafix haben, wel-ches entweder dem Suchstring entspricht oder nicht. Um dies zu uberprufen,benotigt man eine I/O-Operation, um einen dieser Strings in den Hauptspei-cher zu laden und vergleicht ihn dann mit dem Suchstring. Falls die beidengleich sind, sind alle Blatter des Unterbaumes die Treffer der durchgefuhrtenSuchabfrage, falls nicht, gibt es keine Treffer. Die Komplexitat dieser Sucheim internen Speicher ist immer noch O(|P | + Z) wie bei den Suffixbaumen,die Komplexitat der I/O-Zugriffe ist nun aber O(1).

Die zweite Technik ist das so genannte Lexicographic Naming, vorgestellt in[6]. Bei dieser Technik wird jedem String ein Integerwert (Name) zugeordnet.

101

Page 108: HEINZ NIXDORF INSTITUT Fakultät für Elektrotechnik ... Pottmeyer Memory Limitations in Artificial Intelligence ... Vitter hat gezeigt, dass viele in diesem Modell effiziente Entwicklungen

Die arithmetische Ordnung auf den Namen entspricht der lexikographischenOrdnung auf den dazu gehorigen Strings. Dadurch kann man beliebig lan-ge Strings vergleichen, ohne auf sie direkt zugreifen zu mussen, indem manstattdessen die entsprechenden Namen benutzt. Die Datenstruktur mit denNamen kann man bilden, indem man die Stringmenge S sortiert und denRang eines Strings als seinen Namen nutzt. Der Rang ist dabei die Anzahlder lexikographisch kleineren Strings plus eins.

5 String B-Baume

In diesem Kapitel stelle ich die String B-Baume vor, eingefuhrt von Ferraginaund Grossi [7]. Diese Indexstruktur vereinigt die Vorteile von B-Baumen undPatricia Tries und ermoglicht eine effiziente Suche im externen Speicher. An-dere I/O-effiziente Strukturen fur Volltextindizes, die in dieser Arbeit nichtvorgestellt werden, sind z.B die Hierarchie von Indizes von Baeza-Yates et al[8] und die kompakten Pat-Baume von Clark und Munro [9].

Die String B-Baume sind eine Kombination von B-Baumen und PatriciaTries. Ein B-Baum ist eine sehr verbreitete Datenstruktur, wenn es um Daten-verwaltung auf dem externen Speicher geht (z.B. Datenbanken oder Dateisys-teme). Der Vorteil gegenuber anderen Baumstrukturen ist, dass man aufgrundeiner breiten Verzweigung nur wenige Ebenen im Baum und somit nur weni-ge kostspielige Speicherzugriffe hat. Der Verzweigungsgrad wird so gewahlt,dass ein Knoten maximal einen kompletten Speicherblock belegt. Die varia-ble Schlusselanzahl pro Knoten verhindert ein standiges Rebalancieren desBaumes.

Ein Patricia Trie kann auf der anderen Seite beliebig lange Strings effektivverwalten falls er komplett in den Hauptspeicher passt. Die Suche brauchtin diesem Fall nur eine konstante Anzahl an I/O-Zugriffen. Man will nundie Vorteile der beiden Datenstrukturen kombinieren, indem man PatriciaTries als Knoten fur einen B-Baum verwendet und somit beliebig große Texteeffektiv verwalten kann. Im Folgenden beschreibe ich die Struktur eines StringB-Baumes.

Abbildung 5. Der logische Aufbau eines Knotens π, der g Kinder hat

Gegeben ist eine Menge S = s1, ..., sN bestehend aus N Strings (Suffi-xen). Jeder Knoten π besitzt eine geordnete Menge von Strings Sπ, so dass

102

Page 109: HEINZ NIXDORF INSTITUT Fakultät für Elektrotechnik ... Pottmeyer Memory Limitations in Artificial Intelligence ... Vitter hat gezeigt, dass viele in diesem Modell effiziente Entwicklungen

b ≤ |Sπ| ≤ 2b, b = Θ(B). Ein Knoten π besitzt d(π) Kinder mitb/2 ≤ d(π) ≤ b. Der ganz links bzw. ganz rechts stehende Knoten in Sπ

wird mit L(π) bzw. R(π) bezeichnet. Die Menge Sπ bekommt man nun, indemman die Kinder von π von links nach rechts durchgeht und dabei das jeweiligeL(σ) und R(σ) fur ein Kind σ nach π kopiert (Abb. 5). Alle Schlussel befindensich lexikographisch sortiert in den Blattern des Baumes. Das heißt, die ganzeStruktur ist B+-Baum ahnlich. Der Unterschied zu einem B+-Baum ist, dassdie internen Knoten nicht nur Zeiger auf Kindelemente, sondern auch einigeKopien der Schlussel enthalten (Abb. 6).

Abbildung 6. Beispiel fur eine String B-Baum ahnliche Struktur und ihre Einga-bemenge

Die beschriebene Struktur ist noch nicht der endgultige String B-Baum,da hier noch nicht die Patricia Tries fur die Knoten benutzt werden (statt-dessen ein sortiertes Array). Ich werde den Ablauf der Suche zuerst auf diesereinfacheren Datenstruktur beschreiben. Danach ersetze ich die Arrays in denKnoten durch Patricia Tries und zeige, welchen Vorteil es bei der Laufzeitbringen wird.

Die Suche, die hier vorgestellt wird, basiert auf zwei Beobachtungen, diezuerst von Manber und Myers [4] aufgestellt wurden. Sei K ein sortiertes

103

Page 110: HEINZ NIXDORF INSTITUT Fakultät für Elektrotechnik ... Pottmeyer Memory Limitations in Artificial Intelligence ... Vitter hat gezeigt, dass viele in diesem Modell effiziente Entwicklungen

Array. Die erste Beobachtung besagt, dass alle Strings mit dem gemeinsamenPrafix P einen zusammenhangenden Bereich von K einnehmen. Die zweiteBeobachtung besagt, dass sich der ganz links stehende String in diesem Bereichrechts neben der Position von P befindet und analog der ganz rechts stehendelinks neben der Position von P$ wobei $ in diesem Fall ein Symbol ist, welchesgroßer ist als jedes andere Symbol im Alphabet (siehe Abb. 7). Da man sehrleicht ein sortiertes Array aller Strings erhalt, indem man die Blatter desString B-Baumes von links nach rechts aneinander hangt, kann man diesebeiden Beobachtungen bei der Suche benutzen. Die Position von P in K werde

Abbildung 7. Die Positionen von an und an$ im SAbanana

ich durch ein Tupel (τ, j) reprasentieren. Dabei ist τ das entsprechende Blattund j die Position innerhalb des Blattes.

In Abb. 8 ist der Pseudocode fur die Suche dargestellt. Die Suche beginntdamit, dass man zwei Trivialfalle uberpruft. Es wird gepruft, ob P großer(Schritt 1) oder kleiner (Schritt 2) ist als alle anderen Strings in K. Ist beidesnicht der Fall, beginnt man mit der eigentlichen Suche, indem man π := rootsetzt (Schritt 3) und dann den Baum von oben nach unten durchlauft unddabei die Invariante L(π) < P < R(π) fur jeden besuchten Knoten π einhalt(Schritte 4-8). Beim Besuchen des Knotens π ladt man den entsprechendenSpeicherblock in den internen Speicher und wendet die Prozedur PT-Searchan, die im Wesentlichen eine binare Suche darstellt. Dabei sucht man nach derPosition von P in der Stringmenge Sπ, genauer gesagt sucht man nach zweiNachbarstrings, die die Position von P bestimmen: Kj−1 < P < Kj . Falls πein Blatt ist, ist man mit der Suche fertig. Falls es ein interner Knoten ist,muss man zwei Falle unterscheiden:

1. Wenn die Strings Kj−1 und Kj zu zwei verschiedenen Kindern von πgehoren, dann mussen sie aufgrund des Aufbaus des B-Baumes Nach-barstrings sein, also Kj−1 = R(σ′) und Kj = L(σ) fur zwei Nachbar-Kindknoten σ′ und σ. Damit ist die Position von P eindeutig bestimmt.Man wahlt fur t das ganz links liegende Blatt, welches ein Kind von σ istund fur j die erste Position in Sτ , da L(τ) = L(σ) = Kj .

2. Wenn Kj−1 und Kj zum gleichen Knoten gehoren, das heißt Kj−1 = L(σ)und Kj = R(σ) fur einen Knoten σ, dann wird π = σ gesetzt und die Suchewird fortgesetzt.

Nun kommen wir zu der Laufzeitanalyse des Algorithmus. Die ProzedurPT-Search ist eine binare Suche von P auf der Menge Sπ und benotigt dement-sprechend O(log2 S|π|) = O(log2 B) Stringvergleiche. Da sich in einem Kno-ten nur Zeiger auf die tatsachlichen Strings befinden, muss jeder String, denman prufen will, geladen werden. Dafur braucht man zusatzlich O(p/B) I/Ospro String und somit ist die Gesamtlaufzeit fur PT-Search O(p/B log2 B)I/Os. Insgesamt wird PT-Search H mal aufgerufen. O(H) kann man auch als

104

Page 111: HEINZ NIXDORF INSTITUT Fakultät für Elektrotechnik ... Pottmeyer Memory Limitations in Artificial Intelligence ... Vitter hat gezeigt, dass viele in diesem Modell effiziente Entwicklungen

Abbildung 8. Der Pseudocode der Suche der Position von P in K

O(logB N) schreiben, da jeder Knoten Θ(B) Kinder hat. Alle anderen Schrittebenotigen eine konstante Zeit. Somit ist die Gesamtlaufzeit des AlgorithmusO(p/B logB N log2 B) = O(p/B log2 N) I/Os. Zusatzlich benotigt man nochO(Z/B) I/Os, um die gefundenen Strings zu laden.

Nun werden die Suffix-Arrays in den Knoten durch Patricia Tries ersetzt,um die endgultige Datenstruktur zu bekommen. In Kapitel 4 haben Sie bereitsgesehen, dass Patricia Tries nur einen Diskzugriff fur die Suche benotigen.Somit entfallt die binare Suche in den Knoten. Der Suchstring wird einmalgeladen (O(p/B)), man wandert in dem Baum von der Wurzel bis zu ei-nem Blatt (O(logB N)) und am Ende werden die gefundenen Strings geladen(O(Z/B)). Die Gesamtlaufzeit der Suche in einem String B-Baum ist alsoO(p/B + logB N + Z/B) I/Os.

Der eine Vorteil von String B-Baumen ist, dass sie dynamisch sind. Dasheißt, man kann neue Strings hinzufugen, ohne dass man reservierten Spei-cherplatz braucht. Zum Einfugen bzw. Loschen eines Strings der Lange msucht man dessen Position. Die Komplexitat der Suche ist O(m/B + logB N)I/Os (da das Laden der gefundenen Strings entfallt). Es kann dabei passie-ren, dass der Knoten mit dem eingefugten String zu voll wird, d.h. mehr als2b Strings enthalt. In diesem Fall muss der Baum rebalanciert werden. Dervolle Knoten wird in zwei Knoten aufgeteilt. Der Elternknoten bekommt zweineue Zeiger. Falls er dann auch zu voll wird, wird er ebenfalls aufgeteilt. Imschlimmsten Fall kann sich das bis ganz nach oben fortsetzen. Die Wurzelwird als letzter Knoten gesplittet und es entsteht eine neue Wurzel oberhalbdavon. Der Baum wachst um eine Ebene. Beim Loschen eines Strings kanndas Gegenteil passieren. Der Knoten wird zu leer (weniger als b Strings) undwird mit einem Nachbarknoten zusammengefasst. Der Elternknoten hat dannzwei Zeiger weniger und muss eventuell ebenfalls mit einem anderen Knotenzusammengefasst werden. Im Extremfall schrumpft der Baum um eine Ebene.Die Kosten fur das Rebalancieren eines B-Baumes betragen O(logB N). Somitbetragen die Kosten fur das Enfugen/Loschen eines Strings O(m/B+logB N)I/Os.

105

Page 112: HEINZ NIXDORF INSTITUT Fakultät für Elektrotechnik ... Pottmeyer Memory Limitations in Artificial Intelligence ... Vitter hat gezeigt, dass viele in diesem Modell effiziente Entwicklungen

Da man beim Einfugen/Loschen eines Strings in einen String B-Baum al-le seine Suffixe einfugen/loschen muss, muss man die Position jedes Suffixessuchen. Da ein String der Lange m genau m Suffixe besitzt, ist die Gesamt-komplexitat fur das Einfugen/Loschen eines Strings O(m/B + m(logB N))I/Os.

6 I/O-effiziente Konstruktion von Volltextindizes

Neben der Laufzeit der Suchalgorithmen und der Speichereffizienz ist die Zeit,die fur die Konstruktion eines Volltextindexes benotigt wird, ein weiteres wich-tiges Kriterium. In der Tat stellt oft gerade die Konstruktion eines Indexes denFlaschenhals einer Anwendung dar. In diesem Kapitel mochte ich einen derI/O-effizienten Konstruktionsalgorithmen fur Volltextindizes beschreiben. Esist der Doubling Algorithmus, vorgestellt von Arge et al. [10] und modifiziertvon Crauser und Ferragina [11].

Bevor ich auf den Algorithmus eingehe, sei an dieser Stelle eine Bemer-kung angebracht. Alle Formen der Volltextindizes, die ich in dieser Arbeitvorgestellt habe, die Suffixarrays, Suffixbaume, Pat-Baume und auch StringB-Baume, konnen ineinander in O(sort(N)) I/Os uberfuhrt werden. Das heißt,ein Algorithmus, der einen dieser Indizes effizient konstruieren kann, ist furdie anderen ebenfalls effizient.

Der Doubling Algorithmus basiert auf der Technik des LexicographicalNaming (s. Kapitel 4) und wird fur den Aufbau von Suffixarrays verwendet.Sei rk(i) der Name eines Substrings der Lange 2k, der an Position i beginnt.rk(i) ist also die Anzahl der lexikographisch kleineren Substrings plus eins undstellt dementsprechend die Position des entsprechenden Suffixes im Suffixar-ray dar. Der Algorithmus konstruiert rk fur k = 1, 2, ..., dlog2 Ne. Substringskleiner als 2k werden mit $s (Spezialsymbol, kleiner als jedes andere Symbolim Alphabet) aufgefullt (Abb. 9)

Abbildung 9. Der Doubling Algorithmus fur den Text banana

Am Anfang scannt der Algorithmus den Text, der hier als ein einzigerString betrachtet wird. Fur jede Position i wird ein entsprechendes Tripel(rk−1(i), rk−1(i + 2k−1), i) konstruiert. Nach dieser Initialisierungsphase be-ginnt die Hauptschleife des Algorithmus mit der Laufvariablen k. Bei jedemDurchlauf wird das neue rk(i) berechnet. Das geschieht in vier Schritten, diefolgendermaßen aussehen:

1. Sortiere die Tripel nach den ersten beiden Komponenten (was zum Sor-tieren der Substrings der Lange 2k equivalent ist).

106

Page 113: HEINZ NIXDORF INSTITUT Fakultät für Elektrotechnik ... Pottmeyer Memory Limitations in Artificial Intelligence ... Vitter hat gezeigt, dass viele in diesem Modell effiziente Entwicklungen

2. Gehe alle Tripel der Reihe nach durch und weise ihnen aufsteigende Inte-gerzahlen als rk(i) zu, d.h. ersetzte rk(i−1) durch rk(i). Tripel, bei denendie ersten beiden Komponenten (rk−1(i), rk−1(i+2k−1) gleich waren, be-kommen das gleiche rk(i) zugewiesen.

3. Sortiere nach i, d.h. bringe die Tripel in die initiale Reihenfolge.4. Gehe alle Tripel durch und aktualisiere die zweite Komponente, d.h. er-

setze rk−1(i + 2k−1) durch rk(i + 2k) . Das kann man machen, weil inSchritt 2 alle rk(i)s berechnet wurden.

Um den Algorithmus besser zu verstehen, betrachten wir an dieser Stelleeinen Durchlauf des Algorithmus mit konkreten Werten. Nehmen wir an, dassr1 bereits berechnet wurde, r2 soll mit dem nachsten Durchlauf der Schleifeberechnet werden. Wir betrachten den String, der an Position zwei beginnt,oder genauer gesagt das Tripel, das diesen String (“anan“ bei k=2) reprasen-tiert (siehe Abb. 9). Vor Beginn der Schleife ist rk(i = 2) = 2.

1. Infolge der Sortierung kommt das Tripel (2, 2, 2) an die 3. Position.2. r2(2) := 3, das Tripel wird also zu (3, 2, 2)3. Das Tripel kommt wieder an die 2. Position (Sortierung nach i)4. Die zweite Komponente wird durch r2(2 + 22 = 6) = 1 ersetzt, das Tripel

wird also zu (3, 1, 2)

Nach log2 N Durchlaufen bekommt man ein Suffixarray, in dem die Suffixedurch den zugewiesenen Namen lexikographisch sortiert sind (Abb. 9), wobeies eigentlich das Inverse eines Suffixarrays ist, wie es in 3.1 vorgestellt wurde.

Kommen wir nun zu der Laufzeit des Algorithmus. Fur die Schritte 1 und3 benotigt man jeweils O(sort(N)) I/Os, fur 2 und 4 jeweils O(scan(N)) I/Os.Da die Schleife log2 N Durchlaufe macht, werden insgesamt O(sort(N) log2 N)I/Os benotigt. Man kann diese Laufzeit noch verbessern, indem man beruck-sichtigt, dass Namen, die nur ein einziges Mal vorkommen, nicht mehrgeandert werden. In dem Beispiel wird in r0 der Name 4 nur einmal zuge-wiesen. Somit bleibt es bis zum Ende des Algorithmus unverandert, es giltalso: rh(i) = rk(i) fur alle h > k. Tripel mit der ersten Komponente, diedieser Regel entspricht, nennt man fertige Tripel. Solche Tripel werden beiweiteren Durchlaufen der Schleife nicht mehr berucksichtigt. Man lagert siein eine separate Datei aus und benutzt sie am Ende des Algorithmus zurKonstruktion des Suffixarrays. Zwar ist die Worst Case Laufzeit immer nochO(sort(N) log2 N), z.B. bei einem Text T = aaa...a, da aber in der Praxisdie Anzahl der fertigen Tripel schnell ansteigt, ist die tatsachliche Laufzeitmeistens viel besser.

7 Zusammenfassung

In dieser Arbeit habe ich die Volltextindizes vorgestellt. Es ist eine Daten-struktur, die die Stringsuche in einem Text unterstutzt. Dabei werden furjeden String, der im Text vorkommt, alle seine Suffixe gespeichert. Es bedeu-tet einen großeren Speicherbedarf als bei den anderen Suchstrukturen (z.B.invertierte Dateien), ermoglicht aber einfache und schnelle Suchalgorithmen.

107

Page 114: HEINZ NIXDORF INSTITUT Fakultät für Elektrotechnik ... Pottmeyer Memory Limitations in Artificial Intelligence ... Vitter hat gezeigt, dass viele in diesem Modell effiziente Entwicklungen

Außerdem konnen Volltextindizes bei Texten, die aus einem einzigen Stringbestehen (z.B. DNS-Sequenzen), eingesetzt werden, was bei anderen Artenvon Indizes nicht moglich ist.

In dieser Arbeit habe ich nur die einfache Stringabfrage betrachtet, auchdas exakte Stringmatching genannt. Eine komplexere Form der Abfrage aufdem externen Speicher, das so genannte approximative Stringmatching, bleibtbis heute ein offenes Problem. Ein weiteres Thema, welches ich in dieser Aus-arbeitung nicht bearbeitet habe, sind die Kompressionsalgorithmen, die zurReduzierung des benotigten Speichers bei Volltextindizes eingesetzt werdenkonnen.

Literatur

1. P. Sanders. Memory Hierachies - Models and Lower Bounds. In U. Meyer et al.Algorithms for Memory Hierarchies, S. 1-13. Springer Verlag, 2003

2. G. Gonnet, R. Baeza-Yates und T. Snider. New indices for text: PAT trees andPAT arrays. In W. B. Frakes and R. Baeza-Yates [Hrsg.], Information Retrieval:Data Structures and Algorithms. Prentice-Hall, 1992.

3. P. Weiner. Linear pattern matching algorithm. In Proceedings of the 14th Sym-posium on Switching and Automata Theory, S. 1-11. IEEE, 1973.

4. U. Manber und G. Myers. Suffix arrays: A new method for on-line string sear-ches. SIAM Journal of Computing, 22(5):935-948, 1993.

5. D. R. Morrison. PATRICIA - practical algorithm to retrieve information codedin alphanumeric. Journal of the ACM, 15(4):514-534, 1968.

6. R. M. Karp, R. E. Miller und A. L. Rosenberg. Rapid identification of repeatedpatterns in strings, trees and arrays. In Proceedings of the 4th Annual Sympo-sium on Theory of Computing, S. 125-136. ACM, 1972.

7. P. Ferragina und R. Grossi. The string B-tree: A new data structure for stringsearch in external memory and its applications. Journal of the ACM, 46(2):236-280, 1999.

8. R. Baeza-Yates, E. F. Barbosa und N. Ziviani. Hierarchies of indices for textsearching. Journal of Information Systems, 21(6):497-514, 1996.

9. D. R. Clark und J. I. Munro. Efficient suffix trees on secondary storage (ex-tended abstract). In Proceedings of the 7th Annual Symposium on DiscreteAlgorithms, S. 383-391. ACM-SIAM, 1996.

10. L. A. Arge, P. Ferragina, R. Grossi und J. S. Vitter. On sorting strings in exter-nal memory (extended abstract). In Proceedings of the 29th Annual Symposiumon Theory of Computing, S. 540-548. ACM, 1997.

11. A. Crauser and P. Ferragina. A theoretical and experimental study on theconstruction of suffix arrays in external memory. Algorithmica, 32(1):1-35, 2002.

108

Page 115: HEINZ NIXDORF INSTITUT Fakultät für Elektrotechnik ... Pottmeyer Memory Limitations in Artificial Intelligence ... Vitter hat gezeigt, dass viele in diesem Modell effiziente Entwicklungen

Algorithmen fürHardware Caches und TLBs

Stefan Frank

1 Einleitung

Bei der Entwicklung von neuen Algorithmen (für z.B. das Durchsuchen oder Sortieren vonDaten) ist es für die praktische Anwendbarkeit unerlässlich, auch Aspekte der Rechner-architektur zu berücksichtigen. So kann durch entsprechende Optimierung ein deutlicherGeschwindigkeitsvorteil erreicht werden, wie diese Ausarbeitung exemplarisch zeigen wird.Dabei wird das Ziel verfolgt die Anzahl der Zugriffe auf den Speicher möglichst gering zuhalten. Wie in Kapitel 8 des - dieser Ausarbeitung zugrunde liegenden - Buches [3] aus-geführt wird, haben zwar heutige CPUs (Central Processing Unit) eine Taktfrequenz vonmindesten 2 GHz, jedoch liegen die Zugriffszeiten auf den RAM bei ca. 60 ns. Die CPUmüsste also mindestens 120 Taktzyklen warten, bis ein angefordertes Datum aus dem RAM(Random Access Memory) in die lokalen Register des Prozessors geladen wurde. Es ist so-mit leicht verständlich, warum eine Reduzierung der RAM-Anfragen eine Verkürzung derRechenzeit zur Folge haben kann.

Um ein tiefer gehendes Verständnis für die Analyse von Algorithmen bzgl. ihrer Zugriffeauf den Speicher zu erhalten, wird zunächst in Kapitel 2 eine kurze Einführung in dieHardware-Struktur heutiger, moderner Rechner gegeben. Hierauf aufbauend werden Mo-delle vorgestellt, welche die Hardware abstrahieren und in denen Zugriffe berechnet werdenkönnen.

Die Kapitel 3 und 4 präsentieren anhand zweier konkreter Beispiele aus den BereichenSortieren und Suchen wie diese Modelle angewendet werden können. Die Beispiele zeigenaußerdem, dass sich der Aufwand lohnt, den man bzgl. der Optimierung von Algorithmenunter Berücksichtigung der Hardware betreibt, denn teilweise kann eine deutliche Verkür-zung der Rechenzeit erreicht werden.

2 Rechnerarchitektur und die sie abstrahierenden Modelle

An dieser Stelle werden zunächst Grundlagen der Rechnerarchitektur besprochen, welchefür jene Modelle, welche die Hardware abstrahiert darstellen, von Bedeutung sind. Da-bei stehen die sog. Caches und TLBs (Translation Lookaside Buffer) im Mittelpunkt derBetrachtungen.

109

Page 116: HEINZ NIXDORF INSTITUT Fakultät für Elektrotechnik ... Pottmeyer Memory Limitations in Artificial Intelligence ... Vitter hat gezeigt, dass viele in diesem Modell effiziente Entwicklungen

2.1 Cache-Speicher

Fordert der Prozessor ein Datum an, so werden diese vom Massenspeicher in den RAMgeladen und von dort an die CPU übermittelt. Wegen der, bereits in der Einleitung an-gesprochenen Diskrepanz zwischen Taktfrequenz der CPU und der Zugriffszeit des RAMswurden schnelle Zwischenspeicher eingeführt, auf welchen zwar ein sehr schneller Zugriffmöglich ist, jedoch nur eine (im Gegensatz zum RAM) beschränkte Speicherkapazität be-sitzt. Diese sog. Caches sind zwischen CPU und RAM geschaltet. Fordert die CPU einDatum an, so werden die Daten zunächst in den Cache geladen und von dort an die CPUübermittelt. Dabei gibt es i.d.R. mindestens zwei, manchmal auch drei Cache-Stufen (sog.Level-1-, Level-2- und Level-3-Caches). Dabei ist der Level-1-Cache sehr nahe bei der CPU(oftmals auf dem gleichen Chip) und kann die gewünschten Daten häufig schon in einemCPU-Taktzyklus zur Verfügung stellen, hat dafür aber nur eine Speicherkapazität von 8KB bis 32 KB. Der Level-2-Cache benötigt hingegen schon 5-13 Prozessorzyklen, hat dafüraber eine Speicherkapazität von bis zu 4 MB (Zahlen entnommen aus: [1], Seite 310)).Befinden sich die angeforderten Daten im Cache, so liegt ein sog. Cache-Hit vor, andern-falls ein Cache-Miss und die Daten müssen aus dem RAM oder einem hierarchisch tiefergelegenen Cache angefordert werden.

Der Cache ist in sog. Sets unterteilt, wobei jeder Set eine oder mehrere Cachelines hal-ten kann. Die Anzahl der Cachelines pro Set bezeichnet man als sog. Wege-Assoziativität,bei 4 Cachlines spricht man von einem 4-Wege-assoziativen Speicher. Dabei ist eine Ca-cheline die kleinste Einheit, welche an den Cache übermittelt wird und ist i.d.R. 32 bis64 Bytes lang. Hierdurch versucht man spatiale (räumliche) Lokalität auszunutzen, da einangefordertes Datum B, welches direkt auf ein vorher angefordertes Datum A folgt, auchoftmals räumlich (also im Speicher) nebeneinander liegt. Datum B hat man innerhalb derCacheline somit automatisch zusammen mit Datum A übertragen und muss dieses nichtextra in den Cache laden. Das Datum, welches im Speicher an der Stelle x liegt, gehörtzur Cacheline xdivB, wobei B die Anzahl der Dateneinheiten (z.B. 32-Bit-Integer-Words)ist, welche in eine Cacheline passen. Wird das Datum x angefordert, wird somit die ge-samte Cacheline in den Cache geladen und zwar in jenes Set, welches sich berechnet durch(xdivB)modS, wobei S die Anzahl der Sets ist. Sind alle Cachelines innerhalb eines Setsbelegt, so muss eine Cacheline aus dem Cache verdrängt werden, obwohl in einem anderenSet des Speichers noch eine Cacheline frei wäre. Häufig wird jene Line verdrängt, welcheam längsten nicht mehr benutzt wurde (Least-Recently-Used (LRU) - Verfahren). Wirddiese verdrängte Cacheline später wieder angefordert, so spricht man von einem „Conflicemiss“, erfolgt die Verdrängung weil der gesamte Speicher belegt ist, so nennt man das spä-tere Wiederanfordern dieser Line „Capacity miss“. Wird das Datum erstmalig angefordert,so muss dieses zu einem Miss führen und man spricht dann von einem „Compulsory miss“.Temporale Lokalität ist daher ein weiteres Ziel, welches man verfolgt: Daten, die oftmalshintereinander aufgerufen werden sollen auch im Cache bleiben und nicht verdrängt wer-den, um so Misses zu reduzieren. Für weitere Informationen bzgl. Caches sei an dieserStelle auf Kapitel 9 des Buches [2] verwiesen

110

Page 117: HEINZ NIXDORF INSTITUT Fakultät für Elektrotechnik ... Pottmeyer Memory Limitations in Artificial Intelligence ... Vitter hat gezeigt, dass viele in diesem Modell effiziente Entwicklungen

2.2 Der Translation Lookaside Buffer

Heutige Software benötigt häufig mehr Speicher als physikalisch zur Verfügung steht. Wei-terhin wird i.d.R. nicht nur ein Prozess ausgeführt, sondern mehrere. Hieraus resultierendwurde der virtuelle Speicher und der zugehörige logische Adressraum eingeführt, wobeijeder Prozess seinen eigenen Adressraum erhält, welcher wiederum in kleinere gleichgroßeSegmente, den sog. Pages unterteilt ist. Die CPU fordert ein Datum aus dem virtuellenSpeicher des gerade berechneten Prozesses an und nutzt dafür die logische Adresse. Diesemuss zunächst übersetzt werden in eine physikalische was über die sog. Page Table erfolgt.Hier wird jeder logischen Adresse eine physikalische zugeordnet, also eine Stelle im RAM,die das entsprechende Datum hält. Befindet sich das Datum noch im Massenspeicher, sowird es zunächst dort angefordert und dann die RAM-Adresse zugeordnet.

Das Nachschlagen in der Page Table ist sehr zeitaufwändig, da sie häufig selber im RAMgehalten wird. Daher wurde der sog. Translation Lookaside Buffer (TLB) eingeführt, einedirekt in Hardware realisierte Schaltung, welche Übersetzung von logischer zu physikali-scher Adresse halten kann (i.d.R. 32 bis 64 Einträge). Erfolgt eine Adressauflösung, so wirddas Paar physikalische / logische Adresse in der TLB zwischengespeichert. Erfolgt eine er-neute Anforderung der gleichen logischen Adresse, so muss diese nicht über die Page Tableübersetzt, sondern kann durch den viel schnelleren TLB aufgelöst werden, vorausgesetzt dieÜbersetzung wurde in der Zwischenzeit auf Grund von Platzmangel nicht wieder aus demSpeicher verdrängt. Ähnlich dem Cache existieren auch bei einem TLB TLB-Misses undTLB-Hits. Auch hier gibt [2] vertiefende Informationen in Kapitel 10 „Virtueller Speicher“.

2.3 Modelle

Studiert man die beiden obigen Unterabschnitte, so erschließt sich leicht, dass man vorallem die Anzahl der Cache- und TLB-Misses reduzieren möchte. Dass man die Dateneinmalig in den Speicher laden muss bzw. eine Adresse übersetzen muss, lässt sich nichtumgehen. Wenn ein Datum jedoch im Speicher bzw. eine Übersetzung in der TLB ist, sosollten diese Einträge frühestens dann verdrängt werden, wenn sie nicht wieder benötigtwerden. Somit lässt sich die Anzahl der Misses reduzieren und die Rechengeschwindigkeiterhöhen.

U.a. um zu analysieren, wie viele Cache- und TLB-Misses innerhalb eines Programmserfolgen, wurden Modelle entwickelt, welche die wichtigsten Hardware-Eigenschaften inParameter abbilden, mit denen dann gerechnet werden kann. Eines dieser Modelle ist dassog. Cache Memory Model (CMM), in dem davon ausgegangen wird, dass zwar ein Cacheexistiert, jedoch keine TLB. Der Cache ist dabei ein virtueller Cache, er kann also logischeAdressen verarbeiten. Zwar existieren solche Caches, in der Realität spielen sie jedochnur eine untergeordnete Rolle, da fast alle Caches physikalische Caches sind und somiteine bereits aufgelöste physikalische Adresse benötigen. Über folgende, häufig bereits obeneingeführte Parameter, verfügt dieses Modell (siehe auch [3], Seite 178):

• N = Anzahl der Dateneinheiten (z.B. 32-Bit-Integer-Words), welche sortiert, durch-sucht,... werden müssen

• M = Anzahl der Dateneinheiten, welche im Cache gehalten werden können

• B = Anzahl der Dateneinheiten in einer Cacheline

111

Page 118: HEINZ NIXDORF INSTITUT Fakultät für Elektrotechnik ... Pottmeyer Memory Limitations in Artificial Intelligence ... Vitter hat gezeigt, dass viele in diesem Modell effiziente Entwicklungen

• a = Assoziativität des Caches

• Anzahl der Cache-Misses

• Anzahl der ausgeführten Instruktionen

Wie oben bereits erläutert, ist dieses Modell unrealistisch, da TLBs keine Berücksich-tigung finden. Das Internel Memory Modell (IMM) ergänzt das CMM um entsprechendeParameter:

• T = Anzahl der Adressübersetzungen, welche eine TLB halten kann

• B’ = Anzahl der Dateneinheiten in einer Page

• Anzahl der TLB-Misses

Bei der Verwendung dieser Modelle muss dabei immer berücksichtigt werden, dass man alsSoftwareentwickler keinen Einfluss darauf hat, wann welches Datum im TLB oder Cacheverdrängt oder gehalten wird. Dies sind Entscheidungen, welche die Hardware intern trifftund von außen nicht steuerbar ist. Im Rahmen des CMM und IMM geht man bzgl. derVerdrängungsstrategie davon aus, dass LRU eingesetzt wird, wie oben bereits beschrieben.

3 Konkretes Anwendungsbeispiel: Sortieren

In Kapitel zwei wurden das Cache Memory Modell und Internel Memory Modell vorgestellt.Vor allem letzteres soll nun herangezogen werden, um die Cache- und TLB-Misses vonSortieralgorithmen zu analysieren und zu verbessern. Dies soll beispielhaft an (P)LSB-Radix-Sort und Counting-Sort erfolgen.

3.1 Counting-Sort und LSB-Radix-Sort

Algorithmus 1 Couting-Sort-Algorithmus1: Count-Phase2: for int i = 0; i < k; i++ do3: C[A[i].Key()]++;4: end for5: Prefix sum-Phase6: for int i = 0; i < n; i++ do7: C[i] = C[i] + C[i-1];8: end for9: Permute-Phase

10: for int i = k-1; 0 <= i; i-- do11: Z[C[A[i]]] = A[i];12: C[A[i].Key()]--;13: end for

Counting-Sort ist ein stabiles Sortierverfahren, welches ohne direkte Vergleiche der zusortierenden Schlüssel auskommt (siehe auch [6], Kapitel 8.2). Der Algorithmus unterteilt

112

Page 119: HEINZ NIXDORF INSTITUT Fakultät für Elektrotechnik ... Pottmeyer Memory Limitations in Artificial Intelligence ... Vitter hat gezeigt, dass viele in diesem Modell effiziente Entwicklungen

Abbildung 1: Beispielhafter Auszug aus der Permute-Phase des Counting-Sort-Algorithmus

sich dabei in drei Phasen: Count-Phase, Prefix sum-Phase und Permute-Phase. Währendder Count-Phase wird über das Ausgangsarray A gelaufen, das Vorkommen jeder einzelnenZahl gezählt, indem in einem Zähler-Array C jener Eintrag inkrementiert wird, der zu demSchlüssel der Datenstruktur im Ausgangsarray gehört: C[A[i].Key()] + +. Die Größe desZählerarrays richtet sich nach dem größten Schlüssel, der sortiert werden soll. In der Prefixsum-Phase wird über das Zählerarray C gelaufen und das Vorkommen der Zahl an derStelle i aufaddiert auf das Vorkommen der Zahlen, die kleiner sind als i: C[i] = C[i] +C[i−1]. In der Permute-Phase wird das Ausgangsarray von hinten nach vorne durchlaufen(nur so kann Stabilität garantiert werden) und im Zählerarray nachgeschaut, an welcheStelle der im Ausgangsarray aufgefundene Schlüssel in ein extra Zielarray Z geschriebenwerden soll: Z[C[A[i].Key()]] = A[i]. Wurde das Datum in das Zielarray kopiert, so wirdder entsprechende Eintrag im Zählerarray dekrementiert: C[A[i].Key()] − −. Wenn k dieAnzahl der Keys ist, welche sortiert werden müssen und n die Größe des Zählerarrays,dann beträgt die Laufzeit des Algorithmus O(k+n), denn es muss insgesamt zweimal überdas Ausgangsarray (Phase 1 und 3) und einmal über das Zählerarray (Phase 2) gelaufenwerden (siehe auch Abbildung 1 und Algorithmus 1).

Das Problem des Counting-Sort-Algorithmus ist, dass die größte Zahl, welche sortiertwerden soll im Vornherein bekannt sein muss und die Anzahl der Zählerarray-Einträge vondieser Zahl abhängt. Möchte man z.B. Zahlen von 0 bis 1000 Sortieren, wird ein Arraymit 1001 Einträgen benötigt. Least Significant Bit (LSB)-Radix-Sort bietet eine Lösungfür dieses Problem (siehe [6], Kapitel 8.3). Hierbei werden die zu sortierenden SchlüsselStelle für Stelle von hinten nach vorne durchgegangen und nach der Ziffer der geradebetrachteten Stelle sortiert. Zunächst werden also alle Zahlen nach der letzten Stelle, dannnach der vorletzten usw. in die richtige Reihenfolge gebracht. Man muss somit nur nochwissen, wie viele Stellen die größte Zahl hat, die sortiert werden soll und benötigt einZählerarray, welches (in diesem Beispiel) maximal 10 Einträge aufweisen muss. Es sei andieser Stelle angemerkt, dass das Alphabet, welches man sortiert, natürlich irrelevant ist,nur beispielhaft sei dies hier anhand von Zahlen und den Ziffern 0 bis 9 dargestellt. Für

113

Page 120: HEINZ NIXDORF INSTITUT Fakultät für Elektrotechnik ... Pottmeyer Memory Limitations in Artificial Intelligence ... Vitter hat gezeigt, dass viele in diesem Modell effiziente Entwicklungen

Abbildung 2: 32-Bit-Integer-Word mit eingezeichneter 8 Bit Radix r

das Sortieren der Zahlen nach Stellen bietet sich für jede Iteration jeweils Counting-Sortan. Sei d die Anzahl der Stellen, dann muss d-mal Counting-Sort aufgerufen werden unddie resultierende Laufzeit ist O(d(k + n)).

3.2 Bestimmung einer Radix für LSB-Radix-Sort

Es sei folgende Situation gegeben: N 32-Bit-Integer-Zahlen sollen sortiert werden. DieFragestellung ist nun, in wie viele Stellen diese 32-Bit-Zahl unterteilt wird, um die Sortie-rung dann mittels LSB-Radix-Sort unter Verwendung von Counting-Sort durchzuführen.Wird zum Beispiel eine Radix r von 8 (eine Stelle hat 8 Bit) gewählt, dann benötigt dasCounting-Array 28 = 256 Einträge und es muss für jeden der 32/8 = 4 Stellen jeweils einCounting-Sort-Durchgang erfolgen. Wählt man hingegen r = 16, so muss Counting-Sortnur zwei mal aufgerufen werden, es ist jedoch ein Zählerarray von 216 = 65536 Einträgennötig.

[3], Seite 190f. beschreibt eine Vorgehensweise, welche primär auf TLB-Misses aufbautund eine Analyse für die TLB-Miss-Wahrscheinlichkeit aufstellt. Dabei wird davon aus-gegangen, dass es in der Permute-Phase des Counting-Sort-Algorithmus zu den meistenTLB-Misses kommt. Diese Annahme ist realistisch, wenn man davon ausgeht, dass dasZählerarray gänzlich in eine Page passt. Während der Couting-Phase besteht das workingset1 aus dem Ausgangsarray, welches Seite für Seite geladen wird (sequentieller Zugriff).Auf das Zählerarray hingegen wird randomisiert zugegriffen, so dass dieses komplett überdie TLB referenziert werden muss. Dies benötigt jedoch auch nur einen Seiteneintrag in derTLB, da ja davon ausgegangen wird, dass das komplette Array in eine Seite passt. Somitwerden in der Counting-Phase nur zwei TLB-Einträge benötigt, in der Prefix sum-Phasesogar nur eine Seite, nämlich die des Couting-Arrays selber. Während der Permute-Phasewird hingegen eine Seite des Ausgangsarrays und die des Zählerarrays bentötigt, sowiemin

⌈B′

N

⌉, 2r

Seiten für das Zielarray. Letztere Berechnung kommt dadurch zustande,

dass entweder das komplette Zielarray (auf welches ja ebenfalls randomisiert zugegriffenwird) in den Speicher geladen wird, welches dB′

N e Pages benötigt oder aber für jeden Array-Eintrag mindestens eine freie Page vorsieht, in der das Datum abgelegt werden kann (2r

Seiten). Ist eine Seite voll, so kann diese Referenz aus dem Speicher entfernt und durcheine neue ersetzt werden. Auf die verdrängte Seite muss garantiert nicht wieder zugegriffenwerden, da diese ja voll ist und daher keine weiteren Daten aufnehmen kann. Somit ist die

1working set = Anzahl der Seiten, welche in einem bestimmten Zeitraum benötigt werden; alternativeErklärung: Anzahl der nötigen Seiteneinträge in einer TLB, so dass keine Seite verdrängt werden muss,die später noch einmal benötigt wird (capacity miss)

114

Page 121: HEINZ NIXDORF INSTITUT Fakultät für Elektrotechnik ... Pottmeyer Memory Limitations in Artificial Intelligence ... Vitter hat gezeigt, dass viele in diesem Modell effiziente Entwicklungen

Permute-Phase tatsächlich der „Flaschenhals“ des Algorithmus bzgl. der TLB-Misses. Gehtman davon aus, dass 2r Seiten für das Zielarray benötigt werden, so ist die Wahrschein-lichkeit für einen TLB-Hit in der Permute-Phase bei Zugriff auf das Zielarray (T−2)

2r . T − 2ergibt sich aus der Tatsache, dass von T möglichen TLB-Einträgen je eine Seite bereitsfür das Ausgangs-Array und das Zähler-Array reserviert sind. Die Wahrscheinlichkeit füreinen TLB-Miss ist somit 1 − (T−2)

2r = 2r−(T−2)2r . Für r = 6 ergibt sich somit eine Miss-

Wahrscheinlichkeit von 1/32 und für r = 7 von 1/2. Tests auf einer UltraSparc-II-Maschinehaben tatsächlich deutlich längere Ausführungszeiten für r = 7 als für r = 6 festgestellt.Es sei an dieser Stelle darauf hingewiesen, dass hier nur TLB-Betrachtungen eingeflossensind. Berücksichtigt man auch Cache-Strukturen, so erzielt man mit r = 5 gute Erfolge,was sich experimentell ebenfalls bestätigen ließ.

3.3 PLSB-Radix-Sort

Presorted LSB-Radix-Sort (nach [4]) stellt eine Optimierung des LSB-Radix-Sort-Ver-fahrens dar, wobei die zu sortierende Zahlenfolge in kleinere Segmente zerlegt wird unddiese Segmente zunächst jeweils sortiert werden. Danach wird dann die gesamte segment-weise sortierte Eingabe sortiert, wie Algorithmus 2 zeigt. Der Algorithmus verfügt über

Algorithmus 2 PLSB-Radix-Sort nach Rahman und Raman [sic]1: initialise GlobalCount2: for each local sort i do3: initialise LocalCount4: count keys in segment i of Data15: accumulate values in GlobalCount6: prefix sum LocalCount7: permute from segment i of Data1 to segment i of Data28: end for9: prefix sum GlobalCount

10: permute globally from Data2 to Data1

zwei Arrays Data1 und Data2 (wobei Data1 das Ausgangsarray ist) und zwei ZählerarraysLocalCount und GlobalCount. Zunächst wird jedes Segment i von Data1 nach Segment ivon Data2 sortiert, wobei auch das globale Zählerarray entsprechend der Anzahl der Keysin dem Segment i erhöht wird. Abschließend wird in Zeile 9 und 10 das gesamte Arraysortiert von Data2 nach Data1, so dass in Data1 die sortierte Folge gespeichert ist.

Anhand dieses Beispiels soll nun eine Cache-Miss-Analyse vorgenommen werden. Aucheine TLB-Miss-Analyse ist möglich, welche der Cache-Miss-Analyse jedoch sehr ähnelt undin [4] nachgeschlagen werden kann.

Für die nun folgenden Betrachtungen gilt die folgende Voraussetzung (im IMM-Modell):Die Anzahl der Dateneinheiten s in einem Segment sei s=BC

2 . Es gelte weiterhin m = 2r,γ= s

m , γ ≥ 2, C = a·S, a = 4. Schritt (Zeile) 1 und 9 verursachen demnach jeweils mB Cache-

Misses, denn die m Zählerarray-Elemente benötigen mB Cachelines (es sei hier der Einfach-

heit halber davon ausgegangen, dass das Zählerarray optimal im Speicher liegt und somiteine Addition von +1 entfallen kann (siehe hierzu auch beispielhaft Abbildung 3)). Die for-Schleife wird N

s mal durchlaufen, somit sind für Schritt 3 maximal Ns · m

B = Nγ·B ≤ 0, 5N

B

115

Page 122: HEINZ NIXDORF INSTITUT Fakultät für Elektrotechnik ... Pottmeyer Memory Limitations in Artificial Intelligence ... Vitter hat gezeigt, dass viele in diesem Modell effiziente Entwicklungen

Abbildung 3: Die k Elemente mit dem Wert i des j-ten Segments passen zwar in eineCacheline liegen jedoch ungünstig und benötigen daher zwei Cachelines.

Cache-Misses nötig. Da 2 ≤ sm gilt folgt, dass m ≤ s

2 = BC4 = B·a·S

4 = S · B und somitist maximal eine Cacheline in jedem Set des Caches mit dem LocalCount-Array belegt. InSchritt vier muss das Segment i sequentiell in den Speicher geladen werden, wofür nachbekanntem Schema gilt N

s ·sB . Durch die jeweiligen Segmente werden maximal zwei Cache-

lines je Set belegt, denn s = BC2 = B·a·S

2 = 2 ·B · S. Bei Schritt fünf kann man theoretischdavon ausgehen, dass das GlobalCount bereits im Speicher ist, für den Worst-Case habendie Autoren jedoch trotzdem N

s · mB ≤ 0, 5N

B Cache-Misses hinzuaddiert. Schritt 6 benö-tigt keine weiteren Cache-Misses, da das LocalCount-Array vorher bereits in den Speichergeladen wurde und durch die Nutzung in Schritt fünf bestimmt nicht LRU ist. In Schritt7 wird davon ausgegangen, dass nur das LocalCount-Array im Speicher ist. Somit müssendas Data1-Array, auf welches sequentiell und das Data2-Array auf welches randomisiert zu-gegriffen wird, in den Speicher geladen werden (2 · s

B Cache-Misses). Positiv wäre es, wenndas Data2-Array (maximal 2 Cachelines je Set) und das Loacalcount-Array (maximal eineCacheline je Set) im Speicher verbleiben würden, denn auf diese wird randomisiert zuge-griffen. Da dies jedoch nicht garantiert werden kann, wird vom Worst Case ausgegangenund dies wäre die Verdrängung aller 3 Cachelines und das spätere Nachladen dieser Inhal-te, also 3 · S = 3·a·S

4 = 3C4 Cache-Misses. Insgesamt sind somit N

s

(2 · s

B + 3 · C4

)≤ 3, 5N

B

Misses für Schritt 7 anzurechnen. Für Schritt 10 wird die Variable k(i,j) eingeführt, welcheaussagt, dass der Schlüssel i im j-ten Segment genau k-mal vorkommt. Möchte man diesek Schlüssel von Data2 nach Data1 permutieren, so benötigt man jeweils

⌈k(i,j)

B

⌉+ 1 Ca-

chelines, wobei das +1 aus der Tatsache heraus resultiert, dass die k Schlüssel nicht exaktzu Beginn einer Cachline anfangen müssen, sondern möglicher weise sogar an ihrem Ende(siehe auch Abbildung 3). Des weiteren wird genau eine Cacheline des GlobalCount-Arraysbenötigt, welche nämlich den Eintrag i hält. Somit resultiert als gesamter Cacheline-Bedarffür die Permutation eines bestimmten k(i,j): 2 ·

(⌈k(i,j)

B

⌉+ 1

)≤ 2 · k(i,j)

B + 5.Addiert man die Kosten für die einzelnen Schritte auf, so stellt man fest, dass die Anzahl

der Cache-Misses kleiner ist als 7, 5·NB +5·N

γ +2·mB . Da jedoch gilt S ·B ≤ N (hier wird von

einem sehr großen N ausgegangen) und hieraus folgt m ≤ N , kann für das Gesamtergebnisauch geschrieben werden: ≤ 7, 5 · N

B + 5 · Nγ + 2 · N

B . Wenn γ = Ω(B), dann ist die Anzahl

der Cache-Misses gerade O(

NB

). Man kann ebenfalls zeigen, dass unter der Bedingung

γ = Ω(B) auch die Anzahl der TLB-Misses gerade O(

NB

)ist.

Experimente auf einer UltraSparc-II-Maschine haben gezeigt, dass der PLSB-Radix-Sort-Algorithmus tatsächlich eine deutlich bessere Geschwindigkeit aufweist, als der nichtoptimierte LSB-Radix-Sort. So benötigt LSB-Radix-Sort für das Sortieren von 32 Million32-Bit-Unsigned-Integer-Zahlen mit Radix 11 31,71 Sekunden, während PLSB-Radix-Sortmit Radix 11 nur 17,03 Sekunden benötigte.

116

Page 123: HEINZ NIXDORF INSTITUT Fakultät für Elektrotechnik ... Pottmeyer Memory Limitations in Artificial Intelligence ... Vitter hat gezeigt, dass viele in diesem Modell effiziente Entwicklungen

Abbildung 4: Einfache Trie-Struktur. Fett markierte Knoten sind akzeptierte Endzustände.

4 Konkretes Anwendungsbeispiel: Suchen

Während im vorhergehenden Kapitel das Sortieren im Mittelpunkt stand, soll hier einAlgorithmus nach Acharya, Zhu und Shen vorgestellt [1] werden, welcher die Speiche-rung der Knoten in Trie-Suchbäumen optimiert. Abbildung 4 zeigt beispielhaft eine solcheTrie-Struktur. Soll herausgefunden werden, ob das Wort „Baum“ in einem Wörterbuch vor-kommt, so muss Buchstabe für Buchstabe überprüft werden, ob ein entsprechender Linkaus dem gerade betrachteten Knoten hinausführt. So beginnt das gesuchte Wort mit „B“und der Startknoten verfügt auch über eine Kante mit dem Label „B“, also gelangt man zudem Knoten mit der Beschriftung „B“. Ist man bei dem Buchstaben „u“ des Wortes „Baum“angekommen, so müssen alle drei hinausführenden Kanten des Knotens „Ba“ überprüft wer-den, ob sie mit „u“ gelabelt sind. Ziel ist es, genau diese Suche innerhalb der Knoten zuoptimieren.

4.1 3 Datenstrukturen

Acharya, Zhu und Shen schlagen in ihrem Paper vor, drei verschiedene Datenstruktu-ren zu nutzen. Ist die Anzahl der ausgehenden Links eines Knotens klein, so sollen sog.Partitioned-Arrays verwendet werden, welche aus je zwei Cachlines bestehen. In eine Cach-line werden die Schlüssel in der anderen die korrespondierenden Pointer auf den zugehörigenKnoten der nächsten Ebene des Tries hinterlegt. Partitioned-Arrays sind fundamental füralle drei Datenstrukturen, welche die Autoren in ihrem adaptiven Algorithmus verwendethaben und werden immer wieder eingesetzt. Für die Trennung von Keys und Pointer inseparaten Arrays spricht die Tatsache, dass alle Keys in einer Cachline gespeichert sind undsomit erst diese Cacheline auf das Vorhandensein eines gesuchten Keys überprüft werdenkann. Ist ein Key nicht vorhanden, müssen auch keine Pointer (und somit auch nicht diezweite Cacheline) geladen werden, was die Anzahl der geladenen Lines reduziert ([1], Seite298):

117

Page 124: HEINZ NIXDORF INSTITUT Fakultät für Elektrotechnik ... Pottmeyer Memory Limitations in Artificial Intelligence ... Vitter hat gezeigt, dass viele in diesem Modell effiziente Entwicklungen

Abbildung 5: Links: Partitioned-Array mit beispielhafter Belegung für den Knoten „Ba“;Rechts: Hashtable mit Partitioned-Array als Overflow-Chain

This reduces the number of links loaded and avoids loading any links forunsuccessful searches.

Bei heutigen Rechnersystemen ist es des weiteren so, dass nicht gewartet werden muss,bis die gesamte Cacheline geladen ist, sondern nur das Laden der ersten Speicheradresse derCacheline abgewartet werden muss. Während auf diese Daten bereits zugegriffen werdenkann, wird im Hintergrund der Rest der Cacheline übertragen. Somit ist es auch aus diesemAspekt sinnvoll

... that the data structures should be designed so as to pack as many elementsin a cache line as possible. ([1], Seite 298)

Acharya, Zhu und Shen schlagen zwei Algorithmen sowohl für große als auch für kleineAlphabete vor. Die nun folgende Beschreibung erläutert jenen für große Alphabete, fürdie Abweichungen innerhalb des Algorithmus für kleine Alphabete sei an dieser Stelle aufdas Paper verwiesen. Reicht ein Partitioned-Array zur Speicherung aller Keys nicht mehraus, so wird in eine B-Tree-Struktur umgeschaltet. Experimente haben ergeben dass diemaximale Tiefe eines solchen B-Trees gerade 4 sein sollte. Der Fanout der einzelnen Knotendes B-Trees ist begrenzt durch die Anzahl der Keys, welche in einer Cacheline hinterlegtwerden können. Auch hier werden die einzelnen Knoten des Trees durch Partitioned-Arraysrealisiert. Übersteigt der B-Tree die Tiefe 4, so wird in eine Hashtable umgeschaltet, wobeidie Overflow-Chain für den Konflikt-Fall ebenfalls in einem Partitioned-Array realisiertwird.

4.2 Experimentelle Ergebnisse

Die Autoren haben verschiedene Tests durchgeführt, um die Leistungsfähigkeit ihres Al-gorithmus zu beweisen. So nahmen sie ein englisches Standard-Wörterbuch (Webster’sUnabridged Dictionary) und ließen hierin nach allen 212.933 Wörtern suchen, welche inMelville’s „Moby Dick“ auftauchen. Der Ternary-Algorithmus, welcher eine sehr effiziente

118

Page 125: HEINZ NIXDORF INSTITUT Fakultät für Elektrotechnik ... Pottmeyer Memory Limitations in Artificial Intelligence ... Vitter hat gezeigt, dass viele in diesem Modell effiziente Entwicklungen

Abbildung 6: Adaptiver Algorithmus im Vergleich zu einfachen B-Tree-Strukturen (aus:[1], Seite 304)

Abbildung 7: Adaptiver Algorithmus im Vergleich zu einfachen Hashtable-Strukturen (aus:[1], Seite 304)

Implementierung der Trie-Struktur darstellt (siehe [5]), benötigte auf einer Sun-Ultrasparc-II-Maschine für die Suche ca. 2,25 Sekunden, während der hier vorgestellte adaptive Algo-rithmus gerade etwas mehr als 0,5 Sekunde brauchte.

Für einen weiteren Versuch nutzten sie ein Beispiel aus der Welt des Dataminings. Siestellten einen virtuellen Laden auf und wollten wissen, welche Waren oftmals zusammengekauft werden. Hierfür wurden tausende von Einkaufszetteln erstellt mit durchschnitt-lich 4 jedoch maximal 10 Waren. Interessant ist hierbei das sehr große Alphabet: Da derLaden 10.000 Waren führt hat das Alphabet auch eine Kardinalität von 10.000, währenddas Wörterbuchbeispiel gerade mal ein Alphabet mit ca. 60 Zeichen hatte (Groß- undKleinschreibung, Sonderzeichen). Somit ist hier sehr wahrscheinlich, dass viele Hashtableszum Einsatz kommen, die in dem Wörterbuchbeispiel aus verständlichen Gründen kaumeine Rolle gespielt haben. Die Autoren haben daher getestet, wie lange das Datamininggedauert hat, wenn nur B-Trees innerhalb der Trie-Knoten eingesetzt werden bzw. wennzwischen B-Trees und Hashtables umgeschaltet wird. Abbildung 6 zeigt die Resultate für20.000, 40.000, 80.000 und 160.000 Einkaufszettel. Deutlich ist zu erkennen welche Ge-schwindigkeitsvorteile der adaptive Algorithmus gegenüber den reinen B-Trees hat. Dasgleiche Experiment wurde auch im Vergleich zu Hashtables anstatt B-Trees durchgeführt.Auch hier ist der adaptive Algorithmus noch besser, wie Grafik 7 zeigt, auch wenn derGeschwindigkeitsvorteil längst nicht so eindeutig ist, wie das noch im Vergleich zu B-Treesder Fall war.

119

Page 126: HEINZ NIXDORF INSTITUT Fakultät für Elektrotechnik ... Pottmeyer Memory Limitations in Artificial Intelligence ... Vitter hat gezeigt, dass viele in diesem Modell effiziente Entwicklungen

5 Zusammenfassung

Um die Zugriffs- und Übersetzungszeiten zu reduzieren, wurden Caches und TLBs einge-führt. Diese können ihre Leistungsfähigkeit jedoch nur zeigen, wenn auch die Cache- bzw.TLB-Misses reduziert werden. Im Falle eines TLB-Miss muss die logische Adresse gänzlichneu übersetzt werden, wodurch der TLB keinen zeitlichen Gewinn bringen würde. Auchim Falle eines Cache-Miss müsste die CPU warten bis der Cache die Daten von Cachestieferer Ebene oder gar vom RAM selber bereit gestellt bekommt.

Modelle helfen bei der Bewertung eines Algorithmus bzgl. der Hits und Misses undabstrahieren dafür die vorhandene Hardware. Das Cache Memory Modell berücksichtigtdabei TLB-Architekturen nicht, was jedoch unrealistisch ist, da fast jeder Rechner übereine TLB verfügt. Das Internal Memory Modell schließt diese Lücke und beschreibt sowohlCaches als auch TLBs.

Rahman und Raman [sic] verwendeten diese Betrachtungsweise um einen effizienterenRadix-Sort-Algorithmus zu entwerfen, den sie PLSB-Radix-Sort nannten. Durch Vorsor-tieren der Zahlenfolge kann der randomisierte Zugriff auf das Ziel-Array reduziert werden.

Acharya, Zhu und Shen hingegen nahmen sich dem Problem der effizienten Suche inTrie-Baum-Knoten an und entwickelten eine Datenstruktur, welche sich der Größe desFanouts anpasst. Tests ergaben teilweise deutliche Laufzeitvorteile gegenüber dem Ternary-Algorithmus.

Literatur

[1] Acharya, Zhu, ShenAdaptive Algorithms for Cache-efficient Trie Search, ALENEX’99, Seiten 296-311,Springer-Verlag Berlin Heidelberg, 1999

[2] Carter, NicolausComputerarchitektur, mitp-Verlag / Bonn, 2003

[3] Goos, Hartmanis, van LeeuwenAlgorithms for Memory Hierarchies, Springer-Verlag Berlin Heidelberg, 2003

[4] Rahman, RamanAdapting radix sort to the memory hierarchy, ALENEX’00, Seiten 131-146, Springer-Verlag Berlin Heidelberg, 2000

[5] Bentley, SedgewickFast Algorithms for Sorting and Searching Strings, Proceedings of the eighth annu-al ACM-SIAM symposium on Discrete algorithms, Seiten: 360-369 , New Orleans,Louisiana, United States, 1997

[6] Cormen, Leiserson, Rivest, SteinIntroduction to Algorithms, Second Edition, The MIT Press, Cambridge, Massachu-setts London, England, 2001

120

Page 127: HEINZ NIXDORF INSTITUT Fakultät für Elektrotechnik ... Pottmeyer Memory Limitations in Artificial Intelligence ... Vitter hat gezeigt, dass viele in diesem Modell effiziente Entwicklungen

Cacheoptimierungen fur Numerische Algorithmen

Tobias Berghoff

1 EinleitungNumerische Algorithmen werden in vielen Anwendungsbereichen wie Simulationen, Multimedia oderKryptographie eingesetzt. In vielen Fallen ist ihre Laufzeit fur die Gesamtlaufzeit der Anwendung domi-nant, weshalb es wichtig ist, sie effizient zu implementieren. Typischerweise arbeiten die Algorithmen aufgroßen Datenmengen, die im Hauptspeicher abgelegt sind. Auf jedem Element der Datenmenge fuhrt derProzessor eine schnell zu berechnende Operation aus, die haufig weniger Zeit braucht, als das Lesen einesneuen Datums aus dem Hauptspeicher in den Cache, bzw. die Register. Die Laufzeit dieser Algorithmenwird demnach haufig durch die Datenzugriffe und nicht durch die Rechenoperationen dominiert.

Die Speicherhierarchie, die in diesem Text betrachtet werden soll, ist die zwischen Hauptspeicher,Cache und Registern. Es wird beschrieben, wie die Anzahl der Zugriffe auf die tiefer liegenden Schichtender Hierarchie reduziert werden kann, und wie Kenntnis uber das Verhalten des Algorithmus ausgenutztwerden kann um den Speicherdurchsatz zu maximieren.

2 GrundlagenDie Funktionsweise von Caches wird im Weiteren als bekannt vorausgesetzt, es wird aber naher auf dasihnen Zugrunde liegende Prinzip der Zugriffslokalitat eingegangen. Dabei werden Iterationsraume undDistanzvektoren als Beschreibungsform von Schleifennestern vorgestellt.

2.1 SchleifennesterEin Schleifennest der Tiefe n ist eine Verschachtelung von n Schleifen. In wissenschaftlichen Program-men wird ein Großteil der Laufzeit in solchen Schleifen verbracht. Das macht sie fur die Optimierunginteressant und viele Optimierungsansatze verschiedenster Zielsetzung basieren auf der Umstrukturie-rung dieser Schleifennester. Diese Umstrukturierungen stellen wiederum einen signifikanten Teil der sogenannten Schleifentransformationen[1] da. Typische Optimierungsziele sind Vektorisierbarkeit, Instruk-tionsparallelitat, Cacheeffizienz aber auch das Eliminieren unnotiger Datenstrukturen. In diesem Textwerden zwei Schleifentransformationen auf Schleifennestern und eine auf Schleifenfolgen vorgestellt,wobei das Augenmerk auf der Verbesserung der Lokalitat und damit der Cache-Optimierung liegt. Wennuber Schleifennester gesprochen wird, sind meistens perfekte Schleifennester gemeint, d.h. Schleifennes-ter bei denen Zuweisungen nur in der untersten Schleife vorkommen. Das vereinfacht die Behandlungder Nester enorm und viele Schleifennester lassen sich in perfekte Schleifennester umwandeln, was inder Compiler-Literatur beschrieben ist.

2.2 ZugriffslokalitatDer CPU-Cache ist im Vergleich zum Hauptspeicher naturgemaß sehr klein. Es konnen also im Normal-fall nicht alle Daten, die ein Algorithmus betrachtet, in ihm Platz finden. Performanzgewinn bringt der

121

Page 128: HEINZ NIXDORF INSTITUT Fakultät für Elektrotechnik ... Pottmeyer Memory Limitations in Artificial Intelligence ... Vitter hat gezeigt, dass viele in diesem Modell effiziente Entwicklungen

for(int i=0;i<n;++i)for(int j=0;j<m;++j)a[i][j]=i+j;

Abbildung 1: Schleifennest der Tiefe 2 ohne Abhangigkeiten.

Cache entsprechend nur, wenn ein vom Algorithmus gelesenes Datum sich bereits im Cache befindet.Damit das der Fall ist, muss die referenzierte Cache-Line durch einen fruheren Zugriff in den Cache ge-holt worden sein. Das kann auf zwei unterschiedliche Arten geschehen: Im ersten Fall wird auf dieselbeSpeicherstelle zugegriffen, bevor die Cache-Line wieder verdrangt wurde. So etwas wird als zeitlicheLokalitat bezeichnet, da sich die Zugriffe nur dadurch unterscheiden, wann sie durchgefuhrt wurden. Derzweite Fall ist, dass eine andere Speicherstelle in der selben Cache-Line gelesen wurde und diese seitdem nicht verdrangt wurde. In diesem Fall spricht man von raumlicher Lokalitat, da sich die Position derbeiden referenzierten Speicherstellen unterscheidet. Mochte man bestimmen welche Zugriffe eines Algo-rithmus zu Cache-Hits durch Lokalitat fuhren konnen, muss man Zugriffe finden, die einem der beidenFalle entsprechen. Es handelt sich entsprechend immer um Paare von Zugriffen, die irgendwann im Laufedes Programms auf dieselbe - oder eine benachbarte - Speicherstelle zugreifen.

2.3 IterationsraumeMochte man ein Schleifennest systematisch untersuchen, ist die implizite Beschreibung durch den Quell-code nicht immer die beste, da es haufig nicht offensichtlich ist wie die einzelnen Iterationen von einanderabhangen. Eine explizite Beschreibung ist durch den Iterationsraum und die Distanzvektoren in diesemRaum gegeben. Dadurch wird das Uberprufen ob Abhangigkeiten verletzt werden erleichtert und auto-matisierbar. Fur ein Schleifennest der Tiefe n ist der Iterationsraum ein konvexer Polyeder in Zn. JederPunkt im Polyeder reprasentiert einen Aufruf des innersten Schleifenrumpfs und sein Positionsvektorenthalt die Werte der Schleifenzahler zu diesem Zeitpunkt.

Beispielhaft betrachte man das Schleifennest der Tiefe 2 in Abbildung 1. Der Iterationsraum ist indiesem Fall ein konvexes Polygon in Z2, genauer ein Rechteck. Als erste Dimension des Raums verwen-den wir den Wertebereich des Schleifenzahlers i, also [0, n − 1] und als zweiten den des Zahlers j, also[0,m− 1]. Nach 3 ·m + 5 Iterationen sind die Schleifenzahler i = 3 und j = 5. Der Positionsvektor imIterationsraum (Iterationsvektor) ist entsprechend (3, 5). Der Iterationsraum fur diese Schleife mit n = 3und m = 2 ist in Abbildung 2 dargestellt.

Bei den Schleifentransformationen wird davon ausgegangen, dass der gesamte Iterationsraum besucht

Abbildung 2: Iterationsraum des Schleifennests in Abb. 1

122

Page 129: HEINZ NIXDORF INSTITUT Fakultät für Elektrotechnik ... Pottmeyer Memory Limitations in Artificial Intelligence ... Vitter hat gezeigt, dass viele in diesem Modell effiziente Entwicklungen

werden muss, damit der Algorithmus das gewunschte Ergebnis liefert. Entsprechend wird nur die Rei-henfolge, in der Punkte besucht werden, geandert nicht aber die Punkte selbst. Ebenso andern sich dieWerte der Schleifenzahler fur die Punkte nicht.

2.4 Abhangigkeiten und DistanzvektorenEs ist offensichtlich, dass nicht jede Abarbeitungsreihenfolge des Iterationsraums fur jede Schleife gultigist. Dies ist nur der Fall, wenn keinerlei Abhangigkeiten zwischen den einzelnen Iterationen des Schlei-fennests bestehen. Im allgemeinen Fall sind aber nicht alle Iterationen unabhangig voneinander, wie dasBeispiel in Abbildung 3 zeigt. Hier werden in jeder Iteration Elemente des Arrays gelesen, das auch

for(int i=1;i<4;++i)for(int j=1;j<3;++j)a[i][j]=a[i-1][j]+a[i][j-1];

Abbildung 3: Schleifennest der Tiefe 2 mit Abhangigkeiten.

als Speicher fur das Ergebnis der Berechnung dient. Um zu bestimmen ob Abhangigkeiten vorliegenund zwischen welchen Elementen des Iterationsraums das der Fall ist, mussen Punkte im Iterationsraumgefunden werden, die auf dieselbe Speicherstelle zugreifen. In Programmiersprachen mit Zeigerarithme-tik ist es teils praktisch unmoglich alle Abhangigkeiten zu finden, wenn Zeiger in der Schleife genutztwerden. Daher werden hier nur Zugriffe auf disjunkte Arrays behandelt. Weiterhin sind die Ausdruckezum Berechnen der Indizes eines Zugriffs Linearkombinationen der Schleifenzahler, was die Verwen-dung von Vektoren zum Beschreiben der Abhangigkeiten ermoglicht. Auf einen Punkt im Iterationsraumangewandt, zeigen diese Vektoren auf die Iterationen, die von diesem abhangen.

do i1=l1, u1

. . .do id,ld,ud

A[f1(i1, . . . , id)], . . . , fm(i1, . . . , id)] = . . .. . . = A[g1(i1, . . . , id)], . . . , gm(i1, . . . , id)]

end do. . .

end do

Abbildung 4: Allgemeines Schleifennest[1].

Abbildung 4 zeigt ein verallgemeinertes Schleifennest. Es finden sich in der innersten Schleife sowohlLese- als auch Schreibzugriffe. Die Funktion fi transformiert einen Iterationsvektor in die i-te Arrayindi-zierung der Schreiboperation. Die Funktion gi macht selbiges fur die Leseoperation. Da eine Iteration Jnur von einer anderen Iteration I abhangig sein kann, die vor ihr ausgefuhrt wurde, wird ”vorher” formaldurch die Relation ≺ definiert.

I ≺ J ⇐⇒ ∃p : (ip < jp ∧ ∀q < p : iq = jq)

Es wird davon ausgegangen, dass alle Schleifeninkremente positiv sind. Damit bedeutet es nichtsanders, als das die Differenz I − J lexikographisch positiv ist, d.h. as erste Element des resultierenVektors, das nicht 0 ist, muss positiv sein, was leicht einzusehen ist. Damit eine Iteration J von derIteration I abhangt, muss mindestens eine der beiden eine Schreiboperation sein und folgendes gelten:

I ≺ J ∧ ∀p : fp(I) = gp(J)

123

Page 130: HEINZ NIXDORF INSTITUT Fakultät für Elektrotechnik ... Pottmeyer Memory Limitations in Artificial Intelligence ... Vitter hat gezeigt, dass viele in diesem Modell effiziente Entwicklungen

Abbildung 5: Arrayzugriffe vor und nach Schleifenpermutation. Aus [4].

I muss also vor J ausgefuhrt werden und beide mussen dasselbe Arrayelement referenzieren. Wenn eskeine derartigen Iterationen gibt, sind die Zugriffe unabhangig. Die Differenz J − I ist der Distanzvektorfur dieses Paar von Zugriffen.

3 SchleifentransformationenDie Reihenfolge in der die Punkte im Iterationsraum abgearbeitet werden ist entscheidend fur die Perfor-manz des Algorithmus. Haufig lassen sich durch geschickt gewahlte Reihenfolgen die Hauptspeicherzu-griffe sogar asymptotisch verbessern.

3.1 SchleifenpermutationEin haufiges Problem bei Schleifennestern ist, dass die unterste Schleife nicht der untersten Dimensiondes bearbeiteten Arrays entspricht. Das bedeutet, dass nebeneinander liegende Speicherzellen nie nach-einander bearbeitet werden. Die raumliche Lokalitat ist also denkbar schlecht. Sinnvoll ware es, wenndas Schleifennest so aufgebaut ist, dass moglichst viele Zugriffe mit geringer Schrittweite erfolgen. InAbbildung 5 ist auf der linken Seite eine ungeschickte Abarbeitungsreihenfolge dargestellt. Das ersteDatum wird gelesen und mit ihm eine komplette Cache-Line, grau dargestellt. Im nachsten Schritt wirddie Speicherstelle 8 Elemente weiter, also direkt ”unter” der ersten, zusammen mit einer neuen Cache-Line gelesen. Das wird so fortgefuhrt, bis das untere Ende des Arrays erreicht wird. Sollten alle bishereingelesenen Cache-Lines im Cache Platz haben, wird dann das zweite Element der zuerst geladenenCache-Line bearbeitet, usw. Sobald das Array aber groß genug ist, passen alle diese Cache-Lines nichtmehr gleichzeitig in den Cache. Irgendwo wahrend der Abarbeitung der ersten Spalte wird entsprechenddie erste Cache-Line verdrangt. Damit tritt nie eine Wiederverwendung des geladenen Cache-Lines auf.Jeder Datenzugriff erfordert das Laden einer kompletten Cache-Line.

Dreht man die Reihenfolge der Schleifen um, so dass die innere Schleife die Indizierung in der unters-ten Dimension des Arrays ubernimmt, so werden - wie rechts abgebildet - alle Daten nur einmal geladen.Jeder Cache-Line wird komplett abgearbeitet und die minimale Anzahl von Cache-Lines wird ubertragen.Das ist nun nicht mehr abhangig von der Große des Caches.

Schleifenpermutation ist das Vertauschen von Schleifen in einem Schleifennest. Die Distanzvektorendes resultierenden Schleifennests haben ihre Elemente an den Positionen vertauscht, an denen auch dieSchleifen vertauscht wurden. Sind die resultierenden Distanzvektoren legal, d.h. lexikographisch positiv,kann die Transformation durchgefuhrt werden, ohne das Abhangigkeiten verletzt werden.

124

Page 131: HEINZ NIXDORF INSTITUT Fakultät für Elektrotechnik ... Pottmeyer Memory Limitations in Artificial Intelligence ... Vitter hat gezeigt, dass viele in diesem Modell effiziente Entwicklungen

Abbildung 6: Iterationsraum mit linearer Abarbeitungsreihenfolge (links) und Z-Kurve (rechts).[4]

3.2 Schleifen KachelnMan betrachte eine Funktion, die eine beliebig große Matrix transponiert. Fur eine n× n-Matrix konntedie innere Schleife beispielsweise wie in folgt aussehen.

for(int i=0;i<n;++i)for(int j=0;j<n;++j)a[i][j]=b[j][i];

Es fallt direkt auf, dass unabhangig von der Reihenfolge der Schleifen einer der Zugriffe mit Schrittweiten erfolgt, wahrend der andere die gewunschte Schrittweite 1 hat. In diesem Fall ist ein permutieren derSchleifen also keine Losung. Stattdessen wird der Iterationsraum in Unterraume, so genannte Blocke oderKacheln, unterteilt, deren Große nicht von der Große der Eingabematrix abhangig ist. Diese Kacheln wer-den moglichst so gewahlt, dass alle Daten die zum Abarbeiten eines Blocks benotigt werden gleichzeitigin den Cache passen.

Aus dem zweistufigen Schleifennest wird ein neues vierstufiges erzeugt, dessen außere zwei Schleifenuber die Kacheln iterieren wahrend die inneren zwei Schleifen das Innere der Kacheln abdecken. Dieresultieren Abarbeitungsreihenfolge ist eine Z-Kurve, wie in Abbildung 6 zu sehen. Als transformiertesSchleifennest ergibt sich

for(int ii=0;ii<n;ii+=B)for(int jj=0;jj<n;jj+=B)for(int i=ii;i<min(ii+B,n);++i)for(int j=jj;j<min(jj+B,n);++j)a[i][j]=b[j][i];

Als Blockgroße B wurde hier die Anzahl von Datenelementen gewahlt, die in eine Cache-Line passen.Da B nicht notwendigerweise ein Teiler von n sein muss, konnen die letzen Blocke einer Zeile oderSpalte teilweise außerhalb der Matrix liegen. Daher sind die inneren beiden Schleifen extra durch dieDimensionen der Matrix begrenzt.

Betrachtet man die Cachegroße, die notwendig ist um ein verdrangen von Cache-Lines, die noch nichtvollstandig abgearbeitet sind, zu verhindern, wird der Vorteil der Kachelung offensichtlich. Im ursprung-lichen Fall wurde immer genau eine Cache-Line fur die Matrix in Array a benotigt, wohingegen dieMatrix in Array b bis zu n Cache-Lines benotigt, wie bei der Schleifenpermutation besprochen. Nach derKachelung muss nur noch eine konstante Anzahl von Cache-Lines gehalten werden: a benotigt weiterhin

125

Page 132: HEINZ NIXDORF INSTITUT Fakultät für Elektrotechnik ... Pottmeyer Memory Limitations in Artificial Intelligence ... Vitter hat gezeigt, dass viele in diesem Modell effiziente Entwicklungen

nur ein Cache-Line, hier hat sich nichts geandert1, da zwar Blockweise gearbeitet wird, diese Blocke aberaus Cache- Lines bestehen die immer komplett abgearbeitet werden. Fur Arrays b ist die konstante Anzahlebenfalls einfach zu sehen. Hier werden immer B Cache-Lines benotigt, da fur jede Zeile (Cache-Line)von a eine Spalte von B Elementen aus einer ebenso großen Kachel von b gelesen werden muss. DieSpalten dieser zweiten Kachel sind wieder hintereinander angeordnet, so dass die n-te Zeile der a-Kacheldie n-ten Elemente aller Zeilen der b-Kachel liest. Wenn die a-Kachel also abgearbeitet ist, muss auchdie b-Kachel nie wieder betrachtet werden. Die Anzahl der Speicherzugriffe hat sich also um den Faktor1/B auf verbessert, wenn der Cache keine vollstandige Spalte von Cache-Lines halten kann.

Da wie beim Permutieren von Schleifen die Abarbeitungsreihenfolge des Iterationsraums verandertwird, ist wegen moglicher Abhangigkeiten nicht jede Kachelung legal. Prinzipiell durfen Schleifen immerdann gekachelt werden, wenn sie auch permutiert werden durfen.

3.3 SchleifenvereinigungAls Beispiel fur eine Schleifentransformation die nicht auf einzelnen Schleifennestern arbeitet wird ab-schließend die Schleifenvereinigung betrachtet. Bei diesem Verfahren wird ein mehrfaches Abarbeitendes Iterationsraums vermieden in dem mehrere Schleifen mit gleichem Iterationsraum zusammengefasstwerden. Man betrachte folgendes Beispiel:

for(int i=0;i<n;++i)b[i]=a[i]+1.0;

for(int i=0;i<n;++i)c[i]=b[i]*4.0;

Beide Schleifen haben denselben Iterationsraum und keine Distanzvektoren, also keine Abhangigkei-ten in den Schleifen. Dennoch gibt es Abhangigkeiten zwischen den beiden Schleifen. Die zweite Schleifeliest die in der ersten Schleife geschriebenen Werte. Diese Abhangigkeit muss erkannt und eingehaltenwerden, damit die Transformation fehlerfrei durchgefuhrt werden kann. Das Betrachten der Distanzvek-toren hilft hier nicht, da diese nur Abhangigkeiten in den einzelnen Schleifen beschreiben. Bei diesemBeispiel werden die Abhangigkeiten nicht verletzt, solange fur jede Iteration zuerst der Schleifenrumpfder ersten Schleife ausgefuhrt wird. Es ergibt sich also

for(int i=0;i<n;++i)b[i]=a[i]+1.0;c[i]=b[i]*4.0;

Sollte b nur innerhalb dieser Schleife benutzt werden, so bietet sich eine weitere Technik an, die arraycontraction genannt wird. Dabei wird das Array b durch ein Skalar bs ersetzt, da immer nur ein Wertvon b benotigt wird. Dieser kann dann in einem Register gehalten werden, wodurch fur b keine Speicher-Zugriffe mehr anfallen.

4 DatenlayoutBei den Schleifentransformationen bestand der Optimierungsansatz darin, dass man geschickter auf dieDaten zugreift. Dieser Abschnitt behandelt, wie die Daten abgelegt werden konnen um die Lokalitat und

1Hier wird davon ausgegangen, dass mit dem ersten Element der Arrays jeweils eine neue Cache-Line beginnt. Das muss nichtso sein, aber anderenfalls wird nur ein konstanter Faktor von weiteren Cache-Lines benotigt.

126

Page 133: HEINZ NIXDORF INSTITUT Fakultät für Elektrotechnik ... Pottmeyer Memory Limitations in Artificial Intelligence ... Vitter hat gezeigt, dass viele in diesem Modell effiziente Entwicklungen

damit die Cache-Effizienz zu steigern. Zuerst werden Schleifentransformationen als Arraytransformati-on umgesetzt. Danach werden Conflict-Misses betrachtet, die sich durch Schleifentransformationen nurschwer in den Griff kriegen lassen.

4.1 Schleifentransformation als ArraytransformationSowohl Schleifenpermutation als auch Schleifenkachelung lassen sich sowohl durch Umsortierung derSchleifen als auch durch Umsortierung der verwendeten Arrays realisieren2. Im Fall der Kachelung kanndas zu verbessertem Prefetching (Vergleiche Abschnitt 5) und weniger Conflict-Misses fuhren, da dieArrays wieder linear durchlaufen werden konnen. Prinzipiell lassen sich viele Schleifentransformatio-nen derart auf Datenraume ubertragen. Im Fall der Schleifenpermutation wird das als array transposebezeichnet, da im Fall eines zweidimensionalen Arrays die Operation dem Transponieren eines Arraysentspricht. Das ist aber nur ein Spezialfall des allgemeinen Kopierens von Daten zum verbessern der Lo-kalitat (data copying). Diese Operationen konnen entweder statisch oder dynamisch durchgefuhrt werden.Im statischen Fall liegen die Daten nur noch im umsortierten Fall vor, was sich anbietet wenn alle Zu-griffe von der neuen Sortierung profitieren. Dynamisches Kopieren ist immer mit zusatzlichem Aufwandverbunden, was den Performanzgewinn wieder relativieren kann.

4.2 Vermeidung von Conflict-MissesBisher wurde davon ausgegangen, dass die volle Kapazitat des Caches zur Verfugung steht. Bei vollas-soziativen Caches ist diese Annahme auch immer richtig, bei den normalerweise eingesetzten mengen-assoziativen Caches aber nicht. Hier kann jede Cache-Line nur in einer geringen Anzahl von Speicher-stellen im Cache abgelegt werden. Die Gesamtmenge der Speicherstellen die eine Cache-Line aufneh-men konnen wird Cache-Menge (cache set) genannt. Die einzelnen Speicherstellen in der Menge hei-ßen wiederum Wege (ways). CPU-Caches sind haufig 4- bis 12-Weg mengenassoziativ und der denkbarschlimmste Fall ist, wenn nur wenige Mengen des Caches tatsachlich benutzt werden. Die so verursachtenCache-Misses, ausgelost nicht durch einen vollen Cache sondern nur durch volle Cache-Mengen, nenntman Conflict-Misses. Um sie zu verhindern muss dafur gesorgt werden, dass die Daten in moglichst vieleCache-Mengen fallen.

Gegeben sein folgende Schleife:

double a[1024];double b[1024];

for(int i=0;i<1024;++i)sum+=a[i]+b[i];

Wenn die Hardware ein direkt abbildender Cache (1-Weg mengenassoziativ) ist, dessen HashfunktionSpeicheradressen mit 8192 Byte (1024 mal 8 Byte pro double) Unterschied auf denselben Wert abbildet,so treten hier Conflict-Misses auf. Bei dieser Konfiguration fallen die Cache-Lines von a[i] und b[i] indie gleiche Menge und verdrangen sich gegenseitig. Die gesamte Schleife verursacht entsprechend 2047Cache-Misses. Trotz prinzipiell extrem hoher raumlicher Lokalitat wird kein einziger Cache-Hit erreicht.

Man sieht an diesem Beispiel direkt, dass Schleifentransformationen hier nur bedingt helfen. Mankann die Schleife zwar in zwei Schleifen aufteilen, von denen eine dann uber a und die andere uber bgeht3, allgemein ist diese Losung aber nicht.

2Naturlich benotigt eine Arraytransformation haufig auch Anderungen an den Schleifen.3Also eine inverse Schleifenvereinigung, Loop Distribution genannt.

127

Page 134: HEINZ NIXDORF INSTITUT Fakultät für Elektrotechnik ... Pottmeyer Memory Limitations in Artificial Intelligence ... Vitter hat gezeigt, dass viele in diesem Modell effiziente Entwicklungen

4.2.1 Inter-Array Padding

Da das Auftreten der Cache-Misses abhangig von den Startadressen der Arrays ist, konnen diese ver-schoben werden. Man fugt dazu zwischen den beiden Arrays eine Anzahl von Fullbytes (so genanntenpadding bytes) eine, deren einzige Aufgabe es ist, die Startadresse des zweiten Arrays zu verschieben.Die genaue Anzahl der Fullbytes hangt naturlich von der Hashfunktion des Caches ab. Prinzipiell siehtdie Arraydeklaration nun folgendermaßen aus:

double a[1024];char pad[x]; //x bytes paddingdouble b[1024];

Der Nachteil dieser Methode ist, dass sie von der Hashfunktion abhangig ist. Wenn man aber nur Einflussauf eins der beiden Arrays hat, so ist sie die einzige Losung.

4.2.2 Array Merging

Eine Methode die fur kleine Arrayelemente unabhangig von der Hashfunktion ist, ist das array mer-ging, also das Zusammenfugen von Arrays. Die grundlegende Beobachtung ist, dass im Speicher nahbeieinander liegende Daten nicht in dieselbe Cache-Menge fallen werden4. Die Arrays werden jetzt imReißverschlussverfahren zu einem einzigen Array zusammengesetzt, so dass Elemente auf die zeitgleichzugegriffen wird, raumlich nebeneinander liegen. Erreicht werden kann das entweder durch ein Array mitum 1 erhohter Dimension, oder durch ein Array von Datensatzen, falls die Programmiersprache so etwasunterstutzt und nicht nur Zeiger auf Heap-Objekte als Arraytypen zulasst.

double ab[1024][2]; //Arraydimension erweitert.

structdouble a;double b;

ab[1024]; //Array von Datensatzen.

Der Vorteil der Datensatze ist, dass auch Arrays unterschiedlicher Typen auf diese Weise zusammengefugtwerden konnen. In beiden Fallen treten keine Conflict-Misses mehr auf und wenn n Werte vom Typdouble in eine Cache-Line passen, treten nur noch maximal 1/n so viele Cache-Misses auf.

4.3 BandbreitenreduktionBei jedem Datentransfer zwischen Hauptspeicher und Cache werden ganze Cache-Lines ubertragen. Ent-sprechend ist es wichtig dafur zu sorgen, dass in diesen Cache-Lines moglicht viel benotigte Daten liegen.In vielen Fallen iteriert das Programm uber ein Array von Datensatzen, von denen nur Teile fur die Be-rechnung gebraucht werden. Trennt man diese benotigten Daten von den unnotigen Daten lasst sich dieAnzahl der zu ubertragenden Cache-Lines teils erheblich reduzieren. Ein typisches Beispiel hierfur sind3D-Anwendungen, bei denen Eckpunkte von Polygonen aus einer Position und einer Reihe von Attributenbestehen. Diese Attribute werden meistens erst in der Grafikkarte benotigt, wohingegen die Positionsda-ten auch auf der CPU haufig gebraucht werden, beispielsweise um die Polygone zu sortieren. In diesemFall ist es sinnvoll die Daten nicht in einem einzelnen Array zu speichern, sondern separate Arrays furPositionsdaten und Attribute zu haben.

Ein anderer Ansatz wird bei Algorithmen mit wahlfreiem Zugriff auf die Datenelemente interessant.Hier ist der ideale Fall, dass ein Datensatz in der minimalen Anzahl Cache-Lines liegt, da diese bei

4Technisch ist es zwar moglich einen solchen Cache zu bauen, es macht aber wenig Sinn.

128

Page 135: HEINZ NIXDORF INSTITUT Fakultät für Elektrotechnik ... Pottmeyer Memory Limitations in Artificial Intelligence ... Vitter hat gezeigt, dass viele in diesem Modell effiziente Entwicklungen

struct bad struct goodchar a; char a;//3 byte compiler padding; char c;int b; char e;char c; //1 byte compiler padding;//3 byte compiler padding; int b;int d; int d;char e; int f;//3 byte compiler padding; ; //16 bytesint f;

; //24 bytes

Abbildung 7: Links, eine durch Compiler Padding vergroßerte Struktur. Rechts, Verkleinerung durchUmsortierung.

einem Zugriff alle geladen werden mussen. In diesem Fall vergroßert man das Objekt kunstlich, bis seineGroße einem Vielfachen der Cache-Line-Große entspricht. Danach muss man noch dafur sorgen, dassalle Objekte auch genau so im Speicher positioniert werden, dass sie fur den Cache optimal ausgerichtetsind. Bei Objekten deren Große kleiner oder gleich derer einer Cache-Line ist, wird die Anzahl der zuladenden Cache-Lines so haufig halbiert.

4.3.1 Datenausrichtung

Viele Prozessoren erfordern, dass mehrbyteige Datentypen im Speicher entsprechend ihrer Große ausge-richtet sind. Dazu muss die Adresse, an der sich ein Datum der Große n befindet durch die nachst großere(oder gleichgroße) Zweierpotenz teilbar sein. Einige Prozessoren unterstutzen nicht ausgerichtete Datennicht, bei anderen sind diese Zugriffe nur langsamer. Compiler passen entsprechend die Positionen vonEintragen in Datenstrukturen so an, dass sie fur die Architektur optimal liegen. Das lasst sich norma-lerweise uber Compileranweisungen abstellen, fuhrt aber zu langsamerer Ausfuhrungsgeschwindigkeit.Besser ist es, wenn die Eintrage so umsortiert werden, dass beim Ausrichten moglichst wenig Speicherverschwendet wird. Dazu sortiert man die Elemente nach ihrer Große. Der Compiler kann diese Umsor-tierung im Allgemeinen nicht durchfuhren, da Daten von Programmteilen benutzt werden konnen, dievon anderen Compilern ubersetzt wurden.

129

Page 136: HEINZ NIXDORF INSTITUT Fakultät für Elektrotechnik ... Pottmeyer Memory Limitations in Artificial Intelligence ... Vitter hat gezeigt, dass viele in diesem Modell effiziente Entwicklungen

Abbildung 8: Programmablauf ohne Prefetching. CPU und Speichersystem warten abwechselnd[3].

5 PrefetchingDie bisher vorgestellten Methoden versuchen die Anzahl der Cache-Misses zu minimieren. Beim Prefet-ching hingegen nutzt man Parallelitat von CPU und Speichersystem um die Latenzen des Speichersystemszu verdecken. In Abbildung 8 ist ein typischer Programmverlauf mit gekoppelter CPU und Speicher zusehen. Es ist immer nur eine der beiden Einheiten aktiv, wahrend die andere auf die nachste Anweisungwartet. Die Idee des Prefetching ist es nun, die Caches asynchron mit Daten zu fullen. Das bedeutet, dassdie CPU nicht-blockierende Leseanfragen an das Speichersystem stellt, das diese dann versucht zu ver-arbeitet. Entscheidend hierbei ist, dass CPU nicht auf die Fertigstellung der Anfragen warten muss undsomit weiterrechnen kann, wahrend die langsamen Speicherzugriffe erfolgen5.

Damit Prefetching eingesetzt werden kann, muss das Programm in der Lage sein zu bestimmen, wel-che Daten es in naher Zukunft benotigt. Bei den hier betrachteten numerischen Algorithmen ist das sehrhaufig gegeben, da a priori bekannt ist, wie sie den Iterationsraum abarbeiten und ihre Zugriffe durchLinearkombination ihrer Schleifenzahler bestimmt sind.

5.1 Hardware PrefetchingDas am weitesten verbreitete Zugriffsmuster bei haufigen Arrayzugriffen sind Zugriffe mit fester Schritt-weite (constant stride). Viele CPUs erkennen derartige Zugriffsmuster und beginnen von sich aus Datenim Voraus zu laden. Dieses Verhalten hat den Vorteil, dass in diesem Standartfall der Zugriff auf denCache ohne Zutun des Programmierers oder des Compilers verbessert wird. Andererseits werden zu vieleDaten vorgeladen, wenn die CPU nicht bestimmen kann, wann die Schleife terminiert.

5.2 Software PrefetchingProgrammierer haben im Regelfall eine sehr genaue Vorstellung davon, wann welche Daten von ihremProgramm benotigt werden. Genau dieses Wissen macht man sich beim Software Prefetching zu Nut-zen, indem man im Programm codiert, wann welche Daten geladen werden sollen. Diese Aufgabe kannauch vom Compiler ubernommen werden[6], dessen Wissen uber den Algorithmus aber naturgemaß ge-ringer ist. Solange im Voraus bekannt ist, welche Speicherstellen geladen werden mussen, hat man nun

5Eine weitere wichtige Eigenschaft ist, dass diese Anfragen keine Schutzverletzungen verursachen konnen. So muss das Prefet-ching nicht vollstandig konservativ sein.

130

Page 137: HEINZ NIXDORF INSTITUT Fakultät für Elektrotechnik ... Pottmeyer Memory Limitations in Artificial Intelligence ... Vitter hat gezeigt, dass viele in diesem Modell effiziente Entwicklungen

die Moglichkeit die Latenzen des Speichersystems zu verstecken. Zu beachten hierbei ist, dass Prefetch-instruktionen regulare Speicherzugriffe sind und als solche nicht nur uber den Bus ubertragen werdenmussen, sonder von der CPU bearbeitet werden. Jede dieser Instruktionen erfordert eine Adressberech-nung, einen instruction slot in der CPU, Platz im Instruktionscache, usw. Es ist also nicht zu empfehlen soviel wie moglich vorzuladen, da so die CPU wieder ausgebremst wird. Ein weiterer wichtiger Aspekt ist,dass durch die Großenbegrenzung des Caches ein zu aggressives Vorladen die aktuell benotigten (oderandere bereits Vorgeladene) Daten verdrangen und so weitere Cache-Misses verursachen kann. Anderer-seits ist es optimal, wenn ein Datum bereits vollstandig im Cache zu finden ist, wenn es gebraucht wird.Es gilt also zwei Werte zu berechnen: Die Anzahl der Datensatze die fur einen optimalen Betrieb vor-geladen werden sollen und die maximale Anzahl der Datensatze, die in den Cache passen. Letzteres isteinfach, sobald die Großen von Cache und Datensatzen bekannt sind. Die optimale Vorladedistanz wirdim Folgenden berechnet.

5.3 Prefech Scheduling DistanceIn erster Nahrung ist es sehr einfach zu bestimmen, wie viele Iterationen im Voraus Daten geladen werdensollten6. Es handelt sich dabei um die fur das Prefetching benotigte Zeit dividiert durch die Rechenzeiteiner Iteration. Sei Npref die Anzahl der Cache-Lines die in einer Iteration geladen werden mussen, alsodie Anzahl der benotigten Cache-Lines einer Iteration abzuglich der bereits im Cache vorhandenen. Jenach Architektur mussen unter Umstanden eine Menge von Cache-Lines aus dem Cache in eine tiefereHierarchie kopiert werden, entweder weil sie geandert wurden, oder weil ein Victim-Cache eingesetztwird. Die Anzahl dieser zu speichernden Cache-Lines sei Nst.

Wenn das Ubertragen einer Cache-Line Ctransfer Prozessorzyklen in Anspruch nimmt, ist der Ge-samtaufwand fur das Ubertragen der Daten Ctransfer · (Npref + Nst). Dazu kommen noch die Kostenfur das Finden der Speicherstelle (z.B. TLB-Misses) und moglicherweise hardwarespezifische Kosten,zusammengefasst in Clookup, was die Gesamtkosten fur den Datentransfer einer Iteration ergibt. AufSeiten der Ausfuhrungseinheit sind die Prozessorzyklen pro Iteration durch die Instruktionen (inklusivePrefetchinstruktionen) Ninst und die hardwareabhangigen CPI , den Zyklen pro Instruktion, gegeben. Esergibt sich daraus folgende Formel[3].

psd = dClookup + Ctransfer · (Npref + Nst)CPI ·Ninst

e

Auch mit perfektem Prefetching werden nicht CPU und Speichersystem mit Volllast arbeiten. Das istaber auch nicht das Ziel, sondern dass eine der beiden Komponenten nicht warten muss. Das Programmist also entweder CPU- oder Speicherlimitiert, aber es verschwendet keine Zeit mehr durch unnotigeKopplung der Subsysteme.

6Die hier vorgestellte Formel geht davon aus, dass das Programm exklusiven Zugriff auf CPU und Speichersystem hat. In einemSystem mit mehreren Hardware-Threads kann ein anderer Thread das Speichersystem blockieren und die Abschatzung verfalschen.

131

Page 138: HEINZ NIXDORF INSTITUT Fakultät für Elektrotechnik ... Pottmeyer Memory Limitations in Artificial Intelligence ... Vitter hat gezeigt, dass viele in diesem Modell effiziente Entwicklungen

6 AnwendungsbeispielZwei sehr weit verbreitete Bibliotheken fur lineare Algebra sind BLAS und LAPACK. Elementare Matrizen-und Vektoroperationen werden dabei von BLAS bereitgestellt, wahrend LAPACK z.B. Algorithmen furdas Losen linearer Gleichungssysteme oder das Berechnen von Eigenwerten enthalt. Die LAPACK Algo-rithmen basieren dabei auf BLAS und versuchen moglichst viel ihrer Berechnung durch BLAS-Aufrufedurchzufuhren. Daraus resultiert, dass Optimierungen der BLAS direkt die Performanz des LAPACK be-einflussen. Im Weiteren werden einige der vorgestellten Techniken eingesetzt, um eine so genannte Level2 BLAS Operation, eine Vektor-Matrizen-Operation, zu optimieren. Der Algorithmus ist im Verlauf desATLAS-Projekts[7] entstanden. Ziel dieses Projekts ist es automatisch optimierte plattformspezifischeBLAS-Implementierungen zu erzeugen. Diese werden im Allgemeinen nicht mit handoptimierten Imple-mentierungen mithalten konnen, aber fur recht viele Plattformen sind solche BLAS-Implementierungennicht verfugbar.

6.1 Vektor-Matrix-MultiplikationAls Anwendungsbeispiel wird eine Vektor-Matrix-Multiplikation von der Form y ← Ax + y betrachtet,wobei A eine n× n-Matrix ist und x, y Vektoren der Große n. Explizit hat die Berechnung Form

yi ←n∑

j=1

Ai,jxj + yi, 1 ≤ i ≤ n

In C implementiert sieht der Algorithmus dann folgendermaßen aus:

for(int i=0;i<n;++i)for(int j=0;j<n;++j)y[i]+=A[i][j]*x[j]

Der Algorithmus muss zum Berechnen eines yi den gesamten n-Vektor x, sowie die n-elementigeZeile Ai lesen und yi n mal lesen und schreiben. Da y insgesamt n Elemente hat, ergeben sich darausn2 Leseoperationen auf A und x und n2 Lese- und Schreiboperationen auf y. Prinzipiell lasst sich dieAnzahl der Zugriffe nicht andern, wohl aber die Anzahl der Zugriffe auf den Hauptspeicher, speziell durchKachelungsverfahren. Einer der beiden Vektorzugriffe (aber nicht beide) kann von n2 zu n reduziertwerden, indem das aktuelle Element in einem Register gespeichert wird. Da y sowohl geschrieben alsauch gelesen wird, wird es hier fur die Verbesserung ausgewahlt. Spezielle Verhaltensweise von Cache-Architekturen fuhren in der Praxis manchmal dazu, dass x eine bessere Wahl ist. Die Schleife ist jetztleicht verandert:

register float r;for(int i=0;i<n;++i)r=y[i];for(int j=0;j<n;++j)r+=A[i][j]*x[j]

y[i]=r;

Wenn k Register zur Verfugung stehen, konnen entsprechend k innere Schleifen gleichzeitig ausgewertetwerden und damit die Anzahl der Zugriffe auf x um 1/k reduziert werden. Diese Verbesserung wird auchstrip mining genannt und wird ebenfalls eingesetzt um fur Vektorprozessoren zu optimieren. Wahrend

132

Page 139: HEINZ NIXDORF INSTITUT Fakultät für Elektrotechnik ... Pottmeyer Memory Limitations in Artificial Intelligence ... Vitter hat gezeigt, dass viele in diesem Modell effiziente Entwicklungen

bei k = 1 nur eine register spilling, also ein Kopieren eines Zwischenwerts aus einem Register in denSpeicher, vermieden wird, ist die Methode fur k > 1 ein register blocking, eine Register Kachelung(vergleiche Abschnitt 3.2). Der Vektor wird in Kachel der Große k × 1 aufgeteilt und bearbeitet.

Um die Anzahl der Zugriffe auf x von O(n2) auf O(n) zu reduzieren, wird eine Schleifenkachelungdurchgefuhrt wie in Abschnitt 3.2 beschrieben. Um die Blockgroße zu erhalten muss der Speicherbedarfpro Iteration untersucht werden. Da jedes Mal k Elemente von y aktualisiert werden, mussen k × nElemente von A sowie der vollstandige Vektor x gehalten werden. Zusammen mit den zu aktualisierendenElementen ergibt sich ein Speicherverbrauch von etwa k + n + kn.

Gesucht ist also die großte Partitionierung p ≤ n von x, so dass fur eine L1-Cachegroße S giltS ≥ k + p + kp. Die hier angegebene Formel fur den Speicherverbrauch ist offensichtlich reichlichoptimistisch. In der Praxis wird mehr Speicher pro Iteration benotigt werden und durch Cache-Konfliktewird die Ausnutzung nicht perfekt sein. Des Weiteren wird der Algorithmus nicht notwendigerweiseexklusiven Zugriff auf den Cache haben. Diese Dinge mussen aber von System zu System untersuchtwerden und sind nicht Teil dieser Betrachtung. Die Kachelung von x unterteilt das n× n große Problemin dn/pe Unterprobleme der Große n × p. Das bedeutet, dass jeweils ein n × p großer Teilbereich vona mit einem p großen Abschnitt von x verrechnet wird. Dadurch muss y nun wieder haufiger geladenwerden, namlich dn/pen mal. Die Zugriffe auf n sind damit streng genommen wieder quadratisch, aberin der Praxis ist p normalerweise zwischen 300 und 1500, womit nur wenig Kacheln benotigt werden. Istp = 1 ist keine Kachelung von x notwendig und der Algorithmus reduziert sich auf den nicht gekacheltenFall. Die Finale Version benotigt damit dn/pen Lese- und Schreibzugriffe auf y, n Lesezugriffe auf x undn2 Lesezugriffe auf A.

int n_p=ceil(n/p);for(int ii=0;ii<n;ii+=p)for(int i=0;i<n;++i)r=y[i];for(int j=ii;j<min(n,ii+p);++j)r+=A[i][j]*x[j]

y[i]=r;

Bei einem (relativ) unwissenschaftlichen Test7 konnte das verbesserte Cacheverhalten zwar bestatigtwerden, Geschwindigkeitsvorteile waren aber nur schwer zu erreichen. Die Laufzeiten der Algorithmenwar etwa vergleichbar, wenn die Anzahl der Cache-Misses des naiven Algorithmus fast dem doppelten de-rer des hier vorgestellten Algorithmus entsprachen. Beide Algorithmen wurden vom Compiler optimiert,wobei fur den naiven Algorithmus ein Ausrollen von 8 Iterationen der untersten Schleife automatischdurchgefuhrt wurde.

Auf einem Athlon64 mit 64KB L1-Datencache und 512KB L2-Cache war das etwa bei n = 80000gegeben, wobei die Matrix dann naturlich nicht langer quadratisch war. Der gekachelte Algorithmusverursachte zu diesem Zeitpunkt doppelt so viele branch mispredictions, die jeweils mindestens 10 War-tezyklen verursacht haben. Das alleine kann aber kein Grund fur das gemessene Verhalten sein. Wennman nur die L1-Cache-Misses betrachtet, die der gekachelte Algorithmus einspart, dann verliert man nuretwa 10% der Zeit durch die falsche branch prediction.

7Cache-Misses und andere CPU-Ereignisse wurden mit Hilfe der CPU performance counter direkt gemessen. Da diese aberInterrupts auslosen um den Profiler uber die Ursache des Ereignisses zu informieren, beeinflussen sie das Ergebnis. Speziell hatdas Speichersystem Zeit Daten zu laden, wahrend der Interrupt bearbeitet wird. Es wurde aber darauf geachtet, dass nicht zu haufigInterrupts ausgelost werden.

133

Page 140: HEINZ NIXDORF INSTITUT Fakultät für Elektrotechnik ... Pottmeyer Memory Limitations in Artificial Intelligence ... Vitter hat gezeigt, dass viele in diesem Modell effiziente Entwicklungen

Tatsachlich scheint das Problem mit dem Berechnen der Adressen zu tun zu haben. Die innerenSchleifen der beiden Algorithmen unterscheiden sich nur darin, dass der native Algorithmus sequenziellmit einem Iterator uber den Speicher lauft, wahrend der gekachelte Algorithmus parallel mehrere (k) Ite-ratoren besitzt. Dadurch ist der naive Algorithmus in der Lage der 8 Zugriffe im inneren der Schleife sehreinfach zu adressieren. Er speichert die Startadresse des zu bearbeitenden Blocks in einem Register undaddiert dann fur jedes Element einen festen Wert bei der Adressberechnung dazu. Da der Athlon64 einesuperskalare Architektur besitzt und sich das Startregister wahrend der Iteration nicht verschiebt, konnendie Adressen parallel berechnet werden, ohne das Abhangigkeiten auftreten. Die Adresseinheiten lesenein Register aus (das nicht geschrieben wird und daher Latenzfrei gelesen werden kann) und addiereneine Verschiebung. Ein Ausschnitt aus der inneren Schleife des naiven Algorithmus:

fld dword ptr [ecx-0Ch]fmul dword ptr [eax-0Ch]faddp st(1),stfld dword ptr [ecx-10h]fmul dword ptr [eax-10h]faddp st(1),stfld dword ptr [ecx-14h]fmul dword ptr [eax-14h]faddp st(1),stfld dword ptr [ecx-18h]fmul dword ptr [eax-18h]faddp st(1),st

Adressierungen sind von der Form ”dword ptr [register+offset]”. Das Register ecx zeigt auf die Spaltevon A und eax zeigt auf den Anfang des 8er-Blocks von x.

Die Adressierungen des gekachelten Algorithmus sind komplizierter. Beim Zugriff auf x wird jedesMal durch eine Multiplikation (j mal der Große eines floats) und eine Addition (Startadresse des Vektors)die entsprechende Position berechnet.

fld dword ptr [eax+4A4E40h]fmul dword ptr [ecx*4+4160FCh]faddp st(4),stfld dword ptr [eax+4EC2E0h]fmul dword ptr [ecx*4+4160FCh]faddp st(3),stfld dword ptr [eax+533780h]fmul dword ptr [ecx*4+4160FCh]faddp st(2),st

Die CPU muss nun also doppelt so lange auf die Adresse fur xi warten. Da jedes Mal auf diesel-be Speicherstelle zugegriffen wird, wird eigentlich nur eine Adressierung benotigt. Reserviert man einRegister fur xi, andert sich das Ergebnis signifikant. Um das Register freizuhaben, wird k von 8 auf 4reduziert, was keinen Einfluss auf die Geschwindigkeit des Algorithmus hat8. Zu Anfang der innerenSchleife wird xi in ein Register geladen und dann fur die vier Zuweisungen verwendet. Der so optimierteAlgorithmus schlagt den naiven bereits bei n = 16 durch seine bessere Instruktionsparallelitat, bedingtdurch die Verwendung von mehr Registern.

8Ein Test mit k = 2 erzielte hingegen schlechtere Leistung. Entweder ist der maximale Speicherdurchsatz oder die maximaleInstruktionsparallelitat (die CPU hat 3 Fließkommaeinheiten) bereits erreicht. Naher untersucht wurde das aber nicht.

134

Page 141: HEINZ NIXDORF INSTITUT Fakultät für Elektrotechnik ... Pottmeyer Memory Limitations in Artificial Intelligence ... Vitter hat gezeigt, dass viele in diesem Modell effiziente Entwicklungen

N M S Durchlaufe naiv gekachelt verbessert10000 10000 10000 10 2100ms 2200 ms 1700ms128 40000 10000 100 1070ms 1120ms 900ms128 800000 50000 10 2600ms 2200ms 1800ms128 800000 10000 10 2600ms 2250ms 1800ms128 800000 5000 10 2600ms 2250ms 1850ms16 16 10000 10000000 3500ms 3250ms 3050ms

Abbildung 9: Laufzeiten der Algorithmen fur y[N ] = A[N ][M ] × x[M ] + y[N ], bei angenommenerL1-Cachegroße von S floats.

Interessant zu beobachten ist, dass der Geschwindigkeitszuwachs recht konstant ist. Selbst beimSprung von einer 16 × 16-Matrix zu einer 128 × 800000-Matrix, bei der sowohl x als auch jede Ma-trizenzeile uber 3MB groß ist andern sich die Verbesserungen nur von 23, 5% zu 44, 5%.

7 SchlussfolgerungSchleifentransformationen sind ein attraktiver Optimierungsansatz, da sie die Qualitat des Ergebnissesnicht beeinflussen9 und teilweise automatisiert werden konnen. In Programmiersprachen mit Zeigerarith-metik wird das Erkennen aller Abhangigkeiten aber zum Problem, weshalb es haufig dem Programmiereruberlassen wird die Transformationsmoglichkeiten zu entdecken und umzusetzen. Ahnlich ist es mit demSoftware-Prefetching, das zwar in der Form von Compiler-Anweisungen (intrinsics) seinen Weg in diePraxis gefunden hat, aber wiederum im Allgemeinen nicht automatisiert umgesetzt wird. Zu aggressi-ves Prefetching fuhrt zur Verschwendung von Speicherbandbreite, mehr Cache-Misses und aufgeblahtemCode. Ein zu konservatives Verfahren tauscht unter Umstanden Optimiertheit vor, wo nur wenig Ver-besserung erzielt wurde. Es lauft darauf hinaus, dass der Compiler versuchen muss zu erkennen, wasder Programmierer erzielen wollte und das ist immer problematisch. Da bietet es sich an, das Wissendes Programmierers direkt zu nutzen. Ein weiteres Problem hier ist die Fehlersuche. Ein Source-Level-Debugger ist nur solange von Nutzen, wie der angezeigte Quellcode auch dem ausgefuhrten Programmentspricht. Nach einigen aggressiven Schleifentransformationen wird dem Programmierer wenig anderesubrig bleiben, als mit der Ausgabe des Compiler - also dem Maschinencode - direkt zu arbeiten.

Datenoptimierungen spiegeln Teils die Codetransformationen wieder. Viele Schleifentransformatio-nen konnen auch als Arraytransformationen durchgefuhrt werden und haufig macht das auch Sinn. DasKacheln von Schleifen fuhrt beispielsweise oft zu erhohtem Auftreten von Conflict-Misses, weswegendie Kacheln dann so umkopiert werden, dass die Speicherzugriffe wieder eine feste Schrittweite haben.Ebenso kann man haufig Software-Prefetching durch Hardware- Prefetching ersetzen, indem man dieReihenfolge der Datenelemente andert.

Das Entfernen von unnotigen Daten wird die Komplexitatsklasse der Hauptspeicherzugriffe nur sehrselten beeinflussen, aber die konstanten Faktoren sind bei der Optimierung nicht zu vernachlassigen. DasPacken, Zerschneiden und Umsortieren der Daten macht einen Algorithmus naturlich nicht unbedingtlesbarer und hier muss abgewogen werden, wie viel Aufwand berechtig ist. Das ist beim Optimieren aberimmer so.

9Das stimmt nur eingeschrankt. Wenn die Genauigkeit der Register großer ist als die der Speicherstellen, kann beispielswei-se das Kacheln des Iterationsraums zu reduzierter Genauigkeit fuhren. Eine Architektur mit diesen Eigenschaften ist Intels x87Fließkommaarchitektur[2].

135

Page 142: HEINZ NIXDORF INSTITUT Fakultät für Elektrotechnik ... Pottmeyer Memory Limitations in Artificial Intelligence ... Vitter hat gezeigt, dass viele in diesem Modell effiziente Entwicklungen

Literatur[1] David F. Bacon, Susan L. Graham and Oliver J. Sharp Compiler Transformations for High-

Performance Computing ACM Computing Surveys, 26(4):345–420, 1994.

[2] Intel Corp IA-32 Intel R©Architecture Software Developer’s Manual, Volume 1: Basic Architecture,Section 8.1.2, June 2006.

[3] Intel Corp. IA-32 Intel R©Architecture Optimization Reference Manual, Appendix E, June 2006

[4] Markus Kowarschik, Christian Weiß An Overview of Cache Optimization Techniques and Cache-Aware Numerical Algorithms Algorithms for Memory Hierarchies, LNCS 2625, pp. 213-232, 2003.

[5] Monica S. Lam, Edward E. Rothberg and Michael E. Wolf The cache performance and optimizationsof blocked algorithms ACM SIGPLAN Notices, 26(4):63-74, 1991

[6] Todd C. Mowry Tolerating Latency through Software-Controlled Data Prefetching Dissertation,Stanford University, 1994.

[7] R. Clint Whaley, Antoine Petitet and Jack J. Dongarra Automated Empirical Optimizations of Soft-ware and the ATLAS project Parallel Computing 27(1-2):3-35, 2001.

[8] Micheal E. Wolf Improving Locality and Parallelism In Nested Loops Dissertation, Stanford Uni-versity, 1992.

136

Page 143: HEINZ NIXDORF INSTITUT Fakultät für Elektrotechnik ... Pottmeyer Memory Limitations in Artificial Intelligence ... Vitter hat gezeigt, dass viele in diesem Modell effiziente Entwicklungen

Memory Limitations in Artificial Intelligence

Felix Pottmeyer

1. Grundlagen

Diese Ausarbeitung beschäftigt sich mit Speicherbeschränkungen im Bereich der künstlichen

Intelligenz. Sie basiert auf dem Paper Memory Limitations in Artificial Intelligence [3] von

Stefan Edelkamp. Aufgabenstellungen, mit denen sich die künstliche Intelligenz beschäftigt,

lassen sich oft als Suchprobleme beschreiben. Wichtige Probleme der künstlichen Intelligenz

sind zum Beispiel Single Agent Suchprobleme wie das n²-1 Schiebepuzzle oder der Rubiks

Cube und Multi Agent Suchprobleme wie Schach. Die in dieser Ausarbeitung vorgestellten

heuristischen Suchverfahren wurden in erster Linie für Single Agent Suchprobleme

entwickelt, werden (teilweise leicht abgeändert) aber auch für andere Suchprobleme benutzt.

Möchte man Suchverfahren zur Lösung eines Problems anwenden, muss man das zu lösende

Problem zuerst in eine Form bringen, die von einem Suchalgorithmus verarbeitet werden

kann. Dazu wählt man eine Zustandsraumrepräsentation des Problems. Zustände beschreiben

dabei den Informationsstand zu einem beliebigen Zeitpunkt und

Zustandsübergangsoperatoren legen fest, wie man von einem Zustand in einen anderen

gelangen kann. Des weiteren müssen bestimmte Zustände als Start- beziehungsweise

Zielzustände gekennzeichnet werden. Gesucht wird nun eine Folge von

Operatoranwendungen, die, angewandt auf einen Startzustand, diesen in eine Lösung, also

einen Zielzustand überführt. Die Zustandsraumrepräsentation lässt sich als Graph darstellen.

Dabei stellen die Knoten des Graphen Zustände dar und die Kanten des Graphen

repräsentieren die Operatoren. Im Prinzip lässt sich ein so repräsentiertes Problem nun

algorithmisch einfach lösen, indem man zum Beispiel Breitensuche benutzt. Dies ist aufgrund

der Komplexität der behandelten Probleme jedoch nicht möglich, wie folgende Tabelle, die zu

ausgewählten Problemen die Größe des Zustandsraums und die Brute-Force-Suchzeit angibt,

verdeutlicht:

Problem Zustände Brute-Force-Suchzeit

(10 Millionen Zustände/s)

8 Puzzle 510 0,01 Sekunden

32 Rubiks Cube 610 0,2 Sekunden

15 Puzzle 1310 6 Tage

33 Rubiks Cube 1910 68.000 Jahre

24 Puzzle 2510 12 Milliarden Jahre

Dabei wird davon ausgegangen, dass doppelte Zustände erkannt werden, das heißt jeder

Zustand des Zustandsraums nur einmal betrachtet wird. Ist dies nicht der Fall, weil zum

Beispiel nicht mehr alle schon besuchten Zustände in den Speicher passen, kann der

Suchgraph auch für kleinere Probleme schon sehr viel größer werden.

137

Page 144: HEINZ NIXDORF INSTITUT Fakultät für Elektrotechnik ... Pottmeyer Memory Limitations in Artificial Intelligence ... Vitter hat gezeigt, dass viele in diesem Modell effiziente Entwicklungen

Die oben stehende Grafik zeigt ein Beispiel für das 8-Puzzle. Links ist ein Startzustand

abgebildet, rechts der Zielzustand. Gesucht ist dann eine Folge von Zügen, die den Start- in

den Zielzustand überführt. Das 8-Puzzle hat einen Zustandsraum von 9!/2 = 180.440

Zuständen. Wenn wir als Operatoranwendung das verschieben des leeren Feldes um eine

Position ansehen, dann kann ein Zustand (je nach Position des leeren Feldes) entweder 2, 3,

oder 4 Nachfolgezustände haben. Schätzen wir den Verzweigungsgrad (engl. branching

factor) grob mit 3 ab, und gehen wir davon aus, dass man 20 Operatoranwendungen braucht,

um in einen Zielzustand zu gelangen. Dann ist der vollständige Suchraum (ohne

Duplikatserkennung) 203 Zustände (fast 3,5 Milliarden) groß.

Heuristiken

Eine Heuristik h ist eine Funktion, die zu jedem Knoten n seinen Abstand von Zielknoten g

schätzt (ein niedrigerer Wert ist dementsprechend besser). Da ein Zielzustand keinen Abstand

mehr zum Ziel hat gilt immer: h(g) = 0. Seien nun h*(n) die tatsächlichen minimalen Kosten

von n zu g. Eine Heuristik h heißt dann optimistisch, wenn für jedes n gilt h(n) <= h*(n). Eine

optimistische Heuristik darf den tatsächlichen Abstand zum Zielknoten also niemals

überschätzen. Hat man zwei Heuristiken h1 und h2, heißt h1 informierter als h2, wenn für

jeden Knoten n gilt h1(n) >= h2(n). Im Allgemeinen ist es vorteilhaft, eine möglichst

informierte Heuristik zu verwenden, da diese die Suche stärker einschränkt, also schlechtere

Zustände schlechter bewertet. Dabei muss man jedoch beachten, dass informiertere

Heuristiken oftmals auch schwerer zu berechnen sind.

Konsistente Kostenfunktion

Eine Kostenfunktion f(n) ist konsistent, wenn für alle Knoten n und s(n), wobei s(n)

Nachfolger von n ist, f(n) <= f(s(n)) gilt. Die Kosten eines Knotens dürfen also nie geringer

als die Kosten seines Vorgängers sein.

Lemma: Für jede optimistische Kostenfunktion f lässt sich eine konsistente optimistische

Kostenfunktion f’ konstruieren, die mindestens so informiert wie f ist.

Beweis: f’ wird folgendermaßen rekursiv aus f konstruiert: ist n ein Startzustand, setze f’(n) =

f(n). Ansonsten setze f’(s(n)) = max[f(s(n)), f’(n)]. f’ ist monoton, da immer f’(n) <= f’(s(n))

gilt. Beachte, dass f’(n) gleich dem höchsten Wert von f eines Vorgängers von n auf dem Pfad

von n zum Startzustand ist. Da die Kostenfunktion f optimistisch ist, ist der höchste f-Wert

auf einem Pfad eine untere Schranke für die Kosten dieses Pfads (und damit eine untere

Schranke für die Kosten von n). Deshalb gilt, dass f’ ebenfalls optimistisch ist. Außerdem ist

f’ mindestens so informiert wie f, da für alle n, f’(n) >= f(n) gilt.

Für Analyse der im folgenden vorgestellten Algorithmen werden wir immer voraussetzen,

dass die benutzten Heuristiken optimistisch und konsistent sind.

External Memory Model

7 8 4

3 5 1

6 2

1 2 3

4 5 6

7 8

138

Page 145: HEINZ NIXDORF INSTITUT Fakultät für Elektrotechnik ... Pottmeyer Memory Limitations in Artificial Intelligence ... Vitter hat gezeigt, dass viele in diesem Modell effiziente Entwicklungen

Für die Entwicklung und Analyse von externen Algorithmen werden wir das External

Memory Model benutzen. In diesem Modell gibt es einen Prozessor und einen kleinen

internen Speicher, der bis zu M Daten speichern kann. Zusätzlich gibt es einen in der Größe

unbeschränkten externen Speicher. Die Eingabegröße des Problems ist durch N gegeben. Die

Blockgröße B gibt an, wie viele Daten auf einmal zwischen dem internen und dem externen

Speicher übertragen werden können. Als Blöcke definieren wir m = M/B und n = N/B. Für die

Analyse von Algorithmen betrachten wir in diesem Modell nur die Anzahl von gelesenen oder

geschriebenen Blöcken, die internen Berechnungen des Algorithmus verursachen keine

Kosten. Zwei externe Operationen werden wir später benötigen, Scan und Sort. Scan bedeutet

Daten zu lesen, die zusammenhängend auf der Festplatte gespeichert sind. Scan(N) benötigt

( / ) ( )N B nθ θ= Input/Output-Operationen. Sort ist eine Operation, die externes Sortieren

durchführt. Sort(N) kann mit /(log )M B

NO

B I/O-Operationen realisiert werden.

2. A*

A* ist heuristischer Best-First-Suchalgorithmus. Er betrachtet immer den Knoten als nächstes,

der gemäß der Kostenfunktion den geringsten Wert hat. Die Kostenfunktion für einen Knoten

n sieht dabei folgendermaßen aus: f(n) = g(n) + h(n). Dabei sind g(n) die Kosten die benötigt

wurden, um zu Knoten n zu gelangen und h(n) ist der mit einer Heuristik geschätzte Abstand

von n zum nächsten Zielzustand. Die Kostenfunktion f(n) beschreibt somit die geschätzten

Kosten eines Pfades vom Startzustand über Knoten n zum Zielzustand.

A* arbeitet auf impliziten Graphen, der Suchgraph wird also während der Laufzeit aufgebaut.

Dafür werden zwei Listen verwaltet: eine Open- und eine Closed-List. Die Open-List enthält

die erzeugten, aber noch nicht expandierten (d.h. ihre Nachfolger wurden noch nicht

generiert) Knoten. Diese Knoten werden auch als Horizontknoten bezeichnet. Die Closed-List

enthält die bereits expandierten Knoten. Zu Beginn wird die Open-List mit dem Startzustand

initialisiert. Im Verlauf des Algorithmus wird dann immer der Knoten n mit den geringsten

Kosten f(n) aus der Open-List genommen und expandiert. Dabei werden seine neu generierten

Nachfolger in die Open-Liste eingefügt. Wird ein Knoten expandiert, der ein Zielzustand ist,

terminiert der Algorithmus.

Die Arbeitsweise des A* Algorithmus verdeutlicht das folgende Beispiel:

139

Page 146: HEINZ NIXDORF INSTITUT Fakultät für Elektrotechnik ... Pottmeyer Memory Limitations in Artificial Intelligence ... Vitter hat gezeigt, dass viele in diesem Modell effiziente Entwicklungen

Schritt I stellt den Startzustand s dar. Dieser hat heuristische Kosten h(s) = 2. In diesem

Beispiel sind die Kosten von Operatoranwendungen (die Kantengewichte) immer 1. Schritt II

zeigt den Suchgraph, nachdem s expandiert wurde und seine Nachfolger A und B in die

Open-List eingefügt wurden. Da f(A) = g(A) + h(A) = 1 + 1 kleiner als f(B) = 1 + 2 ist, wird

als nächstes Knoten A expandiert. Das Ergebnis dieser Expansion ist in Schritt III zu sehen.

A* expandiert immer den Horizontknoten mit dem geringsten f-Wert. Schritte IV und V

zeigen das Ergebnis der Expansion von Knoten B bzw. F. Knoten G stellt einen Zielknoten

dar, der sich in Schritt V noch in der Open-List befindet. Es bedarf also noch eines nächsten

Schrittes, der Knoten G expandiert, bevor der Algorithmus terminiert. Auf die Darstellung

dieses Schrittes wurde hier verzichtet.

Lemma: A* ist vollständig, das heißt A* findet eine Lösung, sofern eine existiert.

Beweisskizze: Wir nehmen an, dass jede Operatoranwendung positive Kosten von mindestens

e verursacht und dass ein Zielzustand g existiert. Das Expandieren von Knoten führt also zu

Pfaden, deren Kosten um mindestens e (die Kosten der Operatoranwendung) steigen. Seien

nun f* die Kosten des günstigsten Pfades zu g. Da A* ein Best-First-Algorithmus ist und eine

optimistische Heuristik verwendet wird, werden keine Knoten expandiert, deren Kosten

größer als f* sind. Da jede Operatoranwendung bzw. Knotenexpansion mindestens Kosten

von e verursacht, kann kein Pfad länger als f*/e werden kann, bevor Zielzustand g gefunden

wird.

Lemma: A* ist optimal, das heißt der erste gefundene Zielknoten ist der günstigste

Zielknoten.

Beweis: Sei g2 ein nicht optimaler Zielzustand in der Open-Liste und sei n ein Knoten auf

einem kürzesten Pfad zum optimalen Zielzustand g. Da g2 ein Zielzustand ist gilt h(g2) = 0

und dementsprechend f(g2) = g(g2). Da g2 nicht optimal ist gilt ebenfalls g(g2) > g(g). Da die

s 2 s 2

A 1 B 2

s 2

A 1 B 2

C 2 D 3 E 2

s 2

A 1 B 2

C 2 D 3 E 2 F 1

s 2

A 1 B 2

2 D 3 E 2 F 1

G 0

I II III

IV V

140

Page 147: HEINZ NIXDORF INSTITUT Fakultät für Elektrotechnik ... Pottmeyer Memory Limitations in Artificial Intelligence ... Vitter hat gezeigt, dass viele in diesem Modell effiziente Entwicklungen

Heuristik h optimistisch ist gilt f(n) <= g(g) und somit auch f(n) < g(g2). Da g(g2) > f(n) wird

A* niemals g2 expandieren, sondern immer vorher n und dessen Nachfolger auf dem Pfad

zum günstigsten Zielknoten g.

Es gibt keinen vollständigen und optimalen Suchalgorithmus, der zu einer gegebenen

Heuristik h weniger Knoten expandiert als A*. Alle Knoten, die A* expandiert, haben

nämlich Kosten die höchsten so groß sind wie die Kosten f* der optimalen Lösung. Würde ein

Knoten, der geringere Kosten als f* hat, nicht expandiert werden, so wüsste man nicht, ob

dieser Knoten eventuell eine günstigere Lösung darstellt.

Die tatsächliche Laufzeit von A* hängt von der verwendeten Heuristik ab. Wird die

uninformierteste Heuristik benutzt, bei der für jedes n h(n) = 0 gilt, wird A* zur Gleiche-

Kosten-Suche. Sind zusätzlich die Operatorkosten immer 1, wird A* zur Breitensuche.

Benutzt man hingegen eine perfekte Heuristik, wird sofort der optimale Weg zum Zielzustand

gefunden.

Das größte Problem von A* ist auch nicht die Laufzeit, sondern der Speicherbedarf, der bei

O( db ) liegt. Dabei steht b für den Verzweigungsgrad (branching factor) des Suchraums und d

für die Tiefe der Lösung, also die benötigt Anzahl Operatoranwendungen, um vom Start- in

den Zielzustand zu gelangen. Es gibt jedoch mit IDA* eine speicherbeschränkte Version von

A*, deren Speicherbedarf nur O(d) beträgt und die ich im folgenden vorstellen werde.

3. IDA*

Iterative Deepening A* [5] führt eine iterierte Tiefensuche aus. Dabei werden in jeder

Iteration nur Knoten n expandiert, deren Kosten f(n) = g(n) + h(n) kleiner oder gleich einer

Schranke t sind. Wurde in einer Iteration kein Zielzustand erreicht, wird t erhöht und eine

neue Iteration gestartet. Zu Beginn des Algorithmus wird t mit dem f-Wert des Startknotens

initialisiert. Für die Iteration i wird die Schranke t auf den geringsten f-Wert aller in Iteration

i-1 gefundenen, aber nicht expandierten Knoten gesetzt. Zwischen zwei Iterationen muss so

nur der Wert t gespeichert werden.

Das folgende Beispiel erläutert den Ablauf einer IDA* Iteration:

Schritt I zeigt den Startzustand s. Von dort aus wird nun eine Tiefensuche mit Schranke t =

f(s) = h(s) = 4 gestartet. Wir gehen in dem Beispiel wieder von Operatorkosten bzw.

s 4 s

A 6

I II s

A 6

III s

A 6

IV 4 4 4

C

B

6

3

s

A 6

V 4

B 3

C 6

s

A 6

VI 4

B 3

C 6

s

A 6

VII 4

B 3

141

Page 148: HEINZ NIXDORF INSTITUT Fakultät für Elektrotechnik ... Pottmeyer Memory Limitations in Artificial Intelligence ... Vitter hat gezeigt, dass viele in diesem Modell effiziente Entwicklungen

Kantengewichten von 1 aus. A, der erste Nachfolger von s, hat Kosten von 1 + 6 = 7. Da dies

größer als t ist wird A nicht expandiert und der Algorithmus geht wieder zu s. B, der zweite

Nachfolger von s, hat Kosten von 1 + 3 = 4. Da dies nicht größer als die Schranke t = 4 ist,

wird B expandiert. Die Kosten des Nachfolgers von B sind wieder größer als t. Nachdem

jeder Knoten u mit f(u) <= t vollständig expandiert wurde, ist die Iteration beendet. Die

nächste Iteration wird dann mit dem niedrigsten f-Wert eines gefundenen, aber nicht

expandierten Knotens gestartet (in diesem Beispiel ist t=7).

Lemma: IDA* ist vollständig und optimal.

Beweisskizze: IDA* wird mit t = f(s) gestartet. Da eine optimistische Heuristik verwendet

wird, gilt immer f* >= h(s). Die nächste Schranke t` ist dann der minimale f-Wert eines

Horizontknotens aus der letzten Iteration mit f > t. Daraus folgt, dass es keine Knoten geben

kann, deren Kosten zwischen der Schranke t aus Iteration i und t’ aus Iteration i+1 liegen

können. Da IDA* immer alle Knoten bis zu einem Kostenlimit expandiert, bevor (in der

nächsten Iteration) auch Knoten mit größeren Kosten expandiert werden, ist die erste

gefundene Lösung optimal.

Da IDA* eine iterierte Tiefensuche ausführt, hat der Algorithmus auch einen Speicherbedarf

wie Tiefensuche von O(d). Allerdings werden dafür in jeder neuen Iteration alle vorher schon

expandierten Knoten wieder neu expandiert. Hat man jedoch Suchräume, die exponentiell mit

der Tiefe wachsen, so dominiert der Aufwand der letzten Iteration den gesamten vorherigen

Aufwand. Außerdem benutzt IDA* nur Stapeloperationen und hat deshalb pro Knoten einen

deutlich geringeren Overhead als A*, welches teurere Listenoperationen benötigt. So ist IDA*

in der Praxis manchmal sogar schneller als A*. IDA* war auch das erste Verfahren, das

zufällig generierte Instanzen des 15er Puzzles lösen konnte.

Betrachten wir nun die theoretischen Ergebnisse zur Laufzeit von IDA*. Sei n die Anzahl

Knoten, die A* für die Lösung eines Problems expandiert. Dann expandiert IDA* bis zu O(c

n²) viele Knoten auf der Menge der c beschränkten Graphen. Der ungünstigste Fall liegt

genau dann vor, wenn in jeder IDA* Iteration nur ein neuer Knoten expandiert wird. Dann

benötigt IDA* insgesamt n Iterationen und expandiert dabei in jeder Iteration alle bisher

schon expandierten Knoten wieder neu:

Abschließend lässt sich sagen, dass IDA* insbesondere gut für Probleme funktioniert, bei

denen es nur wenig verschiedene f-Werte gibt, da dann in jeder Iteration mehr neue Knoten

expandiert werden und es somit insgesamt weniger Iterationen gibt. Dies ist zum Beispiel für

n²-1 Puzzles der Fall.

A* expandiert wenige Knoten, hat aber einen Speicherbedarf, der exponentiell mit d wächst.

IDA* hat nur einen linearen Speicherbedarf, expandiert aber dafür O(n²) viele Knoten. Im

folgenden werde ich speicherbeschränkte Verfahren vorstellen, die versuchen, die Vorteile

von A* und IDA* miteinander zu kombinieren.

4. Speicherbeschränkte Verfahren

Die in diesem Kapitel vorgestellten Verfahren SMA* und MEIDA* basieren auf A* und

IDA*. Bei beiden Verfahren ist es so, dass ihnen eine Speichergröße zugewiesen wird. Diesen

2

1

( 1)( )

2

n

i

n nci c O cn

=

+= ∈∑

142

Page 149: HEINZ NIXDORF INSTITUT Fakultät für Elektrotechnik ... Pottmeyer Memory Limitations in Artificial Intelligence ... Vitter hat gezeigt, dass viele in diesem Modell effiziente Entwicklungen

Speicher darf das Verfahren dann mit dem Suchraum füllen. Ist der Suchraum größer als der

zugewiesene Speicherplatz, kann er nicht komplett im Speicher gehalten werden. Ist der

Speicher einmal voll, muss vor dem expandieren eines neuen Knotens ein anderer Knoten aus

dem Speicher entfernt werden.

4.1 SMA*

Simplified Memory Bounded A* [6] ist ein auf A* basierender speicherbeschränkter

Suchalgorithmus. SMA* wird eine Variable M übergeben, die angibt, wie viele Knoten

gespeichert werden können. Ist M größer als die Anzahl von A* für ein Problem

expandierten Knoten, verhält sich SMA* genau wie A*.

Eine Besonderheit von SMA* ist, dass bei der Knotenexpansion immer nur ein Nachfolger

generiert wird. Deshalb enthält die Open-List von SMA* auch teilweise expandierte Knoten.

Dies ist notwendig, wenn der Speicher voll ist, also bereits M Knoten gespeichert werden.

Dann muss nämlich nur ein Knoten gelöscht werden, bevor ein anderer (teilweise) expandiert

werden kann. Würden die Knoten immer vollständig expandiert, wüsste man nicht im

Vorfeld, wie viele Knoten vor einer Expansion gelöscht werden müssen. Die Kosten eines

Knotens u sind wie bei A* durch die Funktion f(u) = g(u) + h(u) gegeben und es wird immer

der Knoten mit den geringsten Kosten expandiert. Gibt es mehrere Knoten mit geringsten

Kosten, wird der tiefste expandiert. Ist der Speicher voll, wird der Knoten mit den höchsten

Kosten gelöscht. Bei mehreren Knoten mit höchsten Kosten wird der mit der geringsten Tiefe

gelöscht.

Um den Informationsverlust durch das Löschen von Knoten möglichst gering zu halten,

werden in SMA* Kosten von Knoten an ihre Vorgängerknoten propagiert. Dies geschieht

folgendermaßen: Sobald ein Knoten u vollständig expandiert wurde, bekommt dieser als

Gewicht den geringsten f-Wert aller seiner Nachfolger. Werden nun ein oder mehrere

Nachfolger des Knotens gelöscht, wird in diesem zusätzlich der geringste f-Wert aller

gelöschten Nachfolger gespeichert. Dadurch hat man eine untere Schranke für die Kosten, die

anfallen, wenn man wieder unter Knoten u weitersuchen möchte (also Knoten u erneut

expandieren).

Folgendes Beispiel zeigt den Ablauf des SMA* Algorithmus. Im Gegensatz zu den

vorherigen Beispielen stellen die Knotengewichte hier nicht die heuristischen Kosten, sondern

die Gesamtkosten (f-Werte) dar. Im Beispiel können M = 3 Knoten gespeichert werden.

A 20 I A 20 II

B 25

A 20 III

B 25

D

30 C

45

A 25 IV

B 25 30 C

A 25(30) V

B 25

A 25(30) VI

B 25

A 25(30) VII

B 25(45)

A 25(30) VIII

B 25(45)

50 E

143

Page 150: HEINZ NIXDORF INSTITUT Fakultät für Elektrotechnik ... Pottmeyer Memory Limitations in Artificial Intelligence ... Vitter hat gezeigt, dass viele in diesem Modell effiziente Entwicklungen

In Schritt II wurde der erste Nachfolger des Startknotens A erzeugt. Da A immer noch der

Knoten mit dem geringsten f-Wert ist, wird der nächste Nachfolger von A erzeugt. A wurde

nun vollständig expandiert und bekommt als neue Kosten 25, den geringsten f-Wert aller

seiner Nachfolger (Schritt IV). Da der Speicher voll ist wird als nächstes der Knoten mit den

höchsten Kosten wieder gelöscht und seine Kosten werden an den Vaterknoten propagiert. In

Schritt VI wurde B expandiert, da dieser die geringsten Kosten hatte. Nun ist der Speicher

voll und D, der Knoten mit den höchsten Kosten, wird gelöscht, wobei sein f-Wert wieder an

den Vaterknoten übergeben wird. Dann wird der nächste Nachfolger von B erzeugt. B ist jetzt

vollständig expandiert und bekommt als Gewicht die Kosten seines günstigsten Kindes

(Schritt IX). Die niedrigsten Kosten eines Kindes von A sind nun nicht mehr 25 sondern 30

und dementsprechend werden die Kosten von A angepasst. Der teuerste Knoten E wird

gelöscht und anschließend wird zum zweiten mal der Knoten C erzeugt. Diesmal ist C

allerdings der günstigste Knoten und wird expandiert, nachdem Knoten B gelöscht wurde. F,

der einzige Nachfolger von C, stellt einen Zielknoten dar und der Algorithmus terminiert.

SMA* generiert neue (noch nie zuvor generierte) Knoten in A* Reihenfolge und liefert

deshalb immer ein optimales Ergebnis, sofern der Speicher groß genug ist, um den

Lösungspfad zu speichern.

Dadurch, dass SMA* den vorhandenen Speicherplatz ausnutzt, können Duplikate entdeckt

werden, sofern das Duplikat noch im Speicher liegt. Allerdings hat SMA* einen so großen

Overhead pro Knoten, dass es für praktische Anwendungen ungeeignet ist. Außerdem kann es

passieren, dass man mehrere tiefe Pfade hat, bei denen abwechselnd ein neuer Knoten

generiert wird, dann der Pfad wieder gelöscht wird und der andere Pfad wieder aufgebaut

wird und an diesem ein neuer Knoten generiert wird und so weiter. SMA* geht also davon

aus, dass mit hoher Wahrscheinlichkeit der nächste expandierte Knoten in der unmittelbaren

Nachbarschaft des zuletzt expandierten liegt. Ist dieses jedoch nicht der Fall hat SMA* die

selbe Komplexität wie IDA*.

4.2 MEIDA*

A 25(30) IX

B 45

50 E

A 30 X

B 45

50 E

A 30 XI

B 45

A 30 XII

B 45 30 C

A 30(45) XIII

30 C

A 30(45) XIV

30 C

35 F

144

Page 151: HEINZ NIXDORF INSTITUT Fakultät für Elektrotechnik ... Pottmeyer Memory Limitations in Artificial Intelligence ... Vitter hat gezeigt, dass viele in diesem Modell effiziente Entwicklungen

Memory Extended IDA* [2] ist ein auf IDA* basierendes speicherbeschränktes

Suchverfahren, welches wieder M Knoten speichern kann. Es besteht aus zwei sich

abwechselnden Phasen. In der ersten Phase werden mit einer IDA* Iteration alle Knoten,

deren Kosten geringer als ein Schwellenwert t sind, expandiert. Dabei werden die M

Horizontknoten (entdeckte, aber nicht expandierte Knoten) in eine Vorwärtswarteschlange D

(nach f geordnet) eingefügt. In der zweiten Phase des Algorithmus wird solange das

Minimum aus D expandiert, bis D leer ist. Die Söhne von aus D entfernten und expandierten

Knoten werden in D eingefügt, sofern deren Kosten geringer als die maximalen Kosten in D

sind. Ist D voll, muss vor dem Einfügen eines neuen Knotens in D eventuell das Maximum

aus D gelöscht werden. Ist D leer, wird wieder eine neue IDA* Phase ausgeführt. Dieser wird

als Schranke t der f-Wert des letzten expandierten Knotens übergeben. Durch das Speichern

und Expandieren von Knoten in D kann man also die benötigte Anzahl IDA* Iterationen, und

damit die Anzahl insgesamt expandierter Knoten, verringern.

MEIDA* ist der Algorithmus mit dem besten theoretischen Ergebnis für Suchbäume.

Lemma: Sei n die Anzahl von A* expandierten Knoten und M die Anzahl Knoten, die

MEIDA* speichern kann. Dann expandiert IDA* 2( / )O n M viele Knoten.

Beweis: Sei E(i) die Anzahl in Iteration i expandierter Knoten. Da IDA* in jeder Iteration die

in der letzten Iteration bereits expandierten Knoten wieder expandiert ist R(i) = E(i) – E(i - 1)

die Anzahl der in Iteration i neu expandierten Knoten. Sei L die letzte Iteration. Die Anzahl

der insgesamt expandierten Knoten ist dann gegeben durch 1

* ( 1)L

i

i R L i=

− +∑ . Um eine obere

Schranke für die insgesamt expandierten Knoten zu bekommen, formulieren wir diesen

Ausdruck als Optimierungsaufgabe 1

max * ( 1)L

i

i R L i=

− +∑ mit folgenden Nebenbedingungen:

1. R(1) + R(2) + ... + R(L) = E(L) = n.

2. R(i) >= M, für 1 < i < L

3. R(1) = E(L) – (L-2)M

4. R(L) >= 0

Die optimale Lösung erhält man, wenn R(i) = M, R(1) = E(L) – (L-2)M und R(L) = 0 ist. Das

Einsetzen dieser Werte in die Optimierungsaufgabe führt zum Zielfunktionswert 1

2

( ( ) ( 2) )L

i

iM L E L L M−

=

+ − −∑ . Durch Anwendung der Gaußschen Summenformel und

Ausmultiplizieren der Klammern erhält man 2 / 2 ( 3 / 2)ML n M L M− + + − . Das Maximum

des Zielfunktionswerts wird für L = n/M + 3/2 angenommen und ergibt einen Wert von 2 /(2 ) 3 / 2 / 8n M n M+ + . Dies ist wie behauptet O(n²/M).

6. Externes A*

Suchräume sind oft so groß, dass sie nicht komplett im Hauptspeicher gehalten werden

können. In so einem Fall werden dann die übrigen Daten auf der Festplatte gespeichert. Da

Festplattenzugriffe aber um einen Faktor von 510 bis 610 langsamer sind als Zugriffe auf den

Hauptspeicher, wurde Externes A* [4] entwickelt, eine Variation des Standard A*

Algorithmus, die versucht, die benötigten Festplattenzugriffe zu minimieren. Der Algorithmus

wird für implizite, ungerichtete Graphen mit uniformen Kantengewichten und einer

145

Page 152: HEINZ NIXDORF INSTITUT Fakultät für Elektrotechnik ... Pottmeyer Memory Limitations in Artificial Intelligence ... Vitter hat gezeigt, dass viele in diesem Modell effiziente Entwicklungen

konsistenten Heuristik vorgestellt. In diesem Fall hat externes A* eine I/O Komplexität von

O(sort(|E|) + scan(|V|)).

Da der Algorithmus auf impliziten Graphen arbeitet, werden Nachfolger eines Knotens durch

Anwendung einer Regel generiert. Somit sind keine I/O Operationen notwendig, um

Adjazenzlisten zu lesen. Es verbleibt die Erkennung von Duplikaten als größte Quelle von I/O

Operationen.

Voraussetzungen für den Algorithmus sind ein impliziter ungerichteter Graph mit uniformen

Kantengewichten und eine konsistente Heuristik. Aufgrund der Konsistenz gilt für jeden

Nachfolger v eines Knotens u g(v) – g(u) >= h(u) – h(v). In anderen Worten darf ein Knoten

nie geringere Kosten (einen geringeren f-Wert) als sein Vorgänger haben. Da wir von

uniformen Kosten ausgehen gilt ebenfalls immer h(u) <= h(v) + 1. Da der Graph ungerichtet

ist folgt |h(u) – h(v)| <= 1. Insgesamt erhalten wir, dass der Wert von h(u) – h(v) ein Element

der Menge -1,0,1 ist.

Externes A* benutzt als Datenstruktur ein Array von Buckets, welche auf der Festplatte

gespeichert sind. Das Bucket Open(i, j) enthält genau die Knoten u mit g(u) = i und h(u) = j.

Während der Ausführung des Algorithmus gibt es immer ein grade aktives Bucket Open(i, j).

Für dieses gilt, dass i + j = minf (der geringste noch nicht betrachtete f-Wert) ist. Aus dem

aktiven Bucket werden dann solange Knoten expandiert, bis es leer ist. Anschließend wird das

nächste Bucket Open(i, j) mit i + j = minf aktiviert. Gibt es kein solches Bucket mehr, wird

minf = mini + j > minf | Open(i, j) != ∅ gesetzt. Diese Reihenfolge Knoten zu expandieren

entspricht der des internen A* Algorithmus. Dadurch ergeben sich die Eigenschaften

Vollständigkeit und Optimalität ebenfalls für externes A*.

Doch wie viele Buckets werden nun vom externen A* benötigt?

In oben stehender Grafik aus Paper [4] sind auf der Rechtsachse die g Werte und auf der

Hochachse die h Werte aufgetragen. Jeder Kreis symbolisiert ein Bucket Open(g, h). Alle

Buckets, die auf einer Diagonalen liegen, haben die gleichen Kosten f = g + h. Da jede

Operatoranwendung Kosten von 1 hat und h(u) - h(v) ein Element aus -1,0,1 ist, sind

h(s)

f*

146

Page 153: HEINZ NIXDORF INSTITUT Fakultät für Elektrotechnik ... Pottmeyer Memory Limitations in Artificial Intelligence ... Vitter hat gezeigt, dass viele in diesem Modell effiziente Entwicklungen

Nachfolger von Zuständen aus Bucket Open(g, h) entweder in Open(g+1, h-1), Open(g+1, h)

oder Open(g+1, h+1). Um eine obere Schranke für die maximal benötigte Anzahl Buckets zu

bekommen, kann man die Anzahl Kreise auf den Diagonalen addieren. Da nur Knoten u

expandiert werden, deren Kosten f(u) = g(u) + h(u) nicht größer als die Kosten der optimalen

Lösung f* sind, dürfen Buckets nur in dem durch die f* Diagonale beschränkten Dreieck

vorkommen. Daraus folgt, dass die Gesamtanzahl der Buckets durch f*(f*+1)/2 beschränkt

ist.

Lemma: Die Anzahl Buckets Open(i, j), die A* in einem Gleiche-Kosten-Problemgraphen

mit konsistenter Heuristik benötigt, ist beschränkt durch f*(f*+1)/2.

Duplikate

In ungerichteten Uniforme-Kosten-Zustandsgraphen können Duplikate eines Zustands in

Suchtiefe i höchstens in den Suchtiefen i, i-1 und i-2 auftauchen. Da die Heuristik h eine

totale Funktion ist, gilt außerdem für zwei identische Zustände u und v, dass h(u) = h(v) sein

muss. Daraus ergibt sich folgendes Lemma:

Lemma: Während der Ausführung von A* gilt für alle i, i’, j, j’ mit j != j’, dass die Mengen

Open(i, j) und Open(i’, j’) disjunkt sind.

Aus dem Lemma folgt, dass Duplikaterkennung nur für Buckets mit dem selben h-Wert

durchgeführt werden muss.

Duplikaterkennung wird immer nur für das Bucket, welches als nächstes expandiert werden

soll, durchgeführt. Zu diesem Zeitpunkt sind die anderen Buckets eventuell noch nicht

vollständig generiert, so dass es passieren könnte, dass die Duplikaterkennung für diese zu

einem späteren Zeitpunkt noch einmal wiederholt werden müsste. Die Duplikaterkennung zu

einem früheren Zeitpunkt auszuführen wäre somit redundant.

Das eigentlich Erkennen und Entfernen von Duplikaten erfolgt dann in zwei Schritten. Erstens

wird das grade aktive Bucket Open(g, h) sortiert und dabei werden innerhalb des Buckets

bestehende doppelte Zustände gelöscht. Diese Operation wird durch externes Sortieren

realisiert. Zweitens müssen die Zustände aus den Buckets Open(g-1, h) und Open(g-2, h) von

Open(g, h) subtrahiert werden. Dazu müssen diese drei bereits vorsortierten Buckets einmal

parallel gescannt werden. Anschließend kann das nun duplikatfreie Bucket Open(g, h)

expandiert werden.

Theorem: Die I/O-Komplexität des externen A* Algorithmus auf einem ungerichteten

gleiche Kosten Graph mit konsistenter Heuristik ist durch O(sort(|E|) + scan(|V|)) I/O-

Operationen beschränkt.

Beweis: Jede Kante des Problemgraphen wird von der Duplikaterkennung höchstens einmal

betrachtet. Jeder Zustand wird einmal erzeugt und gespeichert und dann einmal fürs externe

Sortieren gelesen, einmal für die Expansion gelesen und zweimal für die Duplikaterkennung

gescannt.

Schritt 1 der Duplikaterkennung ist das externe Sortieren. Das Bucket Open(g, h) hat einen

Zustand für jede Kante aus den drei Buckets Open(g-1, h-1), Open(g-1, h) und Open(g-1,

h+1). Das externe Sortieren des Buckets Open(g, h) kann also abgeschätzt werden durch

O(sort(|N(Open(g-1,h-1))| + |N(Open(g-1, h))| + |N(Open(g-1, h+1))|)) I/O-Operationen,

147

Page 154: HEINZ NIXDORF INSTITUT Fakultät für Elektrotechnik ... Pottmeyer Memory Limitations in Artificial Intelligence ... Vitter hat gezeigt, dass viele in diesem Modell effiziente Entwicklungen

wobei die Funktion N die Nachfolger eines Knotens generiert. Da jeder Knoten höchstens

einmal expandiert wird, führt dies zu insgesamt O(sort(|E|)) I/O-Operationen.

Schritt 2 der Duplikaterkennung ist das Subtrahieren der Buckets. Dabei müssen die Zustände

der Buckets Open(g-1, h) und Open(g-2, h) vom denen des Buckets Open(g, h) abgezogen

werden. Da die einzelnen Buckets bereits sortiert sind, reicht ein Scan der Buckets aus. Dies

führt zu O(scan(|N(Open(g-1,h-1))| + |N(Open(g-1, h))| + |N(Open(g-1, h+1))|) +

scan(|N(Open(g-1, h)))| + scan(|N(Open(g-2, h))|)) I/O-Operationen. Die Subtraktion addiert

also O(scan(|V|) + scan(|E|)) viele I/Os zur Laufzeit. Die gesamte Duplikaterkennung benötigt

also O(sort(|E|) + scan(|V|)) viele I/O-Operationen.

7. Pattern Datenbanken

Die bislang vorgestellten Techniken zielten alle darauf ab, den vorhandenen Speicherplatz zu

benutzten, um einen möglichst großen Teil des Suchraums zu speichern. Im Gegensatz dazu

wird bei Pattern Datenbanken [1] der Speicherplatz benutzt, um exaktere heuristische Werte

zu speichern und dadurch die Suche besser zu lenken, sodass nur ein geringerer Teil des

Suchraums exploriert werden muss.

Als Motivation betrachten wir die Manhattan-Distanz Heuristik für das n²-1 Puzzle. Diese

geht davon aus, dass zwei Puzzleteile unabhängig voneinander verschoben werden können.

Dies ist im allgemeinen jedoch nicht der Fall, wie folgendes Beispiel verdeutlicht:

Das linke Feld stellt den Startzustand dar und das rechte den Zielzustand. Die Manhattan

Distanz ist für dieses Beispiel vier. Da sich die Wege der beiden Teile aber kreuzen, müssen

sie einander ausweichen und benötigen deshalb zwei weitere Züge, also insgesamt sechs.

Die Verallgemeinerung dieses Ansatzes führt zu den so genannten Pattern Datenbanken.

Dabei ist ein Pattern ein Zustand einer Teilmenge der Puzzleteile. In der Pattern Datenbank

wird dann zu jedem Pattern der gleichen Teilmenge die exakte Anzahl Schritte gespeichert,

die benötigt wird, um dieses Pattern zu lösen. Die Lösung des Patterns stellt ein Teilziel dar,

welches erreicht werden muss, um die Gesamtaufgabe zu lösen. Ist zum Beispiel das

untenstehende Pattern gelöst worden, muss nur noch ein 8-Puzzle gelöst werden, um zur

Gesamtlösung zu kommen.

3 1 3 1

148

Page 155: HEINZ NIXDORF INSTITUT Fakultät für Elektrotechnik ... Pottmeyer Memory Limitations in Artificial Intelligence ... Vitter hat gezeigt, dass viele in diesem Modell effiziente Entwicklungen

Im oben stehenden Beispiel stellt das linke Feld den Startzustand dar. Dieser ist ein Pattern

für die Teilmenge 3,7,11,12,13,14,15 der Puzzleteile und das leere (graue) Feld. Das rechte

Feld stellt den Zielzustand dar. In der Patterndatenbank wird dann zu dem links stehenden

Pattern die exakte Anzahl an benötigten Schritten – für dieses Beispiel 31 – gespeichert.

Beachte, dass die 31 Schritte nur dafür benötigt werden, die betrachtete Teilmenge in die

richtige Position zu bringen. Anschließend muss noch das verbleibende 8-Puzzle gelöst

werden. Dieses hat jedoch nur 9!/2 = 181.440 Zustände und könnte komplett im Voraus

berechnet und gespeichert werden.

Im obigen Beispiel besteht das Pattern aus den 7 Randteilen und dem leeren Feld, also

insgesamt 8 Teilen. Diese 8 Teile können im 15er Puzzle 16!/(16-8)! = 518,918,400 Zustände

annehmen. Die Datenbank muss für dieses Pattern also knapp 519 Millionen Einträge

enthalten.

Eine Pattern Datenbank muss für ein Problem nur einmal berechnet werden und kann dann

immer wieder für neue Instanzen des selben Problems genutzt werden. Die Datenbank kann

erstellt werden, indem vom Zielzustand aus eine Breitensuche gestartet wird. Während dieser

Suche werden alle Züge gezählt. In einem Zug wird dabei entweder ein Teil des Patterns, oder

eines der weißen Nicht-Pattern-Teile verschoben. Jedes Mal, wenn ein neuer Zustand erreicht

wird, wird dieser dann gespeichert, zusammen mit der Anzahl an Schritten, die benötigt

wurde, um ihn zu erreichen. Da das Pattern eben nur eine Teilmenge des Gesamtproblems

betrachtet und löst, kann man es mit so einem Brute-Force-Ansatz effizient lösen, auch wenn

dies für das Gesamtproblem unmöglich ist.

Experimentelle Laufzeitüberprüfung

Patterndatenbanken wurden benutzt, um 100 Testinstanzen des 15er Puzzles zu lösen. Dabei

wurden zwei Pattern getestet. Das erste Pattern ist das bereits oben vorgestellte, bestehend aus

den 7 Randteilen 3,7,11,12,13,14,15 und dem leeren Feld. In der unten stehenden Tabelle ist

es mit FR (fringe, englisch für Rand) abgekürzt. Das zweite Pattern besteht aus den Teilen

8,9,10,12,13,14,15 und dem leeren Feld und ist in der unten stehenden Tabelle mit CO (für

corner) abgekürzt. Als Algorithmus wurde IDA* benutzt. Zum Vergleich wurde IDA* mit der

Manhattan-Distanz Heuristik verwendet.

Experiment # Knoten Baumgröße % Verbesserung

MD 36,302,808,031 100 -

MD + FR 105,067,478 0,29 346

MD + CO 83,125,633 0,23 437

Wie man in oben stehender Tabelle leicht sehen kann, hat die Verwendung einer

Patterndatenbank mit IDA* sehr große Vorteile gegenüber der Verwendung von IDA* mit

14 7

3

15

12

11 13

3

7

11

12 13 14 15

149

Page 156: HEINZ NIXDORF INSTITUT Fakultät für Elektrotechnik ... Pottmeyer Memory Limitations in Artificial Intelligence ... Vitter hat gezeigt, dass viele in diesem Modell effiziente Entwicklungen

Manhattan-Distanz gebracht. Durch Verwendung der Corner Patterndatenbank wurde die

Baumgröße sogar auf 0,23% reduziert, also um einen Faktor von 437 verbessert.

8. Zusammenfassung

In dieser Ausarbeitung wurden verschiedene heuristische Suchverfahren vorgestellt. A* ist

das Suchverfahren, welches die wenigsten Knoten expandiert, hat dafür aber einen

Speicherplatzbedarf, der exponentiell mit der Lösungstiefe wächst. IDA* expandiert auf der

Menge der c-beschränkten Graphen bis zu O(c n²) viele Knoten (wenn A* n Knoten

expandiert), braucht dafür aber nur O(d) Speicher. Speicherbeschränkten Verfahren wie

SMA* und MEIDA* wird die Größe M des Speicherplatzes, den sie verwenden dürfen,

übergeben. Ist der betrachtete Suchraum größer als dieser Speicherplatz, müssen mache

bereits expandierte Knoten wieder aus dem Speicher verdrängt werden, bevor neue Knoten

expandiert werden können. Es besteht das Problem, dass nicht mehr gespeicherte Zustände

eventuell wieder neu erzeugt werden müssen. MEIDA* ist das Speicherbeschränkte

Verfahren mit dem besten theoretischen Ergebnis für Suchbäume. Es expandiert O(n²/M)

viele Knoten. Im externen A* Algorithmus wird immer der komplette bislang erzeugte

Suchraum auf der Festplatte gespeichert. Der Algorithmus ordnet die Zustände auf der

Festplatte so an und führt die Duplikaterkennung so aus, dass die Anzahl benötigter

Festplattenzugriffe minimiert wird. Externes A* benötigt O(sort(|E|) + scan(|V|)) I/O-

Operationen. Ein anderer wichtiger Ansatz besteht darin, den Speicherplatz nicht zum

Speichern des Suchraums, sondern für bessere heuristische Werte zu verwenden. Solche

Werte werden z.B. in Pattern-Datenbanken gespeichert und lenken die Suche so, dass nur ein

geringerer Teil des Suchraums betrachtet werden muss.

9. Literatur

[1] Culberson, J. C., Schaeffer, J. Searching with Pattern Databases. In Gordon McCalla,

Editor, Proceedings of the eleventh Biennial Conference of the Canadian Society for

Computational Studies of Intelligence on Advances in Artificial Intelligence, volume 1081 of

LNAI, pages 402-416, Springer, 1996.

[2] Eckerle, J., Schuirer, S. Effiziente speicherplatzbeschränkte Graph-Such-Algorithmen.

Technischer Bericht Nr. 57, Universität Freiburg, 1994.

[3] Edelkamp, S. Memory Limitations in Artificial Intelligence. In Ulrich Meyers, Peter

Sanders, Jop Sibeyn, Algorithms for Memory Hierarchies, pages 233-250, Springer, 2003.

[4] Edelkamp, S., Jabbar, S., Schrödl, S. External A*. In Proceedings of the 27th German

Conference on Artificial Intelligence, pages 226-240, Ulm, Germany, 2004.

[5] Korf, R. Depth-First Iterative Deepening: An Optimal Admissible Tree Search. In

Artificial Intelligence, Volume 27, Issue 1, pages 97-109, 1985.

[6] Russell, S. Efficient Memory-Bounded Search Methods. In Proceedings of the European

Conference on Artificial Intelligence, pages 1-5, 1992.

150

Page 157: HEINZ NIXDORF INSTITUT Fakultät für Elektrotechnik ... Pottmeyer Memory Limitations in Artificial Intelligence ... Vitter hat gezeigt, dass viele in diesem Modell effiziente Entwicklungen

Algorithmen für Speichernetzwerke

Elmar Köhler

1 Einleitung

In modernen Computern werden heutzutage magnetische Speichersysteme zur persisten-ten Speicherung von Daten verwendet. Das zu speichernde Datenvolumen wächst hierbeiallerdings konstant an. Dies liegt an der globalen Verfügbarkeit der Daten, wie z.B. durchdas Internet, wie auch aufgrund von immer stärker in den Vordergrund rückenden Multi-mediaanwendungen. Um mit dieser Menge an Informationen Schritt zu halten, reichen diesich alle 14 - 18 Monate verdoppelnden Kapazitäten heutiger Festplatten nicht mehr aus.Es müssen andere Wege gefunden werden das Datenvolumen zu fassen. Eine simple Lösungwäre die parallele Nutzung mehrerer Platten ohne besondere algorithmische Verteilung derDaten. Sollte die Kapazität nicht mehr ausreichen, so wird eine weitere Festplatte in denVerbund aufgenommen und die neu anfallenden Daten werden auf dieser gespeichert. Dieshat zwar den Vorteil, dass man annähernd unendliche Kapazität zur Verfügung hat undsich diese durch viele kostengünstige Festplatten realisieren lässt, allerdings beinhaltet dieLösung viele Probleme. So wird die Parallelität des Festplattenverbunds nicht ausgenutzt.Ein groÿes Problem kann auftreten, wenn alle populären Daten auf einer oder wenigen Fest-platten gespeichert werden. Diese Daten werden aufgrund ihrer Popularität viele Anfragenerhalten, was zu einem Flaschenhals bei dieser Festplatte führt und somit langsamererPerformance. Weiterhin wächst die Ausfallwahrscheinlichkeit mit zunehmender Festplat-tenanzahl enorm an. Für jede Festplatte wird vom Hersteller eine Mean-Time-To-Failure

(MTTF) angegeben, welche die mittlere Zeit bis zu einem Ausfall der Platte angibt. DieseZeit ist für eine einzelne Festplatte betrachtet recht hoch, fällt jedoch ab, je mehr Fest-platten in einem Array zusammengefasst werden. Sie ändert sich zu:

MTTFArray =MTTFFestplatte

Anzahl Festplatten

Somit ist eine einfache Lösung mit einem Array aus vielen Festplatten weder besondersperformant, noch ausreichend zuverlässig.Eine ähnliche Lösungsmöglichkeit wäre die Verwendung von vielen Rechnern, welche überein Netzwerk verbunden sind. Hierbei haben wir wieder den Vorteil, dass durch Hinzufügenweiterer Rechner die Kapazität beliebig erhöht werden kann. Die Probleme sind allerdingsähnlich denen eines simplen Festplattenarrays. Einzelne Rechner oder Verbindungen zueinzelnen Rechnern können ausfallen, was zum Verlust der Daten auf diesen führt. Wei-terhin kann es wieder einen Flaschenhals für populäre Daten geben, wenn diese auf einem

151

Page 158: HEINZ NIXDORF INSTITUT Fakultät für Elektrotechnik ... Pottmeyer Memory Limitations in Artificial Intelligence ... Vitter hat gezeigt, dass viele in diesem Modell effiziente Entwicklungen

Rechner gespeichert werden und jener somit viele Anfragen beantworten muss. Die Paral-lelität würde kaum ausgenutzt.Die genannten Probleme führen zum Bedarf nach einer allgemeineren Verwaltung von Fest-platten. Speichernetzwerke können diese Verwaltung gewährleisten. Sie sind eine Sammlungvon Festplatten, welche durch ein Netzwerk verbunden sind. Dies alleine betrachtet wärenoch kein Unterschied zu den vorherigen Lösungsansätzen des Kapazitätsproblems. Dasbesondere an Speichernetzwerken ist jedoch, dass sie Verfahren verwenden, um die Vertei-lung der Daten zu steuern. So werden die Daten nicht einfach auf der neusten Festplattegespeichert, sondern über das gesamte Speichernetzwerk verteilt. Speichernetzwerke be-rücksichtigen das Datenverteilungsproblem, welches sich damit beschäftigt wie Daten imNetzwerk verteilt werden müssen, damit bei einer Anfrage auf einzelne Daten, die Anfrageso schnell wie möglich beantwortet werden kann. Einige Strategien zur Lösung des Pro-blems werden in den nachfolgenden Kapiteln vorgestellt. Zunächst wird jedoch erst dasModell für Speichernetzwerke und die Anforderungen an solche präsentiert.

2 Speichernetzwerke

In diesem Abschnitt werden zunächst Speichernetzwerke beschrieben, sowie ein Modell fürsie vorgestellt. Im Anschluss werden wichtige Anforderungen, die an Speichernetzwerkegestellt werden, präsentiert.

Abbildung 1: Modell eines Speichernetzwerks

2.1 Modell des Speichernetzwerks

Ein Speichernetzwerk besteht aus einer Sammlung von n Festplatten D1, ..., Dn, welchedurch ein Netzwerk verbunden sind. Jede der n Festplatten ist durch eine Kapazität Ci undeine Bandbreite bi charakterisiert. Die maximale Anzahl an Festplatten in dem Speicher-netzwerk betrage N . Für das Netzwerk wird die gesamte Kapazität durch S =

∑1≤i≤n Ci

ausgedrückt. Das Netzwerk kann willkürlich realisiert sein, solange alle Festplatten mitein-ander verbunden sind. Wenn die Charakteristiken aller Festplatten gleich sind, wird dasSpeichernetzwerk homogen bezeichnet, andernfalls ist es heterogen. Die Menge U = 1, ..., p

152

Page 159: HEINZ NIXDORF INSTITUT Fakultät für Elektrotechnik ... Pottmeyer Memory Limitations in Artificial Intelligence ... Vitter hat gezeigt, dass viele in diesem Modell effiziente Entwicklungen

bezeichnet die zu speichernden Datenelemente, welche aus dem Universum der Gröÿe Mbezogen werden. Auf Festplatten wird auf Daten in der Form von Dateneinheiten einerbestimmten Gröÿe, je nach System, zugegrien. Die Gröÿe dieser Dateneinheiten wird hierals Gröÿe eines Datenelements angenommen.In Speichernetzwerken können Dateneinheiten auch redundant gespeichert werden. Die-se Redundanz wird benötigt, um Ausfälle der Festplatten korrigieren zu können. Hierzuwird der Begri der Replikationsreinheit verwendet, welche eine Kopie einer Dateneinheitdarstellt. Durch den Replikationsfaktor r ∈ R wird ausgedrückt, wieviele Replikations-einheiten je Dateneinheit im Speichernetzwerk vorhanden sind. Ein Faktor von 1 stehthierbei für je eine Kopie je Dateneinheit. Somit ergibt sich die Gesamtanzahl an gespei-cherten Elementen im Netzwerk zu m =

∑1≤i≤p i+ r ∗ i. Abbildung 1 zeigt das Modell für

Speichernetzwerk grasch.

2.2 Anforderungen an Speichernetzwerke

Speichernetzwerke unterliegen verschiedenen Anforderungen. Diese sind vielfältig und kön-nen nicht alle gleichzeitig erfüllt werden. Folgende Anforderugnen werden gestellt:

• Last- und Zugrisbalancierung: Beschreibt die Anforderung, die Daten möglichstgleichmäÿig über alle Festplatten zu verteilen. Dies gewährleistet eine gute Platten-ausnutzung und erhöht die Parallelität bei der Abarbeitung von Datenanfragen.

• Verfügbarkeit: Viele Festplatten in einen Array erhöhen die Ausfallwahrscheinlich-keit. Aus diesem Grund müssen Speichernetzwerke sicherstellen, dass die Daten auchim Falle eines Fehlers wieder Verfügbar gemacht werden können. Dies kann durchRedundanz und Mechanismen zur Datenrekonstruktion erreicht werden.

• Ressourcenezienz:Die Ressourcen eines Speichernetzwerks sollen nicht verschwen-det werden. Das Problem der Verfügbarkeit könnte z.B. durch viele Kopien der Daten-einheiten realisiert werden, sodass Festplattenausfälle kompensiert werden können.Diese Lösung verwendet allerdings einen Groÿteil der Speicherressourcen für Kopienund nur einen kleinen Teil für die eigentlichen Daten. Somit wäre viel Speicherplatzverschwendet. Daher ist es wichtig die Ressourcen ezient zu nutzen, vor allem,wenn die Gröÿe der Speichernetzwerke stark zunimmt.

• Zugrisezienz: Daten im Speichernetzwerk sollen möglichst schnell erreicht wer-den. Wenn auf Daten nicht zugegrien werden kann, sind sie verloren. Daher solldie Zeit für einen Datenzugri möglichst kurz sein. Dies kann z.B. durch Parallelitätbei der Abarbeitung von Anfragen realisiert werden, oder indem gröÿere Mengen anDateneinheiten auf einmal eingelesen werden.

• Heterogenität: Speichernetzwerke können nicht immer aus homogenen Festplat-tenarrays bestehen. Speziell, wenn Netzwerke erweitert werden müssen, kann nichtsichergestellt werden, dass Festplatten mit gleichen Charakteristiken, wie die bereitsvorhandenen Platten, verwendet werden. Diese Anforderung beschreibt wie Speicher-netzwerke Festplatten mit unterschiedlichen Kapazitäten und Bandbreiten verwalten.

153

Page 160: HEINZ NIXDORF INSTITUT Fakultät für Elektrotechnik ... Pottmeyer Memory Limitations in Artificial Intelligence ... Vitter hat gezeigt, dass viele in diesem Modell effiziente Entwicklungen

• Adaptivität: Speichernetzwerke sind nicht statisch. Sie verändern sich im Laufe derZeit, wie z.B. wenn die Kapazität des Netzwerks nicht mehr ausreicht und weitereFestplatten verwendet werden müssen. Die Adaptivität beschreibt dabei die Fähig-keit des Netzwerks sich an die Veränderungen anzupassen. Wie geschickt werden diebereits gespeicherten Daten umstrukturiert, um die neu hinzugewonnene, oder auchverlorene, Festplatte zu nutzen. Eine adaptives Speichernetzwerk muss hierbei nureinen geringen Teil der gespeicherten Daten umstrukturieren.

• Lokalität: Lokalität beschreibt den Kommunikationsaufwand, um eine Datenanfragezu beantworten. Sind die Daten z.B. räumlich nah auf den Festplatten angeordnet,sodass sie nacheinander gelesen werden können oder muss der Kopf der Festplattegroÿe Wege zurücklegen.

Die Datenverteilungsstrategien können nicht alle diese Anforderungen optimal erfüllen.Es müssen Kompromisse getroen werden je nachdem, in welchem Kontext das Speicher-netzwerk eingesetzt werden soll. In den nachfolgenden Kapiteln werden Strategien vorge-stellt, welche ihr Hauptaugenmerk auf einzelne der oben genannten Anforderungen legen.

3 Striping

Die Motivation hinter der Entwicklung des Stripings war es eine Last- und Zugrisbalan-cierung zu erreichen. Die Daten sollten möglichst gleichmässig über alle Festplatten verteiltwerden. Dies sollte vermeiden, dass einige Festplatten besonders viele Anfragen erhalten,während andere kaum beansprucht werden. Eine gleichmäÿige Verteilung ermöglicht auchdie Parallelität des Array besser auszunutzen, da Anfragen gleichzeitig bearbeitet werdenkönnen. Striping ist ein deterministischer Ansatz, wo genau vorgegeben wird, welche Da-teneinheit auf welcher Festplatte gespeichert werden soll. Hierbei wird die Menge der pDateneinheiten in Stripes eigenteilt und auf die Festplatten verteilt. Hierzu ist es erstmalnotwendig zu denieren, was ein Stipe genau ist.Ein Stripe ist eine Sammlung von l aufeinanderfolgenden Dateneinheiten, in der auchReplikationseinheiten innerhalb eines Stripes vorkommen können. Die Länge eines Stripeswird meist so gewählt, dass sie der Anzahl Festplatten im Speichernetzwerk entspricht. Die

Abbildung 2: Aufteilung der Dateneinheiten in Stripes

Abbildung 2 zeigt die Aufteilung der Dateneinheiten in Stripes. Die Dateneinheiten werdennacheinander den Stripes zugeordnet, wobei hier eine Stripelänge von 8 gewählt wurde. DieVerteilung der Daten auf die Festplatten erfolgt dann in ganzen Stripes. Dabei werden dieDateneinheiten folgendermaÿen den Festplatten zugeordnet. Die i-te Dateneinheit gelangt

154

Page 161: HEINZ NIXDORF INSTITUT Fakultät für Elektrotechnik ... Pottmeyer Memory Limitations in Artificial Intelligence ... Vitter hat gezeigt, dass viele in diesem Modell effiziente Entwicklungen

auf Festplatte Di mod n, wenn die Stripelänge auf die Anzahl n der Festplatten gesetzt wur-de. In Abbildung 3 wird gezeigt, wie ein Stripe auf die Festplatten D1, ..., D6 verteilt wird.

Abbildung 3: Zuordnung der Stripes

Die Stripelänge wurde auf die Anzahl der Festplatten gesetzt. An dieser Abbildung lassensich die Vorteile des Striping beschreiben. Man sieht, wie sich eine gleichmässige Last-verteilung über die Festplatten ergibt. Weiterhin können ganze Stripes komplett parallelzugegrien werden, sodass die Performance des Systems steigt. Allerdings können dieseVorteile nur so lange optimal ausgenutzt werden, solange die Kapazität der Festplattenhomogen ist. Bei heterogenen Festplatten wird Kapazität verschwendet, sobald die kleins-te Platte gefüllt ist, bzw die Stripes können nicht mehr über alle Festplatten verteilt werdenund manche Festplatten müssen mehrere Dateneinheiten eines Stripes aufnehmen. Dies re-duziert die gewonnene Performance des Striping. Ein weiterer Nachteil tritt auf, wenn sichdie Anzahl der Festplatten im Speichernetzwerk ändert. Um keine überlappenden Stripeszu haben und um die Performance des Speichernetzwerks optimal ausnutzen zu können,muss die Stripelänge angepasst werden. Dies führt jedoch zu einer kompletten Neustruk-turierung der Dateneinheiten, was bei groÿen Speichernetzwerken einen enormen Aufwandbedeutet und nicht ezient ist. Weiterhin hat dieses Verfahren keine Möglichkeit bei einemFestplattenausfall die Daten zu rekonstruieren. Eine Strategie zur Performancesteigerungund zur Rekonstruktion der Daten im Fehlerfall stellt das nächste Verfahren dar.

4 RAID

RAID [2] wurde 1988 von Patterson, Gibson und Katz als Alternative zu einzelnen, teurenFestplatten vorgestellt. Die Motivation hinter RAID liegt darin die Performance und dieVerfügbarkeit von Festplattenarrays zu erhöhen. Hierzu sollten mehrere, homogene Fest-platten einer festen Anzahl zu einem Array zusammengeschlossen werden. Diese Form, dieKapazität eines Speichernetzwerks zu erhöhen, ist günstiger als einzelne, groÿe und teureFestplatten zu verwenden. Besondere Aufmerksamkeit wird hierbei den Fehlern innerhalbdes Array gewidmet. Wie in Kapitel 1 beschrieben, nimmt die MTTF mit zunehmenderAnzahl Festplatten stark ab. Somit müssen Mechanismen verwendet werden, um im Fallevon Plattenfehlern die Daten dennoch wieder rekonstruieren zu können. Patterson, Gib-son und Katz haben RAID in verschiedene Level eingeteilt, welche im nächsten Abschnitt

155

Page 162: HEINZ NIXDORF INSTITUT Fakultät für Elektrotechnik ... Pottmeyer Memory Limitations in Artificial Intelligence ... Vitter hat gezeigt, dass viele in diesem Modell effiziente Entwicklungen

beschrieben werden.

4.1 RAID-Level Übersicht

RAID 0 dient der Performancesteigerung. Bei dieser Strategie werden noch keine Mechanis-men zur Fehlerbehebung verwendet. Es wird simples Striping, wie in Kapitel 3 beschrieben,verwendet. Die Nachteile sind weiterhin, dass bei einem Fehler die Daten nicht rekonstruiertwerden können. Ein erster Ansatz zur Lösung dieses Problems wird in RAID 1 verwendet.Hierbei wird von jeder gespeicherten Dateneinheit eine Kopie auf einer physikalisch an-deren Festplatte gespeichert. Diese Redundanz hat den Vorteil, dass bei einem Fehler diedefekte Festplatte ausgetauscht und die Daten von der Sicherheitskopie wiederhergestelltwerden können. Bei RAID 1 wird jedoch nicht die Parallelität der verschiedenen Festplattenausgenutzt. Die Performance ist weiterhin wie bei einer einzigen Festplatte. Eine geringePerformancesteigerung tritt jedoch beim Lesen von Dateneinheiten auf, da hier ein alter-nierendes Lesen zwischen dem Original und der Kopie nötig ist. Beim Schreiben müssenjedoch die Kopie und das Original aktualisiert werden. Des Weiteren ist dieses Verfahrensehr ressourceninezient. Man benötigt doppelt soviel Speicherplatz für seine Daten.Ein Ansatz, um sowohl die Performance, als auch die Verfügbarkeit ezient zu erhöhenstellt RAID 4 dar. Hierbei werden die Dateneinheiten, wie bei RAID 0, in Stripes eingeteiltund auf die Festplatten aufgeteilt. Dies erhöht jedoch erst die Performance und die Ver-fügbarkeit wurde noch nicht sichergestellt. Zu diesem Zweck werden Parity Informationen

verwendet und auf einer extra Festplatte abgespeichert. Die Parity Informationen ergebensich durch die bitweise XOR-Bildung über die einzelnen Dateneinheiten innerhalb einesStripes. Das XOR ist in Hardware direkt abbildbar und somit eine sehr schnelle Operati-on. Des Weiteren lässt sich beim Fehlen eines einzelnen Bits, z.B. dass eine Dateneinheitverloren gegangen ist, diese mit Hilfe der anderen direkt wieder rekonstruieren.

0 1 0 | 11 1 1 | 11 1 0 | 0

Angenommen die ersten 3 Spalten repräsentieren jeweils die Dateneinheiten auf einer Fest-platte und die 4te Spalte repräsentiert die Parity Information. Fällt nun zum Beispieldie Festplatte, welche durch Spalte 2 repräsentiert wird aus, so sind die Informationenauf dieser Festplatte durch XOR-Bildung über die Festplatte 1, 2 und die Festplatte mitden Parity Informationen wiederherstellbar. Für den ersten Stripe (durch die erste Zeilerepräsentiert wäre dies

(0 XOR 0) XOR 1 = 1

und man erhält die Information auf der 2ten Festplatte wieder. Die anderen Stripes lassensich analog wiederherstellen. Wir haben somit bei RAID 4 Striping, welches die Perfor-mance erhöht, und durch die Parity Information eine Möglichkeit Fehler auszugleichen. DerVorteil der Parity Information im Vergleich zu RAID 1 liegt darin, dass mit einer ParityInformation mehrere Dateneinheiten gesichert werden können. Es wird nicht mehr eineKopie pro Dateneinheit benötigt, sondern für mehrere Dateneinheiten brauchen wir nureinen Parityeinheit. Das Schreiben einzelner Dateneinheiten ist durch die Parity Informa-tion auch nicht komplizierter geworden. Bei RAID 1 musste man im Falle einer Änderung

156

Page 163: HEINZ NIXDORF INSTITUT Fakultät für Elektrotechnik ... Pottmeyer Memory Limitations in Artificial Intelligence ... Vitter hat gezeigt, dass viele in diesem Modell effiziente Entwicklungen

sowohl das Original als auch die Kopie schreiben. In RAID 4 benötigt man die Information,die vorher in der Dateneinheit stand, die neue Information und die alte Parity Information.Mit diesen lässt sich die neue Parity Information folgendermassen bilden:

new parity = (old data XOR new data) XOR old parity

Ein Nachteil von RAID 4 tritt allerdings auf, wenn nicht ganze Stripes geschrieben werden,sondern nur einzelne Dateneinheiten. Hierbei bildet die Parity Information einen Flaschen-hals, da diese auf eine Festplatte liegt und auf diese Informationen nur nacheinander zuge-grien werden kann. Abbildung 4 zeigt dieses Problem. Das x in den Dateneinheiten soll

Abbildung 4: Small-Write Problem in RAID 4

hierbei einen schreibenden Zugri darstellen. Der Schreibzugri auf die 2te Dateneinheitim 2ten Stripe führt dazu, dass die Parity Information auf Festplatte D5 aktualisiert wer-den muss. Ebenso müss für den Schreibzugri auf die 3te Dateneinheit im 1ten Stripe dieParityInformation auf Festplatte D5 verändert werden. Die Zugrie auf die Dateneinhei-ten können parallel durchgeführt werden, da sie auf unterschiedlichen Festplatten liegen.Allerdings liegen die Parity Informationen auf einer Festplatte, was zu einem Flaschenhalsführt. Beim Schreiben ganzer Stripes tritt dieses Problem nicht auf, daher wird dies auchdas Small-Write-Problem genannt.RAID 5 versucht dieses Problem zu lösen, indem die Parity Informationen nicht auf einereinzelnen Platte, sondern über die Stripes verteilt gespeichert werden. Hierdurch wird beimSchreiben einzelner Dateneinheiten nicht immer eine einzige Festplatte zum Aktualisierender Parity Informationen benötigt. Der Schreibaufwand verteilt sich über alle Festplatten.Abbildung 5 zeigt wie sich die Parity Informationen über die Stripes verteilen. Will man

Abbildung 5: Small-Write in RAID 5

nun einzelne Dateneinheiten schreiben, wie z.B. die 1te Dateneinheit im 4ten Stripe unddie 3te Dateneinheit im 2ten Stripe so benötigt, man zum Aktualisieren der Parity Infor-mationen einmal die Information auf Festplatte D2 für den 4ten Stripe und einmal die

157

Page 164: HEINZ NIXDORF INSTITUT Fakultät für Elektrotechnik ... Pottmeyer Memory Limitations in Artificial Intelligence ... Vitter hat gezeigt, dass viele in diesem Modell effiziente Entwicklungen

Information auf Festplatte D4 für den 2ten Stripe. Diese Schreibvorgänge können parallelausgeführt werden, da die Daten auf unterschiedlichen Festplatten liegen, was zu einerPerformancesteigerung führt. Mit RAID 5 ist somit ein Verfahren gegeben, welches diePerformance durch Striping erhöht, sowohl beim Schreiben ganzer Stripes, als auch beieinzelnen Dateneinheiten innerhalb eines Stripes, sowie durch Parity Information die Ver-fügbarkeit ressourcenezient sicherstellt. Die Nachteile liegen allerdings darin, dass RAIDnur einen Fehler korrigieren kann. Tritt ein weiterer Fehler auf, während die Dateneinheitennoch nicht rekonstruiert wurden, so sind die Informationen auf beiden Festplatten verloren.Eine Möglichkeit 2 Fehler zu korrigieren stellt EVENODD dar, wobei zusätzlich Parity In-formationen über die Diagonalen gebildet werden. Dieses Verfahren wird hier jedoch nichtweiter vorgestellt. Weiter Schwächen von RAID liegen in den homogenen Festplatten undder Beschränkung auf eine feste Anzahl Festplatten, da bei Änderung dieser die Stripe-gröÿe angepasst und alle Daten neu verteilt werden müssen. Ein Verfahren, welches mitheterogenen Festplatten arbeiten kann, wird im nächsten Kapitel vorgestellt.

5 Adapt Raid

Adapt Raid beschäftigt sich mit dem Problem heterogener Festplatten in Speichernetz-werken. Heterogene Speichernetzwerke können z.B. durch den Ausfall einer Festplatte ent-stehen. Es kann nicht garantiert werden, dass Festplatten mit denselben Charakteristikenverwendet werden können, sodass die Administratoren von Speichernetzwerken darauf an-gewiesen sind neuere Festplatten beim Austausch zu nutzen, die oftmals höhere Kapazitätund Bandbreite im Vergleich zu den bisher verwendeten Festplatten haben. Mit der da-durch entstanden Heterogenität umzugehen, ist eine schwierige Aufgabe, wenn man wei-terhin versucht die Last- und Zugrisbalancierung aufrecht zu erhalten. Eine Möglichkeitmit der Heterogenität umzugehen, ist das Zusammenfassen von Festplatten zu Clusternanhand ihrer Charakteristiken. Innerhalb eines Clusters können die Daten mit Hilfe bishe-riger Strategien platziert werden. Der Vorteil hiervon ist die leichte Erweiterbarkeit, wenndas Speichernetzwerk vergröÿert werden muss. Allerdings verringert dieser Ansatz nicht dieZeit, um eine Anfrage zu beantworten. Nur Daten auf neueren Festplatten werden deutlichschneller bearbeitet. AdaptRaid versucht RAID zu erweitern und bezieht sich dabei aufRAID 0 und RAID 5.

5.1 AdaptRaid Level 0

AdaptRaid Level 0 [3] verwendet die Annahme, dass neuere Festplatten in der Regel schnel-ler sind und gröÿere Kapazität besitzen. Daher sollten diese Festplatten mehr Anfragenbehandeln. Nichts desto trotz sollte die Parallelität des gesamten Speichernetzwerks solange wie möglich ausgenutzt werden. Die Idee dabei ist es so lange Stripes der Längel = n auf die Festplatten zu verteilen, bis die k kleinsten Festplatten gefüllt sind. Sobalddies geschehen ist, werden Stripes der Länger n− k auf die Festplatten verteilt bis wiederein Teil der Festplatten voll ist und die Stripelänge erneut angepasst werden muss. DiesesVorgehen wird so lange ausgeführt, bis alle Festplatten gefüllt sind. Abbildung 6 zeigt diesbeispielhaft für n Festplatten. Bei diesem Ansatz werden die Charakteristiken der Fest-platten und die gesamte Kapazität zwar ausgenutzt, jedoch werden die neuesten Daten auf

158

Page 165: HEINZ NIXDORF INSTITUT Fakultät für Elektrotechnik ... Pottmeyer Memory Limitations in Artificial Intelligence ... Vitter hat gezeigt, dass viele in diesem Modell effiziente Entwicklungen

Abbildung 6: AdaptRaid Level 0 - Beispielverteilung

die wenigen, schnellen Festplatten gespeichert. Wenn nun viele Anfragen auf diese Datengestellt werden, so wird die Parallelität des Arrays kaum ausgenutzt. Hierzu können Mus-ter eingeführt werden, welche vom Administrator des Speichernetzwerks deniert werdenmüssen. Für die Muster müssen 2 Parameter gesetzt werden. Zum Einen der UtilizationFactor (UF ∈ [0, 1]), welcher die Ausnutzung jeder Festplatte im Verhältnis zur Gröÿtenangibt und die Lines in a pattern (LIP), welcher die Anzahl Zeilen in einem Pattern an-gibt. Abbildung 7 zeigt solch ein Muster. Hierbei gelten die Werte UF1 = 1, UF2 = 0.83,

Abbildung 7: Muster für AdaptRaid Level 0

UF3 = 0.66, UF4 = 0.33 und LIP = 6. Dieses Muster wird nun bei der Verteilung der Da-

Abbildung 8: Anwendung eines Musters

teneinheiten immer wieder angewandt, sodass bei zweimaliger Anwendung eine Verteilung

159

Page 166: HEINZ NIXDORF INSTITUT Fakultät für Elektrotechnik ... Pottmeyer Memory Limitations in Artificial Intelligence ... Vitter hat gezeigt, dass viele in diesem Modell effiziente Entwicklungen

wie in Abbildung 8 erreicht wird. Der Vorteil hierin liegt in der Tatsache, dass nun auchweiterhin bei den neuesten Daten die Parallelität komplett ausgenutzt werden kann, wiez.B. bei den Dateneinheiten 28, 29 und 30, welche über 3 Festplatten verteilt sind. Wei-terhin wird die Kapazität des Speichernetzwerks komplett ausgenutzt. Performancetestsmit mehrere schnellen und langsamen Festplatten ergaben eine 8 - 20 %ige Beschleunigungbeim Lesen und 15 - 35 %ige Beschleunigung beim Schreiben [3], welche auf die Verschie-bung der Daten zu den schnelleren Festplatten zurückzuführen ist.Der Zugri auf Dateneinheiten geschieht in 2 Schritten. Zuerst muss das richtige Mustergefunden werden, welches über die LIP recht einfach erreicht werden kann. Als nächsteswird dieses Pattern angewendet, um so die Dateneinheit zu nden. Der Platzbedarf hierfürist proportional zur Gröÿe des Musters selbst.

5.2 AdaptRaid Level 5

AdaptRaid Level 5 [4] geht ähnlich wie AdaptRaid Level 0 vor. Es werden so lange Stripesder maximalen Länge zugeordnet bis ein Teil der Festplatten voll ist und die Stripelängeangepasst werden muss. Allerdings wird die Stripelänge bei diesem Verfahren auf einenganzzahligen Teiler der maximal möglichen Stripelänge im Speichernetzwerk festgelegt.Dies hat den Vorteil, dass das darüberliegende System keine unterschiedlichen Stripelän-gen berücksichtigen muss, sondern nur die kleinste Stripelänge kennt. Das Speichernetzwerkerledigt die Umrechnung wieviele Dateneinheiten parallel gelesen oder geschrieben werdenkönnen. Abbildung 9 zeigt eine Verteilung der Dateneinheiten mit AdaptRaid Level 5. Die

Abbildung 9: Initiale Verteilung mit AdaptRaid Level 5

maximale Stripelänge ist 4 mit Parity Information und die geringste Länge ist 2 mit Pa-rity Information. Die Parity Information sind wie bei RAID 5 über die Stripes verteilt.Die Zahlen in den Dateneinheiten geben die Blocknummer und den zugehörigen Stripe an,während in den Parity Informationen nur der zugehörige Stripe angegeben ist. Ein Nachteilist hierbei die geringe Auslastung von Festplatte D4 mit nur 33%. Hier wird die Last- undZugrisbalancierung verletzt. Durch das Verteilen der Stripes über alle Festplatten, wie inAbbildung 10 zu sehen, kann die Last über alle Festplatten balanciert werden. Allerdingswird weiterhin Kapazität verschenkt. Diese Löcher in der Verteilung können mit einemTetris-ähnlichen Algortihmus gefüllt werden. Hierbei rücken darüberliegende Dateneinhei-ten eine Zeile tiefer und schliessen die Lücken.Der Zugri auf eine Dateneinheit wird über 3 Tabellen sichergestellt. Beim Starten des Spei-chernetzwerks werden die Tabellen angelegt. Die erste Tabelle beinhaltet für jeden Blockin einem Pattern die Festplatte und die Position auf dieser, die Zweite hält die Position

160

Page 167: HEINZ NIXDORF INSTITUT Fakultät für Elektrotechnik ... Pottmeyer Memory Limitations in Artificial Intelligence ... Vitter hat gezeigt, dass viele in diesem Modell effiziente Entwicklungen

Abbildung 10: Verschieben der Stripes in AdaptRaid Level 5

der Parity Information für jeden Stripe und die dritte Tabelle speichert die Anzahl Blöcke,die jede Festplatte in einem Pattern hat. Hierdurch ist der Zugri auf eine Dateneinheitein simples look-up, was in O(1) durchgeführt werden kann. Der Nachteil hierbei liegt imOverhead, der durch die Tabellen erzeugt werden kann. Cortes und Labarta [4] sagen zwar,dass die Tabellen in ihren Experimenten nicht allzu groÿ geworden sind, allerdings kanndies bei wirklich groÿen Speichernetzwerken durchaus mit erheblichem Rechen- und Spei-cheraufwand verbunden sein. Des Weiteren ist dieses Verfahren nicht adaptiv. Auch wennder Name Anderes vermuten lässt, so müssen bei einer Änderung der Festplattenanzahlim Speichernetzwerk alle Daten neu verteilt werden, wenn man die neu hinzugewonnenKapazität und Bandbreite ausnutzen will.Weitere Verfahren, um mit der Heterogenität in Speichernetzwerken umzugehen stellen

HERA [5] und RIO [6] dar. HERA teilt alle Festplatten in so genannte Extents gleicherGröÿe auf und fasst diese Extents zu Parity Gruppen zusammen. Die Parity Gruppenhaben somit gleiche Kapazität und die Daten lassen sich gleichmäÿig über alle Festplat-ten verteilen, um eine Last- und Zugrisbalancierung sicherzustellen. Die Stripelänge wirdhierbei auf die Anzahl der Extents pro Parity Gruppe gesetzt, sodass ein Extent der Grö-ÿe einer Dateneinheit entspricht. RIO ist ein Ansatz aus dem Multimedia Bereich. Esverwendet eine randomisierte Verteilungsstrategie, wo jede Dateneinheit auf eine zufälligeFestplatte an einer zufälligen Position gesetzt wird. Um mit Heterogenität umzugehen,wird bei der zufälligen Verteilung ein Parameter berücksicht, welcher das Bandbreiten-zu-Speicherplatz-Verhältnis je Festplatte ausdrückt. Je höher dieser ist, um so schneller kanneine Festplatte auf Dateneinheiten zugreifen und sollte somit auch mehr Dateneinheitenerhalten als Festplatten mit geringerem Verhältnis. Genauer wird in dieser Ausarbeitungauf diese beiden Verfahren nicht eingegangen.

6 Cut-and-Paste

Die Cut-and-Paste Strategie [7] stellt ein adaptives Verfahren zur Verwaltung von Speicher-netzwerken dar. Da sich die Anzahl der Festplatten in Speichernetzwerken aufgrund dessteigenden Bedarfs an Kapazität schnell ändern kann, sind adaptive Verfahren immer wich-tiger. Cut-and-Paste ist ein Ansatz, der in 2 Phasen vorgeht. Zuerst wird der Adressraumvon 1, ..., p deniert, wobei p sehr groÿ gewählt werden sollte, da das Verfahren nicht mitnachträglich hinzukommenden Dateneinheiten umgehen kann, wenn diese nicht schon zuBeginn bekannt sind oder entsprechende Platzhalter verwendet wurden. Dies liegt daran,dass die Cut-and-Paste Strategie eine Ordnung auf den Dateneinheiten verwendet, welche

161

Page 168: HEINZ NIXDORF INSTITUT Fakultät für Elektrotechnik ... Pottmeyer Memory Limitations in Artificial Intelligence ... Vitter hat gezeigt, dass viele in diesem Modell effiziente Entwicklungen

durch nachträgliches Einfügen von Dateneinheiten gestört werden würde. Wenn der Adress-raum deniert wurde, wird dieser mit Hilfe einer zufällig ausgewählten Hash Funktion hauf das [0, 1) Intervall zugeordnet (der Hashwert h(b) gibt die Höhe im Intervall an). Durchdie Hashfunktion erhalten wir eine gleichmäÿge Verteilung über das Intervall und somiteine Lastbalancierung. Im zweiten Schritt wird das Intervall in Bereiche aufgeteilt, welchemit Hilfe einer Assimilierungsfunktion f auf die Festplatten verteilt werden. Wenn zweiBereiche auf eine Festplatte zugeordnet werden, so werden diese zusammengefasst und soangepasst, dass der gesamte Bereich auf dieser Festplatte fortlaufend ist. Dies ist wichtig,um die Ordnung über den Dateneinheiten aufrecht zu erhalten. Abbildung 11 zeigt wie

Abbildung 11: Zuordnung durch Cut-and-Paste

man sich die 2 Phasen vorstellen muss. Die Assimilierungsfunktion geht allerdings iterativvor. Initial nimmt sie an, dass nur eine Festplatte zur Verfügung steht und weist das ge-samte [0, 1] Intervall dieser Festplatte zu. Im nächsten Schritt geht sie von 2 Festplattenaus und teilt das Intervall auf die beiden Festplatten auf. Dies geschieht so lange, bis dasIntervall auf alle n Festplatten verteilt ist. In Abbildung 12 ist zu sehen wie der Übergang

Abbildung 12: Hinzufügen einer Festplatte

von n− > n + 1 Festplatten vor sich geht. Von jeder der bisherigen n Festplatten wirdder Bereich [1/n, 1/(n + 1)] abgeschnitten und mit dem Bereich von der n-ten Festplatte

162

Page 169: HEINZ NIXDORF INSTITUT Fakultät für Elektrotechnik ... Pottmeyer Memory Limitations in Artificial Intelligence ... Vitter hat gezeigt, dass viele in diesem Modell effiziente Entwicklungen

beginnend auf die neu hinzugekommene (n+1)-te Festplatte verschoben. Diese Vorgehens-weise führt die Assimilierungsfunktion von 1 bis n durch. Den umgekehrten Fall, dass eineFestplatte entfernt werden muss, kann die Cut-and-Past Strategie ähnlich behandeln. Hier-zu wird der letzte Schritt der Assimilierungsfunktion rückgängig gemacht. Abbildung 13

Abbildung 13: Entfernen einer Festplatte - Schritt 1

zeigt, wie die Dateneinheiten von der (n + 1)-ten Festplatte auf die anderen n Festplattenzurück verteilt werden. Jede Festplatte erhält dabei die gleiche Menge an Dateneinheiten,sodass die Lastverteilung sichergestellt ist. Wenn die Dateneinheiten zurückverteilt wur-

Abbildung 14: Entfernen einer Festplatte - Schritt 2

den, werden die Daten von der zu entfernenden Festplatte D2 auf die leere Festplatte Dn+1

kopiert und die Festplatte D2 kann aus dem Speichernetzwerk entfernt werden. Abbildung14 zeigt diesen Vorgang. Es ist nicht möglich die Daten von der zu entfernenden Festplatteeinfach auf die übrigen Festplatten zu verteilen. Dies würde die Ordnung innerhalb der Da-teneinheiten zerstören und ein späteres Aunden von Dateneinheiten im Speichernetzwerkunmöglich machen. Der Zugri auf eine bestimmte Dateneinheit wird über die Simulationder Assimilierungsfunktion von 1 bis n erreicht, was nur durch eine durchgehend aufrechterhaltende Ordnung auf den Dateneinheiten sichergestellt werden kann.

6.1 Analyse

Für die Analyse von adaptiven Datenverteilungsstrategien ist der Begri der competitive-ness wichtig. Dieser vergleicht eine zu analysierende Strategie mit einer optimalen Stra-tegie. Man geht davon aus, dass eine optimale Strategie nur so viele Dateneinheiten ver-

163

Page 170: HEINZ NIXDORF INSTITUT Fakultät für Elektrotechnik ... Pottmeyer Memory Limitations in Artificial Intelligence ... Vitter hat gezeigt, dass viele in diesem Modell effiziente Entwicklungen

schieben muss, wie auf die neue Festplatte gelangen sollen, bzw von der zu entfernendenFestplatte entfernt werden müssen. 1-competetive gibt hierbei an, dass die Strategie ge-nauso gut wie eine optimale Strategie ist.

Betrachtet man das Hinzufügen einer neuen Festplatte in der Cut-and-Paste Strategie,so sieht man, dass nur so viele Dateneinheiten bewegt werden, wie auf die neue Fest-platte müssen. Von jeder anderen Festplatte wird ein kleiner Teil der Dateneinheiten aufdie neue Festplatte verschoben. Daher ist die Cut-and-Paste Strategie 1-competetive beimHinzufügen von weiteren Festplatten. Für das Entfernen einer Festplatte müssen die Da-teneinheiten einmal von der letzten Festplatte auf alle anderen zurückverteilt werden unddanach von der zu entfernenden Festplatte auf die frei gewordene verschoben werden. DieDateneinheiten müssen also 2 mal bewegt werden, wodurch die Cut-and-Paste Strategie2-competetive beim Entfernen einer Festplatte ist.

Die Cut-and-Paste Strategie stellt eine gute Last- und Zugrisbalancierung sicher. DieHashfunktion verteilt die Dateneinheiten gleichmässig auf das [0, 1] Intervall, welches an-schliessend auf die Festplatten verteilt wird. Dies kann mit Hilfe einer Binomialverteilungbetrachtet werden. Das [0, 1] Intervall wird hierbei in Bereiche der Länge l aufgeteilt (wobeil = 1/n gilt). Da das Intervall genau die Länge 1 hat, ist die Wahrscheinlichkeit, dass eineder p Dateneinheiten in einen bestimmten Bereich fällt genau l. Die Wahrscheinlichkeit füreine Dateneinheit nicht in den Bereich zu gelangen ist das Gegenereignis 1−l. Wenn wir nunp Dateneinheiten auf das [0, 1] Intervall verteilen ergibt sich für diesen Bereich eine Anzahlvon p ∗ l Dateneinheiten, aufgrund des Erwartungswertes der Binomialverteilung. Da alleBereiche gleich groÿ sind, ist die Anzahl Dateneinheiten für jeden Bereich p ∗ l. Nun musssichergestellt werden, dass bei Veränderungen der Festplattenanzahl die Lastbalancierungerhalten bleibt. Wenn eine neue Festplatte Dn+1 in das Speichernetzwerk eingeführt wird,wird von jeder der n Festplatten der Bereich [1/n, 1/(n + 1)] abgeschnitten und auf Dn+1

zugeordnet. Hierdurch bleibt auf jeder der n Festplatten noch ein 1/(n + 1)-te Teil des[0, 1] Intervalls. Auf die neue Festplatte gelangt n mal der abgeschnittene Bereich, was

n ∗ [1n− 1

n + 1] = n ∗ 1

n ∗ (n + 1)=

1n + 1

ergibt und somit die Lastbalancierung aufrecht erhält. Beim Entfernen einer Festplatte wirddiese Balancierung ebenfalls nicht verletzt, da das Hinzufügen nur rückgängig gemacht wirdund somit das Speichernetzwerk in den Zustand vor dem Hinzufügen zurückversetzt wird,welcher der Anforderung der Last- und Zugrisbalancierung genügt hat.

Der Zugri auf eine Dateneinheit geschieht, wie weiter oben erwähnt, durch die Simu-lation der Assimilierungsfunktion von 1 bis n Festplatten. Die Laufzeit für diese Simula-tion beträgt O(log n). Hierzu muss man die Anzahl der Verschiebungen einer einzelnenDateneinheit betrachten. Nimmt man eine beliebige Dateneinheit b auf einer beliebigenFestplatte Dn0 , so muss b auf die nachfolgende Festplatte Dn1 verschoben werden, wenn1n1

≤ hn0(b) gilt. Auf Festplatte Dn1 entspricht die Höhe der Dateneinheit b der Höhe imabgeschnitten Bereich von Dn0 , da der Bereich der vorhergehenden Festplatte zuerst aufdie nachfolgende Festplatte zugeordnet wird. Dies entspricht der Höhe hn1(b) ≤ n1−n0

n1∗(n1−1) .

164

Page 171: HEINZ NIXDORF INSTITUT Fakultät für Elektrotechnik ... Pottmeyer Memory Limitations in Artificial Intelligence ... Vitter hat gezeigt, dass viele in diesem Modell effiziente Entwicklungen

Das nächste Mal wird die Dateneinheit b nun bewegt, wenn sie sich im Bereich der Fest-platte Dn1 bendet, welcher auf Dn2 verschoben werden muss. Hierfür muss hn1 ≥ 1

n2

gelten, was mit hn1(b) ≤ n1−n0n1∗(n1−1) und nach n2 umgeformt folgenden Term ergibt:

n2 ≥ dn1 ∗ (n1 − 1)n1 − n0

e.

Um herauszunden wie groÿ die Sprünge der Dateneinheiten beim Verschieben sind, mussdieser Term minimiert werden. Dazu werden für folgende Funktion, welche sich aus demobigen Term ergibt, die Tiefpunkte berechnet

f(n1) =n1 ∗ (n1 − 1)

n1 − n0.

Bildet man für f(n1) die 1te Ableitung f ′(n1), so erhält man die Extrempunkte

n11 = n0 +√

n20 − n0 n12 = n0 −

√n2

0 − n0.

Da Dn1 eine nachfolgende Festplatte von Dn0 sein muss, fällt n12 weg und wir müssen nurn11 betrachten. Durch Einsetzen von n11 in die 2te Ableitung f ′′(n1) ndet man heraus,dass f(n1) bei n11 einen Tiefpunkt besitzt. Aus n11 ergeben sich 2 Werte für n1

n1 = 2 ∗ n0 − 1 und n1 = 2 ∗ n0.

Setzt man die beiden Werte in n2 ≥ dn1∗(n1−1)n1−n0

e ein, erhält man in beiden Fällen

n2 ≥ 4 ∗ n0 − 2.

Dies bedeutet, dass jede 2te Verschiebung einer beliebigen Dateneinheit b auf eine Fest-platte mit einem mindestens 4 mal so groÿen Index geschieht. Hierdurch erhalten wir, dassein Block maximal O(log n) mal verschoben werden muss und somit die Laufzeit für denZugri auf eine Dateneinheit O(log n) beträgt.

Cut-and-Paste ist eine Strategie mit einer guten competitiveness und schnellen Laufzeitbeim Zugri auf die Daten. Ein Nachteil der Strategie liegt in der Homogenität des Sys-tems. Die Autoren haben versucht Cut-and-Paste mit Hilfe von verschiedenen Leveln, jenach Kapazität und Bandbreite, für heterogene Speichernetzwerke zu erweitern. DiesenAnsatz haben sie allerdings nicht weiter fortgesetzt und stattdessen die Strategien SHARE

und SIEVE entwickelt, welche in dieser Ausarbeitung nicht näher beschrieben werden.

7 Zusammenfassung

Die immer gröÿer werdende Menge an zu speichernden Informationen verlangt nach e-xiblen und ezienten Speichersystemen. Einfache Lösungen, welche nur viele Festplattenzusammenfassen, um groÿe Mengen an Kapazität zu gewährleisten, reichen hierfür nichtaus. Speichernetzwerke mit den entsprechenden Strategien zur Verteilung der Daten kön-nen diesen Anforderungen jedoch gerecht werden. Sie bieten Möglichkeiten die Daten ge-schickt innerhalb des Netzwerks zu verteilen, um Datenzugrie schnell abzuarbeiten. Die

165

Page 172: HEINZ NIXDORF INSTITUT Fakultät für Elektrotechnik ... Pottmeyer Memory Limitations in Artificial Intelligence ... Vitter hat gezeigt, dass viele in diesem Modell effiziente Entwicklungen

Parallelität des Festplattenarrays wird hierbei zur Performancesteigerung ausgenutzt. DieStrategien sind hierbei je nach Aufgabenbereich zu betrachten und es gibt bislang kei-ne Allround-Lösung, die alle Anforderungen, welche an Speichersysteme gestellt werden,auf einmal abdeckt. Es müssen Kompromisse in Kauf genommen werden. Ein besondersverbreiteter Ansatz ist hierbei RAID, welches breits 1988 vorgestellt wurde und ein kos-tengünstiges, ausfallsicheres und performantes Verfahren darstellt. Die fehlenden Punktein RAID wurden in vielen Ansätzen versucht zu lösen, haben allerdings bislang nicht die-se starke Verbreitung gefunden. AdaptRaid beschäftigt sich mit dem Problem heterogeneFestplatten ezient zu verwalten, während die Cut-And-Paste Strategie versucht mög-lichst geschickt auf Veränderungen bei der Anzahl der Festplatten im Speichernetzwerkeinzugehen. Diese Ansätze sind bislang eher theoretischer Art und lösen ebenfalls nichtalle Anforderungen auf einmal. Nichtsdestotroz stellen Speichernetzwerke eine exible undeziente Möglichkeit zur Verwaltung von Daten dar.

Literatur

[1] Salzwedel

Algorithms for Memory Hierarchies, Seiten 251-272, Springer-Verlag Berlin Heidel-

berg, 2003

[2] Patterson, Gibson, Katz

A Case for Redundant Arrays of Inexpensive Disks (RAID), University of California,

1988

[3] Cortes, Labarta

A Case for Heterogeneous Disk Arrays, Universitat Politècnica de Catalunya - Bar-

celona, 2000

[4] Cortes, Labarta

Extending Heterogeneity to RAID level 5, Universitat Politècnica de Catalunya -

Barcelona, 2001

[5] Zimmermann, Ghandeharizadeh

HERA: Heterogeneous extension of raid, In H. Arabnia, editor, Proceedings of the

International Conference on Parallel and Distributed Processing Techniques and Ap-

plications, volume 4, Seiten 2159-2165, CSREA Press, 2000

[6] Santos, Muntz

Using heterogeneous disks on a multimedia storage system with random data allo-

cation, Technical Report 980011, University of California, Los Angeles, Computer

Science Department, 1998

[7] Brinkmann, Salzwedel, Scheideler

Ecient, Distributed Data Placement Strategies for Storage Area Networks, Pader-

born University, 2000

166

Page 173: HEINZ NIXDORF INSTITUT Fakultät für Elektrotechnik ... Pottmeyer Memory Limitations in Artificial Intelligence ... Vitter hat gezeigt, dass viele in diesem Modell effiziente Entwicklungen

An Overview of File System Architectures -Multiple Disk Prefetching Strategies for External Merging

David Brucholder

1 Einleitung

Aktuell gibt es fur die Heimanwender sehr schnelle und leistungsstarke Rechner. Teilweise

sind diese sogar schneller als der Bedarf dafur ist. Nichtsdestotrotz gibt es aufgrund der

Masse an Informationen die durch das weltweite Netz fliessen oder die in Datenbanken

verwaltet werden einen immer großeren Bedarf an schnellerer Rechenleistung, Informati-

onslieferung und Auswertung. Obwohl die Rechenleistung heutiger Rechner schon enorm

ist, reicht diese in nichtziviler1 Anwendung teilweise nur unbefriedigend aus. Daher werden

verstarkt Techniken gesucht, die Berechnungen schneller leisten. Dafur gibt es verschiede-

ne Ansatze.

Zunachst ware die verstarkte Nutzung von Caches zu nennen. Man muss wissen, der Ca-

che ist wesentlich schneller als irgendeine Festplatte oder auch der Arbeitsspeicher. Beim

verstarkten Caching wird versucht, viele Informationen im Cache vorzuhalten und die-

se dann schneller als durch einen Lese-/Schreibzugriff (Ein-/Ausgabeoperation) liefern zu

konnen. Das funktioniert so lange, wie der Cache die benotigten Daten vorhalten kann. Da

liegt auch das Problem beim Caching. Da der Cache in der Regel sehr klein im Verhaltnis

zum Massenspeicher Festplatte ist, kann er auch nur relativ wenige Daten vorhalten. Ein

weiteres Problem fur den Cache ist, daß er nicht immer die benotigten Daten vorhalten

kann, da er begrenzt ist, und somit gezielt Daten holen muss, was wiederum teure Ein-

/Ausgabeoperationen bedeutet.

Hier setzt das sogenannte Prefetching ein. Das Prefetching bedeutet das Laden von Daten

in den Cache, bevor sie uberhaupt benotigt werden. Die Herausforderung an dieser Stelle

ist die Technik, die gewahrleistet, daß auch die benotigten Daten in den Cache geladen

werden und nicht irgendwelche.

Eine ganz andere Technik der Leistungssteigerung, oder vielmehr Optimierung der Aus-

nutzung der vorhandenen Leistung ist die Parallelisierung. Das heißt, es soll mehr als eine

Berechnung gleichzeitig durchgefuhrt werden, oder mehr als eine Datenquelle soll Daten

liefern, z.B. in verteilten Datenbanksystemen. Je nach Anwendungsfall ist das eine, das

Andere oder beides von Nutzen.

In dieser Ausarbeitung soll eine Prefetching-Technik vorgestellt werden, eine Zweite wird1zivil≡Heimanwender

167

Page 174: HEINZ NIXDORF INSTITUT Fakultät für Elektrotechnik ... Pottmeyer Memory Limitations in Artificial Intelligence ... Vitter hat gezeigt, dass viele in diesem Modell effiziente Entwicklungen

angerissen, die zum Ziel hat eine moglichst starke Parallelisierung zu ermoglichen sowie

die benotigten Daten im Cache vorhalten zu lassen.

In Abschnitt 3 werde ich eine grobe Ubersicht uber das in Abschnitt 2.2 naher erlauterte

Modell geben. In Abschnitt 2 werde ich einige mathematische Grundlagen dieser Modelle

erklaren. Dazu gehort eine Erlauterung von Markov-Ketten in Abschnitt 2.1 sowie Formeln

und Definitionen in Abschnitt 2.2.1. Anschließend werde ich einen Beweis fur die Funk-

tionalitat des zufallsbasierten Modells liefern. Im Anschluss daran werde ich eine Analyse

des zufallsbasierten Modells in Abschnitt 4 machen sowie anschließend ein paar Ergebnisse

prasentieren. Zum Schluss werde ich eine kleine Zusammenfassung in Abschnitt 5 geben.

2 Mathematische Grundlagen

In diesem Abschnitt werde ich einige mathematische Grundlagen legen um die spater fol-

gende Analyse in Abschnitt 4 zu fundieren.

In Abschnitt 2.1 werde ich den Begriff der Markov-Ketten erklaren. Im darauf folgenden

Abschnitt 2.2 werde ich notwendige Definitionen (2.2.1) auffuhren sowie die Transitions-

arten (2.2.2) erklaren. In Abschnitt 2.2.3 werde ich die fur das Verstandnis notwendigen

Lemmata und Theoreme naher erlautern.

2.1 Markov-Ketten

Um das Verstandnis fur die folgenden Berechnungen zu legen erklare ich hier zunachst den

Begriff Markov-Ketten. Markov-Ketten (i.w. MK) sind mathematische/stochastische Mo-

delle. Sie sind eine Verkettung von Zustanden durch sogenannte Ubergangswahrscheinlichkeiten.

MK sind als Zustandsgraph darstellbar, wie auch in der weiteren Ausarbeitung ange-

nommen. Eine MK besteht aus einer nichtleeren endlichen Menge an Zustanden, dem

sog. Zustandsraum. Jeder Zustand hat einen oder mehrere Folgezustande, der mit ei-

ner bestimmten Wahrscheinlichkeit gewahlt wird. Daraus ist abzuleiten, daß der Folgezu-

stand bzw. die Folgezustande vom aktuellen Zustand abhangig sind. Dies entspricht der

Gedachtnislosigkeit des Prozesses. Diesbezuglich kann man Markov-Ketten in Ordnungen

einteilen. Eine Markov-Kette oder auch ein Markov-Prozess 1. Ordnung liegt vor, wenn

genau der vorherige Zeitpunkt entscheidend fur den Folgezustand ist. Eine 2. Ordnung

liegt vor, wenn mehr als der vorherige Zeitpunkt berucksichtigt wird, sprich: der vorherige

Verlauf ist fur den Folgezustand ausschlaggebend.

Fur die in dieser Ausarbeitung relevanten Modelle liegt eine Markov-Kette 1. Ordnung

vor. Das bedeutet, daß ausschließlich der aktuelle Zustand fur seinen Nachfolgezustand

2

168

Page 175: HEINZ NIXDORF INSTITUT Fakultät für Elektrotechnik ... Pottmeyer Memory Limitations in Artificial Intelligence ... Vitter hat gezeigt, dass viele in diesem Modell effiziente Entwicklungen

relevant ist.

2.2 Formalia

2.2.1 Definitionen

Hier zunachst ein paar Zeichenerklarungen:

Notation Erlauterung

C Große des Caches in Anzahl Blocke

D Anzahl Laufe, synonym fur Anzahl Platten im System

s = [s1, ..., sj , ..., sD] Ganzzahlvektor mit D Komponenten zur Zustandsdarstellung

sj Einzelne Komponente von s

δ(s) = (C −∑D

i=1 si) Anzahl freier Cache-Blocke in s

γ(s) Anzahl der Komponenten aus s die 1 sind

Definition: Zustand

Ein Cache-Zustand s ist ein Ganzzahlvektor s = [s1, ..., sj , ..., sD], und das sj ≥ 1 fur

1 ≤ j ≤ D, γ(s) ≥ 1 und 0 ≤ δ(s) ≤ C −D.

Das bedeutet, daß der Cache immer mit D Blocken (je Lauf mindestens 1 Block) gefullt

ist und mindestens eine Komponente aus s, also ein Lauf, 1 ist.

2.2.2 Transitionsarten

Um von einem Zustand zum nachsten zu kommen gibt es vier verschiedenen Transitions-

arten. Jeder Transition bestimmt aufgrund ihrer Art und Anwendungswahrscheinlichkeit

(entspricht: Ubergangswahrscheinlichkeit) den Folgezustand. Im folgenden werden diese

Transitionsarten naher erlautert.

1. d-Transitionen: Diese Transition steht fur eine einfache Leerung (Depletion). Ein

Block wird aus Lauf j entfernt, unter den Bedingungen, das alle anderen Laufe

mindestens einen Block gefullt haben (gultiger Zustand), und Lauf j mehr als einen

Block gefullt hat.

Formal: sj > 1, Folgezustand t = [s1, ..., sj − 1, ..., sD]

2. f-Transitionen: Diese Transition wird in dem Fall durchgefuhrt, wenn ein Lauf j

vollstandig geleert wird und zusatzlich alle anderen Laufe mindestens einen Block

frei haben bezuglich der Definition gultiger Zustande, siehe Abschnitt 2.2.1. Dabei

wird zunachst der vollstandig geleerte Lauf wieder mit einem Block aufgefullt und

anschließend alle anderen Laufe mit je einem Block. f steht dabei fur fetch.

3

169

Page 176: HEINZ NIXDORF INSTITUT Fakultät für Elektrotechnik ... Pottmeyer Memory Limitations in Artificial Intelligence ... Vitter hat gezeigt, dass viele in diesem Modell effiziente Entwicklungen

Formal: sj = 1 und δ(s) ≥ D − 1,

Folgezustand t = [s1 + 1, ..., sj−1 + 1, 1, sj+1 + 1, ..., sD + 1]

3. r-Transitionen(Replenish): Eine r-Transition existiert nur im deterministischen Mo-

dell. Sie wird durchgefuhrt, wenn ein Lauf j vollstandig geleert wird, und in der

Summe uber alle anderen Laufe nicht alle oder keiner einen Block frei haben. Dann

wird lediglich der geleerte Lauf wieder gefullt. Das entspricht der Situation, das der

Vorzustand gleich dem Endzustand ist.

Formal: sj = 1, δ(s) < D − 1, und Folgezustand t = s

4. p-Transitionen(Partial Fetch): Eine p-Transition kommt nur im zufallsbasierten Mo-

dell vor. Sie wird durchgefuhrt, wenn ein Lauf j vollstandig geleert wird und in

der Summe uber alle anderen Laufe nicht alle oder keiner einen Block frei haben.

Dann wird aus den ubrigen Laufen, die einen Block frei haben zufallig einer gewahlt,

der ebenfalls einen neuen Block gefullt bekommt. Im ungunstigsten Fall (δ(s) = 0)

wird kein weiterer Block gefullt. Damit entsprache diese spezielle p-Transition der

r-Transition im deterministischen Modell.

Formal: sj = 1, δ(s) < D − 1

2.2.3 Lemmata und Theoreme

Ich werde in diesem Abschnitt ein paar mathematische Umformungsregeln auffuhren. Teil-

weise werde ich auf Beweise in [2] verweisen, da hier eine vollstandige Beweiskette den

Rahmen dieser Ausarbeitung sprengen wurde.

Bevor die folgenden Lemmata eingefuhrt werden, mussen zwei Begriffe definiert werden:

1. Partition und 2. Komposition.

Definition: Partition

Eine Partition ist die Bezeichnung fur eine Zahl n ∈ Z+ fur die eine Sequenz von Zahlen

λ1, λ2, ..., λm ∈ Z+ existieren, die aufsummiert n ergeben. Formal:∑m

i=1 λi = n. Die λi

werden auch Teile der Partition genannt.

Definition: Komposition

Eine Komposition ist eine Partition, in der der Grad der Summanden berucksichtigt wird.

Eine Komposition mit m Teilen wird wie folgt geschrieben: [c1, c2, ..., cm], wobei die ci

Teile der Komposition sind und zusatzlich gilt: ci ≥ 1 fur 1 ≤ i ≤ m.

Lemma 1a:[[1],p.54]

4

170

Page 177: HEINZ NIXDORF INSTITUT Fakultät für Elektrotechnik ... Pottmeyer Memory Limitations in Artificial Intelligence ... Vitter hat gezeigt, dass viele in diesem Modell effiziente Entwicklungen

c(m, n) =

n− 1

m− 1

Dieser Wert ist die Anzahl von moglichen Kompositionen von n mit m Teilen.

Lemma 1b:[[1],p.63]

ci(m,n) =

n−m(i− 1)− 1

m− 1

Dieser Wert ist die Anzahl von Kompositionen von n mit m Teilen, wobei alle Teile großer

oder gleich i sind. Daraus laßt sich das folgende Lemma ableiten

Lemma 2:

Die Anzahl der Kompositionen von n durch m Teile, wobei exakt k Teile gleich 1 sind ist

gegeben durch:

1 wenn k = m = n m

k

n−m− 1

m− k − 1

sonst

Definition: Γm(n)

Γm(n) ist die Menge aller Kompositionen von n mit m Teilen, in denen mindestens ein

Teil gleich 1 ist.

Γm(n) = s = [s1, ..., sm]|∑m

k=1 sk = n, sk ≥ 1, γ(s) ≥ 1.

Lemma 3:

|Γm(n)| =

n− 1

m− 1

n−m− 1

m− 1

Das bedeutet, daß die Anzahl der Komponenten in Γm(n) die Differenz zwischen der

Anzahl der Kompositionen von n mit m Teilen und der Anzahl der Kompositionen von n

mit m Teilen ist, bei denen jeder Teil großer oder gleich 2 ist.

5

171

Page 178: HEINZ NIXDORF INSTITUT Fakultät für Elektrotechnik ... Pottmeyer Memory Limitations in Artificial Intelligence ... Vitter hat gezeigt, dass viele in diesem Modell effiziente Entwicklungen

Lemma 4:

∑s∈Γm(j) γ(s) = m

j − 2

m− 2

Das ist die Anzahl der Teile der aus der Menge Γm(j) die 1 sind, aus allen Kompositionen.

Lemma 5:

|Ψm(n)| =

n

m

n−m

m

Das ist die Anzahl aller Zustande, die die Bedingungen aus der Definition fur Zustande

erfullen.

Lemma 6:

∑s∈Ψm(n) γ(s) = m

n− 1

m− 1

Das ist die absolute Anzahl von Teilen aus der Menge Ψm(n) die gleich 1 sind.

Anstatt die Beweise fur die o.g. Lemmata und Definitionen hier aufzufuhren, verweise

ich fur die Definitionen von Partition und Komposition auf [1], Seite 1 und Seite 54.

Ebenso fur die Beweise der Lemmata 1a und 1b verweise ich auf [1] Seite 54 und 63.

Die Beweise fur die anderen Lemmata und Definitionen sind in [3] auf den Seiten 7 bis 11

zu finden.

3 Prefetching-Modelle

Es existieren verschiedene Prefetching-Techniken. Aus dem Bereich der One-Block-Ahead -

Techniken gibt es einfache Techniken, die je nach Modell einen Block im Voraus lesen. Aus

dem Bereich der Victim Caches werden z.B. die Cache Misses zusatzlich berucksichtigt.

Es gibt jedoch noch einige weitere Modelle.

Die beiden Modelle die ich im folgenden Teil vorstellen werde basieren auf einer anderen

Art des Pretching. Die Grundlegende Idee bei diesen Modellen ist die Parallelisierung von

Ein-/Ausgabeoperationen um eine Geschwindigkeitssteigerung zu erlangen. Am Beispiel

6

172

Page 179: HEINZ NIXDORF INSTITUT Fakultät für Elektrotechnik ... Pottmeyer Memory Limitations in Artificial Intelligence ... Vitter hat gezeigt, dass viele in diesem Modell effiziente Entwicklungen

des External Mergesort mochte ich die Funktionsweise vorstellen.

Zugrunde liegt ein Mehrplattensystem. Auf jeder Platte dieses Systems liegt Blockweise

eine sortierte Folge von Zahlen vor. Im weiteren sollen diese Zahlen plattenubergreifend

sortiert werden. Der Cache hat unbegrenzte Große und eine feste Anzahl von Laufen

(Runs), wobei die Anzahl der Laufe der Anzahl der Platten im System entsprechen. Ein

Block enthalt eine sortierte Folge von Zahlen, die sortiert sind. In den Cache werden in

jeden Lauf je ein Block von je einer Platte eingelesen. Dann werden aus den eingelesenen

Blocken aus dem Cache die Zahlen ausgelesen und ubergreifend sortiert. Leert sich dabei

ein Block, wird je nach Zustand eine bestimmte Transition des erneuten Block-Einlesens

erfolgen, oder nicht.

Bevor ich naher auf die beiden Prefetching-Modelle eingehe, ist es wichtig zu wissen,

das ein Zustandsgraph/Markov-Kette2 aufgebaut wird, in dem von einem zum nachsten

Zustand mit verschiedenen Transitionen (mit Ubergangswahrscheinlichkeiten) gewechselt

werden kann. In Abschnitt 2.2.1 ist die Definition eines gultigen Zustands gegeben.

Wichtig ist hierbei zu verstehen, daß jede Transition, die ein Nachfullen eines Blocks

nach sich zieht, eine Ein-/Ausgabeoperation bedeutet und somit einem teueren Lese-

/Schreibzugriff entspricht. Lediglich eine einfache Leerung durch eine d-Transition hat

keine Ein-/Ausgabeoperationskosten. Das einfache Auffullen des geleerten Blocks j bei f-

und p-Transitionen ist eine Demand-Fetch-Operation. Eine f- oder p-Transition bedeutet

je nach Zustand zusatzliche Prefetch-Operation(en) auf allen anderen Laufen, die nicht

geleert wurden, bzw. nur einem zusatzlichen Lauf.

4 Analyse des randomisierten Prefetching-Modells

An dieser Stelle mochte ich einen Begriff einfuhren, der fur das weitere Verstandnis der

Analyse notwendig ist. Ergodizitat bezeichnet in unserem Fall die Tatsache, daß es eine

einmalige und begrenzte Verteilung von Wahrscheinlichkeiten gibt in einem bestimmten

Zustand in der Markov-Kette zu sein, die Unabhangig vom Initialzustand [1,...,1,...,1] ist.

Ergodizitat liegt vor, wenn die Markov-Kette minimal, wiederkehrend Nicht-Null und ape-

riodisch ist. Minimalitat in einer Markov-Kette haben wir dann, wenn es von jedem Zu-

stand einen Transitionspfad zu jedem anderen Zustand gibt. Die Eigenschaft wiederkehrend

Nicht-Null zu sein, liegt dann vor, wenn die mittlere Zeit zur Ruckkehr von einem Zustand

zu sich selbst endlich ist. Die letzte Eigenschaft, die Aperiodizitat hat eine Markov-Kette2siehe 2.1

7

173

Page 180: HEINZ NIXDORF INSTITUT Fakultät für Elektrotechnik ... Pottmeyer Memory Limitations in Artificial Intelligence ... Vitter hat gezeigt, dass viele in diesem Modell effiziente Entwicklungen

dann, wenn ein Zustand nach beliebig vielen Schritten großer gleich einer Konstanten k

zuruckkehren kann. Das ist dann moglich, wenn die Lange des Transitionspfades aufgrund

z.B. von p-Transitionen variieren kann, wobei ein Zustand s auf sich selbst fuhrt (z.B. bei

0 weiteren freien Cache-Blocken, siehe auch Definition von p-Transition). Durch die Eigen-

schaft der Ergodizitat konnen wir also festhalten, daß es fur die Zustande im Dauerzustand

eine Gleichgewichtswahrscheinlichkeit gibt. Wie spater auch noch gezeigt wird, haben alle

Zustande in der Markov-Kette dieser Modelle die gleichen Wahrscheinlichkeiten.

4.1 Zielsetzung

Das Ziel der beiden Prefetchingmodelle, wobei der Fokus wie schon gesagt, beim zufallsba-

sierten Modell liegt, war eine verstarkte Parallelisierung bezuglich der Fetches von Blocken

zu erlangen. Diese verstarkte Parallelisierung mochte ich nun im folgenden durch den Be-

weis der durchschnittlichen Parallelitat des zufallsbasierten Modells zeigen.

Fur das zufallsbasierte Modell gilt:

Lemma 7:

Jeder Zustand der der Definition fur Zustande entspricht, kann vom Initialzustand [1,...,1,...,1]

erreicht werden. Der Beweis dazu steht in [3] auf Seite 11/12.

⇒ Jeder Zustand kann vom Startzustand erreicht werden.

Die Anzahl der Zustande in der Markov-Kette ist C

D

C −D

D

.

Der Beweis dafur ist in [3] Seite 12.

Die Ergodizitat fur die Markov-Ketten fur das randomisierte Modell wird dadurch ge-

zeigt, daß Minimalitat , Nicht-Null-Wahrscheinlichkeit und Aperiodizitat vorliegen. Die

Minimalitat zeige ich dadurch, daß zunachst von einem Startzustand s durch eine Sequenz

von d-Transitionen zum Initialzustand [1,...,1] gegangen wird. Dann wird der Pfad vom

Initialzustand zu einem Zustand t hinzugefugt, der nach Lemma 7 immer erreichbar ist.

⇒ Diese Markov-Kette ist minimal.

Jeder Zustand s hat eine begrenzte Nicht-Null-Wahrscheinlichkeit, daß zu ihm zuruckgekehrt

wird, da es einen endlich langen und nichtleeren Pfad von s zu sich selbst gibt, und alle

Zustandstransitionen eine begrenzte Nicht-Null-Wahrscheinlichkeit haben.

⇒ Diese Markov-Kette ist wiederkehrend Nicht-Null.

Die letzte Eigenschaft, die Aperiodizitat, zeige ich dadurch das es einen Transitionspfad

8

174

Page 181: HEINZ NIXDORF INSTITUT Fakultät für Elektrotechnik ... Pottmeyer Memory Limitations in Artificial Intelligence ... Vitter hat gezeigt, dass viele in diesem Modell effiziente Entwicklungen

gibt, der von einem Zustand s uber einen anderen Zustand t mit 0 freien Blocken fuhrt.

Von diesem Zustand t kann durch eine beliebig oft wiederholte p-Transition der Transiti-

onspfad zu s beliebig verlangert werden, und somit liegt keine Periodizitat vor.

⇒ Diese Markov-Kette ist aperiodisch.

Damit ist die Ergodizitat der Markov-Kette fur das randomisierte Modell gezeigt. Fur den

vollstandigen Beweis verweise ich auf [3] Seite 12.

Um zu zeigen das jeder Zustand die gleiche Wahrscheinlichkeit 1 C

D

C −D

D

be-

sitzt, muß der Beweis erbracht werden, daß jeder Zustand mit der Wahrscheinlichkeit 1

in der Summe aller Wahrscheinlichkeiten der Eingangstransitionen errreicht wird. Dazu

mussen zunachst drei Falle gepruft werden.

1. δ(s) > 0 und 2 ≤ γ(s) ≤ D

2. δ(s) > 0 und γ(s) = 1

3. δ(s) = 0 und γ(s) = D − k

Der erste Fall bedeutet, daß der Cache nicht voll ist und mindestens zwei Laufe nur einen

Block beinhalten. Dieser Zustand kann nur durch eine d-Transition erreicht werden. Es

gibt maximal D Vorzustande. Von jedem dieser Vorzustande kann mit Wahrschinlichkeit

1/D in den Endzustand gewechselt werden. Daraus folgt:

⇒ D(1/D) = 1

Der zweite Fall bedeutet, daß ein nichtvoller Cache-Zustand vorliegt, in dem genau ein Lauf

nur mit einem Block gefullt ist. Dieser Cache-Zustand kann durch f- oder d-Transitionen

erreicht werden. Da ein Lauf genau einen Block gefullt hat, bleiben D-1 Moglichkeiten fur

eine d-Transition oder eine Moglichkeit fur eine f-Transition ubrig.

⇒ (1/D) + (D − 1)/(1/D) = 1

Im dritten Fall ist der Cache voll und D-k (k=max. D-1) Laufe haben genau einen Block

gefullt. Der Zustand kann nur durch f- oder p-Transitionen erreicht werden, da diese bei-

den Transitionsarten als einzige den Cache fullen.

→ D−kD

∑kj=0

k

j

D − 1

j

Fur die vollstandigen Beweise der o.g. drei Falle mochte ich den interessierten Leser auf

[3] Seite 13 und 14 verweisen.

9

175

Page 182: HEINZ NIXDORF INSTITUT Fakultät für Elektrotechnik ... Pottmeyer Memory Limitations in Artificial Intelligence ... Vitter hat gezeigt, dass viele in diesem Modell effiziente Entwicklungen

Damit ist nun zunachst die Gleichwahrscheinlichkeit aller Zustande gezeigt. Im Folgen-

den Teil kann nun die durchschnittlich gefetchte Anzahl von Blocken durch eine Ein-

/Ausgabeoperation berechnet werden, die

C

D

C −D

D

C − 1

D − 1

betragt. Der Beweis dafur

ist in [3] Seite 14 und 15 zu finden.

Wir suchen nun eine geschlossene Form fur die Binomialkoeffizienten. Zunachst der Nen-

ner. Nach Lemma 6 betragt dieser D

C − 1

D − 1

.

Fur den Zahler wird schließlich die Anzahl von Teilen die gleich 1 sind uber aller Zustande

mit C-j freien Blocken berechnet. Die Anzahl betragt nach Lemma 4 D

j − 2

D − 2

.

Zusatzlich mussen noch die gefetchten Blocke berucksichtigt werden. In der Summe kom-

men wir dabei auf folgende Formel:

∑Cj=D(C − j + 1)D

j − 2

D − 2

−∑C−D

j=D (C − j −D + 1)D

j − 2

D − 2

Durch Vereinfachungen und Ersetzungen kann schließlich fur den Zahler folgende Wert

ermittelt werden:

D

[ C

D

C −D

D

]

Die vollstandige Umformung ist in [3] Seite 15.

Jetzt werden Zahler und Nenner zusammengefuhrt:

D

[ C

D

C −D

D

]

D

C − 1

D − 1

C

D

C −D

D

C − 1

D − 1

q.e.d.

Zusammengefaßt bedeutet dies, daß alle Zustande die gleiche Dauerzustandswahrschein-

lichkeit besitzen und dadurch die durchschnittliche Anzahl gefetchter Blocke durch Ein-

/Ausgabeoperationen den oben gezeigten Wert betragt.

10

176

Page 183: HEINZ NIXDORF INSTITUT Fakultät für Elektrotechnik ... Pottmeyer Memory Limitations in Artificial Intelligence ... Vitter hat gezeigt, dass viele in diesem Modell effiziente Entwicklungen

5 Zusammenfassung

Die berechneten Ergebnisse sowie die simulierten Ergebnisse sind in [3] zu finden. Was

sehr interessant ist, ist die Tatsache, daß das zufallsbasierte Modell rechnerisch schlechter

abschneidet als das deterministische Modell, da dort eigentlich der konkurrierende Zugriff

besonders gut zum Tragen kommen mußte. In der Simulation allerdings hat sich gezeigt,

daß beide Modelle ahnlich gut sind und kaum Unterschiede bestehen.

Abschließend kann ich sagen, daß die beiden Modelle (auch wenn in dieser Arbeit nur das

randomisierte Verfahren gezeigt wurde), das zufallsbasierte wie auch das deterministische

Verfahren, sehr interessante Moglichkeiten sind, ein Prefetching durchzufuhren.

Literatur

[1] G.E. Andrews. The theory of partitions. Addison Wesley.

[2] O. Patashnik R.L. Graham, D.E. Knuth. Concrete mathematics. Addison Wesley.

[3] Peter J. Varman Vinay Sadananda Pai, Alejandro A. Schaffer. Markov analysis of

multiple-disk prefetching strategies for external merging. 1992.

11

177

Page 184: HEINZ NIXDORF INSTITUT Fakultät für Elektrotechnik ... Pottmeyer Memory Limitations in Artificial Intelligence ... Vitter hat gezeigt, dass viele in diesem Modell effiziente Entwicklungen

178

Page 185: HEINZ NIXDORF INSTITUT Fakultät für Elektrotechnik ... Pottmeyer Memory Limitations in Artificial Intelligence ... Vitter hat gezeigt, dass viele in diesem Modell effiziente Entwicklungen

Exploitation of the Memory Hierarchy in RelationalDBMSs

Michael Blank

1 Einleitung

Effizienz ist eine grundlegende Anforderung an Softwaresysteme, die große Datenbeständeverwalten und komplexe Funktion darauf anbieten. Mit der Speicherhierarchie heutiger Com-puter wird versucht Lokalität von Daten und Instruktionen auszunutzen, um die Entfernungund die Diskrepanz der Zugriffszeiten zwischen dem Prozessor und den einzelnen Speicher-stufen zu reduzieren. Lokalität ist jedoch keine geschenkte Eigenschaft von Applikationen;komplexe Daten- und Programmstrukturen oder schlechte Programmierung verhindern allzuoft die Lokalitätseigenschaft. Folglich müssen Lokalitätskriterien bereits beim Programment-wurf beachtet werden.Im Rahmen dieser Seminarausarbeitung werden aufbauend auf [UM03] Algorithmen für Da-tenbank Managment Systeme (DBMSs) untersucht. Der Fokus der Algorithmen liegt darin,die zeitliche Lokalität für wiederkehrende Daten und die räumliche Lokalität für zusammen-gehörige Daten auszunutzen, um die Anzahl der Datentransfers von einer Speicherstufe zueiner zum Prozessor näheren Stufe zu reduzieren und damit die Anfrageausführung zu be-schleunigen. In DBMSs können Lokalitätskriterien auf unterschiedliche Systemschichten an-gewandt werden. Diese Ausarbeitung konzentriert sich nur auf die grundlegenden Kompo-nenten, insbesondere auf Algorithmen zur Join-Berechnung und auf effiziente Indexstruktu-ren.

2 Grundlagen

Zum Verstehen dieser Ausarbeitung werden vom Leser Grundkenntnisse über relationale Da-tenbanken und deren Aufgaben vorausgesetzt. Dieses Kapitel soll nur einen kurzen Überblickgeben und für die folgenden Analysen die grundlegenden Definitionen einführen.In DBMSs werden Daten in Relationen in Form von zweidimensionalen Tabellen verwaltet.Eine Zeile (Tupel) einer Relation R, mit t ∈ R, repräsentiert eine Entität; eine Spalte der Ta-belle entspricht einem Attribut der Entität. Die Kardinalität einer Relation R, die |R| abkürzt,entspricht der Anzahl der Zeilen darin. Je nach Größe werden die Tupel derselben Relationzu mehreren in einem Block auf der Festplatte gespeichert. Im Folgenden wird angenommen,dass B Tupel auf einen Festplattenblock passen. Auf die einzelnen gespeicherten Tupeln kannentweder sequentiell über alle Blöcke oder über einen Index zugegriffen werden. Ein Index

179

Page 186: HEINZ NIXDORF INSTITUT Fakultät für Elektrotechnik ... Pottmeyer Memory Limitations in Artificial Intelligence ... Vitter hat gezeigt, dass viele in diesem Modell effiziente Entwicklungen

indiziert eine Relation R über ein Attribut R.a, um bei Punkt- wie auch bei Bereichsanfragenüber R.a schnell die Blöcke mit den gesuchten Tupeln auf der Festplatte zu identifizieren.Mit Hilfe der relationalen Algebra lassen sich Anfragen, in den meisten DBMSs als SQL1,formulieren, um Relationen miteinander zu verknüpfen oder zu reduzieren und komple-xere Informationen daraus herzuleiten. Die Selektion und der Join stellen für die weitereBetrachtung einen Auszug der Operatoren dieser Sprache dar. Bei der Selektion legt eineBedingung eine Auswahl von Tupeln fest, die in die Ergebnismenge aufgenommen werdensollen. Eine Selektion auf einer Relationen R wird durch σBedingung(R) := t ∈ R|t erfülltBedingung formalisiert. Ein Join R ./ S von zwei Relationen R und S bezeichnet eineSelektion mit der Join-Bedingung, die auf dem kartesischen Produkt2 R × S ausgeführtwird, also R ./Bedingung S := σBedingung(R × S). Ein Equi-Join ist ein Spezialfall des Joins mitder Join-Bedingung, dass der Inhalt bestimmter Spalten identisch sein muss. Ein Equi-Joinüber eine Relation R und S bei dem die Attribute R.a und S.b gleich sein müssen, wird mitR a ./ b S abgekürzt.

Eine Anfrage durchläuft in einem DBMS mehrere Komponenten, die jeweils eine spezi-elle Aufgabe erfüllen; eine typische Umsetzung ist in Abbildung 1 dargestellt.

Abbildung 1: Struktur der Anfrageausführung in einem DBMS

Im ersten Schritt wird die gestellte Anfrage geparst und vom Rewriter in eine Normalformtransformiert, die der Optimizer unterschiedlichen Optimierungen unterzieht. Das Ergebnisder logischen Anfrageoptimierung ist ein sogenannter Anfragebaum (Abbildung 2), eine Da-tenstruktur, die den Datenfluss und die relationalen Operatoren äquivalent zur Ausgangsan-frage beschreibt. Jeder Knoten im Anfragebaum steht für einen Operator mit seiner Imple-mentierung. Liegen für denselben Operator unterschiedliche Implementierungen vor, wähltder Optimizer anhand von Metriken die aus, die am meisten Effizienz verspricht.Der Executor ist letztlich für die Ausführung des Anfragebaums zuständig. Beginnend amWurzelknoten werden die Operatorenknoten Tupel für Tupel ausgeführt. Benötigt dabei ein

1Structured Query Language ist eine deklarative Datenbanksprache für relationale Datenbanken und stellt eineReihe von Befehlen zur Definition von Datenstrukturen nach der relationalen Algebra.

2Das Kartesische Produkt R×S ist eine Operation sehr ähnlich dem kartesischen Produkt aus der Mengenlehre.Das Resultat ist die Menge aller Kombinationen der Tupel aus R und S.

180

Page 187: HEINZ NIXDORF INSTITUT Fakultät für Elektrotechnik ... Pottmeyer Memory Limitations in Artificial Intelligence ... Vitter hat gezeigt, dass viele in diesem Modell effiziente Entwicklungen

Knoten weitere Eingabetupel, werden sie von seinen Kindknoten nachgeholt. Dieser Vorgangwiederholt sich bis zu den Blättern des Anfragebaums, wo die Tupel sequentiell oder übereinen Index von der Festplatte eingelesen werden. Diese Art der Datenverarbeitung wirdPipeline-Ausführung genannt, sie verspricht neben des geringen Speicherbedarfs für Zwi-schenergebnisse auch eine schnelle Auslieferung der ersten Endergebnisse.Die Komponente Access Methods abstrahiert vom Executor die physische Organisation derTupel auf der Festplatte und den Zugriff darauf. Das Puffern von bereits eingelesenenTupeln erledigt der Buffer Manager transparent für die darüberliegenden Komponenten. Dertatsächliche Zugriff auf die Festplattenblöcke erfolgt vom Storage Manager.

Die in den Abbildungen 1 und 2 farblich hervorgehobenen Komponenten kennzeich-nen Bereiche, für die im Folgenden Algorithmen vorgestellt werden.Das Kapitel 3 wird unterschiedliche Implementierungen des Join-Operators als Teil vomExecutor und Kapitel 4 den indexierten Zugriff auf Tupeln als Aufgabe der KomponenteAccess Methods vorstellen.

Abbildung 2: Anfragebaum

3 Join-Algorithmen

Für den Join-Operator existiert eine Vielzahl von Implementierungen, die abhängig vom Sze-nario in Einsatz kommen. Weil die vom Join zu verarbeitenden Daten nur selten komplett inden Arbeitspeicher oder in den Cache passen, müssen sie wiederkehrend von der entspre-chend tieferen Speicherhierarchieebene nachgeladen werden. Daher stellt das aufkommendeDatentransfervolumen einen Flaschenhals dieser Algorithmen dar. Eine Abhilfe versprechenEntwurfstechniken, die die Lokalität von Daten ausnutzen.Durch das Blocken von Daten kann zum Beispiel im Nested Loop Join die Anzahl der Daten-transfers intern, zwischen Hauptspeicher und Cache, und extern, zwischen Festplatte undHauptspeicher, reduziert werden. Hier werden Tupeln blockweise verarbeitet, um soweitmöglich die zeitliche Lokalität der im Block eingelesenen Tupeln auszunutzen.Bei den Hash Joins wird die Technik der horizontalen Partitionierung von Daten angewandt. Hierwerden Tupeln nach einem bestimmten Muster in mehrere Teilmengen verteilt und der Joinanschließend nur zwischen zugehörigen Paaren dieser Teilmengen gebildet. Der Vorteil dieserMethode liegt darin, dass nach der Partitionierung die einzelnen Teilmengen im externen Fallnur einmal von Festplatte in den Hauptspeicher eingelesenen werden müssen.

181

Page 188: HEINZ NIXDORF INSTITUT Fakultät für Elektrotechnik ... Pottmeyer Memory Limitations in Artificial Intelligence ... Vitter hat gezeigt, dass viele in diesem Modell effiziente Entwicklungen

3.1 Nested Loop Join

Bei der Berechnung eines Joins über eine Relation R und S mit einer beliebigen Join-BedingungR ./ S verfolgt der Nested Loop Join Algorithmus [PM92] die einfache Idee, für jedes TupeltR ∈ R und jedes tS ∈ R die Join-Bedingung zu überprüfen. Dazu wird für jedes Tupel deräußeren Relation R aus Listing 1 die innere Relation S jedes Mal komplett traversiert, um diepassenden Join-Paare zu finden. Erwartungsgemäß beträgt die Laufzeit des Nested Loop JoinsO(|R||S|). Ausreichend ist diese Laufzeit insbesondere bei Nicht-Equi-Joins mit komplizier-ten Bedingungen, die andere Join-Algorithmen unter Umständen nicht beantworten könnten.Im Wesentlichen wird die Laufzeit jedoch von der Anzahl der externen und der internen Da-tenzugriffen innerhalb der Speicherhierarchie dominiert.Im externen Fall, unter der Annahme, dass mit dem sequentiellen Scan das Einlesen einesFestplattenblocks mit B Tupeln genau eine I/O-Operation benötigt, interessiert uns die Frage,wie oft Blöcke von der Festplatte in den Hauptspeicher geladen werden müssen. Weil für dieäußere Relation |R|

B Blöcke und für jedes Tupel davon die innere Relation komplett mit |S|B

Blöcken eingelesen werden müssen, führt der Nested Loop Join insgesamt |R|B + |R| |S|B I/O-

Operationen aus.Im internen Fall wird dagegen die Anzahl der Zugriffe auf den Hauptspeicher betrachtet,um Tupeln in den Cache für die Abarbeitung durch die CPU zu transferieren. Der NestedLoop Join benötigt hier |R| Zugriffe für die äußere Relation und für jedes Tupel davon jeweils|S| Zugriffe auf alle Tupel der inneren Relation, weil das sequentielle Zugriffsmuster auf Sdie Wiederverwendung bereits gecachter Tupel verhindert. So werden insgesamt |R|+ |R||S|Tupeltransfers vom Hauptspeicher in den Cache verursacht.In beiden Fällen verzeichnet der Algorithmus eine hohe Zugriffslast auf die jeweils nächst-niedrigere Speicherebene der Speicherhierarchie, weil unter anderem die zeitliche Lokalitätvon Daten kaum ausgenutzt wird. Die nachfolgenden Abschnitte behandeln Erweiterungendes Nested Loop Joins, die durch das Blocken von Daten das externe wie auch das interneTransfervolumen reduzieren.

Listing 1: Einfacher Nested Loop Join Algorithmus1 Res := ;2 for each tR in R3 for each tS in S4 if Join -Bedingung erfüllt (tR, tS) then

5 Res := Res ∪ (tR tS);

3.1.1 Externer Blocked Nested Loop Join

Ein wesentlicher Nachteil im I/O-Verhalten des Nested Loop Joins besteht in der fehlendenWiederverwendung von bereits von Festplatte eingeladenen Tupeln. Auch ein womöglichgroßer zur Verfügung stehender Hauptspeicher wird nicht ausgenutzt. Mit dem externenBlocked Nested Loop Join [PM92] werden diese Schwächen weitgehend behoben.Die Idee des Algorithmuses liegt darin, für möglichst große in den Hauptspeicher eingeleseneFragmente der äußeren Relation die innere Relation nur einmal zu traversieren. Das Blocken

182

Page 189: HEINZ NIXDORF INSTITUT Fakultät für Elektrotechnik ... Pottmeyer Memory Limitations in Artificial Intelligence ... Vitter hat gezeigt, dass viele in diesem Modell effiziente Entwicklungen

der äußeren Relation steigert so die zeitliche Lokalität der gelesenen Tupel von R und redu-ziert die Anzahl der Zugriffe auf die innere Relation S.Vor der Ausführung des externen Blocked Nested Loop Joins aus Listing 2 wird zuerst der zurVerfügung stehender Hauptspeicher aufgeteilt. Zum Einlesen der äußeren Relation R wirdmöglichst viel Platz reserviert, es wird angenommen, dass M Festplattenblöcke mit B Tupelndarin in den Hauptspeicherblock bR passen. Der restliche Hauptspeicher muss für einen Fest-plattenblock der inneren Relation S und für die Ergebnisse der Join-Berechnung ausreichen.Die Ausführung des Joins erbringen die vier ineinander verschachtelten Schleifen. In den bei-den äußeren Schleifen (Zeile 2-3) werden M Blöcke von R eingelesen und dafür jeweils nureinmal S traversiert. Den Join berechnen die beiden inneren Schleifen (Zeile 4-7) zwischen denim Hauptspeicher befindenden Tupeln tR ∈ bR und tS ∈ bS nach dem bereits kennengelerntenNested Loop Join Verfahren.Die Laufzeit des Algorithmuses ist gleich der des einfachen Nested Loop Joins, es werdenjedoch deutlich weniger I/O-Operationen benötigt. Das Blocken der äußeren Relation erfor-dert in dieser Variante die Relation S nur noch |R|

MB mal zu traversieren. Die Gesamtanzahlverursachter Festplattenzugriffe beträgt somit |R|

B + |R|MB

|S|B .

Listing 2: Externer Blocked Nested Loop Join Algorithmus1 Res := ;2 for each block bR of R /* |bR| = MB */

3 for each block bS of S /* |bS| = B */

4 for each tR in bR5 for each tS in bS6 if Join -Bedingung erfüllt (tR, tS) then

7 Res := Res ∪ (tR tS);

3.1.2 Interner Blocked Nested Loop Join

Interne Join-Verfahren konzentrieren sich auf die Berechnung des Joins auf Teildaten, diebereits in den Hauptspeicher mittels externer Verfahren transferiert sind. Hier ist das Ziel,die Datenlokalität im Cache zu erhöhen, um die Anzahl der Zugriffe auf den zu cachendenHauptspeicher zu verringern.Im einfachen Nested Loop Join aus Listing 1 rührt das schlechte Cache-Verhalten vom se-quentiellen Zugriff auf die innere Relation S her. Jeder Zugriff auf ein Tupel aus S erzeugtunter Umständen einen Cache-Miss, weil die sequentiell eingelesenen Daten nicht so schnellwiederverwendet werden können, wie sie aus dem Cache wieder verdrängt werden.Der interne Blocked Nested Loop Join [AS94] wirkt durch das Blocken der inneren Relation Sdiesem Problem entgegen. Die Idee ist, die Relation S für jedes Tupel aus R nicht mehr sequen-tiell, sondern blockweise zu traversieren, um auf diese Weise für die in einen Cache-Block ein-gelagerten S-Tupel die Lokalität und die Hit-Rate zu verbessern. Dazu teilt der Algorithmusaus Listing 3 die Relation S zuerst in Bc große Blöcke auf. Es wird im Folgenden angenommen,dass unter einer gegebenen Architektur auf einen Cache-Block Bc viele Tupeln3 von S passen.

3Zur Vereinfachung wird hier die Einlagerung von ganzen Tupeln in den Cache betrachtet. In praktischenAnwendungen werden für den Join nicht relevante Daten extrahiert, um eine möglichst hohe Cache-Lokalität zuerzielen.

183

Page 190: HEINZ NIXDORF INSTITUT Fakultät für Elektrotechnik ... Pottmeyer Memory Limitations in Artificial Intelligence ... Vitter hat gezeigt, dass viele in diesem Modell effiziente Entwicklungen

So erfolgt für jeden Block bS (äußere Schleife in Zeile 2) die Berechnung des Joins mit der ein-fachen Nested Loop Variante (beide inneren Schleifen in Zeile 3-6) zwischen den gecachtenTupeln aus bS und ganz R.Die Reorganisation des Zugriffsmusters auf die innere Relation S verspricht für einen ausdem Hauptspeicher in den Cache geladenen Block bS einen hohen Grad an Wiederverwen-dung ohne Verdrängung und eine erneute Einlagerung. Folglich muss auf alle Tupeln von Snur einmal im Hauptspeicher zugegriffen werden. Dafür resultiert jedoch ein höherer Zugriffauf Tupeln der äußeren Relation R, weil diese komplett für jeden Block bS, wovon es jedochnur |S|

Bcgibt, gelesen wird. Mit insgesamt |S|

Bc|R|+ |S| Zugriffen auf Tupeln im Hauptspeicher

verbessert der interne Blocked Nested Loop Join sein Cache-Verhalten im Vergleich zum ein-fachen Algorithmus. Praktische Untersuchungen in [AS94] ergaben eine Beschleunigung derJoin-Berechnung um bis zu 250%.

Listing 3: Interner Blocked Nested Loop Join Algorithmus1 Res := ;2 for each block bS of S /* |bS| = Bc */

3 for each tR in R4 for each tS in bS5 if Join -Bedingung erfüllt (tR, tS) then

6 Res := Res ∪ (tR tS);

3.2 Hash Join

Hash Joins gehören zu den effizientesten Algorithmen des Join-Operators. In ihrer Wirkungsind sie jedoch nur auf den Equi-Join R a ./ b S mit der Bedingung, dass der Inhalt bestimmterAttribute R.a und S.b identisch sein muss, beschränkt. Genau diese Einschränkung verleihtdem Hash Join jedoch seine Stärke.In den nachfolgenden Abschnitten wird der Fokus auf externen Hash Join Algorithmen liegen,die das Aufkommen von wiederholenden Zugriffen auf die Festplatte optimieren, weil keineder zu joinenden Relation auf einmal in den Hauptspeicher passen. Vorgestellt werden derGrace und der Hybrid Hash Join.

3.2.1 Grace Hash Join

Der Grace Hash Join [MK83] ist ein typischer Divide & Conquer Algorithmus, der die Ein-gabedaten zuerst in disjunkte Teilmengen zerlegt und sie anschließend einzeln der Join-Berechnung unterzieht. Der Algorithmus aus Listing 4 zur Berechnung des Equi-Joins gehtdabei in zwei Phasen vor.In der Build-Phase (Zeile 2-8) werden Tupeln der sogenannten Build-Relation R und der Probe-Relation S durch eine Hash-Funktion h über die Join-Attribute in Partitionen PRh(R.a) undPSh(S.b) eingeteilt, so dass jede Partition PRi der Probe-Relation in den Hauptspeicher passt.Die einzelnen Partitionen werden dabei extern auf der Festplatte zwischengespeichert.

Definition 1. Zwei Partitionen PRi ⊆ R und PSj ⊆ S heißen hash-identisch, wenn i = j gilt,d.h. alle Tupeln darin über denselben Hash-Schlüssel verfügen.

184

Page 191: HEINZ NIXDORF INSTITUT Fakultät für Elektrotechnik ... Pottmeyer Memory Limitations in Artificial Intelligence ... Vitter hat gezeigt, dass viele in diesem Modell effiziente Entwicklungen

Satz 1. Wenn für ein Tupel tR ∈ R mit tR ∈ PRi und ein tS ∈ S mit tS ∈ PSj die Gleichheitüber die Join-Attribute tR.a = tS.b gilt, dann sind PRi und PSj mit i = j hash-identisch.

Beweis. Weil bei Gleichheit von tR.a und tS.b ihre Hash-Schlüssel h(tR.a) und h(tS.a), die dieZuordnung zu entsprechenden Partitionen festlegen, ebenfalls identisch sind, folgt der Satz.

Der Satz 1 liefert eine notwendige Bedingung für die Berechnung von passenden Join-Tupelnzwischen R und S. Demnach können nur Tupel aus den hash-identischen Partitionen PRi undPSj mit i = j die Join-Bedingung erfüllen. Der untenstehende Algorithmus arbeitet die zueinander passenden Partitionen in der Probe-Phase (Zeile 10-15) schrittweise ab, indem zuerstfür die jeweils nächste Partition PRi, die komplett in Hauptspeicher passt, eine Hash-Tabelle(Zeile 12) über die Werte PRi.a aufgestellt wird. Anschließend (Zeile 13-15) werden die einge-lesenen Tupel der hash-identischen Partition PSi sequentiell gegen die Schlüssel in der Hash-Tabelle geprüft, um übereinstimmende Join-Partner zu bestimmen.Weil der vorgestellte Grace Hash Join im Gegensatz zum Nested Loop Join keine verschach-telten Abläufe zwischen den Relationen aufweist und die Abarbeitung der Tupel einer Re-lation von den Tupeln der anderen sauber trennt, beträgt die Laufzeit des AlgorithmusesO(|R| + |S|). Unter Annahme einer Gleichverteilung der Join-Attribute und einer perfek-te Hash-Funktion h für die Partitionierung, sowie, dass pro I/O-Zugriff auf die Festplattegleichzeitig B Tupeln gelesen bzw. geschrieben werden, benötigt die Build-Phase |R|

B + |S|B

Lese-Zugriffe und genauso viele Schreib-Zugriffe, um die Partitionen zwischenzuspeichern.In der anschließenden Probe-Phase kostet das Einlesen der Partitionen von R wieder nur |R|

BI/O-Operationen und, weil jedes S-Tupel nur einmal gegen die Hash-Tabelle geprüft werdenmuss, zusätzlich noch |S|

B Zugriffe auf die Partitionen von S. Somit verursacht der Grace HashJoin Algorithmus insgesamt 3 |R|

B + 3 |S|B I/O-Operationen.

Listing 4: Grace Hash Join Algorithmus für Equi-Join R a ./ b S1 Res := ;2 /* Build -Phase */

3 for each tR in R do

4 i := h(tR.a);5 PRi := PRi ∪ tR;6 for each tS in S do

7 j := h(tS.b);8 PSj := PSj ∪ tS;9

10 /* Probe -Phase */

11 for i := 1 to N do

12 Lese PRi ein und erzeuge Hash -Tabelle über tR.a mit tR ∈ PRi13 for each tS in PSi do

14 for each tR in Hash -Tabelle mit Schlüssel tS.b do

15 Res := Res ∪ (tR tS);

185

Page 192: HEINZ NIXDORF INSTITUT Fakultät für Elektrotechnik ... Pottmeyer Memory Limitations in Artificial Intelligence ... Vitter hat gezeigt, dass viele in diesem Modell effiziente Entwicklungen

3.2.2 Hybrid Hash Join

Der Hybrid Hash Join[Dd84] ist eine Erweiterung vom Grace Hash Join, der das I/O-Verhalten weiter verbessert. Hier wird der Nachteil behoben, dass ein womöglich großer zurVerfügung stehender Hauptspeicher während der Build-Phase nicht ausgenutzt wird. Voll-ständigkeitshalber ist der Algorithmus in Listing 5 angegeben.Die Idee von Hybrid Hash Join liegt darin, die Probe-Phase für die Tupeln der ersten Parti-tion, die im Hauptspeicher ohne zwischenzuspeichern Platz haben, in die Build-Phase vor-zuziehen. Dazu wird bereits während der Partitionierung von R eine Hash-Tabelle über dieder Partition PR1 zugeordneten Tupeln (Zeile 6-7) aufgestellt. Bei der anschließenden Partitio-nierung von S können die der Partition PS1 eingeteilten Tupeln (Zeile 12-14) sofort der Join-Prüfung über die Hash-Tabelle unterzogen werden. Alle anderen Partitionen werden analogzum Grace Hash Join auf der Festplatte gepuffert und in der Probe-Phase paarweise verarbei-tet.Der Hybrid Hash Join verbessert bei gleicher Laufzeit sein I/O-Verhalten im Vergleich zumGrace Hash Join um 2 |PR1|

B + 2 |PS1|B I/O-Operation, die sonst zum Puffern und Wiedereinlesen

der ersten Partitionen benötigt wären.

Listing 5: Hybrid Hash Join Algorithmus für Equi-Join R a ./ b S1 Res := ;2 Erzeuge eine leere Hash -Tabelle

3 /* Build -Phase */

4 for each tR in R do

5 i := h(tR.a);6 if i = 1 then

7 Ergänze Hash -Tabelle um tR mit dem Schlüssel tR.a8 else

9 PRi := PRi ∪ tR;10 for each tS in S do

11 j := h(tS.b);12 if j = 1 then

13 for each tR in Hash -Tabelle mit Schlüssel tS.b do

14 Res := Res ∪ (tR tS);15 else

16 PSj := PSj ∪ tS;17

18 /* Probe -Phase */

19 for i := 2 to N do

20 Lese PRi ein und erzeuge Hash -Tabelle über tR.a mit tR ∈ PRi21 for each tS in PSi do

22 for each tR in Hash -Tabelle mit Schlüssel tS.b do

23 Res := Res ∪ (tR tS);

4 Index B-Bäume

Dieses Kapitel behandelt die physikalische Organisation von Index B-Bäumen im Kontextrelationaler Datenbanksysteme. Insbesondere wird das Kompressionsverfahren der Präfix B-Bäume zur Verbesserung des I/O-Verhaltens vorgestellt.

186

Page 193: HEINZ NIXDORF INSTITUT Fakultät für Elektrotechnik ... Pottmeyer Memory Limitations in Artificial Intelligence ... Vitter hat gezeigt, dass viele in diesem Modell effiziente Entwicklungen

Ein Index indiziert in Datenbanken eine Relation über Werte bestimmter Spal-ten(Schlüsselattribute), um die Suche nach diesen zu beschleunigen. Bei einer Anfragemit einer indizierten Spalte als Suchkriterium bestimmt das Datenbanksystem die Blöckemit den gewünschten Tupeln auf der Festplatte anhand der Indexstruktur, anstatt alleBlöcke sequentiell durchzusuchen. Als Indexstruktur kommt in der Regel ein B+-Baum zurAnwendung, der eine Erweiterung des B-Baumes [RB72] ist.

Abbildung 3: Beispiel einer B-Baum Datenbankindexstruktur für deutsche Kfz-Kennzeichen

Ein B+-Baum, wie in Abbildung 3 dargestellt, ist immer ein vollständig balancierter Baum, dersich aus zwei Arten von Knoten aufbaut, die jeweils auf einen Festplattenblock passen. Dieinneren Knoten, sogenannte Index-Knoten, enthalten Schlüsseln zum Verzweigen auf Nach-folgeknoten und die Blattknoten zum Verweisen auf die indizierten Tupeln. Anders als beieinfachen B-Bäumen werden hier keine Nutzdaten in Knoten gespeichert, nur die Blätter ent-halten Zeiger auf Tupel der indizierten Relation. Eine weitere Eigenschaft vom B+-Baum, diehier nicht weiter betrachtet wird, ist die Verkettung von Blattknoten zu einer linearen Liste,um bei Bereichsanfragen den nächsten Schlüssel aus den benachbarten Blättern nicht wiedervon der Wurzel aus zu suchen.

Definition 2. (Blockstruktur eines Indexknotens)Ein auf einem Block P gespeicherter Indexknoten fasst maximal B sortierte Schlüssel s1, . . . , smder indizierten Spalte auf und verweist mit den Zeigern p0, . . . , pm auf Blöcke P(pi) der Nach-folgeknoten.

P : p0, s1, p1, s2, . . . , si, pi, si+1, . . . , sm, pm

Sei P ein Block mit einem Indexknoten gemäß Definition 2 und T(P) der zugehörige Unter-baum mit Index- und Blattknoten, den P aufspannt, so teilen die Schlüssel von P die Schlüs-selbereiche seiner Unterbäume T(P(pi)) in m + 1 Teilbereiche ein. Für einen Schlüssel x einesUnterbaums T(P(pi)) gilt:

x < si+1 wenn i = 0,si ≤ x < si+1 wenn i = 1, 2, . . . , m − 1,si ≤ x wenn i = m

187

Page 194: HEINZ NIXDORF INSTITUT Fakultät für Elektrotechnik ... Pottmeyer Memory Limitations in Artificial Intelligence ... Vitter hat gezeigt, dass viele in diesem Modell effiziente Entwicklungen

Mit diesem großen Verzweigungsgrad zu maximal B + 1 Unterknoten reduzieren B-Bäumeim Vergleich zu Binärbäumen ihre Baumhöhe h und damit die Anzahl der kostspieligen I/O-Zugriffe bei der Suche nach einem Schlüssel von der Wurzel bis zum Blatt. Folglich benötigtdas Auffinden eines Tupels über den B+-Baum h Lesezugriffe auf Baumknoten und einen I/O-Zugriff auf das Tupel selbst. Die Baumhöhe h ≤ 1 + dlogBNe mit N gespeicherten Schlüsselnhängt vor allem vom konstanten Faktor (Logarithmusbasis), dem Verzweigungsgrad B, ab:Je mehr Schlüssel auf einen Block passen, desto schneller verzweigt die Suche nach einemSchlüssel und erfordert aufgrund geringerer Baumhöhe weniger I/O-Zugriffe.Die für das I/O-Verhalten so wichtige Verzweigungseigenschaft der B+-Bäume ist jedochstark durch die Blockgröße beschränkt. Auch die Schlüssellänge z.B. bei einem Index übereine Textspalte kann die Belegung eines Knotens verringern. Um mehr Platz für Schlüsselbzw. Verzweigungen pro Knoten zu gewinnen, wird häufig Kompression der Schlüsselattri-bute angewandt. Kompression erzielt in B+-Bäumen besonders gute Redundanzreduktion,weil alle Schlüssel eines Knotens in einem vom Vaterknoten definierten Bereich liegen. Imnachfolgenden Abschnitt wird das Kompressionsverfahren der Präfix B-Bäume vorgestellt.

4.1 Präfix B-Bäume

Der Präfix B-Baum [RB77] ist eine Erweiterung des B-Baumes mit dem Ziel, durch Kompressi-on die Baumhöhe und damit die I/O-Zugriffe auf Knoten weiter zu reduzieren. Dazu werdenim Präfix B-Baum Schlüsseln mittels Präfix-Kompression komprimiert, um mehr davon aufeinen Festplattenblock zu bekommen. Die Idee ist, für einen Knoten einen Schlüssel-Präfix zubestimmen, der allen seinen Unerknoten gemeinsam ist, und diesen aus jedem Unterknotenwegen Redundanz zu extrahieren. Das Verfahren verzichtet dabei auf zusätzliche Speiche-rung der Präfixe, sondern ermittelt sie während der Schlüsselsuche von der Wurzel bis zumBlatt. Die Struktureigenschaften des B-Baumes bleiben somit erhalten.Ein Präfix B-Baum ist auf einem Schlüssel-Alphabet mit lexikographischer Ordnung definiert.Sei P weiterhin ein Block mit einem gespeicherten Index-Knoten und T(P) der zugehörigeUnterbaum mit Index- und Blattknoten, den P aufspannt. Die Baumstruktur ordnet jedemBlock P eine größte untere λ(P) und eine kleinste obere µ(P) Schlüssel-Schranke zu, zwischendenen alle möglichen Schlüssel x in T(P) liegen:

λ(P) ≤ x < µ(P).

Sei l0 das kleinste Zeichen des Schlüssel-Alphabets und ∞ größer als jedes andere Zeichen,dann gilt für den Block R mit dem Wurzelknoten des Präfix B-Baumes:

λ(R) = l0, µ(R) = ∞.

Um λ und µ für andere Knoten zu definieren, sei P ein Index-Knoten nach der Definition 2 mitden unteren und oberen Schranken λ(P) und µ(P). Dann lassen sich die Schranken λ(P(pi))und µ(P(pi)) für die Unterknoten P(pi), mit λ(pi) und µ(pi) abgekürzt, rekursiv aus denSchlüsseln und Schranken von P definieren:

λ(pi) =

si wenn i = 1, 2, . . . , m,λ(P) wenn i = 0,

µ(pi) =

si+1 wenn i = 0, 1, . . . , m − 1,µ(P) wenn i = m.

188

Page 195: HEINZ NIXDORF INSTITUT Fakultät für Elektrotechnik ... Pottmeyer Memory Limitations in Artificial Intelligence ... Vitter hat gezeigt, dass viele in diesem Modell effiziente Entwicklungen

Weil alle Schlüsseln eines Unterbaums T(pi) im Bereich zwischen der untersten und oberstenSchlüssel-Schranke eingeschlossen sind, müssen sie offensichtlich alle einen gemeinsamen,unter Umständen auch einen leeren, Präfix κ(pi) haben. Sei ki der längste gemeinsame Prä-fix von λ(pi) und µ(pi), so lautet der Präfix κ(pi) von P(pi), der allen Schlüsseln in T(pi)gemeinsam ist

κ(pi) =

kilj wenn λ(pi) = kiljz und µ(pi) = kilj+1, wobei z ein beliebiges Wort und lj+1

das unmittelbar nächste Zeichen nach lj in Alphabetordnung ist,ki sonst.

Die Definition von κ(pi) erlaubt in der ersten Alternative ki um ein zusätzliches Zeichen lj zuverlängern, weil aus der Definition der Schranken alle möglichen Schlüsseln x in T(pi) nur imBereich kiljz ≤ x < kilj+1 liegen können und folglich alle den gemeinsamen Präfix kilj haben.Sowohl λ(pi) und µ(pi), und damit auch κ(pi), sind allein aus der Traversion des Baumes vonder Wurzel bis zum Knoten P(pi) bestimmbar und müssen nicht separat gespeichert wer-den. Die Kompression des Unterbaums T(pi) erfolgt dadurch, dass aus jedem darin enthal-tenen Schlüssel der Präfix κ(pi) extrahiert und nur der Rest gespeichert wird. Somit kannein komprimierter Indexknoten P gemäß Definition 3 mehr Schlüsseln pro Block aufnehmen.Wodurch der Präfix B-Baum, wie in Abbildung 4 dargestellt, eine kleinere Baumhöhe undweniger I/O-Zugriffe als der B+-Baum erzielt.

Definition 3. (Blockstruktur eines komprimierten Indexknotens)Ein Indexknoten P eines Präfix B-Baumes speichert im Gegensatz zur Definition 2 die Schlüs-seln s1, . . . , sm komprimiert ab. Das Komprimat si eines Schüssels si ergibt sich aus dem Weg-lassen des gemeinsamen Präfixes, also si = κ(P)si.

P : p0, s1, p1, s2, . . . , si, pi, si+1, . . . , sm, pm

Die Suche nach einem Schlüssel x im Präfix B-Baum verläuft identisch wie im B-Baum ab.Knoten müssen dazu nicht dekomprimiert werden. Die richtige Verzweigung zu Nachfolge-knoten in einem Knoten P wird anhand des vom Präfix κ(P) befreiten Hilfsschlüssels x mitx = κ(P)x ermittelt. Denn wenn x in T(P) liegt, muss es den Präfix κ(P) haben. Dadurch kannzusätzlich die Binärsuche auf den kürzeren Schlüsseln innerhalb eines Knotens profitieren.Analog zu B-Bäumen kann es bei Einfüge- oder Löschoperationen im Präfix B-Baum zu Auf-teilung, Verschmelzung oder Verschiebung von Knoten kommen, um Bedingungen für dieGewichtsbalance aufrechtzuerhalten. Dabei müssen unter Umständen Korrekturen an denPräfixen und komprimierten Schlüsseln vorgenommen werden.Bei Aufteilung eines Knotens P in P′ und P′′ können die neuen Präfixe κ(P′) und κ(P′′) längerals κ(P) und die komprimierten Schlüsseln in den neuen Knoten kürzer ausfallen.Anstatt einen vollen Block P aufzuteilen, kann der Überlauf an Schlüsseln in den Bruderkno-ten T verschoben werden. Infolgedessen sich der Präfix κ(P) verlängern und κ(T) verkürzenbzw. die Schlüssel-Kompression in P verbessern und in T verschlechtern kann.Werden zwei Knoten P und T zu einem neuen Knoten Q verschmolzen, vergrößert sich wo-möglich der Schlüsselbereich in Q, was zu kürzerem Präfix und schlechterer Kompression inQ führt.

189

Page 196: HEINZ NIXDORF INSTITUT Fakultät für Elektrotechnik ... Pottmeyer Memory Limitations in Artificial Intelligence ... Vitter hat gezeigt, dass viele in diesem Modell effiziente Entwicklungen

Zusammengefasst erzielen Präfix B-Bäume eine hohe Redundanzreduktion ohne erheblichenMehraufwand und ohne größere Änderung an der Struktur einfacher B-Bäume vorzunehmen.Dazu haben experimentelle Untersuchungen in [RB77] gezeigt, dass durch die Kompressionerzielte Verdichtung der Schlüssel zur Senkung der Baumhöhe und bis zu 25% weniger I/O-Zugriffen führt.

Abbildung 4: Beispiel eines Präfix B-Baumes aus Abbildung 3 (Für jeden Block P ist links λ(P),rechts µ(P) und darüber κ(P) abgebildet)

5 Zusammenfassung

In dieser Ausarbeitung wurden Algorithmen und Konzepte für DBMSs vorgestellt, die sichmit Berechnung von Join-Anfragen und dem indexierten Zugriff auf Daten befassen. Ein Pro-blem dieser Algorithmen ist die große Datenmenge, von der nur ein Bruchteil gleichzeitig inden Hauptspeicher oder in den Cache passt. Die Folge sind wiederholte Datentransfers in derSpeicherhierarchie von einer Speicherstufe zu einer anderen, die die vorgestellten Algorith-men mittels Lokalitätskriterien versuchen zu reduzieren.Für die Berechnung des Joins wurden zwei Kategorien von Algorithmen betrachtet. DerNested Loop Join für beliebige Join-Bedingungen wurde in einer I/O- und einer Cache-optimierter Version vorgestellt. Das Blocken von Daten im Hauptspeicher bzw. im Cache er-zielt hier eine höhere zeitliche Lokalität.Im Rahmen der Hash Joins, die nur beim Equi-Join zum Einsatz kommen, wurden der Graceund der Hybrid Algorithmus für das externe Szenario behandelt. Bei beiden wird mit derhorizontalen Partitionierung von Daten ein zu Eingabedaten lineares I/O-Verhalten erreicht.Um den Zugriff auf Tupel auf der Festplatte über einen Index zu beschleunigen, wurde derEinsatz von Index B-Bäumen in Datenbanken vorgestellt. Aufgrund des hohen Verzwei-gungsgrades von B-Bäumen erlauben sie auch bei großen Datenmengen ein Tupel überein Schlüssel mit sehr wenigen I/O-Zugriffen aufzufinden. Einen noch höheren Verzwei-gungsgrad, somit besseres I/O-Verhalten, erreichen Präfix B-Bäume durch Kompression derSchlüssel. Die Kompression bewirkt hier eine höhere räumliche Lokalität von zusammenge-höriger Schlüssel.

190

Page 197: HEINZ NIXDORF INSTITUT Fakultät für Elektrotechnik ... Pottmeyer Memory Limitations in Artificial Intelligence ... Vitter hat gezeigt, dass viele in diesem Modell effiziente Entwicklungen

Literatur

[AS94] A. SHATDAL, C. KANT, J. F. NAUGHTON: Cache conscious algorithms for relational queryprocessing. Seite 510–521. In Proceedings of the 20th Int’l. Conference on Very LargeDatabases, 1994.

[Dd84] D. DEWITT, R. KATZ, F. OLKEN L. SHAPIRO M. STONEBREAKER D. WOOD: Imple-mentation techniques for main memory database systems. Seite 1–8. In Proceedings of theSIGMOD Int’l. Conference on the Management of Data, 1984.

[MK83] M. KITSUREGAWA, H. TANAKA, T. MOTOOKA: Application of hash to database machineand its architecture. Seite 66–74. New Generation Computing, 1983.

[PM92] P. MISHRA, M. EICH: Join processing in relational databases. Seite 63–113. ACM Com-puting Surveys, 1992.

[RB72] R. BAYER, E. M. MCCREIGHT: Organization and maintenance of large ordered indexes.Seite 173–189. Acta Informatica, 1972.

[RB77] R. BAYER, G. UNTERAUER: Prefix B-Trees. Seite 11–26. ACM Trans. on Database Sys-tems, 1977.

[UM03] U. MEYERS, P. SANDERS, J. SIBEYN: Algorithms for Memory Hierarchies. Springer, 2003.

191

Page 198: HEINZ NIXDORF INSTITUT Fakultät für Elektrotechnik ... Pottmeyer Memory Limitations in Artificial Intelligence ... Vitter hat gezeigt, dass viele in diesem Modell effiziente Entwicklungen

192

Page 199: HEINZ NIXDORF INSTITUT Fakultät für Elektrotechnik ... Pottmeyer Memory Limitations in Artificial Intelligence ... Vitter hat gezeigt, dass viele in diesem Modell effiziente Entwicklungen

Ausarbeitung zum SeminarVerteilte Algorithmen

bei Prof. Meyer auf der Heide

Parallel Bridging Modelsund ihre Emulation

Martin KloseMatr.-Nr 6147053

[email protected]

Paderborn, WS 2006/2007

193

Page 200: HEINZ NIXDORF INSTITUT Fakultät für Elektrotechnik ... Pottmeyer Memory Limitations in Artificial Intelligence ... Vitter hat gezeigt, dass viele in diesem Modell effiziente Entwicklungen

1 Einleitung

Die vorliegende Ausarbeitung geht vor allem auf den Aspekt der Modelle zur Entwicklung von Algorith-men für parallele Rechenmaschinen ein, wie sie in [1] angesprochen worden sind. Außerdem sind wei-terführende Literaturhinweise genutzt worden um die Modelle ausführlicher zu betrachten. Zum Schlusswird die gegenseitige Emulation der verschiedenen Modelle erläutert.

2 Parallel Bridging Models

Zur Analyse paralleler Algorithmen gibt es bereits ein Modell nämlich das PRAM1-Modell [2]. Es hatjedoch einige Nachteile. Im PRAM verfügt jeder der p Prozessoren über einen eigenen lokalen Speicher.Darüber hinaus gibt es einen beliebig großen globalen Speicher, auf den alle Prozessoren zugreifen kön-nen (siehe Abbildung 1) Im PRAM-Modell sind die Zugriffskosten auf lokalen oder globalen Speicher,sowie Berechnungen des einzelnen Prozessors gleich teuer. Es bildet aber die realen Eigenschaften paral-leler Computer unzureichend ab. Denn diese habe in der Regel eine beschränkte Datenübertragungsratezwischen den einzelnen Prozessoren und Speichern. Es gibt einen Zuschlag für die Kommunikation mitden anderen Prozessoren, sowie auch eine Verzögerung dabei. Das PRAM-Modell hingegen hat dieseBeschränkungen nicht. Dies kann dazu führen, dass mit PRAM entwickelte Algorithmen einen hohenKomunikationsaufwand haben. Dieses Problem entsteht dadurch, dass die Kommunikation nicht teurerals lokale Operationen ist, und die Versuchung besteht viel zu kommunizieren. Daraus folgt aber, dassdann solche Algorithmen auf realen Maschinen schlechte Performanz haben.

Eine neuere Klasse von Modellen stellen die Parallel Bridging Models (PBM) [3] dar. Ziel der PBMist es, ein besseres Modelle für parallele Computer darzustellen, welches gleichzeitig unabhängig von derzugrunde liegender Hardware ist, aber dennoch eine gute Vorhersage für die reale Laufzeit von Algo-rithmen liefert. Sowie das von Neumann-Modell ein abstraktes Modell für Computer ist und eine Brücke(engl. bridge) zwischen der Hardware und Software eines einzelnen Computers schlägt, so soll das PBMeine Brücke zwischen einem parallelen Computer mit mehreren Prozessoren und den Algorithmen (Soft-ware) sein. Dadurch soll es möglich sein (also ohne die konkrete (Ziel)-Architecktur zu berücksichtigen)nur anhand des PBM einen Algorithmus zu entwickeln, der auf allen möglichen PBM Architeckturenlauffähig ist und dessen Laufzeit der mit dem Modell bestimmten Laufzeitabschätzung entspricht.

Ein PBM sollte folgende Aspekte berücksichtigen:

Kostenbemessung Ein PBM sollte über eine Kostenbemessung verfügen, um die Entwicklung vonAlgorithmen anzuleiten und eine adäquat Laufzeitvorhersage liefern. Außerdem sollte es unabhän-gig von einer konkreten Architecktur sein, aber dennoch die Grundzüge eines parallelen Computerswiderspiegeln.

Universelle Effizienz PBM-Algorithmen sollten nicht übermäßig an Performanz einbüßen, wenn erauf einer konkreten Maschine ausgeführt wird. Wünschenswert ist ein konstanter Faktor an Ver-langsamerung zwischen dem PBM und einer Maschine, dadurch wird es Möglich Algorithmen nurfür das PBM zu entwickeln ohne die Zielplattform zu berücksichtigen.

Neutralität und Portabilität Ein PBM sollte sich neutral gegenüber der Anzahl der Prozessoren ver-halten, so dass nicht nur Maschinen mit vielen, sondern auch welchen mit wenigen Prozessorengenügend abgedeckt werden. Es sollte darüber hinaus möglichst weit von parallelen Maschine ab-strahieren, so dass Details wie Speicherverwaltung etc. nicht berücksichtigt werden. Dadurch solles auch ein gute Modell für die Entwicklung von Algorithmen sein.

1parallel random access machine

1

194

Page 201: HEINZ NIXDORF INSTITUT Fakultät für Elektrotechnik ... Pottmeyer Memory Limitations in Artificial Intelligence ... Vitter hat gezeigt, dass viele in diesem Modell effiziente Entwicklungen

globaler Speicher

lokaler

Speicher

lokaler

Speicher

lokaler

Speicher

1P 2P pP

Abbildung 1: Eine PRAM-Maschine besteht aus p Prozessoren, die jeweils einen eigenen lokalen Spei-cher haben, und aus einem unbegrenzten globalen Speicher auf den alle Prozessoren zu-greifen können.

Parallele Abschwächung Damit ist gemeint, dass Algorithmen, die für v virtuelle Prozessoren ge-schrieben sind, optimal auf auf p realen Prozessoren laufen, wenn p ein bisschen kleiner als v ist.(z.B. v = p log p).

2.1 Bulk Synchronous Parallel Model (BSP)

Nennen wir einen Computer, dem das bulk synchronous parallel model ([4]) zugrunde liegt, BSP-Maschine.Nachfolgend werden die Eigenschaften einer solchen BSP-Maschine beschrieben. Eine solche Maschi-ne besteht aus p Prozessoren, welche jeweils einen eigenen lokalen Speicher haben und durch einenKommunikations-Mechanismus untereinander verbunden sind. Abbildung 2 verdeutlicht den physikali-schen Aufbau. In der Tabelle 1 sind die Parameter einer BSP-Maschine enthalten. Wie bereits erwähnt,ist p die Anzahl der Prozessoren oder die Größe der Maschine2.Der Ablauf eines Algorithmus auf ei-ner BSP-Maschine wird in so genannte supersteps unterteilt. Nach jedem dieser supersteps wird eineSynchronisation der Prozessoren durchgeführt, bei der die im vorangegangenen superstep verschicktenNachrichten zugestellt werden. Den Aufwand dieser Synchronisation bezeichnet der Parameter L. DieKosten der Verschickung einer Nachricht liefert der Parameter g. Es müssen mindestens g Zeiteinheitenvergehen, bevor ein Prozessor eine weitere Nachricht verschicken kann.

Im BSP-Modell besteht die Berechnung eines Problems aus supersteps, welche in Abbildung 3 dar-gestellt sind. Während eines supersteps findet die lokale Berechnung eines jeden Prozessors auf seinemjeweiligen lokalen Speicher statt (graue Balken). Außerdem werden Nachrichten zwischen den Prozes-soren verschickt (dünne Linien). Auf der linken Seite findet das Verschicken statt, auf der rechten Seitedas Empfangen. Die Nachrichten werden erst nach der Synchronisation endgültig zugestellt, so dass dieverschickten Nachrichten immer erst im nächsten superstep t + 1 verfügbar sind.

In Tabelle 2 sind die wichtigsten Eigenschaften einer BSP-Maschine dargestellt. Die lokale Berech-nung wi,t entspricht den grauen Balken in der Abbildung 3. Um die Laufzeit eines Algorithmus auf einerBSP-Maschine zu bestimmten, brauchen wir zuerst die Laufzeit eines einzelnen supersteps. Die längstelokale Berechnung im superstep t ist wt (längster graue Balken in Abbildung 3). Danach findet die Nach-richtenübertragung statt. Sie ist von der Anzahl der empfangenen Nachrichten (µi,t) und der verschickten

2engl. the size of the machine

2

195

Page 202: HEINZ NIXDORF INSTITUT Fakultät für Elektrotechnik ... Pottmeyer Memory Limitations in Artificial Intelligence ... Vitter hat gezeigt, dass viele in diesem Modell effiziente Entwicklungen

p Anzahl der ProzessorenL Nachrichten-Latenz/Synchronisationg Kostenparameter für das Nachrichten-Routing

Tabelle 1: Parameterüberblick einer BSP-Maschine [4]

Prozessor i (pi) in superstep t

wi,t lokale Berechnung von pi

µi,t Anzahl der empfangenen Nachrichten von pi

λi,t Anzahl der verschickten Nachrichten von pi

wt = maxi wi,t Größte lok. Berechnung aller Prozessoren in superstep thi,t = maxλi,t, µi,t Maximum der empfangenen/verschickten Nachrichten von pi

ht = maxi hi,t Maximum der empfangenen/verschickten Nachrichten aller Prozessorenwt + g · ht + L Kosten von superstep t

Tabelle 2: Laufzeitgrößen einer BSP-Maschine [4]

Nachrichten (λi,t) der einzelnen Prozessoren pi abhängig. Für die Dauer der Übertragung in einem super-step ist die Übertragung mit den meisten Nachrichten ausschlaggebend. Diese findet entweder bei demeinem Prozessor statt, der die meisten Nachrichten verschickt oder aber bei dem einen Prozessor, der diemeisten Nachrichten entgegen nimmt. Die größte (meiste Anzahl von Nachrichten) Übertragung wird mitht bezeichnet. Darin sind jedoch noch nicht die Kosten g einer Übertragung berücksichtigt, Damit folgtfür die Übertragungskosten g · ht. Nach dem Übertragen werden die Prozessoren synchronisiert und dieNachrichten endgültig zugestellt. Das kostet L. Daher folgt für die Kosten eines einzelnen superstepswt + g · ht + L.

Die Laufzeit-Anaylse eines BSP-Algorithmus erfolgt aus der Berechnung der Kosten der einzelnensupersteps. Ein Algorithmus, der T supersteps benötigt, um zu terminieren, vollführt lokale Berechnun-gen im Umfang von W =

∑1≤t≤T wt und hat einen Kommunikationsaufwand von H =

∑1≤t≤T ht.

Außerdem wird T mal die Synchronisation (nach jeden superstep) vollzogen. Daraus ergibt sich für dieLaufzeit W + g · H + T · L

Wenn Tseq die Zeit für den besten Algorithmus zu einem gegebenen Problem ist, dann sucht manidealerweise einen BSP-Algorithmus für den gilt: W = c · Tseq/p,L · T = o(Tseq/p) und g · H =o(Tseq/p) für eine kleine Konstante c ≥ 1. In Worten ausgedrückt heißt das, dass die Berechnung mit demBSP-Algorithmus p mal so schnell (mit einem konstanten Verzögerungsfaktor c) wie im sequentiellenFall sein soll. Die zusätzlichen Kosten für Kommunikation und Synchronisation sollen nicht größer seinals Tseq in Relation zur der Anzahl der Prozessoren p. Ein BSP-Algorithmus, für den die genanntenBedingungen zutreffen, wird c-optimal genannt.

2.2 LogPAuch wenn jährlich die Prozessoren schneller und die Speicher größer werden, besteht kontinuierlich einProblem bei parallelen/verteilten Systemen: Die Latenz, der Kommunikationszuschlag sowie die begrenz-te Datenübertragungsrate des Verbindungsnetzwerks zwischen den einzelnen Prozessoren/Speichern sindimmer geringer als der Zugriff auf lokale Ressourcen. Somit entsteht ein entscheidendes Nadelöhr beiparallelen Prozessen. Das LogP-Modell ([5], [6]) berücksichtigt daher besonders den Kommunikations-aufwand zwischen den beteiligten Prozessoren und ignoriert hingegen die lokalen Berechnungen. DiesesModell beschreibt ein System aus verteiltem Speicher und Prozessoren (siehe Abbildung 4) LogP hatfolgende Parameter:

3

196

Page 203: HEINZ NIXDORF INSTITUT Fakultät für Elektrotechnik ... Pottmeyer Memory Limitations in Artificial Intelligence ... Vitter hat gezeigt, dass viele in diesem Modell effiziente Entwicklungen

630 F. Meyer auf der Heide and R. Wanka

Interconnection Mechanism

Mem

ory

Proce

ssor

PP P1 2 p

(a)

t

P P PP P

L

1 2 3 4 p

w

w

Tim

e

(b)

Sup

erst

epS

uper

step

+ 1

tt

t +1

tg · h

tg · h +1

……

……

L

Fig. 1. (a) A BSP computer and (b) the execution of a BSP algorithm.

the current superstep. Lethi,t = maxµi,t,λi,t.This superstep is finished by executing abarrier synchronization. Summarizing over all processors, we introduce the parameterswt = maxi wi,t and ht = maxi hi,t. If an algorithm performsT supersteps, we useW =

∑1≤t≤T wt andH =

∑1≤t≤T ht. W is called the local work of the algorithm,

H its communication volume. Note that the size of the packets sent is not taken intoaccount. In the course of analyzing a BSP algorithm, the task is to determine concretevalues forT , H, andW .

The actual time that a BSP machine needs to execute the above BSP algorithm de-pends on the following machine parameters:L, thelatency, andg, thegap, orbandwidthinefficiency. L is the maximum time that a message sent from a processorPi needs toreach processorPj , taken over alli andj. Likewise,L is also the time necessary for asingle synchronization. Every processor can put a new packet into the interconnectionmechanism afterg units of time have been elapsed. Concrete values ofg andL canbe measured by experiments. For a different platforms catalogue, see [14]. The thirdmachine parameter isp, thenumber of processors, or the size of the machine.

Hence, the runtime of thetth superstep is (at most)wt + g ·ht +L, and the overallruntime is (at most)W +g ·H +L ·T .

Note that we consider sums of times although it is often sufficient to only considerthe maximum of the involved times when, e. g., pipelining can be used. This only resultsin a constant factor-deviation, whereas it simplifies many analyses considerably.

Let Tseq be the runtime of a best sequential algorithm known for a problem. Ideally,we are seeking BSP algorithms for this problem whereW = c ·Tseq/p,L ·T = o(Tseq/p),andg ·H = o(Tseq/p), for a small constantc ≥ 1. Such algorithms are calledc-optimal.There are two popular ways to represent results of a BSP analysis. First, values ofT , H,andW are given. For example, see Theorem 1 below. The other way is to state (withndenoting the input size) for which ranges ofn/p, g, andL the algorithm is1-optimal.Theorem 2 concluded from Theorem 1 is presented in this way.

Abbildung 2: BSP-Maschine mit p Prozessoren. Jeder besitzt einen eigenen Speicher (engl. Memory)und ist über einen Kommunikations-Mechanismus mit den anderen Prozessoren verbunden.Quelle:[1]

330 Massimo Coppola and Martin Schmollinger

P1

P3

P2

Pp

w t g h t

P1

P3

P2

Pp

L

...

superstep t+1 f(n) g(n)work

com

m. /

mer

ge

deco

mpo

sitio

n

...

s(n)f(n)

deco

mpo

sitio

n

mer

geFig. 15.3. (a) BSP superstep execution (b) CGM supersteps

by barriers (i.e. all units must complete a superstep before any of them canproceed to the next superstep), we can estimate the length of a superstepin time units as wt + g · ht + L. This value becomes an upper bound if weassume instead that synchronization is only enforced when actually needed(e.g. before receiving a message).

We can analyze a BSP algorithm by computing wt and ht for each super-step. If the algorithm terminates in T supersteps, the local work W =

twt

and the communication volume H =∑

tht of the algorithm lead to the cost

estimate W + g · H + L · T . A more sound evaluation compares the perfor-mance of the algorithm with that of the best known sequential algorithm.Let Tseq be the sequential running time, we call c-optimal a BSP algorithmthat solves the problem with W = c · Tseq/p and g ·H + L · T = o(Tseq/p) fora constant c.

Other parallel bridging models have been developed. Among them wemention the CGM model, which is the closest to the BSP, the LogP and theQSM models, which we describe below.

The Coarse-Grained Multicomputer. The coarse-grained multicomputer

(CGM) model [245] is based on supersteps too. The communication phase inCGM is different from that of BSP, as it involves all processors in a globalcommunication pattern, and O(n) data are exchanged at each communica-tion phase. In Fig. 15.3b the different patterns are the f, g, s functions. Onlytwo numeric parameters are used, the number of nodes p and the problemsize n. Each node has thus O(n/p) local memory.

In the original presentation the model was parametric, as the networkstructure was left essentially unspecified. The communication phases wereallowed to be any global pattern (e.g. sorting, broadcasts, partial sums) whichcould be efficiently emulated on various interconnection networks. To get theactual algorithmic cost, one should substitute the routing complexity of theparallel patterns on a given network (e.g. g(n, p) may be the complexity ofexchanging O(n/p) keys in a hypercube of diameter log2 p).

The challenge in the CGM model is to devise a coarse-grain decompositionof the problem into independent subproblems by exploiting a set of “portable”global parallel routines. The best algorithms will usually require the smallest

Abbildung 3: Im BSP-Modell wird beim Ausführen eine Folge von Schritten abgearbeitet, die so genann-ten supersteps. BSP supersteps bestehen aus einer lokalen Berechnung (wt), dem Verschi-cken und Empfangen von Nachrichten (g ·ht) und der abschließenden Synchronisation (L).Danach folgt der nächste suoerstep t + 1. Quelle:[4]

4

197

Page 204: HEINZ NIXDORF INSTITUT Fakultät für Elektrotechnik ... Pottmeyer Memory Limitations in Artificial Intelligence ... Vitter hat gezeigt, dass viele in diesem Modell effiziente Entwicklungen

L beschreibt die Latenz-Obergrenze (engl. latency) für das Verschicken einer (kleinen) Nachricht voneiner Speicher/Prozess-Einheit zu einer anderen.

o ist der Kommunikationszuschlag (engl. overhead), der notwendig ist, damit ein Prozessor eine Nach-richt sendet oder empfängt. In dieser Zeit ist der Prozessor gebunden und kann keine anderenOperationen vollziehen.

g bezeichnet den kleinsten zeitlichen Abstand (engl. gap) zwischen zwei hintereinander gesendeten oderempfangenen Nachrichten eines Prozessors. Der Kehrwert von g ist proportional zur verfügba-ren Datenübertragungsrate pro Prozessor. Da im LogP Modell alle verschickten Nachrichten kleinsind, können bei einem kleinem g Nachrichten mit einer kleineren Verzögerung hintereinanderverschickt werden, so dass die Datenübertragungsrate steigt.

P ist die Anzahl der Speicher/Prozessor-Einheiten.

Die Größe der vorgestellten Parameter wird in der Regel als ein Vielfaches der Prozessor-Zyklus-Zeitgemessen. Im Gegensatz zum BSP-Modell gibt es in LogP keine supersteps und es ist asynchron. Auchdie Verzögerung beim Verschicken der Nachrichten variiert, denn L stellt lediglich eine Obergrenze da.Daher ist die Reihenfolge, in der die Nachrichten an der Ziel Speicher/Prozessor-Einheit ankommen, un-vorhersagbar, so wie es z.B. auch im Internet der Fall ist. Im LogP-Modell wird angenommen, dass dieverschickten Nachrichten eine kleine feste Größe haben. Daher kann eine Laufzeitabschätzung nur fürAlgorithmen erfolgen, die kurze Nachrichten verschicken. In [7] wird jedoch eine Erweiterung für LogPvorgestellt, um auch große Nachrichten verschicken zu können. Außerdem besteht in LogP eine Kapa-zitätsbeschränkung für das Kommunikationsnetzwerk. Diese gilt sowohl für das Senden als auch für dasEmpfangen von Nachrichten. Stellt man sich den Übertragungskanal als eine Röhre vor, die höchstensalle g Zeiteinheiten eine Nachricht aufnehmen kann, weil der Empfänger auch nur alle g Zeiteinheiten ei-ne Nachricht aus der Röhre entnehmen kann und somit Platz für einen neue Nachricht schafft, dann wirddeutlich, dass nur L/g Nachrichten in die Röhre passen. Da Nachrichten nur ganz oder gar nicht ver-schickt werden können und die Verschickung bereits erfolgen kann, wenn die (nächsten) g Zeiteinheitenanbrechen, folgt für die Kapazitätsbeschränkung: dL/ge. Wird ein Sendeversuch unternommen, welcherdie Beschränkung verletzten würde, dann wird der Sender solange blockiert, bis das Versenden der Nach-richt unter Einhaltung der Beschränkung erfolgen kann. Im LogP Modell gibt es zwei Variationen. Dieerste enthält die beschriebene Kapazitätsbeschränkung und wird auch stalling3 LogP genannt. Die zwei-te Variante hat diese Beschränkung nicht und wird nostalling4 genannt. Hier ist immer die nonstallingVariante gemeint, außer es wird ausdrücklich anderes erwähnt.

Parallele Sortieralgorithmen stellen eine gute Grundlage dar, um die Aussagefähigkeit eines Modells zuevaluieren, denn das parallele Sortieren erfordert sowohl lokale Berechnungen als auch Kommunikationzwischen den einzelnen Prozessoren. In [8] wird die Laufzeit verschiedener paralleler Sortieralgorithmenim LogP-Modell berechnet. Diese Berechnungen werden dann in einer Evaluation, für die die Sortieral-gorithmen mit Split-C[9] implementiert worden sind und auf einer CM5 [10] ausgeführt wurden, mit derrealen Laufzeit verglichen. Dabei stellt sich heraus, dass das LogP-Modell eine gute Vorhersage liefert.Abbildung 5 zeigt einer Vergleich zwischen der Vorhersage und der tatsächlichen Laufzeit.

2.3 QSMEin weitere Vertreter aus der Familie der Parallel Bridging Models ist das Queuing Shared Memory Mo-dell (QSM) [11]. Es hat sowohl Eigenschaften vom PRAM als auch vom BSP. Wie bei PRAM verfügendie Prozessoren bei QSM über individuellen lokalen Speicher und kommunizieren über globalen gemein-samen Speicher miteinander. Ähnlich wie bei BSP verfügt QSM über Phasen. Es wird eine Reihenfolge

3engl. blockierend4engl. nicht blockierend

5

198

Page 205: HEINZ NIXDORF INSTITUT Fakultät für Elektrotechnik ... Pottmeyer Memory Limitations in Artificial Intelligence ... Vitter hat gezeigt, dass viele in diesem Modell effiziente Entwicklungen

the assumption of a large number of data elementsper processor. This has significant impact on thekinds of algorithms that are effective in practice.

Network technology is advancing as well, but it isnot driven by the same volume market forces asmicroprocessors and memory. Currently, communi-cation bandwidth lags far behind internal processormemory bandwidth and the time to move data acrossthe network is far greater than the time to move databetween chips on a node. Moreover, the realizableperformance is limited by the interface between thenetwork and the node, which consumes processingcycles just getting data into and out of the network.Although network interfaces are improving, proces-sors are improving in performance even faster, so wemust assume that high latency and overhead of com-munication, as well as limited bandwidth, will contin-ue to be problems.

There appears to be no consensus emerging onthe interconnection topology: The networks of newcommercial machines are typically different fromtheir predecessors and different from one another.In addition, most production parallel machines canoperate in the presence of network faults and allowthe operating system to assign programs to collec-tions of nodes. Thus, the physical interconnectunderlying a program may vary even on a singlemachine. Attempting to exploit a specific networktopology is likely to yield algorithms that are not veryrobust in practice.

The convergence of parallel architectures is reflect-ed in our LogP model that addresses significant com-

mon issues while suppressing machine specific ones,such as network topology and routing algorithm. Themodel characterizes a parallel machine by a small setof parameters. In our approach, a good algorithmembodies a strategy for adapting to differentmachines in terms of these parameters.

LogP ModelStarting from the technological motivations previous-ly discussed, together with programming experienceand examination of popular theoretical models, we

have developed a model of a distributed-memorymultiprocessor in which processors communicate bypoint-to-point messages. The model specifies the per-formance characteristics of the interconnection net-work, but does not describe the structure of thenetwork.

The main parameters of the model are the follow-ing (illustrated in Figure 2):

L: An upper bound on the latency, or delay,incurred in communicating a message containinga word (or small number of words) from itssource processor/memory module to its targetprocessor/memory module.

o: The overhead, defined as the length of time that aprocessor is engaged in the transmission orreception of each message. During this time, theprocessor cannot perform other operations.

g: The gap, defined as the minimum time intervalbetween consecutive message transmissions orconsecutive message receptions at a processor.The reciprocal of g corresponds to the availableper-processor communication bandwidth.

P: The number of processor/memory modules.

The parameters L, o, and g are typically measuredas multiples of the processor cycle time. The model isasynchronous, in that processors work asynchronouslyand the latency experienced by any message is unpre-dictable, but is bound above by L in the absence ofstalls. Because of variations in latency, messages direct-ed to a given target module may not arrive in the sameorder as they are sent. The basic model assumes thatall messages are of a small fixed size. Furthermore, itis assumed that the network has a finite capacity, suchthat at most L/g messages can be in transit from anyprocessor or to any processor at any time. If a proces-sor attempts to transmit a message that would exceedthis limit, it stalls until the message can be sent with-out exceeding the capacity limit.

In analyzing an algorithm, the key metrics are themaximum time and the maximum amount of storageused by any processor. In order to be considered cor-rect, an algorithm must produce correct resultsunder all interleavings of messages consistent withthe upper bound of L on latency. However, in esti-mating the running time of an algorithm, we assumethat each message incurs a latency of L.

LogP models communication but does not attemptto model local computation. We have resisted thetemptation to provide a more detailed model of theindividual processors taking into account factors suchas cache size or pipeline structure, and rely instead onthe existing body of knowledge in implementing fastsequential algorithms on modern uniprocessor sys-tems to fill the gap. An implementation of a good par-allel algorithm on a specific machine will surelyrequire a degree of local tuning.

There is a concern that LogP has too many para-meters, which makes analysis of interesting algo-rithms difficult. Fortunately, the parameters are not

COMMUNICATIONS OF THE ACM November 1996/Vol. 39, No. 11 81

P M P M P M. . .P (processors)

oo (overhead)

L (latency)Interconnection network

g (gap)

Limited capacity(L/g to or froma processor)

Figure 2. The LogP model describes an abstractmachine configuration in terms of four performanceparameters: L, the latency experienced in each communication event; o, the overhead experienced by the sending and receiving processors for each communication event; g, the gap between successivesends or successive receives by a processor; and P, the number of processor/memory modules.

Abbildung 4: Im LogP-Modell wird eine abstrakte parallele Maschine mit vier Parametern beschrieben: Lbeschreibt die Latenz im Verbindungsnetzwerk, o bezeichnet den Kommuikationszuschlagbeim Verschicken und Empfangen eine Nachricht, g bezeichnet den zeitlichen Mindestab-stand zwischen dem Verschicken zweier Nachrichten und P bezeichnet die Anzahl derSpeicher/Prozessor-Einheiten. Quelle:[5]

Predicted

N/P

us

/ke

y

0

2 0

4 0

6 0

8 0

100

120

140

16

38

4

32

76

8

65

53

6

13

10

72

26

21

44

52

42

88

10

48

57

6

Measured

N/P

us

/ke

y

0

2 0

4 0

6 0

8 0

100

120

140

16

38

4

32

76

8

65

53

6

13

10

72

26

21

44

52

42

88

10

48

57

6512

256

128

6 4

3 2

Figure 11: Predicted and measured execution time per key of radix sort on the CM-5.

N/P

us

/ke

y

0

2 0

4 0

6 0

8 0

100

120

140

16

38

4

32

76

8

65

53

6

13

10

72

26

21

44

52

42

88

1E

+0

6

Dist

GlobalHist

LocalHist

Dist-m

GlobalHist-m

LocalHist-m

Figure 12: Predicted and measured execution times per key of various phases in radix sort on 512 processors.

sort, it is faster for large .

Figure 12 shows the breakdown by phases for 512 processors. Both the prediction and the measurements

show a significant decrease in time per key with increasing number of keys, due to the fixed cost of

constructing the global histogram. This observation implies that a smaller radix size should be used to sort

small data sets. At large values of , the time to distribute the keys comprises 85% of the execution time.

Our measurements show that the time to permute the keys across processors increases with both and

. The model matches the measured execution time precisely for 32 processors and 16K keys. On 512

processors and 16K keys, our measured time is 34% higher than that predicted by the model; with 1M keys

it is 47%. This increase in communication time both with the number of processors and problem size may

be due to the contention which we do not model, although additional experiments indicate that the increase

with is largely due to tlb misses on the destination processor, similar to the misses observed in the local

sort. As a result of the poorer accuracy of our model for very large numbers of processors, we may not be

able to extrapolate our results to 1024 processors as well for radix sort as for the other sorts.

Figure 13 shows the execution time of radix sort for various input sets. The execution time for

constructing the local histogram increases slightly with entropy, due to a decrease in the locality of histogram

19

Abbildung 5: Zusehen ist die durch LogP vorhergesagte Laufzeit für Radix-Sort auf der linken Seiteund die tatsächliche Laufzeit auf der rechten Seite. Die Legende gibt die Linieart für diejeweilige Anzahl von Prozessoren an. Die X-Achse gibt die gesamt Zahl der zu sortierendenWerte im Verhältnis zur Prozessoranzahl an. Auf der Y-Achse sind νs pro Wert (key) proProzessor aufgetragen. Quelle:[8]

6

199

Page 206: HEINZ NIXDORF INSTITUT Fakultät für Elektrotechnik ... Pottmeyer Memory Limitations in Artificial Intelligence ... Vitter hat gezeigt, dass viele in diesem Modell effiziente Entwicklungen

dieser synchronisierter Phasen durchgeführt. In jeder dieser Phasen werden folgende Operationen belie-big verschränkt durchgeführt:

1. globalen Speicher lesen: jeder Prozessor i liest den Wert der globalen Speicheradressen ri und ko-piert diese in seinen lokalen Speicher. Gelesene Speicherinhalte aus dem globalen Speicher stehenerst in der nächsten Phase zur Verfügung und können erst dann verwendet werden.

2. globalen Speicher beschreiben: jeder Prozessor i beschreibt wi globale Speicher-Adressen.

3. lokale Berechnung: jeder Prozessor i vollzieht ci lokale Operationen, bei denen er nur auf seinenlokalen Speicher zugreifen kann.

In der selben Phase dürfen die Prozessoren auch gleichzeitig auf eine globale Speicheradresse zugrei-fen. Dabei darf der Zugriff für alle entweder nur schreibend oder aber nur lesend erfolgen. Bei gleich-zeitigem Schreiben in eine globalen Speicherzelle ist es nicht vorhersehbar, welcher Prozess erfolgreichsein wird, d.h., von welchem Prozessor der Wert geschrieben wird. Der geschriebene Wert kann auchfrühestens in der nächsten Phase gelesen werden. Ein Prozessor kann in einer Phase mehrere Operationendurchführen, aber die Ergebnisse von Operationen, die auf den globalen Speicher zugreifen, sind erst inder nächsten Phase verfügbar.

Das QSM-Modell verfügt über zwei Parameter κ und g. Das g bezeichnet den Faktor um den der Zu-griff auf den globalen Speicher langsamer ist, als auf den lokalen. Das vorliegende Modell heißt queuingshared memory, shared memory, weil es einen gemeinsamen globalen Speicher gibt über den kommuni-ziert wird und das queuing kommt daher, weil man es sich auch als eine Reihe von Queues (DatenstrukturWarteschlange) vorstellen kann. Bei dieser Sichtweise wird angenommen, dass jede globale Speicherstel-le eine Warteschlange hat. In diese werden Anfragen zum Lesen und Schreiben seitens der Prozessorenhinzugefügt und einzeln nacheinander abgearbeitet. Dadurch entsteht ein Verzögerung. Die maximaleVerzögerung, die in einer solchen Warteschlange auftreten kann, wird als maximale Konkurenzsituation(maximum contention) bezeichnet und spiegelt sich im zweiten QSM-Parameter κ wieder.

Für die Laufzeit eines Algorithmus im QSM-Modell wird wie bei BSP die Summe der einzelnenSchritte bzw. Phasen gewählt. Hierfür sind noch einige Komponenten notwendig: In jeder Phase wirdmit mop = maxici das Maximum der lokalen Berechnung aller i Prozessoren und mit mrw =maxiri, wi das Maximum der globalen Lese/Schreib-Zugriffe aller i Prozessoren bezeichnet. Für dieDauer einer Phase würde dann mop+g·mrw+κ gelten. Es wird jedoch in [11], welches QSM einführt, fürdie Laufzeit einer Phase folgende Brechung benutzt: maxmop, g ·mrw, κ. Für die zweite Variante wirddamit argumentiert, dass der Unterschied zur ersten höchstens Faktor drei beträgt und es wird auf [12]verwiesen, wo gezeigt wird, dass zumindest auf einigen Computer die zweite Variante besser zutrifft.Durch die große Ähnlichkeit zu PRAM kann eine Vielzahl von für PRAM entwickelten Algorithmenleicht für QSM angepasst werden.

2.4 s-QSM

Eine Variation vom QSM-Modell ist s-QSM (symmetrisches QSM) bei dem die Dauer einer Phase durchmaxmop, g · mrw, g · κ gegeben ist.

3 EmulationMöchte man die Emulation von PBMs betrachten ist es erst notwendig ein Maß für die Güte der Emu-lation einzuführen. Als arbeitserhaltend bezeichnen wir eine Emulation, bei der das Produkt aus derProzessoranzahl p und der Rechenzeit t auf der emulierten und der emulierenden Maschine gleich (zu-züglich eines konstanten Faktors) ist. Also wenn eine Maschine mit p = 2 Prozessoren und t = 10

7

200

Page 207: HEINZ NIXDORF INSTITUT Fakultät für Elektrotechnik ... Pottmeyer Memory Limitations in Artificial Intelligence ... Vitter hat gezeigt, dass viele in diesem Modell effiziente Entwicklungen

Emulierendes Modell

Emuliertes Modell BSP LogP (blockierend) QSM

BSP O(log4 p + (l/g) log2 p) O(d(g log p)/Le)LogP (nicht blockierend) O(L/l) (det.) 1 (det.) O(d(g log p)/le)QSM O((L/g) + g log p) O(log4 p + (l/g) log2 p + g · log p)

Tabelle 3: Verlangsamerung von arbeitserhaltend Emulationen. Die mit det. gekennzeichneten Ergebnis-se sind deterministische Emulationen. L ist die BSP-Latenz und l ist die LogP-Latenz. Nach[13]

Zeiteinheiten je Prozessor arbeitet, dann ist die Emulationen arbeitserhaltend wenn die von ihr emulier-te Maschine z.B. p

′= 5 Prozessoren hat, die jeweils t

′= 4 Zeiteinheiten arbeiten. Bei der Emulation

kommt es in der Regel zur einer Verlangsamerung. Diese ist (f), wenn der Algorithmus in Zeit der t aufp Prozessoren läuft und in Zeit der t

′= (t ·(p/p

′)) auf p

′ ≤ p/f Prozessoren emuliert werden kann. Eineideale Verlangsamerung hat den Faktor 1 und bedeutet, dass sie höchstens einen konstante Verschlechte-rung der Effizienz darstellt. Tabelle 3 enthält die Verlangsamerung bei der gegenseitigen Emulation dervorgestellten PBMs.

3.1 Arbeitserhaltende Emulation von BSP auf LogPIn diesem Abschnitt wird das Verfahren aus [13] vorgestellt, mit dem BSP auf LogP emuliert werdenkann. Als das Routen einer h-Relation wird das Vorgehen im BSP Modell bezeichnet, bei dem die Nach-richten in in einem superstep verteilt werden. Dabei entspricht h dem ht aus der vorangegangenen BSP-Beschreibung.

Lemma 3.1 Nach [14] können folgenden Problem im LogP-Modell in B(p) = O

(l

⌈log plog l

g

⌉)Zeit ge-

löst werden:

• Synchronization der p Prozessoren

• Summieren von p Werten, von denen jeweils einer pro Prozessor gespeichert ist.

Lemma 3.2 Nach [13] kostet das Routen einer h-Relation in LogP mit p-Prozessoren O(g(h+H(p))+l),mit H(p) = O

(log3 p · log log p

), Zeit.

Die beiden Größen B(p) und H(p) sind nur zur Vereinfachung eingeführt worden. Um das Routen derh-Relation durchzuführen ist es notwendig die Größe von h vorher zu bestimmen.

Lemma 3.3 [13] liefert einen Algorithmus, welcher mit hoher Wahrscheinlichkeit in ZeitO(g log2 p + (H(p) + B(p)) · log p

log log p

)einen Wert für h liefert der

1. eine obere Schranke für den wahren Wert von h ist

2. nicht größer als das Doppelte vom wahren h ist

Der Algorithmus für die Emulation von BSP auf LogP sieht wie folgt aus:

1. Initialisierung: der Speicher und die Prozessoren werden gleichmäßig auf die Prozessoren vomLogP verteilt.

8

201

Page 208: HEINZ NIXDORF INSTITUT Fakultät für Elektrotechnik ... Pottmeyer Memory Limitations in Artificial Intelligence ... Vitter hat gezeigt, dass viele in diesem Modell effiziente Entwicklungen

2. supersteps: unter Einhaltung der LogP Kapazitätsbeschränkung werden die Nachrichten zu dendazugehörigen LogP Prozessoren wie folgt geroutet:

2.1 finde eine gute oberer Schranke für h2.2 route die h-Relation2.3 führe die Sychronization durch

Die Laufzeit bei einem superstep im BSP ist: wt + g · ht + L. Im LogP muss die lokale Berechnungwt nicht berücksichtigt werden. Sie kann es auch gar nicht, weil LogP kein Maß dafür hat und nur dieKommunikation in Rechnung stellt. Das Verschicken der Nachrichten (g ·ht) wird im Schritt 2.2 gemachtund 2.3 spiegelt den Parameter L wieder. Die Kosten für Schritt 2.1 liefert Lemma 3.3. Lemma 3.2 gibtdie Kosten für Schritt 2.2 an und in Lemma 3.1 sind die Kosten für den letzten Schritt enthalten. Dadie Faktoren der Kosten der Schritte 2.2 und 2.3 bereits in 2.1 enthalten sind, können diese Schritte zurAbschätzung vernachlässigt werden. Setzt man B(p) und H(p) in die Formel aus Lemma 3.3 so folgtfolgende Lösung, welche auch in Tabelle 3 aufgeführt ist:

O

(log4 p +

lg

log lg

· log2 p

log log p

)≤ O

(log4 p +

l

glog2 p

)

4 Zusammenfassung

Es wurde auf die Notwendigkeit von PBMs eingegangen. Verschiedenen Vertreter dieser Modell-Klassemit ihren unterschiedlichen Eigenschaften wurde erläutert.Durch die gegenseitige Emulation der Modell,die zudem keine große Verzögerung verursacht, ist es Möglich die Modell auszutauschen. Dadurch kannman leichtere oder jeweils besser passende Modelle wählen um parallele Algorithmen zu entwickeln, denselbst wenn die Zielplattform ein anderes PBM ist, kann es durch Emulation den Einsatz ermöglichen.LogP ist z.B. durch die Asynchronität sehr schwierig zu analysieren und wurde bisher auch kaum für dieAuswertung komplexer Algorithmen gewählt. QSM hingegen ist ein einfacheres Modell, es auch auchnur zwei Parameter, was die Analyse vereinfacht. Außerdem besteht ein großer Vorteil in der Ähnlichkeitzu PRAM, so dass sich PRAM-Algorithmen leicht an QSM anpassen lassen. BSP kommt öfter zumEinsatz, außerdem stehen mehrerer Entwicklungswerkzeuge zur Verfügung um direkt BSP-Algorithmenzu implementieren.

Literatur

[1] COPPOLA, M. ; M., Schmollinger: Hierarchical Models and Software Tools for Parallel Program-ming. In: MEYER, Ulrich (Hrsg.) ; SANDERS, Peter (Hrsg.) ; SIBEYN, Jop (Hrsg.): Volume in corsodi pubblicazione, springer, 2003 (lncs 2625), S. 320–354

[2] FORTUNE, Steven ; WYLLIE, James: Parallelism in random access machines. In: STOC ’78: Pro-ceedings of the tenth annual ACM symposium on Theory of computing. New York, NY, USA : ACMPress, 1978, S. 114–118

[3] VALIANT, Leslie G.: A bridging model for parallel computation. In: Commun. ACM 33 (1990), Nr.8, S. 103–111. – ISSN 0001–0782

[4] AUF DER HEIDE, Friedhelm M. ; WANKA, Rolf: Parallel Bridging Models and Their Impact onAlgorithm Design. In: ICCS ’01: Proceedings of the International Conference on ComputationalScience-Part II. London, UK : Springer-Verlag, 2001. – ISBN 3–540–42233–1, S. 628–637

9

202

Page 209: HEINZ NIXDORF INSTITUT Fakultät für Elektrotechnik ... Pottmeyer Memory Limitations in Artificial Intelligence ... Vitter hat gezeigt, dass viele in diesem Modell effiziente Entwicklungen

[5] CULLER, David E. ; KARP, Richard M. ; PATTERSON, David ; SAHAY, Abhijit ; SANTOS, Eunice E.; SCHAUSER, Klaus E. ; SUBRAMONIAN, Ramesh ; VON EICKEN, Thorsten: LogP: a practicalmodel of parallel computation. In: Commun. ACM 39 (1996), Nr. 11, S. 78–85. – ISSN 0001–0782

[6] CULLER, David E. ; KARP, Richard M. ; PATTERSON, David A. ; SAHAY, Abhijit ; SCHAUSER,Klaus E. ; SANTOS, Eunice ; SUBRAMONIAN, Ramesh ; VON EICKEN, Thorsten: LogP: Towardsa Realistic Model of Parallel Computation. In: Principles Practice of Parallel Programming, 1993,S. 1–12

[7] ALEXANDROV, Albert ; IONESCU, Mihai F. ; SCHAUSER, Klaus E. ; SCHEIMAN, Chris: LogGP:Incorporating Long Messages into the LogP Model for Parallel Computation. In: Journal of Paralleland Distributed Computing 44 (1997), Nr. 1, S. 71–79

[8] DUSSEAU, Andrea C. ; CULLER, David E. ; SCHAUSER, Klaus E. ; MARTIN, Richard P.: FastParallel Sorting Under LogP: Experience with the CM-5:. In: IEEE Transactions on Parallel andDistributed Systems 7 (1996), Nr. 8, S. 791–805

[9] CULLER, David E. ; ARPACI-DUSSEAU, Andrea C. ; GOLDSTEIN, Seth C. ; KRISHNAMURTHY,Arvind ; LUMETTA, Steven ; VON EICKEN, Thorsten ; YELICK, Katherine A.: Parallel programmingin Split-C. In: Supercomputing, 1993, S. 262–273

[10] HILLIS, W. D. ; TUCKER, Lewis W.: The CM-5 Connection Machine: a scalable supercomputer.In: Commun. ACM 36 (1993), Nr. 11, S. 31–40. – ISSN 0001–0782

[11] GIBBONS, Phillip B. ; MATIAS, Yossi ; RAMACHANDRAN, Vijaya: Can shared-memory modelserve as a bridging model for parallel computation? In: SPAA ’97: Proceedings of the ninth annualACM symposium on Parallel algorithms and architectures. New York, NY, USA : ACM Press, 1997.– ISBN 0–89791–890–8, S. 72–83

[12] BLELLOCH, Guy E. ; GIBBONS, Phillip B. ; MATIAS, Yossi ; ZAGHA, Marco: Accounting formemory bank contention and delay in high-bandwidth multiprocessors. In: SPAA ’95: Proceedingsof the seventh annual ACM symposium on Parallel algorithms and architectures. New York, NY,USA : ACM Press, 1995. – ISBN 0–89791–717–0, S. 84–94

[13] RAMACHANDRAN, Vijaya ; GRAYSON, Brian ; DAHLIN, Michael: Emulations between QSM, BSPand LogP: a framework for general-purpose parallel algorithm design / CS department UT-Austin.1998 ( TR-98-22). – UTCS Technical Report

[14] KARP, Richard M. ; SAHAY, Abhijit ; SANTOS, Eunice E. ; SCHAUSER, Klaus E.: Optimal Broad-cast and Summation in the LogP Model. In: ACM Symposium on Parallel Algorithms and Architec-tures, 1993, S. 142–153

10

203

Page 210: HEINZ NIXDORF INSTITUT Fakultät für Elektrotechnik ... Pottmeyer Memory Limitations in Artificial Intelligence ... Vitter hat gezeigt, dass viele in diesem Modell effiziente Entwicklungen

204

Page 211: HEINZ NIXDORF INSTITUT Fakultät für Elektrotechnik ... Pottmeyer Memory Limitations in Artificial Intelligence ... Vitter hat gezeigt, dass viele in diesem Modell effiziente Entwicklungen

Fallstudie: Speicherbewußtes, paralleles Sortieren

Stefan Finke

1 Einleitung

Die effiziente Parallelisierung eines Algorithmus ist eine schwierige Aufgabe, die sowohl die Be-herrschung von Softwaretechniken als auch Kenntnisse uber die Zielhardware erfordert. DerProgrammierer oder der Compiler mussen verschiedene Parameter einstellen, die den Algorith-mus an die Netzwerktopologie und die Kommunikationsbibliotheken des Computers anpassen,oder die Datenlokalitat des Algorithmus’ in der vorliegenden Speicherhierarchie herausstellt.In dieser Seminararbeit werden unterschiedliche Techniken, welche auf dem Prinzip der Da-tenlokalitat beruhen, untersucht, die fur die Entwicklung effizienter paralleler Algorithmen an-gewandt werden konnen. Um die Datenlokalitat ausnutzen zu konnen, sind zwei Aspekte vongroßer Bedeutung. Die Reduzierung von Fehlgriffen auf die lokalen Caches und die Verringe-rung des Zeitaufwandes die ein Prozessor fur den Zugriff auf verteilte oder entfernte Cachesund Speicher benotigt.Zum besseren Verstandnis der Nutzung der Datenlokalitat wird diese an Sortieralgorithmenvorgestellt, wobei besonders auf die parallelen Aspekte des Problems eingegangen wird. Die Al-gorithmen werden hier fur das Sortieren innerhalb des Speichers verwendet.Kapitel 2 stellt die Architekturaspekte vor, die Einfluss auf die Kosten von Speicherzugriffenund der Kommunikation haben. In Kapitel 3 wird der SF-Radix Sortieralgorithmus fur shared

und distributed memory vorgestellt und analysiert. Der C3-Radix Sortieralgorithmus wird inKapitel 4 als verbesserte Losung des Problems, ebenso unter der Verwendung von shared unddistributed memory, dargestellt und analysiert. Die Kapitel 3 und 4 beschreiben weiterhin un-terschiedliche Implementationen der Algorithmen, um die Auswirkung auf die Datenlokalitatherauszustellen und somit den Einfluss auf die Performanz. Abschließend wird in Kapitel 5 ei-ne kurze Zusammenfassung der Ergebnisse dieser Seminararbeit gegeben.

2 Architektur

In dieser Seminararbeit werden multiple instruction, multiple data-Architekturen,kurz MIMD, unter den fur die vorzustellenden Algorithmen notwendigen Techniken desshared memory (SM MIMD) und des distributed memory (DM MIMD) verwendet. MIMD-Computer fuhren parallel Operationen auf verschieden gearteten Eingangsdatenstromen durch,wobei die Verteilung der Aufgaben an die zur Verfugung stehenden Ressourcen meistens durcheinen oder mehrere Prozessoren selbst zur Laufzeit durchgefuhrt wird. Jeder Prozessor hat da-bei Zugriff auf die Daten anderer Prozessoren.In diesem Abschnitt werden die beiden Entwurfe des SM MIMD und des DM MIMD kurzerlautert und dann das Board SGI Origin 2000 vorgestellt, auf dem alle Berechnungen durch-gefuhrt worden sind.

205

Page 212: HEINZ NIXDORF INSTITUT Fakultät für Elektrotechnik ... Pottmeyer Memory Limitations in Artificial Intelligence ... Vitter hat gezeigt, dass viele in diesem Modell effiziente Entwicklungen

2.1 SM MIMD

Um die Zugriffszeiten in einem shared memory-System zu verringern ist das Anlegen einerSpeicherhierarchie notwendig. Diese Hierarchie bilden mehrere Caches, angeordnet auf unter-schiedlichen Leveln. Fur jeden Prozessor existieren sowohl lokale Cache-Speicher, als auch eineHierarchie entfernter Caches.Aus dieser Speicherverteilung enstehen Synchronisationsprobleme zwischen den Kopien einzel-ner Daten in den Caches unterschiedlicher Prozessoren. Verandert ein Prozessor diese Daten,mussen alle Kopien die sich im Speicher weiterer Prozessoren befinden an diese Veranderungangepasst werden. Im Folgenden werden zwei mogliche Losungen fur dieses Problem vorge-stellt.

1. Verandert ein Prozessor die Daten in seinem lokalen Cache, werden alle Kopien dieserDaten in anderen Caches, sowie die im Hauptspeicher aktualisiert. Wenn sich zwei odermehr Prozessoren das gleiche Datum teilen, wird dies als true sharing bezeichnet.

2. Verandert ein Prozessor die Daten in einer seiner Cachelines, werden alle Cachelines inden anderen Prozessoren die dieses Datum enthalten als ungultig gesetzt. Ein Zugriffauf solch eine ungultige Cacheline erzeugt immer einen Cache-Fehlzugriff, da diesesVerfahren auf der gesamten Cacheline arbeitet und nicht auf einzelne Daten. Wirddann auf ein Datum in der ungultigen Cacheline zugegriffen, welches nicht fur dieUngultigkeit verantwortlich ist, also eigentlich noch einen richtigen Wert besitzt, wirddies als false sharing bezeichnet. Ansonsten handelt es sich wie unter 1. schon erlautertum ein true sharing.

2.2 DM MIMD

In einem MIMD-System mit verteiltem Speicher mussen die einbezogenen Prozessoren uberNachrichten kommunizieren. Kosten fur eine Nachricht setzen sich aus fixen Kosten, wie z.B.die Ubertragungszeit, und variablen Kosten, die z.B. von der Große der Nachricht abhangen,zusammen. Hier werden zwei Arten der Kommunikation betrachtet, die synchrone und dieasynchrone Ubertragung.

• Bei der synchronen Kommunikation wartet der Prozessor bis die Kommunikationbeendet ist und fuhrt parallel keine weiteren Berechnungen aus.

• Bei der asynchronen Kommunikation sendet der Prozessor die Nachricht und nimmtdanach direkt wieder Aktivitaten auf. In diesem Fall sind Kommunikation und Berech-nungen parallel moglich. Allerdings fallt auch hier Overhead z.B. durch das Puffern vonDaten an.

206

Page 213: HEINZ NIXDORF INSTITUT Fakultät für Elektrotechnik ... Pottmeyer Memory Limitations in Artificial Intelligence ... Vitter hat gezeigt, dass viele in diesem Modell effiziente Entwicklungen

2.3 SGI Origin 2000

Die Algorithmen in dieser Seminararbeit wurden alle auf dem Origin 2000 von Silicon Graphics(SGI) getestet. Das O2000 ist ein massiv paralleler NUMA Computer und arbeitet aufverteilten, gemeinsan genutzten Speicher (Distributed Shared Memory, DSM). Dadurch ister gut fur die unterschiedlichen hier vorgestellten Algorithmen geeignet, da sie alle, egal obmit geteiltem oder verteiltem Speicher arbeitenden, auf dem gleichen Board ausgefuhrt werdenkonnen.Ein Baueinheit des O2000 besteht aus einem 250Mhz MIPS R10000 Prozessor mit eigenem32Kb on-chip first-level-Cache fur Daten und Instruktionen und einem 4Mb großen second-level-Cache, ebenfalls Daten und Instruktionen. Eine Node− Card setzt sich aus zwei Prozessorenund einem 128Mb großen geteiltem Speicher mit einer Bandbreite von 720Mb/s zusammen.Gruppen von zwei Node− Cards werden dann an einen Router angebunden, so dass diese andas Netzwerk angeschlossen sind.In dieser Seminararbeit setzt sich das Netzwerk aus vier Routern zusammen, die wie ein 2-d-Hypercube-Netzwerk mit 160Gb/s globaler Bandbreite verbunden sind. Weiterhin hat dieseHypercube zwei Express-Links zu den beiden Routern die nicht direkt verbunden sind.Auf dieser Architektur werden die spater vorgestellten Algorithmen mit Beispieldaten getestet,um dann konkrete Daten fur eine Analyse und ein Vergleich zwischen den Algorithmen zuhaben.

3 sequentielle und einfache Radix Sortieralgorithmen

Der Radix Sortieralgorithmus ist ein sequentieller Algorithmus der einfach parallelisiert werdenkann. In diesem Kapitel wird kurz die sequentielle Ausfuhrung und dann zwei paralleleLosungen, eine mit geteiltem und eine mit verteiltem Speicher, vorgestellt.

3.1 sequentieller Radix Sort

Die Idee hinter dem Radix Sortieralgorithmus ist die Folgende: ein b-bit großer Schlussel wirdvon dem niedrigstwertigen zum hochstwertigen Bit sortiert. Die b-bits eines Schlussels wer-den dabei in Gruppen mit m Zeichen von bi aufeinanderfolgenden Bits so aufgeteilt, dass∑m−1

i=0 bi = b gilt.Fur die eigentliche Sortierarbeit wird ein bestehendes Sortierverfahren verwendet. In dieserArbeit wird auf den Counting-Algorithmus zuruckgegriffen, was sich auch in dem Algorithmusauf der linken Seite der Abbildung 3 fur den sequentiellen Radix-Sort widerspiegelt.Counting-Sort ist auf der rechten Seite der Abbildung an einem kurzen Beispiel dargestellt.Der obere Ausschnitt zeigt den ersten Schritt des Algorithmus. Hier werden die vorkommendenWerte im Eingabefeld A gezahlt und in das Hilfsfeld C geschrieben (Zeilen 3-6). In der Mit-te ist der zweite Schritt des Counting-Sort zu sehen. Die vorher gezahlten Werte werden hier

207

Page 214: HEINZ NIXDORF INSTITUT Fakultät für Elektrotechnik ... Pottmeyer Memory Limitations in Artificial Intelligence ... Vitter hat gezeigt, dass viele in diesem Modell effiziente Entwicklungen

kumulativ im Hilfsfeld aufaddiert (Zeilen 7-13). Der letzte Schritt ist dann das Schreiben derWerte aus dem Eingangsfeld A, uber das Hilfsfeld C in das Ausgabefeld B (Zeilen 14-18) unddas Inkrementieren der Werte in C. In dem Beispiel ist dieser Schritt aus Ubersichtsgrundennur fur die ersten vier Werte dargestellt. Die Integration dieses Algorithmus’ in Radix-Sortwird im Folgenden erlautert.

10

443559176481122141

71615334299491732697

924983

0

10987654321

20191817161514131211

232221

1

302115326

0

987654321

0

212119181712971

0

987654321

1

222120181714984

0

987654321

10

12

81211

17

644

59

0

10987654321

20191817161514131211

232221

S C C C D

count accum.

1.

2.

Abbildung 1: Beispiel einer Sortierung mit Radix-Sort fur einen Schlussel mit 2 Dezimalstellen

In Abbildung 1 ist ein großeres Beispiel fur den Algorithmus Radix-Sort dargestellt. Esgibt den Zustand des Sortieralgorithmus in der 1. Iteration an, nachdem neun Elementebearbeitet wurden. Vektor S enthalt N = 24 aus 2 Bits bestehende zu sortierende Schlussel,Vektor C enthalt die notwendigen nbuckets = 10 Zahler und in Vektor D wird das Ergebnisder entsprechenden Iteration geschrieben. In dem vorliegenden Beispiel enthalt C fur jedenmoglichen Dezimalwert einen Zahler, also zehn Stuck.Die erste Iteration des Algorithmus durchlauft die niedrigstwertigen Bits von S und initialisiertden Vektor C entsprechend (Zeilen 1 und 2). Die niedrigstwertigen Bits von S sind die erstenDezimalstellen der einzelnen Werte. Die ersten Bits sind also 0, 1, 4, 1, 2, 1, etc. Fur dieseWerte wird nun der erste Schritt des Counting-Algorithmus ausgefuhrt. Er zahlt die Anzahl derWerte an der momentan zu untersuchenden Bitstelle. In dem Vektor C mit dem Label count

ist z.B. zu sehen dass die zwei als niedrigwertigstes Bit genau zweimal vorkommt, namlich in12 und in 92. Sind alle Bits der entsprechenden Stelle gezahlt worden, tritt die zweite Phasedes Counting-Algorithmus in Kraft. Hier werden die Werte des Vektors C, ausgehend von demWert C[0] = 0 kumulativ addiert und wieder in den Vektor C zuruckgeschrieben. Dies ist furdie ersten drei Werte des Vektors C mit dem Label accum. beispielhaft dargestellt, 0+1=1 und1+6=7. Der letzte Schritt des Counting-Algorithmus durchlauft die entsprechenden Bitstellen

208

Page 215: HEINZ NIXDORF INSTITUT Fakultät für Elektrotechnik ... Pottmeyer Memory Limitations in Artificial Intelligence ... Vitter hat gezeigt, dass viele in diesem Modell effiziente Entwicklungen

von S nochmal komplett und schreibt die Werte, entsprechend des Werts in C, an die passendeStelle in D. In der Abbildung ist das beispielhaft an dem Wert 17 in S vorgefuhrt. Da es sichum das niederwertigste Bit handelt zahlt nur die 7 von 17. Es wird also der Wert an der Stelle7 im Vektor C mit dem Label accum. gelesen und die 17 in die dort angegebene Stelle imErgebnisvektor D geschrieben (1.). Nun wird noch der Wert in Vektor C um eins inkrementiert(2.). Zum Abschluß des Algorithmus werden die Vektoren S und D vertauscht(Zeile 19), da Dnun das bis an diese Stelle sortierte Ergebnis beinhaltet.Dieser Vorgang wird fur alle Bitstellen des Schlussels in S wiederholt, bis der gesamte Schlusselstabil sortiert ist. In dem Beispiel ware also lediglich noch eine zweite Iteration fur die ersteBitstelle notwendig.

1: for dig = least significant digit to most significant digitdo

2: initialize(C, nbuckets)

3: for i = 0 to N − 1 do4: value⇐ get digit value(S[i], dig)5: C[value]⇐ C[value] + 16: end for

7: tmp⇐ C[0]8: C[0]⇐ 09: for i = 1 to nbuckets− 1 do

10: accum⇐ tmp + C[i− 1]11: tmp⇐ C[i]12: C[i]⇐ accum13: end for

14: for i = 0 to N − 1 do15: value⇐ get digit value(S[i], dig)16: D[C[value]]⇐ S[i]17: C[value]⇐ C[value] + 118: end for

19: swap addresses(S, D)20: end for

Hilfsfeld C

0 76543213 4143146

Eingabefeld A

0 032020 54321

0 00000000 7654321

Ausgabefeld B

0 76543213 4143146

Eingabefeld A

0 00000000 7654321

Ausgabefeld B

0 76543213 4143146

Eingabefeld A

0 60040300 7654321

Ausgabefeld B

16

Hilfsfeld C0 742200 54321

76

Hilfsfeld C0 742200 54321

76

1 3 5 8

Abbildung 2: Counting-Sort

Abbildung 3: SF-Radix-Sort und Counting-Sort

Analyse

Laufzeit

1. N Elemente aus dem Wertebereich [1...k] mit Counting-Sort sortieren =⇒ O(k+n), dahier k so gewahlt dass gilt: k = O(n) =⇒ O(k+n) = O(n)

2. Sortierung aus 1. muss fur alle b Bits der Schlussel wiederholt werden =⇒ b * O(n) =O(n), da b konstant

209

Page 216: HEINZ NIXDORF INSTITUT Fakultät für Elektrotechnik ... Pottmeyer Memory Limitations in Artificial Intelligence ... Vitter hat gezeigt, dass viele in diesem Modell effiziente Entwicklungen

die Laufzeit betragt insgesamt O(k+n) = O(n), wenn k=O(n)

Speicherplatzbedarf

1. einen Quell- und einen Zielvektor zu Speicherung aller Schlussel =⇒ 2*n = O(n)

2. einen Zahlervektor zur Speicherung der Anzahl der Werte =⇒ 1*k = O(n), wenn k =O(n)

es wird O(n+k) = O(n), wenn k=O(n) gilt, Speicherplatz benotigt

Eigenschaften

1. Algorithmus sortiert stabil, da auch der verwendete Sortieralgorithmus Counting-Sortstabil lauft

2. Wertebereich eingeschrankt, nur auf Integer-Wert anwendbar

3. speicherintensiv durch die Verwendung zweier zusatzlicher Vektoren

3.2 SF-Radix Sort mit geteiltem Speicher

Diese parallele Version ist dem sequentiellen Radix-Sortieralgorithmus sehr ahnlich. Algorith-mus 1 ist eine OpenMP1-Version und enthalt zusatzliche Direktiven, die den Algorithmus par-allelisieren. Die Parallelisierung lauft dabei auf Thread- und Schleifenebene ab, d.h.die speziel-len Compiler-Direktiven verteilen die Ausfuhrung einer Schleife auf mehrere Threads und/oderProzessoren. OpenMP ist fur den Einsatz auf Systemen mit geteiltem Hauptspeicher geieignetund wird teilweise mit MPI2 kombiniert. Hier dient es zum besseren load-balancing zwischenden Prozessoren.

Bevor auf den Algorithmus und die Vorgehensweise eingegangen wird, werden die zumVerstandnis benotigten OpenMP-Direktiven erlautert:

• #pragma omp for teilt die Schleifendurchlaufe gleichmaßig auf Threads auf

• shared Werte die fur alle Threads sichtbar sind

• private jeder Thread arbeitet mit einer eigenen Kopie des Wertes

• schedule(static) Threads erhalten immer abwechselnd die gleiche Ausfuhrungszeit

1 OpenMP ist eine seit 1997 gemeinschaftlich von verschiedenen Hardware- und Compilerherstellern entwickelteProgrammierschnittstelle. Der Standard dient zur Shared-Memory-Programmierung in C/C++/Fortran aufMultiprozessor-Computern.

2 Das Message-Passing-Interface ist ein Protokoll, das die Kommunikation zwischen mehreren, parallel laufendenProzessoren unterstutzt.

210

Page 217: HEINZ NIXDORF INSTITUT Fakultät für Elektrotechnik ... Pottmeyer Memory Limitations in Artificial Intelligence ... Vitter hat gezeigt, dass viele in diesem Modell effiziente Entwicklungen

10

443559176481122141

71615334299491732697

924983

0

10987654321

20191817161514131211

232221

1

102013013

0

987654321

0

200102313

0

222119181712971

0

987654321

10

5373921271619181211

9717263534944464483

492959

0

10987654321

20191817161514131211

232221

S

Gl0

LCacc0

D

1

222121181815984

0

987654321

LCacc1

Gl1

Abbildung 4: Beispiel einer Sortierung mit Radix-Sort mit geteiltem Speicher fur einen Schlussel mit2 Dezimalstellen

In Abbildung 4 ist das gleiche Beispiel fur zwei Prozessoren zu sehen, wie im vorherigenAbschnitt das des sequentiellen Radix-Sort. S und D haben dabei die gleiche Funktion. GLi

reprasentiert den globalen Zahler und LCacc0 den lokalen Akkumulator des jeweiligen Prozessorsi. Bei diesem Algorithmus teilen sich die Prozessoren die Speichervektoren S, D und Gl. DasBeispiel hier bezieht sich auf zwei Prozessoren, wobei der Prozessor P0 auf dem weißen Vektorund P1 auf dem grauen Vektor arbeitet. In der Abbildung wird der Fall des niedrigstwertigenBits durchgespielt.Zu Beginn initialisiert jeder Prozessor seine Zahler in der globalen Zahlermatrix Gl (Zeilen 3bis 5). Dann fullt er diesen, genau wie im vorherigen Abschnitt schon beschrieben, uber eineZahlung der Bits auf (Zeilen 6 bis 10). Die omp for-Direktive in Zeile 6 sorgt dabei fur eineSynchronisation aller Prozessoren. Uber folgende Formel wird dann der Vektor LCacc aufgefullt(Zeile 11):

∑Pip=0

∑i−1j=0 Gl[j][ip] +

∑pid−1ip=0 Gl[i][ip], 0 ≤ i ≤ nbuckets− 1

Diese Formel berechnet die Position des jeweiligen Wertes in D unter der Berucksichtigungaller vorherigen Prozessoren. In dem Beispiel sind zwei Werte, eingekreist in der Abbildung, soberechnet worden.

LCacc0[1] =∑1

ip=0

∑0j=0 Gl[j][ip]

LCacc0[1] =∑1

ip=0 Gl[0][ip]

LCacc0[1] = Gl[0][0] + Gl[0][1] = 1 + 0 = 1

211

Page 218: HEINZ NIXDORF INSTITUT Fakultät für Elektrotechnik ... Pottmeyer Memory Limitations in Artificial Intelligence ... Vitter hat gezeigt, dass viele in diesem Modell effiziente Entwicklungen

Hieraus ergibt sich dass die 1 aus S[1] an die Stelle D[1] verschoben werden muss. Dies ist imoberen Beispiel in der Abbildung 4 zu sehen.

LCacc1[1] =∑1

ip=0

∑0j=0 Gl[j][ip] +

∑0ip=0 Gl[1][ip]

LCacc1[1] =∑1

ip=0 Gl[0][ip] + Gl[1][0]

LCacc1[1] = Gl[0][0] + Gl[0][1] + Gl[1][0] = 1 + 0 + 3 = 4

An dieser Berechnung kann abgelesen werden dass die 91 aus S[14] an die Stelle D[4] geschriebenwird. Dies ist durch das untere Beispiel in der Abbildung zu sehen.Das oben angesprochenen Verschieben der Werte von den LCacci wird in den Zeilen 12 bis17 des Algorithmus’ realisiert. Die Prozessoren schreiben dabei unabhangig voneinander ihreErgebnisse in der Zielvektor D. Bevor zum nachsten Schritt ubergegangen werden kann, mussendie Prozessoren wieder uber ein omp for (Zeile 12) synchronisiert werden. Abschließend tauschtein Prozessor die Vektoren D und S wie beim sequentiellen Radix-Sort auch (Zeilen 18 und 19)und es findet eine letzte Synchronisierung statt (Zeile 18), damit alle Prozessoren auch wiederauf den korrekten Vektoren arbeiten.

Algorithm 1 sequentieller Radix Sortieralgorithmus mit geteiltem Speicher1: #pragma omp parallel shared(S,D,Gl) private(LCacc)2: for dig = least significant digit to most significant digit do3: for i = 0 to nbuckets− 1 do4: Gl[i][pid]⇐ 05: end for

6: #pragma omp for private(i,value) schedule(static)7: for i = 0 to N − 1 do8: value⇐ get digit value(S[i], dig)9: Gl[value][pid]⇐ Gl[value][pid] + 1

10: end for

11: partial sum(Gl, LCacc)

12: for i = 0 to N − 1 do13: value⇐ get digit value(S[i], dig)14: D[LCacc[value]]⇐ S[i]15: LCacc[value]⇐ LCacc[value] + 116: end for

17: #pragma omp single18: swap addresses(S, D)19: end for

Analyse

Laufzeit

212

Page 219: HEINZ NIXDORF INSTITUT Fakultät für Elektrotechnik ... Pottmeyer Memory Limitations in Artificial Intelligence ... Vitter hat gezeigt, dass viele in diesem Modell effiziente Entwicklungen

1. N Elemente aus dem Wertebereich [1...k] mit Counting-Sort und pid Prozessoren sortieren=⇒O(k+n/pid), da hier k so gewahlt dass gilt: k=O(n) und pid konstant =⇒O(k+n/pid)= O(n)

2. Sortierung aus 1. muss fur alle b Bits der Schlussel wiederholt werden =⇒ b* O(n) =O(n), da konstant

die Laufzeit betragt insgesamt O(k+n) = O(n), wenn k=O(n)

Speicherplatzbedarf

1. einen Quell- und einen Zielvektor zu Speicherung aller Schlussel =⇒ 2*n = O(n)

2. einen lokalen Zahlervektor je Prozessor zur Speicherung der Anzahl der Werte =⇒ 1*k*pid= O(n), wenn k so gewahlt dass gilt: k=O(n)

es wird O(n) Speicherplatz benotigt

Eigenschaften

1. Algorithmus sortiert stabil, da auch der verwendete Sortieralgorithmus Counting-Sortstabil lauft

2. Wertebereich eingeschrankt, nur Integer moglich

3. speicherintensiv durch die Verwendung zweier zusatzlicher Vektoren

Analyse der vorgestellten Radix-Sort-Algorithmen

Beide bisher vorgestellten Algorithmen haben einen großen Nachteil. Durch die Verwendungspezieller Programmiersprachen ergeben sich bestimmte Eigenschaften bei dem Ablegen derDaten im Speicher. Der C Compiler legt z.B. die Zeilen der globalen Matrix nacheinander imSpeicher ab. Dies hat zur Folge dass fur ein Bucket i die beiden Zahler der Prozessoren P0

und P1 in der selben Reihe auch im Speicher in die gleich Cacheline geschrieben werden. Diebeiden Prozessoren greifen dann immer wieder nacheinander auf diese Cacheline zu und set-zen sie dann immer abwechselnd auf ungultig. Wenn dann der andere Prozessor erneut auf dieCacheline zugreift, muss er diese neu aus dem Speicher laden. Dieses false sharing entsteht,da die Cachekoharenz auf der Basis von Cachelines arbeitet und nicht auf elementarer Ebene.

Losung 1Das Vertauschen von Spalten Zeilen des globalen Vektors kann das Auftreten von false sharing

reduzieren. Bei Programmiersprachen wie Fortran ware dies nicht notwendig, hier werden dieSpalten schon nacheinander im Speicher abgelegt. So konnen zwei Zahler von unterschiedlichenProzessoren eines Buckets i nicht mehr in die selbe Cacheline gelangen.

213

Page 220: HEINZ NIXDORF INSTITUT Fakultät für Elektrotechnik ... Pottmeyer Memory Limitations in Artificial Intelligence ... Vitter hat gezeigt, dass viele in diesem Modell effiziente Entwicklungen

SF-Radix-Sort

L2-Fehlgriffe Entwertungen Laufzeit in s

einfache Implementation 9828950 9725467 51,29speicherbewusste Implementation 1534000 251744 5,76

Tabelle 1: Durchschnittliche Anzahl an L2-Fehlgriffe und Entwertungen von Cachelines pro Prozessorund dessen Auswirkugen auf die Laufzeit

Losung 2Eine weitere Verbesserung ist das Auslagern des Zahlervektors in den jeweiligen Prozessor.Hier rechnet jeder Prozessor auf seinen eigenen lokalen Zahlervektor und synchronisiert sichdann mit der globalen Matrix. Um dies zu realisieren mussen lediglich die ersten beiden Schrit-te des Algorithmus 1 verandert werden.

1. die lokalen Zahler mussen initialisiert werden

2. alle Prozessoren Pi berechnen ihre lokalen Zahlervektoren

kein false sharing mehr durch die Zahlervektoren. Es treten lediglich einige bei derSynchronisierung mit der globalen Matrix auf.

ErgebnisseDie zweite speicherbewusste Losung reduziert die L2-Cache-Fehlgriffe und das false sharing

signifikant. Die globalen Zugriffe werden von n- auf nbucket-Zugriffe verringert. Eine zusatzlicheVerbesserung ware das Auffullen der Cache-line, falls eine Zahlerreihe in der Mitte dieser endet.Dies wurde den Platzverbrauch zwar erhohen, aber die Anzahl false sharings weiter minimie-ren. Dieser Zusammenhang ist auch in der Tabelle 3.2 zu sehen. Sie zeigt die durchschnittlicheAnzahl von Fehlgriffen im L2-Cache und ungultige Cachelines pro Prozessor fur die jeweiligeImplementation des Radix-Sort-Algorithmus. Hierzu wurden 16 Millionen Schlussel auf demSGI Origin 2000 sortiert. Die Verbesserungen im speicherbewussten Algorithmus fuhren dabeizu einer 8,9-fachen Ausfuhrungsgeschwindigkeit.

Das Hauptproblem bei dem Algorithmus mit geteiltem Speicher ist jedoch, dass jedesmal wennein weiteres Bit der Schlussel sortiert werden soll, ein Datenaustausch zwischen Caches un-terschiedlicher Prozessoren stattfindet. Die Ursache fur diesen Transfer ist in dem Tausch desQuellvektors S und des Zielvektors D am Ende einer Iteration zu finden. Verdeutlicht wird diein dem Beispiel in Abbildung 4. Werte die im Zielvektor der ersten Iteration im Cache des Pro-zessor P1 stehen (grau gekennzeichnet), werden nach dem Tausch im Quellvektor der zweitenIteration von Prozessor P0 benotigt (weißer Bereich). Diese Daten mussen dann aus dem Ca-che des Prozessors P1 in den Cache des Prozessor P0 geladen werden.Ein weiteres Problem ist der mit der Bitanzahl der Schlussel steigende Synchronisations-aufwand. Zum Einen wird mit steigender Prozessoranzahl die Laufzeit durch die haufiger

214

Page 221: HEINZ NIXDORF INSTITUT Fakultät für Elektrotechnik ... Pottmeyer Memory Limitations in Artificial Intelligence ... Vitter hat gezeigt, dass viele in diesem Modell effiziente Entwicklungen

benotigten Synchronisationroutinen erhoht und zum Anderen mussen alle schnelleren Prozes-soren an einem Synchronisationspunkt auf den langsamsten warten, was zu einer schlechte Aus-lastung der Prozessoren fuhrt.

3.3 SF-Radix Sort mit verteiltem Speicher

Dieser Algorithmus arbeitet mit verteiltem Speicher. Er wird an dem selben Beispiel erlautertwie die beiden anderen Algorithmen zuvor. Auch hier werden wieder die niedrigswertigen Bitsbetrachtet, so wie in Abbildung 5 dargestellt. Die N -Bits werden gleichmaßig auf die im Bei-spiel verwendeten beiden Prozessoren aufgeteilt.

10

443559176481122141

716153342994917326

97

924983

0

10987654321

876543210

11

11109

1

102013013

0

987654321

10

971735446441281211

349483537392716191

59

492926

0

10987654321

876543210

11

11109

SLC

0

D

0

200102313

0

987654321

LC1

S

P0

P1

count

0

11119985541

0

987654321

LC0

0

101010997430

0

987654321

LC1

accum

10

5373921271619181211

97172635349444644

83

492959

0

10987654321

876543210

11

11109

S

SD

Abbildung 5: Beispiel einer Sortierung mit Radix-Sort mit verteiltem Speicher fur einen Schlussel mit2 Dezimalstellen

Jeder Prozessor pid wendet die drei Schritte des Counting-Algorithmus lokal unter Verwendungdes Vektors LCpid an (Zeilen 3 bis 18). Diese werden dann in eine lokale Matrix kopiert (Zeilen 19bis 22) und uber eine MPI-allgather-Funktion (Zeile 23) an alle anderen Prozessoren gesendet.Damit haben alle Prozessoren alle Zahler in ihrer jeweiligen lokalen Matrix vorliegen. Die zusendenden Daten konnen sehr groß sein, Θ(k x P 2), aber in diesem Fall sind sowohl k, derWertebereich der einzelnen Bits, als auch P , die Anzahl an Prozessoren, klein, so dass einBroadcast keine Probleme bereitet. Nun werden jedem Prozessor mehrere aufeinanderfolgendebuckets zugewiesen. Diese Zuweisung kann lokal auf der Matrix Gl berechnet werden. Umeine gut Lastverteilung zu erreichen werden die buckets an der Grenze zu zwei Prozessoren

215

Page 222: HEINZ NIXDORF INSTITUT Fakultät für Elektrotechnik ... Pottmeyer Memory Limitations in Artificial Intelligence ... Vitter hat gezeigt, dass viele in diesem Modell effiziente Entwicklungen

aufgeteilt und unter diesen beiden verteilt (Zeile 24). Anschließend werden die Daten ubereine all-to-all-Kommunikation zwischen den Prozessoren ausgetauscht, so dass jeder Prozessoraufeinanderfolgende globale buckets besitzt. Jeder dieser buckets enthalt fur alle Schlussel diegleichen Werte fur das niederwertigste Bit (Zeile 25). Abschließend mussen wieder S und D

vertauscht werden und die nachste Iteration kann beginnen.

Algorithm 2 sequentieller Radix Sortieralgorithmus mit verteiltem Speicher1: for dig = least significant digit to most significant digit do2: initialize(LC, nbuckets)

3: for i = 0 to N − 1 do4: value⇐ get digit value(S[i], dig)5: LC[value]⇐ LC[value] + 16: end for

7: tmp⇐ LC[0]8: LC[0]⇐ 09: for i = 1 to nbuckets− 1 do

10: accum⇐ tmp + LC[i− 1]11: tmp⇐ LC[i]12: LC[i]⇐ accum13: end for

14: for i = 0 to N − 1 do15: value⇐ get digit value(S[i], dig)16: D[LC[value]]⇐ S[i]17: LC[value]⇐ LC[value] + 118: end for

19: Gl[pid][0]⇐ LC[0]20: for i = 1 to nbuckets− 1 do21: Gl[pid][i]⇐ LC[i]− LC[i− 1]22: end for

23: allgather(Gl[pid][0], nbuckets,Gl

24: bucket distribution(Gl)25: data communication(S, D, Gl)

26: swap addresses(S, D)27: end for

ErgebnisseBei dem Radix-Sort mit verteiltem Speicher treten große Probleme bei der Datenkommunikati-on auf. Bei der Methode in Zeile 25 handelt es sich um ein balancedall− to− allrouting[2,3,4].Dieses Problem ist schon in vielen Arbeiten analysiert worden und wird hier nicht genauererlautert.Der Algorithmus konnte aber bei jedem Datenkommunikationsschritt einen Schlussel von ei-nem Prozessor zu einem anderen ubertragen. Da es genau so viele solcher Kommunikations-

216

Page 223: HEINZ NIXDORF INSTITUT Fakultät für Elektrotechnik ... Pottmeyer Memory Limitations in Artificial Intelligence ... Vitter hat gezeigt, dass viele in diesem Modell effiziente Entwicklungen

schritte gibt, wie der Schlussel Bits hat, nutzt diese Form des Radix-Sort die Datenlokalitatnur minimal aus.

4 Speicherbewusste Algorithmen

Die bisher vorgestellten Algorithmen sind fur das vorliegende Sortierproblem nicht effizient. Indiesem Abschnitt wird daher C3-Radix-Sort in seiner reinen Form und mit der Verwendungvon shared und distributedmemory vorgestellt.

10

443559176481122141

71615334299491732697

924983

0

10987654321

20191817161514131211

232221

2

222222233

0

987654321

0

201816141210852

0

987654321

1

2421211918171297

0

987654321

1

4434352126291217104

97838171736164535949

929491

0

10987654321

20191817161514131211

232221

S C C DC1

4435342926211712104

91838173716461595349

979492

D

count accum

Reverse Sorting

Sort bucketby bucket

buckets

Abbildung 6: Beispiel einer Sortierung mit CC-Radix-Sort fur einen Schlussel mit 2 Dezimalstellen

4.1 Cache Conscious Radix Sort

Der CC-Radix-Sort basiert auf den gleichen Prinzipien wie der einfache Radix-Sort, startetaber mit dem hochstwertigen Bit der Schlussel. Ziel dieses Algorithmus’ ist es die Lokalitat derSchlusselvektoren S, D und C zu verbessern, wenn große Datenmengen sortiert werden sollen.Abbildung 6 zeigt beispielhaft den Ablauf von CC-Radix-Sort. Zunachst fuhrt der Algorithmusdie schon bekannten drei Schritte des Counting-Algorihtmus’ startend mit dem hochstwertigenBit aus. Mit dieser Methode des ReverseSorting sind die Werte des Schlussels dann so sortiert,dass S in 2b

m−1 buckets, mit Hilfe der bm−1 hochstwertigen Bits, aufgeteilt werden kann. Da essich in dem Beispiel um Dezimalzahlen handelt, sind es hier 10 buckets. Nach dieser Sortierungsind die buckets schon untereinander fertig sortiert. Die Werte in bucket 0, 1 und 4 sind z.B.kleiner als die Werte in bucket 1, 10, 17 und 12, und diese sind wiederum kleiner als die Werteim bucket 2, 29, 26 und 21. Es mussen also nur noch die einzelnen buckets intern sortiertwerden, was durch einen einfachen Sortieralgorithmus, hier Radix-Sort, vollzogen werden kann.

217

Page 224: HEINZ NIXDORF INSTITUT Fakultät für Elektrotechnik ... Pottmeyer Memory Limitations in Artificial Intelligence ... Vitter hat gezeigt, dass viele in diesem Modell effiziente Entwicklungen

C3-Radix-Sort

L2-Fehlgriffe Entwertungen Laufzeit in s

einfache Implementation 3875000 4338310 21,69speicherbewusste Implementation 833559 311237 2,55

Tabelle 2: Durchschnittliche Anzahl an L2-Fehlgriffe und Entwertungen von Cachelines pro Prozessorund dessen Auswirkugen auf die Laufzeit

4.2 C3-Radix Sort mit geteiltem Speicher

Dieser Algorithmus ist ahnlich dem von Algorithmus 4. Der einzige Unterschied ist dass in denZeilen 3 bis 18 lediglich ein Schleifendurchlauf fur das hochstwertig Bit notwendig ist. Jetztfuhrt jeder Prozessor noch sechs Schritte aus. Die ersten vier sind die gleichen wie bei demRadix-Sort mit geteiltem Speicher, außer daß sie nur auf dem hochstwertigen Bit ausgefuhrtwerden und sind hier nur kurz angesprochen. Dazu gehoren die Initialisierung der Zahler derglobalen Matrix Gl und die drei Schritte des Counting Algorithmus: Zahlen, Inkrementierenund Verschieben der Werte. Danach entscheiden die Prozessoren lokal eine gute Verteilung derentstandenen buckets. Ist keine gute Verteilung moglich, konnen die vorherigen Schritte mitdem nachsten hochstwertigen Bit bm−2 wiederholt werden. Die Prozessoren sortieren dann ihrebuckets mit dem CC-Radix-Sort. Von jedem bucket mussen dabei nur die b −

∑rssi=1 bm−i Bits

sortiert werden, wobei rss die Anzahl der ReverseSorting-Schritte ist.Nach der Verteilung der buckets auf die Prozessoren arbeiten diese nur noch auf ihrem lokalenVektor. Dadurch wurden die Zugriffe eines Prozessors auf entfernte Caches auf eins reduziert.Der shared memory-C3-Radix Sortieralgorithmus kann die Datenlokalitat viel effektiver alsder SF-Radix-Sort ausnutzen, bei dem immer wieder auf eine globale Matrix zugegriffen wird.Weiterhin werden hier weniger Synchronisationspunkte benotigt, da nur das hochstwertigeBit betrachtet wird, und nicht wie beim SF-Radix-Sort alle Bits durchlaufen werden. Dershared memory-C3-Radix-Sort uberwindet somit die Nachteile des vorher vorgestellten SF-Radix-Sort.

Analyse der vorgestellten Radix-Sort-Algorithmen

Die Tabelle 4.2 enthalt die Anzahl von L2-Fehlgriffen, das Auftreten von ungultigen Cachelinesund die Aufuhrungszeit fur die in diesem Kapitel vorgestellten Version des C3-Radix-Sort.Es ist zu sehen dass eine nicht speicherbewusste Implementation selbst unter der Verwendungeines speicherbewussten Algorithmus’ wie den C3-Radix-Sort starke Performanzeinbußungenvorzeigt. Die speicherbewusste Implementation ist um das 8,5-fache schneller.Weiterhin kann man bei einem Vergleich mit der Tabelle 3.2 auf Seite 10 leicht gesehenwerden, dass der hier vorgestellte Algorithmus C3-Radix-Sort signifikant besser ist als der SF-Radix-Sort. Die Begrundung fur die 2,35-fache Geschwindigkeitssteigerung des normalen C3-Radix-Sort liegt in der kleineren Anzahl an L2-Fehlgriffen und der geringen Anzahl ungultiger

218

Page 225: HEINZ NIXDORF INSTITUT Fakultät für Elektrotechnik ... Pottmeyer Memory Limitations in Artificial Intelligence ... Vitter hat gezeigt, dass viele in diesem Modell effiziente Entwicklungen

Cachelines. Diese verringern sich um 39% bei dem L2-Fehlgriffen und 45% bei den ungultigenCachelines.Die speicherbewusste Implementation ist um den Faktor 2,25 schneller als der speicherbewussterSF-Radix-Sort. Die Anzahl der ungultigen Cachlines ist zwar ahnlich hoch, aber die L2-Fehlgriffe verringern sich doch um ca. 50%.

4.3 C3-Radix Sort mit verteiltem Speicher

Dieser Algorithmus gleicht dem Algorithmus 5 sehr. Wie im vorherigen Abschnitt schonbeschrieben benotigt auch der C3-Radix-Sort nur einen Schleifendurchlauf fur das hochstwertigeBit (Zeilen 2 bis 23). Jeder Prozessor sortiert eine Menge buckets lokal. Er fuhrt funf Schritteaus, wobei die ersten drei denen des Radix-Sort mit verteiltem Speicher gleichen. Es werden diedrei Schritte des Counting-Algorithmus, Zahlen, Inkrementieren, Verschieben, durchgefuhrt,die lokalen Zahler werden dann an alle anderen Prozessoren gesendet und eine gut Verteilungder entstandenen buckets wird berechnet. Dann werden die Daten kommuniziert, so dassjeder Prozessor die globalen buckets in seinem globalen Speicher hat, die im vorangegangenenSchritt berechnet wurden. Jetzt werden die buckets lokal mit dem CC-Radix-Sort sortiert,wobei hier wieder nur die b −

∑rssi=1 bm−i Bits sortiert werden und rss wieder die Anzahl der

ReverseSorting-Schritte reprasentiert.Der hier vorgestellte Algorithmus lost die Problem des SF-Radix-Sort mit verteiltem Speicher.Er fuhrt nur einen Kommunikationsschritt, statt einen fur jedes Bit des Schlussels aus. Ausdiesem Grund kann die Datenlokalitat der Schlussel ausgenutzt werden, wenn die buckets

sortiert werden. SF-Radix-Sort benotigt fur jedes Bit des Schlussels ein Kommunikationsschrittund kann daher nicht die Lokalitat der Daten ausnutzen.

5 Zusammenfassung

In dieser Seminararbeit wurde das parallele Sortieren uber eine Fallstudie an den bei-den Algorithmentypen des Straight Forward Radix sort, SF-Radix-Sort, und desCache Conscious Radixsort, C3-Radix-Sort, betrachtet. Fur beide Arten wurde eineshared memory- und eine distributed memory-Losung implementiert und analysiert.Zum Einen wird in dieser Arbeit der Einfluß der Implementationsart und der verschiedenenKommunikationsmechanismen auf die Performanz eines Algorithmus gezeigt.Im Falles des verteilten Speichers hangt die Ausfuhrungszeit stark von den L2-Cache Fehlgrif-fen und den Entwertungen von Cachelines, welche wiederum zu L2-Cache Fehlgriffen fuhrenkann, ab. Es wurde gezeigt, dass die Performanz mit einer erhohten Anzahl solcher Fehlgriffeabnimmt. Bei den speicherbewussten Implementationen des SF-Radix-Sort verringert sich dieAusfuhrungszeit z.B. um den Faktor 8,9 und bei dem C3-Radix-Sort um den Faktor 8,5, ein-hergehend mit einer stark verrigerten Anzahl von L2-Fehlgriffen.Bei der Version des C3-Radix-Sort mit verteiltem Speicher beeinflussen die vielen synchronen

219

Page 226: HEINZ NIXDORF INSTITUT Fakultät für Elektrotechnik ... Pottmeyer Memory Limitations in Artificial Intelligence ... Vitter hat gezeigt, dass viele in diesem Modell effiziente Entwicklungen

Programmiermodell SF-Radix-Sort C3-Radix Sort

Geteilter Speicher 5,76 2,55 (2,25)Verteilter Speicher 6,56 2,36 (2,78)

Tabelle 3: Ausfuhrungszeiten in Sekunden fur Algorithmen SF-Radix-Sort und C3-Radix-Sort mitgeteiltem und verteiltem Speicher

Nachrichten die Performanz. Hier wurde gezeigt dass durch die Reduzierung der festen Kostenbei Nachrichten die Performanz der Implemenation gesteigert werden kann. Eine weitere Ver-besserung ist die Verwendung von asynchronen Nachrichten, falls die Kommunikation und dieBerechnungen parallel ablaufen konnen. Die C3-Radix-Sort-Version mit den asynchron versen-deten gruppierten Nachrichten ist z.B. 1,25-mal schneller als die einfache Implementation.Zum Anderen wurde gezeigt das der speicherbewusste C3-Radix-Sortieralgorithmus sich fur

das parallele Sortieren besser eignet als der SF-Radix-Sortieralgorithmus.

Tabelle 5 bildet die Ausfuhrungszeiten fur die bei Algorithmen SF-Radix-Sort und C3-Radix-Sort einmal mit geteiltem und einmal mit verteiltem Speicher ab. Die Zahlen in den Klammernsind Faktoren um wieviel sich der C3-Radix-Sort-Algorithmus durch die Reduzierung vonDatenkommunikation auf nur einen Schritt und durch die Verbesserung der Datenlokalitat imVergleich zu SF-Radix-Sort gesteigert hat.Es ist gut zu sehen dass die Implementationen mit distributed memory besser sind als die,die shared memory verwenden. Die hier gemessenen Daten sind allerdings architekurabhangigund konnten z.B. mit der Anzahl der Prozessoren variieren.

Literaturverzeichnis

1 OpenMP. OpenMP:Simple, Portable, Scalable SMP Programming, http:www.openmp.org

2 P. Sanders und R. Solis-Oba, How helpers hasten h-relations, 8-th European Symposiumon Algorithms, 2000

3 J. F. Sibeyn, Routing with finite speeds of memory and network, 22nd Symposium onthe Mathematical Foundations of Computer Science, 1997

4 J. F. Sibeyn, Faster gossiping on butterflies, 28th International Colloqium on Automata,Languages and Programming, 2001

5 Dani Jimenez-Gonzalez, Josep-L. Larriba-Pey und Juan J. Navarro, Case Study: MemoryConscious Parallel Sorting

220