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:
- emettere il contenuto del PC (il "registro contatore programmi") sul bus degli indirizzi;
- leggere il codice operativo dell'istruzione dal bus dati;
- PC incrementale;
- decodifica il codice operativo per capire cosa farne;
- emettere i contenuti del PC sul bus degli indirizzi;
- leggere l'operando dell'istruzione (in questo caso 10) dal bus dati;
- PC incrementale;
- alimentare l'operando e SI al sommatore;
- emette il risultato del sommatore sul bus degli indirizzi;
- 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, operand
che 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.