Come funziona la previsione delle filiali, se è ancora necessario verificare le condizioni?


30

Stavo leggendo la risposta popolare su Branch Prediction da https://stackoverflow.com/q/11227809/555690 e c'è qualcosa che mi confonde:

  • Se hai indovinato, continua.
  • Se hai indovinato, il capitano si fermerà, tornerà indietro e ti urlerà per premere l'interruttore. Quindi può riavviare l'altro percorso.

Se indovina ogni volta, il treno non dovrà mai fermarsi.

Se indovini troppo spesso, il treno impiegherà molto tempo a fermarsi, fare il backup e riavviare.

Ma questo è quello che non capisco: per sapere se la tua ipotesi era giusta o sbagliata, devi comunque verificare le condizioni . Quindi, come funziona anche la previsione del ramo, se in entrambi i casi stai ancora eseguendo lo stesso controllo condizionale?

Quello che sto cercando di dire è che la previsione del ramo non è esattamente la stessa di non avere alcuna previsione del ramo perché stai facendo gli stessi controlli condizionali? (ovviamente mi sbaglio, ma non capisco)


1
Questo articolo wiki fa un ottimo lavoro spiegandolo.
Enderland

8
Una moderna CPU è pipeline e può fare diverse cose contemporaneamente. Quindi può iniziare a fare le sue ipotesi mentre sta ancora cercando di capire se ha indovinato. Se l'ipotesi era corretta, la pipeline continua a funzionare. In caso di ipotesi errata, la pipeline viene espulsa e l'esecuzione ricomincia dal punto "risposta giusta".
Mark Space

2
Lettura correlata: pipeline . Vorrei anche raccomandare di rileggere la risposta accettata su quella domanda SO, in quanto risponde alla tua domanda qui.

Risposte:


19

Naturalmente la condizione viene controllata ogni volta. Ma quando viene verificato, è di gran lunga nella pipeline della CPU. Nel frattempo, anche altre istruzioni sono entrate nella pipeline e sono in varie fasi di esecuzione.

Di solito, una condizione è immediatamente seguita da un'istruzione di diramazione condizionale, che si ramifica se la condizione restituisce VERO o cade se la condizione restituisce FALSO. Ciò significa che ci sono due diversi flussi di istruzioni che possono essere caricati nella pipeline dopo l'istruzione condizione e l'istruzione derivata, a seconda che la condizione sia VERA o FALSA. Sfortunatamente, immediatamente dopo aver caricato l'istruzione condition e l'istruzione branch, la CPU non sa ancora a cosa valuterà la condizione, ma deve comunque continuare a caricare roba nella pipeline. Quindi seleziona una delle due serie di istruzioni in base a un'ipotesi su cosa valuterà la condizione.

Più tardi, mentre l'istruzione della condizione percorre la pipeline, è tempo di essere valutata. A quel tempo, la CPU scopre se la sua ipotesi era giusta o sbagliata.

Se l'ipotesi risulta essere corretta, il ramo è andato nel posto giusto e le istruzioni giuste sono state caricate nella pipeline. Se si scopre che l'ipotesi era errata, allora tutte le istruzioni che sono state caricate nella pipeline dopo che l'istruzione del ramo condizionale erano errate, devono essere scartate e il recupero delle istruzioni deve ricominciare dal posto giusto.

Emendamento

In risposta al commento di StarWeaver, per dare un'idea di cosa deve fare la CPU per eseguire una singola istruzione:

Considera qualcosa di così semplice MOV AX,[SI+10]che noi umani pensiamo ingenuamente come "carica AX con la parola in SI più 10". All'incirca, la CPU deve:

  1. emettere il contenuto del PC (il "registro contatore programmi") sul bus degli indirizzi;
  2. leggere il codice operativo dell'istruzione dal bus dati;
  3. PC incrementale;
  4. decodifica il codice operativo per capire cosa farne;
  5. emettere i contenuti del PC sul bus degli indirizzi;
  6. leggere l'operando dell'istruzione (in questo caso 10) dal bus dati;
  7. PC incrementale;
  8. alimentare l'operando e SI al sommatore;
  9. emette il risultato del sommatore sul bus degli indirizzi;
  10. leggere AX dal bus dati.

Questo è un enorme 10 passi. Alcuni di questi passaggi verranno ottimizzati anche nelle CPU senza pipeline, ad esempio la CPU incrementerà quasi sempre il PC in parallelo con il passaggio successivo, il che è una cosa facile da fare perché il PC è un registro molto, molto speciale che è mai usato per nessun altro lavoro, quindi non esiste alcuna possibilità di contesa tra le diverse parti della CPU per l'accesso a questo particolare registro. Tuttavia, ci restano 8 passaggi per un'istruzione così semplice e notiamo che sto già assumendo un certo grado di raffinatezza per conto della CPU, ad esempio suppongo che non ci sarà bisogno di un passaggio aggiuntivo per il sommatore per eseguire effettivamente l'aggiunta prima che il risultato possa essere letto da essa,

Ora, considera che esistono modalità di indirizzamento più complicate, come MOV AX, [DX+SI*4+10], e anche istruzioni molto più complicate, come quelle MUL AX, operandche eseguono effettivamente cicli all'interno della CPU per calcolare il loro risultato.

Quindi, il mio punto qui è che la metafora del "livello atomico" è tutt'altro che adatta al livello di istruzione della CPU. Potrebbe essere adatto per il livello di passaggio della pipeline, se non si desidera andare troppo in basso al livello di gate logico effettivo.


2
Eh, mi chiedo se una parte del problema che le persone (incluso me) hanno nel capire questo è che è molto difficile (per me comunque) immaginare un CPU che abbia una conoscenza parziale di una singola istruzione; o avere un mucchio di istruzioni per metà finite "passare attraverso il forno a nastro per pizza" ... almeno per me, mi sento come un passaggio in scala all'atomico quando sono abituato a lavorare con le cose tra il set di erettori e il livello del tornio di metallo.
StarWeaver

1
@StarWeaver Mi è piaciuto il tuo commento, quindi ho modificato la mia risposta per affrontarlo.
Mike Nakis,

1
Caspita, bella spiegazione. Tendo a dimenticare quanto va semplicemente spostando le parole in posizioni più utili. Sto ancora visualizzando una cpu come set di forni per pizza a cinghia: 3.
StarWeaver

Vale la pena ricordare che la domanda Stack Overflow collegata all'OP - quella con 1,3 milioni di visualizzazioni che probabilmente ha introdotto oltre 1 milione di programmatori al fatto in precedenza sconosciuto che esiste anche la "previsione del ramo" - mostra un esempio in Java . Per le persone come me che sono abituate a lavorare a livello di astrazione che lingue come Java ci forniscono, anche se MOV AX,[SI+10]è alieno, non "semplice"; la maggior parte dei programmatori oggi non ha mai scritto assembly. Non "pensiamo ingenuamente" che significhi qualcosa.
Mark Amery,

@MarkAmery beh, okay, ho pensato che fosse piuttosto ovvio che per "noi umani" intendo "noi umani che osiamo scrivere in assemblea". Il punto è che anche i programmatori di linguaggio assembly non pensano alla pipeline in ogni momento, o addirittura a tutti.
Mike Nakis,

28

Pensalo come un viaggio senza GPS. Arrivi a un incrocio e pensi di dover girare, ma non ne sei completamente sicuro. Quindi fai il turno, ma chiedi al passeggero di controllare la mappa. Forse hai tre miglia lungo la strada quando finisci di discutere su dove ti trovi. Se avessi ragione, sei tre miglia più lontano di quanto saresti stato se ti fossi fermato e litigato prima di girare. Se hai sbagliato, devi voltarti.

Le pipeline della CPU funzionano allo stesso modo. Quando riescono a controllare le condizioni, sono già in fondo alla strada. La differenza è che non devono guidare indietro di tre miglia, perdono solo il vantaggio. Ciò significa che non c'è nulla di male nel provare.


2
Questa spiegazione è chiara.
sharptooth,

2

Da quanto ho capito, la previsione del ramo è molto utile quando la condizione che devi controllare richiede il risultato di qualcosa che è costoso o ancora in corso, e altrimenti giocheresti con i pollici in attesa che il valore valuti la condizione.

Con cose come l'esecuzione fuori servizio, è possibile utilizzare la previsione del ramo per iniziare a riempire i punti vuoti nella pipeline che altrimenti la CPU non sarebbe in grado di utilizzare. In una situazione in cui non ci sono, per qualche motivo, cicli inattivi nella pipeline, quindi sì, non c'è un guadagno nella previsione del ramo.

Ma la chiave qui è, la CPU sta iniziando il lavoro per uno dei rami previsti perché non può ancora valutare la condizione stessa.


1

Forma breve:

Alcune CPU possono iniziare a lavorare su una nuova istruzione prima di finire quella vecchia. Queste sono le CPU che utilizzano la previsione del ramo.

Un esempio di pseudocodice:

int globalVariable;
int Read(int* readThis, int* readThat)
{
    if ((globalVariable*globalVariable % 17) < 5)
       return *readThis;
    else
       return *readThat;
}

Il codice sopra verifica una condizione e in base al risultato deve restituire il valore memorizzato nella posizione di memoria addThiso il valore archiviato in readThat. Se la previsione del ramo prevede che la condizione sia true, la CPU leggerà già il valore memorizzato nella posizione di memoria addThismentre esegue il calcolo necessario per valutare l' ifistruzione. Questo è un esempio semplificato.


1

Sì, la condizione è verificata in entrambi i modi. Ma il vantaggio della previsione del ramo è che puoi fare un lavoro invece di aspettare il risultato del controllo delle condizioni.

Diciamo che devi scrivere un saggio e può trattarsi dell'argomento A o dell'argomento B. Sai dai precedenti saggi che al tuo insegnante piace l'argomento A meglio di B e lo sceglie più spesso. Invece di aspettare la sua decisione, puoi iniziare a scrivere il saggio sul primo argomento. Ora ci sono due possibili esiti:

  1. Hai iniziato il tuo saggio sull'argomento sbagliato e devi abbandonare ciò che hai scritto finora. Devi iniziare a scrivere sull'altro argomento ed è lo stesso sforzo di tempo che avresti aspettato.
  2. Hai indovinato bene e hai già lavorato.

Le CPU moderne sono inattive per la maggior parte del tempo perché sono in attesa di risposte IO o del risultato di altri calcoli. Questa volta può essere usato per fare qualche lavoro futuro.

Anche se devi eliminare ciò che stai facendo in questo tempo di inattività, è molto più efficace se hai la possibilità di indovinare quale percorso sceglierà il programma. E le CPU moderne hanno questa capacità.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.