Numero ottimale di thread per core


281

Diciamo che ho una CPU a 4 core e voglio eseguire un processo nel minor tempo possibile. Il processo è idealmente parallelizzabile, quindi posso eseguirne parti su un numero infinito di thread e ogni thread richiede lo stesso tempo.

Poiché ho 4 core, non mi aspetto alcun aumento di velocità eseguendo più thread rispetto ai core, poiché un singolo core è in grado di eseguire un singolo thread solo in un determinato momento. Non so molto sull'hardware, quindi questa è solo una supposizione.

C'è un vantaggio nell'esecuzione di un processo parallelizzabile su più thread rispetto ai core? In altre parole, il mio processo terminerà più velocemente, più lentamente o nello stesso lasso di tempo se lo eseguo usando 4000 thread anziché 4 thread?

Risposte:


254

Se i tuoi thread non eseguono I / O, sincronizzazione, ecc. E non c'è nient'altro in esecuzione, 1 thread per core ti darà le migliori prestazioni. Tuttavia, molto probabilmente non è così. L'aggiunta di più thread di solito aiuta, ma dopo un certo punto, causano un certo peggioramento delle prestazioni.

Non molto tempo fa, stavo facendo test delle prestazioni su una macchina quad-core 2 che eseguiva un'applicazione ASP.NET su Mono con un carico abbastanza decente. Abbiamo giocato con il numero minimo e massimo di thread e alla fine abbiamo scoperto che per quella particolare applicazione in quella particolare configurazione il throughput migliore era compreso tra 36 e 40 thread. Qualunque cosa al di fuori di questi confini ha funzionato peggio. Lezione imparata? Se fossi in te, testerei con un numero diverso di thread fino a trovare il numero giusto per la tua applicazione.

Una cosa è certa: i thread 4k impiegheranno più tempo. Ci sono molti cambi di contesto.


21
Penso che la risposta di Gonzalo sia buona. Vorrei solo aggiungere che dovresti sperimentare e misurare. Il tuo programma differirà dai suoi, dai miei o da chiunque altro e solo le misurazioni del comportamento del tuo programma risponderanno correttamente alle tue domande. L'esecuzione di programmi paralleli (o concorrenti) non è un'area in cui si possono trarre buone conclusioni solo dai primi principi.
Mark ad alte prestazioni,

5
+1, + risposta: mi sorprende il fatto che avere molti più thread rispetto ai core si traduca in prestazioni migliori, anche se ha più senso se più thread significano una maggiore porzione di tempo rispetto ai thread concorrenti. Sarebbe bello che la mia applicazione potesse rilevare differenze nelle prestazioni e sintonizzarsi automagicamente sul numero ottimale di thread.
Juliet,

12
Non dovrebbe sorprenderti in uno scenario del mondo reale. I thread bloccano l'attesa di risorse IO come l'accesso al disco, la rete, ecc. E anche l'attesa che risorse non IO come altri thread finiscano di usare variabili condivise. Quello che vuoi veramente ottenere è il numero minimo di thread in modo tale che almeno un thread per core possa essere sempre in esecuzione.
patros,

4
1 filo per nucleo non è ottimale. Deve essere leggermente più, preferibilmente due volte, poiché ciò consentirà l'esecuzione di un altro thread se un thread è temporaneamente bloccato. Anche se solo in memoria. Ciò è più importante se si dispone di sistemi (P4, I7, Sun Rock ecc.) Che dispongono di SMT / HT)
Marco van de Voort

1
Da qui il "Molto probabilmente non è il caso" nella mia risposta. La ricerca del numero giusto dipende dall'applicazione e dall'architettura su cui viene eseguita.
Gonzalo,

129

Sono d'accordo con la risposta di @ Gonzalo. Ho un processo che non esegue l'I / O, ed ecco cosa ho trovato:

inserisci qui la descrizione dell'immagine

Si noti che tutti i thread funzionano su un array ma su intervalli diversi (due thread non accedono allo stesso indice), quindi i risultati potrebbero differire se hanno funzionato su array diversi.

La macchina 1.86 è un macbook air con un SSD. L'altro mac è un iMac con un normale HDD (penso che sia 7200 rpm). La macchina Windows ha anche un HDD a 7200 rpm.

In questo test, il numero ottimale era uguale al numero di core nella macchina.


14
+1 per il grafico. Chiaramente 1 thread per core è il migliore, ma è interessante notare che il sistema quad core sembra non avere un numero di thread più elevato (<100 comunque) come fanno gli altri.
Jim Garrison,

46
-1 per il grafico! Curve morbide attraverso coordinate X con valori interi? Un salto selvaggio da 1 2 3 a 10 20 30 a 50 100? E coordinate y che sono multipli di 10 più 2 per una buona misura. Questo sta facendo Excel, vero?
Spacedman,

5
@Spacedman Sì, lo è. Le curve morbide hanno un aspetto molto più bello IMHO. : D
Motasim,

22
@PascalvKooten, Il problema non è che sembra carino, ma inganna a prima vista. Innanzitutto l'asse y parte da 42, esagerando l'apparente differenza tra le macchine testate. In secondo luogo, la strana progressione dei valori dell'asse x suggerisce che il "tempo impiegato" non si ridimensiona linearmente con il "numero di thread", questo è particolarmente vero per la linea blu. Penso che il problema che altri (incluso me stesso) abbiano con esso sia che travisa i dati.
pauluss86,

13
@Spacedman La critica sul grafico è la cosa più ridicola che mi sono imbattuto nelle ultime 24 ore. Il grafico aiuta. Un sacco. Periodo. Sarebbe stato fatto meglio? Non importa a nessuno. Curva liscia anziché discreta? Questo è il tuo problema ???? Suppongo che tutti voi non includereste mai un simile grafico nella loro risposta perché non avete il tempo / energia extra per farlo sembrare buono. Questo è il mio punto.
tyrex,

50

So che questa domanda è piuttosto vecchia, ma le cose si sono evolute dal 2009.

Ci sono due cose da prendere in considerazione ora: il numero di core e il numero di thread che possono essere eseguiti all'interno di ciascun core.

Con i processori Intel, il numero di thread è definito dall'hyperthreading che è solo 2 (se disponibile). Ma Hyperthreading riduce i tempi di esecuzione di due, anche quando non si usano 2 thread! (vale a dire 1 pipeline condivisa tra due processi: questo è utile quando si hanno più processi, altrimenti no. Più core sono decisamente migliori!)

Su altri processori potresti avere 2, 4 o persino 8 thread. Quindi, se hai 8 core ciascuno dei quali supporta 8 thread, potresti avere 64 processi in esecuzione in parallelo senza cambio di contesto.

"Nessun cambio di contesto" ovviamente non è vero se si esegue con un sistema operativo standard che farà il cambio di contesto per qualsiasi altra cosa fuori dal proprio controllo. Ma questa è l'idea principale. Alcuni sistemi operativi ti consentono di allocare processori in modo che solo la tua applicazione abbia accesso / utilizzo di detto processore!

Dalla mia esperienza, se hai molti I / O, più thread sono buoni. Se hai un intenso lavoro di memoria (leggi sorgente 1, leggi fonte 2, calcolo veloce, scrivi), avere più thread non aiuta. Ancora una volta, questo dipende da quanti dati leggi / scrivi simultaneamente (cioè se usi SSE 4.2 e leggi valori a 256 bit, questo blocca tutti i thread nel loro passaggio ... in altre parole, 1 thread è probabilmente molto più facile da implementare e probabilmente quasi altrettanto veloce se non effettivamente più veloce. Ciò dipenderà dal processo e dall'architettura della memoria, alcuni server avanzati gestiscono intervalli di memoria separati per core separati, quindi thread separati saranno più veloci supponendo che i dati siano archiviati correttamente ... motivo per cui, su alcuni architetture, 4 processi verranno eseguiti più velocemente di 1 processo con 4 thread.)


4
Probabilmente ce ne sono altri, ma quello che conosco è il processore POWER di IBM. Avevano sistemi con 4 o 8 thread per processori. Ora possono avviare più core, quindi invece offrono 2 thread per core ...
Alexis Wilke,

Questo è vecchio, ma la maggior parte di Intel i5, i7 ha CPU multi-thread come ad esempio CPU i7 di solito hanno 4 core, ma 8 thread.
Edgar.

4
I processori non hanno thread. Hanno nuclei fisici e logici. Con l'hyperthreading, un singolo core fisico funziona come due core logici. Avevo una tecnologia che insisteva sul fatto che i processori con thread fossero una cosa reale, quindi ho disegnato un'immagine sulla lavagna di un processore con un fuso di filo che spuntava da esso.

@TechnikEmpire Dai un'occhiata a questo intel.com/content/www/us/en/processors/core/… , forse allora puoi contattare Intel e disegnare anche loro i thread.
g7k,

24

Le prestazioni effettive dipenderanno dal rendimento volontario di ciascun thread. Ad esempio, se i thread NON eseguono alcun I / O e non utilizzano alcun servizio di sistema (ovvero sono associati al 100% di CPU), 1 thread per core è l'ottimale. Se i thread fanno qualcosa che richiede l'attesa, dovrai sperimentare per determinare il numero ottimale di thread. 4000 thread comporterebbero un notevole sovraccarico di programmazione, quindi probabilmente non è neanche ottimale.


21

La risposta dipende dalla complessità degli algoritmi utilizzati nel programma. Ho trovato un metodo per calcolare il numero ottimale di thread effettuando due misurazioni dei tempi di elaborazione Tn e Tm per due numeri arbitrari di thread 'n' e 'm'. Per gli algoritmi lineari, il numero ottimale di thread sarà N = sqrt ((m n (Tm * (n-1) - Tn * (m-1))) / (n Tn-m Tm)).

Si prega di leggere il mio articolo per quanto riguarda i calcoli del numero ottimale per vari algoritmi: pavelkazenin.wordpress.com


4
Perché viene sottoposto a downgrade? Mi dispiace ma questa è la risposta migliore a questa domanda. gonzalo affronta la parte in grassetto della domanda e pkazen affronta il titolo. Entrambe le risposte sono molto utili, ma la risposta di pkazen è rilevante perché abbiamo un metodo sistematico per approssimare il numero di thread. Dà anche la formula per gli algoritmi linea.
tobiak777,

1
Non ho espresso il mio voto negativo, ma se lo facessi sarebbe sulla base del fatto che non esiste una vera spiegazione del perché o del modo in cui il numero ottimale di thread potrebbe essere correlato alla complessità dell'algoritmo, salvo leggere l'intero articolo collegato, che è una lettura lunga (a causa della complessità dell'articolo). Oltre a ciò, alcuni aspetti dell'articolo non mi sono chiari, soprattutto come i risultati sperimentali confermano la teoria.
Codebling

Inoltre, credo che questo calcolo presupponga che tu abbia un numero infinito di core della CPU. Sebbene si tratti di informazioni sicuramente preziose, la domanda si riferisce a macchine reali con un numero limitato di core.
Navneeth,

9

Ho pensato di aggiungere un'altra prospettiva qui. La risposta dipende dal fatto che la domanda stia assumendo un ridimensionamento debole o forte.

Da Wikipedia :

Ridimensionamento debole: come varia il tempo di soluzione con il numero di processori per una dimensione del problema fissa per processore.

Forte ridimensionamento: come varia il tempo di soluzione con il numero di processori per una dimensione del problema totale fissa.

Se la domanda assume un ridimensionamento debole, allora è sufficiente la risposta di @ Gonzalo. Tuttavia, se la domanda assume un forte ridimensionamento, c'è ancora qualcosa da aggiungere. Nel ridimensionamento forte si presuppone una dimensione del carico di lavoro fissa, quindi se si aumenta il numero di thread, la dimensione dei dati su cui ciascun thread deve lavorare diminuisce. Nelle moderne CPU gli accessi alla memoria sono costosi e sarebbe preferibile mantenere la località mantenendo i dati nella cache. Pertanto, il probabile numero ottimale di thread può essere trovato quando il set di dati di ciascun thread si adatta alla cache di ciascun core (non entrerò nei dettagli per discutere se si tratta di cache L1 / L2 / L3 del sistema).

Questo vale anche quando il numero di thread supera il numero di core. Ad esempio, supponiamo che ci siano 8 unità arbitrarie (o AU) di lavoro nel programma che verranno eseguite su una macchina a 4 core.

Caso 1: eseguire con quattro thread in cui ogni thread deve completare 2 UA. Ogni thread richiede 10 secondi per essere completato ( con molti errori nella cache ). Con quattro core il tempo totale sarà di 10 secondi (10 secondi * 4 thread / 4 core).

Caso 2: eseguire con otto thread in cui ogni thread deve completare 1 UA. Ogni thread richiede solo 2 secondi (anziché 5 secondi a causa della ridotta quantità di errori nella cache ). Con quattro core il tempo totale sarà di 4 secondi (2 secondi * 8 fili / 4 core).

Ho semplificato il problema e ignorato le spese generali menzionate in altre risposte (ad esempio, i cambi di contesto) ma spero che si ottenga il punto che potrebbe essere utile avere un numero maggiore di thread rispetto al numero disponibile di core, a seconda della dimensione dei dati che si " trattare con.


7

4000 thread contemporaneamente sono piuttosto alti.

La risposta è sì e no. Se si sta eseguendo un sacco di I / O di blocco in ogni thread, quindi sì, è possibile mostrare accelerazioni significative facendo probabilmente fino a 3 o 4 thread per core logico.

Se tuttavia non stai facendo molte cose bloccanti, l'overhead aggiuntivo con il threading lo renderà più lento. Quindi usa un profiler e vedi dove si trovano i colli di bottiglia in ogni possibile pezzo parallelo. Se stai eseguendo calcoli pesanti, quindi più di 1 thread per CPU non ti aiuterà. Se stai effettuando molti trasferimenti di memoria, non sarà di aiuto neanche. Se stai eseguendo molti I / O, ad esempio per l'accesso al disco o l'accesso a Internet, sì, più thread ti aiuteranno fino a un certo punto o almeno renderanno l'applicazione più reattiva.


7

Prova delle prestazioni.

Comincerei ad aumentare il numero di thread per un'applicazione, iniziando da 1, e poi andando a qualcosa come 100, eseguendo tre-cinque prove per ogni numero di thread e costruendo un grafico della velocità operativa rispetto al numero di thread .

Dovresti che il case a quattro thread sia ottimale, con lievi aumenti di tempo dopo, ma forse no. È possibile che l'applicazione abbia una larghezza di banda limitata, ad esempio il set di dati che si sta caricando in memoria è enorme, si verificano molti errori di cache, ecc., In modo che 2 thread siano ottimali.

Non puoi saperlo fino a quando non esegui il test.


3

Troverai quanti thread puoi eseguire sul tuo computer eseguendo il comando htop o ps che restituisce il numero di processo sul tuo computer.

Puoi usare la pagina man sul comando 'ps'.

man ps

Se si desidera calcolare il numero di tutti i processi degli utenti, è possibile utilizzare uno di questi comandi:

  1. ps -aux| wc -l
  2. ps -eLf | wc -l

Calcolo del numero di un processo utente:

  1. ps --User root | wc -l

Inoltre, è possibile utilizzare "htop" [Riferimenti] :

Installazione su Ubuntu o Debian:

sudo apt-get install htop

Installazione su Redhat o CentOS:

yum install htop
dnf install htop      [On Fedora 22+ releases]

Se vuoi compilare htop dal codice sorgente, lo troverai qui .


2

L'ideale è 1 thread per core, purché nessuno dei thread si blocchi.

Un caso in cui questo potrebbe non essere vero: ci sono altri thread in esecuzione sul core, nel qual caso più thread possono dare al tuo programma una porzione maggiore del tempo di esecuzione.


Dipende se si desidera che i processi in background degli utenti vengano eseguiti in modo anomalo mentre l'applicazione è in esecuzione. Per questo motivo puoi semplicemente impostare una priorità in tempo reale per ogni thread e ottenere la massima potenza. Ma agli utenti piace il multitasking.
Earlz,

2
Bene, abbiamo a che fare con un'applicazione magica idealmente parallelizzabile. Se mai avessi creato una cosa del genere, mi sarei sentita in diritto di dare il massimo alla CPU.
patros,

2

Un esempio di molti thread ("pool di thread") vs uno per core è quello dell'implementazione di un web server in Linux o Windows.

Poiché i socket sono sottoposti a polling in Linux, molti thread possono aumentare la probabilità che uno di essi esegua il polling del socket giusto al momento giusto, ma il costo di elaborazione complessivo sarà molto elevato.

In Windows il server verrà implementato utilizzando le porte di completamento I / O - IOCP - che renderanno guidato l'evento dell'applicazione: se un I / O completa il sistema operativo avvia un thread di stand-by per elaborarlo. Quando l'elaborazione è stata completata (in genere con un'altra operazione I / O come in una coppia richiesta-risposta) il thread ritorna alla porta IOCP (coda) per attendere il completamento successivo.

Se nessun I / O è stato completato, non è necessario eseguire alcuna elaborazione e non viene avviato alcun thread.

Infatti, Microsoft non consiglia più di un thread per core nelle implementazioni IOCP. Qualsiasi I / O può essere collegato al meccanismo IOCP. IOC possono anche essere pubblicati dall'applicazione, se necessario.


Non so di quale Linux stia parlando, ma i miei blocchi fino all'arrivo di una connessione. Ti suggerisco di leggere alcune cose su select () e FD_SET () e funzioni / macro simili.
Alexis Wilke,

Ok, quindi non esiste una forma asincrona che ritorni immediatamente?
Olof Forshell il

Dalla pagina man select ():timeout is an upper bound on the amount of time elapsed before select() returns. If both fields of the timeval structure are zero, then select() returns immediately. (This is useful for polling.) If timeout is NULL (no timeout), select() can block indefinitely.
Alexis Wilke,

0

parlando dal punto di vista del calcolo e della memoria (calcolo scientifico) 4000 thread rallenteranno l'esecuzione dell'applicazione. Parte del problema è un sovraccarico molto elevato di cambio di contesto e molto probabilmente una localizzazione di memoria molto scarsa.

Ma dipende anche dalla tua architettura. Da dove ho sentito che i processori Niagara sono in grado di gestire più thread su un singolo core utilizzando una sorta di tecnica avanzata di pipelining. Tuttavia non ho esperienza con quei processori.


0

Spero che abbia un senso, controlla l'utilizzo della CPU e della memoria e metti un valore di soglia. Se il valore di soglia viene attraversato, non consentire di creare un nuovo thread altrimenti consentire ...

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.