2012-05-16 12 views
7

Quando provo il seguente codiceprogramma OpenMP è più lenta di quella sequenziale

double start = omp_get_wtime(); 

long i; 

#pragma omp parallel for 
    for (i = 0; i <= 1000000000; i++) { 
     double x = rand(); 
    } 

    double end = omp_get_wtime(); 

    printf("%f\n", end - start); 

tempo di esecuzione è circa 168 secondi, mentre la versione sequenziale spende solo 20 secondi.

Sono ancora un principiante nella programmazione parallela. Come posso ottenere una versione parallela più veloce di quella sequenziale?

risposta

13

Il generatore di numeri casuali rand(3) utilizza variabili di stato globali (nascoste nell'implementazione di (g) libc). L'accesso ad essi da più thread porta a problemi di cache e inoltre non è thread-safe. Si dovrebbe usare la chiamata rand_r(3) con seed parametro privata al thread:

long i; 
unsigned seed; 

#pragma omp parallel private(seed) 
{ 
    // Initialise the random number generator with different seed in each thread 
    // The following constants are chosen arbitrarily... use something more sensible 
    seed = 25234 + 17*omp_get_thread_num(); 
    #pragma omp for 
    for (i = 0; i <= 1000000000; i++) { 
     double x = rand_r(&seed); 
    } 
} 

Si noti che questo produrrà diverso flusso di numeri casuali quando eseguito in parallelo rispetto a quando eseguito in serie. Vorrei anche raccomandare erand48(3) come una fonte di numeri casuali (pseudo-) migliore.

+0

Si noti inoltre che poiché 'double x = rand()' non modifica lo stato esterno, il compilatore potrebbe essere tentato di ottimizzare il loop out nella versione sequenziale. In generale, dovresti testare con codice che non può essere ottimizzato. – Vanwaril

+2

@Vanwaril, 'rand()' non è un elemento intrinseco. Il compilatore non sa se è una funzione pura o no (è _not_) e quindi non dovrebbe ottimizzare la chiamata. –

+0

Grazie mille. Ora la versione parallela trascorre 5 secondi mentre quella sequenziale impiega 9 secondi. –

Problemi correlati