Κατανεμημένος και Παράλληλος Προγραμματισμός Ηλίας Κ. Σάββας Καθηγητής Τμήμα Μηχανικών Πληροφορικής ΤΕ, ΤΕΙ Θεσσαλίας Email: savvas@teilar.gr Παράλληλος προγραμματισμός OpenMP (3) Critical vs. Single Η οδηγία collapse Πάλι βρόγχοι.. Ασκήσεις με βρόγχους Αναζήτηση στοιχείου σε πίνακα Ταξινόμηση πίνακα: count-sort ΕνόητηταI #9 - OpenMP directives 2 Critical vs. single (1 από 2) int a=0, b=0; # pragma omp parallel load a { # pragma omp critical a++; # pragma omp single b++; printf("\n\na=%d, b=%d\n\n", a,b); return 0; Διεργασία 0, Διεργασία 1,. load a add 1 add 1 store a store a Διεργασία x load b add 1 store b a = 8, για 8 πυρήνες b = 1 ΕνόητηταI #9 - OpenMP directives 3 1
Critical vs. single (2 από 2) Critical: αποκλειστικά μία διεργασία/πυρήνας εκτελεί το επόμενο μπλοκ εντολών (αλλά εάν είναι πχ 8 πυρήνες και οι 8 θα το εκτελέσουν αλλά σειριακά) Single: αποκλειστικά μία και μοναδική διεργασία/πυρήνας θα εκτελέσει το επόμενο μπλοκ εντολών (όχι αποκλειστικά ο master) Εκτός και εάν #pragma omp master πρακτικά είναι ίδιο με το: if(omp_get_thread_num() == 0) ΕνόητηταI #9 - OpenMP directives 4 Η οδηγία collapse(x) (1 από 4) Απαγορεύεται: #pragma omp parallel for for(y=0; y<25; ++y) { // ERROR!!! #pragma omp for for(x=0; x<80; ++x) Α[y] = x * y; Σωστό: #pragma omp parallel for collapse(2) for(int y=0; y<25; ++y) for(int x=0; x<80; ++x) A[y] = x * y; Θα παραλληλίσει και τους δύο βρόγχους ΕνόητηταI #9 - OpenMP directives 5 Η οδηγία collapse(x) (2 από 4) Πολλαπλασιασμός πινάκων: C NxN A NxN B NxN, c i, j k 0 for (i=0; i<n; i++) for (j=0; j<n; j++) { C[i][j] = 0; for (k=0; k<n; k++) C[i][j] += A[i][k] * B[k][j]; N b i, k c k, j ΕνόητηταI #9 - OpenMP directives 6 2
Η οδηγία collapse(x) (3 από 4) Εάν παραλληλισθεί μόνο η πρώτη for: N διαμοιραζόμενες επαναλήψεις (ανά γραμμή) Οι δύο πρώτες: Ν 2 διαμοιραζόμενες επαναλήψεις (ανά στοιχείο) Όλες: Ν 3 διαμοιραζόμενες επαναλήψεις ( ανά όρο του κάθε στοιχείου). Δεν είναι εφικτό. Πολλές διεργασίες θα προσπαθούν να προσπελάσουν ταυτόχρονα κοινές μεταβλητές. ΕνόητηταI #9 - OpenMP directives 7 Η οδηγία collapse(x) (4 από 4) # pragma omp parallel for private(ego) collapse(2) { ego = omp_get_thread_num(); for (i=0; i<n; i++) for (j=0; j<n; j++) { C[i][j] = 0; printf( H diergasia %d ypologizei to %d-%d stoixeio\n, ego, I, j); for (k=0; k<n; k++) C[i][j] += A[i][k] * B[k][j]; ΕνόητηταI #9 - OpenMP directives 8 Ασκήσεις (1 από 5) Να παραλληλιστεί ο ακόλουθος βρόγχος: for (i = 0; i < N; i++) { y = sqrt(a[i]); D[i] = y + A[i] / (x * x); # pragma omp parallel for for (i = 0; i < N; i++) { y = sqrt(a[i]); D[i] = y + A[i] / (x * x); ΕνόητηταI #9 - OpenMP directives 9 3
Ασκήσεις (2 από 5) Να παραλληλισθεί ο κώδικας υπολογισμού του Ν!=1*2*3* *Ν int g=1; for (i=2; i<=n; i++) g *= i; int g; # pragma omp parallel for reduction(*:g) for (i=2; i<=n; i++) g *= i; ΕνόητηταI #9 - OpenMP directives 10 Ασκήσεις (3 από 5) Να παραλληλιστούν σωστά οι βρόγχοι: #pragma omp parallel { for (i = 0; i < N; i ++) { D[i] = x * A[i] + x * B[i]; #pragma omp for for (i = 0; i < N; i++) C[i] = c * D[i]; ------------- #pragma omp parallel { # pragma omp for for (i = 0; i < N; i ++) { D[i] = x * A[i] + x * B[i]; # pragma omp for nowait for (i = 0; i < N; i++) C[i] = c * D[i]; ------ ΕνόητηταI #9 - OpenMP directives 11 Ασκήσεις (4 από 5) Άρση εξάρτησης δεδομένων και παραλληλισμός βρόγχου int A[N], B[M], i,j=5; for (i=0; i<n; i++) { j+=2; A[i] = j * B[j] int j = 0; # pragma omp parallel for for (i=0; i<n; i++) { j = 7 + 2*i; A[i] = j * B[j]; ΕνόητηταI #9 - OpenMP directives 12 4
Ασκήσεις (5 από 5) Μπορεί να παραλληλιστεί ο ακόλουθος βρόγχος (δικαιολογήστε): #pragma omp parallel for A[i] = B[i] A[i 1]; Όχι γιατί υπάρχει εξάρτηση δεδομένων. Μπορεί μόνο με χρήση βοηθητικού πίνακα για να αποθηκεύει τις τιμές του Α ΕνόητηταI #9 - OpenMP directives 13 Αποτελέσματα 5 ης άσκησης (1 από 4) for (i=0; i<n;i++) { A[i] = i; B[i] = i * i; printf("%3d, %3d\n", A[i], B[i]); printf("\n\n"); { printf("%3d, %3d\n", A[i-1], A[i]); for (i=0; i<n; i++) A[i] = i; printf("\n\n"); #pragma omp parallel for { printf("%3d, %3d\n", A[i- 1], A[i]); ΕνόητηταI #9 - OpenMP directives 14 Αποτελέσματα 5 ης άσκησης (2 από 4) Α Β 0 -> 0, 0 1 -> 1, 1 2 -> 2, 4 3 -> 3, 9 4 -> 4, 16 Σωστό: 0, 1, 5, 14, 30 Αποτέλεσμα: 0, 1, 11, 27, 5 ΕνόητηταI #9 - OpenMP directives 15 5
Αποτελέσματα 5 ης άσκησης (3 από 4) #pragma omp parallel for Σωστό: 0, 1, 5, 14, 30 Αποτέλεσμα 1: 0, 1, 5, 14, 19 Αποτέλεσμα 2: 0, 1, 5, 11, 27 ------------------------------------- ΕνόητηταI #9 - OpenMP directives 16 Αποτελέσματα 5 ης άσκησης (4 από 4) #pragma omp parallel for private(i, A) #pragma omp parallel for default(none) shared(n,b) private(i,a) Σωστό: 0, 1, 5, 14, 30 Αποτέλεσμα: 0, 1, 2, 3, 4 ΕνόητηταI #9 - OpenMP directives 17 Αποτελέσματα 5 ης άσκησης (5 από 5) #pragma omp parallel for schedule(dynamic) Σωστό: 0, 1, 5, 14, 30 Αποτέλεσμα 1: 0, 1, 5, 14, 30 Αποτέλεσμα 2: 0, 1, 5, 11, 27 --------------------------------------- ΕνόητηταI #9 - OpenMP directives 18 6
Παραλληλοποίηση 5 ης άσκησης # pragma omp parallel { # pragma omp for for (i=0; i<n; i++) //βοηθητικός πίνακας temp[i] = A[i]; # pragma omp for A[i] = B[i] + temp[i - 1]; Αποτέλεσμα: 0, 1, 5, 14, 30 ΕνόητηταI #9 - OpenMP directives 19 Αναζήτηση στοιχείου σε πίνακα (1 από 2) Να γραφεί παράλληλο πρόγραμμα με χρήση της OpenMP το οποίο να αναζητά το πλήθος της εμφάνισης κάποιου στοιχείου σε διάνυσμα. #include <omp.h> #include <stdio.h> #include <stdlib.h> int main( int argc, char **argv ) { int *P, N, i; /* Pinakas - megethos - deiktis */ int x, f=0; /* stoixeio poy anazitoyme, poses fores vrethike */ double ta, tt; /* gia metrisi xronou */ ΕνόητηταI #9 - OpenMP directives 20 Αναζήτηση στοιχείου σε πίνακα (2 από 2) ta = omp_get_wtime(); /* arxi metrisis xronou */ /* anazitisi */ # pragma omp parallel for num_threads(4) reduction(+:f) for (i=0; i<n; i++) if (P[i] == x ) f++; tt = omp_get_wtime(); /* telos metrisis xronou */ printf("\n\nto %d yparxei ston pinaka %d fores", x, f); printf("\n\nxronos ektelesis: %.16f\n\n", tt-ta); ΕνόητηταI #9 - OpenMP directives 21 7
Συγκρίσεις ΕνόητηταI #9 - OpenMP directives 22 OpenMP vs. MPI Ν (x1,000,000) /P MPI P=2 OpenMP Threads=2 MPI P=4 OpenMP Threads=4 100 0.323 0.144 0.195 0.119 200 0.642 0.286 0.384 0.236 300 1.134 0.429 0.576 0.354 400 1.290 0.570 0.758 0.472 500 1.590 0.712 0.953 0.599 600 1.926 0.854 1.163 0.707 700 2.661 0.998 1.334 0.825 800 3.538 1.139 1.519 0.943 900 4.668 1.281 1.693 1.062 ΕνόητηταI #9 - OpenMP directives 23 MPI και OpenMP Παραλληλοποίηση σε πρώτο επίπεδο (επίπεδο υπολογιστικής συστοιχίας - cluster) με MPI Παραλληλοποίηση σε δεύτερο επίπεδο (επίπεδο κόμβων) με ΟpenΜP MPI: Διαμοίραση πίνακα και αποστολή <part> και αντίστοιχο μέρος του πίνακα στους worker nodes OpenMP: σε κάθε worker node χρήση της ΟΜP για την παραλληολοποίηση των βρόγχων με reduction(+: sum) MPI: Παραλαβή αποτελέσματος από τον master node με MPI_Reduce (&sum, &total_sum) ΕνόητηταI #9 - OpenMP directives 24 8
Χρήσιμες οδηγίες double omp_get_wtime(void) Επιστρέφει χρόνο σε δευτερόλεπτα int omp_get_num_procs(void) Σύνολο διαθέσιμων επεξεργαστών / πυρήνων του ΗΥ int omp_get_max_threads(void) Μέγιστος αριθμός νημάτων που μπορούν να δοθούν σε μία νέα ομάδα int omp_get_thread_limit(void) Μέγιστος αριθμός νημάτων που είναι διαθέσιμα εξαρχής ΕνόητηταI #9 - OpenMP directives 25 Count sort (1 από 2) Για κάθε στοιχείο του πίνακα, μετράμε το πλήθος των στοιχείων που είναι μικρότερα από αυτό και στην συνέχεια το τοποθετούμε σε ένα βοηθητικό πίνακα στη σωστή θέση Εάν υπάρχουν ίδια στοιχεία το λαμβάνουμε υπόψη ώστε να μην τοποθετηθούν στην ίδια θέση Μειονεκτήματα: αργή μέθοδος (πολυπλοκότητα Ν 2 ) και η χρήση βοηθητικού πίνακα ΕνόητηταI #9 - OpenMP directives 26 Count sort (2 από 2) Σειριακή προσέγγιση: for (i=0; i<n; i++) { count = 0; for (j=0; j<n; j++) if (A[j] < A[i]) count++; else if (A[j] == A[i] && j < i) count++; temp[count] = A[i]; //metafora temp ston A for (i=0; i<n; i++) A[i] = temp[i]; free(temp); Ζητούμενο: να παραλληλισθεί! ΕνόητηταI #9 - OpenMP directives 27 9
Τέλος της OMP Ερωτήσεις; Χρησιμοποιείστε το email για όποιες επιπλέον απορίες / ερωτήσεις: savvas@teilar.gr Σημειώσεις μαθήματος (και όχι μόνο): https://e-class.teilar.gr/courses/cs386/ ΕνόητηταI #9 - OpenMP directives 28 10