Η παρουσίαση φορτώνεται. Παρακαλείστε να περιμένετε

Η παρουσίαση φορτώνεται. Παρακαλείστε να περιμένετε

© 2006-07 Ασκήσεις στα Προηγμένα Θέματα Αρχιτεκτονικής Υπολογιστών ακ. έτος 2006-2007 Νεκτάριος Κοζύρης Νίκος Αναστόπουλος

Παρόμοιες παρουσιάσεις


Παρουσίαση με θέμα: "© 2006-07 Ασκήσεις στα Προηγμένα Θέματα Αρχιτεκτονικής Υπολογιστών ακ. έτος 2006-2007 Νεκτάριος Κοζύρης Νίκος Αναστόπουλος"— Μεταγράφημα παρουσίασης:

1 © Ασκήσεις στα Προηγμένα Θέματα Αρχιτεκτονικής Υπολογιστών ακ. έτος Νεκτάριος Κοζύρης Νίκος Αναστόπουλος

2 © Άσκηση 1: pipelining

3 © Εξετάζουμε την εκτέλεση του παρακάτω κώδικα ο οποίος αντιγράφει ένα «null-terminated» string. Repeat: lb r3,0(r1) ;load char (1byte) sb r3,0(r2) ;store char beqz r3,Exit ;was char NULL? addi r1,r1,1 ;update r1 to point at next char of source string addi r2,r2,1 ;update r2 to point at next char of target string j Repeat Exit: Υποθέσεις αρχιτεκτονική σωλήνωσης 5 σταδίων (IF ID EX MEM WB) εγγραφή σε έναν καταχωρητή στο 1 ο μισό ενός κύκλου, ανάγνωση στο 2 ο εντολή διακλάδωσης χωρίς συνθήκη: η διεύθυνση-στόχος γίνεται γνωστή στο στάδιο IF εντολή διακλάδωσης με συνθήκη: πρόβλεψη διακλάδωσης (NOT TAKEN), η προβλεπόμενη διεύθυνση-στόχος γίνεται γνωστή στο στάδιο IF, ο έλεγχος για την ορθότητα της πρόβλεψης στο ΜΕΜ

4 © Αρχικά, υποθέτουμε ότι δεν υπάρχει σχήμα προώθησης. Για τις 2 πρώτες επαναλήψεις, δείξτε τα διάφορα στάδια του pipeline από τα οποία διέρχονται οι εντολές σε αυτό το διάστημα εκτέλεσης. Υποδείξτε και εξηγείστε τους πιθανούς κινδύνους (hazards) που μπορούν να προκύψουν κατά την εκτέλεση, καθώς και τον τρόπο με τον οποίον αυτοί αντιμετωπίζονται. Πόσοι κύκλοι απαιτούνται κατά μέσο όρο για την αντιγραφή ενός χαρακτήρα;

5 ©

6 Repeat: lb r3,0(r1) sb r3,0(r2) beqz r3,Exit addi r1,r1,1 addi r2,r2,1 j Repeat Exit: πραγματική εξάρτηση δεδομένων → RAW κίνδυνος δεδομένων …ο κίνδυνος επιλύεται με stalls 2 κύκλων

7 © Repeat: lb r3,0(r1) sb r3,0(r2) beqz r3,Exit addi r1,r1,1 addi r2,r2,1 j Repeat Exit: πραγματική εξάρτηση δεδομένων …δεν εγείρει όμως RAW κίνδυνο δεδομένων, αφού με τα stalls της προηγούμενης περίπτωσης ο κίνδυνος εξαλείφεται

8 © Repeat: lb r3,0(r1) sb r3,0(r2) beqz r3,Exit addi r1,r1,1 addi r2,r2,1 j Repeat Exit: πραγματικές εξαρτήσεις δεδομένων …δεν εγείρουν όμως κίνδυνο δεδομένων, αφού στο pipeline εγγραφή σε κάποιον καταχωρητή γίνεται στο 1o μισό ενός κύκλου, ενώ η ανάγνωση από τον ίδιον καταχωρητή στο 2o μισό του ίδιου κύκλου.

9 © Repeat: lb r3,0(r1) sb r3,0(r2) beqz r3,Exit addi r1,r1,1 addi r2,r2,1 j Repeat Exit: η beqz δεν προκαλεί κίνδυνο ελέγχου, διότι υπάρχει πρόβλεψη διακλάδωσης η οποία γίνεται σωστά για την ακολουθία εντολών της άσκησης η j δεν προκαλεί κίνδυνο ελέγχου, διότι η διεύθυνση- στόχος της διακλάδωσης υπολογίζεται στο στάδιο IF, και η εκτέλεση μπορεί να συνεχίσει από τον επόμενο κύκλο χωρίς stalls

10 © κύκλοι για την αντιγραφή ενός χαρακτήρα (γενική περίπτωση)

11 © Για την ίδια ακολουθία εντολών, δείξτε όπως και πριν τον χρονισμό του pipeline, θεωρώντας όμως τώρα ότι υπάρχουν όλα τα δυνατά σχήματα προώθησης. Πόσοι κύκλοι απαιτούνται κατά μέσο όρο για την αντιγραφή ενός χαρακτήρα;

12 © εξαλείφονται τα stalls της προηγούμενης περίπτωσης 6 κύκλοι για την αντιγραφή ενός χαρακτήρα

13 © Επεκτείνουμε την παραπάνω αρχιτεκτονική σωλήνωσης διπλασιάζοντας το εύρος της σωλήνωσης. Αναδιατάξτε την ακολουθία των εντολών των προηγούμενων ερωτημάτων ώστε να είναι δυνατόν να εκτελεστεί αποδοτικά σύμφωνα με τα νέα δεδομένα. Δείξτε τον χρονισμό του pipeline, θεωρώντας όλα τα δυνατά σχήματα προώθησης, και υποδείξτε τα σημεία όπου γίνεται προώθηση. Πόσοι κύκλοι απαιτούνται κατά μέσο όρο για την αντιγραφή ενός χαρακτήρα;

14 © Repeat: lb r3,0(r1) sb r3,0(r2) beqz r3,Exit addi r1,r1,1 addi r2,r2,1 j Repeat Exit: Αναδιάταξη εντολών για αποδοτική εκτέλεση στη διπλή σωλήνωση: οι εντολές να είναι κατά το δυνατόν ανά 2 ανεξάρτητες ώστε να μπορούν να εκτελεστούν παράλληλα δεν πρέπει να επηρεάζεται η σημασιολογία του προγράμματος Repeat: lb r3,0(r1) addi r1,r1,1 sb r3,0(r2) addi r2,r2,1 beqz r3,Exit j Repeat Exit:

15 © κύκλοι για την αντιγραφή ενός χαρακτήρα

16 © Για να βελτιώσουμε κι άλλο την απόδοση, εφαρμόζουμε την τεχνική του ξεδιπλώματος βρόχων (loop unrolling). Για την ακολουθία εντολών των προηγούμενων ερωτημάτων εφαρμόστε unrolling 2 φορές. Θεωρείστε ότι έχετε πάλι διπλή σωλήνωση όπως και πριν, οπότε φροντίστε να αναδιατάξετε όπου είναι δυνατόν την ακολουθία, επιτυγχάνοντας το μέγιστο δυνατό παραλληλισμό. Δείξτε τον χρονισμό του pipeline, θεωρώντας όλα τα δυνατά σχήματα προώθησης, και υποδείξτε τα σημεία όπου γίνεται προώθηση. Πόσοι κύκλοι απαιτούνται κατά μέσο όρο για την αντιγραφή ενός χαρακτήρα;

17 © Loop unrolling k φορές: επαναλαμβάνουμε το «σώμα» του loop k φορές, ώστε να αντιγράφονται k διαδοχικοί χαρακτήρες σε μια επανάληψη του loop αυξάνουμε τις μεταβλητές δεικτοδότησης ώστε να δείχνουν στον χαρακτήρα που βρίσκεται k θέσεις μπροστά από τον τρέχοντα Repeat: lb r3,0(r1) sb r3,0(r2) beqz r3,Exit addi r1,r1,1 addi r2,r2,1 j Repeat Exit: Repeat: lb r3,0(r1) sb r3,0(r2) beqz r3,Exit lb r3,1(r1) sb r3,1(r2) beqz r3,Exit addi r1,r1,2 addi r2,r2,2 j Repeat Exit: Repeat: lb r3,0(r1) addi r1,r1,2 sb r3,0(r2) addi r2,r2,2 beqz r3,Exit lb r3,-1(r1) sb r3,-1(r2) beqz r3,Exit j Repeat Exit: Αρχικός κώδικας (k=1)Unrolled (k=2)Unrolled και αναδιατεταγμένος

18 © η επόμενη εντολή της «j Repeat» μπορεί να αρχίσει να εκτελείται στον 6 ο κύκλο, και στην 1 η σωλήνωση (διότι αυτή δεν έχει stalls) απαιτούνται κατά μέσο όρο 5/2 = 2.5 κύκλοι για την αντιγραφή ενός χαρακτήρα

19 © Άσκηση 2: caches

20 © Θεωρούμε το ακόλουθο κομμάτι κώδικα int i,j; double result, a[110][4]; for(i=0; i<4; i++) for(j=0; j<100; j++) result += a[j][i]*a[j+1][i] + 0.5; Υποθέσεις κάθε στοιχείο του πίνακα έχει μέγεθος 8 bytes υπάρχει 1 επίπεδο κρυφής μνήμης, πλήρως συσχετιστικής, με LRU πολιτική αντικατάστασης, αποτελούμενη από 100 blocks δεδομένων το μέγεθος του block είναι 32 bytes ο πίνακας είναι αποθηκευμένος στην κύρια μνήμη κατά γραμμές, και είναι «ευθυγραμμισμένος» ώστε το 1 ο στοιχείο του να απεικονίζεται στην αρχή μιας γραμμής της cache αρχικά η cache είναι άδεια

21 © Βρείτε ποιες από τις αναφορές στα στοιχεία του πίνακα a για όλη την εκτέλεση του παραπάνω κώδικα καταλήγουν σε misses στην cache. Υποδείξτε ποια είναι compulsory, ποια είναι capacity, και ποια conflict. Δώστε τον συνολικό αριθμό των misses.

22 © block = 32 bytes 1 στοιχείο = 8 bytes πίνακας αποθηκευμένος κατά γραμμές σε 1 block της cache θα απεικονίζονται 4 διαδοχικά στοιχεία του πίνακα, π.χ. a[i][j], a[i][j+1], a[i][j+2], a[i][j+3] επιπλέον πίνακας ευθυγραμμισμένος σε 1 block της cache θα απεικονίζεται 1 ολόκληρη γραμμή του πίνακα, δηλαδή a[i][j], a[i][j+1], a[i][j+2], a[i][j+3] όπου j%4=0

23 © αναφορά στη μνήμηπεριεχόμενα cache a[0][0]a[0][1]a[0][2]a[0][3] a[0][0]compulsory miss i=0,j=0 δηλαδή, αναφερόμαστε για 1 η φορά στα αντίστοιχα blocks…

24 © αναφορά στη μνήμηπεριεχόμενα cache a[0][0]a[0][1]a[0][2]a[0][3] a[1][0]a[1][1]a[1][2]a[1][3] a[0][0]compulsory miss i=0,j=0 a[1][0]compulsory miss

25 © αναφορά στη μνήμηπεριεχόμενα cache a[0][0]a[0][1]a[0][2]a[0][3] a[1][0]a[1][1]a[1][2]a[1][3] a[0][0]compulsory miss i=0,j=0 a[1][0]compulsory miss a[1][0]hit i=0,j=1

26 © αναφορά στη μνήμηπεριεχόμενα cache a[0][0]a[0][1]a[0][2]a[0][3] a[1][0]a[1][1]a[1][2]a[1][3] a[2][0]a[2][1]a[2][2]a[2][3] a[0][0]compulsory miss i=0,j=0 a[1][0]compulsory miss a[1][0]hit i=0,j=1 a[2][0]compulsory miss

27 © αναφορά στη μνήμηπεριεχόμενα cache a[0][0]a[0][1]a[0][2]a[0][3] a[1][0]a[1][1]a[1][2]a[1][3] a[2][0]a[2][1]a[2][2]a[2][3] a[0][0]compulsory miss i=0,j=0 a[1][0]compulsory miss a[1][0]hit i=0,j=1 a[2][0]compulsory miss Έτσι για i=0, j=2…99 θα έχουμε 1 hit + 1 comp. miss για κάθε επανάληψη του j

28 © αναφορά στη μνήμηπεριεχόμενα cache a[0][0]a[0][1]a[0][2]a[0][3] a[1][0]a[1][1]a[1][2]a[1][3] a[2][0]a[2][1]a[2][2]a[2][3] a[0][0]compulsory miss i=0,j=0 a[1][0]compulsory miss a[1][0]hit i=0,j=1 a[2][0]compulsory miss Έτσι για i=0, j=2…99 θα έχουμε 1 hit + 1 comp. miss για κάθε επανάληψη του j για i=0 θα έχουμε 2+99=101 misses, όλα compulsory

29 © αναφορά στη μνήμηπεριεχόμενα cache a[0][0]a[0][1]a[0][2]a[0][3] a[1][0]a[1][1]a[1][2]a[1][3] a[2][0]a[2][1]a[2][2]a[2][3] a[3][0]a[3][1]a[3][2]a[3][3] a[4][0]a[4][1]a[4][2]a[4][3] ………… a[98][0]a[98][1]a[98][2]a[98][3] a[99][0]a[99][1]a[99][2]a[99][3] a[99][0]compulsory miss i=0,j=99

30 © αναφορά στη μνήμηπεριεχόμενα cache a[100][0]a[100][1]a[100][2]a[100][3] a[1][0]a[1][1]a[1][2]a[1][3] a[2][0]a[2][1]a[2][2]a[2][3] a[3][0]a[3][1]a[3][2]a[3][3] a[4][0]a[4][1]a[4][2]a[4][3] ………… a[98][0]a[98][1]a[98][2]a[98][3] a[99][0]a[99][1]a[99][2]a[99][3] a[99][0]compulsory miss i=0,j=99 a[100][0]compulsory miss αντικατέστησε το LRU block που υπήρχε στην cache

31 © αναφορά στη μνήμηπεριεχόμενα cache a[100][0]a[100][1]a[100][2]a[100][3] a[0][0]a[0][1]a[0][2]a[0][3] a[2][0]a[2][1]a[2][2]a[2][3] a[3][0]a[3][1]a[3][2]a[3][3] a[4][0]a[4][1]a[4][2]a[4][3] ………… a[98][0]a[98][1]a[98][2]a[98][3] a[99][0]a[99][1]a[99][2]a[99][3] a[0][1]capacity miss i=1,j=0 διότι αντικαταστάθηκε λόγω έλλειψης χώρου το block που είχε έρθει στην cache κατά το παρελθόν και το περιείχε

32 © αναφορά στη μνήμηπεριεχόμενα cache a[100][0]a[100][1]a[100][2]a[100][3] a[0][0]a[0][1]a[0][2]a[0][3] a[1][0]a[1][1]a[1][2]a[1][3] a[3][0]a[3][1]a[3][2]a[3][3] a[4][0]a[4][1]a[4][2]a[4][3] ………… a[98][0]a[98][1]a[98][2]a[98][3] a[99][0]a[99][1]a[99][2]a[99][3] a[0][1]capacity miss i=1,j=0 a[1][1]capacity miss

33 © αναφορά στη μνήμηπεριεχόμενα cache a[100][0]a[100][1]a[100][2]a[100][3] a[0][0]a[0][1]a[0][2]a[0][3] a[1][0]a[1][1]a[1][2]a[1][3] a[3][0]a[3][1]a[3][2]a[3][3] a[4][0]a[4][1]a[4][2]a[4][3] ………… a[98][0]a[98][1]a[98][2]a[98][3] a[99][0]a[99][1]a[99][2]a[99][3] a[0][1]capacity miss i=1,j=0 a[1][1]capacity miss a[1][1]hit i=1,j=1

34 © αναφορά στη μνήμηπεριεχόμενα cache a[100][0]a[100][1]a[100][2]a[100][3] a[0][0]a[0][1]a[0][2]a[0][3] a[1][0]a[1][1]a[1][2]a[1][3] a[2][0]a[2][1]a[2][2]a[2][3] a[4][0]a[4][1]a[4][2]a[4][3] ………… a[98][0]a[98][1]a[98][2]a[98][3] a[99][0]a[99][1]a[99][2]a[99][3] a[0][1]capacity miss i=1,j=0 a[1][1]capacity miss a[1][1]hit i=1,j=1 a[2][1]capacity miss

35 © αναφορά στη μνήμηπεριεχόμενα cache a[100][0]a[100][1]a[100][2]a[100][3] a[0][0]a[0][1]a[0][2]a[0][3] a[1][0]a[1][1]a[1][2]a[1][3] a[2][0]a[2][1]a[2][2]a[2][3] a[4][0]a[4][1]a[4][2]a[4][3] ………… a[98][0]a[98][1]a[98][2]a[98][3] a[99][0]a[99][1]a[99][2]a[99][3] a[0][1]capacity miss i=1,j=0 a[1][1]capacity miss a[1][1]hit i=1,j=1 a[2][1]capacity miss Στις επόμενες επαναλήψεις θα έχουμε κυκλικές αντικαταστάσεις blocks, οπότε τα misses και τα hits θα ακολουθούν το ίδιο μοτίβο όπως και για i=0.

36 © αναφορά στη μνήμηπεριεχόμενα cache a[100][0]a[100][1]a[100][2]a[100][3] a[0][0]a[0][1]a[0][2]a[0][3] a[1][0]a[1][1]a[1][2]a[1][3] a[2][0]a[2][1]a[2][2]a[2][3] a[4][0]a[4][1]a[4][2]a[4][3] ………… a[98][0]a[98][1]a[98][2]a[98][3] a[99][0]a[99][1]a[99][2]a[99][3] a[0][1]capacity miss i=1,j=0 a[1][1]capacity miss a[1][1]hit i=1,j=1 a[2][1]capacity miss Στις επόμενες επαναλήψεις θα έχουμε κυκλικές αντικαταστάσεις blocks, οπότε τα misses και τα hits θα ακολουθούν το ίδιο μοτίβο όπως και για i=0. συνολικά θα έχουμε 4*101=404 misses

37 © αναφορά στη μνήμηπεριεχόμενα cache a[100][0]a[100][1]a[100][2]a[100][3] a[0][0]a[0][1]a[0][2]a[0][3] a[1][0]a[1][1]a[1][2]a[1][3] a[2][0]a[2][1]a[2][2]a[2][3] a[4][0]a[4][1]a[4][2]a[4][3] ………… a[98][0]a[98][1]a[98][2]a[98][3] a[99][0]a[99][1]a[99][2]a[99][3] a[0][1]capacity miss i=1,j=0 a[1][1]capacity miss a[1][1]hit i=1,j=1 a[2][1]capacity miss Conflict misses δεν έχουμε διότι η cache είναι fully associative → τα blocks δεδομένων μπορούν να απεικονιστούν οπουδήποτε στην cache

38 © To σύνολο εντολών της αρχιτεκτονικής του επεξεργαστή διαθέτει μία ειδική εντολή prf(*addr). H εντολή αυτή προ-φορτώνει στην κρυφή μνήμη ολόκληρο το μπλοκ που περιέχει τη λέξη που βρίσκεται στη διεύθυνση μνήμης addr. Χωρίς να αλλάξετε τη σειρά των loads για τις αναφορές στα στοιχεία του πίνακα, εισάγετε κλήσεις στην prf (1 ή περισσότερες) στον παραπάνω κώδικα ώστε να μειωθούν τα misses. Δώστε τον συνολικό αριθμό των misses. Υποθέστε ότι 7 επαναλήψεις του εσωτερικού loop είναι αρκετές ώστε να “καλυφθεί” ο χρόνος που απαιτείται για να έρθουν τα δεδομένα που ζητά η prf στην cache. Mη λάβετε ειδική μέριμνα για την προφόρτωση δεδομένων στις αρχικές επαναλήψεις του loop, ούτε για τις έξτρα προφορτώσεις στις τελευταίες επαναλήψεις.

39 © Ας δούμε τις αναφορές σε στοιχεία του πίνακα για τις πρώτες επαναλήψεις του loop: (i,j)= (0,0):a[0][0] miss, a[1][0] miss (0,1):a[1][0] hit, a[2][0] miss (0,2):a[2][0] hit, a[3][0] miss (0,3):a[3][0] hit, a[4][0] miss (0,4):a[4][0] hit, a[5][0] miss (0,5):a[5][0] hit, a[6][0] miss (0,6):a[6][0] hit, a[7][0] miss (0,7):a[7][0] hit, a[8][0] miss (0,8):a[8][0] hit, a[9][0] miss οι πρώτες επαναλήψεις που χρειάζονται για να καλύψουν χρονικά τη μεταφορά δεδομένων που ζητά η prf δηλαδή, αν η prf κληθεί στην (0,0), τότε τα δεδομένα που ζήτησε θα έρθουν στην (0,7) για ποιες αναφορές θα εφαρμόσουμε προφόρτωση; για εκείνες που καταλήγουν σε misses (a[j+1][i]) έτσι, στην επανάληψη (0,0) πρέπει να ζητήσουμε το a[8][0], στην (0,1) το a[9][0], κ.ο.κ.

40 © for(i=0; i<4; i++) for(j=0; j<100; j++) { prf(&a[j+8][i]); result += a[j][i]*a[j+1][i] + 0.5; } Έτσι, τα μόνα misses που συμβαίνουν σε κάθε επανάληψη είναι τα εξής: (i,j)= (0,0):a[0][0] miss, a[1][0] miss (0,1):a[1][0] hit, a[2][0] miss (0,2):a[2][0] hit, a[3][0] miss (0,3):a[3][0] hit, a[4][0] miss (0,4):a[4][0] hit, a[5][0] miss (0,5):a[5][0] hit, a[6][0] miss (0,6):a[6][0] hit, a[7][0] miss (0,7):a[7][0] hit, a[8][0] hit (0,8):a[8][0] hit, a[9][0] hit συνολικά, θα έχουμε 4*8=32 misses

41 © Υποθέστε τώρα ότι έχετε μια cache ίδιας οργάνωσης, αλλά “απείρου” μεγέθους. Πώς θα ξαναγράφατε τον κώδικα του ερωτήματος 2, μειώνοντας περαιτέρω τον αριθμό των κλήσεων στην prf; for(j=0; j<100; j++){ prf(&a[j+8][0]); result += a[j][0]*a[j+1][0] + 0.5; } for(i=1; i<4; i++) for(j=0; j<100; j++) result += a[j][i]*a[j+1][i] + 0.5; ξέρουμε ότι η cache είναι “απείρου” μεγέθους, οπότε οι επόμενες επαναλήψεις δεν οδηγούν σε capacity misses για να ελαχιστοποιήσουμε τα prefetches, εκτελούμε την 1 η μόνο επανάληψη του εξωτερικού βρόχου με prefetches και τις υπόλοιπες ως έχουν συνολικά, θα έχουμε 8 misses

42 © Θεωρείστε πάλι τον αρχικό κώδικα (χωρίς τις προφορτώσεις). Εκτός από την προφόρτωση δεδομένων, ποια άλλη γνωστή τεχνική βελτιστοποίησης θα εφαρμόζατε στον κώδικα ώστε να μειωθούν τα misses; for(i=0; i<4; i++) for(j=0; j<100; j++) result += a[j][i]*a[j+1][i] + 0.5; στο σώμα του loop δεν υπάρχουν εξαρτήσεις, επομένως μπορούμε να εφαρμόσουμε αναδιάταξη βρόχων (loop interchange) for(j=0; j<100; j++) for(i=0; i<4; i++) result += a[j][i]*a[j+1][i] + 0.5; τώρα ο πίνακας προσπελαύνεται όπως είναι αποθηκευμένος → καλύτερη τοπικότητα αναφορών, αφού γειτονικά στοιχεία προσπελαύνονται σε διαδοχικές επαναλήψεις του εσωτερικού loop misses συμβαίνουν όταν αναφερόμαστε στο πρώτο στοιχείο κάθε γραμμής (i=0) → συνολικά έχουμε 100 misses

43 ©


Κατέβασμα ppt "© 2006-07 Ασκήσεις στα Προηγμένα Θέματα Αρχιτεκτονικής Υπολογιστών ακ. έτος 2006-2007 Νεκτάριος Κοζύρης Νίκος Αναστόπουλος"

Παρόμοιες παρουσιάσεις


Διαφημίσεις Google