Klaus-Peter Löhr! 3 Datenfluss! 3.1 Spezifikation von Filtern ! 3.2 Implementierung von Filtern 3.3 Komposition über Kanäle! Zusammenfassung ! ! WS 13/14 ALP 5 - Datenfluss !2! !4! !10! !31! 1 3.1 Spezifikation von Filtern! Spezifikation eines Filters Filter: Abbbildung von Eingabefolgen auf Ausgabefolgen Signatur: getypte Ein/Ausgabe-Ports, z.B. filter :: Param->[X]->[Y] -> ([U], [V]) Semantik: filter p x y = .....! WS 13/14 ALP 5 - Datenfluss 2 Termination von Filtern: bei endlichen Eingabefolgen mit Ende-Markierungen wie [], ^D, "EOF", ‘.', ...! terminierend: Spezifikation fordert endliche E/A-Folgen Beispiele: Unix sort, Haskell sort, sum u.U. terminierend: E/A-Folgen können unendlich sein Beispiele: Unix grep, Haskell filter! ! nichtterminierend: Eingabefolgen müssen unendlich sein (d.h. Filter wartet grundsätzlich auf Eingabe) WS 13/14 ALP 5 - Datenfluss 3 3.2 Implementierung von Filtern! Voraussetzung: die Programmiersprache verfügt über kanalbezogene Kommunikationsmechanismen (2.3, S.20)! Es folgen Beispiele für diesen Spezialfall: in1! in2! out1! filter out2! (filter der Einfachheit halber ohne weitere Parameter) ! WS 13/14 ALP 5 - Datenfluss 4 Occam: (inspiriert von CSP [Hoare 1985]) ! !PROC filter(CHAN OF INT in1, in2, out1, out2) ! ! SEQ .....! ! in1 ? mesvar ! ! !Empfangen ! ! .....! ! out2 ! message ! !Senden ! ! ALT ! ! ! !disjunktives Empfangen ! ! in1 ? mesvar! ! out1 ! message! ! guard & in2 ? mesvar !verzögertes Empfangen ! ! out2 ! message! !:! l synchrone Kommunikation (ungepuffert!) l höchstens je ein Sender und Empfänger je Kanal! WS 13/14 ALP 5 - Datenfluss 5 ! Go: ! !func ! ! ! ! ! ! ! ! ! ! !}! [Google 2007] filter(in1, in2 <-chan int, ! out1, out2 chan<- int) {! mesvar := <-in1 ! !Empfangen ! .....! out2 <- message ! !Senden ! select { ! ! !disjunktives(!) Empfangen ! case mesvar := <-in1 :! ...! case mesvar := <-in2 : ! ! ...! }! l synchrone oder asynchrone Kommunikation WS 13/14 ALP 5 - Datenfluss 6 Unix (hier mit C): // usage: filter in2 out2 !int main(int argc, char** argv) {! !read(0, &message, count); ... !Empfangen ! !int c = open(argv[2], flags); !(aktualisiere out2)! !write(c, message, count); ...! !Senden !! !} ! l beschränkt gepuffert l Erstes Argument von read/write („file descriptor“) ist Portnummer : 0/1/2 = Standard-E/A/Fehler-Kanäle. Zusätzlich: 3/4/... „durch explizite Aktualisierung“ gemäß Kanalnamen im Argumentvektor. l disjunktives Empfangen/Senden mit select-Systemaufruf l keine Typisierung: Bytestrom! WS 13/14 ALP 5 - Datenfluss 7 Haskell: filter :: [Int]->[Int] -> ([Int],[Int]) filter x y = (u,v) where ! ! ! u = ...! ! ! v = ...! l synchrone Kommunikation (ungepuffert), vermittelt durch verzögerte Listen (lazy lists, streams) ! l Argumente = Eingabefolgen anonymes Ergebnis = Tupel der Ausgabefolgen „Ports“ x y u v l „Senden“ = Listenkopf zur Verfügung stellen „Empfangen“ = Listenkopf übernehmen l starke Typisierung WS 13/14 ALP 5 - Datenfluss 8 Haskell: Einfache Anbindung an Standard-Ein/Ausgabe ! interact :: (String -> String) -> IO ()! ! macht interact f zum Filter mit Standard-E/A ! Beispiel: Programmdatei lower.hs enthält Haskell-Skript ! ! ! ! !import Data.Char! !main = interact (map toLower)! è ! WS 13/14 !runhugs lower ! !wandelt für die Ausgabe alle eingelesenen Buchstaben in Kleinbuchstaben um ALP 5 - Datenfluss 9 3.3 Komposition über Kanäle! x! a! y! b! (2) (1) u! c! d! w! v! (3) WS 13/14 ALP 5 - Datenfluss 10 (1) Rückkoppelung (Zyklus): möglich, in der Praxis selten (typisch: Datenflussmaschine [2.3, S. 17]) (2) Verschmelzen: nichtdeterministisch, oft akzeptabel (typisch: gleichartige Daten aus mehreren Quellen) (3) Splitten: nichtdeterministisch, selten akzeptabel (typisch: Lastverteilung) Beachte: WS 13/14 Wenn alle Filter determiniert sind und jeder Kanal höchstens je einen Sender und Empfänger hat, ist das zusammengesetzte Programm determiniert. Es ist selbst wiederum als Filter einsetzbar. ALP 5 - Datenfluss 11 Verklemmungsgefahr: steigt mit sinkender Pufferkapazität Verklemmungsfreiheit liegt genau dann vor, wenn Ø unbeschränkte Pufferung: Zyklenfreiheit Ø beschränkte Pufferung: Kreisfreiheit* Ø keine Pufferung: Kreisfreiheit* * d.h. bei Ignorierung der Kantenrichtungen WS 13/14 ALP 5 - Datenfluss 12 Fairness: betrifft die Behandlung blockierender Kommunikationsoperationen beim Verschmelzen oder Splitten Ø unbeschränkte Pufferung: nur Empfangen kann blockieren Ø beschränkte Pufferung: auch Senden kann blockieren Ø keine Pufferung: auch Senden kann blockieren E In jedem Fall ist FCFS wünschenswert. WS 13/14 ALP 5 - Datenfluss 13 Beschreibung der Komposition: graphisch (wie auf S. 9) mit eigener Koordinations/Kompositionssprache mit Implementierungssprache der Komponenten ! In jedem Fall formale Sprache mit Syntax und Semantik ! WS 13/14 ALP 5 - Datenfluss 14 3.3.1 ... mit graphischer Komposition! ! Viele Ansätze in der Forschung - wenig praktische Systeme ! Beispiel 1: LabVIEW Graphische „Datenflusssprache“ für Laborautomatisierung aber eher graphische Beschreibung von Datenabhängigkeiten als Komposition nichtsequentieller Programme. Automatische Codeerzeugung. WS 13/14 ALP 5 - Datenfluss 15 (Quelle: http://www.upscale.utoronto.ca/PVB/LabView.html ) WS 13/14 ALP 5 - Datenfluss 16 Beispiel 2: Flow - ähnlich LabVIEW WS 13/14 ALP 5 - Datenfluss 17 (Quelle: http://www.mi.fu-berlin.de/inf/groups/ag-tech/projects/flow/ ) WS 13/14 ALP 5 - Datenfluss 18 3.3.2 ... mit Koordinationssprache! Populär sind Skriptsprachen, die von den Mechanismen des Betriebssystems zur Interprozesskommunikation Gebrauch machen. Beispiel Unix: Ø schwergewichtige Prozesse Ø Pipes und Named Pipes als Kanäle Ø Konfigurierung statisch (deklarativ) und/oder dynamisch (imperativ) Ø beschränkt gepuffert, nach FCFS bedient Ø Senden/Empfangen blockiert, bis Empfänger/Sender vorhanden. Ø Sendeversuch verursacht Ausnahme SIGPIPE (Fehler „Broken Pipe“), wenn kein Empfänger mehr vorhanden. Ø Empfangen liefert den Wert 0, wenn kein Sender mehr vorhanden. WS 13/14 ALP 5 - Datenfluss 19 Statisches Konfigurieren mit der Unix Shell: Verteiltes Programm rein deklarativ mittels Operator & : ! !x & y & z & x & ...! Pipe-Operator | an Stelle von & : vereinbart anonymen Kanal (= Pipe) zwischen den beiden Operanden, der die Ports 1 bzw. 0 im linken bzw. rechten Operanden aktualisiert ! Named Pipes („fifos“) ermöglichen beliebige Datenfluss-Graphen: WS 13/14 ALP 5 - Datenfluss 20 Named Pipes ermöglichen beliebige Datenfluss-Graphen: 1. Weitere Kanäle imperativ als Named Pipes bereitstellen: ! !z.B. mkfifo a b c d ...! 2. Die Filter mit diesen Kanälen passend parametrisieren, z.B. ! WS 13/14 x a b & y b c & ...! Achtung: ob ein Argument als Ein- oder Ausgabekanal oder als „normaler“ Parameter fungiert, ist der Spezifikation von x zu entnehmen! 3. Die Named Pipes wieder abräumen: rm a b c ... ALP 5 - Datenfluss 21 Zur Erinnerung: Ein/Ausgabe-Umlenkung mit < bzw. > wie z.B. in! ! ! ! !cat <a >b! ! wobei a,b Dateien - aber auch Named Pipes sein können ! Beispiel: statt x a b Standard-E/A einbeziehen: x a >b ( ist äquivalent mit x a mit leicht geänderten x und y ! WS 13/14 ALP 5 - Datenfluss & y b c ! & | y <b c ! y c ) 22 Prinzip: System aus Filtern ist selbst wieder Filter ! Ø Skript mit formalen Parametern $1,$2,.., z.B. für 2.3, S. 18: ! !mkfifo x ! !merge $1 $2 >x & merge x $3 ! !rm x ! Ø Benennung durch Dateinamen des Skripts, z.B. merge3.sh !(keine Vereinbarung von formalen Parametern) Ø Als Programm deklarieren durch Erteilung des x-Rechts Ø Ausführung mit aktuellen Parametern wie normales Programm, z.B. merge3.sh in1 in2 in3 WS 13/14 ALP 5 - Datenfluss 23 Beispiel für „System als Subsystem verwenden“: Programm check.sh enthält ! !runhugs lower <$1 | java Check $2 ! Damit Programm checkgerman.sh ! ! ! ! !check.sh $1 german.dic | sort | uniq -u! angewendet z.B. so: ! checkgerman.sh mytext! Weitere Möglichkeiten der Shell, z.B. ! WS 13/14 !a|b|c & x|y|z & ALP 5 - Datenfluss ! (è man bash) 24 Die beteiligten Filter können in beliebigen Sprachen implementiert sein (deren E/A auf der Unix-E/A basiert) ! Ein Skript kann selbst wiederum als Filter fungieren ! WS 13/14 ALP 5 - Datenfluss 25 Das Beispiel von S. 9: #!/bin/bash # usage: page9 <in2 in1 out1 >out2! mkfifo a b c d! !x a b <$1 \ ! & !y <a b >d \! & !u c d \! & !v <c \! & !w c d >$2 ! rm a b c d! ! ! Übungsfrage: welche Annahmen über die StandardE/A-Ports der beteiligten Programme werden hier gemacht? WS 13/14 ALP 5 - Datenfluss 26 3.3.3 ... mit textueller Programmiersprache! ... in der auch die Komponenten geschrieben sind, z.B. Occam, Go, Haskell, ..., Datenflußsprachen [Johnston et al. 2004] Occam (S. 5): Beispiel Verschmelzung wie in 2.3, S. 18: PROC merge3(CHAN OF INT in1, in2, in3, out)! ! CHAN OF INT x :! ! PAR! ! merge(in1,in2,x)! ! merge(in3,x,out)! !:! WS 13/14 ALP 5 - Datenfluss 27 Go (S. 6): func merge3(in1, in2, in3 <-chan int,! ! out chan<- int) {! ! x := make(chan int, 100)! ! go merge(in1, in2, x)! ! go merge(x, in3, out)! !}! ! ! Beachte: WS 13/14 go hat die Funktionsweise eines fork. Der Aufruf von merge3 bewirkt eine „imperative, schrittweise Erzeugung“ der Komponenten des Datenflusssystems (dagegen deklarativ bei Occam) ALP 5 - Datenfluss 28 Haskell (S. 8): „stream processing“ merge3 :: Num a => [a]->[a]->[a] -> [a]! !merge3 in1 in2 in3 =! ! merge (merge in1 in2) in3! in1! in2! in3! merge (x)! merge (out)! Keine echte Nichtsequentialität in Haskell! (Aber: Communicationg Haskell Processes [CHP]) WS 13/14 ALP 5 - Datenfluss 29 Beispiel Partialsummen von Skalarprodukt wie in 2.3, S. 17: sumprod x y = b where! a = zipWith(*) x y! b = zipWith(+) a (0:b) 0 x! * y! a! + b! Generell: Zyklus im Graphen entspricht Rekursion im Text Haskell-Literatur ist reiche Quelle komplexer Beispiele WS 13/14 ALP 5 - Datenfluss 30 Zusammenfassung! Ø Spezifikation der Filter Ø Implementierung der Filter mit Programmiersprache Ø Komposition der Filter über Kanäle - mit graphischer Sprache - mit Koordinations/Kompositionssprache - mit Programmiersprache Ø determiniert, wenn kein Splitten/Verschmelzen Ø aber Verklemmungsgefahr Ø komponiertes System ist wiederum Filter! WS 13/14 ALP 5 - Datenfluss 31 Quellen! C.A.R Hoare: Communicating Sequential Processes. Prentice-Hall 1985. http://www.usingcsp.com/ INMOS: Occam 2.1 Reference Manual. INMOS 1995. http://www.wotug.org/occam/documentation/oc21refman.pdf Google: Go. http://golang.org/ J.P. Morrison: Flow-Based Programming. Morrison Enterprises 2010 (2. ed.). ISBN 0-442-1771-5 W.M. Johnston et al.: Advances in Dataflow Programming Languages. ACM Computing Surveys 36.1, March 2004 (Fortsetzung:) WS 13/14 ALP 5 - Datenfluss 32 Quellen (Fortsetzung) Unix/Linux...: pubs.opengroup.org/onlinepubs/9699919799/ www.FreeBSD.org/ www.linuxmanpages.com/ dell9.ma.utexas.edu/cgi-bin/man-cgi?pipe+7 Haskell: www.haskell.org/haskellwiki/Haskell en.wikibooks.org/wiki/Haskell www.haskell.org/haskellwiki/Concurrency www.cs.kent.ac.uk/projects/ofa/chp/ CHP: LabVIEW: www.ni.com/gettingstarted/labviewbasics/d/ Flow: www.mi.fu-berlin.de/inf/groups/ag-tech/projects/flow/ WS 13/14 ALP 5 - Datenfluss 33