Che cosa fa MaxDegreeOfParallelism?

Sto usando Parallel.ForEach e sto facendo alcuni aggiornamenti del database, ora senza impostare MaxDegreeOfParallelism, un computer con processore dual core risulta in timeout client SQL, dove altrimenti il ​​processore quad core in qualche modo non ha timeout.

Ora non ho il controllo su quale tipo di core del processore sono disponibili dove viene eseguito il mio codice, ma ci sono alcune impostazioni che posso modificare con MaxDegreeOfParallelism che probabilmente eseguirà meno operazioni contemporaneamente e non determinerà timeout?

Posso aumentare i timeout ma non è una buona soluzione, se sulla CPU inferiore posso elaborare meno operazioni simultaneamente, questo metterà meno carico sulla cpu.

Ok, ho letto anche tutti gli altri post e MSDN, ma impostando MaxDegreeOfParallelism su un valore inferiore, le mie macchine quad core soffriranno?

Ad esempio, c’è comunque qualcosa da fare, se la CPU ha due core, quindi usare 20, se la CPU ha quattro core allora 40?

La risposta è che è il limite superiore per l’intera operazione parallela, indipendentemente dal numero di core.

Quindi, anche se non si utilizza la CPU perché si sta aspettando su IO o su un blocco, non verranno eseguite altre attività in parallelo, ma solo il massimo specificato.

Per scoprirlo, ho scritto questo pezzo di codice di prova. C’è un blocco artificiale lì per stimolare il TPL ad usare più thread. Lo stesso accadrà quando il tuo codice è in attesa di IO o database.

class Program { static void Main(string[] args) { var locker = new Object(); int count = 0; Parallel.For (0 , 1000 , new ParallelOptions { MaxDegreeOfParallelism = 2 } , (i) => { Interlocked.Increment(ref count); lock (locker) { Console.WriteLine("Number of active threads:" + count); Thread.Sleep(10); } Interlocked.Decrement(ref count); } ); } } 

Se non si specifica MaxDegreeOfParallelism, la registrazione della console mostra che fino a circa 8 attività sono in esecuzione contemporaneamente. Come questo:

 Number of active threads:6 Number of active threads:7 Number of active threads:7 Number of active threads:7 Number of active threads:7 Number of active threads:7 Number of active threads:6 Number of active threads:7 Number of active threads:7 Number of active threads:7 Number of active threads:7 Number of active threads:7 Number of active threads:7 Number of active threads:7 Number of active threads:7 Number of active threads:7 Number of active threads:7 Number of active threads:7 Number of active threads:7 

Inizia più basso, aumenta nel tempo e alla fine sta cercando di eseguire 8 contemporaneamente.

Se lo limito ad un valore arbitrario (diciamo 2), ottengo

 Number of active threads:2 Number of active threads:1 Number of active threads:2 Number of active threads:2 Number of active threads:2 Number of active threads:2 Number of active threads:2 Number of active threads:2 Number of active threads:2 Number of active threads:2 Number of active threads:2 Number of active threads:2 Number of active threads:2 Number of active threads:2 Number of active threads:2 Number of active threads:2 Number of active threads:2 

Oh, e questo è su una macchina quad-core.

Ad esempio, c’è comunque qualcosa da fare, se la CPU ha due core, quindi usare 20, se la CPU ha quattro core allora 40?

Puoi farlo per rendere il parallelismo dipendente dal numero di core della CPU:

 var options = new ParallelOptions { MaxDegreeOfParallelism = Environment.ProcessorCount * 10 }; Parallel.ForEach(sourceCollection, options, sourceItem => { // do something }); 

Tuttavia, le nuove CPU tendono a utilizzare l’hyper-threading per simulare core aggiuntivi. Quindi, se si dispone di un processore quad-core, quindi Environment.ProcessorCount segnalerà probabilmente questo come 8 core. Ho scoperto che se si imposta il parallelismo per rendere conto dei core simulati, in realtà rallenta altri thread come i thread dell’interfaccia utente.

Quindi, sebbene l’operazione finisca un po ‘più velocemente, un’interfaccia utente dell’applicazione potrebbe subire un ritardo significativo durante questo periodo. La divisione di “Environment.ProcessorCount” di 2 sembra raggiungere le stesse velocità di elaborazione mantenendo la CPU disponibile per i thread UI.

Sembra che il codice che stai eseguendo in parallelo sia deadlocking, il che significa che a meno che tu non riesca a trovare e risolvere il problema che sta causando ciò, non dovresti parallelizzarlo affatto.

imposta il numero di thread da eseguire in parallelo …