ΕΚΔΟΣΗ 1.0 ΟΚΤΩΒΡΙΟΣ, 2017 ΕΙΣΑΓΩΓΗ ΣΤΑ ΚΑΤΑΝΕΜΗΜΕΝΑ ΣΥΣΤΗΜΑΤΑ ΤΟ ΠΡΩΤΟΚΟΛΛΟ TARRY ΕΠΙΜΕΛΕΙΑ: Β. ΤΣΑΚΑΝΙΚΑΣ, Β. ΤΑΜΠΑΚΑΣ
CONTENTS ΕΙΣΑΓΩΓΗ ΣΤΑ ΚΑΤΑΝΕΜΗΜΕΝΑ ΣΥΣΤΗΜΑΤΑ... 2 Το πρωτόκολλο TARRY... 2 Εισαγωγή... 2 Το πρωτόκολλο TARRY... 2 Περιγραφή Πρωτοκόλλου... 3 Εργαστηριακή Άσκηση Το πρωτόκολλο TARRY... 5 Βήμα 1: ΤΟ ΠΡΩΤΟΚΟΛΛΟ TARRY... 5 Δραστηριότητες... 9 Βιβλιογραφία... 10 ΟΚΤΩΒΡΙΟΣ, 2017 ΕΙΣΑΓΩΓΗ ΣΤΑ ΚΑΤΑΝΕΜΗΜΕΝΑ ΣΥΣΤΗΜΑΤΑ 1
ΕΙΣΑΓΩΓΗ ΣΤΑ ΚΑΤΑΝΕΜΗΜΕΝΑ ΣΥΣΤΗΜΑΤΑ ΤΟ ΠΡΩΤΟΚΟΛΛΟ TARRY ΕΙΣΑΓΩΓΗ Τα πρωτόκολλα της οικογένειας του TARRY μπορούν να χρησιμοποιηθούν για να μεταδώσουν αποδοτικά πληροφορία σε ένα δίκτυο, ενώ ταυτόχρονα μπορούν να μας επιτρέψουν ένα δένδρο σύνδεσης μεταξύ των κόμβων. Ανήκει φυσικά στην οικογένεια των πρωτοκόλλων διάσχισης. Τα πρωτόκολλα διάσχισης έχουν τις παρακάτω ιδιότητες: 1. Υπάρχει ένας μόνο αρχικοποιητής που αρχίζει τον υπολογισμό στέλνοντας ακριβώς ένα μήνυμα. 2. Μια διεργασία όταν λάβει ένα μήνυμα είτε στέλνει ένα μήνυμα είτε εκτελεί ένα τοπικό κώδικα (decide) που εξαρτάται από τον γενικότερο αλγόριθμο. 3. Ο αλγόριθμος τερματίζει στον αρχικοποιητή και όταν συμβεί αυτό η κάθε διεργασία έχει στείλει ένα μήνυμα τουλάχιστον μια φορά. ΤΟ ΠΡΩΤΟΚΟΛΛΟ TARRY Οι βασικές αρχές πρωτοκόλλου TARRY είναι: 1. Ισχύουν οι γενικές τρεις ιδιότητες που αναφέρθηκαν στην προηγούμενη παράγραφο. 2. Ένας κόμβος ποτέ δεν στέλνει 2η φορά ένα μήνυμα μέσα από το ίδιο κανάλι. 3. Πατέρας ενός κόμβου ορίζεται ο γείτονας από τον οποίο λήφθηκε για 1 η φορά ένα μήνυμα. 4. Ένας κόμβος στέλνει τη σκυτάλη (token) στον πατέρα του μόνο όταν δεν υπάρχει διαθέσιμο κανάλι, με βάση την αρχή (1). Ιδιότητες του πρωτοκόλλου TARRY Από όλους τους κόμβους αποφασίζει μόνο ο αρχικοποιητής. Το πρωτόκολλο του TARRY σχηματίζει ένα γεννητικό (συνδετικό) δένδρο (spanning tree). Το γεννητικό αυτό δένδρο δεν είναι κατ ανάγκη κατά βάθος (Depth First Search DFS). ΟΚΤΩΒΡΙΟΣ, 2017 ΕΙΣΑΓΩΓΗ ΣΤΑ ΚΑΤΑΝΕΜΗΜΕΝΑ ΣΥΣΤΗΜΑΤΑ 2
ΕΙΚΟΝΑ 1: ΟΙ ΒΑΣΙΚΕΣ ΑΡΧΕΣ ΤΟΥ ΠΡΩΤΟΚΟΛΛΟΥ TARRY ΠΕΡΙΓΡΑΦΗ ΠΡΩΤΟΚΟΛΛΟΥ 1. Ο αρχικοποιητής επιλέγει έναν γείτονα και του στέλνει το token. Σημαδεύει το αντίστοιχο κανάλι ως χρησιμοποιημένο. 2. Κάθε κόμβος (και ο αρχικοποιητής) όταν λάβει το token (εκτελούνται με τη σειρά που αναφέρονται):(αν δεν έχει ήδη πατέρα) σημαδεύει τον αντίστοιχο γείτονα ως πατέρα του. a. Αν όλα τα κανάλια του είναι χρησιμοποιημένα τότε «αποφασίζει». b. Αν υπάρχει ένας γείτονας (εκτός του πατέρα του) στον οποίο δεν έχει στείλει το token, τότε του στέλνει το token. c. Αν έχει στείλει σε όλους τους γείτονες (εκτός του πατέρα του) τότε στέλνει το token στον πατέρα του. ΟΚΤΩΒΡΙΟΣ, 2017 ΕΙΣΑΓΩΓΗ ΣΤΑ ΚΑΤΑΝΕΜΗΜΕΝΑ ΣΥΣΤΗΜΑΤΑ 3
Σε ψευδογλώσσα, το πρωτόκολλο TARRY εμφανίζεται στον παρακάτω πίνακα Initiator var usedp[q]: boolean init false fatherp: δείκτης σε κόμβο init undef; begin fatherp:=p; Επέλεξε ένα q Neighp; usedp[q]:=true; send<token> to q; end All nodes begin if fatherp=undef then fatherp:=q0; if q Neighp : usedp[q] then decide if q Neighp : (q fatherp not usedp[q]) then begin choose q Neighp fatherp with not usedp[q]; usedp[q] :=true; send<token> to q; end begin usedp[fatherp] := true; send<token> to fatherp; end; end. ΟΚΤΩΒΡΙΟΣ, 2017 ΕΙΣΑΓΩΓΗ ΣΤΑ ΚΑΤΑΝΕΜΗΜΕΝΑ ΣΥΣΤΗΜΑΤΑ 4
ΕΡΓΑΣΤΗΡΙΑΚΗ ΆΣΚΗΣΗ ΤΟ ΠΡΩΤΟΚΟΛΛΟ TARRY Σε αυτό το τμήμα της εργαστηριακής άσκησης θα δοκιμάσουμε να υλοποιήσουμε το πρωτόκολλο TARRY και να δοκιμάσουμε την επίδοσή του. Κατά την διάρκεια εκτέλεσης του εργαστηριακού οδηγού θα πρέπει να συμπληρώνετε παράλληλα και την εργαστηριακή σας αναφορά, πρότυπο της οποίας μπορείτε να βρείτε στο openclass του μαθήματος. Η εργαστηριακή αναφορά θα πρέπει να έχει παραδοθεί την ημέρα πριν το επόμενο εργαστήριο, σύμφωνα με τις οδηγίες. Βήμα 1: ΤΟ ΠΡΩΤΟΚΟΛΛΟ TARRY Στο πρώτο βήμα της εργαστηριακής άσκησης θα προσπαθήσουμε να υλοποιήσουμε το πρωτόκολλο ECHO και να μελετήσουμε την συμπεριφορά τους. Για αυτό το λόγο: 1. Συνδεθείτε σε ένα λειτουργικό Linux (Ubuntu ή LUbuntu). 2. Ανοίξτε ένα terminal 3. Δημιουργήστε έναν φάκελο MPI_ABCD, όπου ABCD το μητρώο σας. Για να το πετύχετε αυτό, εκτελέστε την εντολή mkdir MPI_ABCD. Στην συνέχεια μπείτε στον φάκελο εκτελώντας την εντολή cd MPI_ABCD. 4. Δημιουργήστε το αρχείο tarry.c εκτελώντας την εντολή gedit TARRY.c 5. Αντιγράψτε το παρακάτω πρόγραμμα στο αρχείο σας #include "mpi.h" #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <time.h> #include <limits.h> int main( int argc, char *argv[] ) int end = 0, i, k, neighbournumber,token, rn, next, notfinished = 1; int wsize = 5; int father; int *index, *edges, *outindex, *outedges,*neighbours, *visited; int nnodes, nedges; MPI_Comm comm1, comm2; MPI_Request request[5]; MPI_Status status, status2; MPI_Init( &argc, &argv ); //preparation of environment of MPI MPI_Comm_size( MPI_COMM_WORLD, &wsize ); // Get the number of Processors int rank; MPI_Comm_rank(MPI_COMM_WORLD, &rank); srand(time(null) + rank); if (wsize >= 3) // If Processor number is more than 3 we can make a graph. index = (int*)malloc(wsize * sizeof(int) ); edges = (int*)malloc(wsize * 2 * sizeof(int) ); neighbours = (int*)malloc(wsize * 10 * sizeof(int) ); visited = (int*)malloc(wsize * 10 * sizeof(int) ); ΟΚΤΩΒΡΙΟΣ, 2017 ΕΙΣΑΓΩΓΗ ΣΤΑ ΚΑΤΑΝΕΜΗΜΕΝΑ ΣΥΣΤΗΜΑΤΑ 5
// allocate memory for arrays if (!index!edges) printf( "Unable to allocate %d words for index or edges\n", 3 * wsize ); //Error Control if we cannot allocate memory fflush(stdout); MPI_Abort( MPI_COMM_WORLD, 1 ); index[0]=2; index[1]=5; index[2]=6; index[3]=8; index[4]=10; edges[0]=1; edges[1]=4; edges[2]=0; edges[3]=2; edges[4]=3; edges[5]=1; edges[6]=1; edges[7]=4; edges[8]=0; edges[9]=3; &comm1 ); MPI_Graph_create( MPI_COMM_WORLD, wsize, index, edges, 0, if (rank == 0) //Initiator int rn = rand()%neighbournumber; MPI_Graph_neighbors_count(comm1,rank,&neighbourNumber); MPI_Graph_neighbors(comm1,rank,neighbourNumber,neighbours); -----\n"); MPI_COMM_WORLD); neighbours[rn]); for(i=0;i<neighbournumber;i++) visited[i] = 0; printf( "\n-------------tarry STARTED------------------- //Send tokens to random neighbour rn = rand()%neighbournumber; MPI_Send(&token, 1, MPI_INT, neighbours[rn], 0, printf("node %d will send to %d the token\n", rank, fflush(stdout); visited[rn] = 1; while (end == 0) MPI_Recv(&token, 1, MPI_INT, MPI_ANY_SOURCE, 0, MPI_COMM_WORLD, &status2); next = 0; notfinished = 1; ΟΚΤΩΒΡΙΟΣ, 2017 ΕΙΣΑΓΩΓΗ ΣΤΑ ΚΑΤΑΝΕΜΗΜΕΝΑ ΣΥΣΤΗΜΑΤΑ 6
while ( (next < neighbournumber) && notfinished == 1 ) if ( (visited[next] == 0) && neighbours[next]!= father) notfinished = 0; next++; if (notfinished == 1)//all visited except father end = 1; printf("node %d will send to %d the token\n", rank, neighbours[next]); fflush(stdout); sleep(1); MPI_Send(&token, 1, MPI_INT, neighbours[next], 0, MPI_COMM_WORLD); visited[next] = 1; ------\n"); printf( "\n-------------tarry FINISHED------------------ MPI_Recv(&token, 1, MPI_INT, MPI_ANY_SOURCE, 0, MPI_COMM_WORLD, &status2); father = status2.mpi_source; MPI_Graph_neighbors_count(comm1,rank,&neighbourNumber); MPI_Graph_neighbors(comm1,rank,neighbourNumber,neighbours); for(i=0;i<neighbournumber;i++) visited[i] = 0; while (end == 0) next = 0; notfinished = 1; while ( (next < neighbournumber) && notfinished == 1 ) if ( (visited[next] == 0) && neighbours[next]!= father) notfinished = 0; next++; if (notfinished == 1)//all visited except father ΟΚΤΩΒΡΙΟΣ, 2017 ΕΙΣΑΓΩΓΗ ΣΤΑ ΚΑΤΑΝΕΜΗΜΕΝΑ ΣΥΣΤΗΜΑΤΑ 7
token\n", rank, father); MPI_COMM_WORLD); printf("node %d will send to father %d the fflush(stdout); sleep(1); MPI_Send(&token, 1, MPI_INT, father, 0, end = 1; printf("node %d will send to %d the token\n", rank, neighbours[next]); fflush(stdout); sleep(1); MPI_Send(&token, 1, MPI_INT, neighbours[next], 0, MPI_COMM_WORLD); visited[next] = 1; MPI_Recv(&token, 1, MPI_INT, MPI_ANY_SOURCE, 0, MPI_COMM_WORLD, &status2); MPI_Comm_free( &comm1 ); //Empty comm1 and give to system. MPI_Finalize(); //Finish MPI return 0; 6. Σχεδιάστε τον γράφο που δηλώνεται στο παραπάνω πρόγραμμα. 7. Αφού αποθηκεύσετε και κλείσετε το αρχείο, μεταγλωττίστε το εκτελώντας την εντολή mpicc tarry.c o tarry 8. Εάν δεν έγινε κάποιο λάθος, ο μεταγλωττιστής δεν θα πρέπει να βγάλει κανένα μήνυμα. Τότε, μπορείτε να εκτελέσετε το πρόγραμμα, τρέχοντας την εντολή mpirun np 10./tarry. Σε αυτή την εντολή, η παράμετρος np καθορίζει το πλήθος των διεργασιών που θα δημιουργηθούν στον «κόσμο» μας. 9. Αντιγράψτε την έξοδο του προγράμματος στην εργαστηριακή αναφορά σας. Τι παρατηρείτε; ΟΚΤΩΒΡΙΟΣ, 2017 ΕΙΣΑΓΩΓΗ ΣΤΑ ΚΑΤΑΝΕΜΗΜΕΝΑ ΣΥΣΤΗΜΑΤΑ 8
ΔΡΑΣΤΗΡΙΟΤΗΤΕΣ Προσπαθήστε να λύσετε τις παρακάτω δραστηριότητες. Οι απαντήσεις κάθε δραστηριότητας θα πρέπει να εμφανίζονται στην εργαστηριακή σας αναφορά. 1. Μετατρέψτε το παράδειγμα του βήματος 1, έτσι ώστε το πρωτόκολλο να τρέξει πάνω στον παρακάτω γράφο index[0]=4; index[1]=6; index[2]=7; index[3]=8; index[4]=10; edges[0]=1; edges[1]=2; edges[2]=3; edges[3]=4; edges[4]=0; edges[5]=4; edges[6]=0; edges[7]=0; edges[8]=0; edges[9]=1; 2. Μετατρέψτε το παράδειγμα του βήματος 1, έτσι ώστε κάθε κόμβος να τυπώνει το πλήθος των φορών που κατείχαν το token. Συγκρίνετε τα αποτελέσματα με τα αντίστοιχα του πρωτοκόλλου ECHO. 3. Μετατρέψτε το παράδειγμα του βήματος 1, έτσι ώστε ο αρχικοποιητής να υπολογίζει το χρονικό διάστημα που απαιτήθηκε να εκτελεστεί το πρωτόκολλο. 4. Εκτελέστε το πρωτόκολλο TARRY για τον παρακάτω γράφο. Σχεδιάστε στη συνέχεια το δέντρο που προκύπτει. 5. Μετατρέψτε το πρόγραμμα του βήματος 1 έτσι ώστε ο αρχικοποιητής να μπορεί να είναι οποιοσδήποτε κόμβος, ο οποίος θα δίνεται ως είσοδος του προγράμματος. ΟΚΤΩΒΡΙΟΣ, 2017 ΕΙΣΑΓΩΓΗ ΣΤΑ ΚΑΤΑΝΕΜΗΜΕΝΑ ΣΥΣΤΗΜΑΤΑ 9
ΒΙΒΛΙΟΓΡΑΦΙΑ "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 ΕΙΣΑΓΩΓΗ ΣΤΑ ΚΑΤΑΝΕΜΗΜΕΝΑ ΣΥΣΤΗΜΑΤΑ 10