L'uso di più core richiede l'esposizione esplicita del parallelismo a livello di thread al sistema operativo, che di solito richiede al programmatore di scrivere un programma multi-thread. (O per eseguire un programma a thread singolo più volte su input diversi, come la compilazione con make -j4
)
Tuttavia, i compilatori per alcune lingue supportano l'auto-parallelizzazione. Ad esempio, C o C ++ con OpenMP possono compilare un normale for()
ciclo in un programma che avvia più thread.
#pragma omp parallel for
for(int i = 0; i < 1000000; ++i)
{
A[i] = B[i] * constant + C[i];
}
Tuttavia, ciò deve accadere quando hai scritto o compilato il programma. Non è possibile che hardware e sistemi operativi attuali utilizzino più core per velocizzare un programma a thread singolo.
Correlati: come viene eseguito un singolo thread su più core? : risposta: non lo fanno. Esistono altri tipi di parallelismo, come il parallelismo a livello di istruzione che un singolo core della CPU trova e sfrutta per eseguire un singolo thread più velocemente di un'istruzione alla volta.
La mia risposta a questa domanda entra in alcuni dettagli di come le moderne CPU trovano e sfruttano il parallelismo a livello di istruzione a grana fine. (Principalmente focalizzato su x86). Questo è solo una parte del funzionamento delle normali CPU, avendo più istruzioni in volo contemporaneamente e non è qualcosa che devi abilitare in modo speciale. (Ci sono contatori delle prestazioni che possono farti vedere quante istruzioni per clock la tua CPU è riuscita a eseguire durante l'esecuzione di un programma o altre misure.)
Si noti che RPi3 utilizza core della CPU ARM Cortex-A53 in ordine . Ogni core è superscalare a 2 dimensioni (2 istruzioni per clock come ILP consente), ma non può riordinare le istruzioni per trovare più parallelismo a livello di istruzione e nascondere la latenza.
Tuttavia, la CPU è pipeline, quindi il numero totale di istruzioni in volo (dal recupero e decodifica fino alla fase di riscrittura alla fine della pipeline) è significativo. Quando le dipendenze dei dati non limitano le cose, ci possono essere 2 istruzioni in ogni fase della pipeline su cui la CPU sta lavorando, con un throughput di 2 istruzioni per clock. (Ecco cosa significa 2 in larghezza.)
Non può eseguire le istruzioni fuori servizio, ma con un attento ordinamento delle istruzioni (di solito da un compilatore) può comunque nascondere la latenza di un'istruzione che impiega più cicli affinché il suo output sia pronto. (ad esempio un carico anche se colpisce nella cache o una moltiplicazione richiederà più cicli, invece che un add sia pronto il ciclo successivo). Il trucco è ordinare le istruzioni asm in modo che ci siano più istruzioni indipendenti tra quella che produce un risultato e quella che lo utilizza.
Avere un software (un compilatore) che programma staticamente le istruzioni è più fragile che avere hardware che può riordinare internamente preservando l'illusione di funzionare nell'ordine del programma. È molto difficile per i compilatori fare un buon lavoro come anche una piccola finestra fuori servizio per le istruzioni di riordino perché i mancati cache sono imprevedibili ed è difficile analizzare le catene di dipendenze tra le chiamate di funzione al momento della compilazione. E il numero di registri è limitato senza rinominare i registri hardware.
Tutto questo è un piccolo conforto quando il tuo codice viene eseguito più lentamente di quanto desideri. Sicuramente ci sono molte cose interessanti sotto il cofano in un Cortex-A53, ma ci sono altre cose interessanti sotto il cofano in un Cortex-A57 (come l'esecuzione fuori servizio di un massimo di 3 istruzioni per orologio), e ancora di più in una grande CPU x86 come Skylake (per non parlare delle differenze di velocità di clock).
Cortex-A53 è piuttosto fantastico rispetto a un https://en.wikipedia.org/wiki/Classic_RISC_pipeline come MIPS originale di cui avresti imparato a studiare in classe di architettura informatica, ma per gli standard moderni è piuttosto di fascia bassa.