Transformationale Optimierung von Entwurfsdarstellungen der algorithmischen Ebene

Transformationale Optimierung von Entwurfsdarstellungen der algorithmischen Ebene Joachim Gerlach, Wolfgang Rosenstiel [email protected]...
Author: Petra Bösch
1 downloads 0 Views 689KB Size
Transformationale Optimierung von Entwurfsdarstellungen der algorithmischen Ebene Joachim Gerlach, Wolfgang Rosenstiel [email protected], [email protected] Universität Tübingen Arbeitsbereich Technische Informatik Sand 13 • 72076 Tübingen

Kurzfassung: Dieses Papier gibt einen Überblick über Verfahren zur Optimierung von Entwurfsdarstellungen der algorithmischen Entwurfsebene. Sämtliche der beschriebenen Optimierungsverfahren sind innerhalb des an der Universität Tübingen entstandenen Entwurfswerkzeugs ExTra (Design Space Exploration using Transformations) realisiert. Das System umfaßt weiter Verfahren zur abstrakten Bewertung und Steuerung der Auswahl und Anwendung von Optimierungsschritten und liefert somit ein Werkzeug zur automatisierten Exploration des Entwurfsraums auf algorithmischer Ebene [Ge99].

Tübingen November 1999

-1

Inhaltsverzeichnis: 1

Einleitung ....................................................................................................................................... 1

2

Grundlagen ..................................................................................................................................... 3 2.1 Entwurfsdarstellung ............................................................................................................ 3 2.2 Sprachgebrauch ................................................................................................................... 7

3

Datenfluß-Transformationen ........................................................................................................ 10 3.1 Optimierung von Feldzugriffen ........................................................................................ 10 3.2 Skalarisierung von Feldern ............................................................................................... 12 3.3 Kontraktion von Feldern ................................................................................................... 13 3.4 Propagierung von Konstantenwerten ................................................................................ 14 3.5 Elimination von Konstantenberechnungen ....................................................................... 16 3.6 Elimination temporärer Datenelemente ............................................................................ 17 3.7 Elimination gemeinsamer Teilausdrücke .......................................................................... 19 3.8 Expansion gemeinsamer Teilausdrücke ............................................................................ 20 3.9 Elimination boolescher Berechnungen ............................................................................. 21 3.10 Elimination von Komparator-Berechnungen .................................................................... 23 3.11 Normalisierung von Komparator-Berechnungen .............................................................. 24 3.12 Identifikation und Normalisierung von Schleifenzähler-Variablen .................................. 25 3.13 Manipulation von Schleifen- und Verzweigungsbedingungen ......................................... 28 3.14 Algebraische Optimierungen ............................................................................................ 29 3.15 Reduktion von Operator-Kosten ....................................................................................... 33

4

Kontrollfluß-Transformationen ..................................................................................................... 34 4.1 Partitionierung von Grundblöcken .................................................................................... 34 4.2 Verschmelzen von Grundblöcken ..................................................................................... 35 4.3 Verschieben von Grundblöcken ........................................................................................ 36 4.4 Extraktion Schleifen-unabhängiger Grundblöcke ............................................................. 39 4.5 Elimination leerer Konstrukte ........................................................................................... 40 4.6 Elimination unerreichbarer Konstrukte ............................................................................. 42 4.7 Mischen von Verzweigungskonstrukten ........................................................................... 43 4.8 Verschieben Schleifen-unabhängiger Codesegmente ....................................................... 45 4.9 Entrollen von Schleifen ..................................................................................................... 47 4.10 Partitionierung von Schleifen ............................................................................................ 51 4.11 Verschmelzen von Schleifen ............................................................................................. 54 4.12 Umkehrung der Iterationsrichtung von Schleifen ............................................................. 57 4.13 Vertauschung der Iterationsreihenfolge geschachtelter Schleifen .................................... 59 4.14 Pipelining von Schleifen ................................................................................................... 62 4.15 Expansion von Funktionsaufrufen .................................................................................... 66 4.16 Spezialisierung von Funktionen ........................................................................................ 68 4.17 Elimination unerreichbarer Funktionen ............................................................................ 71

5

Zusammenfassung ........................................................................................................................ 71

6

Literatur ........................................................................................................................................ 72

0

Transformationale Optimierung von Entwurfsdarstellungen der algorithmischen Ebene1 Joachim Gerlach, Wolfgang Rosenstiel [email protected], [email protected] Universität Tübingen Arbeitsbereich Technische Informatik Sand 13 • 72076 Tübingen Kurzfassung: Dieses Papier gibt einen Überblick über Verfahren zur Optimierung von Entwurfsdarstellungen der algorithmischen Entwurfsebene. Sämtliche der beschriebenen Optimierungsverfahren sind innerhalb des an der Universität Tübingen entstandenen Entwurfswerkzeugs ExTra (Design Space Exploration using Transformations) realisiert. Das System umfaßt weiter Verfahren zur abstrakten Bewertung und Steuerung der Auswahl und Anwendung von Optimierungsschritten und liefert somit ein Werkzeug zur automatisierten Exploration des Entwurfsraums auf algorithmischer Ebene [Ge99].

1 Einleitung Während noch vor wenigen Jahren der stetige Technologie-Fortschritt und der damit verbundene Anstieg der Entwurfskomplexität die Hauptproblematik beim Entwurf digitaler Systeme darstellte, verschiebt sich die Problematik in heutiger Zeit. Mit dem Erreichen von Komplexitätsstufen, die mit heutigen Methoden nicht mehr überschaubar sind, treten immer mehr Ansätze in den Vordergrund, die sich nicht mit der Steigerung, sondern mit der Handhabung der Entwurfskomplexität beschäftigen. Einen möglichen Ansatz hierfür stellt die Einführung neuer (höherer) Abstraktionsebenen zur Entwurfsspezifikation dar: Lieferte etwa innerhalb der Hardware-Entwurfsdomäne noch vor wenigen Jahren die Register-TransferEbene eine obere Schranke für Schaltungsbeschreibungen, sind in heutiger Zeit Ansätze verfügbar, die eine Spezifikation des Entwurfs auf algorithmischer Ebene gestatten. Ein weiterer Ansatz zur Handhabung der Komplexität von Entwürfen resultiert aus dem zunehmenden Einsatz automatisierter Entwurfsverfahren (Synthese-Verfahren). Die Entwicklung von Synthese-Ansätzen orientiert sich dabei am Anstieg der Spezifikationsebene: Während etwa innerhalb der Hardware-Entwurfsdomäne noch vor wenigen Jahren Verfahren der Logiksynthese obere Grenze der Automatisierung darstellte, sind heute automatisierte Ansätze der algorithmischen Entwurfsebene (High-Level-Synthese-Verfahren) verfügbar. Mit steigender Abstraktionsebene vergrößert sich jedoch gleichzeitig auch der Entwurfsraum auf dieser Ebene: Durch das Betrachten immer komplexerer Ausschnitte des Gesamtsystems erhöht sich zwangsläufig die Anzahl der innerhalb eines Prozeßschritts erfaßten Komponenten, was zu einer Vergrößerung des Optimierungspotentials führt. Innerhalb der Hardware-Entwurfsdomäne stellt der Übergang von der Register-Transfer-Ebene zur algorithmischen Beschreibungsebene einen wesentlichen Schritt dar: Hand in Hand mit der Erhöhung der Abstraktionsebene erfolgt ein Wechsel von der strukturellen zur verhaltensorientierten Darstellungsdomäne (was bedeutet, daß für einen Entwurf nicht dessen struktureller Aufbau, 1. Diese Arbeit wurde teilweise unterstützt durch die Deutsche Forschungsgemeinschaft, Schwerpunktprogramm „Rapid Prototyping für integrierte Steuerungssysteme mit harten Zeitbedingungen“.

1

sondern dessen funktionales Verhalten spezifiziert wird). Im Bereich der optimierenden (Software-)Compiler werden bereits seit längerer Zeit Optimierungstechniken untersucht und erfolgreich eingesetzt, die eine Manipulation der Ausgangsspezifikation auf einer Abstraktionsebene vornehmen, die der algorithmischen Entwurfsebene entspricht [AhSeUl86] [BaGrSh94]. Der Übergang zur algorithmischen Hardware-Beschreibungsebene eröffnet somit erstmals die Möglichkeit, Domänen-übergreifende Optimierungstechniken zum Einsatz kommen zu lassen, woraus eine wesentliche Vergrößerung des Optimierungspotentials resultiert (Abbildung 1 verdeutlicht die Zusammenhänge). Dieser Sachverhalt stellt insbesondere unter den Gesichtspunkten Hardware/Software-Codesign [StWo97] und dem Entwurf eingebetteter Systeme [GuAl95] einen wesentlichen Fortschritt dar. Spezifikation

Hardware

Software Optimierungspotential

Algorithmische Ebene

High-Level-Synthese

Compiler

Logik-Synthese

Assembler

Layout-Synthese

Lader/Binder

Hardwareentwurf

Softwareprogramm

AssemblerEbene

Register-TransferEbene LogikEbene LayoutEbene

MaschinencodeEbene ZielmaschinencodeEbene

Abbildung 1. Optimierungspotential im Hardware/Software-Coentwurf.

Das Entwurfswerkzeug ExTra [Ge99] beinhaltet eine Sammlung von Optimierungstechniken, deren Ursprung dem Software-Compilerbau zuzuschreiben ist. Dieses Papier stellt die algorithmische Vorgehensweise der einzelnen Optimierungsverfahren im Detail dar und erläutert exemplarisch deren Wirkungsweise. Neben den angegebenen Verfahren beinhaltet ExTra weiter Optimierungstechniken, die sich an den spezifischen Anforderungen der Hardware-Domäne orientieren und daher kein Pendant auf Software-Seite besitzen. Für deren Darstellung wird auf [Ge99] verwiesen. Das Papier ist wie folgt gegliedert: Kapitel 2 stellt die zugrundeliegende Datenstruktur zur Entwurfsdarstellung auf algorithmischer Ebene dar und erläutert eine Reihe von Begriffen, die in den folgenden Abschnitten Anwendung finden. Die nachfolgenden beiden Kapitel beinhalten eine Zusammenstellung der realisierten Optimierungsverfahren. Dabei konzentriert sich Kapitel 3 auf Verfahren, deren Wirkungsweise primär den Datenfluß, jedoch nicht unmittelbar den Kontrollfluß eines Entwurfs beeinflussen. Kapitel 4 beschreibt Optimierungsverfahren, die eine explizite Manipulation der Kontrollstruktur eines Entwurfs vornehmen.

2

2 Grundlagen 2.1 Entwurfsdarstellung Die realisierten Transformationsverfahren setzen unmittelbar auf einer Entwurfsdarstellung der algorithmischen Ebene auf. Im konkreten Fall handelt es sich hierbei um die Datenstruktur eines attributierten Kontroll-/Datenfluß-Graphen [HoEiHa94], dessen Aufbau im folgenden vorgestellt werden soll. Ein Kontroll-/Datenfluß-Graph (CDFG) besteht aus einem Kontrollfluß-Graph (CFG) und einem Datenfluß-Graph (DFG). Ein Kontrollfluß-Graph besteht aus einer Menge von Knoten, die Kontrollkonstrukte repräsentieren, sowie einer Menge von Kanten, die Kontrollfluß-Abhängigkeiten beschreiben. Eine Kante von Knoten v1 zum Knoten v2 des Kontrollfluß-Graphen signalisiert, daß das Kontrollkonstrukt des Knotens v1 stets vor dem Kontrollkonstrukt des Knotens v2 zur Ausführung kommt. Besitzt ein Knoten v1 des Kontrollfluß-Graphen mehrere ausgehende Kanten, so signalisiert dies verzweigenden Kontrollfluß (wobei eine Determinierung der Verzweigungsbedingung innerhalb des Kontrollkonstrukts von Knoten v1 erfolgt). Für die Betrachtungen der nachfolgenden Kapitel sind folgende Kontrollkonstrukte von Bedeutung: • Sequentielle Konstrukte: Sequentielle Konstrukte sind gegeben durch Grundblöcke im Sinne der klassischen Compiler-Theorie (Basic Block Node). Sonderfälle von Grundblökken stellen solche dar, die einen Funktionsaufruf (Function Node) oder einen Rücksprung aus der aktuellen Hierarchieebene (Return Node) realisieren. • Verzweigungskonstrukte: Verzweigungskonstrukte sind untergliedert in einfache Verzweigungen (If Node und End If Node, entsprechend if-then- oder if-then-else-Statements in höheren Programmiersprachen) sowie Fallunterscheidungen (Case Node und End Case Node, entsprechend switch-case-Statements in höheren Programmiersprachen). • Schleifenkonstrukte: Schleifenkonstrukte sehen eine iterierte Ausführung von Konstrukten bis zum Erreichen eines Terminierungskriteriums vor (While Node und End While Node). CFG

A

CFG

CFG While Node

If Node

Basic Block Node

Basic Block Node

Function Node

B1

Basic Block Node

Basic Block Node

B2

End If Node

D End While Node

Return Node

Sequentielle Konstrukte

Verzweigungskonstrukt (einfach)

Schleifenkonstrukt

A

CFG Case Node

Basic Block Node

B1

C

Basic Block Node

Basic Block Node

B2

Basic Block Node

B3

B4

End Case Node

Verzweigungskonstrukt (Fallunterscheidung) Abbildung 2. Konstrukte des Kontrollfluß-Graphen.

3

Abbildung 2 zeigt anhand von Beispielen die verschiedene Typen von Kontrollkonstrukten sowie deren Konkatenation mittels Kontrollfluß-Kanten. Innerhalb eines Verzweigungskonstrukts wird Knoten A (vom Typ If Node oder Case Node) als Verzweigungsbedingung und Teilgraph Bi, i∈{1,...,4}, als Verzweigungsrumpf oder Verzweigungsast bezeichnet. In analoger Weise wird innerhalb eines Schleifenkonstrukts Knoten C (vom Typ While Node) als Schleifenbedingung und Teilgraph D als Schleifenrumpf bezeichnet. Die Teilgraphen Bi und D entsprechen dabei nicht notwendig einzelnen Grundblöcken (wie in Abbildung 2 dargestellt), sondern können selbst beliebig komplexen Kontrollfluß enthalten. Im Falle von hierarchischen Entwürfen entspricht jede einzelne Funktion der Ausgangsbeschreibung einem separaten Kontroll-/Datenfluß-Graphen. Ein Funktionsaufruf wird auf Kontrollfluß-Ebene durch einen Knoten vom Typ Function Node realisiert, welcher eine Referenz auf den aufgerufenen Kontrollfluß-Graphen beinhaltet. Trifft der Kontrollfluß auf einen Funktionsaufruf, so wechselt dieser vom Function Node-Knoten zum Startknoten des aufgerufenen Kontrollfluß-Graphen. Erreicht der Kontrollfluß innerhalb des aufgerufenen Kontrollfluß-Graphen einen Knoten vom Typ Return Node, wechselt dieser zurück zum aufrufenden KontrollflußGraphen und wird dort im entsprechenden Function Node-Knoten fortgesetzt. Abbildung 3 stellt den Kontrollfluß innerhalb einer einfachen Funktionshierarchie, bestehend aus einer aufrufenden Funktion f und einer aufgerufenen Funktion g, exemplarisch dar. CFG (f)

Kontrollfluß Basic Block Node

CFG (g) Basic Block Node

Function Node Return Node Basic Block Node

Abbildung 3. Kontrollfluß in hierarchischen Entwurfsbeschreibungen.

Die Knoten des Kontrollfluß-Graphen korrespondieren auf Datenfluß-Ebene zu jeweils einem Grundblock im Sinne der klassischen Compilertheorie [AhSeUl86]. Ausnahmen hiervon bilden die Knotentypen End If Node, End Case Node und End While Node; diese dienen ausschließlich der Strukturierung des Kontrollflusses und besitzen somit kein direktes Pendant auf Datenfluß-Ebene. Ein Datenfluß-Graph entspricht einer Menge von Grundblöcken. Knoten des Datenfluß-Graphen gehören genau einem der folgenden Typen an: • Datenfluß-Knoten im klassischen Sinne: Datenfluß-Knoten im klassischen Sinne entsprechen Datenfluß-Operationen. Als Datenfluß-Operationen sollen dabei entweder Zugriffe auf Datenelemente (etwa Variablen, Felder, Speicher) oder die Anwendung von Operatoren verstanden werden. Als Operatoren sind neben den klassischen arithmetischen Operatoren (etwa Addition, Subtraktion, Multiplikation) auch solche zugelassen, die eine Indizierung von Feldzugriffen (ArrRead Node und ArrAss Node), den Aufruf einer Funktion oder die Rückgabe eines Datenwertes (Return Node) vornehmen. • Knoten zur Grundblockstrukturierung des Datenflusses: Zur Strukturierung des Datenflusses stehen Knoten der Typen BB Begin Node und BB End Node zur Verfügung, die Anfang und Ende eines Grundblocks signalisieren. Nach Definition besitzt ein Grundblock genau einen Start- und einen Endpunkt des Kontrollflusses, die somit eineindeutig den BB Begin Node- und BB End Node-Knoten entsprechen. 4

Kanten des Datenfluß-Graphen entsprechen genau einem der folgenden Typen: • Datenfluß-Kanten im klassischen Sinne: Datenfluß-Kanten im klassischen Sinne beschreiben den Datentransfer zwischen Datenfluß-Operationen. Eine Datenfluß-Kante vom Knoten v1 zum Knoten v2 signalisiert dabei, daß die Ergebnisse der zu v1 korrespondierenden Datenfluß-Operation als Eingabe der zu v2 korrespondierenden Datenfluß-Operation dienen. Dies impliziert, daß die zu v1 korrespondierende Datenfluß-Operation abgeschlossen sein muß, bevor die zu v2 korrespondierende Datenfluß-Operation zur Ausführung kommt. • Kanten zur Spezifikation der sequentiellen Abfolge von Datenfluß-Operationen: Eine Kante vom Knoten v1 zum Knoten v2 signalisiert, daß die zu v1 korrespondierende Datenfluß-Operation abgeschlossen sein muß, bevor die zu v2 korrespondierende DatenflußOperation zur Ausführung kommt. Da die sequentielle Abfolge von Operatoren implizit durch den Datentransfer festgelegt wird, dient dieser Kantentyp zur Spezifikation der sequentiellen Abfolge von Zugriffen auf Datenelemente (und wird aus diesem Grund auch als Datenabhängigkeitskante bezeichnet). • Kanten zur Grundblockstrukturierung des Datenflusses: Kanten zur Grundblockstrukturierung des Datenflusses verbinden jeweils einen BB Begin Node-Knoten mit sämtlichen Eingangsknoten des entsprechenden Grundblocks, sämtliche Ausgangsknoten eines Grundblocks mit dem entsprechenden BB End Node-Knoten sowie BB End Node-Knoten und BB Begin Node-Knoten unterschiedlicher Grundblöcke. Letztere korrespondieren zu den Kanten des Kontrollfluß-Graphen (und werden aus diesem Grund auch als Kontrollfluß-Kanten bezeichnet). Kontrollfluß-Kanten dienen der Herstellung eines zusammenhängenden Datenfluß-Graphen, wodurch sich der Umgang mit der Graphstruktur wesentlich vereinfacht (etwa die Graph-Traversierung). In Abbildung 4 sind verschiedene Beispiele von Datenfluß-Operationen angegeben: (a) realisiert eine einfache Addition zweier Variablenwerte a und b und speichert das Ergebnis in Variable c ab. (b) zeigt eine Konkatenation von Operatoren. Hier erhält die Variable c den Wert (a+2)*b. Innerhalb des in (c) dargestellten Datenfluß-Graphsegments erfolgt zuerst eine Zuweisung des Konstantenwertes 0 an die Variable a und dann eine Zuweisung des

a

b

a

b

Const 2

+

+

c

DFG DFG

=

b

*

a

=

c

DFG

Const 2 func

DFG

E

(a) (b) a

a

Const 0

x

Const 5

(d)

a

(c)

Const 3

Const 4

Const 1


) = F

C-6

( ≥ ) = T

Tabelle 2: Algebraische Identitäten mit Komparator-Ausdrücken.

Eine Anwendung der Regeln aus Tabelle 2 erfolgt wie bereits in Abschnitt 3.9 stets von links nach rechts, wobei auch hier die Terminations- und Konfluenzeigenschaft (mangels kritischer Paare) trivialerweise gegeben ist. Abbildung 20 zeigt in (a) einen Grundblock, welcher innerhalb des Datenfluß-Graphen eine Verzweigungsbedingung realisiert. Unter der Annahme der Eliminierbarkeit der Temporärvariable b sowie der Optimierung des Ausdrucks a+0 zu a kann eine Vereinfachung der Verzweigungsbedingung in die in (b) dargestellte Form vorgenommen werden. Nach Anwendung der Regeln C-3 und C-6 ergibt sich das in (c) angegebene Datenfluß-Graphsegment, welches sich durch Anwendung der booleschen Optimierungsregel B-12 weiter in die in (d) dargestellte Form vereinfachen läßt. Analog wie in Abschnitt 3.9 wird auch hier eine positive Logik zugrunde gelegt. Insgesamt konnte im Beispiel also eine Reduktion der Verzweigungsbedingung auf einen booleschen Konstantenwert vorgenommen werden, wodurch 23

unter Anwendung der in Abschnitt 4.6 angegebenen Transformation eine vollständige Elimination des Verzweigungskonstrukts möglich wird.

C-3 C-6

DFG (a)

DFG

DFG (b)

(c)

DFG

(d)

Abbildung 20. Elimination von Komparator-Berechnungen.

3.11 Normalisierung von Komparator-Berechnungen Einige Kontrollfluß-Transformationen setzen die Existenz von Verzweigungs- oder Schleifenbedingungen voraus, die in normalisierter Form vorliegen. Auf diese Weise werden weiterführende Aktivitäten wie etwa die Identifikation von Schleifenzählern oder Schleifengrenzen wesentlich vereinfacht. In diesem Zusammenhang hilfreiche Transformationen stellen die in Abschnitt 3.9 und 3.10 angegebenen Optimierungen boolescher Berechnungen und Komparator-Berechnungen dar. Diese zielen auf eine Reduktion der Komplexität zusammengesetzter boolescher Ausdrücke ab. Für die Generierung einer normalisierten Form von Verzweigungs- und Schleifenbedingungen liefert jedoch neben der Reduktion der Komplexität auch die zielgerichtete (algebraische) Umformung von Komparator-Ausdrücken ein wichtiges Hilfsmittel. Die Transformation zur Normalisierung von Komparator-Berechnungen (engl. condition normalization) zielt auf die Generierung einer normalisierten Form von Komparator-Ausdrücken ab. Unter einem normalisierten Komparator-Ausdruck soll dabei ein Ausdruck der Form verstanden werden, wobei bzw. einem beliebigen (nicht notwendig atomaren) Variablen- bzw. Konstantenausdruck und einem beliebigen Komparator entspricht. Ähnlich wie der in Abschnitt 3.14 angegebene Optimierungsschritt versucht auch diese Transformation, durch Anwendung algebraischer Regeln eine Umformung des betrachteten Ausdrucks vorzunehmen. Ziel der Transformation ist es dabei, sämtliche konstanten bzw. variablen Anteile des Ausdrucks auf jeweils einer Seite des Vergleichsoperators anzuordnen. Die Transformation schafft auf diese Weise Ausgangspunkte für weitere Optimierungen wie etwa der in Abschnitt 3.5 aufgeführten Elimination von Konstantenberechnungen.

24

Abbildung 21 zeigt ein Beispiel: Aus Datenfluß-Graphsegment (a) entsteht durch Zusammenfassung sämtlicher konstanter bzw. variabler Komponenten der Schleifenbedingung auf jeweils einer Seite der Ungleichung das in (b) dargestellte Datenfluß-Graphsegment. Auf diese Weise wird eine Umformung des Ausdrucks 7-i-1>3 in i0 angenommen, was durch Anwendung der in Abschnitt 3.12 angegebenen Transformation zur Normalisierung von SchleifenzählerVariablen erreicht werden kann. A

li < ub

B A

A‘

li < ub

B

C

C

B

li < ub - ink(li,C)

x

C

(a)

(b)

Abbildung 50. Transformation zum Pipelining von Schleifen.

Innerhalb der Pipelining-Transformation erfolgt die Identifikation eines Partitionierungspunkts auf heuristische Weise. Hierzu wird zunächst die Menge aller legalen Partitionierungspunkte des Schleifenrumpfs ermittelt. Aus dieser wird anschließend heuristisch ein Kandidat ausgewählt, welcher ein gewinnbringendes Pipelining erwarten läßt (was genau dann der Fall ist, wenn ein Verschmelzen der Kontroll-Konstrukte vom Schleifenrumpf-Ende des Teilgraphen A und vom Schleifenrumpf-Anfang des Teilgraphen B durchführbar ist). Insbesondere sei dabei angemerkt, daß die beim Pipelining an den Partitionierungspunkt des Schleifenrumpfs gestellten Forderungen wesentlich schwächer sind als im Falle der in Abschnitt 4.10 erläuterten Transformation zur Partitionierung von Schleifenkonstrukten. Beim Pipelining erfolgt eine Umkehrung der Abarbeitungsreihenfolge des Schleifenrumpfs durch Vertauschung der Teilgraphen B und C. Dabei wird die Schleifenbedingung A durch eine Schleifenbedingung A‘ ersetzt, innerhalb welcher durch Reduktion der oberen Schleifengrenze ub um den Faktor ink(li,C) die Iterationszahl des Schleifenrumpfs dekrementiert wurde. Durch Duplikation des Teilgraphen B vor das Schleifenkonstrukt (korrespondierend zur Phase der Pipeline-Initialisierung) sowie Duplikation des Teilgraphen C hinter das Schleifenkonstrukt (korrespondierend zur Phase der Pipeline-Entleerung) ist sicherzustellen, daß keine Veränderung des funktionalen Verhaltens erfolgt. Ferner ist durch Einbettung des Schleifenkonstrukts in ein Verzweigungskonstrukt mit Verzweigungsbedingung A‘‘ zu gewährleisten, daß die Transformation auch dann keine Veränderung des funktionalen Verhaltens bewirkt, wenn der Schleifenrumpf innerhalb des Abarbeitungskontexts nicht zur Ausführung kommt. Durch wiederholte Anwendung der Transformation für unterschiedliche Partitionierungspunkte des Schleifenrumpfs wird ein mehrstufiges Pipelining realisiert.

64

A‘‘ B

A‘‘ A‘

A

C B

B C

C

CFG A

B

CFG

A‘

B

C C C DFG

B

DFG (a)

(b) Abbildung 51. Pipelining von Schleifen (1).

Abbildung 51 zeigt in (a) das Beispiel eines einfachen Schleifenkonstrukts, welches durch Anwendung der Pipelining-Transformation in die in (b) dargestellte Form überführt wird. Innerhalb die Transformation wurde ein Partitionierungspunkt derart gewählt, daß der Schleifenrumpf in einen aus zwei Kontrollkonstrukten bestehenden konsistenten Teilgraphen B und einen aus einem Grundblock bestehenden Teilgraphen C zerfällt. Dabei wurde die Variable i als Schleifenzähler erkannt und innerhalb des Schleifenrumpfs der konstante Inkrement-Faktor ink(i,C)=1 identifiziert. Abbildung 52 zeigt in (a) den resultierenden Schleifenrumpf aus Abbildung 51 (b) sowie einen möglichen Ablaufplan des Kontroll-/ Datenfluß-Segments. Durch Anwendung der in Abschnitt 4.2 beschriebenen Transformation 65

zum Verschmelzen von Grundblöcken kann eine Optimierung des Schleifenrumpfs in die in Abbildung 52 (b) dargestellte Form durchgeführt werden. Auf diese Weise kann eine nebenläufige Ausführung der Operationen op2 und op3 erreicht werden, wodurch sich der Ablaufplan des Schleifenrumpfs um einen Zeitschritt reduziert. CFG CFG

C B op1 C

op2

op1 cstep

cstep

i

Op1

i

Op1

i+1

Op2

i+1

Op2 Op3

i+2

Op3

.....

B

op3

.....

op3

op2

DFG

DFG (a)

(b) Abbildung 52. Pipelining von Schleifen (2).

4.15 Expansion von Funktionsaufrufen Die Möglichkeit zur modularen und hierarchischen Entwurfsspezifikation stellt ein unverzichtbares Werkzeug zur Handhabung komplexer Entwürfe dar und begünstigt moderne Entwurfskonzepte wie etwa Reuse-Techniken. Wesentliche Vorteile der Verwendung hierarchischer Beschreibungssprachen sind: • Ist an mehreren Stellen des Kontrollflusses eine bestimmte Funktionalität zu erbringen, bewirkt eine Realisierung dieser Funktionalität als eigenständige Funktion eine Reduktion des Beschreibungsaufwands auf Spezifikationsebene sowie eine Verringerung des Realisierungsaufwands auf Implementierungsebene. • Die Auslagerung von Funktionalität in eigenständige Funktionen führt zu einer Vereinfachung der Entwurfsbeschreibung und Verbesserung der Lesbarkeit der Spezifikation. • Die aus der Verwendung hierarchischer Beschreibungssprachen resultierende Partitionierung der Komplexität eines Entwurfs vereinfacht nachfolgende Entwurfsschritte, da innerhalb der Entwurfswerkzeuge einzelne Funktionen in der Regel als autonome Einheiten abgearbeitet werden. Trotzdem besitzt die Verwendung hierarchischer Beschreibungskonzepte auch Nachteile, die hauptsächlich in folgenden Sachverhalten begründet liegen:

66

• Die Instanziierung einer Funktion bedeutet stets Zusatzaufwand, da administrative Arbeiten wie etwa die Abbildung von aktuellen auf formale Schnittstellenparameter oder die Verwaltung eines Rücksprungpunktes für den Kontrollfluß erfolgen muß. • In der Regel unterstützen Entwurfswerkzeuge keine Hierarchie-übergreifenden Optimierungen, wodurch Optimierungspotential an den Funktionsschnittstellen verloren geht. Aus diesen Argumenten resultiert ein Trade-Off für den Einsatz von Funktionsaufrufen in Entwurfsbeschreibungen. Eine in diesem Zusammenhang wichtige Transformation stellt die Expansion von Funktionsaufrufen (engl. function inlining) dar. Die Transformation der Expansion von Funktionsaufrufen ersetzt innerhalb des Kontroll-/Datenflusses eine Stelle der Instanziierung einer Funktion durch eine entsprechend parametrisierte Kopie des Funktionsrumpfs. Die Vorgehensweise zur Expansion einer Funktion an einer gegebenen Stelle ihrer Instanziierung ist folgende: 1. In einem ersten Schritt erfolgt eine Duplikation der Schachtelungseinheit des Funktionsrumpfs in die Schachtelungseinheit des Funktionsaufrufs. 2. Der zweite Schritt beinhaltet die Auflösung von Namenskonflikten, die potentiell beim Einfügen des duplizierten Schleifenrumpfs in die Schachtelungseinheit des Funktionsaufrufs entstehen. Hierzu sind im Kollisionsfall lokale Datenstrukturen des duplizierten Schleifenrumpfs an jeder Stelle ihres Auftretens durch neue typgleiche temporäre Datenstrukturen zu ersetzten. 3. Im dritten Schritt wird ein Grundblock generiert, innerhalb welchem eine Zuordnung von aktuellen Parametern des Funktionsaufrufs zu formalen Parametern der Funktionsschnittstelle erfolgt. In analoger Weise wird ein Grundblock erzeugt, der eine Zuordnung von Rückgabewerten der Funktion und Ergebniswerten des Funktionsaufrufs vornimmt. Im Fall einer leeren Parameterliste bzw. bei fehlenden Rückgabewerten kann auf eine Generierung des entsprechenden Grundblocks verzichtet werden. 4. Im vierten Schritt erfolgt eine Anpassung der Attribute der Schnittstellenparameter innerhalb des duplizierten Schleifenrumpfs. 5. Schließlich kann unter Verwendung der im dritten Schritt erzeugten Grundblöcke eine Substitution des Funktionsaufrufs durch das im zweiten Schritt generierte Duplikat des Schleifenrumpfs vorgenommen werden. Abbildung 53 verdeutlicht die Wirkungsweise der Transformation zur Expansion von Funktionsaufrufen anhand eines einfachen Beispiels: Innerhalb der in (a) dargestellten Funktionshierarchie erfolgt in Block A ein Aufruf der Funktion plus, welche als Eingabe zwei ganzzahlige Werte erwartet und als Rückgabewert einen ganzzahligen Wert liefert. Bei der Duplikation des Funktionsrumpfs B entsteht ein Namenskonflikt, der durch Substitution der Variable a durch eine interne Variable a_i0 aufgelöst wird (in Grundblock B‘). Innerhalb der Grundblöcke C und D wird eine Zuordnung der aktuellen Parameter a und 1 zu den formalen Parametern a_i0 und d, sowie eine Zuordnung der Rückgabevariable x zur Ergebnisvariable b vorgenommen. (b) zeigt die resultierende Kontroll-/Datenfluß-Struktur, die in der expandierten Form Ausgangspunkt für weiterer Optimierungen darstellt. Insbesondere kann für den Fall, daß innerhalb der Funktionshierarchie keine weitere Instanziierung der Funktion plus erfolgt, unter Anwendung der in Abschnitt 4.17 beschriebenen Transformation eine Elimination der Funktionen plus vorgenommen werden.

67

CFG CFG

C B‘ D

A

C A

CFG

B

B‘

B D

DFG

DFG DFG (a)

(b) Abbildung 53. Expansion von Funktionsaufrufen.

4.16 Spezialisierung von Funktionen Die im vorigen Abschnitt erläuterte Transformation zur Expansion von Funktionsaufrufen erlaubt die vollständige Elimination eines Funktionsaufrufs und ermöglicht auf diese Weise Hierarchie-übergreifende Optimierungen. Die in diesem Abschnitt beschriebene Transformation zur Spezialisierung von Funktionen (engl. function cloning) bewirkt keine vollständige Elimination eines Funktionsaufrufs, sondern zielt darauf ab, den Aufruf einer Funktion durch den entsprechenden Aufruf einer optimierten Variante der Funktion zu ersetzen. Das Potential zur Optimierung des Funktionsrumpfs resultiert dabei aus einer Analyse der Schnittstellenparameter und ist somit unmittelbar an den Kontext des Funktionsaufrufs gebunden: Kann beispielsweise mittels einer Datenfluß-Analyse gezeigt werden, daß der Aufruf einer Funktion mehrfach oder ausschließlich unter Verwendung einer Parametrisierung erfolgt, in welcher bestimmten Schnittstellenparametern identische konstante Werte zugeordnet sind, wirkt sich die Bereitstellung einer entsprechend optimierten Variante der Funktion (mit reduzierter Parameterliste) in vielen Fällen positiv auf das Entwurfsergebnis aus. Die Transformation zur Spezialisierung von Funktionen stellt eine mächtige Kontrollfluß-Transformation dar, da sie häufig eine Elimination großer Abschnitte des Funktions-

68

rumpfs ermöglicht. Die Vorgehensweise zur Spezialisierung einer Funktion innerhalb einer gegeben Entwurfshierarchie ist folgende: 1. Für eine gegebene Funktion wird mittels einer Datenfluß-Analyse die Menge aller spezialisierten Kandidaten identifiziert. Kandidaten für eine Spezialisierung liefern dabei Funktionsinstanziierungen, die eine Reduktion ihrer Schnittstellenparameter erlauben, etwa aufgrund von konstanten Werten oder Datenabhängigkeiten innerhalb der Argumentlisten. 2. Wurde im ersten Schritt eine Funktion an einer bestimmten Stelle ihres Aufrufs als Kandidat für eine Spezialisierung erkannt, wird durch Duplikation des Funktionsrumpfs und generische Erweiterung des Funktionsbezeichners eine spezialisierte Variante der Funktion mit reduzierter Argumentliste erzeugt. 3. Innerhalb der spezialisierten Funktionsvariante ist ein Grundblock zu generieren, in welchem eine Initialisierung der durch die Reduktion der Argumentliste eliminierten Schnittstellenparameter vorgenommen wird. 4. Durch die Fixierung von Schnittstellenparametern vergrößert sich das Optimierungspotential innerhalb der spezialisierten Funktionsvariante. Daher ist auf dieser ein isolierter transformationaler Optimierungsprozeß anzustoßen. Die Wirkungsweise der Transformation soll anhand eines einfachen Beispiels demonstriert werden: In Abbildung 54 ist eine einfache Funktionshierarchie bestehend aus einer aufrufenden Funktion main und einer aufgerufenen Funktion plus dargestellt. Die Funktion plus erwartet eine Argumentliste bestehend aus drei ganzzahlige Werten und liefert einen ganzzahligen Rückgabewert. Die Funktion plus berechnet die Summe zweier ganzzahliger Werte, wobei mittels eines dritten Schnittstellenparameters mode spezifiziert werden kann, ob für die Addition ein einfacher Addierer oder eine komplexere Variante mit Sättigungslogik zum Einsatz kommen soll: plus ( x, y, 0 ) = x + y  – 128  plus ( x, y, 1 ) =  x + y   127

falls x + y < – 128 falls – 128 ≤ x + y ≤ 127 falls x + y > 127

Die Transformation zur Spezialisierung von Funktionen identifiziert innerhalb des dargestellten Aufrufs der Funktion plus das konstante Argument mode=0. Unter der Annahme, daß ein Aufruf der Funktion plus an sämtlichen Stellen des Kontrollflusses mit der identischen konstanten Belegung des Arguments mode erfolgt (also zur Addition stets die einfache Variante des Addierers verwendet wird), generiert die Transformation eine spezialisierte Funktionsvariante plus_x_x_0, deren Argumentliste um den Parameter mode reduziert ist. Innerhalb der spezialisierten Funktionsvariante wird eine entsprechende konstante Belegung der Variablen mode mit dem Wert 0 vorgenommen. Durch Anwendung der Datenfluß-Transformationen zur Propagierung von Konstantenwerten (Abschnitt 3.4), zur Elimination von Temporärdaten (Abschnitt 3.6) und zur Normalisierung von Verzweigungsbedingungen (Abschnitt 3.11) sowie der Kontrollfluß-Transformation zur Elimination unerreichbarer Konstrukte (Abschnitt 4.6) kann innerhalb der spezialisierten Funktionsvariante eine vollständige Elimination der komplexeren Addierer-Variante vorgenommen werden. Durch eine zusätzliche Anwendung der Transformation zur Elimination unerreichbarer Funktionen (Abschnitt 4.17) resultiert die in Abbildung 55 dargestellte Funktionshierarchie.

69

main ()

CFG

CFG

int plus ( int x, int y, int mode )

DFG

Abbildung 54. Spezialisierung von Funktionen (1).

Aus dem Beispiel lassen sich zweierlei positive Effekte der Transformation ableiten: • Die Spezialisierung von Funktionen bewirkt eine Elimination von Schnittstellenparametern und reduziert so den Umfang der beim Funktionsaufruf zu transferierenden Datenelemente. • Durch die Spezialisierung von Funktionen vergrößert sich das transformationale Optimierungspotential innerhalb der spezialisierten Funktionsvariante wesentlich, was Ausgangspunkt für nachfolgende Transformationen darstellt. Die realisierte Transformation unterstützt eine flexible Identifikation auch komplexer Abhängigkeiten zwischen den Schnittstellenparametern eines Funktionsaufrufs. Hierzu wird zusätzlich zur Analyse der Parameterliste eine Analyse der dem Funktionsaufruf vorangehenden Kontroll-/Datenfluß-Struktur durchgeführt. So ist der Algorithmus etwa in der Lage, den konstanten Wert eines Schnittstellenparameters auch dann korrekt zu erkennen, wenn 70

dieser aus mehreren (konsistenten) Zuweisungen an unterschiedlichen Positionen des Kontroll-/Datenflusses resultiert. CFG main ()

int plus_x_x_0 ( int x, int y ) CFG

DFG DFG Abbildung 55. Spezialisierung von Funktionen (2).

4.17 Elimination unerreichbarer Funktionen Eine weitere Transformation zur Optimierung von hierarchischen Entwurfsbeschreibungen stellt die Elimination unerreichbarer Funktionen (engl. dead function elimination) dar. Innerhalb der Transformation werden mittels einer Hierarchie-übergreifenden Datenfluß-Analyse Funktionen der Ausgangsbeschreibung identifiziert, für die an keiner Stelle des Kontrollflusses ein Aufruf erfolgt. Diese Funktionen stellen für den Kontrollfluß unerreichbare Konstrukte dar, die somit aus der Funktionshierarchie entfernt werden können. Auf diese Weise wird die Implementierung redundanter Entwurfsabschnitte verhindert. Innerhalb der Transformation wird eine Hierarchie-übergreifende Erreichbarkeitsanalyse durchgeführt. Dabei werden sämtliche Positionen von Funktionsaufrufen in einer globalen Datenstruktur protokolliert. Nach Terminierung der Erreichbarkeitsanalyse kann durch Analyse der Datenstruktur eine Identifikation von Funktionen durchgeführt werden, für die an keiner Stelle des Kontrollflusses eine Instanziierung erfolgt. Diese werden aus der Funktionshierarchie entfernt. Die Ausgangssituation zur Anwendung der Transformation tritt häufig als Konsequenz der in den Abschnitten 4.15 und 4.16 aufgeführten Transformationen zur Expansion von Funktionsaufrufen und zur Spezialisierung von Funktionen auf.

5 Zusammenfassung Das an der Universität Tübingen entstandenen Entwurfswerkzeugs ExTra (Design Space Exploration using Transformations) [Ge99] beinhaltet eine Sammlung von Domänen-unabhängigen Optimierungstransformationen der algorithmischen Ebene. Dieses Papier gibt 71

einen Überblick über die realisierten Verfahren und erläutert deren algorithmische Vorgehensweise im Detail.

6 Literatur [AhSeUl86]

A.V.Aho, R.Sethi, J.D.Ullman, Compilers: Principles, Techniques and Tools, Addison Wesley, 1986.

[Av95]

J. Avenhaus. Reduktionssysteme. Springer-Verlag, 1995.

[BaGrSh94]

D.F. Bacon, S.L. Graham, O.J. Sharp. Compiler Transformations for High-Performance Computing. ACM Computing Surveys, Vol. 26, No. 4, December 1994, pp. 345-420.

[Bu97]

R. Bündgen. Termersetzungssysteme - Theorie, Implementierung, Anwendung. Vieweg Verlag, 1997.

[BuCoLo82]

B. Buchberger, G.E. Collins, R. Loos (Eds.). Computer Algebra: Symbolic and Algebraic Computation. Springer-Verlag, 1982.

[CaCoKe86]

D. Callahan, K.D. Cooper, K. Kennedy, L. Torczon. Interprocedural Constant Propagation. ACM SIGPLAN Notices, Vol. 21, No. 7, 1986, pp. 152-161.

[De74]

N. Deo. Graph Theory with Application to Engineering and Computer Science. PrenticeHall, Series in Automatic Computation, 1974.

[GaDuWu92]

D.D. Gajski, N. Dutt, A. Wu, S. Lin. High-Level Synthesis: Introduction to Chip and System Design. Kluwer Academic Publishers, 1992.

[GaJaGa88]

D. Gannon, W. Jalby, K. Gallivan. Strategies for Cache and Local Memory Management by Global Program Transformation. Journal on Parallel and Distributed Computing, Vol. 5, No. 5, October 1988, pp. 587-616.

[Ge99]

J. Gerlach. Transformationale Entwurfsraum-Exploration für den Entwurf eingebetteter Systeme. Dissertation, Universität Tübingen, 2000 (to appear).

[GiMa90]

L.G. Gilligan, J.F. Marquardt. CALCULUS and the DERIVE Program. Gilmar Publishing Company, 1990.

[GuAl95]

R.K. Gupta, J. Allen (Eds.). Co-Synthesis of Hardware and Software for Digital Embedded Systems. Kluwer International Series in Engineering and Computer Science, 329. Kluwer Academic Publishers. July 1995.

[HoEiHa94]

A. Hoffmann, H.-J. Eikerling, W. Hardt, R. Genevriere. PSF - Paderborn Synthesis Format. Technical Report SFB 358-B2-6/94. University of Paderborn, Technical University of Dresden, June 1994.

[JoAl90]

R.B. Jones, V.H. Allen. Software Pipelining: A Comparison and Improvement. Symposium and Workshop on Microprogramming and Microarchitecture (MICRO’23), Orlando, Florida, November 1990, pp. 46-56.

[Ko94]

M. Kofler. Maple V Release 3: Einführung und Leitfaden fuer den Praktiker. AddisonWesley, 1994.

[McCaWr91]

M.A.H. McCallum, F.J. Wright. Algebraic Computing with REDUCE. Oxford University Press, 1991.

[Mu97]

S.S. Muchnick. Advanced Compiler Design and Implementation. Morgan Kaufmann Publishers, 1997.

[PaHe95]

D.A. Patterson, J.L. Hennessy. Computer Architecture: A Quantitative Approach (Second Edition). Morgan Kaufmann Publishers, 1995.

[RiJa96]

M. Rim, R. Jain. Valid Transformations: A New Class of Loop Transformations for HighLevel Synthesis and Pipelined Scheduling Applications. IEEE Transactions on Parallel and Distributed Systems, Vol. 7, No. 4, April 1996, pp. 399-410.

72

[SaCo95]

F. Sanchez, J. Cortadella. Time-Constrained Loop Pipelining. IEEE/ACM International Conference on Computer-Aided Design (ICCAD‘95), San Jose, California, November 1995, pp. 592-596.

[SaTh92]

V. Sarkar, R. Thekkath. A General Framework for Iteration-Reordering Loop Transformations (Technical Summary). ACM SIGPLAN Notices, Vol. 27, No. 7, July 1992, pp. 175-187.

[StWo97]

J. Staunstrup, W.Wolf (Eds.). Hardware/Software Co-Design - Principles and Practice. Kluwer Academic Publishers, 1997.

[WeZa91]

M.N. Wegman, F.K. Zadeck. Constant Propagation with Conditional Branches. ACM Transactions on Programming Languages and Systems, Vol. 13, No.2, April 1991, pp. 181-210.

[Wo88]

M. Wolfe. Vector Optimization Versus Vectorization. Journal on Parallel and Distributed Computing, Vol. 5, No. 5, October 1988, pp. 551-567.

[Wo97]

S. Wolfram. Das Mathematica-Buch: Mathematica Version 3 . Addison-Wesley-Longman, 1997.

[WoLa91]

M.E. Wolf, M.S. Lam. A Loop Transformation Theory and an Algorithm to Maximize Parallelism. IEEE Transactions on Parallel and Distributed Systems, Vol. 2, No. 4, October 1991, pp. 452-471.

73

Suggest Documents