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

13
Kapitel7 Einteilung Prozesse In parallele Die im letzten Kapitel anhand der abstrakten Interpretationen der Basisfunktio- nen, Konstruktoren und Kombinatoren hergeleiteten "evaluation transformer" lie- fern Informationen iiber die in einem Kombinatorprogramm enthaltene implizite Par alleli tat. Prinzipiell kann jeder Teilausdruck, fiir den sich wahrend der Programmausfiih- rung ein von verschiedener Auswerter ergibt, parallel ausgewertet werden. Eine solche Implementierung der parallelen Auswertung eines funktionalen Programms ist aber nicht unbedingt optimal, da die parallele Auswertung eines Teilausdruckes immer einen zusatzlichen Organisationsaufwand erfordert. Der Teilausdruck und die Informationen, die zu seiner Auswertung notwendig sind, miissen als Nach- richt kodiert werden, zu einem anderen Prozessorelement transferiert und dort dekodiert werden. In analoger Weise muB schlieBlich das Ergebnis der Teilberech- nung zuriicktransportiert werden. Ein Teilausdruck, der parallel ausgewertet wird, sollte also so komplex sein, daB der Gewinn, der durch die parallele Ausfiihrung erreicht wird, groBer ist als der Mehraufwand, mit dem die Parallelausfiihrung verbunden ist. Dieser Mehraufwand wird haufig mit Kommunikationskosten bezeichnet, ob- wohl die eigentlichen Kommunikationskosten, also die Zeiten fiir die Ubertragung von Nachrichten zwischen Prozessorelementen, vernachlassigbar klein sind. Daher werden wir den Mehraufwand Verteilungskosten nennen. Zur Entscheidung, ob ein Teilausdruck parallel ausgewertet werden solI oder nicht, muB also eine KomplexWitsabschatzung des Ausdruckes vorgenommen wer- den. Da die vorhandene Parallelitat natiirlich vom Auswerter eines Ausdruckes abhangt, ist letztendlich erst zur Laufzeit zu erkennen, welche Teilausdriicke tat- R. Loogen, Parallele Implementierung funktionaler Programmiersprachen © Springer-Verlag Berlin Heidelberg 1990

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

Kapitel7

Einteilung Prozesse

• In parallele

Die im letzten Kapitel anhand der abstrakten Interpretationen der Basisfunktio­nen, Konstruktoren und Kombinatoren hergeleiteten "evaluation transformer" lie­fern Informationen iiber die in einem Kombinatorprogramm enthaltene implizite Par all eli tat.

Prinzipiell kann jeder Teilausdruck, fiir den sich wahrend der Programmausfiih­rung ein von ~o verschiedener Auswerter ergibt, parallel ausgewertet werden. Eine solche Implementierung der parallelen Auswertung eines funktionalen Programms ist aber nicht unbedingt optimal, da die parallele Auswertung eines Teilausdruckes immer einen zusatzlichen Organisationsaufwand erfordert. Der Teilausdruck und die Informationen, die zu seiner Auswertung notwendig sind, miissen als Nach­richt kodiert werden, zu einem anderen Prozessorelement transferiert und dort dekodiert werden. In analoger Weise muB schlieBlich das Ergebnis der Teilberech­nung zuriicktransportiert werden. Ein Teilausdruck, der parallel ausgewertet wird, sollte also so komplex sein, daB der Gewinn, der durch die parallele Ausfiihrung erreicht wird, groBer ist als der Mehraufwand, mit dem die Parallelausfiihrung verbunden ist.

Dieser Mehraufwand wird haufig mit Kommunikationskosten bezeichnet, ob­wohl die eigentlichen Kommunikationskosten, also die Zeiten fiir die Ubertragung von Nachrichten zwischen Prozessorelementen, vernachlassigbar klein sind. Daher werden wir den Mehraufwand Verteilungskosten nennen.

Zur Entscheidung, ob ein Teilausdruck parallel ausgewertet werden solI oder nicht, muB also eine KomplexWitsabschatzung des Ausdruckes vorgenommen wer­den. Da die vorhandene Parallelitat natiirlich vom Auswerter eines Ausdruckes abhangt, ist letztendlich erst zur Laufzeit zu erkennen, welche Teilausdriicke tat-

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

190 KAPITEL 7. EINTEILUNG IN PARALLELE PROZESSE

sachlich parallel ausgewertet werden k6nnen. Die Entscheidung iiber die Paral­lelauswertung sollte aber zur Ubersetzungszeit soweit vorbereitet werden, daB sie zur Laufzeit keine zusatzliche Zeit erfordert.

Wir beschreiben in diesem Kapitel eine Transformation von Kombinatorsy­stemen in sogenannte parallelisierte K ombinatorsysteme, in den en die Stellen, an denen eine Parallelauswertung m6glich ist und sinnvoll erscheint, durch ein spe­zielles syntaktisches Konstrukt angezeigt werden. Motiviert wurde dieser Ansatz durch die Arbeiten von Hudak und Goldberg [Hudak, Goldberg 85ajb], die einen ahnlichen Algorithmus zur Erzeugung serieller Kombinatorsysteme, welche im we­sentlichen den hier betrachteten parallelisierten Kombinatorsystemen entsprechen, beschreiben.

Serielle Kombinatoren bestimmen die Granularitat der Parallelitat. Jeder Teil­ausdruck, fiir den eine Parallelauswertung gewinnbringend sein kann, wird als Kombinator definiert. Parallele Prozesse entsprechen damit immer Kombinator­aufrufen. Weiterhin enthalt der Rumpf eines seriellen Kombinators keinen Teil­ausdruck, fiir den eine Parallelauswertung lohnend sein kann, der aber nicht als solcher gekennzeichnet ist.

Wir beginnen mit der Beschreibung der erweiterten Syntax und Reduktionsse­mantik parallelisierter Kombinatorsysteme.

7.1 Parallelisierte Kombinatorsysteme

Die Ausdriicke, die als Riimpfe parallelisierter Kombinatoren auftreten, sind ap­plikative Ausdriicke, die ein spezielles syntaktisches Konstrukt enthalten k6nnen, das M6glichkeiten zur Parallelauswertung anzeigt.

7.1.1 Definition Sei rg eine Rangfunktion.

Die Menge

.ParEXPrg = (ParExp;g It E Typ(S, D))

der parallelisierten applikativen A usdriicke iiber rg ist die kleinste Typ( S, D)­sortierte Mengenfamilie mit:

1. - 9. analog zu der Definition der flachen applikativen Ausdriicke (5.4.1) und

10. Sei p E IN, Yi E Loct• mit ti E Typ(S, D) (1 ~ i ~ p).

Falls Fi(eil, ... ,eir.) E ParExp;~ mit Fi E Def(rg) und rg(Fi) = ri,

falls e E ParExp;g mit (t E Typ(S, D)) und eVi E Evsett fUr 1 ~ i ~ p, dann ist auch

7.1. PARALLELISIERTE KOMBINATORSYSTEME

let par Yl=F1(ell, ... ,elrJ ifevl and and YP = Fp(epl,"" epr ) if evp

P t in e E ParExPrg'

191

Das neu hinzugekommene letpar-Konstrukt zeigt explizit Moglichkeiten zur Parallelausfiihrung an. Teilausdriicke, die unter bestimmten Auswertern parallel ausgewertet werden konnen, werden aus dem Gesamtausdruck herausabstrahiert. Sie werden durch Applikationen von - wenn notig neu definierten - Kombina­toren F1 , ... , Fp reprasentiert. Parallele Prozesse entsprechen also Kombinatorap­plikationen. Dies ermoglicht eine kompakte Beschreibung der Prozesse durch den Kombinatornamen und die Argumentliste.

Die Parallelausfiihrung von Teilausdriicken hangt im allgemeinen von dem Aus­werter des Gesamtausdruckes abo Die Kombinatorapplikation Fi (eil, ... , eir.) solI nur dann parallel ausgefiihrt werden, wenn der aktuelle Auswerter des Gesamtaus­druckes grofier ist als der im letpar-Konstrukt gegebene Auswerter eVi. Die parallelen Teilprozesse werden im Gesamtausdruck durch die lokalen Variablen Yl, ... , YP ersetzt. Der verbleibende Ausdruck e beschreibt den Teil der Berech­nung, der sequentiell ausgefiihrt werden solI. Bei der Referenzierung der in e enthaltenen Variablen Yi (1 ::; i ::; p) erfolgt eine Synchronisation der sequentiellen Hauptrechnung mit dem i-ten parallelen Teilprozefi.

Das entstehende Prozefisystem ist hierarchisch. Die Ausfiihrung eines paralle­lisierten Kombinatorsystems startet mit der Ausfiihrung des Hauptprogrammaus­druckes. Letpar-Ausdriicke fiihren zur Aktivierung von Teilprozessen, die auf anderen Prozessorelementen ausgefiihrt werden konnen. Die Ausfiihrung von par­allelen Teilprozessen kann erneut zur Aktivierung paralleler Prozesse fiihren. Nach Beendigung eines Prozesses wird das Resultat an die Stellen iibermittelt, an denen es benotigt wird.

Die Definition parallelisierter Ausdriicke ist sehr allgemein gehalten. Es ist eine beliebige Schachtelung der ausdrucksbildenden Konstrukte zugelassen, die in dieser Allgemeinheit nicht notwendig ist. So wird das letpar-Konstrukt i.a. nicht in der Argumentposition einer Applikation auftreten.

Parallelisierte Kombinatorsysteme und -programme sind solche, in denen par­allelisierte Ausdriicke als Kombinatorriimpfe und als Hauptausdruck auftreten.

7.1.2 Definition Ein parallelisiertes Kombinatorprogramm

(F;e)

vom Typ s E SUD besteht aus einem parallelisierten (flachen) Kombina­torsystem

192 KAPITEL 7. EINTEILUNG IN PARALLELE PROZESSE

mit r = 1, Fi E Funt • mit ti E Typ(S, D) und t ..

ei E ParEXPr~ mit free (ei) ~ {xi, ... ,X~JU{FI, ... ,Fr},

wobei rg : { {FI' ·F; , Fr } : ~} (1 ~ i ~ r) und einem parallelisierten

applikativen Ausdruek

e E ParExp~g mit free(e) ~ {FI , ... , Fr }.

Die niehtdeterministische Reduktionssemantik parallelisierter Kombinatorsy­sterne entsprieht derjenigen flaeher Kombinatorsysteme, denn die Semantik des letpar-Konstruktes entsprieht der des let-Konstruktes. Aueh bei der Annotie­rung wird das letpar-Konstrukt wie das let-Konstrukt behandelt. Das let par­Konstrukt beeinfluBt allerdings die Reduktionsstrategie, wie wir im naehsten Ka­pitel verdeutliehen werden. Zuvor besehreiben wir noeh den Algorithmus zur Er­zeugung von letpar-Ausdriieken in Kombinatorprogrammen.

7.2 Der Parallelisierungsalgorithmus

Zur Erlauterung der Vorgehensweise bei der Erzeugung parallelisierter Kombina­torsysteme diskutieren wir zunaehst ein einfaehes Beispiel. Sei

ein zu parallelisierender Ausdruek, wobei f eine zweistellige Basisfunktion seL Da alle Basisfunktionen strikt interpretiert werden, ist es prinzipiell moglieh, die Ar­gumentausdriieke el und e2 parallel auszuwerten, d.h. einen der beiden Ausdriieke auf einem anderen Prozessor auszufiihren. 1m folgenden bezeiehne

• Ti(exp) die Zeitkosten fiir die Ausfiihrung von exp auf i Prozessorelementen und

• Vi(exp) die Verteilungskosten, d.h. den Mehraufwand, der auf Prozessorele-ment i geleistet werden muB, bei Parallelausfiihrung von expo

Dabei nehmen wir zur Vereinfaehung an, daB geniigend Prozessoren vorhanden sind und daB jedes Prozessorelement mit jedem anderen direkt Naehriehten aus­tausehen kann.

Wird etwa der Beispielausdruek e auf Prozessor 1 ausgefiihrt und die Auswer­tung von e2 naeh Prozessor 2 verlagert, so ergeben sieh, grob gesehen, folgende A usfiihrungszeiten:

TI (e) = TI(ed + TI(e2) + T(f) und T2(e) = VI(e2) + max{TI(ed, T2(e2) + V2(e2)} + T(f).

7.2. DER PARALLELISIERUNGSALGORITHMUS 193

Dabei steht

- fUr die Kodierung von e2 in eine Nachricht und die Versendung der Nachricht und

- fUr das Empfangen und Dekodieren des Resultates von e2

und

- fUr das Empfangen der Nachricht, die e2 enthalt, die Dekodierung dieser Nachricht sowie

- die Kodierung des Resultates von e2 nach Beendigung der Ausfiihrung und die Versendung der Antwortnachricht.

Damit die Parallelauswertung einen Gewinn bringt, sollte

gelten. Dies ist gleichbedeutend mit

d.h. es soUte V1(e) < T1(e2) und V1(e) + V 2(e) < T1(el)

gelten. Beide Ausdriicke miissen also eine gewisse Komplexitat haben. Damit

minimal wird, soUte zudem T1(e2) < T1(et) sein, d.h. es ist giinstiger, den weni­ger komplexeren Teilausdruck auf einem anderen Prozessorelement ausfUhren zu lassen.

Zur Parallelisierung wird somit neben den Striktheitsinformationen ein Kom­plexitiitsmap fUr Ausdriicke benotigt, das die Zeit, die zur Ausfiihrung eines Aus­druckes benotigt wird, abschatzt. Eine exakte Bestimmung von Ausfiihrungs­zeit en beliebiger Ausdriicke ist natiirlich nicht moglich. Ein solches Kompli­xitatsmafi wird i.a. auf Heuristiken beruhen. Es kann natiirlich auf eine spezielle Zielarchitektur zugeschnitten werden, wenn man die Abbildung der Ausdriicke in Maschinencode untersucht und Zeiten fiir einzelne Maschinenbefehle oder be­stimmte Maschinencodesequenzen beriicksichtigt. Auch die Verteilungskosten sind von der Zielmaschine abhangig.

194 KAPITEL 7. EINTEILUNG IN PARALLELE PROZESSE

Das strenge sprachorientierte 'top-down'-Vorgehen kann an dieser Stelle also nicht ohne weiteres fortgesetzt werden. Bei der Aufteilung des funktionalen Pro­grammes in parallele Prozesse sind Informationen iiber die Zielarchitektur not­wendig. Bereits bei den obigen Abschatzungen gingen bestimmte Vorstellungen iiber die Organisation der parallelen Ausfiihrung auf der Maschinenebene ein. Es erfolgt hier ein RiickfluB von Informationen der maschinennahen Implementierung in die sprachliche Zwischenebene der parallelisierten Kombinatorsysteme.

1m folgenden set zen wir voraus, daB wir ein geeignetes KomplexitatsmaB fiir Ausdriicke sowie eine Abschatzung der Verteilungskosten zur VerfUgung haben. Das KomplexitatsmaB bezeichnen wir mit

complexity: AppExp -+ Rt

und distribution-costs E R bezeichne die Abschatzung der durchschnittlichen Ver­teilungskosten. Als weitere Eingaben benotigt der Parallelisierungsalgorithmus natiirlich das mit Annotationen versehene zu parallelisierende Kombinatorpro­gramm.

Wir beschreiben zunachst eine Parallelisierungsfunktion fiir annotierte Aus­driicke eines Kombinatorprogramms n.

Die Parallelisierungsfunktion erhalt als Eingabe neben dem annotierten Aus­druck ein Kennwort zur eindeutigen Bezeichnung neu zu definierender Kombinato­reno Als Ausgabe erhalt man ein Paar, dessen erste Komponente der transformierte Ausdruck ist, aus dem die Teilausdriicke, fUr die eine Parallelauswertung sinnvoll erscheint, herausabstrahiert sind. Solche Teilausdriicke sind durch Applikationen neu definierter Kombinatoren ersetzt, die in der zweiten Komponente gegeben sind. In folgender Definition bezeichne Comdef wie in Kapitel 5 die Menge al­ler Kombinatordefinitionsgleichungen und ParExp die Menge aller parallelisierten applikativen Ausdriicke.

7.2.1 Definition Sei (n, e, (AN(k,e), AN(R,e) , ANrk,e»)} ein annotiertes Kombi­natorprogramm. Unter Benutzung eines KomplexitatsmaBes complexity und einer Abschatzung der Verteilungskosten dc (distribution costs) definieren wir die Funktion

par = parR: FExPR x IN* -+ ParExp x P( Comdef).

Die Komponentenfunktionen von parR bezeichnen wir mit parI und par2.

1. parR (ean ) := (e, 0), falls complexity (e) < dc.

Dieser Fall trifft insbesondere fUr nicht-zusammengesetzte Ausdriicke zu.

t lR bezeichnet die Menge der reellen Zahlen.

7.2. DER PARALLELISIERUNGSALGORITHMUS 195

2. Ansonsten erfolgt die Definition durch strukturelle Induktion uber den Aufbau der zusammengesetzten flachen applikativen Ausdrucke. Fur konditionale Ausdrucke gehen wir der Einfachheit halber von der kon­textfreien Annotierung aus:

(a) par((if e then el else e2 fi)an, w) := ( if parI (ern, w.O) then parI (ern, w.1) else parI (e~n, w.2) fi,

par2(ean , w.O) U par2(ern, w.1) U par2(e~n, w.2))

(b) par((case e of CI(Yll,.··,Ylml): eli ... i Ck(Ykl, ... , Ykm,,) : ekesac )an, w)

:= (case parl(ean,w.O) of CI(Yll, ... , Ylml) : parI (ern , w.1)i

esac,

par2(e, w.O) U U7=1 par2(ej, w.j))

(c) par(let YI = el and ... and Yk = ek in e, w) := ( let par Yil = F w.i l ( var ill, ... , var il n'l) if ev i l

and and Yi, = FW.i, (vari,l, . .. , vari,n,,) if eVi, in let Yh = eXPiI and ... and Yjm = eXPjm in parl(e,w.O), {Fw.h( varhl,···, varhnh) = parI (eh, w.h) I

hE {1, ... , k} mit complexity(eh) > de}

U par2(e, w.O) U U7=1 par2(el, w.l)), wobei gilt:

• {i l , ... ,ill n {it, ... ,jm} = 0 und {il, ... ,il}U{jl, ... ,jm} = {l, ... ,k}

• {il, ... ,il}:= {h E {l, ... ,k} I complexity(en) > de /\ 3~ E Evset : EThS(e)(~) > ~o}

Dabei sei e = let YI = el and ... and Yk = ek in e und ETCS(e) bezeichne den kontextsensitiven 'evaluation trans­former' von e, der durch ANn(e) gegeben ist.

• eVil. := min{~ E Evset I EThS(e)(~) > ~o}, • {varhl' ... ' varhnh} := free(eh) n (Ary U Loc) fur 1 :::; h :::; ktt

{ ejh falls complexity(ejh) < de }

• eXPjh:= FW.jh(varjhl, ... ,varjhn3h) sonst

mit h E {1, ... , m}.

ttZur Vereinfachung verzichten wir auf eine Umbenennung lokaler Variablen zu Argumentva­riablen, die genau genommen in den Kombinatordefinitionen vorgenommen werden mull.

196 KAPITEL 7. EINTEILUNG IN PARALLELE PROZESSE

(d) Sei, E n u r mit Stelligkeit k.

par(,(el, ... , ek), w) := ( let par Yw.i l = F w.il ( var ill, ... , var il n'l) if eVil

and and Yw.i , = F w.i , (var i,l, ... , var i,n,,) if eVi, in ,( eXPI, ... , eXPk), U7=1 par2(ej,w.j) U {Fw.h(varhl, ... ,varhnh) =parl(eh,w.h) I

hE {I, ... , k} \ {io}, eomplexity(eh) > de}),

wobei

• {io,il, ... ,il}:= {h E {I, ... ,k} I eomplexity(eh) > de " 3~ E Evset : ETh(J)(~) > ~o},

io sei minimal mit complexity ( eio) ~ complexity ( eiJ) fUr alle 1 ~j ~ m

• {varjl,'''' varjnJ := /ree(ej) n (Arg U Loe), j E {I, ... , k}

• eViJ := min{~ E Evset I ETiJ (,)(~) > ~o} und

{ Yw.j fallsjE{il, ... ,il},

• ex .'= parl(ej,w.j) falls j = io, PJ • ej falls complexity ( ej) < dc,

Fw.i(varjl, ... ,varjnJ ) sonst.

(e) Sei F E {FI , ... , Fr } mit Rang k und Rumpf eF in R. ETCS(F( el, ... , ek)) sei der kontextsensitiven 'evaluation transfor-mer' von F bzgl. der Applikation F( el, ... , ek). Dann gilt:

par(F(el, ... , ek), w) := (letpar Yw.i l = FW ' il (varill, ... , variln'l) if eVil

and Yw.i, = F w.i, ( var i,l, ... , var i,ni, ) if eVi, in F( eXPI,"" eXPk), {Fw.h( varhl,···, varhnh) = parI (eh, w.h)

I h E {I, ... , k} \ (parset \ {iI, ... , il}), complexity ( eh) > de}

U U7=1 par2(ej, w.j) ),

wobei

• parset := {j E {I, ... , k} I complexity ( ej) > de " 3~ E Evset : ETCS(F(el, ... , ek))(~) > ~o}

7.2. DER PARALLELISIERUNGSALGORITHMUS

parset falls complexity(eF) > dc, parset \ {jo}

falls complexity( e F) ~ dc und jo E parset ist minimal mit complexity ( ejo) ~ complexity( ej) fUr alle j E parset.

197

• eVi, := min{~ E Evset I ETi:(F(el, ... ,ek»(~) > ~o} (1 ~ j ~ I)

• {varhl, ... , Varhnh} := free(eh) n (Arg U Loe) (1 ~ h ~ k) und

• ex .. = parl(ej,w.j) fallsjEparset\{il, ... ,il}, { Yw.j falls j E {it, ... , ill,

PJ • ej falls complexity(ej) ~ dc, Fw.j( var jl, ... , var jn,) sonst.

(f) par(ap(eO,el, ... ,ek» := (letpar Yw.i] = F w.i] (var i] , ... , var i] n , ]) if eVil

and and Yw.i, = Fw.i,(vari,l, ... ,vari/n.) ifevi, in ap(expo, ... ,exPk), {Fw.j ( var jl, ... , Varjn) = parI (ej, w.j)

I j E {I, ... , k} \ (parset \ {i l , ... , il}), complexity(ej) > dc} U U;=l par2 (ej, w.j) )

wobei

• parset := {j E {O, ... , k} I complexity ( ej) > dc /\ 3~ E Evset : ET?(ap(eo, ... , ek»(~) > ~o}

Dabei bezeichnet ETCS(ap(eo, ... , ek» den kontextsensitiven 'evaluation transformer' von ap(eo, ... ,ek).

• {i l , ... , ill := parset \ min{jo E parset I Vj: complexity(ejo) ~ complexity(ej)},

• {varjl' ... ' Varjn,} := free(ej) n (Arg U Loc) (1 ~ j ~ k), • eViJ := min{~ E Evset I ETi:(ap(eo, ... , ek»(~) > ~o}

(1 ~ j ~ I) und

Yw.j falls j E {i l , ... , ill, parI (ej, w.j) fUr j = min{jo E parset I

Vh : complexity(ejo) > complexity ( eh) },

ej falls complexity( ej) < dc, Fw.j(varjl, ... ,varjnJ ) sonst

198 KAPITEL 7. EINTEILUNG IN PARALLELE PROZESSE

Die Parallelisierung eines Ausdruckes nirnmt folgenden Verlauf: Zunachst wird die Komplexitat des Ausdruckes bestimmt. Gilt

complexity( e) < dc,

so braucht der Ausdruck nicht weiter untersucht zu werden, da eine Parallel­ausfiihrung von Teilausdriicken aufgrund der zu geringen Komplexitat nicht lohnt.

Anderenfalls, werden im Fall konditionaler Ausdriicke die Teilausdriicke paral­lelisiert. 1m Fall applikativer Ausdriicke - zu denen wir auch let-Ausdriicke zahlen - werden mit Hilfe des Komplexitatsmafies und mit Hilfe der kontextsensitiven 'evaluation transformer' der Applikation die Teilausdriicke bestimmt, fiir die bei gewissen Auswertern eine Parallelauswertung von Vorteil ist. Es wird jeweils Sorge getragen, daB einer der parallel auswertbaren Teilausdriicke als Teil der Hauptrech­nung erhalten bleibt. Bei Kombinatorapplikationen kann dies auch der Rumpf des Kombinators sein. Fiir die Teilausdriicke, die gegebenenfalls parallel ausgewertet werden, werden neue Kombinatoren definiert, deren Rumpf der parallelisierten Form dieser Teilausdriicke entspricht. Die Definition redundanter Kombinatoren, deren Rumpf einer Kombinatorapplikation entspricht, kann dabei natiirlich ver­mieden werden. Bei der Ersetzung 'redundanter' Kombinatorapplikationen andert sich allerdings der Berechnungsort der Argumente der Kombinatorapplikation, die den Rumpf des 'neu' erzeugten Kombinators bildet. Die Aktivierung der Argu­mente erfolgt nicht mehr an dem Ort, an dem der parallele Prozef3 ausgewertet wird, sondern an dem Ort, wo die Aktivierung des parallelen Prozesses stattfindet.

In der Definition neuer Kombinatoren weicht der hier beschriebene Algorithmus von dem in [Hudak, Goldberg 85a] gegebenen Algorithmus abo Wahrend wir die parallelisierte Form der Teilausdriicke als Rumpf der neu definierten Kombinatoren wahlen und damit die parallele Ausfiihrung von Teilprozessen der Teilausdriicke lokal halten, abstrahieren Hudak und Goldberg die parallelen Teilberechnungen auch aus den Kombinatorapplikationen. Dies fiihrt zu einer friiheren Aktivie­rung solcher Teilprozesse bei der Ausfiihrung des parallelisierten Kombinatorsy­stems, verschlechtert allerdings die Lokalitat der Teilprozesse, da diese nicht mehr von den Prozessen aktiviert werden, die ihre Ergebnisse benotigen, sondern unter Umstanden sogar zeitlich vor diesen Prozessen. Zur Erhaltung der Lokalitat haben wir den Ansatz gewahlt, parallele Teilberechnungen von parallelen Berechnungen lokal zu diesen zu halten. Der Grad der Parallelitat bleibt natiirlich erhalten.

Ob ein herausabstrahierter Teilausdruck tatsachlich parallel ausgefiihrt werden sollte, hangt vom Auswerter und 'evaluation transformer' des Gesamtausdruckes abo In obiger Definition wird eine Parallelauswertung zugelassen, sob aId sich ein

7.2. DER PARALLELISIERUNGSALGORITHMUS 199

von ~o verschiedener Auswerter fUr den Teilausdruck ergibt. An dieser Stelle kann eine Analyse der Komplexitat der Teilberechnung unter Einbeziehung des Aus­werters eines Ausdruckes eine genauere Kontrolle der Granularitat der parallelen Prozesse ergeben. Die Komplexitat eines Teilausdruckes ist zwar vom Auswerter des Teilausdruckes unabhangig, aber die Komplexitat der von einem Teilausdruck initiierten Teilberechnung wird sehr stark vom Auswerter des Teilausdruckes beein­flufit. Natiirlich erfordern genauere Analysen einen grofieren Aufwand. Bei jeder Verfeinerung der Analysetechniken stellt sich letztendlich die Frage, in welchem Verhaltnis der Optimierungsgewinn zum Mehraufwand steht. Daher werden wir auf weitere Verfeinerungen des Parallelisierungsalgorithmus hier nicht eingehen.

Eine Besonderheit des obigen Algorithmus ist, daB nicht nur die Teilausdrucke, fUr die eine Parallelauswertung auf Grund der durch die 'evaluation transformer' gegebenen Informationen moglich ist, zur Definition neuer Kombinatoren fUhren, sondern aIle Teilausdriicke, deren Komplexitat eine Parallelausfiihrung lohnend erscheinen laBt. Dies zeigt eine weitere Quelle der Parallelitiit in parallelisier­ten Kombinatorsystemen. Nicht nur Kombinatorapplikationen, die im let par­Konstrukt ausgezeichnet sind, fUhren zu parallelen Prozessen, sondern auch Kom­binatorapplikationen, die 'strikte' Argumente in dynamisch zur Laufzeit entste­henden Applikationen sind bzw. als nicht-strikte Argumente verzogert ausgewer­tet werden. Welche Programmteile parallel ausgewertet werden, beschreiben wir detailliert im folgenden Kapitel durch eine deterministische Graphreduktionsse­mantik, die die Grundlage der im dritten Teil dieser Arbeit entwickelten Maschi­nenimplementierung bildet.

Die Transformation eines Kombinatorprogramms in ein parallelisiertes Kom­binatorprogramm erfolgt also in folgender Weise:

1. Anhand der abstrakten Interpretation werden fUr alle applikativen Teil­ausdriicke des Kombinatorprogramms kontextsensitive "evaluation transfor­mer" bestimmt.

2. Die Parallelisierungsfunktion liefert dann zu jedem annotierten Kombinator­rumpf einen parallelisierten Ausdruck und eine Menge neu definierter Kom­binatoren.

3. Die Ersetzung der Kombinatorriimpfe durch die parallelisierten Ausdriicke und die Hinzunahme der neu definierten Kombinatoren ergibt das paralleli­sierte Kombinatorsystem.

4. Mittels der Annotationen des urspriinglichen Systems wird schlieBlich in ein­facher Weise die Annotierung des parallelisierten Systems bestimmt.

200 KAPITEL 7. EINTEILUNG IN PARALLELE PROZESSE

7.2.2 Definition Sei ('R., e, AN (7i,e») mit

'R. = (Fi(xL . .. ,x~J = ei 11 ::; i ::; r)

und AN(7i,e):= (AN(k,e),AN(~,e),AN(k,e»)

ein annotiertes Kombinatorprogramm.

Dann hei6t

par('R.):= (Fi(xL ... ,x~J = parl(e~n,i) 11::; i::; m) U (U~=l par2(e~n, i)) U par2(ean, 0)

die Parallelisierung von 'R. (unter dem KomplexWitsmafi complexity und den Verteilungskosten dc).

(par('R.) , parI (ean , 0)) hei6t entsprechend die Parallelisierung von ('R., e) un­ter den gegebenen Annahmen.

Die Parallelisierung eines Kombinatorprogramms ist ein wohldefiniertes paral­lelisiertes Kombinatorprogramm. Wir verzichten hier allerdings auf einen formalen Beweis dieser Aussage. Die Superkombinatoreigenschaft bleibt bei der Paralleli­sierung erhalten.

Zum Abschlu6 dieses Kapitels geben wir eine Parallelisierung des Beispielpro­gramms zur Listensortierung an:

7.2.3 Beispiel Untersucht man die Riimpfe der Kombinatoren des Beispieles 5.2.6 bzw. 5.4.11 unter Beriicksichtigung der in Beispiel 6.2.5 gegebenen 'eva­luation transformer' dieser Kombinatoren bzw. der kontextsensitiven 'evalua­tion transformer' der Kombinatorriimpfe, so ergeben sich sinnvolle Paralleli­sierungsmoglichkeiten eigentlich nur im Rumpf des Kombinators QSort. Die Kombinatoren Filter und Append sind eher sequentieller Natur, wahrend die Kombinatoren Tgeq und Tit von zu geringer Komplexitat sind.

Unter entsprechenden Vorgaben ist etwa folgende Parallelisierung des Bei­spielprogramms denkbar, bei der der Kombinator QSort wie folgt ersetzt wird:

PQSort(lintliBt) := case 1 of NIL: NIL;

CONS(YI, Y2) :

esac

letpar iii = PQSort(Filter (Tlt(Yt), Y2)) if 6 and ih = PQSort( Filter ( Tgeq(YI ), Y2)) if 6 in Append (jiI, CONS(YI, fh))

7.2. DER PARALLELISIERUNGSALGORITHMUS 201

Bei der Erzeugung dieses Kombinators wurde die Definition redundanter Kombinatoren fiir die parallelen Prozesse vermieden.

Auf die mogliche Parallelausfiihrung der Argumentausdriicke der Aufrufe von PQSort wurde verzichtet. Eine tatsachliche Parallelisierung wird stark von dem vorgegebenen Komplexitatsmafi bzw. den Verteilungskosten abhangen, iiber die wir hier keine Annahmen machen.