Come può una CPU fornire più di un'istruzione per ciclo?


41

Le istruzioni di Wikipedia al secondo dicono che un i7 3630QM fornisce circa 110.000 MIPS a una frequenza di 3,2 GHz; sarebbe (110 / 3.2 istruzioni) / 4 core = ~ 8.6 istruzioni per ciclo per core ?! Come può un singolo core fornire più di un'istruzione per ciclo?

A mio avviso, una pipeline dovrebbe essere in grado di fornire solo un risultato per clock.

Questi sono i miei pensieri:

  • La frequenza interna è in realtà superiore a 3,2 GHz
  • Alcune parti della CPU sono asincrone in un modo che un umile umano come me non può capire
  • Esistono più pipeline simultanee per core
  • Una pipeline può fornire più del risultato per clock, un'istruzione può saltare le fasi della pipeline e ci sono più prefetcher per tenere il passo
  • Mi manca qualcosa

1
Fornisce 110.000 Dhrystone MIPS, quindi DMIPS, non MIPS, è qualcosa che vedo direttamente - forse questo potrebbe fare la differenza? Vedi en.wikipedia.org/wiki/Dhrystone

Risposte:


44

In primo luogo, come sottolinea il commento di Keelan e la risposta di Turbo J , la misurazione era di 113,093 MIPS Dhrystone e non MIPS nativi .

La microarchitettura Ivy Bridge dell'i7 3630QM può eseguire solo il commit di 4 µops fusi per ciclo, sebbene possa iniziare l'esecuzione di 6 µops per ciclo. (Il numero di µops fusi in una traccia di codice è approssimativamente uguale al numero di istruzioni; alcune istruzioni complesse vengono decodificate in più µops che non sono fuse e alcune coppie di istruzioni possono essere fuse in un singolo µop, ad esempio un confronto immediato seguito da un salto condizionale.)

Due delle tue speculazioni su come eseguire più istruzioni in un singolo ciclo sono abbastanza valide e sono state utilizzate in processori reali. La tua prima ipotesi, che viene utilizzato un orologio interno più veloce, è stata utilizzata negli ALU "fireball" originali del Pentium 4. Questi ALU erano sincronizzati al doppio della frequenza del resto del core, che era già relativamente alto.

(Ciò è stato realizzato utilizzando una ALU sfalsata in cui la metà inferiore di un'aggiunta è stata eseguita in un ciclo, consentendo a un'operazione dipendente di utilizzare la metà inferiore del risultato nel ciclo successivo. Per operazioni come aggiungi, xor o spostamento a sinistra che richiedono solo la metà inferiore degli operandi per produrre la metà inferiore completa del risultato, tale sfalsamento, noto anche come pipeline di larghezza, consente la latenza dei risultati a ciclo singolo e la produttività a ciclo singolo).

HyperSPARC utilizzava una tecnica in qualche modo correlata, ALU in cascata. HyperSPARC ha fornito i risultati di due ALU in una terza ALU. Ciò ha permesso di eseguire due operazioni indipendenti e una terza dipendente in un singolo ciclo.

La tua ipotesi che "ci sono più condutture simultanee per core" è l'altra tecnica che è stata utilizzata. Questo tipo di design è chiamato superscalar ed è di gran lunga il mezzo più comune per aumentare il numero di operazioni eseguite in un singolo ciclo.

Ci sono anche alcune altre probabilità e fini dell'esecuzione delle istruzioni che potrebbero essere degne di nota. Alcune operazioni possono essere eseguite in modo più efficiente al di fuori delle normali unità di esecuzione. La tecnica di eliminazione degli spostamenti sfrutta l'uso della ridenominazione dei registri nei processori fuori servizio per eseguire operazioni di spostamento durante la ridenominazione dei registri; lo spostamento semplicemente copia il numero di registro fisico da una posizione nella tabella di ridenominazione (chiamata tabella di alias del registro) in un'altra. Questo non solo aumenta efficacemente la larghezza di esecuzione, ma rimuove anche una dipendenza. Questa tecnica è stata utilizzata all'inizio con lo x87 basato su stack, ma ora è ampiamente utilizzata nei processori x86 ad alte prestazioni di Intel. (L'uso di istruzioni distruttive a due operandi in x86 rende l'eliminazione delle mosse più utile di quanto sarebbe in un tipico RISC.)

Una tecnica simile all'eliminazione degli spostamenti è la gestione delle istruzioni di azzeramento del registro durante la ridenominazione. Fornendo un nome di registro che fornisce il valore zero, un'istruzione di cancellazione del registro (come xor o sottrazione con entrambi gli operandi essendo lo stesso registro) può semplicemente inserire quel nome nella tabella di ridenominazione (RAT).

Un'altra tecnica utilizzata da alcuni processori x86 riduce il costo delle operazioni push e pop. Di solito un'istruzione che utilizza il puntatore dello stack dovrebbe attendere un ciclo completo per un push o pop precedente per aggiornare il valore del puntatore dello stack. Riconoscendo che push and pop aggiunge o sottrae solo un piccolo valore al puntatore dello stack, è possibile calcolare in parallelo i risultati di più aggiunte / sottotazioni. Il ritardo principale per l'addizione è la propagazione del carry, ma con valori piccoli i bit più significativi del valore base - in questo caso il puntatore dello stack - avranno al massimo un carry-in. Ciò consente di applicare un'ottimizzazione simile a quella di un sommatore carry-select a più aggiunte di valori piccoli. Inoltre, poiché il puntatore dello stack viene in genere aggiornato solo da costanti,

È anche possibile unire le istruzioni in un'unica operazione più complessa. Mentre il processo inverso di suddivisione delle istruzioni in più operazioni più semplici è una vecchia tecnica, la fusione delle istruzioni (che Intel definisce fusione macro-op) può consentire all'implementazione di supportare operazioni più complesse di quelle esposte nel set di istruzioni.

Sul lato teorico, sono state proposte altre tecniche. Costanti di piccole dimensioni diverse da zero potrebbero essere supportate nel RAT e alcune semplici operazioni che utilizzano o producono in modo affidabile valori così piccoli potrebbero essere gestite in anticipo. ("Physical Register Inlining", Mikko H. Lipasti et al., 2004, ha suggerito di utilizzare il RAT come mezzo per ridurre il conteggio dei registri, ma l'idea potrebbe essere estesa per supportare il caricamento di piccoli immediati e semplici operazioni su piccoli numeri.)

Per le cache di traccia (che memorizzano sequenze di istruzioni sotto particolari presupposti del flusso di controllo), possono esserci opportunità di unire le operazioni separate da rami e rimuovere le operazioni che producono risultati inutilizzati nella traccia. La memorizzazione nella cache delle ottimizzazioni in una cache di traccia può anche incoraggiare l'esecuzione di ottimizzazioni come l'unione di istruzioni che potrebbe non essere utile se dovessero essere eseguite ogni volta che il flusso di istruzioni veniva recuperato.

La previsione del valore può essere utilizzata per aumentare il numero di operazioni che possono essere eseguite in parallelo rimuovendo le dipendenze. Un predittore di valore basato sul passo è simile all'ottimizzazione pop / push di un motore di stack specializzato menzionato in precedenza. Può calcolare più aggiunte principalmente in parallelo, rimuovendo la serializzazione. L'idea generale di previsione del valore è che con un valore previsto, le operazioni dipendenti possono procedere senza indugio. (La direzione della diramazione e la previsione del bersaglio sono in realtà solo una forma molto limitata di previsione del valore, che consente di recuperare le seguenti istruzioni che dipendono dal "valore" della diramazione, presa o meno, e dall'indirizzo di istruzione successivo, un altro valore.)


eccezionale! Grazie per le preziose informazioni. Potresti suggerire un libro in cui posso leggere tutte queste tecniche architettoniche?
senza lavoro

@workless Una volta superate le basi della pipeline e dell'esecuzione superscalare fuori ordine (che verrebbero coperte dalla maggior parte dei libri di testo sull'architettura del computer), le migliori fonti di informazioni sono probabilmente le descrizioni di specifiche microarchitettura del processore (come l'articolo su Haswell collegato nella risposta di gnasher729 ) e documenti accademici (ISCA e MICRO [conferenze] generalmente hanno buoni articoli; HPCA, PACT, ASPLOS e forse alcuni altri hanno anche una buona reputazione). Andy Glew (forse più famoso per il suo lavoro sul Pentium Pro) ...
Paul A. Clayton

1
... stava lavorando su un wiki di CompArch, che avrebbe presentato concetti più avanzati, ma i progressi sono stati lenti e apparentemente è stato violato qualche tempo fa e quindi ora fornisce solo un messaggio di errore ( semipublic.comp-arch.net/wiki ). Intende ripristinare il wiki (il testo originale è stato conservato) utilizzando diversi software wiki (ha avuto alcuni problemi con il software che stava usando e lo sta prendendo come un'opportunità per apportare miglioramenti), ma "Ci vorrà un po '".
Paul A. Clayton,

Un buon esempio del successo dell'architettura superscalare è stato HyperThreading di Intel - con tutte queste ottimizzazioni, gli ingegneri di Intel hanno scoperto che circa il 30% della ALU era inutilizzato per la maggior parte del tempo, perché la memoria non poteva scorrere abbastanza velocemente, o il la pipeline non può essere riempita in modo abbastanza efficiente. HyperThreading ti consente di lavorare molto gratuitamente nello scenario ideale. È molto meno che avere un nuovo core separato, ma è anche molto più economico (e può essere combinato anche con il multi-core).
Luaan,

@ PaulA.Clayton - due acquisizioni di quella pagina sono su Wayback. 20 dicembre 2013 e 14 febbraio 2014 . Non so se queste acquisizioni precedano i problemi con la pagina. Sfortunatamente, quando ho provato a visitare quelle pagine su Wayback, ho ricevuto il messaggio " Bummer. La macchina che serve questo file non funziona. Ci stiamo lavorando. ", Quindi non sono sicuro di cosa si possa vedere su quelle pagine .
Kevin Fegan,

10

Parte della magia oscura accade all'interno dei moderni processori, ma i tuoi pensieri sono decisamente sulla retta via.

La chiave per comprendere l'efficienza dei moderni processori è rendersi conto che sono superscalari . Da Wikipedia (sottolineatura mia):

Un'architettura CPU superscalare implementa una forma di parallelismo chiamata parallelismo a livello di istruzione all'interno di un singolo processore. Pertanto, consente un throughput della CPU più veloce di quanto sarebbe altrimenti possibile a una determinata frequenza di clock.

Questi moderni processori hanno più unità di esecuzione per core, come hai indovinato. L'hyper-threading è interessante da considerare, alcune parti della pipeline sono duplicate ma altre no.

Anche l'esecuzione fuori ordine è interessante da leggere, ma non risponde direttamente alla tua domanda. Tuttavia, riduce il numero di cicli CPU "sprecati".

L'efficienza è influenzata anche da molte altre cose che possono causare uno stallo all'interno del processore, tra cui (ma sicuramente non limitato a):

  • I risultati delle precedenti istruzioni non sono disponibili.
  • Manca la cache.
  • La ramificazione del codice, che invaliderebbe le istruzioni già recuperate (leggi la previsione delle filiali qui e qui ).

I compilatori moderni cercano di aiutare con molti degli elementi di cui sopra, quindi il processore prende il sopravvento. Per un buon esempio, vedi questa domanda altrove su Stackexchange, che evidenzia un'importante differenza tra due istruzioni che possono fare la stessa cosa (in alcune circostanze). Tuttavia, uno può essere "più veloce" dell'altro su alcuni processori a causa dell'unità di esecuzione in uso.

Per una spiegazione leggibile dall'uomo della moderna pipeline della CPU, vedere Un viaggio attraverso la pipeline della CPU . Per una spiegazione un po 'più tecnica, consultare il documento sulla microarchitettura di Agner Fog .


grazie per la spiegazione e i collegamenti molto interessanti. Come nota Cell sembra molto interessante, non vedo l'ora di studiare di più sulle architetture della CPU ^ _ ^. "" L'x86 utilizza una "superpipeline" come descritto sopra. La famiglia Cell utilizza un approccio "sinergico" che coinvolge nove mini-cpus. È vero che ogni mini-cpu segue una pipeline per lo più in ordine, i mini-cpus hanno più pipeline superscalar parallele anziché una singola pipeline. "" "
senza lavoro

3

Cosa pensi che sia successo: tutti gli ingegneri di Intel, AMD e IBM hanno letto che una pipeline può fornire solo un risultato per ciclo, e hanno detto "vabbè, allora è tutto, non possono rendere questi processori più veloci". Oppure hanno letto questo e hanno detto: "Non è possibile fornire più di un risultato per ciclo? Vedremo a riguardo!".

Per una buona introduzione all'architettura Haswell, ad esempio, puoi seguire questo link http://www.realworldtech.com/haswell-cpu/ oppure puoi semplicemente visitare il sito Web Intel e troverai un po 'di documentazione lì.

Ogni core del processore Haswell ha un numero enorme di unità di esecuzione, che possono eseguire operazioni indipendenti l'una dall'altra, quindi più operazioni possono essere eseguite in parallelo. Successivamente, il processore Haswell ha diverse unità di esecuzione che gestiscono operazioni vettoriali con dimensioni fino a 256 bit. Un'operazione vettoriale potrebbe ad esempio eseguire quattro operazioni in virgola mobile a precisione doppia o otto operazioni in virgola mobile a precisione singola in un'operazione vettoriale. E infine, il processore Haswell supporta "fused multiply-add", il che significa che il calcolo dei tempi b più c è solo una singola operazione.

Il massimo teorico, dal momento che Haswell ha due unità in grado di aggiungere e moltiplicare le fusioni, è due operazioni di aggiungere e moltiplicare le fusioni per ciclo, ciascuna operazione che esegue otto moltiplicazioni a precisione singola più aggiunte o 32 operazioni a virgola mobile a precisione singola.

Il processore 3630 non è nell'elenco dei prezzi più recenti di Intel, ma ci sono modelli come il 3740QM con quattro core. Pertanto, anziché 32, è possibile ottenere 128 operazioni in virgola mobile per ciclo di clock. Questo è il massimo teorico. Raggiungere metà di ciò nella vita reale è una sfida, ma non impossibile per compiti adeguati. Ci sono altri processori disponibili con un massimo di 15 core (per i prezzi che nemmeno i fanatici di gioco più fanatici pagheranno).

Quindi hai una combinazione di molti moltiplicatori:

  1. Più core per processore.
  2. (L'hyperthreading, non menzionato in precedenza, consente di avvicinarsi ai limiti teorici)
  3. L'operazione di aggiunta multipla fusa esegue due operazioni aritmetiche contando solo come una.
  4. Vettori a 256 bit che eseguono 8 operazioni contando solo come una.
  5. Aggiungono due unità di esecuzione vettoriale in grado di gestire la fusione multipla.

8.6 operazioni per ciclo non sono troppo difficili da realizzare. Persino 8.6 operazioni per ciclo per core non sono troppo difficili.


Mi chiedo se sarebbe pratico o vantaggioso progettare una CPU con alcuni core con x86 e alcuni con un set di istruzioni ottimizzato per il comportamento superscalare. So che Intel e AMD fanno alcune cose piuttosto sorprendenti per aggirare i limiti nel set di istruzioni x86, ma in alcuni casi penso che conoscere alcune cose che l'attuale set di istruzioni non può esprimere sarebbe utile. Ad esempio, versioni distinte di ADDistruzioni basate sul fatto che l'overflow debba essere lasciato inalterato o dovrebbe essere impostato quando si verifica l'overflow (e lasciato impostato in caso contrario).
supercat

1
Mi rattrista il fatto che in questi tempi, molte lingue non riescano a controllare l'overflow. So che Java è praticamente bloccato da requisiti semantici, ma in linguaggi come C # che includono operatori aritmetici sia intrappolati che non intrappolati, l'unica buona ragione per cui vedo di non intrappolare l'overflow è perché si ha bisogno di un comportamento di avvolgimento. Allo stato attuale, il controllo di overflow può imporre una significativa penalità di velocità, ma se un linguaggio macchina fosse progettato attorno all'idea che il trapping di overflow non deve essere preciso fino a quando il codice può garantire che non si siano verificati overflow prima dell'operazione ...
supercat

... raggiunge alcuni punti critici, dovrebbe essere possibile ridurre quasi a zero lo overhead di trappola. Se il codice esegue un calcolo e quindi memorizza un valore in una posizione che verrà abbandonata se il primo calcolo trabocca, non dovrebbe essere necessario ritardare l'archiviazione fino a quando il processore non sa se il primo calcolo ha esito positivo, ma al momento il processore non ha modo di saperlo. Se il codice potesse semplicemente eseguire tutte le operazioni che possono essere eseguite in modo sicuro indipendentemente dal verificarsi di un overflow, quindi verificare se si sono verificati overflow impropri su uno di essi ...
supercat

... sembra che dovrebbe aiutare a ridurre le dipendenze di esecuzione.
supercat

2

Il benchmark Drystone è del 1984 e la corrispondente macchina nominale VAX MIPS 1 non è molto efficiente in termini moderni. Perfino un Cortex M3 eroga 1,25 DMPIS / MHz.

I processori per architettura Intel Core possono effettivamente eseguire più istruzioni in parallelo in un singolo core, poiché sono presenti più unità di elaborazione.


1

Ho imparato molto dallo Jon "Hannibal" Stokes di Ars Technica, articoli eccellenti ed estesi sull'argomento dell'architettura a microprocessore. Gli articoli sono un po 'datati (sembrano essere circa del 2004), ma ancora molto rilevanti.

Alcuni dei collegamenti alla parte successiva di un articolo sono interrotti, tuttavia sembra che tu possa risolverli tu stesso confrontando attentamente l'URL della prima parte e l'URL interrotto della pagina successiva (ad esempio aggiungendo un punto m-qualsiasi nell'URL).

(sì, questa è una risposta solo link glorificato, scusa; gli articoli sono troppo buoni per non menzionarli)

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.