Professional Documents
Culture Documents
Report
Report
Πανεπιστήµιο Πατρών
Παράλληλη Επεξεργασία
΄Ασκηση Εξαµήνου
Πάτρα, 2013
Παρατηρούµε ότι η συνάρτηση dist και κατά δεύτερο λόγο η pgain καταναλώνουν τον περισσότερο χρόνο εκτέλεσης
στο πρόγραµµά µας. Συνεπώς καταλήγουµε πως πρέπει να παραλληλοποιήσουµε τα συγκεκριµένα τµήµατα του κώδικα
για να έχουµε αύξηση των χρονικών επιδόσεων.
3 Παραλληλοποίηση µε χρήση OpenMP
3.1 Συνάρτηση dist
Ξεκινώντας µε τη συνάρτηση dist αρχικά επιχειρούµε να την παραλληλοποιήσουµε χρησιµοποιώντας το πρότυπο
OpenMP και συγκεκριµένα την οδηγία
]pragma omp for reduction(+:result)
η οποία κάνει διαµοιρασµό εργασίας σε νήµατα που διαθέτουµε, ο αριθµός των οποίων είναι προκαθορισµένος από τη
µεταβλητή περιβάλλοντος OMP_NUM_THREADS. Το reduction εξασφαλίζει ότι η τελική τιµή της result ϑα είναι το άθροισµα
των µερικών αθροισµάτων της τοπικής µεταβλητής result που έχει το κάθε νήµα, διασφαλίζοντας έτσι την ορθότητα του
αποτελέσµατος.
Εκτελώντας τον τροποποιηµένο κώδικα παρατηρούµε ότι το πρόγραµµα παρουσιάζει χρονοκαθυστέρηση σε σχέση
µε το αρχικό και άρα επιλέγουµε τελικά να µη κάνουµε τη συγκεκριµένη αλλαγή. Ο λόγος για των οποίο συµβάινει αυτό
είναι γιατί ο ϐρόχος στον οποίο εφαρµόζουµε παραλληλοποίηση είναι αρκετά µικρός και ο ϕόρτος εργασίας σε κάθε
επανάληψη είναι επίσης αρκετά µικρός (τέσσερις αριθµητικές πράξεις) ώστε η δηµιουργία νηµάτων να επιβαρύνει τελικά
την εκτέλεσή του, αφού για να γίνει ο καταµερισµός τους πρέπει να γίνουν οι κατάλληλες αρχικοποιήσεις σε κάθε νήµα.
3
] pragma omp for nowait
΄Ολες οι µεταβλητές είναι διαµοιραζόµενες µεταξύ των νηµάτων αλλά αυτό δε µας προβληµατίζει γιατί τα νήµατα δουλε-
ύουν µε τοπικές µεταβλητές που υπάρχουν στο µπλοκ του ϐρόγχου. Τοποθετήσαµε το όρισµα nowait το οποίο δηλώνει ότι
δεν υπάρχει ϕράγµα στο τέλος του ϐρόγχου επανάληψης συνεπώς οποιδήποτε νήµα τελειώνει µπορεί να συνεχίσει στο
επόµενο τµήµα του κώδικα. Αυτό µας το επιτρέπει το γεγονός ότι στον επόµενο ϐρόγχο δεν επεξεργαζόµαστε δεδοµένα
που έχουν προκύψει από τον προηγούµενο ϐρόγχο. ∆ηλαδή οι δύο ϐρόγχοι είναι ανεξάρτητοι κάτι που σηµαίνει ότι ϑα
αν ένα νήµα τελειώσει πιο γρήγορα τη δουλειά του µπορούµε να του αναθέσουµε αµέσως νέα, αυξάνοντας έτσι την
απόδοση του προγράµµατος µας.
Τέλος, µε την εντολή
παραλληλοποιούµε το δεύτερο ϐρόγχο αφού κάθε επανάληψη δουλεύει σε διαφορετικό σηµείο των διαµοπιραζόµενων
µεταβλητών και συνεπώς δε χρειάζεται να προσθέσουµε εµείς κάποια επιπλέον παράµετρο ώστε να εξασφαλίσουµε τη
σωστή λειτουργία.
Με τη προσθήκη και αυτού του κώδικα, έχουµε παραλληλοποιήσει την πγαιν κατά το µέγιστο. Η προσθήκη παραπάνω
εντολών, (πχ σε κάποια άλλη πολύ µικρή από άποψη δουλειάς for) δεν είχε τα επιθυµητά αποτελέσµατα, αλλά αύξανε
το χρόνο εκτέλεσης. Το ίδιο συνέβη και κατά την προσπάθεια µας να παραλληλοποιήσουµε την αµέσως επόµενη από
άποψη χρόνου στο scalasca συνάρτηση, την pspeedy, στην οποία οποιαδήποτε προσπάθεια για προσθήκη νηµάτων είχε
ως αποτέλεσµα την αύξηση του χρόνου κάτι λογικό, αφού η pspeedy κατείχε ένα εξαιρετικά µικρό ποσοστό του χρόνου
εκτέλεσης του προγράµµατος και η προσθήκη νηµάτων όπως περιγράψαµε και στη dist οδήγησε στην καθυστέρηση της
εκτέλεσης της.
4
΄Εκδοση OpenMP -Ο0 ΄Εκδοση OpenMP -Ο3
129.579 71.1904 47.8969 38.91 24.1717 22.2504
534.363 282.665 147.648 152.482 86.6444 67.3398
1912.47 1000.19 637.901 504.088 287.696 247.221
5
Για καλύτερη οπτικοποίηση των αποτελεσµάτων προχωρήσαµε στη δηµιουργία γραφηµάτων που δείχνουν τους
χρόνους εκτέλεσης
6
• Χρόνοι εκτέλεσης για µεγάλες παραµέτρους εισόδου
Ενώ παρακάτω ϕαίνεται και το ποσοστιαίο κέρδος που είχε κάθε έκδοση µε την αύξηση των χρησιµοποιούµενων
νηµάτων :
• Ποσοστιαία αύξηση απόδοσης για µικρές παραµέτρους εισόδου
7
• Ποσοστιαία αύξηση απόδοσης για µεσαίες παραµέτρους εισόδου
8
Παρατηρούµε ότι όταν ο compiler χρησιµοποιεί την παράµετρο -Ο3 , οπότε και κάνει ϐελτιστοποιήσεις στον κώδικα
κατά το compilation, η αύξηση της απόδοσης είναι µικρότερη. Αυτό οφείλεται στο ότι ο compiler ϑα ενώσει κάποιους
ϐρόγχους for και ϑα κάνει και άλλες λειτουργίες οι οποίες ϱίχνουν αρκετά το χρόνο εκτέλεσης, αφήνοντας µας ως
αποτέλεσµα µικρότερο χώρο για ϐελτίωση του. Στις εκδόσεις στις οποίες ο compiler δε πραγµατοποιεί ϐελτιστοποιήσεις
παρατηρειται σηµαντικά µεγαλύτερο κέρδος. Συγκεκριµένα, ενώ στις -Ο3 τόσο µε 2 όσο και µε 4 νήµατα είχαµε περίπου
100% αύξηση, στις -Ο0 έχουµε έως και 250% αύξηση για την έκδοση µε openmp ενώ όταν χρησιµοποιήσουµε και εντολές
simd η αύξηση εκτινάσεται πάνω από 500% . Παρατηρούµε ότι η εισαγωγή εντολών simd αυξάνει πάρα πολύ την απόδοση
του προγράµµατος µας. Και πάλι όµως, δεν επιτυγχάνουµε τη ϑεωρητική αύξηση που λέει πως εφόσον εκτελούµε τις
αριθµητικές πράξεις σε τετράδες δεδοµένων έπρεπε να περιµένουµε τετραπλασιασµό της απόδοσης. Αυτό συµβαίνει
για διάφορους λόγους και πιθανότατα οφείλεται στην αρχιτεκτονική των σύγχρονων επεξεργαστών η οποία δεν µας
επιτρέπει να επιτύχουµε το κέρδος που µας δίνει η ϑεωρητική υλοποίηση.
9
6 Παράρτηµα
6.1 Αναπαράσταση Αποτελεσµάτων
Για την αναπαράσταση των χρονικών αποτελεσµάτων που καταγράψαµε, δηµιουργήθηκε ο παρακάτω κώδικας σε
matlab:
21 threads = [1,2,4];
22 max_axis = [200 800 2000];
23 names = [’small’ ’medium’ ’large’];
24 f o r k=1:3
25 f i g u r e (k);
26 s e t (0,’DefaultAxesLineStyleOrder’,’-|-.|--|:’)
27
28 plot1 = p l o t (threads,seqO0(k,:),...
29 threads,ompO0(k,:),...
30 threads,ompsimdO0(k,:),...
31 threads,seqO3(k,:),...
32 threads,ompO3(k,:),...
33 threads,ompsimdO3(k,:),...
34 ’MarkerSize’,20,’Marker’,’.’,...
35 ’LineWidth’,1,...
36 ’LineStyle’,’--’);
37 s e t (plot1(1),’MarkerFaceColor’,’auto’,’DisplayName’,’seq -O0’);
38 s e t (plot1(2),’DisplayName’,’omp with simd -O0’);
39 s e t (plot1(3),’MarkerFaceColor’,’auto’,’DisplayName’,’seq -03’);
40 s e t (plot1(4),’DisplayName’,’omp -O3’);
41 s e t (plot1(5),’DisplayName’,’omp with simd -O3’);
42 s e t (plot1(6),’MarkerFaceColor’,’auto’,’DisplayName’,’omp -O0’);
43 a x i s ([0 5 0 max_axis(k)]);
44 y l a b e l ( ’Time’ );
45 x l a b e l ( ’Threads’ );
46
10
49
50 f i g u r e (3+k);
51 s e t (0,’DefaultAxesLineStyleOrder’,’-|-.|--|:’)
52
53 plot2 = p l o t (threads,perc_gain(seqO0(1,:),seqO0(1,:)),...
54 threads,perc_gain(ompO0(1,:),seqO0(1,:)),...
55 threads,perc_gain(ompsimdO0(1,:),seqO0(1,:)),...
56 threads,perc_gain(seqO3(1,:),seqO3(1,:)),...
57 threads,perc_gain(ompO3(1,:),seqO3(1,:)),...
58 threads,perc_gain(ompsimdO3(1,:),seqO3(1,:)),...
59 ’MarkerSize’,20,’Marker’,’.’,...
60 ’LineWidth’,1,...
61 ’LineStyle’,’--’);
62 s e t (plot2(1),’MarkerFaceColor’,’auto’,’DisplayName’,’seq -O0’);
63 s e t (plot2(2),’DisplayName’,’omp with simd -O0’);
64 s e t (plot2(3),’MarkerFaceColor’,’auto’,’DisplayName’,’seq -03’);
65 s e t (plot2(4),’DisplayName’,’omp -O3’);
66 s e t (plot2(5),’DisplayName’,’omp with simd -O3’);
67 s e t (plot2(6),’MarkerFaceColor’,’auto’,’DisplayName’,’omp -O0’);
68 a x i s ([0 5 0 500]);
69 y l a b e l ( ’% increase in execusion speed’ );
70 x l a b e l ( ’Threads (s) ’ );
71
75
76 end
1 f u n c t i o n [R] = perc_gain(X1,X2)
2 R = abs (X1-X2)./ X1;
3 R = R *100;
4 end
11
6.2 Bash Script
Για το compiling καθώς και την εκτέλεση του προγράµµατος χρησιµοποιήθηκε το παρακάτω bash script το οποίο εκτελεί
την τελευταία έκδοση του κώδικα µε τα ορίσµατα της επιλογής µας, τόσο για τη σειριακή όσο και για τις παράλληλες
εκδοχές του κώδικα, ενώ τα αποτελέσµατα που εξάγονται αντιγράφονται στο αρχείο report.txt.
1 #!/bin/bash
2 i f [[ -f diff_results.txt ]]; t h e n
3 echo ’deleting previous file!’
4 rm diff_results.txt
5
6 fi
7 i f [[ -f output_small_O0.txt ]]; t h e n
8 echo ’deleting previous temporary files!’
9 rm output_small_*.txt
10
11 fi
12 i f [[ -f output_medium_O0.txt ]]; t h e n
13 echo ’deleting previous temporary files!’
14 rm output_medium_*.txt
15
16 fi
17 i f [[ -f output_large_O0.txt ]]; t h e n
18 echo ’deleting previous temporary files!’
19 rm output_large_*.txt
20
21 fi
22 i f [[ -f report.txt ]]; t h e n
23 rm report.txt
24
25 fi
26 echo ’compiling single threaded with O3....’
27 g++ -O3 -Wall -Wextra -o streamcluster_O3 streamcluster.cpp | grep error
28 echo ’compiling single threaded with O0....’
29 g++ -O0 -Wall -Wextra -o streamcluster_O0 streamcluster.cpp | grep error
30 echo ’compiling omp version with O3....’
31 g++ -O3 -fopenmp -Wall -Wextra -o streamcluster_omp_O3 streamcluster_omp.cpp | grep error
32 echo ’compiling omp version with O0....’
33 g++ -O0 -fopenmp -Wall -Wextra -o streamcluster_omp_O0 streamcluster_omp.cpp | grep error
34 echo ’compiling omp+simd version with O3....’
35 g++ -O3 -fopenmp -msse -Wall -Wextra -o streamcluster_omp_simd_O3 \
36 streamcluster_omp_simd.cpp | grep error
37 echo ’compiling omp+simd version with O0....’
38 g++ -O0 -fopenmp -msse -Wall -Wextra -o streamcluster_omp_simd_O0 \
39 streamcluster_omp_simd.cpp | grep error
40 echo ’’
41 echo ’’
42 echo ’’
43 echo ’’
44
45 while true
46 do
47
12
51 echo ’normal numbers’ >> report.txt
52 echo ’SMALL’ | tee -a report.txt
53 echo ’running sequential program with -O0’ | tee -a report.txt
54 ./streamcluster_O0 10 20 32 4096 4096 1000 none output_small_O0.txt | tee -a report.txt
55 echo ’running parallel program with -O0: ’ | tee -a report.txt
56 ./streamcluster_omp_O0 10 20 32 4096 4096 1000 none output_small_omp_O0.txt \
57 | tee -a report.txt
58 echo ’running parallel program +simd commands with -O0: ’ | tee -a report.txt
59 ./streamcluster_omp_simd_O0 10 20 32 4096 4096 1000 none output_small_omp_simd_O0.txt \
60 | tee -a report.txt
61 echo ’running sequential program with -O3’ | tee -a report.txt
62 ./streamcluster_O3 10 20 32 4096 4096 1000 none output_small_O3.txt \
63 | tee -a report.txt
64 echo ’running parallel program with -O3: ’ | tee -a report.txt
65 ./streamcluster_omp_O3 10 20 32 4096 4096 1000 none output_small_omp_O3.txt \
66 | tee -a report.txt
67 echo ’running parallel program +simd commands with -O3: ’ | tee -a report.txt
68 ./streamcluster_omp_simd_O3 10 20 32 4096 4096 1000 none output_small_omp_simd_O3.txt \
69 | tee -a report.txt
70
76 ;;
77
78 2)
79 echo ’normal numbers’ >> report.txt
80 echo ’MEDIUM’ | tee -a report.txt
81 echo ’running sequential program with -O0’ | tee -a report.txt
82 ./streamcluster_O0 10 20 64 8192 8192 1000 none output_medium_O0.txt | tee -a report.txt
83 echo ’running parallel program with -O0: ’ | tee -a report.txt
84 ./streamcluster_omp_O0 10 20 64 8192 8192 1000 none output_medium_omp_O0.txt \
85 | tee -a report.txt
86 echo ’running parallel program +simd commands with -O0: ’ | tee -a report.txt
87 ./streamcluster_omp_simd_O0 10 20 64 8192 8192 1000 none output_medium_omp_simd_O0.txt \
88 | tee -a report.txt
89 echo ’running sequential program with -O3’ | tee -a report.txt
90 ./streamcluster_O3 10 20 64 8192 8192 1000 none output_medium_O3.txt \
91 | tee -a report.txt
92 echo ’running parallel program with -O3: ’ | tee -a report.txt
93 ./streamcluster_omp_O3 10 20 64 8192 8192 1000 none output_medium_omp_O3.txt \
94 | tee -a report.txt
95 echo ’running parallel program +simd commands with -O3: ’ | tee -a report.txt
96 ./streamcluster_omp_simd_O3 10 20 64 8192 8192 1000 none output_medium_omp_simd_O3.txt \
97 | tee -a report.txt
98
104 ;;
105
106 3)
13
107 echo ’normal numbers’ >> report.txt
108 echo ’LARGE’ | tee -a report.txt
109 echo ’running sequential program with -O0’ | tee -a report.txt
110 ./streamcluster_O0 10 20 128 16384 16384 1000 none output_large_O0.txt \
111 | tee -a report.txt
112 echo ’running parallel program with -O0: ’ | tee -a report.txt
113 ./streamcluster_omp_O0 10 20 128 16384 16384 1000 none output_large_omp_O0.txt \
114 | tee -a report.txt
115 echo ’running parallel program +simd commands with -O0: ’ | tee -a report.txt
116 ./streamcluster_omp_simd_O0 10 20 128 16384 16384 1000 none output_large_omp_simd_O0.txt\
117 | tee -a report.txt
118 echo ’running sequential program with -O3’ | tee -a report.txt
119 ./streamcluster_O3 10 20 128 16384 16384 1000 none output_large_O3.txt \
120 | tee -a report.txt
121 echo ’running parallel program with -O3: ’ | tee -a report.txt
122 ./streamcluster_omp_O3 10 20 128 16384 16384 1000 none output_large_omp_O3.txt \
123 | tee -a report.txt
124 echo ’running parallel program +simd commands with -O3: ’ \
125 | tee -a report.txt
126 ./streamcluster_omp_simd_O3 10 20 128 16384 16384 1000 none output_large_omp_simd_O3.txt \
127 | tee -a report.txt
128
134 ;;
135
136 4)
137 echo ’big numbers’ >> report.txt
138 echo ’SMALL’ | tee -a report.txt
139 echo ’running sequential program with -O0’ | tee -a report.txt
140 ./streamcluster_O0 10 20 256 32768 32768 1000 none output_small_O0.txt \
141 | tee -a report.txt
142 echo ’running parallel program with -O0: ’ | tee -a report.txt
143 ./streamcluster_omp_O0 10 20 256 32768 32768 1000 none output_small_omp_O0.txt \
144 | tee -a report.txt
145 echo ’running parallel program +simd commands with -O0:’| tee -a report.txt
146 ./streamcluster_omp_simd_O0 10 20 256 32768 32768 1000 none output_small_omp_simd_O0.txt \
147 | tee -a report.txt
148 echo ’running sequential program with -O3’| tee -a report.txt
149 ./streamcluster_O3 10 20 256 32768 32768 1000 none output_small_O3.txt \
150 | tee -a report.txt
151 echo ’running parallel program with -O3: ’ | tee -a report.txt
152 ./streamcluster_omp_O3 10 20 256 32768 32768 1000 none output_small_omp_O3.txt \
153 | tee -a report.txt
154 echo ’running parallel program +simd commands with -O3: ’ | tee -a report.txt
155 ./streamcluster_omp_simd_O3 10 20 256 32768 32768 1000 none output_small_omp_simd_O3.txt \
156 | tee -a report.txt
157
14
163 ;;
164
165 5)
166 echo ’big numbers’ >> report.txt
167 echo ’MEDIUM’ | tee -a report.txt
168 echo ’running sequential program with -O0’ | tee -a report.txt
169 ./streamcluster_O0 10 20 512 65536 65536 1000 none output_medium_O0.txt \
170 | tee -a report.txt
171 echo ’running parallel program with -O0: ’ | tee -a report.txt
172 ./streamcluster_omp_O0 10 20 512 65536 65536 1000 none output_medium_omp_O0.txt \
173 | tee -a report.txt
174 echo ’running parallel program +simd commands with -O0: ’ | tee -a report.txt
175 ./streamcluster_omp_simd_O0 10 20 512 65536 65536 1000 none output_medium_omp_simd_O0.txt \
176 | tee -a report.txt
177 echo ’running sequential program with -O3’ | tee -a report.txt
178 ./streamcluster_O3 10 20 512 65536 65536 1000 none output_medium_O3.txt
179 tee -a report.txt
180 echo ’running parallel program with -O3: ’ | tee -a report.txt
181 ./streamcluster_omp_O3 10 20 512 65536 65536 1000 none output_medium_omp_O3.txt
182 tee -a report.txt
183 echo ’running parallel program +simd commands with -O3: ’ | tee -a report.txt
184 ./streamcluster_omp_simd_O3 10 20 512 65536 65536 1000 none output_medium_omp_simd_O3.txt
185 tee -a report.txt
186
192 ;;
193
194 6)
195 echo ’big numbers’ >> report.txt
196 echo ’LARGE’ | tee -a report.txt
197 echo ’running sequential program with -O0’ | tee -a report.txt
198 ./streamcluster_O0 10 20 1024 131072 131072 1000 none output_large_O0.txt
199 tee -a report.txt
200 echo ’running parallel program with -O0: ’ | tee -a report.txt
201 ./streamcluster_omp_O0 10 20 1024 131072 131072 1000 none output_large_omp_O0.txt
202 tee -a report.txt
203 echo ’running parallel program +simd commands with -O0: ’ | tee -a report.txt
204 ./streamcluster_omp_simd_O0 10 20 1024 131072 131072 1000 none output_large_omp_simd_O0.txt \
205 | tee -a report.txt
206 echo ’running sequential program with -O3’ | tee -a report.txt
207 ./streamcluster_O3 10 20 1024 131072 131072 1000 none output_large_O3.txt \
208 | tee -a report.txt
209 echo ’running parallel program with -O3: ’ | tee -a report.txt
210 ./streamcluster_omp_O3 10 20 1024 131072 131072 1000 none output_large_omp_O3.txt \
211 | tee -a report.txt
212 echo ’running parallel program +simd commands with -O3: ’ | tee -a report.txt
213 ./streamcluster_omp_simd_O3 10 20 1024 131072 131072 1000 none output_large_omp_simd_O3.txt \
214 | tee -a report.txt
215
15
219 diff output_large_O3.txt output_large_omp_simd_O3.txt >> diff_results.txt
220
221 ;;
222
223 0)
224 exit
225 ;;
226 *)
227 echo ’invalid choice’
228 ;;
229 esac
230
236 echo ’The results from both programs are the same.’;
237 else
238 echo ’Abort ship!’
239 fi
240
241 fi
242
243
244 done
16