2014-09-03 8 views

risposta

5

Da qualche parte all'interno del processore. Ciò che viene fatto esattamente dipende dal processore.

In un caso molto semplice, è possibile prendere 4096 bit di dati di previsione ramo. Quindi per ogni ramo, prendi gli ultimi 12 bit dell'indirizzo del ramo, che fornisce 4096 valori diversi e prendilo come indice nei dati di previsione del ramo. E dal momento che hai solo un bit di dati, devi solo memorizzare se è stato preso l'ultimo ramo.

Il vantaggio è che è molto economico. Lo svantaggio è che due rami distano esattamente 4096 byte e usano la stessa voce nella tabella. Quindi se il tuo codice esegue sempre questi due rami e uno viene sempre preso e uno non viene mai preso, la previsione del ramo è piuttosto negativa.

Alcuni processori utilizzano due bit per ramo che significano "strong take", "taken", "not taken", "strong not take". Ogni volta che viene preso un ramo, la predizione si sposta verso "presa forte", se il ramo non viene preso si muove verso "forte non preso". Funziona meglio se i rami vengono di solito presi con rare eccezioni.

Alcuni processori non usano solo gli ultimi 12 o più bit dell'indirizzo di diramazione, ma si mischiano se dicono che sono stati presi gli ultimi quattro rami. Supponiamo che tu abbia il codice

if (x >= 0) { ... } 
if (x <= 0) { ... } 

e x è raramente 0, ma in modo piuttosto positivo, positivo o negativo. Quindi il primo ramo è difficile da prevedere, ma il secondo non viene mai preso dopo che il primo è stato preso, e sempre preso se il primo non viene preso. Mescolando queste informazioni, si utilizzano due voci nella tabella di predizione del ramo per il secondo ramo, ma la previsione per il secondo ramo sarà molto accurata, anche se il ramo è preso a caso o non preso.

Si ha sempre il problema che la stessa voce nella tabella di predizione del ramo verrà utilizzata per più di un ramo; vivi e basta. (Fare qualcosa di intelligente per gestire questa operazione richiederebbe troppo spazio di archiviazione. Stiamo utilizzando la previsione di 1 o 2 bit per filiale in modo da poter disporre di tabelle enormi con spazio di memorizzazione molto ridotto).

+0

Mi chiedevo perché non lo inseriscono in alcuni bit inutilizzati nell'opcode nel codice stesso. Suppongo che sarebbe molto lento dato che dovrebbe tornare a ram. – johnnycrash

+0

@johnnycrash, bastone cosa? la risoluzione della diramazione non è statica per una singola posizione di diramazione nel programma (un IP/PC univoco), l'esempio migliore è un ramo di loop - è preso solo fino al punto in cui non viene più preso. Alcuni predittori di branche terrebbero più voci per questi rami in vari contesti storici. Se invece si intende modificare questi bit durante il runtime, cercare il codice di auto-modifica e ripensarci. – Leeor

+0

@Leeor Poiché questo sarebbe solo un suggerimento, non ci sarebbe un problema di codice auto-modificante. (Inoltre, il front-end farebbe la modifica.) Se un programma/thread multipli eseguisse il codice, ci sarebbe un problema, nel qual caso una ricarica Icache potrebbe fare una predizione dalla cronologia di un altro thread. Ciò significherebbe anche blocchi di cache più sporchi per il writeback. –