Nello scorso articolo abbiamo visto perchè la Branch Prediction è una componente essenziale dei processori superscalari, da quali blocchi base è composta e come questi blocchi si raccordano col resto dell’architettura. Adesso bisogna rispondere all’ultima domanda: che cosa c’è davvero dentro un predittore dinamico? Che algoritmi vengono usati per generare le predizioni?
Innanzitutto, il predittore deve predire due cose contemporaneamente: la direzione di salto e, se il salto è preso, il bersaglio di salto. Un termine comune trovato in letteratura per questo tipo di struttura è Branch Target Buffer (BTB) e ha quest’aspetto:
E’ simile ad una piccola cache, indirizzata tramite il Program Counter, che restituisce la direzione di salto (basata in qualche modo sulla storia passata di quel salto) e il bersaglio di salto (l’indirizzo a cui si è saltati l’ultima volta che il salto è stato eseguito).
Come per ogni cache, anche per questa ci sono due requisiti contrastanti:
- velocità: idealmente vorremmo che il BTB risponda in un solo ciclo di clock, in modo da avere una predizione per il prossimo PC dato il PC corrente; memorie veloci devono essere piccole (più la memoria è piccola più le interconnessioni sono brevi e la circuiteria è semplice, riducendo il tempo di accesso)
- hit rate: il tasso di predizione corretta è in realtà il prodotto di due fattori: il tasso di predizione del BTB per lo hit rate del BTB, cioè quanto spesso troviamo nel BTB le informazioni che stiamo cercando; idealmente vorremmo avere uno hit rate del 100%, che impone l’uso di BTB grossi
Anche il tipo di associatività è importante: una cache fully-associative avrà uno hit rate maggiore, ma sarà più lenta; il contrario è vero per una cache direct mapped. Tutti questi fattori sono critici nella progettazione del predittore e vengono estensivamente analizzati con simulatori architetturali.
Il Program Counter corrente viene usato quindi per accedere contemporamente alla Instruction Cache e al predittore, per ottenere il prossimo PC. Lo stadio di Fetch assomiglierà allora a qualcosa del genere:
Supponendo di avere un processore RISC con istruzioni a 32 bit, il prossimo PC sarà o il PC corrente più 4 byte (se il BTB predice salto non preso, o se si è verificato un miss) oppure il PC contenuto nel BTB stesso (se cè stato hit nel BTB ed è stato predetto salto preso). Se la predizione è corretta, e l’indirizzo bersaglio è disponibile al prossimo ciclo di clock, la penalità di salto è stata completamente cancellata: il salto dovrà comunque essere eseguito per la validazione della predizione, ma potrà essere eseguito in parallelo con le istruzioni che lo seguono, invece che prima di esse. Questa è la “magia” della Branch Prediction.
Usare il passato per predire il futuro
Il modo più semplice per predire la direzione di salto è costruire una macchina a stati finiti (FSM) che tiene traccia degli ultimi N esiti del salto (1 bit per esito): la macchina avrà 2^N stati, e ad ogni stato è associata una predizione:
Studi sperimentali dimostrano che è sufficiente un numero molto piccolo di bit per avere ottime prestazioni: 2 bit sono già sufficienti a superare il 90% di predizioni corrette nella maggior parte dei casi.
Il sistema più semplice è tenere 1 solo bit di storia per salto, cioè predire per il prossimo salto la stessa direzione di quello precedente. Sembra quasi uno scherzo, un sistema così semplice non può essere accurato! Invece, dal momento che la maggior parte dei salti è fortemente polarizzata, perfino con un solo bit di storia è facile ottenere predizioni accurate a più dell’80% !
Uno dei casi più comuni di salti sono quelli che controllano la condizione di uscita da un loop. Come si comporta un predittore a 1 bit in questo caso? Supponiamo di avere un piccolo loop che si ripete 4 volte, il meccanismo allora funzionerà così:
dove ho indicato in rosso le predizioni errate. Il predittore indovinerà appena il 50% delle volte. In generale, sbaglierà sempre la prima e l’ultima iterazione del ciclo. Per cicli lunghi questo non è grosso problema, ma per cicli brevi l’accuratezza cade a livelli inaccettabili.
Come si comporta in questo caso un predittore a 2 bit, cioè un predittore che tiene traccia degli ultimi due esiti di ogni salto? Prima di tutto bisogna rispondere alla domanda: quale predittore a 2 bit? Con 2 bit si può costruire una FSM a 4 stati, e ci sono molti modi di collegare quegli stati… infatti, ce ne sono più di 4 milioni!
Il conto si fa così: da ogni stato escono due transizioni, una per quando il salto è preso (taken) e una per quando non è preso (non-taken); ogni transizione può andare a finire in ognuno dei 4 stati della FSM, quindi ci sono 4 * 4 = 16 possibili combinazioni di transizioni per stato, e 16 ^ 4 = 65536 possibili tabelle di transizione per l’intera macchina. Inoltre, ogni stato può generare una predizione preso/non preso, che genera ulteriori 2 ^ 4 possibilità. Per finire lo stato iniziale può essere uno qualunque dei 4 stati. In totale, ci sono 65536 * 16 * 4 = 4194304 possibili predittori a 2 bit!
Naturalmente la quasi totalità di questi predittori è completamente inutile, ma esiste un piccolo numero di soluzioni alternative con buone caratteristiche. Uno studio sperimentale esaustivo fu condotto nel 1992 da Ravi Nair per IBM. Con poca sorpresa, il predittore migliore si rivelò essere anche quello più ovvio da immaginare: un contatore a saturazione, originariamente proposto da Jim Smith all’inizio degli anni ’80 e brevettato per la CDC:
Il predittore predice un salto preso in 3 stati su 4: solo se gli ultimi due esiti sono stati non-preso, allora predirà non-preso. Confrontiamo il comportamento di questo predittore con quello del predittore a 1 bit, sullo stesso loop:
Il predittore predice di prendere sempre il salto! Questo è un miglioramento rispetto al caso precedente, perchè ora si sbaglia solo l’ultima iterazione del ciclo e basta. Nel caso di loop a 4 iterazioni, la percentuale di successo sale dal 50% al 75%, un ottimo incremento.
E se aumentassimo il numero di bit di storia, otterremmo risultati migliori? Sì, ma non molto. Un altro studio sempre di Nair misurò sperimentalemente questi valori:
1 bit: 82.5% - 96.2% 2 bit: 86.8% - 97.0% 3 bit: 88.3% - 97.0%
Passare da 2 a 3 bit, nei casi da lui considerati, aumentava di poco il caso peggiore, e per nulla il caso migliore, e tutto questo usando il 50% di bit in più, che significa buffer più grosso e quindi più lento: è addirittura possibile che, una volta tenuta in conto l’implementazione circuitale, il sistema a 3 bit sia più lento!
Per fare un salto in avanti e costruire predittori molto più efficaci bisogna pensare a qualcosa di molto diverso… e molto più sofisticato.
Predittori a due livelli
Fino a questo momento abbiamo considerato ogni branch a sè stante, scollegato dagli altri branch del programma, ma l’esperienza ci dice che spesso l’esito di un branch dipende da quelli dei branch vicini a lui, oppure dall’esito passato del branch stesso, ma tenendo in considerazione non il mero numero di salti presi/non presi, ma la loro sequenza temporale.
Ad esempio, nel loop degli esempi precedenti, sappiamo che se abbiamo preso il salto 3 volte di fila, allora la prossima volta sarà non preso, altrimenti sarà preso.
Un esempio di correlazione “spaziale” (tra branch vicini) invece potrebbe essere:
int x, y, z; ... if( x == 0 ) { z = 0; } ... if( x * y > 4 ) { ... } ... if( z < 2 ) { ... }
Se il primo salto è non-preso (cioè l’if è vero e viene eseguito il codice tra parentesi, immediatamente seguente al branch) allora sicuramente il secondo salto è preso e il terzo è non-preso. Se riuscissimo a correlare tra loro questi salti, una volta eseguito il primo, se esso fosse preso sapremmo come eseguire gli altri due con una affidabilità del 100% !
All’inizio degli anni ’90 due ricercatori (Yeh e Patt) proposero una famiglia di predittori basati su due livelli: il primo livello tiene traccia della storia dei branch eseguiti prima di quello in esame (cioè dei branch vicini nel codice, eseguiti appena prima di questo), mentre il secondo è una tavola di contatori a 2 bit (gli stessi visti prima), che tiene traccia della storia del salto in esame:
Il Branch History Register (BHR) è uno shift register dove vengono accumulati i risultati degli ultimi N branch (qualunque essi siano). Il BHR tiene traccia quindi della storia globale, il percorso di istruzioni che ci ha portati al salto in esame; la Pattern History Table (PHT) è una collezione di predittori indicizzata tramite una concatenazione della storia globale con (una parte del) l’indirizzo del salto in esame: in questo modo è possibile fare predizioni diverse per lo stesso salto a seconda del code path che ci ha portati lì. Questo schema è chiamato Global History 2-Level Predictor.
Uno schema simile (sempre di Yeh e Patt) è il Local History 2-Level Predictor:
In questo caso ogni branch ha il suo shift-register (Branch History Table) e tiene traccia della propria storia separatamente da quella degli altri branch (da cui il nome local). Di nuovo, la storia del salto viene concatenata all’indirizzo del salto stesso per accedere alla PHT e generare la predizione. Lo schema Global History può essere considerato un caso particolare di questo, dove la BHT ha una sola cella (in altre parole, zero bit sono necessari per accedere alla BHT).
Torniamo all’esempio del loop con 4 iterazioni: come si comporta un Local History Predictor in questo caso? Finalmente abbiamo uno schema capace di fare predizioni diverse a seconda della diversa storia del salto, quindi ci aspettiamo che sia capace di fare meglio degli algoritmi precedenti, che erano invece costretti ad eseguire una “media” della storia del salto. Questo è infatti il caso:
dove ho indicato con ‘1’ un salto preso e con ‘0’ un salto non preso: si alternano successivamente tre 1 e uno 0. Dopo un certo numero di ripetizioni del loop, il predittore ha imparato che se la storia locale contiene un salto non preso e tre presi il prossimo sarà non preso, e sarà preso negli altri casi. Il tempo di “addestramento” di questo schema è superiore (deve “imparare” lo schema di ripetizione sia della storia locale che dei predittori, in totale 4 + 4 * 2 = 12 bit di informazione invece che 2), ma la capacità predittiva è migliore. In questo caso, il predittore ha una precisione del 100%, dove gli schemi precedenti si fermavano al 50% e al 75% rispettivamente.
Da notare che questo è vero solo se la lunghezza del ciclo è inferiore o uguale ai bit di storia accumulati nella BHT, altrimenti il predittore non ha abbastanza informazione per capire dove si trova all’interno del ciclo e sbaglierà di nuovo l’ultima iterazione del ciclo.
Aliasing
Fino a questo momento ho lasciato intendere che ogni branch ha il proprio predittore nel buffer, ma non è necessario che sia così; anzi, ci sono motivi per preferire il contrario. Consideriamo questo predittore… “particolare”:
La predizione viene fatta da un generatore casuale, senza alcuna correlazione col salto da eseguire. Naturalmente, il processore eseguirà comunque il programma correttamente! perchè i salti vengono comunque eseguiti e validati. Altrettanto ovviamente, le prestazioni di questo processore saranno penose.
Ma il punto è che, dato che il predittore può sbagliare, possiamo prenderci certe libertà architetturali. Ad esempio, il buffer potrebbe non avere tag: tutti i branch il cui indirizzo mappa sulla stessa entry nel buffer usano la stessa FSM, interferendo tra loro. Questo è chiamato aliasing; l’unica cosa che ci interessa è che l’aliasing sia abbastanza basso da avere un impatto trascurabile sulle prestazioni.
Eliminare le tag (e anche, ad esempio, i controlli ECC che invece troviamo nelle cache per evitare la possibile corruzione dei dati) permette di costruire buffer più piccoli e veloci, con effetti benefici sulle prestazioni.
Conclusione
In questo articolo ho illustrato alcune tecniche base usate per predire dinamicamente la direzione dei branch. Nel prossimo articolo descriverò alcune tecniche più sofisticate che permettono di ottenere precisioni ancora maggiori.
Bellissimo articolo!
Quello del branch prediction è uno dei temi che mi ha sempre interessato.
Sei riuscito a spiegarlo semplicemente ma allo stesso tempo in modo completo, bravo!
Attendo il tuo prossimo articolo! :D
Grandissimo, mi sto seriamente appassionando alla materia grazie a questi articoli :-)
Grande Pleg! Come sempre, riesci ad essere preciso, ma chiarissimo!
E’ incredibile la qualità di queste pagine
Bello.
Mi è piaciuto molto la parte finale dell’articolo (la spiegaizone dell’Aliasing).
Grazie ragazzi!
Ci tengo a soddisfare tutti i miei 5 lettori :)
La predizione dei salti e’ un argomento molto vasto, stimo di poterci scrivere un altro paio di articoli, uno su tecniche piu’ avanzate e un altro su qualche esempio reale (ad es. la Trace Cache del P4 e la “Way & Line Prediction” dei vecchi Alpha).
vai tranquillo… meglio 5 Spartani che 50 Ateniesi, in questa dura lotta all’ultimo transistor :-D
Ehm, dove si imparano queste cose? Ho trovato il lavoro che voglio fare nel caso mi dovesse andare male con la Programmazione.. :P
Complimenti per l’ottima capacità di esposizione (e per gli schemi, quanto adoro gli schemi!).
I tuoi lettori sono più di 5 anche se non commentato gli articoli :)
@ #H
Cioè vuoi fare il branch predictor :D
@Ciano
E’ una battuta, ma a scanso di equivoci te lo chiarisco lo stesso: intendevo “fare lo stesso lavoro di Pleg”! xD
P.S. Non ti offendere, ma la battuta non faceva manco tanto ridere xD
@ #H
In genere i corsi di laurea in ingegneria elettronica / informatica trattano questi argomenti in un qualche corso. La mia esperienza in Italia al riguardo e’ stata deludente, e cmq non c’e’ alcuno sbocco lavorativo (non si fanno CPU o GPU o cose simili da noi). Anche in Europa non va molto meglio, l’unica grossa compagnia che progetta CPU e’ ARM in Inghilterra (e sempre in Inghilterra mi viene in mente anche Maxeler, che pero’ fa sistemi HPC di tipo diverso… ma intrigante, fanno codesign hardware-software per problemi specifici). Sia Intel che AMD che NVidia hanno qualche centro in Europa, ma non so quanto design si faccia (per dire, i due centri di design principali di Intel sono Hillsboro, Oregon, e Haifa, Israele).
C’e’ un po’ di roba in Giappone (ad es. Toshiba e Sony che fecero il Cell insieme ad IBM, Fujitsu fa una versione dello Sparc, NEC coi suoi processori vettoriali per i supercomputer giapponesi), e la Cina sta cercando di buttarsi nella mischia (un po’ sviluppando il suo Longsoon, un po’ costruendo il supercomputer piu’ potente del mondo, ma con tecnologia americana).
Ma la quasi totalita’ delle compagnie che progetta questa classe di macchine sono negli States: IBM, Intel, AMD, NVidia, Qualcomm, TI, e molte altre piu’ piccole: Tensilica coi suoi processori customizzabili, Tilera con processori manycore con interessanti tecnologie di interconnessione e ripartizionamento, tutte le compagnie di FPGA (Xilinx, Altera, …), DE Shaw Research fa dei processori per simulazioni molecolari per applicazioni biomedicali molto interessanti… questi per citare i primi che mi vengono in mente.
Per quel che riguarda le fonti, invece, i testi di riferimento sono in genere:
* Patterson, Hennessy, Computer organization and design — The hardware/software interface
* Hennessy, Patterson, Computer Architecture — A quantitative approach
* Shen, Lipasti, Modern processor design — Fundamentals of superscalar processors
Soprattutto l’ultimo e’ il testo che uso come riferimento per scrivere questi articoli, ed e’ l’unico testo al mondo che conosca che tratti processori superscalari in dettaglio. Sono comunque tutti dei libroni densissimi, quasi indigeribili senza opportuno background o guida.
Per dare un’idea di chi sono gli autori: Patterson e Hennessy furono dei pionieri nella ricerca sulle architetture RISC, MIPS e sulla tecnologia RAID (quella dei dischi); Patterson e’ a capo del dipartimento di elettronica e informatica (EECS) di Berkeley, mentre Hennessy era a capo del dipartimento di elettronica (EE) di Stanford, e adesso e’ rettore di Stanford.
Shen era professore al Carnegie Mellon, poi ha diretto per 6 anni il laboratorio di ricerca sulle microarchitetture di Intel (nella sede centrale a Santa Clara e in Oregon), mentre adesso dirige un centro di ricerca Nokia a Palo Alto (non so i dettagli).
In Italia quasi non c’è futuro, qualsiasi sia il campo in cui ci si voglia cimentare. Ma da questo punto di vista non mi faccio problemi, ho deciso già da parecchio che se ce ne sarà bisogno (e sono sicuro che sarà così) andrò a lavorare anche a migliaia di chilometri da casa. Certo, andare a lavorare proprio per Intel, AMD, NVidia, IBM o ARM sarebbe davvero una gran cosa, ma con la formazione scolastica che abbiamo nel belpaese la vedo difficile…
Purtroppo/per fortuna ho intrapreso la “via del software” molto tempo fa (ma farei ancora in tempo a cambiare volendo) ed è un campo che mi appassiona molto; inoltre, come hai detto tu riguardo le fonti, senza una solida base è quasi impossibile, e io non ho nemmeno una base non-solida (in elettronica, nonostante la stia facendo a scuola).
Potendo farei hardware/software, nel senso di seguire i corsi di laurea in Informatica e Ingegneria Elettronica contemporaneamente, ci vorrebbe parecchio impegno e un bel po’ di sacrificio, ma il rischio di fare “troppo di tutto e male” è comunque alto (d’altra parte anche i benefici in caso di successo sarebbero alti). Mah, manca ancora qualche mese alla scelta dell’università per decidere su cosa basare il mio futuro; per il momento, ho soltanto una grandissima confusione.
In ogni caso, ci tengo a rinnovarti i miei complimenti. Sei riuscito ad attirare la mia attenzione molto più tu in una manciata di post, che decine di professori in anni di scuola. ;)
Io ho fatto il Politecnico di Milano, e dalla mia esperienza informatica ed elettronica sono tenuti accuratamente separati, senza possibilita’ di prendere esami dell’altro corso. Questo praticamente impedisce di farsi una formazione nel campo della Computer Architecture, il cui pane quitidiano sono proprio le interazioni hardware-software.
Infatti per compensare ho dovuto, come dici, “andare a migliaia di chilometri da casa”. Se hai le competenze, la passione, e la possibilita’, e’ una cosa che raccomando senza riserve, per me stata l'”illuminazione”.
E “lavorare proprio per Intel, AMD, NVidia, IBM o ARM” e’ molto difficile… ma non impossibile ;)
“Io ho fatto il Politecnico di Milano, e dalla mia esperienza informatica ed elettronica sono tenuti accuratamente separati, senza possibilita’ di prendere esami dell’altro corso. Questo praticamente impedisce di farsi una formazione nel campo della Computer Architecture, il cui pane quitidiano sono proprio le interazioni hardware-software.”
Esattamente. Oltretutto, se ho capito bene, in Italia non è possibile seguire due corsi di laurea contemporaneamente nella stessa università; nel senso che ti puoi iscrivere ad un corso alla volta. Almeno, è quanto mi hanno detto, non ho verificato di persona.
“Infatti per compensare ho dovuto, come dici, “andare a migliaia di chilometri da casa”. Se hai le competenze, la passione, e la possibilita’, e’ una cosa che raccomando senza riserve, per me stata l’”illuminazione”.”
Passione ne ho da vendere; competenze un po’ meno :P
“E “lavorare proprio per Intel, AMD, NVidia, IBM o ARM” e’ molto difficile… ma non impossibile ;)”
Infatti non ho smesso di crederci xD
Comunque, ti volevo fare una domanda che non c’entra quasi nulla con l’articolo. In pratica, volevo sapere quale differenza, a livello materiale, c’è tra una CPU ed una GPU; nel senso: perché una è più indicata per i calcoli e l’altra per l’elaborazione grafica? Perché alla fine son calcoli anche quelli, quindi una GPU deve avere qualche componente hardware che la rende più adatta a quel determinato tipo di calcoli, solo che non ho capito il principio di questa cosa.
E inoltre, perché una GPU di una moderna scheda grafica, è più potente di un processore? Ho letto su svariati siti che grazie alle moderne GPU e alla tecnologia CUDA di NVidia (che, se ho capito bene permette di delegare alla GPU alcune operazioni del processore, allegerendogli il carico di lavoro) sono stati bucati, mediante brute-force, parecchi algoritmi di cifratura, per questo ho immaginato che fossero più potenti le GPU delle CPU.
E’ un ramo di quest’argomento che mi affascina molto, ma in ogni caso scusa per tutte ‘ste domande :D
“In pratica, volevo sapere quale differenza, a livello materiale, c’è tra una CPU ed una GPU; nel senso: perché una è più indicata per i calcoli e l’altra per l’elaborazione grafica?”
La risposta e’ semplice: perche’ le hanno costruite cosi’ :)
La risposta completa (aka tecnica) e’ molto lunga, ed e’ il pane appunto della Processor Architecture.
In breve: la tecnologia di base, comune a CPU, GPU e tutto il resto e’, ovviamente, l’elettronica digitale (porte logiche, memoria, ed altre cosette) che puoi costruire con essa.
Con questa tecnologia di base puoi costruire ogni genere di circuito, per eseguire ogni genere di algoritmo.
Una CPU e’ progettata per essere una macchina di Turing, capace quindi di eseguire qualsiasi algoritmo. In particolare, costruiamo una CPU in modo da offrire delle operazioni di base (specificate dall’ISA) su cui poi possiamo costruire il software, col quale implementiamo qualsiasi tipo di algoritmo. Immagina una stratificazione di livelli di astrazione: l’elettronica esporta un’astrazione (logica digitale) su cui costruiamo la CPU, e sulla CPU esportiamo un’astrazione (l’ISA) su cui costruiamo i programmi.
Una GPU invece e’ costruita per fare una cosa molto diversa, cioe’ risolvere problemi di computer grafica (calcolare intersezioni di linee e poligoni, assemblare triangoli, colorare pixel, eccetera). Dato che una CPU e’ in grado di eseguire qualsiasi algoritmo, puo’ ovviamente anche essere usata per fare computer grafica (il rendering di immagini si faceva una volta solo su CPU, curiosamente, ma per motivi ben precisi); ma non e’ COSTRUITA ESPLICITAMENTE per fare quello, quindi fa quello che puo’ (ovvero, le prestazioni sono basse).
La differenza in sostanza e’ questa: volendo eseguire un certo algoritmo, se invece di scrivere un programma che usa i blocchetti base messi a disposizione dalla CPU, costruisci un circuito che FA QUELLO esplicitamente, e nient’altro, puoi ottenere una macchina molto piu’ veloce (e che consuma meno).
Nel particolare caso delle GPU, per risolvere i problemi di grafica si scopre che (semplificando molto) serve una tonnellata di ALU parallele, con poche strutture di controllo. Una CPU invece ha molte meno ALU e molte piu’ strutture di controllo, perche’ deve poter fare qualsiasi cosa. Quindi, quei problemi particolari che si adattano all’architettura di una GPU (molti calcoli paralleli, poco controllo di flusso, ecc.) se fatti girare su una GPU volano! Se no fanno schifo :)
Credo di aver capito.
In parole povere, una CPU è qualcosa di general purpose, mentre per le GPU hanno fatto in modo di trovare un’architettura capace di essere più veloce con la computer grafica (un po’ come si faceva con i processori matematici tempo fa).
Così però, una GPU non potrebbe eseguire operazioni general purpose demandate al processore; quindi, in definitiva, non si può dire che le GPU sono più veloci delle CPU perché fanno tutt’altro lavoro e non possono essere paragonate. Giusto?
Giusto.
Ma negli ultimi anni le GPU sono evolute da puro “acceleratore grafico” ad unita’ altamente programmabili: in pratica oggi sono dei massicci processori paralleli (sempre cmq specializzati in grafica, con molte funzioni dedicate) che possono eseguire codice generico… non generico come una CPU (ad es. non puoi far girare un sistema operativo sulla GPU, ad oggi), ma e’ un eccellente “number-cruncher”, cioe’ se devi fare una tonnellata di operazioni matematiche, e queste possono essere eseguite in parallelo, allora la GPU fa al caso tuo.
E’ come paragonare una Ferrari ad un camion: se devi portare una persona dal punto A al punto B, la Ferrari (la CPU) fa prima; ma se devi portare 15 tonnellate di mattoni, ti serve un camion :)
Se hai un camion Ferrari puoi trasportare 15 tonnellate di mattoni a 300 Km/h? http://www.album-mmt.it/data/media/346/2_2.jpg
:-D
@Pleg
Ho capito, grazie per la spiegazione :D
@Antonio Barda
http://www.nvidia.it/object/product-quadro-6000-it.html
Questa mi sa che è qualcosa di molto simile ad un camion-ferrari xD
Complimenti, bell’articolo come sempre :)
Non so se siamo solo 5 o 5000 a seguirti, ma quelli che ci sono immagino appassionatissimi. Ho tardato a rispondere, ma l’articolo l’ho letto appena uscito, ho l’appuntamento fisso con questa rubrica! Mi consenti di approfondire un’argomento che mi appassiona, ma per il quale altrimenti non avrei il tempo di cercare informazioni con questo livello di dettaglio. Non vedo l’ora in cui arriverai a descrivere le soluzioni delle architetture più attuali (non so però se i dettagli tecnici siano già disponibili…).
Grazie :)
I dettagli delle soluzioni adottate nelle macchine di adesso sono in genere sconosciuti (a meno che non ci lavori, e allora cmq hai firmato clausole di riservatezza e non divulgazione, quindi ciccia :)
Ma qualcosa di piu’ recente ci sara’ nel prossimo articolo: la trace cache del Pentium4 e’ curiosa e interessante, fonde insieme cache e predittore (che, alla fin fine, stanno insieme alla testa della pipeline e la alimentano di istruzioni, quindi perche’ no? :) , e il predittore bimodale pare sia usato nel Sandy Bridge, in una qualche sua variante.
Potrei cercare articoli dell’IEEE, che in genere hanno la roba piu’ aggiornata, ma sono anche di solito terribilmente aridi e specialistici e mal si adattano ad articoli di carattere piu’ generale come quelli che scrivo.