Λ10 Παράλληλος & Κατανεμημένος Προγραμματισμός 2009

Σχετικά έγγραφα
Κεφάλαιο VΙΙ (λίγο διαφορετικό)

26/3/2012 Προγραμματισμός συστημάτων κοινόχρηστης μνήμης (Ι) Β. Δημακόπουλος

Μέρος Ι: νήματα POSIX Κεφάλαιο 4 (νέο βιβλίο) Κεφάλαιο 7 (παλιές σημειώσεις)

Υ07 Παράλληλα Συστήματα & 29/3/2016 Προγραμματισμός συστημάτων κοινόχρηστης μνήμης (Ι)

Τμήμα Μηχανικών Πληροφορικής Τ.Ε. Σχολή Τεχνολογικών Εφαρμογών Ακαδημαϊκό έτος

16. Πίνακεσ και Συναρτήςεισ

Δείκτεσ Διαχείριςθ Μνιμθσ. Βαγγζλθσ Οικονόμου Διάλεξθ 8

17. Πολυδιάςτατοι πίνακεσ

Προγραμματισμός με Κοινόχρηστο Χώρο Διευθύνσεων 4

Εργαστήριο 14. Συγχρονισμός Νημάτων (χρήση pthread_mutex_t, pthread_cond_t)

ΛΕΙΣΟΤΡΓΙΚΆ ΤΣΉΜΑΣΑ. 2 ο Εργαςτιριο Διαχείριςθ Διεργαςιϊν

Η γλώςςα προγραμματιςμού C

ΝΗΜΑΤΑ - ΕΡΓΑΣΤΗΡΙΟ 1 - ΣΗΜΕΙΩΣΕΙΣ

3 ΕΝΤΟΛΕΣ ΕΠΑΝΑΛΗΨΗΣ ( while, do while )

ΛΕΙΣΟΤΡΓΙΚΆ ΤΣΉΜΑΣΑ. 3 ο Εργαςτιριο υγχρονιςμόσ Διεργαςιϊν

Εθνικό Μετσόβιο Πολυτεχνείο Σχολή Ηλεκτρολόγων Μηχ. και Μηχανικών Υπολογιστών Εργαστήριο Υπολογιστικών Συστημάτων. Συγχρονισμός

5 ΜΕΘΟΔΟΙ - ΠΑΡΑΜΕΤΡΟΙ

Εθνικό Μετσόβιο Πολυτεχνείο Σχολή Ηλεκτρολόγων Μηχ. και Μηχανικών Υπολογιστών Εργαστήριο Υπολογιστικών Συστημάτων. Συγχρονισμός

Υ07 Παράλληλα Συστήματα /3/2018 Προγραμματισμός συστημάτων κοινόχρηστης μνήμης (IΙ)

ΕΝΟΤΗΤΑ 2: ΤΟ ΛΟΓΙΣΜΙΚΟ ΤΟΥ ΥΠΟΛΟΓΙΣΤΗ. ΚΕΦΑΛΑΙΟ 5: Γνωριμία με το λογιςμικό του υπολογιςτι

2/4/2012 Προγραμματισμός συστημάτων κοινόχρηστης μνήμης (ΙΙ) OpenMP Β. Δημακόπουλος

Ειςαγωγι ςτθν Επιςτιμθ Υπολογιςτϊν. Ειςαγωγι ςτθν Python

Εκφωνήσεις ασκήσεων εργαστηρίου 2 (pthreads)

Ένα πρόβλθμα γραμμικοφ προγραμματιςμοφ βρίςκεται ςτθν κανονικι μορφι όταν:

Παράλληλη Επεξεργασία

Προγραμματισμός με το OpenMP Β. Δημακόπουλος

ΕΡΓΑΣΗΡΙΑΚΗ ΑΚΗΗ 4.1

Ρρογραμματιςμόσ Μεκόδων Επίλυςθσ Ρροβλθμάτων. 18. Αλφαριθμητικά. Ιωάννθσ Κατάκθσ. ΕΡΛ 032: Ρρογραμματιςμόσ Μεκόδων Επίλυςθσ Ρροβλθμάτων

Προγραμματιςμόσ Μεκόδων Επίλυςθσ Προβλθμάτων. 19. Αλφαριθμητικά II. Ιωάννθσ Κατάκθσ. ΕΠΛ 032: Προγραμματιςμόσ Μεκόδων Επίλυςθσ Προβλθμάτων

ΕΦΑΡΜΟΓΖσ ΒΆΕΩΝ ΔΕΔΟΜΖΝΩΝ ΚΑΙ ΔΙΑΔΙΚΣΥΟΤ. Ειρινθ Φιλιοποφλου

ςυςτιματα γραμμικϊν εξιςϊςεων

ΡΟΓΑΜΜΑΤΙΣΤΙΚΟ ΡΕΙΒΑΛΛΟΝ MICRO WORLDS PRO

Μάθημα 9 ο ΤΕΧΝΙΚΕΣ ΔΙΑΧΕΙΡΙΣΗΣ ΕΙΚΟΝΙΚΗΣ ΜΝΗΜΗΣ

Παρουσίαση 5 ης Άσκησης:

ΚΥΠΡΙΑΚΗ ΜΑΘΗΜΑΤΙΚΗ ΕΤΑΙΡΕΙΑ

Μέρος IΙ: OpenMP Κεφάλαιο 4 (νέο βιβλίο)

x n D 2 ENCODER m - σε n (m 2 n ) x 1 Παραδείγματα κωδικοποιθτϊν είναι ο κωδικοποιθτισ οκταδικοφ ςε δυαδικό και ο κωδικοποιθτισ BCD ςε δυαδικό.

Δομζσ Αφαιρετικότθτα ςτα Δεδομζνα

ΛΕΙΣΟΤΡΓΙΚΆ ΤΣΉΜΑΣΑ. 7 θ Διάλεξθ Διαχείριςθ Μνιμθσ Μζροσ Γ

Παρουσίαση 5 ης Άσκησης:

ΣυγχρονισµόςσεΣυστήµατα ΠολλαπλώνΝηµάτων

Visual C Express - Οδηγός Χρήσης

Δομθμζνοσ Προγραμματιςμόσ. Βαγγζλθσ Οικονόμου Εργαςτιριο 9

Ε-85: Ειδικά Θέµατα Λογισµικού

ΛΕΙΣΟΤΡΓΙΚΆ ΤΣΉΜΑΣΑ. 3 θ Διάλεξθ υγχρονιςμόσ Διεργαςιϊν

Προγραμματιςμόσ Μεκόδων Επίλυςθσ Προβλθμάτων. 15. Πίνακεσ ΙI. Ιωάννθσ Κατάκθσ. ΕΠΛ 032: Προγραμματιςμόσ Μεκόδων Επίλυςθσ Προβλθμάτων

ΛΕΙΤΟΥΓΙΚΆ ΣΥΣΤΉΜΑΤΑ. 5 ο Εργαςτιριο Ειςαγωγι ςτθ Γραμμι Εντολϊν

Συγχρονισμός & σηματοφόροι. Προγραμματισμός II 1

Παράλληλη Επεξεργασία

Α) Ενδεικτικϋσ απαντόςεισ των θεμϊτων

Modellus 4.01 Συ ντομοσ Οδηγο σ

Στα προθγοφμενα δφο εργαςτιρια είδαμε τθ δομι απόφαςθσ (ι επιλογισ ι ελζγχου ροισ). Ασ κυμθκοφμε:

Προγραµµατισµός Νηµάτων. Αρχικοποίηση µιας Φοράς pthread_once_t once_block = PTHREAD_ONCE_INIT; pthread_mutex_t mutex;

ΛΕΙΣΟΤΡΓΙΚΆ ΤΣΉΜΑΣΑ. 4 θ Διάλεξθ θμαφόροι

Εργαςτιριο Πικανοτιτων Σθμειϊςεισ προγραμματιςμοφ: βαςικζσ γνϊςεισ ανάπτυξθσ εφαρμογϊν. Κϊςτασ Αρβανιτάκθσ

NIKOΛΑΟΣ ΝΤΙΡΛΗΣ 5ο ΦΡΟΝΤΙΣΤΗΡΙΟ ΑΙΘΟΥΣΑ Β4

Dr. Garmpis Aristogiannis - EPDO TEI Messolonghi

Ειδικά Θζματα Βάςεων Δεδομζνων

ΕΝΟΣΗΣΑ 3: ΧΡΗΗ ΕΡΓΑΛΕΙΩΝ ΕΚΦΡΑΗ ΚΑΙ ΔΗΜΙΟΤΡΓΙΑ

Λειτουργικά Συστήματα

Αςκιςεισ ςε (i) Δομζσ Ευρετθρίων και Οργάνωςθ Αρχείων (ii) Κανονικοποίθςθ

Πόςο εκτατό μπορεί να είναι ζνα μη εκτατό νήμα και πόςο φυςικό. μπορεί να είναι ζνα μηχανικό ςτερεό. Συνιςταμζνη δφναμη versus «κατανεμημζνησ» δφναμησ

Δομζσ Δεδομζνων Πίνακεσ

Σφντομεσ Οδθγίεσ Χριςθσ

Πανεπιςτιμιο Κφπρου ΟΙΚ 223: Μακθματικά για οικονομολόγουσ ΙΙ Διδάςκων:

Παράςταςη ακεραίων ςτο ςυςτημα ςυμπλήρωμα ωσ προσ 2

Αςφάλεια και Προςταςία Δεδομζνων

ΠΡΟΓΡΑΜΜΑΣΙΜΌ ΤΠΟΛΟΓΙΣΏΝ. Κεφάλαιο 8 Η γλϊςςα Pascal

Αυτόνομοι Πράκτορες. Αναφορά Εργασίας Εξαμήνου. Το αστέρι του Aibo και τα κόκαλα του

ΗΛΕΚΣΡΟΝΙΚΗ ΤΠΗΡΕΙΑ ΑΠΟΚΣΗΗ ΑΚΑΔΗΜΑΪΚΗ ΣΑΤΣΟΣΗΣΑ

Εργαστήριο ΔΙΕΡΓΑΣΙΕΣ - ΔΙΑΧΕΙΡΙΣΗ

ΕΝΟΤΗΤΑ 2: ΕΠΙΚΟΙΝΩΝΩ ΜΕ ΤΟΝ ΥΠΟΛΟΓΙΣΤΗ. ΚΕΦΑΛΑΙΟ 5: Αρχεία - Φάκελοι

Πωσ δθμιουργώ φακζλουσ;

Άπειρεσ κροφςεισ. Τθ χρονικι ςτιγμι. t, ο δακτφλιοσ ςυγκροφεται με τον τοίχο με ταχφτθτα (κζντρου μάηασ) μζτρου

Δημιουργία & Τερματισμός Διεργασιών. Προγραμματισμός II 1

Ειςαγωγή ςτην πληροφορική

Λ10 Παράλληλος & Κατανεμημένος Προγραμματισμός 2009

Λειτουργικά Συστήματα

Virtualization. Στο ςυγκεκριμζνο οδηγό, θα παρουςιαςτεί η ικανότητα δοκιμήσ τησ διανομήσ Ubuntu 9.04, χωρίσ την ανάγκη του format.

Διαχείριςη Αριθμοδεικτών (v.1.0.7)

Μάκθςθ Κατανομϊν Πικανότθτασ και Ομαδοποίθςθ

Οδηγίεσ προσ τουσ εκπαιδευτικοφσ για το μοντζλο του Άβακα

343 Ειςαγωγι ςτον Προγραμματιςμό

Εργαςτιριο Βάςεων Δεδομζνων

ΕΡΓΑΣΗΡΙΟ ΕΦΑΡΜΟΜΕΝΗ ΠΛΗΡΟΦΟΡΙΚΗ

Εγχειρίδιο Χρήςησ Προςωποποιημζνων Υπηρεςιών Γ.Ε.ΜΗ. (Εθνικό Τυπογραφείο)

Πλαγιογώνια Συςτήματα Συντεταγμζνων Γιϊργοσ Καςαπίδθσ

Διαγώνισμα Φυσική ς Α Λυκει ου Έργο και Ενε ργεια

Αυτόματη δημιουργία στηλών Αντιστοίχηση νέων λογαριασμών ΦΠΑ

Λαμβάνοντασ υπόψη ότι κατά την πρόςθεςη δφο δυαδικϊν ψηφίων ιςχφει: Κρατοφμενο

Σύ ντομος Οδηγο ς χρη σης wikidot για τα projects

Συστήματα Παράλληλης και Κατανεμημένης Επεξεργασίας

Ειδικά Θζματα Βάςεων Δεδομζνων

Προγραμματιςμόσ Μεκόδων Επίλυςθσ Προβλθμάτων. 20. Αρχεία. Ιωάννθσ Κατάκθσ. ΕΠΛ 032: Προγραμματιςμόσ Μεκόδων Επίλυςθσ Προβλθμάτων

ΛΕΙΣΟΤΡΓΙΚΆ ΤΣΉΜΑΣΑ. 9 θ & 10 θ Διάλεξθ Ιδεατι Μνιμθ Μζροσ Β

Τεχνικζσ Ανάλυςησ Διοικητικών Αποφάςεων

Άςκθςθ 1θ: Να γραφεί αλγόρικμοσ που κα δθμιουργεί με τθ βοικεια διπλοφ επαναλθπτικοφ βρόχου, τον ακόλουκο διςδιάςτατο πίνακα:

Εγχειρίδιο Χρήςησ Προςωποποιημζνων Υπηρεςιών Γ.Ε.ΜΗ. (Εθνικό Τυπογραφείο)

Εγχειρίδιο Χριςθσ τθσ διαδικτυακισ εφαρμογισ «Υποβολι και παρακολοφκθςθ τθσ ζγκριςθσ Εκπαιδευτικών Πακζτων»

ΑΔΡΑΝΕΙΑ ΜΑΘΗΣΕ: ΜΑΡΙΑΝΝΑ ΠΑΡΑΘΤΡΑ ΑΝΑΣΑΗ ΠΟΤΛΙΟ ΠΑΝΑΓΙΩΣΗ ΠΡΟΔΡΟΜΟΤ ΑΝΑΣΑΙΑ ΠΟΛΤΧΡΟΝΙΑΔΟΤ ΙΩΑΝΝΑ ΠΕΝΓΚΟΤ

Transcript:

Λ10 Παράλληλος & Κατανεμημένος Προγραμματισμός 2009 Μάθημα 2 ο 27/10/2009 Προγραμματισμός «κοινού χώρου διευθύνσεων» (κοινής μνήμης) Β. Δημακόπουλοσ

Shared address space / shared variables Σι χρειάηεται κανείσ για να προγραμματίςει ςε αυτό το μοντζλο: Οντότθτεσ εκτζλεςθσ (νιματα, διεργαςίεσ) Δθμιουργία, διαχείριςθ Κοινζσ μεταβλθτζσ μεταξφ των οντοτιτων Οριςμόσ μεταβλθτϊν (τι είναι κοινό και πωσ ορίηεται) Σισ διαβάηουν και τισ τροποποιοφν όλεσ οι διεργαςίεσ Αμοιβαίοσ αποκλειςμόσ Π.χ. κλειδαριζσ υγχρονιςμόσ Π.χ. κλιςεισ φραγισ (barrier calls) #2

Γιατί αμοιβαίοσ αποκλειςμόσ; Αρχικά η κοιμή μεταβλητή A είμαι 0 Νήμα Τ1 Νήμα Τ2 A = Α+1; Α = Α-1; Λεπτομζρεια εκτζλεςθσ τθσ εντολισ Α = Α±1 ςε ζναν επεξεργαςτι: α. Ο επεξεργαςτισ μεταφζρει από τθ μνιμθ τθν τιμι τθσ Α β. Αυξάνει/μειϊνει κατά 1 γ. Αποκθκεφει ςτθν μνιμθ τθν νζα τιμι. Χρονική ςτιγμή Τι κάνει ο επεξεργαςτήσ 1 Τι κάνει ο επεξεργαςτήσ 2 t α - t + 1 β α t + 2 γ β t + 3 - γ Α = -1 Χρονική ςτιγμή Τι κάνει ο επεξεργαςτήσ 1 Τι κάνει ο επεξεργαςτήσ 2 t - α t + 1 α β t + 2 β γ t + 3 γ Α = 1 Χρονική ςτιγμή Εντολή που εκτελεί ο επεξεργαςτήσ 1 Εντολή που εκτελεί ο επεξεργαςτήσ 2 t - α t + 1 - β t + 2 - γ t + 3 t + 4 t + 5 α β γ Α = 0 #3

Δθμιουργία οντοτιτων εκτζλεςθσ fork() για διεργαςίεσ int x = 2; (α)... x = fork(); (β) if (x == 0) /* παιδύ */ (γ) κώδικασ Α; (δ) else /* γονϋασ */ (ε) κώδικασ Β; (η) κώδικασ Γ;... main() fork(); fork(); fork(); main() int y = 0; y = 1; if (fork()) x = x+y; else x = x-y; printf( %d\n, x); Τι θα τυπωθεύ; Πόςεσ θα φτιαχτούν; #4

Δθμιουργία διεργαςιϊν Αντιγράφονται τα πάντα: Κακολικζσ μεταβλθτζσ ωρόσ (ότι ζχει γίνει malloc()) Ο κϊδικασ τθσ διεργαςίασ (ίςωσ να μθ χρειαςτεί αυτι θ αντιγραφι) τοίβα (ςτθν κατάςταςθ που βρίςκεται εκείνθ τθ ςτιγμι) Καταχωρθτζσ (p.x. program counter) Άρα, θ διεργαςία παιδί εκτελεί αμζςωσ μετά το fork() Άρα, τίποτε κοινό οι διεργαςίεσ μεταξφ τουσ Ιδιαίτερα χρονοβόρο Με τεχνικζσ όπωσ το copy-on-write μπορεί το Λ να μθν αντιγράψει τα πάντα (π.χ. τισ κακολικζσ μεταβλθτζσ) παρά μόνο όταν χρειαςτεί (δθλαδι πότε??), γλιτϊνοντασ κάποιον χρόνο #5

Δθμιουργία οντοτιτων εκτζλεςθσ νιματα (posix) Διαφορετικι λογικι ςτα νιματα Δεν δθμιουργείται αντίγραφο από τίποτε Δεν ξεκινάει θ εκτζλεςθ του νιματοσ από το ςθμείο δθμιουργίασ του Σο νιμα κα εκτελζςει μια ςυνάρτθςθ που κα του δοκεί και κα τερματίςει capitalize(char *strings[100]) pthread_create(&thrid, NULL, capfunc, (void*) string[5]);... void *capfunc(void *str)... #6

Προςοχι Πάντα #include <pthread.h> Μετάφραςθ: gcc <file.c> -D_REENTRANT -lpthread #7

Δθμιουργία νθμάτων pthread_create(&thrid, attributes, function_to_call, function_parameter); Η ςυνάρτθςθ του νιματοσ παίρνει πάντα μόνο ζνα όριςμα Σο νιμα «ηει» μζχρι να τελειϊςει (επιςτρζψει) θ ςυνάρτθςθ. Φυςικά θ ςυνάρτθςθ αυτι μπορεί να καλεί κι άλλεσ ςυναρτιςεισ Μόλισ επιςτρζψει το νιμα καταςτρζφεται Ο γονζασ (αρχικό νιμα), αφοφ δθμιουργιςει το νιμα ςυνεχίηει κανονικά τθν εκτζλεςι του main() pthread_create(&thrid, NULL, func, NULL); capitalize(char *strings[100]) pthread_create(&thrid, NULL, func, NULL); pthread_create(&thrid, NULL, func, NULL); for (i = 0; i < 100; i++) pthread_create(&thrid, NULL, capfunc, (void*) string[i]);... Πόςα θα φτιαχτούν; #8

Πϊσ μπορϊ να περάςω > 1 παραμζτρουσ; struct manyparams int x; int y; double z; ; main() struct manyparams myargs;... /* Pass a pointer to the structure */ pthread_create(&thrid, NULL, threadfunc, (void*) &myargs);... void *threadfunc(void *ptr) struct manyparams *s = ptr; /* Cast the pointer */... s->x += s->y;... #9

Σερματιςμόσ νιματοσ Δφο τρόποι: είτε επιςτρζφει από τθ ςυνάρτθςθ που του δόκθκε να εκτελζςει είτε καλεί τθν pthread_exit(&returnvalue) και τερματίηει αμζςωσ. Σιμι επιςτροφισ: είτε αυτό που γίνεται return από τθ ςυνάρτθςθ του νιματοσ είτε το όριςμα τθσ pthread_exit(). και ςτισ δφο περιπτϊςεισ, είναι δείκτθσ ςτθν τιμι αυτι (void *). #10

Αναμονι τερματιςμοφ νιματοσ main() pthread_t tids[5]; int i; for (i = 0; i < 5 i++) pthread_create(&tids[i], NULL, thrfunc, (void*) i); for (i = 0; i < 5; i++) pthread_join(tids[i], NULL); printf( All threads done.\n ); Σο cast αυτό κζλει πολφ προςοχι!! void *thrfunc(void *x) int id = (int) x; printf( Hi! I am thread %d\n, id); return (NULL); #11

Αμοιβαίοσ αποκλειςμόσ - κλειδαριζσ Από τουσ διάφορουσ τρόπουσ για αμοιβαίο αποκλειςμό, ο ςυχνότερα χρθςιμοποιοφμενοσ είναι οι κλειδαριζσ (locks). Η κλειδαριά είναι είτε ανοιχτι είτε κλειδωμζνθ. Όταν ζνα νιμα κλειδϊςει τθν κλειδαριά, οποιοδιποτε άλλο νιμα προςπακιςει να τθν κλειδϊςει κα αποτφχει και κα αναγκαςτεί να περιμζνει. Όταν το νιμα ολοκλθρϊςει τθ δουλειά του, ξεκλειδϊνει τθν κλειδαριά και ζνα από τα νιματα που περιμζνουν κα κατορκϊςει να τθν κλειδϊςει. Επομζνωσ, μία κρίςιμθ περιοχι του προγράμματοσ μπορεί να προςτατευκεί (αμοιβαίοσ αποκλειςμόσ) με μία κλειδαριά:... lock(kleidaria); <critical section> unlock(kleidaria);... #12

Κλειδαριζσ ςτα pthreads: mutexes main() pthread_mutex_t mymutex; pthread_mutex_init(&mymutex, NULL); pthread_mutex_lock(&mymutex);... /* Κρύςιμη περιοχό */ pthread_mutex_unlock(&mymutex); Αντί για pthread_mutex_init(), μποροφμε να κάνουμε και ςτατική αρχικοποίθςθ (αρχικοποίθςθ χρειάηεται πάντα): pthread_mutex_t mymutex = PTHREAD_MUTEX_INITIALIZER; #13

Τπολογιςμόσ του π = 3,14 Αρικμθτικι ολοκλιρωςθ π 1 4 1 0 x 2 4 3,5 3 2,5 2 1,5 1,5 1 0,5 0,5 0 0 0 1 2 3 4 5 6 7 8 9 10 0 0,1 0,2 0,3 0,4 0,5 0,6 0,7 0,8 0,9 1 διάστημα i (π λάτος διαστημάτων x W = 0,1) N 1 i 0 1 (i 4W 1 2) W 2 #define N 1000000 double pi = 0.0, W = 1.0/N; main() int i; for (i = 0; i < N; i++) pi += 4*W / (1 + (i+0.5)*(i+0.5)*w*w); printf("pi = %.10lf\n", pi); #14

Τπολογιςμόσ του π = 3,14... με 1 νιμα ανά επανάλθψθ #define N 100000 double pi = 0.0, W = 1.0/N; main() int i; for (i = 0; i < N; i++) pi += 4*W / (1 + (i+0.5)*(i+0.5)*w*w); printf("pi = %.10lf\n", pi); /* 1 νόμα ανϊ επανϊληψη */ #define N 100000 double pi = 0.0, W = 1.0/N; pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER; void *thrfunc(void *iter) int i = (int) iter; pthread_mutex_lock(&lock); pi += 4*W / (1 + (i+0.5)*(i+0.5)*w*w); pthread_mutex_unlock(&lock); main() int i; pthread_t tids[n]; /* Remember the tread ids */ for (i = 0; i < N; i++) pthread_create(&tids[i], NULL, thrfunc, (void *) i); for (i = 0; i < N; i++) pthread_join(tids[i], NULL); printf("pi = %.10lf\n", pi); #15

Προβλιματα Τπερβολικά πολλά νιματα (πολλά ςυςτιματα δεν επιτρζπουν πάνω από λίγεσ χιλιάδεσ) και επομζνωσ υπερβολικά «λεπτόκοκκοσ» παραλλθλιςμόσ (fine grain) Ακόμα και αν επιτρζπονταν τόςα πολλά νιματα, ο ςυναγωνιςμόσ για τθν κλειδαριά είναι τεράςτιοσ. Αποτζλεςμα: αργι εκτζλεςθ και μόνο για μθ ακριβι προςζγγιςθ του π. Μάκθμα: η καλφτερη τακτική είναι ςυνήθωσ να δημιουργοφμε τόςα νήματα όςοι είναι και οι επεξεργαςτζσ του ςυςτήματοσ #16

Μοίραςμα τθσ δουλειάσ ςε λίγα νιματα #define NPROCS 2 /* dual core */ #define N 10000000 /* Για ακρύβεια (ύδια με ςειριακό) */ #define WORK N/NPROCS double pi = 0.0, W = 1.0/N; pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER; void *thrfunc(void *iter) int i, me = (int) iter; for (i = me*work; i < (me+1)*work; i++) pthread_mutex_lock(&lock); pi += 4*W / (1 + (i+0.5)*(i+0.5)*w*w); pthread_mutex_unlock(&lock); main() int i; pthread_t tids[nprocs]; for (i = 0; i < NPROCS; i++) /* νόματα = # επεξεργατών */ pthread_create(&tids[i], NULL, thrfunc, (void *) i); for (i = 0; i < NPROCS; i++) pthread_join(tids[i], NULL); printf("pi = %.10lf\n", pi); Τι πάει ςτραβά; #17

Λίγα νιματα αποφυγι ςυναγωνιςμοφ #define NPROCS 2 /* dual core */ #define N 10000000 /* Για ακρύβεια (ύδια με ςειριακό) */ #define WORK N/NPROCS double pi = 0.0, W = 1.0/N; pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER; void *thrfunc(void *iter) int i, me = (int) iter; double mysum = 0.0; for (i = me*work; i < (me+1)*work; i++) mysum += 4*W / (1 + (i+0.5)*(i+0.5)*w*w); pthread_mutex_lock(&lock); pi += mysum; pthread_mutex_unlock(&lock); main() int i; pthread_t tids[nprocs]; for (i = 0; i < NPROCS; i++) /* νόματα = # επεξεργατών */ pthread_create(&tids[i], NULL, thrfunc, (void *) i); for (i = 0; i < NPROCS; i++) pthread_join(tids[i], NULL); printf("pi = %.10lf\n", pi); #18

Πίνακασ επί πίνακα for (i = 0; i < Ν; i++) for (j = 0; j < Ν; j++) for (k = sum = 0; k < N; k++) sum += Α[i][k]*B[k][j]; C[i][j] = sum; Παραλλθλοποίθςθ: Ενόσ βρόχου (i) μοίραςμα των επαναλιψεων του πρϊτου for ςε νιματα Δεν δουλεφει καλά πάντα, π.χ. τι γίνεται αν # επεξεργαςτϊν > Ν?? Δφο βρόχων (i και j) Checkerboard partitioning: παραλλθλοποίθςθ και των δφο βρόχων Μπορώ εναλλακτικά να παραλλθλοποιιςω τον βρόχο j και k? #19

Διαχωριςμόσ ςκακιζρασ c 00 c 01 c 0(S-1) c 0S c 0(N-1) c 10 c 11 c 1(S-1) c 1S c 1(N-1) C 00 C 01 C 0(M-1) c 20 c 21 c 2(S-1) c 2S c 2(N-1) Τποπίνακεσ διάςταςθσ S S c S0 c S1 c S(S-1) c SS c S(N-1) C 10 C 11 C 1(M-1) Άρα M = N/S υποπίνακεσ οριηόντια / κάκετα: M 2 υποπίνακεσ C (M-1)0 C (M-1)1 C (M-1)(M-1) c (N-1)0 c (N-1)1 c (N-1)S #20

Διαχωριςμόσ ςκακιζρασ αρίκμθςθ υποπινάκων C 00 C 01 C 0(M-1) C 10 C 11 C 1(M-1) Αν τουσ αρικμιςουμε από 0 ζωσ Μ 2-1, ο i-οςτόσ υποπίνακασ είναι ο C xy όπου: x = i / M y = i % M C xy C (M-1)0 C (M-1)1 C (M-1)(M-1) #21

Διαχωριςμόσ ςκακιζρασ το πρόγραμμα #define N 50 /* Πύνακασ 50x50 */ #define NPROCS 25 /* Αριθμόσ επεξεργαςτών/διεργαςιών */ #define M 5 /* Η ρύζα του 25 */ #define S N/M /* S = N / M */ double A[N][N], B[N][N], C[N][N]; void *thrfunc(void *arg) int i, j, k, x, y, myid = (int) arg; double sum = 0.0; x = myid / M; y = myid % M; for (i = x*s; i < (x+1)*s; i++) /* υπολογύζει τα ςτοιχεύα του Cxy */ for (j = y*s; j < (y+1)*s; j++) for (k = 0; k < N; k++) sum += A[i][k]*B[k][j]; C[i][j] = sum; ; Δεν υπάρχει ανάγκθ αμοιβαίου αποκλειςμοφ Embarrassingly parallel main() int i; pthread_t tids[nprocs]; for (i = 0; i < NPROCS; i++) pthread_create(&tids[i], NULL, thrfunc, (void *) i); for (i = 0; i < NPROCS; i++) pthread_join(tids[i], NULL); #22

Πίνακασ επί διάνυςμα πιο απλό? float A[N][N], v[n], res[n]; for (i = 0; i < Ν; i++) res[i] = 0.0; for (j = 0; j < Ν; j++) res[i] += Α[i][j]*v[j]; Παραλλθλοποίθςθ του βρόχου i, μοιράηοντασ τισ επαναλιψεισ ςτα νιματα #23

Πίνακασ επί διάνυςμα παράλλθλα (Ι) main() int i; pthread_t tids[nprocs]; for (i = 0; i < NPROCS; i++) pthread_create(&tids[i], NULL, thrfunc, (void *) i); for (i = 0; i < NPROCS; i++) pthread_join(tids[i], NULL); #define N 8000 #define NPROCS 8 #define RPT N/NPROCS /* "Rows Per Thread" */ double A[N][N], v[n], res[n]; void *thrfunc(void *arg) int i, j, myid = (int) arg; Καλόσ κϊδικασ, όταν NPROC < N. Σι γίνεται όταν, όμωσ, ζχουμε NPROC > N? for (i = myid*rpt; i < (myid+1)*rpt; i++) res[i] = 0.0; for (j = 0; j < N; j++) res[i] += A[i][j]*v[j]; Η παραλλθλοποίθςθ του βρόχου, τότε, δεν κα δουλεφει καλά. Θα υπάρχουν διεργαςίεσ που δεν κάνουν τίποτε! παραλλθλοποίθςθ και των δφο βρόχων (i και j) μαηί #24

Πίνακασ επί διάνυςμα παράλλθλα (ΙΙ) #define N 100 #define NPROCS 200 #define RPT N/NPROCS /* "Rows Per Thread" */ double A[N][N], v[n], res[n]; pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER; void *thrfunc(void *arg) int i, j, myid = (int) arg; double sum = 0.0; main() int i; pthread_t tids[nprocs]; for (i = 0; i < N; i++) res[i] = 0.0; for (i = 0; i < NPROCS; i++) pthread_create(&tids[i], NULL, thrfunc, (void *) i); for (i = 0; i < NPROCS; i++) pthread_join(tids[i], NULL); i = myid / 2; /* Γραμμό που αναλαμβϊνω */ myhalf = (N/2)*(myid % 2); /* Οι μιςϋσ επαναλόψεισ του j */ for (j = myhalf; j < myhalf + N/2; j++) sum += A[i][j]*v[j]; pthread_mutex_lock(&lock); res[i] += sum; pthread_mutex_unlock(&lock); Παράλλθλθ αρχικοποίθςθ; Κάκε ηεφγοσ νθμάτων να αρχικοποιεί το δικό του res[i] Π.χ. το ηυγό νιμα (myid%2 == 0) να κάνει res[i] = 0.0. Τπάρχει κάποιο πρόβλθμα; Απαιτείται, πλζον, αμοιβαίοσ αποκλειςμόσ. Προςοχι ςτθν αρχικοποίθςθ του res[]. #25

υγχρονιςμόσ! Οι οντότθτεσ εκτζλεςθσ πρζπει μερικζσ φορζσ να ςυγχρονίηονται. Θα πρζπει να περιμζνουν μζχρι να ςυμβεί κάποιο γεγονόσ υνικθσ μθχανιςμόσ: φράγματα (barriers) κάποιο νιμα που καλεί μία ςυνάρτθςθ φράγματοσ, μπλοκάρει και περιμζνει όλα τα υπόλοιπα νιματα να φτάςουν ςτο φράγμα πριν προχωριςει παρακάτω. Μόλισ φτάςει και το τελευταίο, «ξεμπλοκάρουν» όλα και ςυνεχίηουν τθν εκτζλεςι τουσ. pthread_barrier_wait() Δεν είναι μζροσ του «κλαςικοφ» ςτάνταρ. Αποτελεί επζκταςθ. Για να χρθςιμοποιθκεί ςτα ςυςτιματα που το υποςτθρίηουν, πρζπει ςτον κϊδικα να μπει #define _XOPEN_SOURCE 600 #26

ωςτι παράλλθλθ αρχικοποίθςθ #define N 100 #define NPROCS 200 #define RPT N/NPROCS /* "Rows Per Thread" */ double A[N][N], v[n], res[n]; pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER; pthread_barrier_t *bar; void *thrfunc(void *arg) int i, j, myid = (int) arg; double sum = 0.0; i = myid / 2; /* Γραμμό που αναλαμβϊνω */ myhalf = (N/2)*(myid % 2); /* Οι μιςϋσ επαναλόψεισ του j */ for (j = myhalf; j < myhalf + N/2; j++) sum += A[i][j]*v[j]; if (myid % 2 == 0) res[i] = 0.0; pthread_barrier_wait(bar); Όλα τα νιματα ςτον ίδιο barrier! pthread_mutex_lock(&lock); res[i] += sum; pthread_mutex_unlock(&lock); Άλλθ ιδζα; Σο άρτιο νιμα να δθμιουργεί το περιττό, αμζςωσ μετά τθν αρχικοποίθςθ (άρα => παράλλθλθ δθμιουργία νθμάτων) #27

Μεταβλθτζσ ςυνκικθσ Ο βαςικόσ μθχανιςμόσ ςυγχρονιςμοφ ςτα νιματα Posix. Ζνα νιμα κα περιμζνει ςε μια μεταβλθτι ςυνκικθσ ζωσ ότου θ μεταβλθτι το ενθμερϊςει ότι μπορεί να ςυνεχίςει Κάποιο άλλο νιμα ςθματοδοτεί τθ μεταβλθτι ςυνκικθσ, επιτρζποντασ άλλα νιματα να ςυνεχίςουν Κάκε μεταβλθτι ςυνκικθσ, ωσ διαμοιραηόμενο δεδομζνο, ςυςχετίηεται και με ζνα ςυγκεκριμζνο mutex Με τισ μεταβλθτζσ ςυνκικθσ αποφεφγεται ο ςυνεχισ ζλεγχοσ (busy waiting) τθσ κατάςταςθσ των δεδομζνων Ζνα νιμα που τροποποιεί τθν τιμι των δεδομζνων ειδοποιεί τα ενδιαφερόμενα μζςω μιασ μεταβλθτισ ςυνκικθσ Παράδειγμα: χιμα παραγωγοφ καταναλωτι με χριςθ ουράσ δεδομζνων Σο νιμα-καταναλωτισ εξάγει και επεξεργάηεται ςτοιχεία τθσ oυράσ εφόςον αυτι δεν είναι άδεια, διαφορετικά μπλοκάρει Σο νιματα-παραγωγόσ προςκζτει ςτοιχεία ςτθν ουρά και ειδοποιεί με τθ μεταβλθτι ςυνκικθσ το νιμα καταναλωτι που περιμζνει #28

Χριςθ τατικι αρχικοποίθςθ: pthread_cond_t condition = PTHREAD_COND_INITIALIZER; Δυναμικι αρχικοποίθςθ: pthread_cond_init(&condition); Μια μεταβλθτι ςυνκικθσ ςυςχετίηεται πάντοτε με ζνα mutex Αναμονι με: pthread_cond_wait(&condition, &mutex); Σο νιμα αναςτζλλει τθν εκτζλεςθ του μζχρι να ςθματοδοτθκεί θ μεταβλθτι ςυνκικθσ Σο νιμα πρζπει να ζχει ιδθ κλειδϊςει το ςυςχετιηόμενο mutex Σο νιμα αναςτζλλεται ενϊ το mutex ξεκλειδϊνεται αυτόματα ϊςτε να επιτραπεί θ χριςθ του από άλλα νιματα Όταν το νιμα ενεργοποιθκεί με τθν ειδοποίθςθ του μζςω τθσ μεταβλθτισ ςυνκικθσ, αυτόματα το mutex είναι κλειδωμζνο από το ίδιο #29

θματοδότθςθ pthread_cond_signal(&condition); pthread_cond_broadcast(&condition); Με τθν pthread_cond_signal ζνα νιμα ειδοποιεί κάποιο άλλο νιμα που περιμζνει ςε κάποια μεταβλθτι ςυνκικθσ Με τθν pthread_cond_broadcast, ζνα νιμα ειδοποιεί όλα τα νιματα που περιμζνουν ςε κάποια μεταβλθτι ςυνκικθσ Σο νιμα που πρόκειται να ςθματοδοτιςει μια μεταβλθτι ςυνκικθσ ςυνικωσ ζχει κλειδϊςει το mutex που ςυςχετίηεται με αυτι. τθν περίπτωςθ αυτι πρζπει να ελευκερϊςει το mutex ϊςτε να ςυνεχιςτεί θ εκτζλεςθ τθσ pthread_cond_wait #30

Διαδικαςία Τπάρχει κάποια ςυνκικθ ι κάποιο γεγονόσ που κζλουμε να ελζγξουμε (ζςτω π.χ. εάν count >= N). Απαιτείται μία condition variable (cond) και μια κλειδαριά (mut) Ο ζλεγχοσ του γεγονότοσ γίνεται μόνο αφοφ πρϊτα το νιμα κλειδϊςει το mut. Αν το γεγονόσ/ςυνκικθ ιςχφει (π.χ. count >= N) τότε Σο νιμα ξεκλειδϊνει το mut και υνεχίηει τθν εκτζλεςι του Αν το γεγονόσ/ςυνκικθ δεν ιςχφει τότε Σο νιμα αναςτζλλεται καλϊντασ τθν pthread_cond_wait(&cond,&mut) το mut ξεκλειδϊνεται αυτόματα από το ςφςτθμα Κάποιο άλλο νιμα κα καλζςει τθν pthread_cond_signal(&cond) όταν θ ςυνκικθ γίνει αλθκισ Σο πρϊτο νιμα ξυπνάει από τθν αναμονι ζχοντασ το mutex αυτόματα κλειδωμζνο και εκτελεί τθ δουλειά του Σο νιμα ξεκλειδϊνει το mutex όταν ζχει ολοκλθρϊςει #31

Παραδείγματα #32

Παραδείγματα #33

Ορκόσ τρόποσ χριςθσ /* THREAD A * Wait for the flag to become TRUE */ pthread_mutex_lock(&lock); while (flag == FALSE) pthread_cond_wait(&condvar, &lock); pthread_mutex_unlock(&lock); /* THREAD B */ if (something_happens) pthread_mutex_lock(&lock); flag = TRUE; pthread_cond_signal(&condvar); pthread_mutex_unlock(&lock); Γιατί θ κλειδαριά; Διότι το pthread_cond_signal() είναι memoryless: αν ζνα signal ςταλεί αλλά δεν υπάρχει κάποιο νιμα που κάνει wait(), τότε το ςιμα χάνεται. Αν αμζςωσ μετά το while και πριν προλάβει να κάνει wait(), το νιμα Β κάνει singal(), τότε το ςιμα κα χακεί και το νιμα Α κα περιμζνει για πάντα. Γιατί το while; Διότι μπορεί μετά το flag = TRUE να ξφπνθςε το νιμα Α, αλλά να πρόλαβε ζνα άλλο νιμα να το ζκανε πάλι FALSE. Επίςθσ μπορεί μερικζσ φορζσ κάποιο νιμα να ξυπνιςει από το wait() απρόςμενα, οπότε πριν προχωριςει κα πρζπει να ξαναελζγξει αν όντωσ το flag είναι TRUE. #34

Εργαςία (ςε 1 εβδομάδα) Διάβαςμα και παρουςίαςθ των αλγορίκμων για κλειδαριζσ και barriers από το paper: Algorithms for scalable synchronization on shared-memory multiprocessors, John M. Mellor-Crummey, Michael L. Scott, ACM TOCS (1991) Link: http://www.cs.rice.edu/~johnmc/papers/tocs91.pdf Πιο «μαηεμζνα» (?) για barriers: http://etd.nd.edu/etd-db/theses/available/etd-07122006-010333/unrestricted/sridharans072006.pdf http://archiv.tu-chemnitz.de/pub/2005/0074/data/csr-04-03.pdf 1 διαφάνεια ανά αλγόρικμο (λογικι αλγορίκμου + ςχιμα) 4-5 για locks 4-5 για barrier #35

Δυναμικι ςυμπεριφορά Η μζχρι τϊρα διάςπαςθ ςε «εργαςίεσ» ιταν ςτατικι δθλαδι είχαμε προκακορίςει ακριβώσ τι κα εκτελζςει το κάκε νιμα. π.χ. ςτο π, ι ο διαχωριςμόσ ςκακιζρασ ςτον πολ/μο πινάκων Ωσ γνϊμονα είχαμε τθν ιςοκατανομι φόρτου ϊςτε όλα τα νιματα να εκτελζςουν παρόμοιο ζργο και άρα να δουλζψουν για ίδιο χρονικό διάςτθμα (που είναι το ιδανικό). Σι γίνεται όμωσ αν κάποιοι επεξεργαςτζσ Είναι πιο αργοί από τουσ άλλουσ ι Για το ςυγκεκριμζνο διάςτθμα είναι περιςςότερο φορτωμζνοι από τουσ άλλουσ (διότι π.χ. εκτελοφν και κάποια άλλθ εφαρμογι) ε αυτι τθν περίπτωςθ, θ ιςόποςθ διαμοίραςθ των εργαςιϊν ΔΕΝ ΕΙΝΑΙ ΟΤΙ ΚΑΛΥΤΕΡΟ! #36

Αυτοδρομολόγθςθ (self-scheduling) Εφαρμόηετε ςε αυτζσ τισ περιπτϊςεισ. Δυναμικά (δθλαδι κατά τθν ϊρα τθσ εκτζλεςθσ), τα πιο «αργά» νιματα κα εκτελζςουν λιγότερο ζργο. Πϊσ; Δεν προκακορίηουμε τι κα εκτελζςει το κάκε νιμα Αφινουμε κάκε νιμα να ηθτάει δουλειά να κάνει Όςο πιο γριγορα τελειϊςει μία δουλειά, τόςεσ περιςςότερεσ δουλειζσ κα πάρει να εκτελζςει while (there-are-things-to-do) Work = get-the-next-work() execute(work); #37

Αυτοδρομολόγθςθ κϊδικασ Ζςτω ότι κάπωσ ζχουμε χωρίςει τθ δουλειά ςε NUMWORKS εργαςίεσ, από 0 ζωσ NUMWORKS 1. Ζςτω ότι θ i-οςτι εργαςία εκτελείται ωσ execute(i) #define NUMWORKS 100 int workid; pthread_mutex_t worklock = PTHREAD_MUTEX_INITIALIZER; void *thrfunc(void *arg) int t; while (1) /* Για πϊντα */ pthread_mutex_lock(&worklock); t = workid++; pthread_mutex_unlock(&worklock); if (t >= NUMWORKS) break; execute(t); #38

Αυτοδρομολόγθςθ, ςυνζχεια Για οποιαδιποτε εφαρμογι, ΑΚΡΙΒΩ το ίδιο πρόγραμμα Αρκεί μόνο να κζςουμε το NUMWORKS ςε ςωςτι τιμι και να υλοποιιςουμε τθ κατάλλθλθ execute() Σα ταχφτερα νιματα «κλζβουν» τισ πιο πολλζσ εργαςίεσ και άρα καλφτερθ κατανομι φόρτου τθ γενικότερθ μορφι τθσ, υπάρχει μία ουρά από εργαςίεσ που πρζπει να εκτελεςτοφν. Σα νιματα «τραβοφν» εργαςίεσ από τθν κεφαλι τθσ ουράσ Αν δεν υπάρχει μεγάλθ διαφορά ςτισ ταχφτθτεσ (π.χ. το ςφςτθμα εκτελεί μόνο τθ δικι μασ εφαρμογι), θ αυτοδρομολόγθςθ δεν είναι πάντα ότι καλφτερο μιασ και ζχει ςυναγωνιςμό για τθν κλειδαριά (ι τθν πρόςβαςθ ςτθν ουρά), για κάκε εργαςία. #39

Παράδειγμα: υπολογιςμόσ του π με αυτοδρομο/ςθ int workid; pthread_mutex_t worklock = PTHREAD_MUTEX_INITIALIZER; void *thrfunc(void *arg) int t; while (1) /* Για πϊντα */ pthread_mutex_lock(&worklock); t = workid++; pthread_mutex_unlock(&worklock); if (t >= NUMWORKS) break; execute(t); #define N 10000000 /* Για ακρύβεια (ύδια με ςειριακό) */ #define NUMWORKS 10000 #define WORK N/NUMWORKS /* Πόςεσ επαναλόψεισ η κϊθε εργαςύα */ double pi = 0.0, W = 1.0/N; pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER; void execute(int iter) int i; double mysum = 0.0; for (i = iter*work; i < (iter+1)*work; i++) mysum += 4*W / (1 + (i+0.5)*(i+0.5)*w*w); pthread_mutex_lock(&lock); pi += mysum; pthread_mutex_unlock(&lock); #40

Παράδειγμα: checkerboard + αυτοδρομολόγθςθ int workid; pthread_mutex_t worklock = PTHREAD_MUTEX_INITIALIZER; void *thrfunc(void *arg) int t; while (1) /* Για πϊντα */ pthread_mutex_lock(&worklock); t = workid++; pthread_mutex_unlock(&worklock); if (t >= NUMWORKS) break; execute(t); #define N 10000 /* μϋγεθοσ πύνακα */ #define M 100 /* 100 x 100 υποπύνακεσ */ #define S N/M /* Μϋγεθοσ υποπύνακα */ #define NUMWORKS Μ*Μ /* τόςοι υποπύνακεσ */ void execute(int wid) int i, j, k, x, y; double sum = 0.0; x = wid / M; y = wid % M; for (i = x*s; i < (x+1)*s; i++) /* τα ςτοιχεύα του Cxy */ for (j = y*s; j < (y+1)*s; j++) ; for (k = 0; k < N; k++) sum += A[i][k]*B[k][j]; C[i][j] = sum; #41

διεργασίες στο Unix

Προγραμματιςμόσ με διεργαςίεσ ςτο UNIX Sys-V Shared Memory IPC #include <sys/types.h> #include <sys/ipc.h> #include <sys/shm.h> /* Για shared memory */ #include <sys/sem.h> /* Για semaphores */ Δθμιουργία διεργαςιϊν με fork() (returns 0 to the child). Δεν υπάρχουν κοινζσ μεταβλθτζσ (μόνο κοινόσ χϊροσ ςτθ μνιμθ, δεςμευόμενοσ δυναμικά) Δεν υπάρχουν κλειδαριζσ, μόνο semaphores Δεν υπάρχουν μθχανιςμοί ςυγχρονιςμοφ αλλά μποροφμε να κάνουμε πολλά πράγματα #43

Τλοποίθςθ τθσ join() Αναμονι τερματιςμοφ παιδιϊν με χριςθ τθσ wait(). Η παρακάτω τερματίηει τα παιδιά και κάνει το γονζα να περιμζνει. join(int myid, N) int i; if (myid!= 0) /* Παιδύ */ exit(0); else /* Γονϋασ */ for (i = 0; i < N; i++) wait(0); /* Αναμονό για τερματιςμό Ν παιδιών */ #44

Semaphores semget() για οριςμό semid = semget(ipc_private, 1, 0600 IPC_CREAT); semctl() για αρχικοποίθςθ / καταςτροφι / ζλεγχο semctl(semid, 0, SETVAL, arg); semctl(semid, IPC_RMID, 0); semop() για αφξθςθ / μείωςθ semop(semid, &opr, 1); union semun ; int val; struct semid_ds *buf; ushort_t *array; union semun arg; arg.val = k; /* αρχικοπούηςη */ #45

Κλειδαριζσ από semaphores initlock(int *l) union semun arg; *l = semget(ipc_private, 1, 0600 IPC_CREAT); arg.val = 1; /* Binary semaphore */ semctl(*l, 0, SETVAL, arg); lock(int *l) struct sembuf opr; opr.num = opr.flag = 0; opr.op = -1; /* Μεύωςη κατϊ 1 */ semop(*l, &opr, 1);; unlock(int *l) struct sembuf opr; opr.num = opr.flag = 0; opr.op = 1; /* Αύξηςη κατϊ 1 */ semop(*l, &opr, 1); Καταςτροφό: semctl(*l, IPC_RMID, 0); #46

Κοινζσ «μεταβλθτζσ» int memid = shmget(ipc_private, size, 0600 IPC_CREAT); char *p = shmat(memid, 0, 0); shmctl(memid, ICP_RMID, 0); /* Απελευθϋρωςη μνόμησ */ τα νιματα οι μεταβλθτζσ (κακολικζσ) είναι κοινζσ και δεν χρειάηεται τίποτε, οφτε για τον οριςμό τουσ, οφτε για τον χειριςμό τουσ Με διεργαςίεσ (πολφπλοκοι χειριςμοί με pointers): memid = shmget(ipc_private, 2*sizeof(int), 0600 IPC_CREAT); p = shmat(memid, 0, 0); *((int *) p) = 2; *(((int *) p) + 1) = *((int *) p); #47

.. πιο εφκολοσ χειριςμόσ Σζχναςμα (δομι με τισ κοινζσ μεταβλθτζσ): struct mine int i, j; *myvars; memid = shmget(ipc_private, sizeof(struct mine), 0600 IPC_CREAT); myvars = (struct whatever *) shmat(memid, 0, 0); myvars->i = 2; myvars->j = myvars->i; #48