2009-06-10 8 views
8

Ho un lavoro imbarazzante-parallelizzabile in un'app console .NET 3.5 e voglio sfruttare i processori hyperthreading e multi-core. Come scegliere il miglior numero di thread di lavoro per utilizzare uno di questi il ​​meglio su un sistema arbitrario? Ad esempio, se si tratta di un dual core, desidero 2 thread; quad core Voglio 4 thread. Quello che sto alla fine è determinare le caratteristiche del processore, così posso sapere quanti thread creare.Come scegliere il miglior numero di thread per hyptherthreading/multicore?

Non sto chiedendo come suddividere il lavoro né come eseguire il threading, mi sto chiedendo come faccio a determinare il numero "ottimale" dei thread su una macchina arbitraria su cui verrà eseguita questa console.

+0

Il numero "ottimale" non è necessariamente il numero di processori che possiedi. Si basa su questo, ma a seconda di cosa stai facendo, i thread non saranno sempre in elaborazione, quindi avere più thread rispetto ai processori è spesso più efficiente. –

risposta

9

È possibile utilizzare Environment.ProcessorCount se è l'unica cosa che si sta cercando. Ma solitamente usare un ThreadPool è davvero l'opzione migliore.

Il pool di thread .NET ha anche disposizioni per l'assegnazione a volte più thread di quello che hai core per massimizzare il throughput in alcuni scenari in cui molti thread sono in attesa di I/O per terminare.

+0

ProcessorCount è davvero quello che sto cercando. Per quanto riguarda ThreadPool: come il mio commento a Mark, come mi aiuta ThreadPool se non so quanti thread creare? –

+0

ThreadPool determina autonomamente quanti thread utilizzare su un determinato sistema. Fondamentalmente usa la stessa proprietà (se non ricordo male) a meno che tu non specifichi diversamente. – Joey

+0

Se * sai * che invierai il lavoro immediatamente, puoi utilizzare ThreadPool.SetMinThreads al conteggio del processore. – Rick

15

Suggerirei di non provare a determinarlo da soli. Usa il ThreadPool e lascia che .NET gestisca i thread per te.

+0

Questo non mi aiuta affatto. Se creo 4 thread su un single-core, nessun sistema hyperthreaded allora sto sprecando risorse. Se creo 2 thread su un quad core, sto utilizzando solo metà del processore. –

+0

L'utilizzo del ThreadPool comporta un sovraccarico, ma delega anche la responsabilità a parti sensibili che gestiscono la pianificazione in modo ragionevole. Potresti essere in grado di gestire la gestione della memoria meglio di GarbageCollector, quindi pensi di implementare il tuo garbage collector. Non proverei a indovinare come funziona il ThreadPool. – Mark

2

L'unico modo è una combinazione di analisi dei dati e del codice basata sui dati delle prestazioni.

Diverse famiglie di CPU e velocità rispetto alla velocità di memoria rispetto ad altre attività sul sistema stanno andando a rendere l'accordatura diversa.

Potenzialmente è possibile eseguire l'autoregolazione, ma ciò significa avere una qualche forma di sintonizzazione delle prestazioni dal vivo e regolazione automatica.

0

Si può affermare che il vero modo di scegliere il numero migliore di thread è che l'applicazione si profili e modifichi in modo adattivo il comportamento del thread in base a ciò che offre le migliori prestazioni.

+0

Non pensavo a quello! Grazie, vedrò quello per il mio progetto in quanto non è correlato alla macchina su cui gira ma a un SqlServer remoto. –

1

Ho letto qualcosa di recente (vedere la risposta accettata allo this question per esempio).

La semplice risposta è che si lascia decidere al sistema operativo. Può fare un lavoro molto migliore per decidere cosa è meglio di quanto puoi.

Esistono diverse domande su un tema simile: la ricerca di "numeri ottimali" (senza virgolette) offre un paio di pagine di risultati.

0

Ho scritto una semplice app per la numerazione dei numeri che utilizzava più thread e ho scoperto che sul mio sistema Quad-core, ha completato la maggior parte del lavoro in un periodo fisso utilizzando 6 thread.

Penso che l'unico vero modo per determinare sia attraverso la sperimentazione o la profilazione.

2

Una buona regola del pollice, dato che si è completamente vincolati alla CPU, è processorCount+1.

Ecco +1 perché avrete sempre ottenere alcune attività avviati/fermati/interrotto e n compiti sarà quasi mai completamente riempire n processori.

+0

Qualche idea sul perché il +1? –

+0

+1 perché si otterranno alcune attività avviate/arrestate/interrotte e n le attività non riempiranno quasi mai completamente i processori. –

+0

Per favore spiega il downvote - Mi piacerebbe sapere cosa sto facendo male. Grazie. –

1

Direi che dipende anche da ciò che si sta facendo, se la creazione di un'applicazione server utilizzando tutto il possibile dalla CPU tramite Environment.ProcessorCount o un pool di thread è una buona idea. Ma se questo è in esecuzione su un desktop o una macchina che non è dedicata a questa attività, è consigliabile lasciare un po 'di CPU inattiva in modo che la macchina "funzioni" per l'utente.

+0

È un'app console gestita dall'utente, quindi voglio ridurre i tempi di esecuzione utilizzando tutti i "processori". ProcessorCount è davvero quello che voglio però. –

3

Il numero ottimale sarebbe solo il numero di processori. Otterrete sempre un thread in esecuzione su una CPU (logica o fisica) per ridurre al minimo gli switch di contesto e l'overhead che ha con esso.

Se quello è il numero giusto dipende (proprio come tutti hanno detto) su quello che stai facendo. Il threadpool (se ho capito bene) tenta praticamente di usare il minor numero possibile di thread, ma ne gira un altro ogni volta che un thread si blocca.

Il blocco non è mai ottimale ma se si sta facendo qualsiasi forma di blocco la risposta cambierebbe drasticamente.

Il modo più semplice e semplice per ottenere un comportamento buono (non necessariamente ottimale) è utilizzare il threadpool. Secondo me è davvero difficile fare qualcosa di meglio del threadpool, quindi questo è semplicemente il miglior punto di partenza e pensare solo a qualcos'altro se riesci a dimostrare perché non è abbastanza buono.

2

O anche meglio del ThreadPool, utilizzare istanze di attività .NET 4.0 dal TPL. La libreria Task parallela è costruita su una base del framework .NET 4.0 che determinerà il numero ottimale di thread per eseguire le attività nel modo più efficiente possibile.

4

Il numero corretto è ovviamente 42.

Ora sulla nota seria. Basta usare il pool di thread, sempre.

1) Se si dispone di una lunga elaborazione compito (es. La CPU) che può essere partizionato in più pasti del pezzo allora si deve partizionare il vostro compito e poi presentare tutti gli elementi di lavoro individuali al ThreadPool. Il pool di thread raccoglierà gli elementi di lavoro e inizierà a sfornare in modo dinamico in quanto dispone di funzionalità di autocontrollo che includono l'avvio di nuovi thread secondo necessità e può essere configured at deployment by administrators according to the deployment site requirements, anziché calcolare i numeri in fase di sviluppo. Se è vero che la dimensione di partizionamento corretta dell'attività di elaborazione può tenere conto del numero di CPU disponibili, la risposta corretta dipende tanto dalla natura dell'attività e dai dati di cui non vale nemmeno la pena parlare in questa fase (e inoltre le preoccupazioni principali dovrebbero essere il NUMA nodes, la memoria locale e la contesa della cache interbloccata e solo dopo il numero di core).

2) Se si esegue l'I/O (incluse le chiamate DB), è necessario utilizzare l'I/O asincrono e completare le chiamate in ThreadPool chiamate routine di completamento.

Questi due sono gli unici validi motivi per cui è necessario disporre di più thread e sono entrambi gestiti al meglio utilizzando ThreadPool. Qualsiasi altra cosa, incluso l'avvio di una discussione per 'richiesta' o 'connessione', sono in effetti anti-pattern nel mondo dell'API Win32 (la forcella è un modello valido in * nix, ma sicuramente non in Windows).

Per una più specializzata e modo, la discussione modo più dettagliato l'argomento posso solo consigliare le carte Rick Vicik sul tema:

0

Oltre al conteggio del processore, è possibile prendere in considerazione l'affinità del processore del processo contando i bit nell'affinità maschera restituita dalla funzione GetProcessAffinityMask.

0

Se non vi è un'elaborazione I/O eccessiva o chiamate di sistema quando i thread sono in esecuzione, il numero di thread (tranne il thread principale) è in generale uguale al numero di processori/core nel sistema, altrimenti si può provare ad aumentare il numero di thread testando.

Problemi correlati