Buona domanda, o almeno una con una risposta interessante. Parte di questa risposta rappresenta un mondo in cui le CPU possono scalare in modo efficiente in larghezza anziché con più core separati. I modelli di licenza / prezzo sarebbero diversi!
Il resto spiega perché non possono. Sommario:
- Il costo di più core si avvicina a linearmente
- Il costo dell'ampliamento della scala della pipeline superscalare di 1 core ~ quadraticamente ~ Questo è fattibile con una forza bruta sufficiente, fino a un certo punto. Le prestazioni a thread singolo sono molto importanti per l'uso interattivo (la latenza end-to-end è importante, non solo la velocità effettiva), quindi le attuali CPU high-end di fascia alta pagano quel prezzo. ad es. Skylake (4 in larghezza), Ryzen (5 o 6 in larghezza) e Apple A12 (7 in larghezza per i core più grandi, 3 in larghezza per i core a basso consumo energetico)
- Gravi decrementi dell'IPC si riducono semplicemente allargando la pipeline oltre 3 o 4, anche con l'esecuzione fuori servizio per trovare l' ILP . I fallimenti delle filiali e quelli della cache sono difficili e bloccano ancora l'intera pipeline.
Non hai menzionato la frequenza, solo IPC, ma anche la frequenza di ridimensionamento è difficile. Una frequenza più alta richiede una tensione più elevata, quindi le scale di potenza con frequenza a cubetti : ^1
dalla frequenza direttamente e ^2
dalla tensione. (Il condensatore immagazzina bilance di energia con V ^ 2 e la maggior parte della potenza dinamica oltre la corrente di dispersione proviene dalla carica di pompaggio nei carichi capacitivi di cancelli FET + fili.)
Prestazioni = frequenza volte IPC. (All'interno della stessa architettura. WIDE SIMD consente di eseguire lo stesso lavoro con meno istruzioni e alcuni ISA sono più densi di altri, ad esempio MIPS spesso richiede più istruzioni per eseguire lo stesso lavoro di x86 o AArch64.)
I costi sono in area die (costo di produzione) e / o potenza (che limita indirettamente la frequenza perché il raffreddamento è difficile). Inoltre, ridurre la potenza e le prestazioni per Watt è un obiettivo in sé, soprattutto per dispositivi mobili (batteria) e server (densità di potenza / costi di raffreddamento / costi di elettricità).
Prima che il multi-core per socket fosse una cosa, avevi sistemi multi-socket per casi d'uso di fascia alta in cui volevi più throughput di quanto fosse ottenibile con una singola CPU che potesse essere prodotta, quindi quelli erano gli unici sistemi SMP. (Server, workstation di fascia alta).
Se un singolo core potesse scalare in modo efficiente come desiderato, avremmo sistemi con 1 core fisico per socket e SMT (ad esempio HyperThreading) per consentire loro di agire come più core logici. I desktop / laptop tipici avrebbero solo 1 core fisico e non avremmo difficoltà a parallelizzare cose che non si ridimensionano linearmente con più core. per esempiomake -j4
per sfruttare server multi-socket e / o nascondere la latenza I / O su un desktop. (O forse proveremmo ancora a parallelizzare molto se la larghezza della pipeline si ridimensionasse facilmente ma IPC no, quindi dovevamo usare più thread SMT.) Il kernel del tuo sistema operativo avrebbe comunque bisogno di funzionare su tutti i core logici, a meno che la CPU presenta SMT al sistema operativo era molto diverso, quindi sarebbero ancora necessari algoritmi di programmazione parallela e blocco.
Donald Knuth ha detto in un'intervista del 2008
Potrei anche infiammare un po 'la mia infelicità personale con l'attuale tendenza verso l'architettura multicore. Per me, sembra più o meno che i progettisti hardware abbiano esaurito le idee e che stiano cercando di passare la colpa per la futura fine della Legge di Moore agli scrittori di software dandoci macchine che funzionano più velocemente solo su alcuni parametri chiave!
Sì, se potessimo avere miracolose CPU single-core con un throughput 8x su programmi reali , probabilmente le useremmo comunque. Con i sistemi a doppia presa solo quando valeva la pena pagare molto di più per una maggiore produttività (non prestazioni a thread singolo).
Più CPU riduce i costi di cambio di contesto quando sono in esecuzione più programmi (lasciandoli funzionare realmente in parallelo invece di passare rapidamente da uno all'altro); il multitasking preventivo che interrompe l'enorme macchinario fuori servizio che una tale CPU richiederebbe probabilmente farebbe ancora più male di quanto non faccia ora.
Fisicamente sarebbe single core (per una semplice gerarchia di cache senza interconnessioni tra core) ma supporterebbe SMT (ad esempio HyperThreading di Intel) in modo che il software potesse usarlo come 8 core logici che competono dinamicamente per le risorse di throughput. O quando solo 1 thread è in esecuzione / non bloccato, otterrà il massimo beneficio.
Quindi useresti più thread quando ciò è effettivamente più semplice / naturale (ad esempio processi separati in esecuzione contemporaneamente) o per problemi facilmente parallelizzabili con catene di dipendenze che impedirebbero di massimizzare l'IPC di questa bestia.
Ma sfortunatamente è auspicabile pensare da parte di Knuth che le CPU multi-core smetteranno mai di essere una cosa a questo punto.
Ridimensionamento delle prestazioni a thread singolo
Penso che se realizzassero un equivalente a 1 core di una CPU a 8 core, un core avrebbe un aumento dell'800% dell'IPC in modo da ottenere le massime prestazioni in tutti i programmi, non solo quelli ottimizzati per più core.
Sì è vero. Se fosse possibile costruire una tale CPU , sarebbe davvero sorprendente. Ma penso che sia letteralmente impossibile nello stesso processo di fabbricazione dei semiconduttori (ovvero la stessa qualità / efficienza dei transistor). Certamente non è possibile con lo stesso budget di potenza e la stessa area di una CPU a 8 core, anche se risparmieresti logica per incollare i core insieme e non avresti bisogno di tanto spazio per le cache private per core.
Anche se permetti aumenti di frequenza (dato che il vero criterio è lavorare al secondo, non lavorare per clock), rendere anche una CPU 2 volte più veloce sarebbe una sfida enorme.
Se fosse possibile in qualsiasi luogo vicino alla stessa potenza e allo stesso budget di area (quindi costo di produzione) costruire una tale CPU, sì, i fornitori di CPU le avrebbero già costruite in quel modo.
Nello specifico, più core o core più ampi? sezione, affinché il background necessario per comprendere questa risposta; inizia in modo semplice con il funzionamento delle CPU con pipeline in ordine, quindi superscalare (istruzioni multiple per clock). Spiega quindi come abbiamo colpito il power-wall proprio attorno all'era P4, portando alla fine del facile ridimensionamento della frequenza, lasciando principalmente solo IPC e facendo più lavoro per istruzione (ad es. SIMD) come percorso, anche con transistor più piccoli.
L'ampliamento di una pipeline (istruzioni massime per orologio) in genere riduce i costi in termini di larghezza al quadrato . Tale costo viene misurato nell'area dello stampo e / o della potenza, per un più ampio controllo delle dipendenze in parallelo (rilevamento dei pericoli) e un più ampio programmatore fuori servizio per trovare le istruzioni pronte per l'esecuzione. E più porte di lettura / scrittura sul file di registro e cache se si desidera eseguire istruzioni diverse da nop
. Soprattutto se hai istruzioni a 3 input come FMA o add-with-carry (2 registri + flag).
Ci sono anche rendimenti IPC decrescenti per ampliare le CPU ; la maggior parte dei carichi di lavoro ha ILP (parallelismo a livello di istruzione) limitato su piccola scala / a corto raggio per lo sfruttamento delle CPU, quindi allargare il core non aumenta l'IPC (istruzioni per clock) se l'IPC è già limitato a meno della larghezza del core per catene di dipendenze, filiali mancate, cache mancate o altre bancarelle. Sicuramente otterresti un aumento di velocità in alcuni loop non srotolati con iterazioni indipendenti, ma non è quello che la maggior parte del codice trascorre la maggior parte del suo tempo a fare. Le istruzioni di confronto / ramo costituiscono il 20% del mix di istruzioni nel codice "tipico", IIRC. (Penso di aver letto numeri dal 15 al 25% per vari set di dati.)
Inoltre, una mancanza di cache che blocca tutte le istruzioni dipendenti (e quindi tutto una volta raggiunta la capacità ROB) costa di più per una CPU più ampia. (Il costo opportunità di lasciare inattive più unità di esecuzione; più potenziale lavoro da non svolgere.) O un ramo mancante provoca allo stesso modo una bolla.
Per ottenere 8 volte l'IPC, avremmo bisogno almeno di un miglioramento di 8 volte nell'accuratezza della previsione delle succursali e nelle percentuali di hit della cache . Ma le percentuali di hit della cache non si adattano bene con la capacità della cache oltre un certo punto per la maggior parte dei carichi di lavoro. E il prefetching HW è intelligente, ma non può essere così intelligente. E a 8 volte l'IPC, i predittori di filiali devono produrre 8 volte il numero di previsioni per ciclo, oltre a renderle più accurate.
Le attuali tecniche per la realizzazione di CPU con esecuzione fuori servizio possono trovare ILP solo su brevi intervalli . Ad esempio, la dimensione ROB di Skylake è 224 Uops di dominio fuso, lo scheduler per Uops non eseguiti è di 97 dominio non fuso. Vedere Comprensione dell'impatto di lfence su un loop con due lunghe catene di dipendenze, per aumentare le lunghezze in un caso in cui la dimensione dello scheduler è il fattore limitante nell'estrazione di ILP da 2 lunghe catene di istruzioni, se diventano troppo lunghe. E / o vedi questa risposta più generale e introduttiva ).
Quindi trovare ILP tra due lunghi loop separati non è qualcosa che possiamo fare con l'hardware. La ricompilazione binaria dinamica per la fusione di loop potrebbe essere possibile in alcuni casi, ma è difficile e non qualcosa che le CPU possono davvero fare a meno che non seguano la rotta Transmeta Crusoe. (strato di emulazione x86 sopra un diverso ISA interno; in tal caso VLIW). Ma i moderni modelli x86 standard con cache uop e potenti decodificatori non sono facili da battere per la maggior parte del codice.
E al di fuori di x86, tutti gli ISA ancora in uso sono relativamente facili da decodificare, quindi non c'è motivazione per la ricompilazione dinamica oltre alle ottimizzazioni a lunga distanza. TL: DR: sperando in compilatori magici che possano esporre più ILP all'hardware non ha funzionato per Itanium IA-64 , ed è improbabile che funzioni per una CPU super-wide per qualsiasi ISA esistente con un modello seriale di esecuzione.
Se avessi una CPU super-wide, vorresti sicuramente supportarla SMT in modo da poterla nutrire con il lavoro da eseguire eseguendo più thread a basso ILP.
Poiché Skylake è attualmente largo 4 uops (e raggiunge un reale IPC da 2 a 3 uops per clock, o anche più vicino a 4 nel codice ad alta velocità effettiva), un'ipotetica CPU 8x più ampia sarebbe larga 32!
Essere in grado di ritagliarlo in 8 o 16 CPU logiche che condividono in modo dinamico quelle risorse di esecuzione sarebbe fantastico: i thread non bloccati ottengono tutta la larghezza di banda del front-end e il throughput del back-end.
Ma con 8 core separati, quando un thread si blocca non c'è nient'altro da mantenere alimentate le unità di esecuzione; gli altri thread non ne beneficiano.
L'esecuzione è spesso esplosiva: si blocca in attesa di un mancato caricamento della cache, quindi una volta che arrivano molte istruzioni in parallelo possono usare quel risultato. Con una CPU super-wide, l'esplosione può andare più veloce e può davvero aiutare con SMT.
Ma non possiamo avere magiche CPU super-wide
Quindi, per ottenere il rendimento, dobbiamo invece esporre il parallelismo all'hardware sotto forma di parallelismo a livello di thread . Generalmente i compilatori non sono bravi a sapere quando / come usare i thread, tranne che per casi semplici come loop molto grandi. (OpenMP o gcc's -ftree-parallelize-loops
). Ci vuole ancora intelligenza umana per rielaborare il codice per fare in modo efficiente un lavoro utile fatto in parallelo, perché la comunicazione tra thread è costosa, così come l'avvio del thread.
TLP è un parallelismo a grana grossa, a differenza dell'ILP a grana fine all'interno di un singolo thread di esecuzione che HW può sfruttare.
Le CPU mirate a carichi di lavoro interattivi (come Intel / AMD x86 e core di fascia alta Apple / ARM AArch64) contribuiscono sicuramente a ridurre i rendimenti del ridimensionamento IPC, perché le prestazioni a thread singolo sono ancora così preziose quando la latenza è importante, non solo la produttività per problemi fortemente paralleli.
Essere in grado di eseguire 8 copie di un gioco in parallelo a 15 fps ciascuno è molto meno prezioso di essere in grado di eseguire una copia a 45 fps. I venditori di CPU lo sanno, ed è per questo che le moderne CPU usano l'esecuzione fuori servizio anche se costa una notevole potenza e un'area di stampo. (Ma le GPU non lo fanno perché il loro carico di lavoro è già enormemente parallelo).
L'hardware Xeon Phi a molti core di Intel (Knight's Landing / Knight's Mill) è un interessante punto di mezzo: esecuzione fuori servizio molto limitata e SMT per mantenere i core a 2 larghezze alimentati con le istruzioni SIMD AVX512 per ridurre i numeri. I core si basano sull'architettura Silvermont a bassa potenza di Intel. (Dirigente fuori servizio ma con una piccola finestra di riordino, molto più piccola della grande famiglia Sandybridge. E una pipeline più stretta.)
A proposito, tutto questo è ortogonale al SIMD. Fare sempre più lavoro per istruzione aiuta sempre, se è possibile per il tuo problema.
Modelli di prezzo
I modelli di prezzo del software sono basati sull'attuale panorama dell'hardware.
I modelli di licenza per core sono diventati più diffusi (e rilevanti anche per i desktop single-socket) con l'avvento delle CPU multi-core. Prima di ciò, era rilevante solo per server e grandi workstation.
Se il software non necessitasse di più core per funzionare alla massima velocità, non ci sarebbe davvero un modo per venderlo a un prezzo inferiore a persone che non ne trarranno grandi benefici perché lo eseguono su una CPU più debole. A meno che forse l'ecosistema software / hardware non abbia evoluto i controlli su "canali SMT" che consentono di configurare una larghezza massima di esecuzione per il codice in esecuzione su quel core logico. (Ancora una volta immaginando un mondo in cui le CPU si ridimensionano in larghezza della pipeline anziché più core separati.)