ΕΚΔΟΣΗ 1.0 ΟΚΤΩΒΡΙΟΣ, 2017 ΕΙΣΑΓΩΓΗ ΣΤΑ ΚΑΤΑΝΕΜΗΜΕΝΑ ΣΥΣΤΗΜΑΤΑ ΕΙΣΑΓΩΓΗ ΣΤO MESSAGE PASSING INTERFACE - MPI ΕΠΙΜΕΛΕΙΑ: Β. ΤΣΑΚΑΝΙΚΑΣ, Β. ΤΑΜΠΑΚΑΣ
CONTENTS ΕΙΣΑΓΩΓΗ ΣΤΑ ΚΑΤΑΝΕΜΗΜΕΝΑ ΣΥΣΤΗΜΑΤΑ... 2 Εισαγωγή... 2 Η Δομή ενός προγράμματος MPI... 2 Βασικές οντότητες στο MPI... 3 Βασικές Συναρτήσεις στο MPI... 4 Επικοινωνία στο MPI... 5 Εργαστηριακή Άσκηση Γνωριμία με το MPI... 7 Βήμα 1: Έλεγχος εάν το MPI είναι ήδη εγκατεστημένο στο pc... 7 Βήμα 2: Δημιουργία του πρώτου προγράμματος MPI... 7 Βήμα 3: Ανασταλτική επικοινωνία... 8 Βήμα 4: Μη Ανασταλτική επικοινωνία... 9 Δραστηριότητες... 10 Βιβλιογραφία... 12 ΟΚΤΩΒΡΙΟΣ, 2017 ΕΙΣΑΓΩΓΗ ΣΤΑ ΚΑΤΑΝΕΜΗΜΕΝΑ ΣΥΣΤΗΜΑΤΑ 1
ΕΙΣΑΓΩΓΗ ΣΤΑ ΚΑΤΑΝΕΜΗΜΕΝΑ ΣΥΣΤΗΜΑΤΑ ΕΙΣΑΓΩΓΗ ΣΤO MESSAGE PASSING INTERFACE - MPI ΕΙΣΑΓΩΓΗ Στόχος της πρώτης εργαστηριακής άσκησης είναι η παρουσίαση του περιβάλλοντος διεπαφής ανταλλαγής μηνυμάτων (Message Passing Interface) MPI, με το οποίο είναι δυνατή η δημιουργία εφαρμογών που στηρίζονται στις αρχές του κατανεμημένου και του παράλληλου προγραμματισμού. Το πρότυπο MPI δεν είναι τίποτε άλλο από μια συλλογή συναρτήσεων που μπορεί να χρησιμοποιηθεί μέσα από προγράμματα που είναι γραμμένα σε γλώσσα C ή σε γλώσσα Fortran και τα οποία επιτρέπουν τη δημιουργία και χρήση ενός πλήθους διεργασιών που εκτελούνται παράλληλα στον ίδιο ή σε διαφορετικούς υπολογιστές και επικοινωνούν μεταξύ τους χρησιμοποιώντας το μοντέλο ανταλλαγής μηνυμάτων. Σε αντίθεση με το σειριακό μοντέλο προγραμματισμού στο οποίο λαμβάνει χώρα η χρήση ενός και μοναδικού επεξεργαστή που επικοινωνεί συνεχώς με την κεντρική μνήμη του συστήματος δια μέσου διαδικασιών ανάγνωσης και εγγραφής, στο αντίστοιχο κατανεμημένο / παράλληλο μοντέλο υπονοείται η χρήση πολλών διαφορετικών επεξεργαστών κάθε ένας εκ των οποίων χρησιμοποιεί τη δική του περιοχή μνήμης και τις δικές του μεταβλητές προγράμματος. Αυτό σημαίνει πως οι εν λόγω επεξεργαστές δεν μοιράζονται κάποιο κοινό φυσικό χώρο διευθύνσεων μνήμης, και επομένως οι ενέργειες μιας διεργασίας που εκτελείται σε ένα υπολογιστή, δεν είναι ορατές από τις υπόλοιπες διεργασίες του SGI MPI Digital MPI Intel MPI SUN MPI MPICH MPI HP MPI LAM CHIMP IBM MPI Το MPI είναι ένα σύνολο προδιαγραφών για προγραμματιστές και χρήστες βιβλιοθηκών μεταβίβασης μηνυμάτων. Δεν είναι βιβλιοθήκη καθ' αυτή αλλά περιγράφει τις προδιαγραφές τις οποίες πρέπει να πληροί μια βιβλιοθήκη. συστήματος. Εάν δε, κάποια διεργασία απαιτεί τη χρήση μιας μεταβλητής η οποία ανήκει στο χώρο κάποιας άλλης διεργασίας, η μεταβλητή αυτή δεν είναι κοινή στις δύο διεργασίες, αλλά θα πρέπει να αποσταλεί από τη μια διεργασία στην άλλη δια μέσου κάποιου μηνύματος (message). Ο βαθμός ολοκλήρωσης του MPI έχει οδηγήσει πολλές εταιρείες να δημιουργήσουν την δική τους έκδοση (υλοποίηση) της αρχιτεκτονικής του MPI, όπως φαίνεται στο διπλανό σχήμα. Η ΔΟΜΗ ΕΝΟΣ ΠΡΟΓΡΑΜΜΑΤΟΣ MPI Η γενική δομής ενός προγράμματος MPI παρουσιάζετε στο σχήμα Χ παρακάτω. Πιο συγκεκριμένα, μπορούμε να δούμε πως ένα πρόγραμμα γραμμένο σε MPI ΟΚΤΩΒΡΙΟΣ, 2017 ΕΙΣΑΓΩΓΗ ΣΤΑ ΚΑΤΑΝΕΜΗΜΕΝΑ ΣΥΣΤΗΜΑΤΑ 2
περιλαμβάνει δύο κύρια μέρη. Το 1 ο μέρος είναι το «σειριακό» και εκτελείται μόνο σε έναν επεξεργαστή, ενώ το 2 ο μέρος είναι το παράλληλο και εκτελείται σε κάθε κόμβο ξεχωριστά. Serial part Parallel part Serial part Σχήμα Χ: Η γενική δομή ενός προγράμματος MPI ΒΑΣΙΚΕΣ ΟΝΤΟΤΗΤΕΣ ΣΤΟ MPI Διεργασία Η στοιχειώδης μονάδα μιας εφαρμογής MPI είναι η διεργασία (process) η οποία δημιουργείται και εκτελείται ανεξάρτητα από τις υπόλοιπες διεργασίες του συστήματος χρησιμοποιώντας τους δικούς της πόρους (resources). Η κάθε διεργασία ταυτοποιείται με μοναδικό τρόπο από ένα κωδικό διεργασίας (Process Id, PID) που στην ορολογία του προτύπου ονομάζεται τάξη (rank) και λαμβάνει τιμές μεγαλύτερες ή ίσες με το μηδέν. Εάν το πλήθος των διεργασιών που εκτελούνται στο σύστημα είναι γνωστό και ίσο με Ν, τότε οι κωδικοί αυτών των διεργασιών θα έχουν τις Ν συνεχόμενες τιμές 0,1,2,3,.,Ν-1. Επειδή οι τάξεις των διεργασιών προσδιορίζουν τις διεργασίες του συστήματος με ΟΚΤΩΒΡΙΟΣ, 2017 ΕΙΣΑΓΩΓΗ ΣΤΑ ΚΑΤΑΝΕΜΗΜΕΝΑ ΣΥΣΤΗΜΑΤΑ 3
μοναδικό τρόπο, χρησιμοποιούνται πάρα πολύ συχνά από τους προγραμματιστές των εφαρμογών MPI για να προσδιορίσουν την προέλευση και τον προορισμό των διακινούμενων μηνυμάτων. Ομάδες Διεργασιών Το MPI χρησιμοποιεί αντικείμενα τα οποία ονομάζονται communicators και groups για να ορίσει ποιο σύνολο διεργασιών μπορεί να επικοινωνήσει μεταξύ τους. Οι περισσότερες ρουτίντες του MPI απαιτούν να ορίσει ο χρήστης έναν communicator σαν παράμετρο. Οι communicators και τα groups καλύπτονται αργότερα με περισσότερες λεπτομέρειες. Προς το παρόν, απλά χρησιμοποιούμε την εντολή MPI_COMM_WORLD όταν χρειάζεται ένας communicator - είναι ο προκαθορισμένος communicator που περιλαμβάνει όλες τις λειτουργίες του MPI. Rank Μέσα σε έναν communicator, κάθε διεργασία έχει ένα μοναδικό ακέραιο αναγνωριστικό που της έχει ανατεθεί από το σύστημα όταν γίνεται η αρχικοποίηση. Επίσης ονομάζεται και "task ID". Τα Ranks είναι συνεχόμενα και ξεκινούν από το μηδέν. Χρησιμοποιείται από τον προγραμματιστή για να προσδιορίζει την προέλευση και τον προορισμό του μηνύματος. Συχνά χρησιμοποιείται σε δομές ελέγχου για τον έλεγχο της εκτέλεσης του προγράμματος (if rank=0 do this / if rank=1 do that). ΒΑΣΙΚΕΣ ΣΥΝΑΡΤΗΣΕΙΣ ΣΤΟ MPI Στον πίνακα Χ εμφανίζονται οι βασικές συναρτήσεις του MPI. Πίνακας Χ: Οι βασικές συναρτήσεις του MPI Συνάρτηση Χρήση Κλήση MPI_Init MPI_Comm_size MPI_Comm_rank MPI_Abort Αρχικοποιεί το περιβάλλον εκτέλεσης του MPI. Αυτή η συνάρτηση πρέπει να κληθεί σε κάθε πρόγραμμα MPI, πριν από οποιαδήποτε άλλη συνάρτηση και μόνο μία φορά. Προσδιορίζει τον αριθμό των διεργασιών στο group το οποίο σχετίζεται με έναν communicator. Γενικά χρησιμοποιείται μέσα στον communicator MPI_COMM_WORLD για τον προσδιορισμό του αριθμού των διεργασιών που χρησιμοποιούνται από την εφαρμογή. Προσδιορίζει το αναγνωριστικό της καλούμενης διεργασίας μέσα στον communicator. Αρχικά, κάθε διεργασία θα αποκτήσει έναν μοναδικό αριθμό από το 0 μέχρι το "πλήθος των διεργασιών-1" μέσα στον communicator MPI_COMM_WORLD. Αυτή η θέση συχνά χρησιμοποιείται και ως task ID. Τερματίζει όλες τις διεργασίες του MPI που σχετίζονται με τον communicator. MPI_Init (&argc,&argv) MPI_Comm_size (comm,&size) MPI_Comm_rank (comm,&rank) MPI_Abort (comm,errorcode) ΟΚΤΩΒΡΙΟΣ, 2017 ΕΙΣΑΓΩΓΗ ΣΤΑ ΚΑΤΑΝΕΜΗΜΕΝΑ ΣΥΣΤΗΜΑΤΑ 4
MPI_Get_process or_name MPI_Initialized Επιστρέφει το όνομα της διεργασίας. Επίσης επιστρέφει το μήκος του ονόματος. Ο buffer του ονόματος πρέπει να είναι τουλάχιστον MPI_MAX_PROCESSOR_NAME χαρακτήρες σε μέγεθος. Δείχνει αν η έχει κληθεί η MPI_Init - επιστρέφει λογικό true (1) ή false (0). MPI_Wtime Επιστρέφει τον χρόνο που έχει περάσει σε δευτερόλεπτα (διπλής ακρίβειας) στην διεργασία που το καλεί. MPI_Wtick MPI_Finalize Επιστρέφει την ανάλυση της ώρας σε δευτερόλεπτα από το MPI_Wtime. Τερματίζει το περιβάλλον εκτέλεσης του MPI. Αυτή η συνάρτηση πρέπει να είναι η τελευταία από τις ρουτίνες που θα κληθούν σε κάθε πρόγραμμα MPI - δεν πρέπει να κληθούν άλλες ρουτίνες μετά από αυτή. MPI_Get_processo r_name (&name,&resultlen gth) MPI_Initialized (&flag) MPI_Wtime () MPI_Wtick () MPI_Finalize () ΕΠΙΚΟΙΝΩΝΙΑ ΣΤΟ MPI Ο βασικός μηχανισμός επικοινωνίας του MPI είναι η μετάδοση δεδομένων μεταξύ ενός ζεύγους διεργασιών, εκ των οποίων η πρώτη αποστέλλει το μήνυμα ενώ η δεύτερη το παραλαμβάνει. Αυτός ο τρόπος επικοινωνίας ονομάζεται επικοινωνία από σημείο σε σημείο (point to point communication) και αποτελεί το μοντέλο επικοινωνίας για ένα πολύ μεγάλο εύρος εφαρμογών MPI. Point to point communication Το MPI προσφέρει ένα σύνολο συναρτήσεων που χρησιμοποιείται για την αποστολή και λήψη δεδομένων με τη μορφή μηνυμάτων. Το κάθε ένα από αυτά τα μηνύματα χαρακτηρίζεται από μια τυποποίηση συγκεκριμένης μορφής και ταυτοποιείται μονοσήμαντα από μία ετικέτα (tag) που μας επιτρέπει να το ξεχωρίσουμε από τα υπόλοιπα μηνύματα της εφαρμογής. Αυτή η τυποποίηση είναι εξαιρετικά σημαντική και είναι ιδιαίτερα χρήσιμη σε περιπτώσεις επικοινωνίας διεργασιών που ανήκουν σε ετερογενή συστήματα (δηλαδή σε συστήματα που χαρακτηρίζονται από διαφορετική αρχιτεκτονική) και η οποία απαιτεί την ενδιάμεση μετατροπή των διακινούμενων δεδομένων. Από την άλλη μεριά η χρήση της ετικέτας προσφέρει και αυτή αρκετά πλεονεκτήματα, όπως είναι για παράδειγμα η δυνατότητα της σωστής ταξινόμησης μιας ομάδας μηνυμάτων που παραλαμβάνονται με σειρά διαφορετική από εκείνη με την οποία έχουν σταλεί. Σε πλήρη αναλογία με τα πακέτα δεδομένων που διακινούνται σε ένα δίκτυο υπολογιστών, ένα μήνυμα του προτύπου MPI δεν περιέχει μόνο τα δεδομένα προς αποστολή, αλλά και πολλές άλλες πληροφορίες οι οποίες είναι αναγκαίες για την επιτυχή μετάδοση του μηνύματος. Οι πληροφορίες αυτές περιλαμβάνουν μεταξύ των άλλων το πλήθος και τον τύπο των δεδομένων που περιλαμβάνονται στο μήνυμα, τις τάξεις των διεργασιών αποστολής και λήψης, την ετικέτα του μηνύματος και το όνομα του πληροφοριοδότη δια της χρήσεως του οποίου επικοινωνούν οι δύο διεργασίες. Οι παραπάνω πληροφορίες διαβιβάζονται ως ορίσματα στη συνάρτηση που ΟΚΤΩΒΡΙΟΣ, 2017 ΕΙΣΑΓΩΓΗ ΣΤΑ ΚΑΤΑΝΕΜΗΜΕΝΑ ΣΥΣΤΗΜΑΤΑ 5
Blocking & non-blocking communication ΕΙΣΑΓΩΓΗ ΣΤO MESSAGE PASSING INTERFACE - MPI χρησιμοποιείται για την αποστολή του μηνύματος, ενώ εντελώς ανάλογη είναι και η κλήση της συνάρτησης παραλαβής του μηνύματος, η οποία ωστόσο περιέχει και ένα επιπλέον όρισμα που περιλαμβάνει πληροφορίες σχετικές με τη διαδικασία παραλαβής. Χρησιμοποιώντας αυτές τις δύο συναρτήσεις (καθώς και ορισμένες άλλες που χρησιμοποιούνται για την αρχικοποίηση και τον τερματισμό του προτύπου), μπορούμε να κατασκευάσουμε όλες σχεδόν τις εφαρμογές που χαρακτηρίζονται από αυτή τη διαδικασία ανταλλαγής μηνυμάτων. Collective communication Το δεύτερο είδος επικοινωνίας που υποστηρίζει το πρωτόκολλο MPI, είναι οι συλλογικές επικοινωνίες (collective communications) οι οποίες χαρακτηρίζονται από την ύπαρξη περισσότερων από δύο διαδικασιών. Οι πιο σημαντικές από αυτές τις μορφές επικοινωνίας, είναι η εκπομπή (broadcasting), όπου ένα μήνυμα αποστέλλεται ενιαίο σε όλες τις διεργασίες, η διασπορά (scattering) όπου ένα μήνυμα διασπάται σε μικρότερα κομμάτια κάθε ένα εκ των οποίων αποστέλλεται και σε μια διαφορετική διεργασία, η συλλογή (gather) όπου το σύνολο των μηνυμάτων που αποστέλλονται από όλα τα μέλη μιας ομάδας διεργασιών παραλαμβάνεται από μια απλή διεργασία, και η μείωση (reduce) όπου μια διεργασία συλλέγει δεδομένα από τις υπόλοιπες διεργασίες της ομάδας, και ταυτόχρονα υπολογίζει κάποια συνάρτηση αυτών των δεδομένων (για παράδειγμα το μέσο όρο τους). Σε όλες τις παραπάνω διεργασίες, υπάρχει μια κεντρική διεργασία η οποία είτε αποστέλλει τις πληροφορίες στις υπόλοιπες διεργασίας της ομάδας, είτε συλλέγει τα μηνύματα που αποστέλλονται από αυτές. Στην περίπτωση των διεργασιών από σημείο σε σημείο, οι συναρτήσεις του MPI εμφανίζονται σε δύο διαφορετικές μορφές που φέρουν τα ονόματα παρεμποδιστικές (blocking) και μη παρεμποδιστικές (non blocking) συναρτήσεις. Μια συνάρτηση λέγεται παρεμποδιστική όταν η κλήση της μέσα από κάποια διεργασία αναστέλλει τη λειτουργία αυτής της διεργασίας, μέχρι την ολοκλήρωση της λειτουργίας της συνάρτησης που έχει κληθεί. Στην αντίθετη περίπτωση, κατά την οποία η κλήση της συνάρτησης δεν προκαλεί την αναστολή της λειτουργίας της διεργασίας, η εν λόγω συνάρτηση λέγεται μη παρεμποδιστική. Εντελώς ανάλογη με την προηγούμενη κατάσταση, είναι και αυτή που συσχετίζεται με τον τρόπο λειτουργίας της διεργασίας παραλήπτη. Εάν η εν λόγω διεργασία χρησιμοποιεί την παρεμποδιστική έκδοση της receive η οποία νοείται ως η συνάρτηση που διαβάζει το περιεχόμενο του μηνύματος που έχει σταλεί τότε η λειτουργία της διεργασίας παραλήπτη θα ανασταλεί κατά το χρονικό διάστημα ανάγνωσης της πληροφορίας. Όταν η διακινούμενη πληροφορία έχει παραληφθεί στο σύνολό της από τη διεργασία παραλήπτη, η συνάρτηση receive θα αναστείλει τη λειτουργία της κάτι που θα επιτρέψει τη συνέχιση και τελικά την ολοκλήρωση της λειτουργίας της διεργασίας παραλήπτη. Στην περίπτωση κατά την οποία χρησιμοποιούνται οι μη παρεμποδιστικές εκδόσεις των συναρτήσεων αποστολής και παραλαβής μηνυμάτων, η κατάσταση είναι εντελώς διαφορετική. Στην περίπτωση αυτή η κλήση της μη παρεμποδιστικής έκδοσης της send, δεν αναστέλλει τη λειτουργία της διεργασίας αποστολέα, η οποία συνεχίζεται κανονικά και εκτελείται παράλληλα με την αποστολή του μηνύματος. ΟΚΤΩΒΡΙΟΣ, 2017 ΕΙΣΑΓΩΓΗ ΣΤΑ ΚΑΤΑΝΕΜΗΜΕΝΑ ΣΥΣΤΗΜΑΤΑ 6
ΕΡΓΑΣΤΗΡΙΑΚΗ ΆΣΚΗΣΗ ΓΝΩΡΙΜΙΑ ΜΕ ΤΟ MPI Σε αυτό το τμήμα της εργαστηριακής άσκησης θα δοκιμάσουμε να εκτελέσουμε κάποια προγράμματα σε MPI και να κατανοήσουμε πλήρως την λειτουργία τους. Κατά την διάρκεια εκτέλεσης του εργαστηριακού οδηγού θα πρέπει να συμπληρώνετε παράλληλα και την εργαστηριακή σας αναφορά, πρότυπο της οποίας μπορείτε να βρείτε στο openclass του μαθήματος. Η εργαστηριακή αναφορά θα πρέπει να έχει παραδοθεί την ημέρα πριν το επόμενο εργαστήριο, σύμφωνα με τις οδηγίες. Βήμα 1: Έλεγχος εάν το MPI είναι ήδη εγκατεστημένο στο pc Στο πρώτο βήμα της εργαστηριακής άσκησης θα εξετάσουμε εάν το MPI έχει εγκατασταθεί στο PC στο οποίο εργαζόμαστε. Για αυτό το λόγο: 1. Συνδεθείτε σε ένα λειτουργικό Linux (Ubuntu ή LUbuntu). 2. Ανοίξτε ένα terminal 3. Εκτελέστε την εντολή: mpiexec --version 4. Είναι το αποτέλεσμα που λαμβάνετε ίδιο (ή παρόμοιο) με το παρακάτω; Σχήμα Χ: Έξοδος της mpiexec 5. Αντιγράψτε την έξοδο της εντολής στην εργαστηριακή αναφορά. Βήμα 2: Δημιουργία του πρώτου προγράμματος MPI Σε αυτό το βήμα θα δημιουργήσουμε το πρώτο μας πρόγραμμα σε MPI. 1. Ανοίξτε ένα terminal 2. Δημιουργήστε έναν φάκελο MPI_ABCD, όπου ABCD το μητρώο σας. Για να το πετύχετε αυτό, εκτελέστε την εντολή mkdir MPI_ABCD. Στην συνέχεια μπείτε στον φάκελο εκτελώντας την εντολή cd MPI_ABCD. 3. Δημιουργήστε το αρχείο hello_mpi.c εκτελώντας την εντολή gedit hello_mpi.c 4. Αντιγράψτε το παρακάτω πρόγραμμα στο αρχείο σας #include "mpi.h" #include <stdio.h> int main( argc, argv ) int argc; char *argv[]; { int rank, size; MPI_Init( &argc, &argv ); MPI_Comm_rank( MPI_COMM_WORLD, &rank ); MPI_Comm_size( MPI_COMM_WORLD, &size ); printf( "I am %d of %d\n", rank, size ); MPI_Finalize(); return 0; ΟΚΤΩΒΡΙΟΣ, 2017 ΕΙΣΑΓΩΓΗ ΣΤΑ ΚΑΤΑΝΕΜΗΜΕΝΑ ΣΥΣΤΗΜΑΤΑ 7
5. Αφού αποθηκεύσετε και κλείσετε το αρχείο, μεταγλωττίστε το εκτελώντας την εντολή mpicc hello_mpi.c o hello_mpi 6. Εάν δεν έγινε κάποιο λάθος, ο μεταγλωττιστής δεν θα πρέπει να βγάλει κανένα μήνυμα. Τότε, μπορείτε να εκτελέσετε το πρόγραμμα, τρέχοντας την εντολή mpirun np 10./hello_mpi. Σε αυτή την εντολή, η παράμετρος np καθορίζει το πλήθος των διεργασιών που θα δημιουργηθούν στον «κόσμο» μας. 7. Αντιγράψτε την έξοδο του προγράμματος στην εργαστηριακή αναφορά σας. Βήμα 3: Ανασταλτική επικοινωνία Σε αυτό το βήμα θα δημιουργήσουμε ένα πρόγραμμα σε MPI, στο οποίο δύο διεργασίες θα επικοινωνούν μεταξύ τους. 1. Ανοίξτε ένα terminal 2. Μπείτε στον φάκελο MPI_ABCD. 3. Δημιουργήστε το αρχείο send_receive.c εκτελώντας την εντολή gedit send_receive.c 4. Αντιγράψτε το παρακάτω πρόγραμμα στο αρχείο σας #include "mpi.h" #include <stdio.h> int main( int argc, char *argv[] ) { int rank, size, retval; MPI_Status status; char inmessage, outmessage1='a', outmessage2='b'; retval=mpi_init( &argc, &argv ); if (retval!=mpi_success) { printf("error starting MPI.\n"); MPI_Abort(MPI_COMM_WORLD,retVal); MPI_Comm_rank( MPI_COMM_WORLD, &rank ); MPI_Comm_size( MPI_COMM_WORLD, &size ); if(rank==0) { MPI_Send(&outMessage1,1,MPI_CHAR,1,0,MPI_COMM_WORLD); MPI_Recv(&inMessage,1,MPI_CHAR,1,0,MPI_COMM_WORLD, &status); printf("process %02d send %c and received %c\n", rank, outmessage1, inmessage); if(rank==1) { MPI_Recv(&inMessage,1,MPI_CHAR,0,0,MPI_COMM_WORLD, &status); MPI_Send(&outMessage2,1,MPI_CHAR,0,0,MPI_COMM_WORLD); printf("process %02d send %c and received %c\n", rank, outmessage2, inmessage) MPI_Finalize(); return 0; 5. Προσπαθήστε να προβλέψετε την έξοδο του προγράμματος 6. Αφού αποθηκεύσετε και κλείσετε το αρχείο, μεταγλωττίστε το εκτελώντας την εντολή mpicc send_receive.c o send_receive 7. Εάν δεν έγινε κάποιο λάθος, ο μεταγλωττιστής δεν θα πρέπει να βγάλει κανένα μήνυμα. Τότε, μπορείτε να εκτελέσετε το πρόγραμμα, τρέχοντας την εντολή mpirun np 2./send_receive 8. Αντιγράψτε την έξοδο του προγράμματος στην εργαστηριακή αναφορά σας. ΟΚΤΩΒΡΙΟΣ, 2017 ΕΙΣΑΓΩΓΗ ΣΤΑ ΚΑΤΑΝΕΜΗΜΕΝΑ ΣΥΣΤΗΜΑΤΑ 8
Βήμα 4: Μη Ανασταλτική επικοινωνία Σε αυτό το βήμα θα δημιουργήσουμε ένα πρόγραμμα σε MPI, στο οποίο δύο διεργασίες θα επικοινωνούν μεταξύ τους. 1. Ανοίξτε ένα terminal 2. Μπείτε στον φάκελο MPI_ABCD. 3. Δημιουργήστε το αρχείο send_receive.c εκτελώντας την εντολή gedit Ιsend_Ιreceive.c 4. Αντιγράψτε το παρακάτω πρόγραμμα στο αρχείο σας #include <stdio.h> #include <stdlib.h> #include <mpi.h> #include <math.h> int main(argc,argv) int argc; char *argv[]; { int myid, numprocs; int tag,source,destination,count; int buffer; MPI_Status status; MPI_Request request; MPI_Init(&argc,&argv); MPI_Comm_size(MPI_COMM_WORLD,&numprocs); MPI_Comm_rank(MPI_COMM_WORLD,&myid); tag=1234; source=0; destination=1; count=1; request=mpi_request_null; if(myid == source){ buffer=2017; MPI_Isend(&buffer,count,MPI_INT,destination,tag,MPI_COMM_WORLD,&request); if(myid == destination){ MPI_Irecv(&buffer,count,MPI_INT,source,tag,MPI_COMM_WORLD,&request); MPI_Wait(&request,&status); if(myid == source){ printf("processor %d sent %d\n",myid,buffer); if(myid == destination){ printf("processor %d got %d\n",myid,buffer); MPI_Finalize(); 5. Προσπαθήστε να προβλέψετε την έξοδο του προγράμματος 6. Αφού αποθηκεύσετε και κλείσετε το αρχείο, μεταγλωττίστε το εκτελώντας την εντολή mpicc Ιsend_Ιreceive.c o Ιsend_Ιreceive 7. Εάν δεν έγινε κάποιο λάθος, ο μεταγλωττιστής δεν θα πρέπει να βγάλει κανένα μήνυμα. Τότε, μπορείτε να εκτελέσετε το πρόγραμμα, τρέχοντας την εντολή mpirun np 2./Ιsend_Ιreceive 8. Αντιγράψτε την έξοδο του προγράμματος στην εργαστηριακή αναφορά σας. ΟΚΤΩΒΡΙΟΣ, 2017 ΕΙΣΑΓΩΓΗ ΣΤΑ ΚΑΤΑΝΕΜΗΜΕΝΑ ΣΥΣΤΗΜΑΤΑ 9
ΔΡΑΣΤΗΡΙΟΤΗΤΕΣ Προσπαθήστε να λύσετε τις παρακάτω δραστηριότητες. Οι απαντήσεις κάθε δραστηριότητας θα πρέπει να εμφανίζονται στην εργαστηριακή σας αναφορά. 1. Μετατρέψτε το παράδειγμα του βήματος 3, έτσι ώστε: a. ο κόμβος 0 να στέλνει έναν ακέραιο c (όποιον εσείς επιθυμείτε) στον κόμβο 1 b. ο κόμβος 1 να ελέγχει εάν ο c είναι άρτιος ή περιττός. Εάν είναι άρτιος, να στέλνει στον 0 τον χαρακτήρα Ε, ενώ σε διαφορετική περίπτωση τον χαρακτήρα O. c. ο κόμβος 0 να εκτυπώνει τον χαρακτήρα που έλαβε 2. Το παρακάτω πρόγραμμα υλοποιεί σε MPI μία τοπολογία δακτυλίου, όπου ο κάθε κόμβος στέλνει μήνυμα στον διπλανό του, όταν λάβει το token. Ο πρώτος κόμβος που ξεκινάει την διαδικασία είναι ο starter, και όταν το token επιστρέψει σε αυτόν, το πρόγραμμα τερματίζει. #include <mpi.h> #include <stdio.h> #include <stdlib.h> int main(int argc, char** argv) { int starter = 11;//Edo dilwnoyme poios komvos theloume na einai arxikopoihtis //Fysika tha prepei na einai mikrotero apo to world_size! MPI_Init(NULL, NULL); //Arxikopoioume to MPI int world_rank; MPI_Comm_rank(MPI_COMM_WORLD, &world_rank); int world_size; MPI_Comm_size(MPI_COMM_WORLD, &world_size); int token = 0; //token = 0/1 simainei pws o komvos den exei/exei to token int previous = world_rank - 1; // o proigoumenos komvos int next = world_rank + 1; // o epomenos komvos if (previous == -1) previous = world_size - 1; if (next >= world_size) next = 0; if (world_rank == starter) { token = 1; MPI_Send(&token, 1, MPI_INT, next, 0, MPI_COMM_WORLD); MPI_Recv(&token, 1, MPI_INT, previous, 0, MPI_COMM_WORLD, MPI_STATUS_IGNORE); printf("starter process %d received token %d from process %d\n", world_rank, token, previous); printf("bye BYE\n\n"); if (world_rank!= starter) { MPI_Recv(&token, 1, MPI_INT, previous, 0, MPI_COMM_WORLD, MPI_STATUS_IGNORE); printf("process %d received token %d from process %d\n", world_rank, token, previous); MPI_Send(&token, 1, MPI_INT, next, 0, MPI_COMM_WORLD); token = 0; MPI_Finalize(); ΟΚΤΩΒΡΙΟΣ, 2017 ΕΙΣΑΓΩΓΗ ΣΤΑ ΚΑΤΑΝΕΜΗΜΕΝΑ ΣΥΣΤΗΜΑΤΑ 10
Καλείστε να συμπληρώστε τα κενά, έτσι ώστε υλοποιείτε η τοπολογία δακτυλίου και να έχετε την παρακάτω έξοδο: vasilis@ubuntu:~/mpi_examples$ mpirun -np 30./exer3a Process 12 received token 1 from process 11 Process 13 received token 1 from process 12 Process 14 received token 1 from process 13 Process 15 received token 1 from process 14 Process 16 received token 1 from process 15 Process 17 received token 1 from process 16 Process 18 received token 1 from process 17 Process 19 received token 1 from process 18 Process 20 received token 1 from process 19 Process 21 received token 1 from process 20 Process 22 received token 1 from process 21 Process 23 received token 1 from process 22 Process 24 received token 1 from process 23 Process 25 received token 1 from process 24 Process 26 received token 1 from process 25 Process 27 received token 1 from process 26 Process 28 received token 1 from process 27 Process 29 received token 1 from process 28 Process 0 received token 1 from process 29 Process 1 received token 1 from process 0 Process 2 received token 1 from process 1 Process 3 received token 1 from process 2 Process 4 received token 1 from process 3 Process 5 received token 1 from process 4 Process 6 received token 1 from process 5 Process 7 received token 1 from process 6 Process 8 received token 1 from process 7 Process 9 received token 1 from process 8 Process 10 received token 1 from process 9 Starter process 11 received token 1 from process 10 BYE BYE 3. Τροποποιείστε τον κώδικα της δραστηριότητας 2, ώστε να υπολογίζει το μέγεθος Ν του δακτυλίου. 4. Γράψτε ένα πρόγραμμα το οποίο θα δημιουργεί έναν κόσμο MPI, μόνο όταν το πλήθος των κόμβων Ν είναι άρτιος αριθμός. Σε αυτή την περίπτωση, τα Ν/2 ζευγάρια (k, N/2+k), με k < N/2 θα ανταλλάζουν έναν ακέραιο (π.χ. το rank τους) κάνοντας χρήση των μη ανασταλτικών συναρτήσεων επικοινωνίας Isend, Ireceive. 5. Τροποποιείστε τον κώδικα της δραστηριότητας 2, έτσι ώστε το token να κάνει 2 κύκλους στον δακτύλιο πριν τερματίσει το πρόγραμμα. 6. Τροποποιείστε τον κώδικα της δραστηριότητας 2, έτσι ώστε το token να ταξιδεύει «αντιωρολογιακά», δηλαδή 11, 10, 9,., 1, 0, 29, 28,., 12, 11. 7. Γράψτε ένα πρόγραμμα σε MPI, στο οποίο όλοι οι κόμβοι (εκτός του 0) θα επιλέγουν έναν τυχαίο αριθμό g στο διάστημα 1-100, και θα τον αποστέλλουν στον κόμβο 0. Ο κόμβος 0 θα αθροίζει όλα τα g και θα εκτυπώνει το αποτέλεσμα στην οθόνη. Για τον σκοπό αυτό θα χρειαστεί να βρείτε πληροφορίες για τις συναρτήσεις τις srand() και rand(). ΟΚΤΩΒΡΙΟΣ, 2017 ΕΙΣΑΓΩΓΗ ΣΤΑ ΚΑΤΑΝΕΜΗΜΕΝΑ ΣΥΣΤΗΜΑΤΑ 11
ΒΙΒΛΙΟΓΡΑΦΙΑ "MPI: The Complete Reference" by Snir, Otto, Huss-Lederman, Walker, and Dongarra, MIT Press (also in Postscript and html) "Using MPI: Portable Parallel Programming with the Message-Passing Interface, " by Gropp, Lusk and Skjellum, MIT Press Designing and Building Parallel Programs, by Ian Foster, Addison-Wesley, 1995. Parallel Programming with MPI, by Peter Pacheco, Morgan-Kaufmann, 1997. MPI θεωρία και Εφαρμογές, A. Μάργαρης, Εκδόσεις Τζιόλα, 2008. Homepage: http:// www.mcs.anl.gov/mpi ΟΚΤΩΒΡΙΟΣ, 2017 ΕΙΣΑΓΩΓΗ ΣΤΑ ΚΑΤΑΝΕΜΗΜΕΝΑ ΣΥΣΤΗΜΑΤΑ 12