Architetture dei processori/Unità di decodifica: differenze tra le versioni

Contenuto cancellato Contenuto aggiunto
Hellisp (discussione | contributi)
Hellisp (discussione | contributi)
Riga 23:
 
== Esecuzione predicativa ==
L'esecuzione predicativa è un approccio che mira a ridurre la dipendenza del processore dall'unità di predizione delle diramazioni. I microprocessori moderni sono dotati di molte unità funzionali in grado di eseguire operazioni in parallelo ma queste unità sono quasi sempre vuote. Processori anche molto complessi come il Pentium 4 pur potendo in teoria eseguire fino a 6 operazioni in contemporanea in realtà per la maggior parte del tempo eseguono una o due operazioni in parallelo. Partendo da questa constatazione l'approccio predicativo punta a riempire al massimo le unità di elaborazioni eliminando le istruzioni eseguite perma errorenon necessarie. Un processore dotato di esecuzione predicativa oltre a leggere le istruzione legge dei predicati associate a esse, questi predicati indicano al processore in caso di salto condizionato quale ramo risulta effettivamente valido. In sostanza in caso di salto condizionato il processore associasostituisce allala condizione di salto con un predicato (per esempio il predicato P0). Al blocco di istruzioni da eseguire se il salto viene eseguito viene associato il predicato P0=0 mentre al blocco di istruzioni da eseguire nel caso il salto non venga eseguito viene associato il predicato P0=1. Poi il processore esegue in parallelo l'istruzione di salto in un'unità funzionale, le istruzioni del primo blocco in una seconda un'unità funzionale e l'istruzione del secondo blocco in una terzaun'altra unità funzionale. Quando lL'istruzione di salto vienein calcolatasostanza siè vedestata seconvertita il predicato che vale 0 oppure 1 e quindi siil processore può stabilire quale blocco di istruzioni sia valido semplicemente eseguendo le istruzioni e calcolando il valore di P0 come clacola il valore di ogni operando. Il blocco con le istruzioni non valide vengonoviene individuateindividuato tramite iil predicatipredicato loro associatiassociato ed eliminateeliminato. Questa filosofia di sviluppo quindi preferisce eseguire anche istruzioni inutili pur di mantenere sempre piene le pipeline. Questa metodologia di esecuzione fornisce buone prestazioni se le pipeline non sono formate da troppi stadi. Per esempio un processore come il Pentium 4 è dotato di pipeline da 31 stadi e quindi un'esecuzione predicativa potrebbe portare ad eseguire fino a 31 operazioni inutili prima dell'individuazione del completamentovalore deldi saltoP0 e quindi dell'individuazione delle istruzioni eseguite erroneamente. Il processore Itanium 2 che implementa questa modalità di esecuzione difatti utilizza pipeline corte, a 8 stadi. L'esecuzione predicativa se non è gestita dal set di istruzioni del processore è molto costosa da implementare. Il processore dovrebbe associare in tempo reale alle istruzioni i vari predicate e tenerne traccia durante l'esecuzione. É da notare che non tutti i salti possono convenientemente essere risolti con i predicati, a volte conviene basarsi sull'unità di predizione dei salti difatti le il salto coinvolge un blocco con molte istruzioni e si ritiene di poter calcolare con buona probabilità l'esito del salto non conviene utilizzare l'esecuzione predicativa. Quale delle due alternative scegliere dipende dal codice e solo un'analisi approfondita del codice permette di individuare l'alternativa migliore ma un processore dovendo scegliere in tempo reale quale alternativa scegliere dovrebbe far affidamento su delle euristiche con non sempre danno il risultato ottimo. Invece un processore dotato nativamente di questa modalità di esecuzione deve semplicemente caricare i predicati e regolare correttamente i registri appositi dato che tutta la fase di analisi del codice è stata svolta precedentemente dal compilatore che non avendo problemi di tempo può individuare l'alternativa migliore. Un esempio classico si ha nel caso dei cicli, in un ciclo cha va da 1 a 1000 per esempio un compilatore comprenderebbe che l'esecuzione predicativa non è la scelta ottimale dato che farebbe eseguire per mille volte del codice in più. Invece, se il set di istruzioni lo consente il compilatore potrebbe indicare al processore che il salto non verrà eseguito permettendo al processore di prevedere correttamente 999 volte la diramazione corretta e sbagliano solo una volta. Invece nel caso di molti IF annidati con condizioni di salto che dipendono da dati esterni e con poche istruzioni controllate dagli IF la strategia predicativa è la migliore soluzione dato che elimina la possibilità di errore ed è in grado di gestire agevolmente anche più condizioni di salto contemporaneamente. Va detto comunque, che in generale l'esecuzione predicativa fornisce risultati peggiori di una buona unità di predizione dei salti. Difatti quasi tutti i processori implementano unità di predizioni dei salti mentre l'esecuzione predicativa è molto meno utilizzata.
 
 
Ovviamente tutte queste infrastrutture aggiuntive rendono le unità di decodifica molto complesse e queste occupano buona parte dei transistor dei moderni processori. Per ridurre il problema si sono sviluppate architetture come le architetture VLIW e derivate che affrontano il problema alla radice con un paradigma diverso eliminando alcune unità funzionali e semplificandone altre.