[Informatik-Fachberichte] Parallele Implementierung funktionaler Programmiersprachen Volume 232 ||...

12
Einleitung Funktionale Programmiersprachen haben eine Reihe von interessanten Vorteilen gegeniiber imperativen Sprachen. Ein funktionales Programm entspricht im we- sent lichen einer Funktion im mathematischen Sinne, die auf die Eingabewerte an- gewendet wird und den Funktionswert als Ausgabe liefert. Der A-Kalkiil von Church und seine Theorie bilden die mathematische Basis der funktionalen Pro- grammierung. Auf Grund dieser mathematischen Tradition haben funktionale Programmiersprachen eine verhaltnismafiig einfache und klare Semantik, die eine wichtige Grundlage fUr Korrektheitsbeweise, Verifikation von Programmeigenschaf- ten sowie fUr Programmtransformationen bildet. In diesem Zusammenhang ist auch die Eigenschaft der "referential transparency" zu nennen: Der Wert eines Ausdruckes hangt nur von seiner Umgebung, nicht aber vom Zeitpunkt seiner Auswertung abo In einem funktionalen Programm kann ein Teilausdruck also im- mer durch einen anderen Ausdruck, der denselben Wert hat, ersetzt werden. Die Semantik des Programms bleibt unverandert. Der Programmentwurf erfolgt in einer funktionalen Sprache auf einer sehr viel h6heren Abstraktionsstufe als in einer imperativen Sprache. Auf Grund dessen sind funktionale Programme ausdrucksstarker und kiirzer als entsprechende im- perative. In Bild 1 ist als Beispiel der Quicksortalgorithmus zur Sortierung einer Folge von ganzen Zahlen in PASCAL und MIRANDA * angegeben. Die PASCAL-Prozedur erwartet die zu sortierenden Zahlen in einem Array, in dem dann in geschickter Weise Elemente vertauscht werden. Das MIRANDA- Programm arbeitet auf einer Liste von ganzen Zahlen, indem die Teillisten der Elemente, die gr6fier bzw. kleiner als das erste Element der Liste sind, sortiert werden und in geeigneter Weise konkateniert werden. Die besondere Ausdrucksstarke funktionaler Sprachen ist groBtenteils darauf zuriickzufUhren, daB Funktionen wie andere Werte behandelt werden, also sowohl *Miranda ist eine funktionale Sprache, die von David Turner [Turner 85J entwickelt wurde. Das Miranda-System ist ein Warenzeichen der Firma Research Software Limited. R. Loogen, Parallele Implementierung funktionaler Programmiersprachen © Springer-Verlag Berlin Heidelberg 1990

Transcript of [Informatik-Fachberichte] Parallele Implementierung funktionaler Programmiersprachen Volume 232 ||...

Page 1: [Informatik-Fachberichte] Parallele Implementierung funktionaler Programmiersprachen Volume 232 || Einleitung

Einleitung

Funktionale Programmiersprachen haben eine Reihe von interessanten Vorteilen gegeniiber imperativen Sprachen. Ein funktionales Programm entspricht im we­sent lichen einer Funktion im mathematischen Sinne, die auf die Eingabewerte an­gewendet wird und den Funktionswert als Ausgabe liefert. Der A-Kalkiil von Church und seine Theorie bilden die mathematische Basis der funktionalen Pro­grammierung. Auf Grund dieser mathematischen Tradition haben funktionale Programmiersprachen eine verhaltnismafiig einfache und klare Semantik, die eine wichtige Grundlage fUr Korrektheitsbeweise, Verifikation von Programmeigenschaf­ten sowie fUr Programmtransformationen bildet. In diesem Zusammenhang ist auch die Eigenschaft der "referential transparency" zu nennen: Der Wert eines Ausdruckes hangt nur von seiner Umgebung, nicht aber vom Zeitpunkt seiner Auswertung abo In einem funktionalen Programm kann ein Teilausdruck also im­mer durch einen anderen Ausdruck, der denselben Wert hat, ersetzt werden. Die Semantik des Programms bleibt unverandert.

Der Programmentwurf erfolgt in einer funktionalen Sprache auf einer sehr viel h6heren Abstraktionsstufe als in einer imperativen Sprache. Auf Grund dessen sind funktionale Programme ausdrucksstarker und kiirzer als entsprechende im­perative. In Bild 1 ist als Beispiel der Quicksortalgorithmus zur Sortierung einer Folge von ganzen Zahlen in PASCAL und MIRANDA * angegeben.

Die PASCAL-Prozedur erwartet die zu sortierenden Zahlen in einem Array, in dem dann in geschickter Weise Elemente vertauscht werden. Das MIRANDA­Programm arbeitet auf einer Liste von ganzen Zahlen, indem die Teillisten der Elemente, die gr6fier bzw. kleiner als das erste Element der Liste sind, sortiert werden und in geeigneter Weise konkateniert werden.

Die besondere Ausdrucksstarke funktionaler Sprachen ist groBtenteils darauf zuriickzufUhren, daB Funktionen wie andere Werte behandelt werden, also sowohl

*Miranda ist eine funktionale Sprache, die von David Turner [Turner 85J entwickelt wurde. Das Miranda-System ist ein Warenzeichen der Firma Research Software Limited.

R. Loogen, Parallele Implementierung funktionaler Programmiersprachen© Springer-Verlag Berlin Heidelberg 1990

Page 2: [Informatik-Fachberichte] Parallele Implementierung funktionaler Programmiersprachen Volume 232 || Einleitung

2

a) Standard-Quicksortalgorithmus in PASCAL:

procedure quicksort (I,r : integer); var x, i, j, tmp : integer; begin

end

ifr> 1 then begin

end

x := a[I]; i := 1; j := r+1; repeat

repeat i:=i+1 until a[ikx; repeat j:=j-1 until a[j]sx; tmp := a[j]; a[j] := ali]; ali] := tmp;

until jsi; . ali] := a[j]; a[j] := a[I]; a[I] := tmp; quicksort (1, j-1); quicksort (j+1, r);

b) Standard-Quicksortalgorithmus in MIRANDA:

quicksort [] = quicksort (x:I) =

[] quicksort (filter « x) 1) ++ [x] ++ quicksort (filter (>= x) 1)

(filter bezeichnet eine Bibliotheksfunktion, deren Definition in Bild 2 angege­ben ist. ++ ist ein Infixoperator zur Listenkonkatenation. « x) und (>= x) bezeichnen einstellige Priidikate, die genau dann den Wert 'true' ergeben, wenn ihr Argument kleiner bzw. grosser als der Wert von x ist.)

Bild 1: Gegeniiberstellung eines imperativen und eines funktionalen Programms

Page 3: [Informatik-Fachberichte] Parallele Implementierung funktionaler Programmiersprachen Volume 232 || Einleitung

3

als Parameter als auch als Ergebnis einer Funktionsapplikation auftreten konnen. Funktionen, bei denen Funktionen als Ein- undjoder Ausgabewerte zugelassen sind, heiBen Funktionen haherer Ordnung oder Funktionale. Sie erlauben etwa die Beschreibung allgemeiner Algorithmen oder Verfahren, die durch die Funktions­parameter an verschiedene Kontexte oder Erfordemisse angepaBt werden konnen.

Die in dem MIRANDA-Quicksortprogramm in Bild Ib verwendete Bibliotheks­funktion filter ist ein Funktional, das aus einer Liste eine Teilliste von Elementen herausfiltert, die eine Eigenschaft besitzen, die durch eine als Parameter iiber­gebene Testfunktion 'test' spezifiziert wird. Die MIRANDA-Spezifikation dieses Funktionals ist in Bild 2 angegeben.

filter test [] filter test (x:l)

= [] = x: (filter test 1), = filter test 1,

test x '" (test x)

('" bezeichnet die logische Negation. Die zweite Definitionsgleichung be­schreibt eine Fallunterscheidung ('guarded expression') nach dem Ergebnis der Applikation der Testfunktion auf das Kopfelement der Argumentliste.)

Bild 2: Beispiel einer Funktion hoherer Ordnung

Durch Aufrufe der Funktion filter mit geeigneten Testfunktionen kann aus einer beliebigen Liste von ganzen Zahlen z.B. die Teilliste der geraden oder ungeraden Zahlen oder, wie im Quicksortprogramm, die Teilliste der Zahlen, die ober- oder unterhalb einer bestimmten Schranke liegen, erzeugt werden.

Funktionen hoherer Ordnung sind ein wichtiges Konzept zur Entwicklung mo­dularer Programme, da sie die Definition allgemeiner, wiederverwendbarer Module ermoglichen. Wie in [Hughes 84] durch interessante Beispiele gezeigt wird, un­terstiitzt auch die Verwendung von 'lazy evaluation' als Auswertungsstrategie die Modularisierung von Programmen. 'Lazy evaluation' bedeutet verzogerte Auswer­tung und bezieht sich auf die Auswertung der Argumente einer Funktionsapplika­tion. Die Auswertung eines Funktionsargumentes wird solange verzogert, bis sein Wert zur Bestimmung des Funktionsresultates benotigt wird. Dies hat den Vor­teil, daB Argumente, die zur Bestimmung des Ergebnisses nicht notig sind, auch nicht ausgewertet werden. Insbesondere kann der Wert einer Funktionsapplika­tion somit definiert sein, obwohl der Wert eines Argumentes undefiniert ist. Auch strukturierte Datenobjekte werden nur insoweit ausgewertet, wie sie benotigt wer­den, so daB auch unendliche Datenstrukturen wie andere Werte behandelt werden

Page 4: [Informatik-Fachberichte] Parallele Implementierung funktionaler Programmiersprachen Volume 232 || Einleitung

4

konnen. 'Lazy evaluation' erlaubt demnach die Verwendung von Teilprogrammen (Modulen), die eine unendliche Ausgabe generieren. Die Termination der Gesamt­berechnung wird nicht geHihrdet, da die Auswertung der Teilprogramme durch die umgebenden Programmteile gesteuert wird. Bild 3 zeigt ein MIRANDA-Programm zur Bestimmung von Fibonacci-Zahlen.

fib i = get (genfib 1 1) i where get [] i = get (x:D 1 = get (x:l) (HI) = genfib x y

o x get Ii x: (genfib y (x+y))

Bild 3: Beispiel zur Programmierung mit unendlichen Datenstrukturen

Die in diesem Programm verwendete Funktion genfib erzeugt die unendliche Liste aller Fibonacci-Zahlen.

Alle diese Besonderheiten funktionaler Programmiersprachen erweisen sich lei­der als problematisch, wenn man sie von der Seite der Implementierung von Pro­grammiersprachen auf von Neumann-Rechnern betrachtet. Imperative Sprachen sind auf die Programmierung von von Neumann-Rechnern ausgerichtet. Sie sind gewissermafien Abstraktionen dieser Computer und daher aufierst effizient auf denselben zu implementieren. Beim Entwurf funktionaler Sprachen stehen die mathematischen Eigenschaften sowie die Ausdrucksstarke der Programme im Vor­dergrund. Dadurch sind diese Sprachen unabhangig von Rechnerarchitekturen.

Die bisher effizienteste Implementierung einer funktionalen Sprache mit 'lazy evaluation' als Auswertungsstrategie auf einem von Neumann-Rechner erfolgte mittels der Technik der 'programmierten Graphreduktion' auf der Basis einer ab­strakten Maschine - der sogenannten G-Maschine [Johnsson 87]. Leider ist selbst diese Implementierung im allgemeinen langsamer als die imperativer Sprachen. Dies zeigt, daB von Neumann-Rechner als Zielarchitekturen zur Implementierung funktionaler Sprachen nicht vorteilhaft sind.

In den letzten Jahren wurden daher - meist in Verbindung mit neuen Im­plementierungstechniken - eine ganze Reihe innovativer Rechnerarchitekturen speziell fUr funktionale Sprachen entworfen, unter anderem etwa in [Turner 79], [Clarke, Gladstone, MacLean, Norman 80], [Johnsson 84, 87], [Fairbairn, Wray 87], [Burn, Peyton-Jones, Robson 88], [Meijer 88], [Peyton-Jones, Saskild 88]. Nur

Page 5: [Informatik-Fachberichte] Parallele Implementierung funktionaler Programmiersprachen Volume 232 || Einleitung

5

einige dieser Entwiirfe wurden bisher tatsachlich in Hardware realisiert. Dazu zahlt die abstrakte G-Maschine, deren Hardwareversion von der Leistungsfahig­keit durchaus mit von Neumann-Rechnern vergleichbar ist [Kieburtz 87].

Die durch technologische Fortschritte stark vorangetriebene Entwicklung von Parallelrechnerarchitekturen offenbart vor allem fUr funktionale Sprachen neue Moglichkeiten. Denn auf Grund der Eigenschaft der 'referential transparency' enthalten funktionale Programme implizite Parallelitat, die darin besteht, dafi un­abhangige Teilausdriicke in beliebiger Reihenfolge, also insbesondere parallel aus­gewertet werden konnen. In dem in Bild 4 angegebenen MIRANDA-Programm zur Berechnung der Fakultatsfunktion konnten etwa im Fall l#h die rekursiven Funktionsaufrufe (pfac 1 m) und (pfac (m+1) h) parallel ausgewertet werden.

pfac 1 h = 1, = l*h, = (pfac 1 m) * (pfac (m+1) h),

where m = (1+h)/2

1 = h 1+1 = h rv(1=h) & rv(1+1=h)

Bild 4: Programm mit impliziter ParallelWit

Prinzipiell konnen funktionale Sprachen auf Parallelrechnern implementiert werden, ohne dafi die Sprache urn syntaktische Konstrukte zur Spezifikation von Parallelitat erweitert werden muB. Der Programmierer braucht sich also nicht urn die Organisation der Parallelausfiihrung seines Programmes, zu der Kommu­nikationen zwischen parallelen Prozessen und die Synchronisation von Prozessen gehoren, zu kiimmern.

Ein sogenannter parallelisierender Compiler kann die in einem Programm ent­haltene implizite Parallelitat entdecken und das Programm in parallele Prozesse zerlegen, so daB eine Auswertung auf einem Parallelrechner durchgefiihrt werden kann, ohne dafi der Programmierer irgendwelche zusatzlichen Angaben machen muB.

Ziel dieses Buches ist die konzeptionelle Entwicklung eines solchen paralleli­sierenden Compilers fiir funktionale Sprachen und damit verbunden der sprach­orientierte Entwurf einer Parallelrechnerarchitektur, die die Ausfiihrung funktio­naler Programme in besonderer Weise unterstiitzt. Bild 5 zeigt schematisch die Vorgehensweise, die wir zur Implementierung funktionaler Sprachen, die 'lazy eva­luation' unterstiitzen, auf Multicomputersystemen gewahlt haben. Vnter Mul­ticomputersystemen verstehen wir dabei Parallelrechner, die aus mehreren un-

Page 6: [Informatik-Fachberichte] Parallele Implementierung funktionaler Programmiersprachen Volume 232 || Einleitung

6

abhangigen Prozessorelementen bestehen, die iiber ein Netzwerk kommunizieren konnen.

Urn von den Besonderheiten der verschiedenen funktionalen Sprachen mit 'lazy evaluation' zu abstrahieren, gehen wir zunachst zu einer Zwischensprache tiber, die wir SAL (Simple Applicative Language) nennen und die im wesentlichen einer erweiterten Form des A-Kalkiils entspricht. Ein parallelisierender Compiler iiber­setzt die Programme dieser Zwischensprache, in eine parallele Zwischensprache, in der Parallelitat explizit durch ein spezielles syntaktisches Konstrukt, das let par­Konstrukt, angezeigt wird. Bild 6 zeigt eine solche Transformation fUr das in Bild 4 angegebene MIRANDA-Programm.

Anhand dieses Beispiels gehen wir kurz auf einige Merkmale von SAL und der parallelen Zwischensprache ein.

In SAL gehort der auszuwertende Ausdruck zum Programm, damit er bei der Parallelisierung beriicksichtigt werden kann. Rekursive Funktionen werden inner­halb eines letrec-Konstruktes definiert, welches ahnlich zu dem where-Konstrukt in MIRANDA ist, also insbesondere geschachtelt auftreten kann. Geschachtelte letrec-Ausdriicke werden bei der Parallelisierung allerdings eliminiert. Zur Defi­nition von Funktionen wird in SAL die A-Notation benutzt. Fiir Fallunterscheidun­gen steht das if - then - else-Konstrukt zur Verfiigung. AIle Ausdriicke werden in Prafixnotation geschrieben. SAL lafit lokale Definitionen von nicht rekursiven Ob­jekten mittels des let-Konstruktes zu. 1m Gegensatz zu den letrec-Konstrukten werden let-Konstrukte bei der Parallelisierung nicht eliminiert.

Ein Programm der parallelen Zwischensprache besteht im allgemeinen aus ei­nem System von globalen Funktionsdefinitionen, d.h. Funktionsdefinitionen, in denen keine letrec- oder A-Konstrukte als echte Teilausdriicke auftreten.

{main

Fl(Xl, ...... ,xmJ )

Fr(Xl, ... ,XmJ

= exp } = eXPl

= eXPr

In Bild 6c betsteht dieses System aus zwei Gleichungen. Applikationen in dieser Sprache werden zur Erleichterung der Implementierung

in sogenannter flacher oder first-order Form:

Funktionssymbol (Argument l , ... , Argumentn )

notiert. Dies hat implementierungstechnische Griinde und wird spater naher erlautert.

Parallelitat wird durch das letpar-Konstrukt angezeigt, das im wesentlichen folgende Form hat:

Page 7: [Informatik-Fachberichte] Parallele Implementierung funktionaler Programmiersprachen Volume 232 || Einleitung

Funktionale Sprache

(Z.B.: MIRANDA, LAZyML etc.)

Erweiterter A-Kalkiil (SAL)

parallelisierender Compiler

Parallele Zwischensprache

Parallele Abstrakte Maschine

M ulticomputersystem

Bild 5: Organisation der parallelen Implementierung

7

Page 8: [Informatik-Fachberichte] Parallele Implementierung funktionaler Programmiersprachen Volume 232 || Einleitung

8

a) MIRANDA-Programm

pfac 1 h = I, = l*h, = (pfac 1 m) * (pfac (m+l) h),

where m = (1+h)/2

mit auszuwertendem Ausdruck (pfac 1 11)

.Jj. Transformation in SAL .Jj.

b) SAL-Programm

letrec pfac = A (I, h). if (=,I,h) then 1

1 = h 1+1 = h fV(l=h) & fV(l+l=h)

else if (=,(+,I,I),h) then (*,I,h) else let m = (j,( +,I,h),2)

in (*, (pfac, I, m), (pfac, (+,m,I), h)) titi

in (pfac, 1, 11)

.Jj. Parallelisierung .Jj.

c) Parallelisiertes Programm

main = pfac(l, 11) pfac (I, h) = if =(I,h) then 1

else if=(+(I,I),h) then *(I,h) else let m = /( +(I,h),2)

titi

in let par y = pfac(l, m) in *(y, pfac( +(m,I), h))

Bild 6: Parallelisierung eines MIRANDA-Programms

Page 9: [Informatik-Fachberichte] Parallele Implementierung funktionaler Programmiersprachen Volume 232 || Einleitung

let par Yl = F{(ell, ... ,el n1 )

and and YP = F;(epl, ... ,epnp ) in e[Yl, ... , YpJ

9

Die Auswertung eines Ausdruckes dieser Form erfolgt derart, daB die Ausdriicke FI( eil, ... , ein.) (1 ~ i ~ p) parallel, d.h. auf anderen Prozessorelementen ausge­wertet werden konnen, wahrend der Ausdruck e lokal ausgewertet wird. In diesem Ausdruck werden die parallel auswertbaren Teilausdriicke mittels der Variablen Yi referenziert. Bei der Parallelisierung wird sichergestellt, daB die parallel auswert­baren Ausdriicke immer als Applikationen von definierten Funktionen dargestellt werden. Dies vereinfacht den Transfer von solchen Ausdriicken zu anderen Pro­zessoren.

Durch das let par-Konstrukt wird ein hierarchisches ProzeBsystem beschrieben. Synchronisation ist nur zwischen der Hauptrechnung, d.h. der Auswertung von e und den parallelen Prozessen zur Auswertung der Teilausdriicke

des Ausdruckes e notwendig. In dem sehr einfachen Fall der Parallelisierung des pfac-Programms in Bild

6 wird jeweils ein rekursiver Aufruf von pfac zur Parallelauswertung freigegeben. Dadurch ergibt sich das in Bild 7 skizzierte ProzeBsystem.

Ausgehend von der parallelen Zwischensprache erfolgt der Entwurf einer par­allelen abstrakten Maschine, auf deren Basis die Organisation der parallelen Pro­grammausfiihrung und die Verwaltung paralleler Prozesse spezifiziert wird. Die Maschine besteht aus einer endlichen Anzahl von Prozessorelementen, die iiber ein Verbindungsnetzwerk Nachrichten austauschen konnen. Jedes Prozessorele­ment enthalt zwei autonom arbeitende Prozessoreinheiten - eine Kommunika­tionseinheit und eine Reduktionseinheit. In den Reduktionseinheiten erfolgt die sequentielle AusfUhrung von Prozessen. In den Kommunikationseinheiten erfolgt die Verwaltung der Parallelitat. Diese dezentrale Organisation der abstrakten Ma­schine ermoglicht eine optimale Ausnutzung von Parallelitat auch innerhalb der verschiedenen Maschinenkomponenten und erleichtert ihre formale Spezifikation.

Ais Implementierungstechnik haben wir die programmierte Graphreduktion gewahlt, da diese sich in sequentiellen Implementierungen, wie bereits erwahnt, bewahrt hat und daher, wie sich zeigen wird, auch fUr eine parallele Implementie­rung eine gute Grundlage bildet. Bei der programmierten Graphreduktion wird das auszufiihrende Programm als Graph repdisentiert, der wiihrend der Ausfiih­rung transformiert wird. Die Graphtransformationen werden durch Maschinen­code gesteuert.

Page 10: [Informatik-Fachberichte] Parallele Implementierung funktionaler Programmiersprachen Volume 232 || Einleitung

10

[3 - rekursiver Aufruf

~ - Prozefi

Bild 7: Rekursive Aufrufe und parallele Prozesse im pfac-Programm

Page 11: [Informatik-Fachberichte] Parallele Implementierung funktionaler Programmiersprachen Volume 232 || Einleitung

11

Die in der parallelen Zwischensprache benutzte Hache Notation fur Applikatio­nen fuhrt zu einer besonders kompakten Graphreprasentation von auszuwertenden Ausdrucken, bei der sichergestellt ist, dafi der nachste durchzufuhrende Transfor­mationsschritt immer bereits durch die Wurzel des zu reduzierenden Graphen be­stimmt ist. Dadurch werden aufwendige Graphtraversierungen, wie sie etwa in der G-Maschine notwendig sind, vermieden.

Die parallele abstrakte Maschine kann auf realen Multicomputersystemen im­plementiert werden oder als Ausgangspunkt einer Hardwareentwicklung dienen. Wir werden am Ende dieses Buches nur die erste Moglichkeit diskutieren und einige Aspekte zur Implementierung der Maschine auf einem OccAM/Transputersystem angeben.

Entsprechend der in Bild 5 enthaltenen Ubersicht ist das Buch in folgende drei Teile gegliedert:

I. Grundlagen und Beschreibung der Ausgangs'sprache II. Parallelisierung funktionaler Programme

III. Entwurf einer parallelen Graphreduktionsmaschine.

1m ersten Teil wird zunachst die Sprache SAL eingefiihrt, die wir als Ausgangs­sprache der parallelen lmplementierung wahlen. Diese einfache funktionale Spra­che wird durch die Angabe der Syntax, Fixpunkt- und Reduktionssemantik de­finiert. Sie umfafit die wesentlichen Konzepte, die allen funktionalen Sprachen zugrundeliegen. Anhand der Sprache SAL werden die wichtigsten sequentiellen Reduktionsstrategien fur funktionale Sprachen vorgestellt.

Aufierdem geben wir einen Uberblick iiber die wichtigsten in der Literatur beschriebenen lmplementierungstechniken fiir funktionale Sprachen. Den Ab­schlufi des erst en Teils bildet eine kurze Ubersicht uber Architekturformen fiir Parallelrechner.

1m zweiten Teil beschreiben wir die Techniken und Verfahren, die im paralleli­sierenden Compiler benutzt werden, urn die in einem funktionalen Programm ent­haltene implizite Parallelitat zu entdecken und das Programm in parallel ausfiihr­bare Teile zu zerlegen. Fur Sprachen mit 'lazy evaluation' erweist sich vor allem die Entdeckung der impliziten Parallelitat als schwierige und aufwendige Aufgabe, wenn nur solche Teilausdriicke ausgewertet werden sollen, deren Wert zur Be­stimmung des Gesamtresultates benotigt wird. Man spricht in diesem Fall von konservativer Parallelitat.

Eine alternative Methode besteht darin, beliebige Teilausdriicke parallel aus­zuwerten und parallele Prozesse, fiir die sich herausstellt, dafi ihr Resultat nicht benotigt wird, abzubrechen. Man bezeichnet dies als spekulative Parallelitat, da Berechnungen durchgefiihrt werden, deren Ergebnis moglicherweise nicht benotigt

Page 12: [Informatik-Fachberichte] Parallele Implementierung funktionaler Programmiersprachen Volume 232 || Einleitung

12

wird. Die Entdeckung von spekulativer Parallelitat ist zwar sehr einfach, aber die Verwaltung der parallelen Prozesse stellt ein groBes Problem bei dieser Methode dar. Eine Verschwendung von Ressourcen kann nieht vollends ausgeschlossen wer­den. Aus diesem Grunde werden wir in diesem Buch nur konservative Parallelitat behandeln.

In dem in Bild 3 angegebenen Programm durfen also z.B. Aufrufe der Funktion genfib immer nur dann ausgewertet werden, wenn ein weiteres Listenelement zur Bestimmung des Gesamtergebnisses benotigt wird. Auf diese Weise wird eine vollstandige Auswertung der durch Aufrufe von genfib erzeugten unendlichen Liste verhindert. Die Ausnutzung von Parallelitat ist in diesem Programm nur begrenzt moglich.

Der zweite Teil des Buches greift zum Teil auf in der Literatur vorgeschlagene Techniken und Algorithmen zuruck und zeigt, wie diese Verfahren in dem paral­lelisierenden Compiler eingesetzt werden. Alle zur Parallelisierung erforderlichen Programmtransformationen werden formal spezifiziert.

Zum AbschluB von Teil II geben wir eine Graphreduktionssemantik fur paralle­lisierte Programme an, die die Darstellung des Programms als Graphen berucksich­tigt und wiedergibt, welche Teilgraphen parallel reduziert werden konnen. Diese Reduktionssemantik bildet die Schnittstelle zwischen der rein sprachliehen Ebene, auf der Programmtransformationen zur Parallelisierung durchgefiihrt werden, und der technischen Ebene der parallelen abstrakten Graphreduktionsmaschine, auf der die parallelisierten Programme ausgefiihrt werden sollen.

Den Entwurf der parallelen abstrakten Graphreduktionsmaschine beschreiben wir im dritten Teil des Buches. Neben der formalen Spezifikation, die wir auf der Basis nichtdeterministischer Transitionssysteme vornehmen, wird die Uber­setzung parallelisierter Programme in Code der parallelen Maschine vollstandig spezifiziert. Anhand eines ausfiihrlichen Beispieles wird die Arbeitsweise der Ma­schine verdeutlieht. lnsgesamt zeigt sieh, daB die Technik der programmierten Graphreduktion in naturlicher Weise an eine parallele Umgebung angepaBt wer­den kann. 1m AnschluB an die formale Spezifikation der Maschine diskutieren wir kurz einige Aspekte der Implementierung der abstrakten Maschine auf einem realen Multiprozessorsystem (einem OccAM/Transputersystem).

Den AbschluB bildet ein Vergleich des hier beschriebenen Ansatzes zur paral­lelen lmplementierung funktionaler Sprachen mit anderen Projekten gleicher Ziel­setzung.

1m Anhang sind mathematische Grundlagen zusammengestellt, die beim Ver­standnis des erst en Kapitels hilfreich sein konnen.