2012-08-23 12 views
9

Soy nuevo aquí y soy un programador de nivel principiante en C. Estoy teniendo algún problema con el uso de openmp para acelerar el for-loop. A continuación se muestra un ejemplo simple:OpenMP y C parallel for loop: ¿por qué mi código se ralentiza cuando se usa 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); 
    } 
} 

El código se basa en una distribución aleatoria gamma para M iteraciones. Resulta que el enfoque paralelo con openmp (opción 1) toma alrededor de 1 minuto, mientras que el enfoque secuencial (opción 2) toma solo 20 segundos. Mientras corro con openmp, puedo ver que el uso de la CPU es de 800% (el servidor que estoy usando tiene 8 CPU). Y el sistema es Linux con GCC 4.1.3. El comando de compilación que estoy usando es gcc -fopenmp -lgsl -lgslcblas -lm (estoy usando GSL)

¿Estoy haciendo algo mal? ¡Por favor, ayúdame! ¡Gracias!

P.S. Como señalaron algunos usuarios, podría ser causado por rng. Pero incluso si reemplazo

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

por decir

tmp=1000*10000; 

el problema sigue ahí ...

+0

No debe hacer que su variable de bucle sea privada, OpenMP se encargará de eso. No sé si esto afecta la ejecución, pero debería arreglarlo y volver a probar. –

+0

Además, tenga en cuenta que tmp = 1000 * 10000 probablemente se optimice por el compilador a un noop, por lo que se sesgará el tiempo. –

+0

¿Estás seguro de que en realidad hay 8 CPU? ¿Podría ser un quad-core con hyperthreading? –

Respuesta

12

gsl_ran_gamma_mt probablemente cerraduras en rng para evitar problemas de concurrencia (si no lo hiciera, su paralelo el código probablemente contenga una condición de carrera y por lo tanto arroje resultados incorrectos). La solución sería tener una instancia de rng por separado para cada subproceso, evitando así el bloqueo.

+1

muchas gracias! pero el problema aún persiste si reemplazo tmp = gsl_ran_gamma_mt (rng, 4, 1./3) con decir tmp = 1000 * 10000 – user1620200

+0

@ user1620200 Impar, debería haber una disminución drástica. Por supuesto, todavía hay una gran sobrecarga para cálculos paralelos involucrados ya que el cálculo real es bastante rápido, incluso con muchas iteraciones. El horario dinámico no ayuda (pruebe uno estático, no hay ninguna razón para un horario dinámico aquí ya que todas las tareas tienen el mismo tamaño). Finalmente, pruebe el consejo de Stephane, pero me sorprendería que ese fuera el problema, ya que esto debería ser trivialmente optimizado. –

+0

Gracias. ¡Descubrí que si me deshacía del horario (dinámico), el problema ya no existe! ¿Me pregunto porque? – user1620200

5

Su variable rng es compartida, por lo que los hilos pasan todo el tiempo esperando para poder usar el generador de números aleatorios. Dé a cada hilo una instancia separada del RNG. Esto probablemente también signifique hacer que el código de inicialización RNG se ejecute en paralelo también.

+0

muchas gracias! pero el problema aún persiste si reemplazo tmp = gsl_ran_gamma_mt (rng, 4, 1./3) con say tmp = 1000 * 10000; – user1620200

1

De nuevo, gracias a todos por ayudar. Acabo de descubrir que si me deshago de

schedule(dynamic) 

en el código, el problema desaparece. Pero ¿por qué es eso?

+1

La programación 'dinámica' es bastante costosa y solo debe usarse en aquellos casos en los que las iteraciones tardan una cantidad considerable de tiempo en completarse, pero esta vez puede variar mucho con cada iteración. 'guided' es aún más costoso ya que hace que los bloques de iteración sean cada vez más pequeños. Utilice la programación 'estática' para las iteraciones con una cantidad fija de tiempo de cálculo. –

+0

¡Muchas gracias Hristo Iliev! – user1620200

+1

Creo que puede aceptar su propia respuesta, ya que usted fue quien resolvió el problema. –