Ferienakademie - Kurs 1

Werbung
Einführung
Haskell Crashkurs
Eigenschaften
Parallelisieren
Ferienakademie - Kurs 1 - parallel Haskell
Michael Kerscher
24. September 2009
Michael Kerscher
Ferienakademie - Kurs 1 - parallel Haskell
Einführung
Haskell Crashkurs
Eigenschaften
Parallelisieren
Einführung
◮
Crashkurs Haskell
◮
Eigenschaften der Sprache
Parallelisieren
◮
◮
◮
Compiler/Laufzeitsystem
Haskell Erweiterungen
◮
◮
Data Parallel Haskell (DPH)
Parallel Haskell
Michael Kerscher
Ferienakademie - Kurs 1 - parallel Haskell
Einführung
Haskell Crashkurs
Eigenschaften
Parallelisieren
Syntax
Lambda-Notation
Currying
Pattern Matching
Haskell Crashkurs
kurzer Einblick in
◮
Syntax
◮
Lambda-Notation
◮
Currying
◮
Typsystem
◮
Pattern Matching
Michael Kerscher
Ferienakademie - Kurs 1 - parallel Haskell
Einführung
Haskell Crashkurs
Eigenschaften
Parallelisieren
Syntax
Lambda-Notation
Currying
Pattern Matching
Terme und Typangaben
Grundlegend besteht Haskell aus den Definitionen von Termen und
deren Typangaben
x :: Int
x = 3
f :: Int -> Int
f y = x + y
-- T y p d e f i n i t i o n
-- F u n k t i o n s d e f i n i t i o n
Michael Kerscher
Ferienakademie - Kurs 1 - parallel Haskell
Einführung
Haskell Crashkurs
Eigenschaften
Parallelisieren
Syntax
Lambda-Notation
Currying
Pattern Matching
Listen, Tupel, arithmetische Listen und
Listenkomprehension
Es existieren gängige Konstrukte aus anderen
Programmiersprachen, z.b. Listen und Tupel
[1 ,2 ,3 ,4] :: [ Int ]
(1 ,2 ,3.5) :: ( Int , Int , Float )
Als Besonderheit unterstützt Haskell arithmetische Listen und
Listenkomprehension
-- Liste mit S c h r i t t w e i t e 1 , von 1 bis 9
list = [1 ,2..9]
-- Praedikat fuer gerade Zahlen
let even n = ( n ‘ mod ‘ 2) == 0
-- alle Elemente aus list mit even = true
in [ x | x <- list , even x ]
Michael Kerscher
Ferienakademie - Kurs 1 - parallel Haskell
Einführung
Haskell Crashkurs
Eigenschaften
Parallelisieren
Syntax
Lambda-Notation
Currying
Pattern Matching
where-Konstrukt
Das where-Konstrukt bindet Ausdrücke an Variablen die nur lokal
sichtbar sind.
Beispiel:
f x y = z + z
where z = x * y
Michael Kerscher
Ferienakademie - Kurs 1 - parallel Haskell
Einführung
Haskell Crashkurs
Eigenschaften
Parallelisieren
Syntax
Lambda-Notation
Currying
Pattern Matching
Lambda-Notation
◮
Haskell kennt anonyme Funktionen
◮
Anonyme Funktionen z.b. als Parameter für Funktionen
höherer Ordnung
map (\ y -> 2* y ) [1 ,2 ,3]
◮
-- -> [2 ,4 ,6]
folgende Funktionen sind gleichwertig
f = \ x y -> x + y
g x y = x+y
Michael Kerscher
Ferienakademie - Kurs 1 - parallel Haskell
Einführung
Haskell Crashkurs
Eigenschaften
Parallelisieren
Syntax
Lambda-Notation
Currying
Pattern Matching
Currying
◮
Parameterübergabe
◮
◮
imperative Sprachen: Tupel (a, b) -> c
funktionale Sprachen: Curry-Form a -> b -> c
sum :: Int -> Int -> Int
sum x y = x + y
◮
◮
◮
◮
Funktionen besitzen nur ein Argument
Funktionen können Funktionen generieren und zurückgeben
partielle Auswertung von Funktionen möglich
Beispiel für die Auswertungsstrategie:
a
a
a
a
a
:: Int
= sum 1 2
-- ersten Parameter verwenden
= (\ y -> 1 + y ) 2 -- zweiten
----- " - - - - - = 1 + 2
= 3
Michael Kerscher
Ferienakademie - Kurs 1 - parallel Haskell
Einführung
Haskell Crashkurs
Eigenschaften
Parallelisieren
Syntax
Lambda-Notation
Currying
Pattern Matching
Typklassen
Haskell nutzt Typklassen
◮
definieren Funktionen mit bestimmter Signatur
◮
jede Instanz muss alle Funktionen aufweisen
Beispieltypklassen:
◮
◮
Equality-Class
class Eq a where
(==) , (/=) :: a -> a -> Bool
instance Eq ( Float , Float ) where
( x , y ) == ( u , v ) = x == u && y == v
v1 /= v2 = not ( v1 == v2 )
Michael Kerscher
Ferienakademie - Kurs 1 - parallel Haskell
Einführung
Haskell Crashkurs
Eigenschaften
Parallelisieren
Syntax
Lambda-Notation
Currying
Pattern Matching
Vererbung: abgeleitete Typklassen
◮
Ordnungsklasse, abgeleitet von Eq
class Eq a = > Ord a where
( <) , ( <=) , ( >=) , ( >) :: a -> a -> Bool
◮
Mehrfachvererbung möglich
class ( A a , B a ) = > C a where -- C erbt von A und B
...
Michael Kerscher
Ferienakademie - Kurs 1 - parallel Haskell
Einführung
Haskell Crashkurs
Eigenschaften
Parallelisieren
Syntax
Lambda-Notation
Currying
Pattern Matching
Polymorphie
Haskell kennt Polymorphie.
◮
Typvariablen
length
:: [ a ] - > Int
length []
= 0
length ( x : xs ) = 1 + length xs
(++) :: [ a ] -> [ a ] -> [ a ] -- L i s t e n k o n k a t e n a t i o n
◮
Typklassen
sort :: Ord a = > [ a ] -> [ a ]
Michael Kerscher
Ferienakademie - Kurs 1 - parallel Haskell
Einführung
Haskell Crashkurs
Eigenschaften
Parallelisieren
Syntax
Lambda-Notation
Currying
Pattern Matching
Pattern Matching und Guards
◮
Pattern Matching erlaubt die Zerlegung von Parametern
mittels eines Strukturmusters
head ( x : xs ) = x
tail ( x : xs ) = xs
fst (a , _ )
= a
◮
Wächter sind boolsche Ausdrücke, die am Wert und nicht der
Struktur entscheiden
◮
Auswertung der Wächter von oben nach unten. Erster
akzeptierter wird ausgeführt. (Laufzeitfehler, falls kein
Wächter akzeptiert)
sign x | x > 0
| x = 0
| x < 0
= 1
= 0
= -1
Michael Kerscher
Ferienakademie - Kurs 1 - parallel Haskell
Einführung
Haskell Crashkurs
Eigenschaften
Parallelisieren
lazy evaluation
keine Nebeneffekte
referenzielle Transparenz
Eigenschaften von Haskell
Haskell besitzt interessante Eigenschaften, die für
Parallelisierbarkeit interessant sind.
◮
lazy evaluation
◮
frei von Nebeneffekten/rein funktional
◮
referenzielle Transparenz
Michael Kerscher
Ferienakademie - Kurs 1 - parallel Haskell
Einführung
Haskell Crashkurs
Eigenschaften
Parallelisieren
lazy evaluation
keine Nebeneffekte
referenzielle Transparenz
Auswertungsstrategie: lazy evaluation
◮
nicht benötigte berechnungsintensive Rechenschritte werden
ausgelassen
◮
nicht strikte Sprache. Trotz (1/0) = ⊥, ist folgender Code
gültig.
f x y = x / 2; -- y wird nicht ausgewert e t
a = f 2 (1/0) -- a = 1
◮
erlaubt das Arbeiten mit unendlichen Datenstrukturen
squares n = ( n * n ) : squares ( n +1) -- unendliche Liste
two_square s n = take 2 squares n -- durch lazy
evaluatio n t e r m i n i e r e n d
Michael Kerscher
Ferienakademie - Kurs 1 - parallel Haskell
Einführung
Haskell Crashkurs
Eigenschaften
Parallelisieren
lazy evaluation
keine Nebeneffekte
referenzielle Transparenz
keine Nebeneffekte
◮
Funktionen verändern keine Daten
◮
◮
◮
unveränderliche Objekte (immutable objects)
gleiche Funktionsparameter ⇒ gleicher Rückgabewert
keine globalen Zustandsvariablen
◮
◮
Auswertungsreihenfolge irrelevant
Mit mehren Prozessoren parallele Ausführung möglich
f :: ( Int -> Int ) -> Int -> Int -> Int
f g x y = g x + g y
Michael Kerscher
Ferienakademie - Kurs 1 - parallel Haskell
Einführung
Haskell Crashkurs
Eigenschaften
Parallelisieren
lazy evaluation
keine Nebeneffekte
referenzielle Transparenz
keine Nebeneffekte
◮
Variable unveränderbar, sobald Wert zugewiesen wurde
◮
in imperativer Sprache x=x+1 erlaubt
◮
in funktionalen Sprachen kein gültiger Ausdruck (terminiert
nicht)
◮
keine Kommunikation über Zustandsvariablen, nur über
Rückgabewerte und Parameter
◮
Spezieller Fall: Monaden
Michael Kerscher
Ferienakademie - Kurs 1 - parallel Haskell
Einführung
Haskell Crashkurs
Eigenschaften
Parallelisieren
lazy evaluation
keine Nebeneffekte
referenzielle Transparenz
referenzielle Transparenz
◮
Variablen sind Zeiger auf Berechnungen
◮
Ausdruck muss nur einmalig ausgewertet werden
◮
späterer Zugriff auf den Wert führt nicht mehr zu
Berechnungen
f :: ( Int -> Int ) -> Int -> Int
f n = a + a
-- a wird nur einmal berechnet
where a = n * n
-- ebenso wird n nur 1 x
ausgewer te t
Michael Kerscher
Ferienakademie - Kurs 1 - parallel Haskell
Einführung
Haskell Crashkurs
Eigenschaften
Parallelisieren
Laufzeitsystem
Data Parallel Haskell
parallel Haskell
Parallelisieren
Verschiedene Möglichkeiten, um Mehrkernprozessoren sinnvoll
auszulasten:
◮ implizite parallele Programmierung durch Features des
Laufzeitsystems/Compilers
◮
◮
◮
explizite parallele Programmierung durch Spracherweiterung
◮
◮
◮
bestehende Programme würden davon profitieren
Programmierer muss sich keine Gedanken über Parallelisierung
machen
Programmierer gibt dem Compiler gezielte Anweisungen
Es ermöglicht gezielte Eingriffe in den Programmfluss
semi-explizite parallele Programmierung
Michael Kerscher
Ferienakademie - Kurs 1 - parallel Haskell
Einführung
Haskell Crashkurs
Eigenschaften
Parallelisieren
Laufzeitsystem
Data Parallel Haskell
parallel Haskell
Laufzeitsystem
Der Compiler könnte selbstständig Threads für einzelne Ausdrücke
anlegen, da keine Seiteneffekte existieren. Probleme:
◮
◮
Nicht jedes Programm ist gut parallelisierbar (Bubble Sort)
Falls parallelisierbar,
◮
◮
◮
muss der Compiler die Aufgaben richtig verteilen können
der Aufwand für die Threaderzeugung darf den erreichten
Spar-Effekt nicht übersteigen
Trotz der Eigenschaften einer funktionalen Sprache
◮
◮
normale Anwendungen verwenden auch I/O
oder auch veränderliche Daten
Michael Kerscher
Ferienakademie - Kurs 1 - parallel Haskell
Einführung
Haskell Crashkurs
Eigenschaften
Parallelisieren
Laufzeitsystem
Data Parallel Haskell
parallel Haskell
Laufzeitsystem
Damit der Compiler parallelisieren könnte, sollten folgende
Eigenschaften erfüllt sein:
◮
◮
rein funktionaler Code, keine Seiteneffekte
genügend große Berechnungsblöcke, damit kein
Leistungsverlust auftritt
◮
◮
gut: Liste von Primzahlen faktorisieren
schlecht: (1+2)*(3+4)
Michael Kerscher
Ferienakademie - Kurs 1 - parallel Haskell
Einführung
Haskell Crashkurs
Eigenschaften
Parallelisieren
Laufzeitsystem
Data Parallel Haskell
parallel Haskell
Data Parallel Haskell
Data Parallel Haskell ist der Codename für eine Erweiterung des
Glasgow Haskell Compiler und seine Bibliotheken um nested data
parallelism zu unterstützen
Aus Usersicht ist nur ein neuer Datentyp eingeführt worden:
◮
Parallele Arrays (parallel arrays) die einer Liste ähnlich sind.
◮
Syntaktischer Zucker: statt [ t ] ⇒ [: t :]
◮
[: :] statt [ ] sind auch bei Listenkomprehension möglich
weiterhin parallele Versionen von bekannten Funktionen, die mit
dem Suffix P gekennzeichnet sind, wie mapP, foldP, filterP, etc.
Michael Kerscher
Ferienakademie - Kurs 1 - parallel Haskell
Einführung
Haskell Crashkurs
Eigenschaften
Parallelisieren
Laufzeitsystem
Data Parallel Haskell
parallel Haskell
Listen im Vergleich mit Parallelen Arrays
Es gibt zwei Hauptunterschiede zwischen den beiden Datentypen
◮ Listen
◮
◮
◮
◮
sind nicht strikt, Elemente können bei Bedarf z.b. mit take aus
unendlichen Listen geholt werden
können induktiv definiert werden
haben gerichtete foldR und foldL, die eine Liste von Werten
auf einen Wert reduzieren.
Parallele Arrays
◮
◮
◮
sind strikt. Elemente können parallel verarbeitet werden und
müssen immer alle zur Verfügung stehen
können nicht induktiv definiert werden
haben nur eine ungerichtete foldP Funktion die eine assoziative
Funktion als Parameter braucht.
Michael Kerscher
Ferienakademie - Kurs 1 - parallel Haskell
Einführung
Haskell Crashkurs
Eigenschaften
Parallelisieren
Laufzeitsystem
Data Parallel Haskell
parallel Haskell
nested data parallelism
Verschiedene Arten von Datenparallelismus
◮ flat data parallelism
◮
◮
Daten brauchen spezielle Struktur (gleiche Größe und Tiefe)
z.B. von CUDA genutzt
mapP (+1) [:1 ,2 ,3 ,4 ,5:]
◮
nested data parallelism
◮
◮
Unterstützt auch irreguläre Strukturen
z.B. Bäume mit unterschiedlich tiefen Ästen, dünnbesetzte
Matrizen (im compressed row format)
-- kann in einem Takt ausgefue h rt werden
mapP ( mapP (+1) ) [:[:1 ,2:] ,[:3 ,4 ,5:] ,[::] ,[:6:]:]
Michael Kerscher
Ferienakademie - Kurs 1 - parallel Haskell
Einführung
Haskell Crashkurs
Eigenschaften
Parallelisieren
Laufzeitsystem
Data Parallel Haskell
parallel Haskell
Beispiel: Quicksort
qsort :: Ord a = > [: a :] -> [: a :]
qsort [::] = [::]
qsort xs
= let
p = xs !: ( lengthP xs ’ div ’ 2) -- pivot aus
Mitte
ss = [: s | s <- xs , s < m :]
ms = [: s | s <- xs , s == m :]
gs = [: s | s <- xs , s > m :]
sorted = [: qsort xs ’ | xs ’ <- [: ss , gs :]:]
in
( sorted !: 0) +:+ ms +:+ ( sorted !:1)
◮
Die parallele Listenkomprehension sorted ist notwendig,
damit die Auswertung parallel laufen kann
◮
Berechnungsstruktur hängt von Vorsortierung ab
◮
Trotzdem wird intern in flat data umgewandelt
Michael Kerscher
Ferienakademie - Kurs 1 - parallel Haskell
Einführung
Haskell Crashkurs
Eigenschaften
Parallelisieren
Laufzeitsystem
Data Parallel Haskell
parallel Haskell
zu beachten
Data Parallel Haskell benötigt in der aktuellen Implementation ein
spezielles Prelude (Standardmodule), welche nicht mit dem
Standard-Prelude kompatibel ist.
◮
◮
ganzes Modul entweder normal“ oder parallelisiert
”
Für Datenübergabe zwischen den Codeteilen PArray
◮
◮
konvertierende Wrapperfunktion als Schnittstelle notwendig
spezielle Annotation, damit vektorisierter Code nicht in
normalen Code eingebettet wird.
Michael Kerscher
Ferienakademie - Kurs 1 - parallel Haskell
Einführung
Haskell Crashkurs
Eigenschaften
Parallelisieren
Laufzeitsystem
Data Parallel Haskell
parallel Haskell
Beispiel mit parallel arrays: Skalarprodukt
{ - # LANGUAGE PArr , P a r a l l e l L i s t C o m p # -}
{ - # OPTIONS - fvectorise # -}
module
where
import
import
import
DotP ( dotp_double , d o t p _ w r a p p e r )
qualified Prelude
Data . Array . Parallel . Prelude
Data . Array . Parallel . Prelude . Double
dotp_dou bl e :: [: Double :] -> [: Double :] -> Double
dotp_dou bl e xs ys = sumP [: x * y | x <- xs | y <- ys :]
-- alternati v e fuer [: x * y | (x , y ) <- zipP xs ys :]
d o t p _ w r a p p e r :: PArray Double -> PArray Double -> Double
{ - # NOINLINE d o t p _ w r a p p e r # -} -- Einbettun g in normalen
Code vermeiden
d o t p _ w r a p p e r v w = dotp_doub l e ( fromPArray P v ) ( fromPArra y P
w)
Michael Kerscher
Ferienakademie - Kurs 1 - parallel Haskell
Einführung
Haskell Crashkurs
Eigenschaften
Parallelisieren
Laufzeitsystem
Data Parallel Haskell
parallel Haskell
Parallel Haskell
Parallel Haskell ist wie Data Parallel Haskell eine Erweiterung von
Haskell.
◮ Data Parallel Haskell
◮
◮
v.A. parallele Bearbeitung von ( listenförmigen ) Daten
”
”
Parallel Haskell
◮
v.A. Parallelisierung von Algorithmen
Michael Kerscher
Ferienakademie - Kurs 1 - parallel Haskell
Einführung
Haskell Crashkurs
Eigenschaften
Parallelisieren
Laufzeitsystem
Data Parallel Haskell
parallel Haskell
SMP parallelism vs. Glasgow Parallel Haskell
Parallel Haskell existiert in zwei Implementierungen:
◮ SMP parallelism
◮
◮
◮
implementiert im offiziellen GHC
unterstützt Single Multiprozessor Machines (SMP)
Glasgow Parallel Haskell
◮
◮
wird separat von GHC entwickelt
unterstützt SMPs sowie ganze Rechner-Cluster
Parallel Haskell ist eine Erweiterung von Haskell
◮
Zwei neue Schlüsselwörter: par und seq
◮
Auswertungsstrategien
Michael Kerscher
Ferienakademie - Kurs 1 - parallel Haskell
Einführung
Haskell Crashkurs
Eigenschaften
Parallelisieren
Laufzeitsystem
Data Parallel Haskell
parallel Haskell
Ein Beispiel für die Anwendung von par und seq
-- U r s p r u e n g l i c h e r Fibonacci - Algorith mu s
nfib :: Int -> Int
nfib n | n <= 1 = 1
| otherwise = n1 + n2
where n1 = nfib ( n -1)
n2 = nfib ( n -2)
-- Typen von par und seq
par :: a -> b -> b
seq :: a -> b -> b
-- p a r a l l e l i s i e r t e r Fibonacci - Algorith m us
import Control . Parallel
nfibP :: Int -> Int
nfibP n | n <= 1 = 1
| otherwise = par n1 ( seq n2 ( n1 + n2 ) )
where n1 = nfibP (n -1)
n2 = nfibP (n -2)
Michael Kerscher
Ferienakademie - Kurs 1 - parallel Haskell
Einführung
Haskell Crashkurs
Eigenschaften
Parallelisieren
Laufzeitsystem
Data Parallel Haskell
parallel Haskell
par
par löst einen spark aus und liefert als Ergebnis das zweite
Argument
◮ Ergebnis von par a b = b
◮
◮
a wird in eine Queue gegeben, b wird sofort berechnet
par n1 (seq n2 (n1+n2))= seq n2 (n1+n2)
◮
n1 wird berechnet, wenn Kapazität verfügbar
Michael Kerscher
Ferienakademie - Kurs 1 - parallel Haskell
Einführung
Haskell Crashkurs
Eigenschaften
Parallelisieren
Laufzeitsystem
Data Parallel Haskell
parallel Haskell
seq
seq zwingt die Laufzeitumgebung, den ersten Parameter vor dem
Zweiten auszuwerten.
◮ Ergebnis von seq a b = b. Aber a wird vor b berechnet.
◮
◮
◮
seq n2 (n1 + n2)= n1 + n2
Zuerst wird n2 ausgewertet
Erst wenn n2 fertig ist, wird n1 + n2 berechnet
Michael Kerscher
Ferienakademie - Kurs 1 - parallel Haskell
Einführung
Haskell Crashkurs
Eigenschaften
Parallelisieren
Laufzeitsystem
Data Parallel Haskell
parallel Haskell
Strategien
◮
Haskell verwendet lazy-evaluation. Probleme:
◮
◮
◮
◮
Berechnungen im spark“-Ausdruck werden nicht vollständig
”
ausgewertet
Workaround: forcing function, welche Berechnung erzwingt.
Nachteil: Viele solcher Funktionen notwendig, Lesbarkeit
verschlechtert
Auswertungsstrategien beseitigen dieses Problem
◮
◮
gezielte Auswertung möglich
Strategien können kombiniert werden
Michael Kerscher
Ferienakademie - Kurs 1 - parallel Haskell
Einführung
Haskell Crashkurs
Eigenschaften
Parallelisieren
Laufzeitsystem
Data Parallel Haskell
parallel Haskell
Grundstrategien
◮
type Strategy a = a -> ()
◮
r0: keine Auswertung des Ausdrucks
r0 :: Strategy a
r0 _ = ()
◮
◮
Nützlich bei Auswertung eines Tupels, wenn nur ein Teil
notwendig ist.
rwhnf: Auswertung bis weak head normal form
rwhnf :: Strategy a
rwhnf x = x ‘seq ‘ ()
Michael Kerscher
Ferienakademie - Kurs 1 - parallel Haskell
Einführung
Haskell Crashkurs
Eigenschaften
Parallelisieren
Laufzeitsystem
Data Parallel Haskell
parallel Haskell
komplexere Strategien
◮
Grundstrategien nur für Grunddatentypen
◮
komplexere Datenstrukturen (Liste und Tupel)
class NFData a where
rnf :: Strategy a
rnf = rwhnf
-- Typklasse
instance NFData a = > NFData [ a ] where
rnf [] = ()
rnf ( x : xs ) = rnf x ‘ seq ‘ rnf xs
instance ( NFData a , NFData b ) = > NFData (a , b ) where
rnf (x , y ) = rnf x ‘ seq ‘ rnf y
Michael Kerscher
Ferienakademie - Kurs 1 - parallel Haskell
Einführung
Haskell Crashkurs
Eigenschaften
Parallelisieren
Laufzeitsystem
Data Parallel Haskell
parallel Haskell
Beispiel für Strategien
using wendet eine Strategie auf Werte an:
using :: a -> Strategy a -> a
using x s = s x ‘ seq ‘ x
Quicksort in einer parallelen Version unter Verwendung einer
Strategie:
quicksort S ( x : xs )
= losort ++ ( x : hisort ) ‘ using ‘ strategy
where
losort = quicksortS [ y | y <- xs , y < x ]
hisort = quicksortS [ y | y <- xs , y >= x ]
strategy result =
rnf losort ‘par ‘
rnf hisort ‘par ‘
rnf result
Michael Kerscher
Ferienakademie - Kurs 1 - parallel Haskell
Einführung
Haskell Crashkurs
Eigenschaften
Parallelisieren
Laufzeitsystem
Data Parallel Haskell
parallel Haskell
Vielen Dank
für die Aufmerksamkeit.
Michael Kerscher
Ferienakademie - Kurs 1 - parallel Haskell
Herunterladen