Προηγμένοι Επεξεργαστές Μετά τον 80386 Γεώργιος Κεραμίδας
Περιεχόμενα Αρχιτεκτονική και ο νόμος του Moore ISA Ο πόλεμος των σετ εντολών: RISC εναντίον CISC Από το μικροκώδικα στο pipelining 80386 -> 80486 Σπάζοντας το φράγμα του 1 IPC: superscalar 80486 -> Pentium Το επόμενο βήμα: out-of-order execution Pentium -> Pentium Pro/ΙΙ/ΙΙΙ, Pentium 4 Μνήμη Caches Κατανάλωση Ισχύος Multicore Architectures: Why? The challenges
Αρχιτεκτονική και ο Νόμος του Moore Νόμος του Moore Ο αριθμός των τρανζίστορ στα ολοκληρωμένα κυκλώματα διπλασιάζεται κάθε ~ 2 χρόνια Intel 4004 (1971): 2300, Pentium 4 (2001): 55.000.000
Αρχιτεκτονική και ο Νόμος του Moore Στην πραγματικότητα η απόδοση (ταχύτητα επεξεργασίας για συγκεκριμένα προγράμματα) των επεξεργαστών διπλασιάζεται σε λιγότερο από 2 χρόνια Σε λιγότερο από 2 χρόνια θα κάνουμε τόση πρόοδο όση κάναμε στα προηγούμενα 28 χρόνια... (σωστό πριν 2005) Είναι αυτό αποτέλεσμα του νόμου του Moore? Μικρότερα τρανζίστορ = πιο γρήγορα τρανζίστορ = πιο πολλά MHz = απόδοση? OXI
Αρχιτεκτονική και ο Νόμος του Moore Η αρχιτεκτονική είναι αυτή που μεταφράζει τα κέρδη στην πυκνότητα και ταχύτητα των τρανζίστορ σε κέρδη στην απόδοση του επεξεργαστή. Παράδειγμα 1: Το χάσμα της μνήμης (memory gap/wall) Την εποχή του Intel 8086 η μνήμη DRAM ήταν πιο γρήγορη από τον επεξεργαστή. Ένα LOAD πιο γρήγορο από ένα ADD. Σήμερα ένα LOAD ~ 200 κύκλους του επεξεργαστή, ίσως ~ 400 εντολές (ADD)! Αλλά η αναλογία των LOAD στα προγράμματα παραμένει η ίδια Λύση? Αρχιτεκτονική: Cache memories, κρυφές γρήγορες μνήμες κάνουν τη DRAM να φαίνεται γρήγορη...
Μνήμη Memory Bottleneck Το χάσμα της Μνήμης (Memory Wall, Memory Gap) H ταχύτητα των επεξεργαστών αυξάνεται πολύ πιο πολύ από αυτή της μνήμης (DRAM) CPU 2x/2 χρόνια DRAM 2x/10 χρόνια Το χάσμα αυξάνεται 50% το χρόνο
Αρχιτεκτονική και ο Νόμος του Moore Παράδειγμα 2: παραλληλισμός στην εκτέλεση εντολών Την εποχή του Intel 8086 μια εντολή χρειαζόταν πολλούς κύκλους για να εκτελεστεί Ένας Pentium 4 μπορεί να εκτελέσει ταυτόχρονα στον ίδιο κύκλο 6 εντολές Εάν δεν μπορούσαμε να εκτελέσουμε πολλές εντολές κάθε κύκλο η αύξηση της απόδοσης θα υπολείπονταν της αύξησης συχνότητας (που έτσι και αλλιώς είναι μικρότερη από 2x/2,5χρόνια). Instruction Level Parallelism or ILP Αυτά τα δύο παραδείγματα αποτελούν την ουσία της σύγχρονής αρχιτεκτονικής
Σετ εντολών Η αρχιτεκτονική του σετ εντολών (ISA) ενός επεξεργαστή είναι το interface με τον έξω κόσμο. Το σετ εντολών καθώς, η διαχείριση μνήμης (virtual memory) και ο χειρισμός των διακοπών (interrupts) ορίζουν την συμπεριφορά του επεξεργαστή. Έχει σημασία το σετ εντολών για το πόσο εύκολο είναι αρχιτεκτονικά να αποσπάσουμε την μέγιστη απόδοση από έναν επεξεργαστή?
Σετ εντολών Τη δεκαετία του 80 οι μικροεπεξεργαστές με αρχηγό την Intel αλλά και άλλους (π.χ. Moto. 68000, Nat. Semi. 32032) ακολουθούσαν τις IBM, DEC VAX-11 και ολοένα παρουσίαζαν πιο πολύπλοκα σετ εντολών Οι εντολές γινόταν όλο και πιο σύνθετες, πλησιάζοντας τις γλώσσες υψηλού επιπέδου («semantic gap», VAX 11) Η αποκορύφωση ήταν ο Intel 432, ένας φοβερά πολύπλοκος επεξεργαστής και μια φοβερή εμπορική αποτυχία της Intel.
Σετ εντολών Επικρατούσα αρχιτεκτονική: αρχιτεκτονική με μικροκώδικα: ένα μικροπρόγραμμα που έτρεχε συνεχώς σε ένα υποτυπώδη κρυφό επεξεργαστή διάβαζε τις (μακρο)εντολές του προγράμματος μια-μια και ενορχήστρωνε την εκτέλεσή τους κατευθείαν πάνω στο υλικό χρησιμοποιώντας όμως πολλούς κύκλους για κάθε μακροεντολή Δεδομένου του περιορισμένου αριθμού τρανζίστορ Αύξηση της πολυπλοκότητας του σετ εντολών με μεγαλύτερο μικροκώδικα Δυνατότερες εντολές = καλύτερη απόδοση? CISC
Σετ εντολών RISC: Αντίδραση στην αύξηση της πολυπλοκότητας ήρθε από το Stanford (MIPS) και το Berkeley (RISC-I, RISC-II, SUN SPARC) Δεδομένου του περιορισμένου αριθμού τρανζίστορ Αύξηση της απόδοσης με απλούστερο σετ εντολών (στα βήματα των CRAY επεξεργαστών) Mικροεντολές -> σετ εντολών
RISC εναντίων CISC RΙSC CISC Διαφορά σε 32 bit Μεταβλητού μήκους Decode Εντολές Ομοιόμορφες Πολλές μορφές Decode Απλές Πολύπλοκες Execute Καταχωρητές Πολλοί Λίγοι Pipelining Addressing Modes Λίγα Πολλά Decode Απλά Πολύπλοκα Execute Χρήσιμα σε Αχρησιμοποίητα από compilers compilers Εκτέλεση Load-store Memory-memory Pipelining
RISC εναντίων CISC IA-32, x86(cisc) Εσωτερική μετάφραση σε RISC μ-ops P-PRO/II/III/4 Μεταβλητού μήκους Σταθερού μήκους 118bit Εντολές Πολλές μορφές - Πολύπλοκες Απλές Καταχωρητές Λίγοι (αρχιτεκτονικοί) Addressing Πολλά Modes Πάρα πολλοί εσωτερικοί (physical registers) Πολύπλοκα Μετάφραση σε πράξεις με διευθύνσεις Αχρησιμοποίητα από compilers Εκτέλεση Memory-memory Load-store εσωτερικα
Η κατάληξη Παρόλο που το RISC ήταν πολύ επιτυχημένο την εποχή που παρουσιάστηκε (2,6x RISC advantage), το CISC κατόρθωσε να επιζήσει και να επικρατήσει Το CISC μπόρεσε να εκμεταλλευτεί όλες τις καινοτομίες του RISC, κυρίως ΟΟΟ, caches Η αρχιτεκτονική όπως εκφράζεται σήμερα αναφέρεται στο εσωτερικό RISC πυρήνα των επεξεργαστών (είτε είναι Pentium 4 είτε οτιδήποτε άλλο) Το εξωτερικό σετ εντολών δεν καθορίζει πια την εσωτερική αρχιτεκτονική ενός επεξεργαστή Itanium: μεταφράζει το ΙΑ-32(x86) στο δικό του σετ εντολών (VLIW) και μετά το εκτελεί!
Περιεχόμενα Αρχιτεκτονική και ο νόμος του Moore Σετ εντολών Ο πόλεμος των σετ εντολών: RISC εναντίον CISC Από το μικροκώδικα στο pipelining 80386 -> 80486 Σπάζοντας το φράγμα του 1 IPC: superscalar 80486 -> Pentium Το επόμενο βήμα: OOO, Εκτέλεση Εκτός Σειράς Pentium -> Pentium Pro/2/3, Pentium IV Μνήμη Caches Κατανάλωση Ισχύος
Από τον μικροπρογραμματισμό στο pipelining: 80386 -> 80486 80386 (1986), IA-32, x86 8 registers Αρχιτεκτονική μικροκώδικα ένα μικροπρόγραμμα τρέχει συνεχώς σε ένα υποτυπώδη κρυφό επεξεργαστή, διαβάζει τις x86 εντολές του προγράμματος μια-μια και ενορχηστρώνει την εκτέλεσή τους κατευθείαν πάνω στο υλικό, χρησιμοποιώντας όμως πολλούς κύκλους για κάθε x86 εντολή π.χ. fetch - decode - execute
80386 sum=0 for i=0 to 10 sum+=a[i] i1 r1=0 /* index */ i2 r0=0 /* sum */ i3 loop:r2=mem[a+r1] /* a[i] */ i4 r0=r0+r2 i5 r1=r1+1 i6 r3=(r1!= 10) i7 if(r3==true) goto loop r2=mem[a+r1] r0 = r0 + r2 r1 = r1 + 1 r3 = r1!=10 fetch i4 decode i4 r0=r0+r2 fetch i5 decode i5 r1=r1 + r2 1 2 3 4 5 6
Πως εκτελούμαι ένα πρόγραμμα Τα προγράμματα είναι στην μνήμη Τα προγράμματα περιέχουν εντολές (instructions) και δεδομένα (data) Βασικά βήματα: instruction fetch και instruction execution 18
How to Execute a Stored Program Εντολές γίνονται fetched και αποθηκεύονται σε special registers Εντολές γίνονται decoded και αποφασίζονται τα επόμενα βήματα Η επόμενη εντολή γίνεται fetched 19
Το Pipeline Τι είναι τελικά ένα παράλληλο σύστημα? A, B, C something C, B, A
Το Pipeline Τι είναι τελικά ένα παράλληλο σύστημα? 1 ms A, B, C something C, B, A Το target frequency? 0.1MHz ή 100KHz
Pipeline Basics Τι είναι τελικά ένα παράλληλο σύστημα? 0.2 ms 0.3 ms 0.5 ms A, B, C C1 C2 C3 C, B, A Πόσο είναι το target frequency τώρα? Είναι το σύστημα παράλληλο? Είναι πιο γρήγορο? Ποια είναι η διαφορά ανάμεσα στο latency και throughput? Είναι ιδανικό σενάριο: χρειαζόμαστε και pipeline registers.
Pipelining Pipelining increases throughput and not latency Each instruction is executed slower in the pipeline compared to the non-pipeline architecture (e.g., 3 cycles) 1000 instructions 1002 cycles (no pipelining 3000 cycles). Limit: 1 instruction per cycle 1 ms A, B, C something C, B, A 0.2 ms 0.3 ms 0.5 ms A, B, C C1 C2 C3 C, B, A
Instruction Execution Time Γιατί υπάρχουν τα κενά? -Ένας απλός λόγος: μία εντολή μπορεί να χρειάζεται τα αποτελέσματα μιας προηγούμενης εντολής
Κενά (Bubbles) Instruction 1 Παράδειγμα: Instruction 1: ADD R1,R2, R3 (R1 R2 + R3) Instruction 2: ADD R5,R2, R4 (R5 R2 + R4) Εντολές σε pipelined Example 2 Instruction 1: ADD R1,R2, R3 (R1 R2 + R3) Instruction 2: ADD R5,R1, R4 (R5 R1 + R4) Εντολές ΌΧΙ σε pipelined Instruction 2 Instruction 3 Instruction 4 Instruction 5 Instruction 6 Instruction 7 Instruction 8 25
Instruction Execution Time Γιατί υπάρχουν τα κενά? -Ένας απλός λόγος: μία εντολή μπορεί να χρειάζεται τα αποτελέσματα μιας προηγούμενης εντολής
Superscalar Issue Time Το Superscalar είναι πιο γρήγορο (μικρότερος χρόνος εκτέλεσης), αλλά χαμηλότερο utilization. Μεγάλο θέμα: Τι γίνεται με το power?
Ποιο είναι πιο γρήγορο, Ποιο πιο low power? Time 1GHz 0.5 GHz 0.8 GHz
Από τον μικροπρογραμματισμό στο pipelining: 80386 -> 80486 80486 (1989) 1.000.000 τρανζίστορ, 2ο chip με > 1M τρανζίστορ (πρώτο με διαφορά μηνών το i860) Αρχιτεκτονική Pipeline/μικροκώδικα Pipeline: επικάλυψη των σταδίων εκτέλεσης των εντολών (π.χ. Fetch, decode, execute) Σαν τις αλυσίδες παραγωγής αυτοκινήτων (π.χ., αμάξωμα, σαλόνι, μηχανή, βάψιμο) Ποιες εντολές εκτελούνται στο pipleline του 80486? Απλές, RISC-like, οι υπόλοιπες με μικροκώδικα Pipeline παράδειγμα fetch - decode - execute (στον 80486 5 στάδια)
80486 sum=0 for i=0 to 10 sum+=a[i] i1 r1=0 /* index */ i2 r0=0 /* sum */ i3 loop:r2=mem[a+r1] /* a[i] */ i4 r0=r0+r2 i5 r1=r1+1 i6 r3=(r1!= 10) i7 if(r3==true) goto loop r2=mem[a+r1] r0 = r0 + r2 r1 = r1 + 1 r3 = r1!=10 fetch i4 decode i4 r0=r0+r2 fetch i5 decode i5 r1=r1+1 fetch i6 decode i6 r3=r1!=10 1 2 3 4 5
Pipelining Το pipelining βελτιώνει μόνο το Ρυθμό (throughput) ΟΧΙ την καθυστέρηση (latency) η κάθε εντολή είναι όσο αργή ήταν και πριν (π.χ. 3κ.) 1000 εντολές 1002 κύκλους (χωρίς pipelining 3000 κύκλους). ΟΡΙΟ 1 εντολή ανά κύκλο. Απαράβατος Κανόνας: διατηρούνται τα Sequential Semantics, εντολές εκτελούνται με τη σειρά που εμφανίζονται στο πρόγραμμα
Pipelining Το pipeline πρέπει να είναι ΠΑΝΤΑ γεμάτο Data hazzards RAW: read after write δεν μπορούμε να εκτελέσουμε αν το αποτέλεσμα δεν είναι έτοιμο load X; A=A+X; Control Hazzards Δεν μπορούμε να αποφασίσουμε γρήγορα από που θα κάνουμε fetch Βλέπε branch prediction
80486: RAW pipeline bubble sum=0 for i=0 to 10 sum+=a[i] i1 r1=0 /* index */ i2 r0=0 /* sum */ i3 loop:r2=mem[a+r1] /* a[i] */ i4 r0=r0+r2 i5 r1=r1+1 i6 r3=(r1!= 10) i7 if(r3==true) goto loop r2=mem[a+r1] r0 = r0 + r2 r1 = r1 + 1 r3 = r1!=10 fetch i3 decode i3 r2=[a+r1] fetch i4 decode i4 STALL r0=r0+r2 fetch i5 decode i5 STALL 1 2 3 4 5
80486: JMP pipeline bubble sum=0 for i=0 to 10 sum+=a[i] i1 r1=0 /* index */ i2 r0=0 /* sum */ i3 loop:r2=mem[a+r1] /* a[i] */ i4 r0=r0+r2 i5 r1=r1+1 i6 r3=(r1!= 10) i7 if(r3==true) goto loop fetch i7 decode i7 jmp i3 fetch i8 decode i8 KILL fetch i9 KILL KILL 1 2 3 fetch 4 i3 decode 5 i3
Superscalar: 80486 -> Pentium Pentium 1993, 3.100.000 τρανζίστορ με 16KB cache Ορισμός του superscalar: διαδοχικές εντολές παράλληλα Εκτέλεση σε σειρά, μέχρι 2 εντολές τον κύκλο Δύο pipelines, 5-στάδια το κάθε ένα Ασύμμετρα pipelines: το ένα πιο ικανό από το άλλο Εύκολες, ανεξάρτητες διαδοχικές εντολές παράλληλα, διαφορετικά μία-μία στο κύριο pipeline
Inorder Pipelines IF IF IF D1 D1 D1 D2 D2 D2 EX EX EX WB WB WB Intel i486 U - Pipe V - Pipe Intel Pentium (2 i486 pipelines)
Pentium sum=0 for i=0 to 10 sum+=a[i] i1 r1=0 /* index */ i2 r0=0 /* sum */ i3 loop:r2=mem[a+r1] /* a[i] */ i4 r0=r0+r2 i5 r1=r1+1 i6 r3=(r1!= 10) i7 if(r3==true) goto loop r2=mem[a+r1] r0 = r0 + r2 r1 = r1 + 1 r3 = r1!=10 fetch i3 decode i3 r2=m[a+r1] fetch i4 fetch i5 decode i4 decode i5 r0=r0+r2 r1=r1+1 fetch i6 decode i6 r3=r1!=10 1 2 3 4 5
Superscalar: 80486 -> Pentium Τι υλικό χρειάζεται για superscalar? Στο decode πρέπει να αποφασίσουμε αν οι εντολές μπορούν να εκτελεστούν παράλληλα Ανεξαρτησία εντολών: Εξάρτηση των εντολών εκδηλώνεται μέσα από την εγγραφή/ανάγνωση καταχωρητών: RAW: Μια εντολή χρειάζεται το αποτέλεσμα μιας άλλης WAR, WAW hazards (κίνδυνοι) resource hazards: αν οι εντολές χρειάζονται τους ίδιους πόρους για την εκτέλεσή τους Control Hazzards
Data Dependacies Η J είναι data dependent από την I: H J προσπαθεί να διαβάσει τον source operand πριν τον γράψει η I I: add r1,r2,r3 J: sub r4,r1,r3 η J είναι data dependent από την Κ, η οποία είναι data dependent από την I (αλυσίδα εξαρτήσεων) Πραγματικές εξαρτήσεις (True Dependences) Προκαλούν Read After Write (RAW) hazards στο pipeline
Name Dependences (1): Anti-dependences Name dependences: όταν 2 εντολές χρησιμοποιούν τον ίδιο καταχωρητή ή θέση μνήμης ( name ), χωρίς όμως να υπάρχει πραγματική ροή δεδομένων μεταξύ τους Anti-dependence: η J γράφει τον r1 πριν τον διαβάσει η I I: sub r4,r1,r3 J: add r1,r2,r3 K: mul r6,r1,r7 Προκαλούν Write After Read (WAR) data hazards στο pipeline
Name Dependences (2): Output dependences Output dependence: η J γράφει τον r1 πριν τον γράψει η I I: sub r1,r4,r3 J: add r1,r2,r3 K: mul r6,r1,r7 Προκαλούν Write After Write (WAW) data hazards στο pipeline
Data Dependacies Δύο εντολές χρησιμοποιούν τον ίδιο register add R1, R2, R3 add R1, R2, R3 add R1, R2, R3 sub R2, R4, R1 sub R2, R4, R1 sub R2, R4, R1 or R1, R6, R3 or R1, R6, R3 or R1, R6, R3 read-after-write (RAW) True dependence (real) write-after-read (WAR) anti dependence (artificial false) write-after-write (WAW) output dependence (artificial - false) Πότε και Που συμβαίνουν τα WAR και WAW hazards? 42
OOO: Pentium->Pentium Pro/II/III Pentium Pro (1995) 5,5M τρανζίστορ (2x8KB L1) Pentium II (1997) 7,5M - 27,4M (2x16KB L1, 256KB L2) Pentium III (1999) 9,5M - 44M (2x16KB L1, 512KB L2) O πρώτος OOO επεξεργαστής. Dynamic Execution (Intel), Out-of-Order, Εκτέλεση εκτός σειράς προγράμματος ΟΟΟ? Σαν το SUPERSCALAR αλλά οι εντολές που εκτελούνται παράλληλα ΔΕΝ χρειάζεται να είναι διαδοχικές Μετάφραση των x86 εντολών σε RISC μ-ops 14 στάδια pipeline (12 σε σειρά 2 εκτός σειράς) μέχρι 5 μ-ops παράλληλα σε 5 FUs: 2 x ALU, LOAD, STORE, FPU
OOO: Pentium->Pentium Pro/II/III Γιατί χρειάζεται το ΟΟΟ? Δεν φτάνει μόνο το SUPERSCALAR? Ας πούμε ότι έχουμε 2 pipelines διαθέσιμα /* C =((A+1)/2)-((B+1)/2) */ i1 r1 = MEM[A] i2 r2 = r1+1 i3 r3 = r1/2 i4 r4 = MEM[B] i5 r5 = r4+1 i6 r6 = r5/2 i7 r7 = r3-r6 i8 MEM[C] = r7 SUPERSCALAR i1 i2 i3 i4 i5 i6 i7 i8 OOO i1 i4 i2 i5 i3 i6 i7 i8 Ο παραλληλισμός ΔΕΝ βρίσκεται σε διαδοχικές εντολές (που συνήθως εξαρτώνται η μια από την άλλη) ΑΛΛΑ ΠΙΟ ΜΑΚΡΥΑ
OOO: Pentium Pro/II/III sum=0 for i=0 to 10 sum+=a[i] i1 r1=0 /* index */ i2 r0=0 /* sum */ i3 loop:r2=mem[a+r1] /* a[i] */ i4 r0=r0+r2 i5 r1=r1+1 i6 r3=(r1!= 10) i7 if(r3==true) goto loop fetch i3 decode i3 r2=m[a+r1] fetch i4 decode i4 Stall fetch i5 decode i5 r1=r1+1 fetch i6 decode i6 Stall Commit r0=r0+r2 r3=r1!=10 Commit Commit Commit 1 2 3 4 5
Pentium Pro Pipeline (Conceptual) FRONT END EXEC FETCH DECODE DISPATCH EXECUTE Decoupled (διαφορετικός ρυθμός εκτέλεσης) Decoupled BACK END RETIRE (COMMIT)
Instruction Decode Μετατροπή x86 instructions σε μops (uops) Uops: 2-operand RISC instructions x86 (IA-32): add (eax), (ebx) MEM(eax) <- MEM(eax) + MEM(ebx) UOPS: ld guop0, (eax) ld guop1, (ebx) add guop0, guop1 sta eax std guop0 guop0 <- MEM(eax) guop1 <- MEM(ebx) guop0 <- guop0 + guop1 MEM(eax) <- guop0
AMD Instruction Decode X86 -> RiscOPs (πιο ισχυρά από τα uops) 2 ισχυρούς decoders vs. 3 της Intel
Multi2Sim Simulator Multi2Sim: multicore and multithreaded X86 binary compatibility Free simulator: Open source project http://www.multi2sim.org/ Χρησιμοποιείται από: Πανεπιστήμια Industry (π.χ. AMD)
x86 Timing Simulator
Memory Hierarchy
Memory Hierarchy
Το pipeline του Multi2Sim
CISC Decoding στο Multi2Sim Κάθε x86 εντολή είναι 1 μέχρι 15 bytes Περίπλοκες εντολές μετατρέπονται εσωτερικά σε micro-instructions (uops). Το Multi2Sim έχει το δικό του uop set Κάθε uop έχει το πολύ 4 output dependences (logical registers and status flags) Το πολύ ένας logical register σε αυτό το set
CISC Decoding στο Multi2Sim Το Multi2Sim έχει το δικό του uop set Ο μέγιστος αριθμός των input dependences για κάθε uop είναι 3 και μπορεί να αποτελείται από logical registers και status flags με το πολύ 2 logical registers.
Παράδειγμα 1 mov edx, DWORD [ebx-0x4] Διαβάζει ένα 32-bit αριθμό από την διεύθυνση ebx-4 και την αποθηκεύει στον edx 3 βήματα: Υπολογισμός του effective memory address Φόρτωση της τιμής Αποθήκευση του αποτελέσματος στον edx Τα βήματα ii και iii γίνονται παράλληλα
Παράδειγμα 1 (συνέχεια) mov edx, DWORD PTR [ebx-0x4] effaddr ea/ebx load edx/ea [0x8004300,4] // for debugging // Memory location // & size Ορολογία: odep1,odep2,.../idep1,idep2,... όπου idepxx input και odepyy output. Ο ea είναι εσωτερικός (μη-αρχιτεκτονικός) register
Παράδειγμα 2 add DWORD [ebx+0x8], eax Βήματα: Διαβάζει από την θέση μνήμης ebx+8 Προσθέτει με τον eax Αποθηκεύει πίσω στην μνήμη effaddr ea/ebx load data/ea [0x8004300,4] add data,eax store data,ea [0x800430,4]
Παράδειγμα 3 rep movsb Κάνει copy 1 byte από την θέση μνήμης που δείχνει ο esi στην θέση μνήμης που δείχνει ο edi. Το prefix rep επαναλαμβάνει την εντολή τόσες φορές όσο η τιμή του ecx. Σε κάθε επανάληψη ο esi και edi αυξάνονται ή μειώνονται κατά 1 (εξαρτάται από την τιμή του flag DF).
Παράδειγμα 3 (συνέχεια) rep movsb load aux/esi [0x80d789f,1] store edi,aux [0x80d789c,1] add edi,df add esi,df sub ecx ibranch ecx
Χρονισμός της rep movsb εντολής X86 -> RiscOPs (πιο ισχυρά από τα uops) 2 ισχυρούς decoders vs. 3 της Intel
Pentium Pro/II/III block diagram (απλοποιημένο) Register file 40 RRF IA-32 x86 x86 εντολές I-Cache ALU1Jmp 4C IFC fetch Decode Decode Decode 2C Dispatch 2C RS 20 2C ALU0 AGU1 LD AGU2 ST FPU ROB 40 1-n C 2C FRONT END EXEC 10 στάδια 1-n στάδια BACK END (COMMIT)
Pentium Pro/II/III Instruction flow Register file 40 RRF IA-32 x86 x86 εντολές I-Cache ALU1Jmp IFC fetch short short long Dispatch RS 20 ALU0 AGU1 LD AGU2 ST ROB 40 1-3 x86 instructions 16b instr. buffer 1 uop 1 uop 4 uops 6 uop buffer 3 uop rename & dispatch Up to 5 uops issue/c FPU Up to 5 uops exec/c 3 uop retire commit/c
Το πρόβλημα με τα branch (JUMP) fetch i3 fetch i4 fetch i5 fetch i6 decode i3 r2=m[a+r1] decode i4 decode i5 r1=r1+1 decode i6 Stall Stall Commit r0=r0+r2 Commit Commit r3=r1!=10 Commit fetch i7 decode i7 Stall Stall if r3 loop Commit fetch i3 fetch i4 fetch i5 fetch i6 fetch i7
Branch prediction Pipeline Πάντα γεμάτο Pentium Pro: 10 pipeline στάδια πριν από την εκτέλεση = 10 * 3 εντολές μετά από ένα branch (JUMP) Πού θα τις βρούμε όλες αυτές τις εντολές? Πρόβλεψη branch i1 r1=0 /* index */ i2 r0=0 /* sum */ i3 loop:r2=mem[a+r1] /* a[i] */ i4 r0=r0+r2 i5 r1=r1+1 i6 r3=(r1!= 10) i7 if(r3==true) goto loop i8 continue:... Ποντάρουμε στο ότι το i7 μάλλον θα πάει στο i3 και όχι στο i8
Branch prediction fetch i3 fetch i4 fetch i5 fetch i6 decode i3 r2=m[a+r1] decode i4 decode i5 r1=r1+1 decode i6 Stall Stall Commit r0=r0+r2 Commit Commit r3=r1!=10 Commit fetch i7 decode i7 Stall Stall if r3 loop Commit Πρόβλεψη fetch i3 fetch i4 fetch i5 fetch i6 decode i3 r2=m[a+r1] decode i4 decode i5 r1=r1+1 decode i6 Stall Stall r0=r0+r2 Commit Commit Commit r3=r1!=10 Commit fetch i7 decode i7 Stall Stall if r3 loop Πρόβλεψη
Pentium Pro branch prediction Register file 40 RRF IA-32 x86 x86 εντολές I-Cache ALU1Jmp IFC fetch Decode Decode Decode Dispatch RS 20 ALU0 AGU1 LD AGU2 ST ROB 40 Branch Predict FPU BACK END FRONT END (COMMIT) 10 στάδια 1-n στάδια 2 σ.
Speculative execution Η πρόβλεψη branch (JUMP) οδηγεί σε ΥΠΟΘΕΤΙΚΗ ΕΚΤΕΛΕΣΗ ΕΝΤΟΛΩΝ (Speculative Execution) υποθέτουμε ότι θα εκτελεστούν Αν όμως κάνουμε λάθος? Θα πρέπει τα αποτελέσματα της υποθετικής εκτέλεσης να είναι αναστρέψιμα Οι βασικοί μηχανισμοί υπάρχουν ήδη για το OOO Το ROB κρατάει τις υποθετικές εντολές ώσπου να επαληθευτεί η ροή του προγράμματος ROB (40) > RS (20)
Κάπως έτσι Pipeline CPI = Ideal pipeline CPI + superscalar register renaming Dynamic execution loop unrolling static scheduling, software pipelining Structural Stalls + Data Hazard Stalls + Control Stalls Branch prediction forwarding speculation delayed branches, branch scheduling
Branch prediction Branch (JUMP) ορολογία: i-x loop:......... i JUMP loop i+1 continue i+2... τaken (αλλαγή ροής) not taken/fall-through συνέχεια ροής Πως γίνεται το branch prediction? Στατικά (π.χ. branch προς τα πίσω είναι taken ) Με τη βοήθεια του compiler Δυναμικά (κατά την εκτέλεση του προγράμματος)
Branch prediction i-x loop:......... i JUMP loop i+1 continue i+2... τaken (αλλαγή ροής) not taken/fall-through συνέχεια ροής Δυναμικό branch prediction Απλοϊκό: για κάθε branch κάνε ότι έκανε την προηγούμενη φορά loop: 10 φορές σωστό, λάθος, λάθος, 9 φορές σωστό, λάθος, λάθος για κάθε branch κάνε ότι έτεινε να κάνει πιο πολύ τις 2-3 πιο πρόσφατες φορές που το είδαμε (Jim Smith, UW, βραβείο Mauchley-Eckert), Pentium branch prediction loop: 10 φορές σωστό, λάθος, 10 φορές σωστό, λάθος...
Deep Pipelines και Branch Misprediction Περισσότερα στάδια στο pipeline Μεγαλύτερο το penalty από branch miss predictions Μεγαλύτερη ανάγκη για καλύτερους branch predictors MIPS based pipeline 1 instruction issued per cycle, branch hazard of 1 cycle. Delayed branch Pentium Pro 3 instructions issued per cycle, 12+ cycle misfetch penalty Θυμηθείτε: τον Pentium 4 δεν μπορούσαμε να τον κάνουμε καλύτερο CMPs (ILP wall)
Εντολές Διακλάδωσης Περίπου 20% των εντολών είναι εντολές διακλάδωσης Next fetch started PC I-cache Fetch Πολλά στάδια μεταξύ υπολογισμού του επόμενου PC και εκτέλεσης του branch (για σύγχρονους επεξεργαστές μπορεί και >10!) Εισαγωγή stalls και επομένως μείωση του ρυθμού ανάγνωσης και εκτέλεσης εντολών Branch executed Fetch Buffer Issue Buffer Func. Units Result Buffer Arch. State Decode Execute Commit
Branch prediction Σύγχρονο branch prediction στον Pentium Pro/II/III Δύο επιπέδων, με ιστορία (two-level, history-based), Yeh & Patt, UM Η συμπεριφορά του branch εξαρτάται από το τι έγινε με τα άλλα branch πριν από αυτό Με άλλα λόγια από πιο δρόμο φτάσαμε σε αυτό το branch Ιστορία: τι έγινε με τα ν προηγούμενα branches π.χ. taken,fall-through,taken,taken (1,0,1,1) Πρόβλεψη: τι έτεινε να κάνει το branch (πιο πολύ) τις προηγούμενες 2-3 φορές που το είδαμε με την ίδια ιστορία Pentium Pro: 4 προηγούμενα branch ιστορία (πχ. 1011), προβλέπει 512 συνδιασμούς ιστορίας/branch 95% ακρίβεια πρόβλεψης
Βranch prediction Πολύ προσοδοφόρο πεδίο (πολλές δημοσιεύσεις) Γιατί? 90-95% επιτυχία πρόβλεψης δεν είναι αρκετή Π.x.: καθημερινή πρόβλεψη σεισμών: σήμερα δεν θα γίνει σεισμός: 99% επιτυχία Το θέμα είναι όμως πόσο κοστίζει η 1 (στις 100) λάθος πρόβλεψη Στους επεξεργαστές το κόστος λάθος πρόβλεψης αυξάνει διαρκώς (Pentium 4, 20-στάδια pipeline, 6 εντολές παράλληλα ) Παραμένει ένα από τα δύσκολα προβλήματα που οδήγησε την Intel σε άλλες αρχιτεκτονικές : IA-64, Itanium που αποφεύγουν την πρόβλεψη
Πρόβλεψη Τεχνικές Μείωσης Control Stalls Software/Compiler Μείωση των εντολών άλματος (loop unrolling) Υπολογισμός της συνθήκης εκτέλεσης διακλάδωσης όσο πιο νωρίς Hardware Αντικατάσταση των bubbles με χρήσιμη δουλειά Παράλληλη εκτέλεση και των 2 ροών προγράμματος μέχρι να αποσαφηνιστεί ποιο κομμάτι της διακλάδωσης θα εκτελεστεί (predication Itanium)
Εντολές Άλματος Χρειαζόμαστε 2 πληροφορίες Αν θα εκτελεστεί το άλμα ή όχι (taken or not taken) Αν εκτελεστεί ποιος είναι ο προορισμός (target PC) Είδος Άλματος Direct Jumps Function Calls Conditional Branches Indirect Jumps Function returns Απόφαση Always Taken??? Always Taken Προορισμός Υπολογίζεται εύκολα Υπολογίζεται εύκολα Υπολογίζεται δύσκολα
Πρόβλεψη Απόφασης Απαιτείται για εντολές διακλάδωσης υπό συνθήκη Η πλειοψηφία των εντολών διακλάδωσης είναι υπό συνθήκη 2 είδη τεχνικών πρόβλεψης Στατικές Δυναμικές Απαιτείται extra hardware Αποθήκευση χρήσιμων πληροφοριών για βελτίωση της ακρίβειας των προβλέψεων (branch history tables, branch target buffers, etc) Μηχανισμός ανάνηψης σε περίπτωση λανθασμένης πρόβλεψης FLASH THE PIPELINE
Στατικές Τεχνικές Πρόβλεψης Branch not taken (NT) Misprediction rate ~60%-70% Branch taken (T) Σε ένα loop λάθος πρόβλεψη μόνο στην τελευταία εκτέλεση Average misprediction rate 34% (SPEC benchmarks) BTFNT Άλματα προς τα πίσω (αρνητικό offset ως προς το PC) προβλέπεται ότι θα εκτελεστούν (Backwards taken) Άλματα προς τα εμπρός (θετικό offset ως προς το PC) προβλέπεται ότι δε θα εκτελεστούν (Forwards not taken) χρησιμοποιείται στον Intel Pentium 4 σε περίπτωση που αποτύχει ο μηχανισμός δυναμικής πρόβλεψης
Profiling Στατικές Τεχνικές Πρόβλεψης Εκτέλεση προγράμματος και καταγραφή στατιστικών Ο compiler τα χρησιμοποιεί για να βοηθήσει το hardware να κάνει σωστή πρόβλεψη (π.χ. αν μια εντολή διακλάδωσης εκτελείται πάνω από τις μισές φορές κατά τη διάρκεια του profiling τότε η πρόβλεψη είναι T) Εύκολη υλοποίηση Τα δεδομένα του profiling και της κανονικής εκτέλεσης μπορεί να είναι πολύ διαφορετικά. Επομένως λάθος προβλέψεις`
Στατικές Τεχνικές Πρόβλεψης Profiling ή compile-time analysis Οι compilers έχουν περιορισμούς. Δεν μπορούν να πιάσουν την δυναμική εκτέλεση του προγραμματος π.χ. Interactive εφαρμογές
4 static ways to reduce control hazards #4: Delayed Branches branch instruction sequential successor 1 sequential successor 2... sequential successor n branch target if taken Branch delay of length Those instruction are a executed delay of one slot: allows the branch outcome and the target address to happen without stalls
«Routing» of a branch delay slot (a) and (c) are the best cases: fills the delay slot and does not increase the number of instructions
Δυναμικές Τεχνικές Πρόβλεψης Branch History Branch Predictor Branch History Φανταστείτε ένα loop -> τα ίδια πράγματα σε iteration Τι είδους ιστορία??? 84
Δύο Κώδικες Παράδειγμα 1 (global) (If b1 & b2 is not taken, b3 will be taken) if (aa==2) // branch b1 a = 0; if (bb==2) // branch b2 bb = 0; if(aa!=bb) { // branch b3 Clearly depends on the results of b1 and b2 Παράδειγμα 2 (local) for (i=0; i<100; i ++) { } // branch b1 clearly depends on the branch history 85
Δυναμικές Τεχνικές Πρόβλεψης 1-bit predictor Η πρόβλεψη βασίζεται στο τι έγινε την προηγούμενη φορά που εκτελέστηκε αυτή η εντολή διακλάδωσης Χρήση πίνακα για την αποθήκευση της απόφασης Προσπέλαση του πίνακα χρησιμοποιώντας k bits του PC Aliasing 0x40010100 0x40010104 0x40010108 0x40010A04 0x40010A08 k bits 1-bit Branch History Table addi r10, r0, 100 addi r1, r1, r0 L1: addi r1, r1, 1 bne r1, r10, L1 NT T T NT T... T NT NT 2 k
Παράδειγμα 1-bit predictor 0x108: for(i=0; i < 100000; i++) {... 0x144: if( ( i % 100) == 0 ) calla( ); 0x150: if( (i & 1) == 1) } Πρόβλεψη (108): 0 Απόφαση (108): T callb( );
Παράδειγμα 1-bit predictor 0x108: for(i=0; i < 100000; i++) {... 0x144: if( ( i % 100) == 0 ) calla( ); 0x150: if( (i & 1) == 1) } Πρόβλεψη (108): Απόφαση (108): callb( ); 0 TTTTTTTT...TTTΤ 100000 T TTTTTTTT...TTTN
Παράδειγμα 1-bit predictor 0x108: for(i=0; i < 100000; i++) {... 0x144: if( ( i % 100) == 0 ) calla( ); 0x150: if( (i & 1) == 1) } Πρόβλεψη (108): Απόφαση (108): callb( ); 0 TTTTTTTT...TTTΤ 100000 T TTTTTTTT...TTTN N T
Παράδειγμα 1-bit predictor 0x108: for(i=0; i < 100000; i++) {... 0x144: if( ( i % 100) == 0 ) calla( ); 0x150: if( (i & 1) == 1) callb( ); } Πρόβλεψη (108): Misprediction = 2/100000 Prediction Rate = 99.998% 0 TTTTTTTT...TTTΤ 100000 N TTTTTTTT...TTTΤ Απόφαση (108): T TTTTTTTT...TTTN T TTTTTTTT...TTTN
Παράδειγμα 1-bit predictor 0x108: for(i=0; i < 100000; i++) {... 0x144: if( ( i % 100) == 0 ) calla( ); 0x150: if( (i & 1) == 1) } Πρόβλεψη (144): 0 Απόφαση (144): N callb( );
Παράδειγμα 1-bit predictor 0x108: for(i=0; i < 100000; i++) {... 0x144: if( ( i % 100) == 0 ) calla( ); 0x150: if( (i & 1) == 1) } Πρόβλεψη (144): Απόφαση (144): callb( ); 0 NTTTTTTT...TTTΤ 100 N TTTTTTTT...TTTN
Παράδειγμα 1-bit predictor 0x108: for(i=0; i < 100000; i++) {... 0x144: if( ( i % 100) == 0 ) calla( ); 0x150: if( (i & 1) == 1) } Πρόβλεψη (144): Απόφαση (144): callb( ); 0 NTTTTTTT...TTTΤ 100 N TTTTTTTT...TTTN N T
Παράδειγμα 1-bit predictor 0x108: for(i=0; i < 100000; i++) {... 0x144: if( ( i % 100) == 0 ) calla( ); 0x150: if( (i & 1) == 1) callb( ); } Πρόβλεψη (144): Misprediction = 2/100 Prediction Rate = 98% 0 NTTTTTTT...TTTΤ 100 N TTTTTTTT...TTTΤ Απόφαση (144): N TTTTTTTT...TTTN T TTTTTTTT...TTTN
Παράδειγμα 1-bit predictor 0x108: for(i=0; i < 100000; i++) {... 0x144: if( ( i % 100) == 0 ) calla( ); 0x150: if( (i & 1) == 1) } Πρόβλεψη (150): 0 Απόφαση (150): T callb( );
Παράδειγμα 1-bit predictor 0x108: for(i=0; i < 100000; i++) {... 0x144: if( ( i % 100) == 0 ) calla( ); 0x150: if( (i & 1) == 1) } Πρόβλεψη (150): callb( ); 0 T Απόφαση (150): T N
Παράδειγμα 1-bit predictor 0x108: for(i=0; i < 100000; i++) {... 0x144: if( ( i % 100) == 0 ) calla( ); 0x150: if( (i & 1) == 1) } Πρόβλεψη (150): callb( ); 0 T N Απόφαση (150): T N T
Παράδειγμα 1-bit predictor 0x108: for(i=0; i < 100000; i++) {... 0x144: if( ( i % 100) == 0 ) calla( ); 0x150: if( (i & 1) == 1) callb( ); } Απόφαση (150): Πρόβλεψη (150): 0 T Misprediction = 1/1 Prediction Rate = 0% T N N T T N N T T N N T T N N T T N N T T N N T T N N T T N N T T N N T T N N T T N N T T N N T
gshare Predictor
Tournament Hybrid Predictor (Pentium 4) meta-predictor 2-bit μετρητές 0,1 χρησιμοποιείται ο P 0 Branch PC Meta- Predictor Pred 0 Pred 1 2,3 χρησιμοποιείται ο P 1 Η τιμή του meta-predictor ενημερώνεται μόνο όταν οι δυο predictors κάνουν διαφορετική πρόβλεψη Pred 0, Pred 1 Συνδυασμοί των προηγουμένων συστημάτων Pred 0 Λάθος Λάθος Σωστή Σωστή Final Prediction Pred 1 Λάθος Σωστή Λάθος Σωστή Meta Update --- +1-1 ---
Data Dependacies Δύο εντoλές χρησιμοποιούν τον ίδιο register add R1, R2, R3 add R1, R2, R3 add R1, R2, R3 sub R2, R4, R1 sub R2, R4, R1 sub R2, R4, R1 or R1, R6, R3 or R1, R6, R3 or R1, R6, R3 read-after-write (RAW) True dependence (real) write-after-read (WAR) anti dependence (artificial false) write-after-write (WAW) output dependence (artificial - false) Where (How) do WAR and WAW hazards occur? 101
Register renaming Ο παραλληλισμός δεσμεύεται από τις αλληλεξαρτήσεις των εντολών Αληθινές εξαρτήσεις: δεν μπορεί να εκτελεστεί μια εντολή πριν από τις εντολές που παράγουν τα ορίσματά της. RAW (Read-After-Write) εξαρτήσεις. Πλασματικές εξαρτήσεις: αποτροπή εκτέλεσης λόγω ανακύκλωσης των καταχωρητών WAW (Write-After-Write) αντι-εξάρτηση WAR (Write-After-Read) output εξάρτηση Αντι-εξάρτηση WAW i1 r1 = r2 * 10 i2 r3 = r1 * 10 i3 r1 = r4 * 20 i4 r5 = r1 * 20 output-εξάρτηση WAR
Register renaming Για τις αληθινές εξαρτήσεις χρειάζεται να περάσουμε σε εξελιγμένα είδη πρόβλεψης για να τις υπερβούμε (Value Prediction, dataflow barrier). Θεωρητικά μιλώντας... Οι πλασματικές εξαρτήσεις μειώνουν τον παραλληλισμό στο επίπεδο εντολών (ILP) χωρίς να έχουν ουσιαστικό λόγο ύπαρξης. Απαλείφονται εύκολα αρκεί να είχαμε πάρα πολλούς καταχωρητές. Αλλά το Σετ Εντολών ποτέ δεν αλλάζει (συμβατότητα λογισμικού). (μόνο επεκτείνεται ) Λύση? Μετονομασία Καταχωρητών (Register Renaming): Αντιστοίχισε τους καταχωρητές σε ένα πολύ μεγαλύτερο σετ, κατά την εκτέλεση του προγράμματος, αυτόματα και αόρατα στον εξωτερικό κόσμο. Εξαλείφει το πλεονέκτημα των RISC που πάντα υποστήριζαν πολλούς καταχωρητές για τους ίδιους λόγους
Register renaming Οι 8 αρχιτεκτονικοί καταχωρητές των x86 αντιστοιχίζονται σε 40 φυσικούς (physical) καταχωρητές Ένας πίνακας (RAT, Register Alias Table) κρατά τις αντιστοιχίες Κάθε φορά που γράφεται ένας αρχιτεκτονικός καταχωρητής αντιστοιχίζεται σε νέο φυσικό καταχωρητή i1 r1 = r2 * 10 i2 r3 = r1 * 10 i3 r1 = r4 * 20 i4 r5 = r1 * 20 i1 ra = r2 * 10 i2 r3 = ra * 10 i3 r1 = r4 * 20 i4 r5 = r1 * 20 i1 ra = r2 * 10 i2 rb = ra * 10 i3 rc = r4 * 20 i4 r5 = rc * 20 Με αυτό τον τρόπο εξαλείφουμε τις πλασματικές εξαρτήσεις (WAW, WAR) αλλά αφήνουμε ανέπαφες τις πραγματικές εξαρτήσεις (RAW)
Pentium Pro/II/III block diagram, register renaming Register Alias Table Register file 40 RRF IA-32 x86 x86 εντολές I-Cache ALU/Jmp fetch Decode Decode rename RS 20 ALU LOAD ROB 40 Decode STORE Branch Predict FPU 10 στάδια 2 στάδια 2 σ.
Register renaming στο Multi2Sim
Σύνοψη: OOO Για να μεγιστοποιήσουμε τον παραλληλισμό στην εκτέλεση εντολών πρέπει να καταφύγουμε σε εκτέλεση εκτός σειράς προγράμματος (OOO). Το OOO υποβοηθείται από: Πρόβλεψη ροής (Branch prediction) και υποθετική εκτέλεση (speculative execution) επιτρέπει (1) να βρούμε αρκετές εντολές ώστε να κρατάμε όλα τα pipelines γεμάτα, (2) να εκτελούμε εντολές υποθετικά ώσπου να επαληθεύσουμε τη ροή του προγράμματος Μετονομασία καταχωρητών (Register Renaming) αφαιρεί τις πλασματικές εξαρτήσεις μεταξύ εντολών που προέρχονται από την ανακύκλωση καταχωρητών
Pentium 4 Microarchitecture 108
Top 10 80x86 Instructions Rank instruction Integer Average Percent total executed 1 load 22% 2 conditional branch 20% 3 compare 16% 4 store 12% 5 add 8% 6 and 6% 7 sub 5% 8 move register-register 4% 9 call 1% 10 return 1% Total 96% Simple instructions dominate instruction frequency 109
Τι άλλο υπάρχει? 110
Instruction Issue Time Χαμηλό utilization των μονάδων λόγω εξαρτήσεων
Superscalar Issue Time Το Superscalar αυξάνει το performance, αλλά όχι το utilization. Συνήθως αυξάνει και το power
Chip Multiprocessor Time Limited utilization when only running one thread
Fine Grained Multithreading Time Intra-thread dependencies still limit performance
Simultaneous Multithreading Time Maximum utilization of function units by independent operations
Basic Out-of-order Pipeline Fetch Decod e/map Queue Reg Read Execu te Dcach e/sto re Buffe r Reg Write Retir e PC Register Map Icache Regs Dcache Regs Threadblind
SMT Pipeline Fetch Decod e/map Queue Reg Read Execu te Dcach e/sto re Buffe r Reg Write Retir e PC Register Map Icache Regs Dcache Regs
Το Hyperthreading Παραδείγματα: Pentium 4, Xeon (Intel) με ονομασια Hyperthreading, Netburst Ο προγραμματιστής έβλεπε τον επεξεργαστή διπλό 5% αύξηση στο chip area, 25% αύξηση στην απόδοση
Changes for SMT Basic pipeline unchanged Replicated resources Program counters Register maps Shared resources Register file (size increased) Instruction queue First and second level caches Translation buffers Branch predictor
Multiprogrammed workload 250% 200% 150% 100% 1T 2T 3T 4T 50% 0% SpecInt SpecFP Mixed Int/FP
Multithreaded Applications 300% 250% 200% 150% 100% 1T 2T 4T 50% 0% Barnes Chess Sort TP
VLIW Αρχές ILP (Instruction-Level Parallelism) Superscalar, OoO: hardware finds it VLIW: let the Software, COMPILER, find it! No need for DYNAMIC EXECUTION Register renaming out Reservation Stations out Reorder Buffer out Out-of-order issue out
VLIW: Very Long Instruction Word
VLIW architetcure
VLIW Execution Semantics
VLIW Execution Semantics
Προβλήματα VLIW Compiler δεμένος με implementation Scheduler must know operation latencies Cannot run binaries in another implementation Dynamically scheduled VLIW Αποσύνδεση operation latencies από τον compiler
Intel/HP EPIC Intel/HP IA-64 Explicitly Parallel Instruction Computer (EPIC) IA-64: instruction set architecture; EPIC is type EPIC = 2nd generation VLIW? Itanium is name of first implementation (2001)
Intel EPIC VLIW Instructions IA-64 instructions are encoded in bundles, which are 128 bits wide. Each bundle consists of a 5-bit template field and 3 instructions, each 41 bits in length 3 Instructions in 128 bit groups ; field determines if instructions dependent or independent Smaller code size than old VLIW, larger than x86/risc Groups can be linked to show independence > 3 instr
Intel EPIC VLIW Instructions
Itanium
Instruction group/bundle
Itanium (or Itanic as in Titanic) Highly parallel and deeply pipelined hardware at 800Mhz (2000) 6-wide, 10-stage pipeline at 800Mhz on 0.18 µ process Hardware checks dependencies (interlocks => binary compatibility over time) DYNAMICALLY SCHEDULED VLIW Predicated execution (select 1 out of 64 1-bit flags) => 40% fewer mispredictions?
Itanium IA-64 Registers The integer registers are configured to help accelerate procedure calls using a register stack 8 64-bit Branch registers used to hold branch destination addresses for indirect branches 64 1-bit predication registers
IA-64/Itanium registers
Itanium