Περιεχόµενα 1) Εισαγωγή 2) Η έναρξη της Occam 3) Occam και η τεχνολογία Transputer 4) Εκδόσεις της occam 5) Occam Μοντέλο ταυτοχρονισµού 6) Κανόνες σύνταξης 7) Δοµή του προγράµµατος 8) Αρχική ενέργεια 9) Δοµές δεδοµένων 10) Κατασκευαστές (constructors) 11) Παράδειγµα 12) Μεθοδολογία για την ανάπτυξη προγράµµατος στην occam 13) Παράδειγµα (για την κατανόηση της µεθοδολογίας) 14) Τελικός κώδικας παραδείγµατος 15) Σύνοψη
Εισαγωγή Η Occam είναι µια παράλληλη γλώσσα προγραµµατισµού που αναπτύχθηκε στη Μεγάλη Βρετανία. Περιγραφή της γλώσσας Τις συνθήκες γύρω από τη δηµιουργία της Και τη σχέση της µε Inmos - Transputer. Εντολές Όπως θα δούµε και στην συνέχεια η occam είναι µια καλή γλώσσα για να «εξερευνήσετε» τον παράλληλο προγραµµατισµό.
Η Έναρξη Της Occam Οι ερευνητές του INMOS ανέπτυξαν ένα µοντέλο ταυτοχρονισµού, το οποίο ονόµασαν Occam. Από το µοντέλο αυτό, αναπτύχθηκε η γλώσσα προγραµµατισµού Occam. Η occam αναπτύχθηκε από τον David May Το όνοµά της προέρχεται από τον William του Όκαµ, ο οποίος ήταν ένας φιλόσοφος του 13 ου αιώνα.
Μία αρχαία φιλοσοφική αρχή του William ήταν «κράτησε τα πράγµατα απλά» Στόχος είναι η γλώσσα να µείνει απλή, εξ ου και το όνοµα. Είναι µία από τις γλώσσες που υποστηρίζουν παράλληλο προγραµµατισµό και βασίζονται σε CSP (Communicating Sequential Processes-επικοινωνία ακολουθιακών διεργασιών)
Occam και η τεχνολογία Transputer Ο επεξεργαστής transputer και η κάρτα τοποθέτησης: Από το µοντέλο του Occam, η Inmos ανέπτυξε ένα (chip) υλικό για την υποστήριξη συγχρονισµού του µοντέλου Αυτό το υλικό είναι στη µορφή ενός πολύ µεγάλης κλίµακας ολοκλήρωσης (VLSI) ενσωµατωµένο τσιπ (IC) και ονοµάζεται Transputer
Ο πρώτος µικροεπεξεργαστής Transputer (T414), δεν είχε καµία µονάδα κινητής υποδιαστολής και είχε µόνο 2 Kbytes RAM, έγινε διαθέσιµη το 1985. Ο Transputer είναι ένας µικροεπεξεργαστής 32-bit (µε ρολόι 20 MHz) που παρέχει 10 MIPS (εκατοµµύρια εντολές ανά δευτερόλεπτο) και 2,0 MFLOPS (εκατοµµύρια πράξεις κινητής υποδιαστολής ανά δευτερόλεπτο) επεξεργαστικής ισχύος, µε 4K bytes RAM και τη δυνατότητα ταυτόχρονης επικοινωνίας όλα σε ένα µόνο chip.
Αν και η occam είναι µια γλώσσα υψηλού επιπέδου, για την Transputer µπορεί να θεωρηθεί ως η γλώσσα assembly. Επειδή ο επεξεργαστής Transputer έχει σχεδιαστεί για να εκτελεί Occam, ο compiler µπορεί να δηµιουργήσει πολύ αποτελεσµατικό και συµπαγή κώδικα µηχανής Είναι ένας υψηλής απόδοσης µικροεπεξεργαστής και ο Transputer έχει στο τσιπ του τέσσερεις (4) σειριακές αµφίδροµες συνδέσεις (20 Megabits / δευτερόλεπτο) για να παρέχει ταυτόχρονη ανταλλαγή µηνυµάτων µε άλλα transputers. Η γλώσσα και το υλικό έχουν σχεδιαστεί έτσι ώστε ένα πρόγραµµα Occam που αποτελείται από µια συλλογή των ταυτόχρονων διεργασιών, µπορεί να εκτελεστεί σε ένα Transputer ή να κατανεµηθεί σε πολλά transputers µε ελάχιστη ή καµία αλλαγή στον κώδικα της Occam.
Εκδόσεις Tης Οccam Η πρώτη έκδοση της occam διανεµήθηκε από το Inmos στα ερευνητικά εργαστήρια και πανεπιστήµια το 1983. Αυτή η έκδοση της occam έχει γίνει γνωστή ως Occam 1 και διανεµήθηκε σε διάφορες µορφές. Από την εµπειρία που αποκτήθηκε κατά τα τρία χρόνια που µεσολάβησαν (1983-1986), ο David May και η οµάδα του στο Inmos είχαν αναπτύξει µια βελτιωµένη έκδοση της occam που ονοµάστηκε occam2. Occam2.1 : ενδιάµεση εκδοχή µεταξύ των occam2 και occam-π, χωρίς πολλές σηµαντικές αλλαγές. Occam-π : είναι η τελευταία έκδοση της occam και περιέχει αρκετές από τις επεκτάσεις της occam2.1
Occam Μοντέλο ταυτοχρονισµού Στην occam, η επικοινωνία µεταξύ ταυτόχρονων διεργασιών επιτυγχάνεται µε το πέρασµα µηνυµάτων κατά µήκος από σηµείο σε σηµείο µέσω καναλιών Απαγόρευση κοινών µεταβλητών
Κανόνες Σύνταξης Όλες οι δεσµευµένες λέξεις θα πρέπει να είναι µε κεφαλαία γράµµατα. Κάθε δήλωση ξεκινά σε µια νέα γραµµή Κάθε νέα εντολή ξεκινά σε µία νέα γραµµή Τα σχόλια ορίζονται από το σύµβολο -- µέχρι και το τέλος της συγκεκριµένης γραµµής
Δοµή Του Προγράµµατος Η δοµή του προγράµµατος είναι µια διαδικασία µε τις δηλώσεις που περιέχει : <declares> <process> Παράδειγµα : INT j: SEQ j := 1 j := j + 1
Αρχική Ενέργεια Στην Occam, υπάρχουν πέντε αρχικές ενέργειες : 1) ανάθεση, 2) παραλαβή, 3) αποστολή, 4) Παράλειψη (skip) και 5) STOP
Ενέργεια Σύνταξη Παράδειγµα Ανάθεση <variable> := <expression> x := y + 1 Παραλαβή <channel>? <variable> Ch? x Αποστολή <channel>! <expression> Ch! y +1 Παράλειψη (skip) SKIP SKIP Stop STOP STOP a) Ανάθεση : καθορίζει την τιµή µιας µεταβλητής b) Παραλαβή : λαµβάνει την τιµή από ένα κανάλι (χρησιµοποιεί το σύµβολο? ) c) Αποστολή : στέλνει την τιµή της έκφρασης σε ένα κανάλι (χρησιµοποιεί το σύµβολο! ) d) Παράλειψη : δεν εκτελεί τίποτε άλλο και τερµατίζει η διεργασία e) Stop : δεν εκτελεί τίποτε άλλο, αλλά ούτε τερµατίζει και τη διεργασία (µε αποτέλεσµα να µην πάµε ποτέ στην επόµενη)
Δοµές Δεδοµένων Στην occam πρέπει να δηλώνονται όλες οι µεταβλητές µε τον εξής τρόπο : <τύπος> <ένα ή περισσότερα αναγνωριστικά διαχωρισµένα µε κώµα> Οι διαθέσιµοι τύποι είναι : INT για ακέραιους BOOL για true/false BYTE για χαρακτήρες REAL32 για πραγµατικούς 32-bit REAL64 για πραγµατικούς 64-bit CHAN για κανάλια Παράδειγµα : INT x, y : CHAN OF INT q :
Πίνακες Παράδειγµα : VAL n IS 100 : INT i, j : [n][n] REAL32 a: [n+1] CHAN OF ANY links : SEQ SEQ i = 0 FOR n SEQ j = 0 FOR n a[i][j] := 0.0 (REAL32) --other code
Κατασκευαστές - Constructors 1) SEQ Αν υπάρχουν πολλές διεργασίες να εκτελεστούν σε διαδοχική σειρά, χρησιµοποιείται ο κατασκευαστής SEQ. Παράδειγµα : SEQ a := 3 b := a + 5 c := a 5
2) PAR Εάν αρκετές διαδικασίες πρέπει να εκτελούνται συγχρόνως, τότε χρησιµοποιείται ο κατασκευαστής PAR. Παράδειγµα : PAR INT x : ch1? x --receive from channel ch1 INT y : ch2? y --receive from channel ch2
CHAN OF BYTE comms, buffer.in, buffer.out : PAR WHILE TRUE BYTE x : SEQ buffer.in? x comms! x WHILE TRUE BYTE y : SEQ comms? y buffer.out! y
3) IF Για να επιλέξει µια διεργασία που εξαρτάται από µία Boolean έκφραση η occam χρησιµοποιεί την εντολή IF Σύνταξη : IF <boolean exp1> p1 <boolean exp2> p2 <boolean exp3> p3 Παράδειγµα : IF a > b c := 3 a < b c := 4 TRUE -- πιάνει την περίπτωση όπου το a==b SKIP
4) While Για να επαναλάβει µία διαδικασία η occam χρησιµοποιεί την εντολή while. Σύνταξη : WHILE <boolean exp> p Παράδειγµα : WHILE i < 10 i := i + 1
5) ALT Ξεκινώντας από την κορυφή κάθε φορά η ALT επιλέγει τον πρώτο «φρουρό» που θα βρει και θα ικανοποιεί την συνθήκη. Κάθε φορά επιλέγεται µία και µόνο διαδικασία. Εάν δεν πληρούνται φύλακες, τότε η ALT περιµένει µέχρι µια φρουρά για να ικανοποιηθεί Σύνταξη : ALT ch1? x A[1] := x ch2? x A[2] := x time? AFTER begin.time + (10* sec) SKIP
Γενική Σύνταξη : ALT <quard1> p1 <quard2> p2. <quardn> pn Παράδειγµα : ALT flag1 & ch1? x a:= 3 (flag2 OR flag3) & ch2? y a := 4 SKIP a := -1
Μια παραλλαγή της ALT είναι η ALT PRI που δίνει προτεραιότητα στους πρώτους φρουρούς. Σε όλες τις τρέχουσες εφαρµογές της occam δεν υπάρχει διαφορά µεταξύ της ALT και PRI ALT. Αυτό σηµαίνει ότι οι εναλλακτικές λύσεις δεν αντιµετωπίζονται δίκαια, γιατί οι κορυφαίοι φύλακες ελέγχονται πρώτα. Αυτό µπορεί να οδηγήσει σε µη εκτέλεση των φρουρών κοντά στο κάτω µέρος αν οι κορυφαίοι φρουροί είναι πολύ «άπληστοι» και ικανοποιείται συνέχεια η συνθήκη τους.
6) PROCs Παράδειγµα : --υπόλοιπο πρόγραµµα PROC buff (CHAN OF BYTE in, out) WHILE TRUE BYTE x : SEQ in? x out! : -- end of buff CHAN OF BYTE comms, buffer.in, buffer.out : PAR buff(buffer.in, comms) buff(comms, buffer.out)
7) Time Παράδειγµα : VAL one.sec IS 15625 : INT begin.time : TIMER time : SEQ -- some code time? Begin.time PRI ALT Ch? y p1 time? AFTER begin.time + one.sec SKIP
Παράδειγµα # INCLUDE hostio.inc -- SP protocol PROC Sqrt.program(CHAN OF SP keyboard, screen) #USE hostio.lib -- i/o library always include BYTE key, result : REAL32 A : SEQ so.write.string.nl(keyboard, screen, Value Square Root ) SEQ i = 1 FOR 10 SEQ so.write.string(keyboard, screen, i = ) so.write.int(keyboard, screen, i, 2) A := REAL32 ROUND i so.write.real32(keyboard, screen, SQRT(A), 4, 6) so.write.nl(keyboard, screen) so.exit(keyboard, screen, sps.success) : -- end
Μεθοδολογία Για Την Ανάπτυξη Προγράµµατος Στην Occam Βήµα 1) Ίσος αριθµός παράλληλων διεργασιών, γραµµών και καναλιών επικοινωνίας. Σχεδιασµός της γενικής συνολικής προσέγγισης Βήµα 2) Γράψτε µια διεργασία για κάθε κουτί. Βήµα 3) Σχεδιάστε µια περιγραφή του PARs, και τον φορέα των καναλιών για τον παραλληλισµό και τις γραµµές επικοινωνίας.
Παράδειγµα (για την κατανόηση της µεθοδολογίας) Βήµα 1)
Βήµα 2) PROC Feed.x(CHAN OF ANY out) REAL32 x : BOOL error : WHILE TRUE SEQ so.write.string.nl(keyboard, screen, Type in a value for x ) so.read.echo.real32(keyboard, screen, x, error) so.write.nl(keyboard, screen) out! x out! x / 0.2 (REAL32) : --end of feed.x
PROC Print.Root(CHAN OF ANY In) -- receive X and Root and print them REAL32 X, Root: WHILE TRUE SEQ In? X In? Root so.write.string(keyboard, screen, "Square root of ") so.write.real32(keyboard, screen, X, 4, 6) so.write.string(keyboard, screen, "is ") so.write.real32(keyboard, screen, Root, 4, 6) so.write.nl(keyboard, screen) : -- end of Print.Root PROC NR(CHAN OF ANY In, Out) -- read in X and current Estimate, compute next iteration and ship out REAL32 X, Estimate: WHILE TRUE SEQ In? X In? Estimate Out! X Out! Estimate + (X / (2.0 (REAL32) * Estimate)) : -- end of NR
Βήµα 3) #INCLUDE "hostio.inc" -- contains SP protocol PROC Newton2(CHAN OF SP keyboard, screen) -- Pipeline example based on "Occam Programming Manual", Inmos, -- Prentice Hall, 1984, section 2.8. -- Computes square root of number by pipeline -- of Newton Raphson iterations -- Programmed by Dan Hyde, Bucknell University, June, 1987 -- updated Jan 5, 1991 #USE "hostio.lib" -- insert code for PROC Feed.X -- insert code for PROC Print.Root -- insert code for PROC NR VAL N IS 4: -- number of iterations in pipeline [N + 1] CHAN OF ANY Links: PAR -- Harness Feed.X(Links[0]) PAR i = 0 FOR N NR(Links[i], Links[i + 1]) Print.Root(Links[N]) : -- end of Main
PROC Controller(CHAN OF ANY Out, In) -- read in real numbers and feed X and X/2 to input of pipeline -- receive X and current estimate and print them REAL32 X, Root: BOOL error: WHILE TRUE SEQ so.write.string.nl(keyboard, screen,"type in a value for X") so.read.echo.real32(keyboard, screen, X, error) so.write.nl(keyboard, screen) Out! X Out! X / 2.0 (REAL32) -- wait to compute the square root In? X In? Root so.write.string(keyboard, screen, "Square root of ") so.write.real32(keyboard, screen, X, 4, 6) so.write.string(keyboard, screen, "is ") so.write.real32(keyboard, screen, Root, 4, 6) so.write.nl(keyboard, screen) : -- end of Controller
Τελικός Κώδικας Παραδείγµατος #INCLUDE "hostio.inc" -- contains SP protocol PROC Newton2(CHAN OF SP keyboard, screen) -- Pipeline example based on "Occam Programming Manual", Inmos, -- Prentice Hall, 1984, section 2.8. -- Computes square root of number by pipeline -- of Newton Raphson iterations -- Programmed by Dan Hyde, Bucknell University, June, 1987 -- updated Jan 5, 1991 #USE "hostio.lib"
PROC Controller(CHAN OF ANY Out, In) -- read in real numbers and feed X and X/2 to input of pipeline -- receive X and current estimate and print them REAL32 X, Root: BOOL error: WHILE TRUE SEQ so.write.string.nl(keyboard, screen, "Type in a value for X") so.read.echo.real32(keyboard, screen, X, error) so.write.nl(keyboard, screen) Out! X Out! X / 2.0 (REAL32) -- wait to compute the square root In? X In? Root so.write.string(keyboard, screen, "Square root of ") so.write.real32(keyboard, screen, X, 4, 6) so.write.string(keyboard, screen, "is ") so.write.real32(keyboard, screen, Root, 4, 6) so.write.nl(keyboard, screen) : -- end of Controller
PROC NR(CHAN OF ANY In, Out) -- read in X and current Estimate, compute next iteration and ship out REAL32 X, Estimate: WHILE TRUE SEQ In? X In? Estimate Out! X Out! Estimate + (X / (2.0 (REAL32) * Estimate)) : -- end of NR VAL N IS 4: -- number of iterations in pipeline [N + 1] CHAN OF ANY Links: PAR -- Harness Controller(Links[0], Links[N]) PAR i = 0 FOR N NR(Links[i], Links[i + 1]) : -- end of Main
Σύνοψη Η γλώσσα προγραµµατισµού Occam είναι µια γλώσσα µε την οποία µπορούµε να εκφράσουµε τον συγχρονισµό. Είναι ιδιαίτερα χρήσιµο για τη διδασκαλία των εννοιών των παράλληλων αλγορίθµων. Ένα πλεονέκτηµα της occam είναι η απλότητά της καθώς και ο προγραµµατιστής δεν χρειάζεται να ασχοληθεί µε κοινές µεταβλητές και των συναφών προβληµάτων τους.
Βιβλιογραφία Occam Manual 3 Dijkstra, E. W., Guarded Commands, Nondeterminacy and Formal Derivations of Programs, Communications of the ACM, Vol. 18, 1975, pp. 453-7. Hoare, C. A. R., Communicating Sequential Processes, Comm. ACM, Vol. 21, No. 8, 1978, pp. 666-677. Hoare, C. A. R., Communicating Sequential Processes, Prentice Hall, 1985. Inmos Limited, Occam 2 Reference Manual, Prentice Hall, 1988. Jones, Geraint and Michael Goldsmith, Programming in Occam 2, Prentice Hall, 1988. May, David, Occam, SIGPLAN Notices, Vol. 18, No. 4, April, 1983, pp. 69-79. May, David, Occam2 Product Definition Manual, Inmos, June, 1986. May, David and Richard Taylor, Occam: An Overview, Microprocessors and Microsystems, Vol. 8, No. 2, March, 1984, pp. 73-79. Walker, Paul, The Transputer, BYTE, May, 1985. Whitney-Strevens, Colin, The Transputer, SIGARCH Newsletter, Vol. 13, No. 3, June, 1985, pp. 292-300