2010-11-20 18 views
6

Estoy escribiendo un programa paralelo utilizando mp abierto en el que genero una matriz de números aleatorios de coma flotante y luego hago una serie de cálculos en ella. Actualmente quiero hacer que el paso donde genero la matriz se ejecute en paralelo, pero tengo el problema de que la función rand() no estaba pensada para ejecutarse simultáneamente. No quiero utilizar bloqueos para proporcionar mutex en rand porque esto es lo único que se hace en el ciclo y probablemente sería más eficiente ejecutarlo secuencialmente. ¿Hay alguna manera de hacer este paso de manera eficiente en paralelo?Generación concurrente de números aleatorios

Aquí si el código actual para esta parte (sin mutex en rand);

#pragma omp parallel default(private) 
{ 
    int i= omp_get_thread_num(); 
    for(int j=0; j<cols; j++) 
     matrix[i][j]= rand()%1000 + (float)(rand()%100)/(float)(rand()%1000); 
} 
+0

Los PRNG generan una secuencia consistente de números de una semilla fija. ¿Es importante para usted este orden (repetibilidad) o realmente desea "aleatorio"? –

+0

No importa si están en algún orden en particular, el problema que tuve fue que cuando lo ejecuté secuencialmente obtuve una distribución bastante buena en mi rango, pero cuando lo cambié a paralelo en general, los números eran menos de 10 y cuando resumí las filas, casi todas sumaron hasta 0 (nunca obtuve negativos con la secuencia). Esto me hace pensar que hay algún tipo de problema de concurrencia con la llamada a la función. – user381261

+1

Espera un segundo: una vez cada mil iteraciones en promedio, rand()% 1000 será cero, entonces, ¿cómo puedes dividir por eso? – TonyK

Respuesta

3

Si está utilizando C++, debería considerar usar el Boost library random number classes. Puede crear una instancia única de PRNG para cada hilo. Si necesita repetibilidad, puede inicializar cada instancia en su hilo principal con valores de semilla generados repetidamente.

0

Si pseudoaleatoria es lo suficientemente bueno (cf. el comentario de Ben), entonces se podría crear su propia PRNG (por ejemplo. Un Mersenne Twister en lugar del método de módulo débil utilizado por la mayoría de los sistemas), y poner en práctica un generador independiente por hilo. si haces esto, DEBES asegurarte de que cada generador tenga una semilla diferente.

0

Un problema real es si desea reproducibilidad, que a menudo se necesita en la prueba. Con una semilla dada, genere una secuencia de semillas de hilos. Entonces cada hilo usará su propia semilla para generar números.

El hecho de que rand() no es seguro para subprocesos no es un problema. Hay muchos algoritmos disponibles y es trivial rodar una instancia (estado) por hilo, simplemente comience desde http://en.wikipedia.org/wiki/Random_number_generation#Computational_methods por ejemplo. El bloqueo para cada llamada rand() sería un desastre de concurrencia.

3

Creo que está buscando rand_r(), que toma explícitamente el estado de RNG actual como parámetro. Entonces cada hilo debe tener su propia copia de los datos iniciales (si quieres que cada hilo comience con la misma semilla o diferentes depende de lo que estés haciendo, aquí quieres que sean diferentes o obtendrás la misma fila una y otra vez). Hay una discusión sobre rand_r() y seguridad de hilos aquí: whether rand_r is real thread safe?.

Digamos que querías que cada hilo comenzara con su número de hilo (que probablemente no es el que quieres, ya que daría la misma matriz cada vez que ejecutaras el mismo número de hilos, pero igual un ejemplo):

#pragma omp parallel default(none) shared(matrix, cols) 
{ 
    int i= omp_get_thread_num(); 
    unsigned int myseed = i; 
    for(int j=0; j<cols; j++) 
     matrix[i][j]= rand_r(&myseed)%1000 + (float)(rand_r(&myseed)%100)/(float)(rand_r(&myseed)%1000 + 1); 
} 

Ahora cada hilo está modificando su propio estado exclusivamente (rand_r() es una función pura) y debe estar en casa libre.

Cuestiones relacionadas