2012-03-26 14 views
5

utilizzando: C++ (MinGW), Qt4.7.4, Vista (OS), intel core2vProCPU core non utilizzati correttamente utilizzando qthreads

ho bisogno per elaborare i 2 file di grandi dimensioni esattamente nello stesso modo. Quindi vorrei chiamare la routine di elaborazione da 2 thread separati per 2 file separati. Il thread della GUI non fa niente di pesante; visualizza solo un'etichetta e avvia un ciclo di eventi per verificare l'emissione delle condizioni di terminazione del thread e chiude di conseguenza l'Applicazione principale. Mi aspettavo che questo utilizzasse i due core (intel core2) in modo un po 'uguale, ma al contrario vedo dal Task Manager che uno dei core è molto utilizzato e l'altro no (anche se non ogni volta che eseguo il codice); anche il tempo necessario per elaborare i 2 file è molto più del tempo impiegato per elaborare un file (ho pensato che avrebbe dovuto essere uguale o un po 'di più ma è quasi uguale all'elaborazione dei 2 file uno dopo l'altro in un file non threadato applicazione). Posso forzare in qualche modo i thread a usare i core che ho specificato?

QThread* ptrThread1=new QThread; 
QThread* ptrThread2=new QThread; 
ProcessTimeConsuming* ptrPTC1=new ProcessTimeConsuming(); 
ProcessTimeConsuming* ptrPTC2=new ProcessTimeConsuming(); 

ptrPTC1->moveToThread(ptrThread1); 
ptrPTC2->moveToThread(ptrThread2); 

//make connections to specify what to do when processing ends, threads terminate etc 
//display some label to give an idea that the code is in execution 

ptrThread1->start(); 
ptrThread2->start(); //i want this thread to be executed in the core other than the one used above 

ptrQApplication->exec(); //GUI event loop for label display and signal-slot monitoring 
+7

I file sono su dischi rigidi fisici separati? Se stai cercando di far ruotare ruggine per leggere due file contemporaneamente, devi cercare tra loro ogni volta che viene programmato un thread diverso e quella parte sommergerà qualsiasi cosa tu possa ottenere dalla CPU. –

+0

I file hanno dimensioni approssimativamente uguali? – Tudor

+0

@PeteKirkham: basta avere 1 HDD – ustulation

risposta

16

lettura in parallelo da un unico disco meccanico spesso (e probabilmente nel tuo caso), non produrrà alcun guadagno di prestazioni, dal momento che il capo meccanico del disco ha bisogno di girare ogni volta per cercare la posizione di lettura successivo, efficacemente rendendo le tue letture sequenziali. Peggio ancora, se un sacco di thread stanno cercando di leggere, le prestazioni potrebbero persino peggiorare rispetto alla versione sequenziale, perché la testina del disco viene rimbalzata in diverse posizioni del disco e quindi deve tornare indietro da dove è stata interrotta ogni volta.

In genere, non è possibile fare di meglio che leggere i file in una sequenza e quindi elaborarli in parallelo utilizzando forse un modello produttore-consumatore.

+0

vedo..può tuttavia dirmi come forzare una discussione su un nucleo di scelta? – ustulation

+0

@ustulation: 'qthread' non fornisce un'API di affinità. Inoltre, non è quasi mai necessario impostare l'affinità per separare i core poiché lo scheduler imposterà il mapping thread-to-CPU nel miglior modo possibile. Ad ogni modo, se proprio ne hai bisogno, guarda questo post sull'uso delle chiamate alla libreria pthread per ottenere questo: http://qt-project.org/faq/answer/setting_thread_processor_affinity_in_linux – Tudor

+0

thanks..i suppongo di dover continuare con l'elaborazione sequenziale perché la dimensione del file è proibitiva per la lettura in RAM seguita dall'elaborazione ... in una nota a parte, non ho mai usato 'boost threads '... potrei darmi un suggerimento se ha questa caratteristica (core Affinity API) in modo che io approfondire quando ne ho bisogno? – ustulation

1

Ho pensato che i miei dati empirici potrebbero essere utili a questa discussione. Ho una directory con 980 file txt che vorrei leggere. Nel framework Qt/C++ e in esecuzione su un Intel i5 quad core, ho creato un'applicazione GUI e aggiunto un worker di classe per leggere un file dato il suo percorso. Ho spinto il lavoratore in un thread, quindi ho ripetuto aggiungendo un thread aggiuntivo a ogni esecuzione. Ho cronometrato all'incirca 13 minuti con 1 thread, 9 minuti con 2 e 8 minuti con 3. Quindi, nel mio caso ci sono stati alcuni benefici, ma si sono ridotti rapidamente.

+0

Qualsiasi sistema che consente a un singolo thread di esaurire la propria capacità di lettura/scrittura sarà instabile o almeno non rispondente a un utente. A meno che tu non ti intralzi, i thread hanno effettivamente i loro IO ridotti. Quello che hai fatto è stato chiedere che il tuo programma abbia più priorità lanciando due thread. – Mikhail

+0

Tutto dipende dalla dimensione dei file. Come regola generale sui dischi fissi meccanici, se si desidera che i costi generali siano inferiori al 10%, è necessario leggere un paio di megabyte alla volta. Quindi se i file sono più piccoli di, ad esempio, 2Mbytes, li leggi nella loro interezza. Se sono più grandi, puoi eseguire il round-robin tra i file per mantenere occupati più thread di calcolo. –

2

Con i dischi rigidi meccanici, è necessario controllare in modo esplicito il rapporto tra il tempo impiegato per la lettura sequenziale e la ricerca del tempo trascorso. Il modo canonico di farlo è con n + m oggetti in esecuzione sui thread m+min(n, QThread::idealThreadCount()). Qui, m è il numero di dischi rigidi in cui si trovano i file e n è il numero di file.

  • Ognuno di m oggetti sta leggendo i file dal disco rigido dato in un round robin. Ogni lettura deve essere sufficientemente grande. Sui moderni dischi fissi, mettiamo a budget 70Mbytes/s di larghezza di banda (puoi confrontare il valore reale), 5ms per una ricerca. Per sprecare al massimo il 10% della larghezza di banda, hai solo 100ms o 100ms/(5ms/seek) = 20 ricerche al secondo. Pertanto è necessario leggere almeno 70 Mbytes/(20 settimane + 1) = 3,3 Megabyte da ciascun file prima di leggere dal prossimo file. Questo thread riempie un buffer con i dati del file e il buffer segnala l'oggetto di calcolo pertinente che è collegato all'altro lato del buffer. Quando un buffer è occupato, si salta semplicemente la lettura dal file specificato finché il buffer non diventa nuovamente disponibile.

  • Gli altri n oggetti sono oggetti di calcolo, eseguono un calcolo su un segnale da un buffer che indica che il buffer è pieno. Non appena i dati del buffer non sono più necessari, il buffer viene "ripristinato" in modo che il lettore di file possa riempirlo.

Tutti gli oggetti di lettura richiedono i propri thread. Gli oggetti di calcolo possono essere distribuiti tra i propri thread in modo round robin, in modo che i thread abbiano tutti all'interno di +1, -0 oggetti l'uno dell'altro.

Problemi correlati