2012-08-23 6 views
9

Sono nuovo qui e un programmatore di livello principianti in C. Sto avendo qualche problema con l'utilizzo di openmp per accelerare il ciclo. Di seguito è riportato un semplice esempio:OpenMP e C paralleli per ciclo: perché il mio codice rallenta quando si utilizza OpenMP?

#include <stdlib.h> 
#include <stdio.h> 
#include <gsl/gsl_rng.h> 
#include <omp.h> 

gsl_rng *rng; 

main() 
{ 
int i, M=100000000; 
double tmp; 

/* initialize RNG */ 
gsl_rng_env_setup(); 
rng = gsl_rng_alloc (gsl_rng_taus); 
gsl_rng_set (rng,(unsigned long int)791526599); 

// option 1: parallel   
    #pragma omp parallel for default(shared) private(i, tmp) schedule(dynamic) 
    for(i=0;i<=M-1;i++){ 
    tmp=gsl_ran_gamma_mt(rng, 4, 1./3); 
    } 


// option 2: sequential  
    for(i=0;i<=M-1;i++){ 
    tmp=gsl_ran_gamma_mt(rng, 4, 1./3); 
    } 
} 

Il codice deriva da una distribuzione gamma casuale per M iterazioni. Si scopre che l'approccio parallelo con openmp (opzione 1) richiede circa 1 minuto mentre l'approccio sequenziale (opzione 2) richiede solo 20 secondi. Durante l'esecuzione con openmp, posso vedere l'utilizzo della CPU è 800% (il server che sto usando ha 8 CPU). E il sistema è Linux con GCC 4.1.3. Il comando di compilazione che sto usando è gcc -fopenmp -lgsl -lgslcblas -lm (sto usando GSL)

Sto facendo qualcosa di sbagliato? Mi aiuti per favore! Grazie!

P.S. Come sottolineato da alcuni utenti, potrebbe essere causato da rng. Ma anche se sostituisco

tmp=gsl_ran_gamma_mt(rng, 4, 1./3); 

da dire

tmp=1000*10000; 

il problema ancora lì ...

+0

Non si dovrebbe rendere privata la variabile del ciclo - OpenMP si prenderà cura di ciò. Non so se questo influisce sull'esecuzione, ma dovresti correggerlo e ripetere il test. –

+0

Inoltre, nota che tmp = 1000 * 10000 probabilmente viene ottimizzato dal compilatore a un noop, in modo tale da distorcere i tempi. –

+0

Sei sicuro che ci siano effettivamente 8 CPU? Potrebbe essere un quad-core con hyperthreading? –

risposta

12

gsl_ran_gamma_mt probabilmente blocca sul rng per evitare problemi di concorrenza (se così non fosse, il vostro parallelo il codice probabilmente contiene una condizione di competizione e quindi produce risultati errati). La soluzione sarebbe quindi di avere un'istanza separata rng per ogni thread, evitando così il blocco.

+1

grazie mille! ma il problema rimane ancora se sostituisco tmp = gsl_ran_gamma_mt (rng, 4, 1./3) con dire tmp = 1000 * 10000 – user1620200

+0

@ user1620200 Dispari, ci dovrebbe essere una drastica diminuzione. Naturalmente, c'è ancora un enorme sovraccarico per i calcoli paralleli coinvolti poiché il calcolo reale è abbastanza veloce, anche con molte iterazioni. La pianificazione dinamica non aiuta (prova uno statico, non c'è motivo per una pianificazione dinamica qui poiché tutte le attività hanno le stesse dimensioni). Infine, prova il consiglio di Stephane, ma sarei sorpreso se questo fosse il problema dal momento che questo dovrebbe essere banalmente ottimizzato. –

+0

Grazie. Ho scoperto che se mi libero dal programma (dinamico), il problema è sparito! Mi chiedo perché? – user1620200

5

La tua variabile rng è condivisa, quindi i thread stanno spendendo tutto il loro tempo in attesa di poter utilizzare il generatore di numeri casuali. Dare ad ogni thread un'istanza separata del RNG. Ciò significa probabilmente che il codice di inizializzazione RNG viene eseguito anche in parallelo.

+0

grazie mille! ma il problema rimane ancora se sostituisco tmp = gsl_ran_gamma_mt (rng, 4, 1./3) con dire tmp = 1000 * 10000; – user1620200

1

Ancora grazie a tutti per l'aiuto. Ho appena scoperto che se mi liberassi di

schedule(dynamic) 

nel codice, il problema scompare. Ma perché è così?

+1

La pianificazione 'dynamic' è piuttosto costosa e dovrebbe essere utilizzata solo nei casi in cui le iterazioni richiedono molto tempo per essere completate, ma questa volta potrebbe variare notevolmente a ogni iterazione. 'guided' è ancora più costoso in quanto rende i blocchi di iterazione sempre più piccoli. Usa la programmazione 'static' per le iterazioni con una quantità fissa di tempo di calcolo. –

+0

Grazie mille Hristo Iliev! – user1620200

+1

Penso che tu possa accettare la tua risposta, dato che sei stato tu a risolvere il problema. –