2012-02-21 10 views
7

Attualmente sto parallelizzando il programma utilizzando openmp su un phenom2 a 4 core. Tuttavia ho notato che la mia parallelizzazione non fa nulla per la performance. Naturalmente ho pensato che mi mancasse qualcosa (falsesharing, serializzazione tramite serrature, ...), tuttavia non sono riuscito a trovare nulla di simile. Inoltre dall'utilizzo della CPU sembrava che il programma fosse eseguito su un solo core. Da quello che ho trovato sched_getcpu() dovrei darmi l'Id del core al thread in cui è attualmente pianificata la chiamata. Così ho scritto il seguente programma di test:Thread OpenMP in esecuzione sullo stesso core CPU

#include <iostream> 
#include <sstream> 
#include <omp.h> 
#include <utmpx.h> 
#include <random> 
int main(){ 
    #pragma omp parallel 
    { 
     std::default_random_engine rand; 
     int num = 0; 
    #pragma omp for 
     for(size_t i = 0; i < 1000000000; ++i) num += rand(); 
    auto cpu = sched_getcpu(); 
    std::ostringstream os; 
     os<<"\nThread "<<omp_get_thread_num()<<" on cpu "<<sched_getcpu()<<std::endl; 
     std::cout<<os.str()<<std::flush; 
    std::cout<<num; 
    } 
} 

Sulla mia macchina questo dà il seguente risultato (i numeri casuali varieranno ovviamente):

Thread 2 on cpu 0 num 127392776 
Thread 0 on cpu 0 num 1980891664 
Thread 3 on cpu 0 num 431821313 
Thread 1 on cpu 0 num -1976497224 

Da questo suppongo che tutti i thread eseguono sul stesso core (quello con id 0). Per essere più certi ho anche provato l'approccio da this answer. I risultati dove lo stesso. Inoltre, l'utilizzo di #pragma omp parallel num_threads(1) non ha rallentato l'esecuzione (leggermente più veloce di fatto), dando credibilità alla teoria che tutti i thread utilizzano la stessa CPU, tuttavia il fatto che la CPU sia sempre visualizzata come 0 mi rende piuttosto sospetto. Inoltre ho controllato GOMP_CPU_AFFINITY che inizialmente non era impostato, quindi ho provato a impostarlo su 0 1 2 3, che dovrebbe legare ogni thread a un core diverso da quello che ho capito. Tuttavia ciò non ha fatto la differenza.

Da quando si sviluppa su un sistema Windows, io uso linux in virtualbox per il mio sviluppo. Quindi pensavo che forse il sistema virtuale non potesse accedere a tutti i core. Tuttavia, controllando le impostazioni di virtualbox è emerso che la macchina virtuale dovrebbe acquisire tutti e 4 i core ed eseguire il mio programma di test 4 volte allo stesso tempo sembra utilizzare tutti e 4 i core a giudicare dall'utilizzo della CPU (e dal fatto che il sistema stava diventando molto poco reattivo) .

Quindi per la mia domanda è fondamentalmente cosa sta succedendo esattamente qui. Più precisamente: La mia deduzione è che tutti i thread utilizzano lo stesso core correttamente? Se lo è, quali potrebbero essere le ragioni di tale comportamento?

+1

heres un errore comune hai impostato la variabile di ambiente OMP_NUM_THREADS = 4? – pyCthon

+0

@pyCthon: 'OMP_NUM_THREADS' non sembra essere impostato, tuttavia dal momento che openmp crea 4 thread non credo che sarebbe necessario. – Grizzly

+0

strano penso che potrebbe essere qualcosa con la tua macchina virtuale ho provato lo stesso codice anche installato utmpx.h e sembrava funzionare bene su un 8 e un 16 core macchina – pyCthon

risposta

6

Dopo alcuni esperimenti ho scoperto che il problema era che stavo iniziando il mio programma dall'interno dell'IDE di eclipse, che apparentemente aveva l'affinità di usare solo un core. Pensavo di avere gli stessi problemi quando partivo dall'esterno dell'IDE, ma un test ripetuto ha mostrato che il programma funziona bene, quando è partito dal terminale anziché dall'interno dell'ide.

0

Si dovrebbe usare #pragma omp parallel for
E sì, hai ragione di non aver bisogno OMP_NUM_THREADS. omp_set_num_threads(4); dovrebbe anche aver fatto bene.

+0

Perché dovrei usare '#pragma omp parallel for', se voglio che i thread facciano cose al di fuori del ciclo (come scrivere il loro id sull'output)? E come ho detto, crea automaticamente 4 thread, il solo sembra essere eseguito sullo stesso core – Grizzly

+0

Anche questo è vero. btw, se non dici omp * parallel * per, allora non avviene la parallelizzazione nel ciclo. Ma ovviamente sei all'interno di una sezione parallela, quindi ... L'unica altra possibile spiegazione che posso pensare è la mancanza di supporto hardware per la tua virtualbox. Hai provato con altre CPU? http://superuser.com/questions/33723/getting-2-processors-to-work-with-virtualbox-on-dual-core-celeron – Nav

+0

Non l'ho fatto. Comunque come detto è possibile usare tutti i core dalla vbox, quindi la mancanza di supporto sembra improbabile – Grizzly

0

se si esegue su Windows, provate questo:

c: \ windows \ system32 \ cmd.exe/C avviare/affinità percorso F \ a \ tuo \ program.exe

/affinità 1 utilizza CPU0

/affinità 2 utilizza CPU1

/affinità 3 utilizza CPU0 e CPU1

/affinità 4 utilizza CPU2

/affinità F utilizza tutti i 4 core

Convertire il numero in esadecimale e vedere i bit da destra che sono i nuclei da utilizzare.

è possibile verificare l'affinità mentre è in esecuzione utilizzando task-manager.

+0

La vbox ha l'affinità corretta per usare tutti i core (ho controllato e inoltre come li userebbe tutti nel mio test con più inizio del mio testprogram). Dal momento che io uso Linux all'interno della vbox che non aiuta davvero lì. – Grizzly

1

Ho compilato il programma utilizzando g ++ 4.6 su Linux

g++ --std=c++0x -fopenmp test.cc -o test 

L'uscita è stata, ovviamente:

Thread 2 on cpu 2 

Thread 3 on cpu 1 
910270973 
Thread 1 on cpu 3 
910270973 
Thread 0 on cpu 0 
910270973910270973 

Il fatto che 4 thread vengono avviati (se non è stato impostato il numero di thread in qualsiasi modo, ad esempio utilizzando OMP_NUM_THREADS) dovrebbe implicare che il programma è in grado di vedere 4 CPU utilizzabili. Non riesco a immaginare perché non li stia usando, ma sospetto un problema nelle impostazioni hardware/software, in alcune variabili d'ambiente o nelle opzioni del compilatore.

Problemi correlati