Τμήμα Ηλεκτρολόγων Μηχανικών και Μηχανικών H/Y Department of Electrical and Computer Engineering Οργάνωση και Σχεδίαση Η/Y (HY232) Εργαστήριο 8 Χειμερινό Εξάμηνο 2016-2017 1. Προσομοίωση λειτουργίας ιεραρχίας μνήμης (1 μονάδα) ποθέστε ότι κατά την εκτέλεση ενός κώδικα παράγονται οι ακόλουθες διαδοχικές διευθύνσεις μνήμης (στο δεκαδικό σύστημα), οι οποίες απευθύνονται σε μια κοινή κρυφή μνήμη εντολών και δεδομένων μεγέθους 64 bytes: 207, 212, 416, 289, 204, 222, 461, 109, 280, 303, 2, 480 Οι διευθύνσεις αυτές είναι διευθύνσεις bytes που προσπελαύνονται κατά τη φάση προσπέλασης μνήμης από εντολές προσπέλασης ενός byte. ποθέτοντας ότι η κρυφή μνήμη είναι αρχικά άδεια και ότι τα δεδομένα προσκομίζονται όταν απαιτούνται, βρείτε τι τιμές υπάρχουν στην cache (tag, valid bits, data array) μετά από τις παραπάνω προσπελάσεις. ποθέστε ότι η κύρια μνήμη έχει μέγεθος 512 bytes. Η μνήμη cache είναι 2-way set associative με cache block μεγέθους 4 bytes και LRU στρατηγική απελευθέρωσης. Σας συνιστώ να χρησιμοποιήσετε τους πίνακες στην διαφάνεια 23 της διάλεξης για την μνήμη cache για την επίλυση της άσκησης. Λύση Η διευθύνσεις του επεξεργαστή αυτού αναφέρονται σε μνήμη 512 bytes και άρα έχουν μέγεθος 9 bits, επειδή 2 9 = 512. Χωρίζονται σε τρία πεδία όπως έχουμε ήδη αναλύσει και στο μάθημα ως εξής: Tag = 4 Set index = 3 Byte offset = 2 H οργάνωση της cache θα έχει 64/4 = 16 blocks που αντιστοιχούν σε 16/2=8 sets επειδή η cache είναι 2-way set associative. Τα 9 bits της διεύθυνσης είναι χωρισμένα ως εξής: Byte Offset = 2 bits, Set Index = 3 bits, Tag = 9-3-2 = 4 bits. Τα blocks που είναι LRU (Least Recently Used) είναι σε italics στους παρακάτω πίνακες. [1]
011 Index Valid Tag Data Y 0 Mem[204..207] Index Valid Tag Data Y 0 Mem[204..207] Y 0 Mem[212..215] Y 1 Mem[416..419] Y 1 Mem[416..419] Y Y 1 Mem[288..291] Y 0 Mem[204..207] Y 0 Mem[204..207] Y 0 Mem[212..215] Y 0 Mem[212..215] 000 Hit Y 1 Mem[416..419] Y 1 Mem[416..419] Y 1 Mem[288..291] Y 1 Mem[288..291] Y 0 Mem[204..207] Y 0 Mem[204..207] Y 0 Mem[212..215] Y 0 Mem[212..215] [2]
Y Y 1 Y 0 Mem[220223] 461= Y 1 Mem[416..419] 109= Y 1 Mem[416..419] Y 1 Mem[288..291] Y 1 Mem[288..291] Mem[204..207] Y 0 Mem[204..207] Y 0 Mem[108..] Y 0 Mem[460..463] Y 0 Mem[460..463] Y 0 Mem[212..215] Y 0 Mem[212..215] Y 1 Y 1 Y 0 Mem[220223] Y 0 Mem[220223] Y 1 Mem[416..419] Y 1 Mem[416..419] Y 1 Mem[288..291] Y 1 Mem[288..291] Mem[460..463] Y 0 Mem[108..] Y 0 Mem[108..] Y 0 Mem[460..463] Y 0 Mem[300..303] Y 0 Mem[212..215] Y 0 Mem[212..215] Y 1 Y 1 1 Mem[280..283] 1 Mem[280..283] Y 0 Mem[220223] Y 0 Mem[220223] [3]
Mem[416..419] Y 0 Mem[0..3] Y 0 Mem[4..7] Y 1 Mem[288..291] Y 1 Mem[480..483] Mem[288..291] Y 0 Mem[108..] Y 0 Mem[108..] Y 0 Mem[300..303] Y 0 Mem[300..303] Y 0 Mem[212..215] Y 0 Mem[212..215] Y 1 Y 1 1 Mem[280..283] 1 Mem[280..283] Y 0 Mem[220223] Y 0 Mem[220223] 2. Χαρακτηριστικά της μνήμης cache (1,5 μονάδα) Σας δίνουμε τις 4 παρακάτω ακολουθίες διευθύνσεων που δημιουργούνται από τις εντολές load ενός προγράμματος που εκτελείται σε έναν επεξεργαστή με Data Cache. Η τελευταία στήλη του πίνακα δείχνει το cache hit ratio για κάθε ακολουθία. Χρησιμοποιώντας αυτήν την πληροφορία, η άσκηση αυτή σας ζητάει να υπολογίσετε τις παρακάτω παραμέτρους της Data Cache, θεωρώντας ότι αρχικά η Cache είναι κενή. Associativity A: 1, 2 ή 4-way Μέγεθος του Cache Block B: 1, 2, 4, 8, 16 ή 32 bytes Μέγεθος της Cache S: 256 ή 512 bytes Πολιτική αντικατάστασης ενός cache block: LRU ή FIFO (το πρώτο χρονικά στοιχείο που μπήκε στο set θα φύγει). Σημειώστε ότι οι παρακάτω διευθύνσεις είναι σε bytes και ότι όλες οι προσπελάσεις της μνήμης διαβάζουν ένα byte. Ακολουθία # Διευθύνσεις Cache Hit Ratio 1 0, 2, 4, 7, 32, 40 33% 2 0, 512, 1024, 1536, 2048, 1536, 1024, 512, 0, 1024 10% 3 0, 64, 128, 256, 512, 256, 128, 64, 0, 512 30% 4 0, 512, 1024, 0, 1536, 0, 2048, 0 25% Λύση Συνήθως σε τέτοιες ασκήσεις ξεκινάμε την αναζήτηση μας από το μέγεθος του cache block Β που είναι και πιο εύκολο να υπολογισθεί. Δοκιμές τύπου trial-and-error βοηθάνε στην επίλυση της άσκησης. Το μέγεθος της cache είναι τουλάχιστον 256 bytes σύμφωνα με την εκφώνηση. Η πρώτη ακολουθία μας λέει ότι μόνο 2 από τις 6 προσπελάσεις είναι HIT, και αυτές δεν μπορεί να είναι παρά η 2 και η 7. Αυτό σημαίνει ότι το Β πρέπει να είναι 4. Κάθε [4]
μέγεθος του B μικρότερο από 4 συνεπάγεται μικρότερο Hit Ratio, ενώ μεγαλύτερο του 4 συνεπάγεται μεγαλύτερο Hit Ratio. Άρα, B=4. Επειδή το μέγεθος της cache είναι τουλάχιστον 256 bytes και το μέγεθος κάθε block B=4, μπορούμε εύκολα να διαπιστώσουμε ότι όλες οι διευθύνσεις της ακολουθίας 2 θα αποθηκευτούν στο set 0 της cache. Οι 5 πρώτες προσπελάσεις της ακολουθίας 2 (0, 512, 1024, 1536, 2048) θα είναι σίγουρα es. Είναι εύκολο να διαπιστώσουμε ότι εάν A=1 θα έχουμε συνολικά 0 Hits, αν Α=2, θα έχουμε 1 Hit (η δεύτερη 1536), ενώ εαν Α=4 θα έχουμε 4 Hits. Ο μόνος τρόπος να έχουμε 1 hit, είναι η Data Cache να είναι 2-way set associative. Άρα, Α=2. Επειδή B=4 και A=2, μπορούμε να δούμε ποιο θα είναι το Hit Rate για τα δύο πιθανά μεγέθη της cache. Για 512 bytes, θα έχουμε 3 hits σε 10 προσπελάσεις και για 256 bytes θα έχουμε 2 hits. Άρα, S=512. Η Data Cache μας έχει μέγεθος 512 bytes, που είναι οργανωμένα σε 64 sets ή 128 blocks που το κάθε block είναι 4 bytes. Στην 4 η ακολουθία όλες οι διευθύνσεις αποθηκεύονται στο set 0. Προσομοιώνοντας τις δύο περιπτώσεις (LRU και FIFO), διαπιστώνουμε ότι η LRU δίνει 2 hits στα 8 (0,25), ενώ η FIFO δίνει 1 hit στα 8. Συνεπώς η πολιτική αντικατάστασης ενός cache block είναι LRU. 3. Συμπεριφορά κώδικα σε ιεραρχία μνήμης (1,5 μονάδα) O παρακάτω κώδικας εκτελείται σε ένα σύστημα με L1 Data Cache 16ΚΒ, direct-mapped με 32-byte blocks. Να υπολογίσετε πόσα cache misses (read και write) θα προκαλέσει συνολικά στην L1 Data Cache η εκτέλεση του παρακάτω κώδικα. Ποιο είναι το miss rate της L1 Data Cache; double a[3][], b[][3]; for (i = 0; i < 3; i++) for (j = 0; j < ; j++) a[i][j] = b[j][0] * b[j+1][0]; Λύση a[0][0] a[0][1] a[0][2] a[0][3]. a[0][98] a[0][99] a[1][0] a[1][1] a[1][2] a[1][3] a[1][98] a[1][99] a[2][0] a[2][1] a[2][2] a[2][3] a[2][98] a[2][99] b[0][0] b[1][0] b[j][0] b[j+1][0] b[][0] b[0][1] b[1][1] b[j][1] b[j+1][1] b[][1] Ο πίνακας a[][] γράφεται ανά γραμμή με αποτέλεσμα να έχουμε πολύ καλή εκμετάλλευση της χωρικής τοπικότητας του. Επειδή το μέγεθος του cache block της L1 DCache είναι 32 bytes, μπορούμε να χωρέσουμε 4 στοιχεία του πίνακα a[][] ανά cache block (οι πίνακες είναι double και κάθε στοιχείο του πίνακα είναι 8 bytes). To στοιχείο a[][] με j=4k θα είναι miss, ενώ όλα τα στοιχεία a[][] με διαφορετικό j θα είναι hit. Επειδή έχουμε συνολικά 3* προσπελάσεις του πίνακα a στον κώδικά μας, θα υπάρχουν 300/4 = 75 misses μόνο λόγω του πίνακα a. [5]
Σε αντιδιαστολή με τον a, ο πίνακας b προσπελαύνεται ανά στήλη και μάλιστα τα ίδια στοιχεία προσπελαύνονται ανεξάρτητα από το iteration του εξωτερικού loop. H πρώτη εκτέλεση του εσωτερικού loop (j=0) δημιουργεί 2 misses (b[j][0] και b[j+1][0]). Η δεύτερη εκτέλεση του εσωτερικού loop (j=1) δημιουργεί μόνο 1 miss στο b[j+1][0] επειδή το b[j][0] έχει γίνει ήδη fetched από την εκτέλεση του loop για j=0. To ίδιο συμβαίνει για όλες τις τιμές του j=1..99. Συνεπώς η προσπέλαση του πίνακα b δημιουργεί 2+99 = read misses σε συνολικά 2*3* = 600 προσπελάσεις. Συνολικά λοιπόν, η εκτέλεση του παραπάνω κώδικα δημιουργεί 75+ = 176 misses. Το συνολικό miss rate είναι 176/(300+600) = 19.55%. [6]