2014-08-31 10 views
6

Sto scrivendo un'applicazione che utilizza una libreria di terze parti per eseguire calcoli pesanti.Riduci contesto Commuta tra thread con la stessa priorità

Questa libreria implementa il parallelismo internamente e genera i thread numerici specificati. Voglio eseguire diverse istanze (conteggio dinamico) di questa libreria e quindi finire con un oversubscribing piuttosto pesante della cpu.

Esiste un modo per aumentare il "quantum tempo" di tutti i thread in un processo in modo che ad es. tutti i thread con priorità normale raramente switch di contesto (yield) a meno che non siano esplicitamente ottenuti attraverso ad es. semafori?

In questo modo, è possibile evitare la maggior parte delle spese generali relative all'aumento dell'abbonamento alla CPU. Nota che in questo caso non mi interessa se un thread è affamato per alcuni secondi.

EDIT:

Un modo complicato per farlo è quello di eseguire la pianificazione filo manualmente.

  1. Enumerare tutti i thread con una priorità specifica (ad esempio normale).
  2. Sospendi tutti.
  3. Creare un ciclo che riprende/sospende i thread ogni ad es. 40 ms e si assicura che non venga eseguito alcun mor thread del conteggio corrente della CPU.

Eventuali svantaggi principali con questo approccio? Non sei sicuro di quale sia il sovraccarico di riprendere/sospendere un thread?

+0

Le istanze lib sono interdipendenti? In caso contrario, perché non si può evitare di sovraccaricare i core disponibili eseguendo il numero di thread come core nel modo di un pool di thread? –

+0

Bene visto che il numero di istanze cambia dinamicamente è difficile. Avrei bisogno di inizializzare/reinizializzare la libreria più volte per cambiare il numero di thread in base al carico corrente. – ronag

+0

Se si è utilizzato un pool di thread, il numero di istanze di libreria in esecuzione in qualsiasi momento sarà uguale al numero di thread nel pool. Le altre istanze della libreria si accodavano fino a quando i thread del pool non diventano disponibili per elaborarle. Non sembra esserci alcun motivo nell'applicare la CPU a un'istanza se il risultato è sovraccarico? –

risposta

4

Non c'è niente di speciale che devi fare. Qualsiasi programma di pianificazione decente non consente agli switch di contesto non forzati di consumare una parte significativa delle risorse della CPU. Qualsiasi sistema operativo che non ha uno schedulatore decente non dovrebbe essere usato.

Il sovraccarico delle prestazioni di oversubscribing della CPU è non il costo degli interruttori di contesto non forzati. Perché? Perché lo scheduler può semplicemente evitare quelli. Lo scheduler esegue solo un interruttore di contesto non forzato quando questo ha un vantaggio. I costi delle prestazioni sono:

  1. Si può richiedere più tempo per finire un lavoro perché più lavoro sarà fatto su altri posti di lavoro tra quando viene avviato il lavoro e quando il lavoro finisce.

  2. Ulteriori thread consumano memoria per le loro pile e altre informazioni di tracciamento correlate.

  3. Più thread generalmente significa più conflitto (ad esempio, quando viene allocata memoria) che può significare più commutazioni di contesto forzato in cui un thread deve essere disattivato perché non può avanzare in avanti.

Si desidera solo provare a modificare il comportamento del programma di pianificazione quando si conosce qualcosa di significativo che lo scheduler non conosce. Non c'è niente di simile che sta succedendo qui. Quindi il comportamento predefinito è quello che vuoi.

+0

Wel .. dipende dalla quantità di dati che potrebbe dover essere ricaricata nelle cache di base. Non sappiamo quanto potrebbe essere il post di OP :( –

+0

No, ma le persone che hanno progettato lo scheduler sapevano quanto fossero grandi le cache di base.Quindi potevano facilmente assicurarsi che non ci fossero così tante opzioni di contesto non forzate che il caricamento delle cache di base fosse significativo. E, naturalmente, a meno che non siano incompetenti, hanno fatto esattamente questo. –

+0

Può essere non trascurabile, su Windows comunque - ho provato questo. –

2

Eventuali svantaggi principali con questo approccio? Non sei sicuro di quale sia l'overhead di riprendi/sospendi un thread?

, riprendere/sospendere il filo è un'attività molto molto pericoloso fatto in modalità utente del programma di. Quindi non dovrebbe essere usato (quasi mai). Inoltre, non dovremmo usare questi concetti per ottenere qualcosa che qualsiasi programmatore moderno fa per noi. Anche questo è menzionato in altri post di questa domanda.

Quanto sopra è applicabile per qualsiasi sistema operativo, ma dal tag di post SO mi sembra che sia stato richiesto il sistema basato su Microsoft Windows . Ora, se leggiamo il SuspendThread() da MSDN, otteniamo la seguente:..

"Questa funzione è progettata principalmente per l'uso da parte di debugger E 'non destinati ad essere utilizzato per la sincronizzazione dei thread SuspendThread chiamata su un thread che possiede un oggetto di sincronizzazione, ad esempio un mutex o una sezione critica, può portare a un deadlock se il thread chiamante tenta di ottenere un oggetto di sincronizzazione di proprietà di un thread sospeso ".

Consideriamo quindi lo scenario in cui thread ha acquisito alcune risorse (parte implicitamente di codice non .. dalla libreria o dalla modalità kernel) e se sospendiamo il thread ciò si tradurrebbe in una situazione di deadlock misterioso come altri thread di quello processo sarebbe in attesa di quella particolare risorsa. Il fatto è che non siamo sicuri (in qualsiasi momento) nel nostro programma che quale tipo di risorse siano acquisite da qualsiasi thread in esecuzione, sospendere/riprendere il thread non è una buona idea.

Problemi correlati