prestazioni multi-threading quando la CPU è al massimo

1

Ho notato che il mio software degrada gravemente quando il numero di thread è sostanzialmente aumentato .

Ciò che intendo è che quando limite il numero di thread, le prestazioni sono molto migliori rispetto a quando le faccio girare tutte simultaneamente.

La mia cpu è un i7-3940XM, quindi molto veloce per un cellulare e non è ancora troppo trasandato rispetto ai desktop i7 per un vecchio processore. È a 4 core ma ha 8 core logici. Windows 10.

Il test case crea 65 thread e ci vogliono quasi 5 minuti per funzionare. La CPU è al massimo quando ciò accade perché il codice è per lo più tutto in memoria e le uniche risorse a cui accede con maggiore frequenza è un ram-disk.

Ma quando limito il numero di thread che possono essere eseguiti contemporaneamente, le prestazioni migliorano drasticamente:

Threads significa Thread concomitanti nell'immagine sottostante, ogni volta è per la stessa applicazione che ha eseguito 65 thread totali, solo il # di thread concorrenti varia

Quindisembracheleprestazionisianolemiglioriquandoil#dithreadèvicinoal#deicorelogici

Ilmotivopercuistopostandoèchemichiedosedevoindagareulteriormentesehoqualcosache"blocca" nel mio codice, non capisco davvero perché quando non c'è un limite sul numero di thread simultanei rallenta così drammaticamente.

Qualcuno può offrire qualche pensiero?

Aggiornamento:

Ho trovato un codice di scrittura / lettura di file che avevo dimenticato e spento - quindi con 8 thread simultanei non ha fatto differenza nel tempo per thread ma a 65 è caduto fino a 1,00 secondi media per thread

    
posta ycomp 09.06.2016 - 20:40
fonte

2 risposte

5

Sembra che tu stia riscontrando problemi Cambio di contesto . (L'articolo collegato parla di interi processi piuttosto che di thread, ma l'idea è simile) C'è un costo molto reale incorso quando una CPU passa dal lavorare su una cosa a un'altra.

Come hai scoperto, quando il numero di CPU corrisponde approssimativamente al numero di thread, le CPU non devono mettere giù un po 'di lavoro per raccogliere e lavorare su un altro molto spesso.

Se hai "troppi" thread, allora il sistema operativo cercherà di fare progressi approssimativamente uguali su tutti loro allo stesso tempo. Dato che non hai molti core, significa che ogni core raccoglierà un thread, farà un po 'di lavoro, salverà il lavoro da qualche parte, raccoglierà il thread successivo e ripeterà. Il "prelevamento" e "salvataggio" si sommano.

Il threading è utile per mantenere viva un'interfaccia utente e può essere molto utile per il lavoro intensivo di I / O (dove si impiega molto tempo ad attendere l'arrivo o la partenza dei bit). Una volta che hai passato "tieni tutti i core occupati", non è troppo utile per velocizzare le operazioni legate alla CPU.

    
risposta data 09.06.2016 - 20:54
fonte
2

Poiché Dan Pichelman ha sottolineato nella sua risposta, sembra che tu stia incontrando grandi quantità di contesto interruttori. Ecco cosa sta succedendo in forma d'arte ASCII, su un computer a tre core più semplice. Avrò interruttori di contesto utilizzare un periodo di tempo ciascuno, e fare 24 periodi di tempo di lavoro divisi equamente tra i thread. Per evitare thread affamati di runtime, ci sarà uno switch di contesto ogni tre periodi al thread successivo nella coda. Se la coda è vuota, il thread corrente continuerà a essere eseguito senza un interruttore di contesto.

Con tre thread (8 unità di lavoro per thread) finiamo tutto il lavoro alla fine del 9 ° periodo:

Core  Time Period
        1  2  3  4  5  6  7  8  9
0     |CS|a0|a1|a2|a3|a4|a5|a6|a7|
1     |CS|b0|b1|b2|b3|b4|b5|b6|b7|
2     |CS|c0|c1|c2|c3|c4|c5|c6|c7|

Con sei thread (4 unità di lavoro per thread), le cose impiegano un po 'più di tempo, grazie a tutti i cambi di contesto:

Core  Time Period
        1  2  3  4  5  6  7  8  9 10 11 12
0     |CS|a0|a1|a2|CS|d0|d1|d2|CS|a3|CS|d3|
1     |CS|b0|b1|b2|CS|e0|e1|e2|CS|b3|CS|e3|
2     |CS|c0|c1|c2|CS|f0|f1|f2|CS|c3|CS|f3|

E per completezza, ecco solo due thread (12 unità di lavoro per thread), impiegando più tempo ancora con il core 2 inattivo:

Core  Time Period
        1  2  3  4  5  6  7  8  9 10 11  12  13
0     |CS|a0|a1|a2|a3|a4|a5|a6|a7|a8|a9|a10|a11|
1     |CS|b0|b1|b2|b3|b4|b5|b6|b7|b8|b9|b10|b11|
2     |CS| i| i| i| i| i| i| i| i| i| i|  i|  i|

Si noti inoltre che i processori con hyperthreading o cose simili, come i due core per modulo in alcuni processori AMD, hanno risorse condivise tra thread sullo stesso core o sullo stesso modulo. Questo potrebbe portare a un thread in attesa che l'altro finisca di usare quella risorsa. Tuttavia, questo non sembra essere un problema significativo per te, se non del tutto, dato che la tua esecuzione su 5 thread (che dovrebbe evitare la maggior parte tali conflitti) è stata più lenta delle tue 8 e 10 esecuzioni di thread (che avere maggiori probabilità di incontrare tali conflitti).

    
risposta data 09.06.2016 - 21:48
fonte

Leggi altre domande sui tag