2010-03-07 8 views
5

Necesito ejecutar simulaciones de MonteCarlo en paralelo en diferentes máquinas. El código está en C++, pero el programa se configura y se inicia con un script de python que establece muchas cosas, en particular, la semilla aleatoria. La función setSeed thake un 4 bytes entero sin signoMejor semilla para el proceso paralelo

Usando un simple

import time 
setseed(int(time.time())) 

no es muy bueno porque puedo enviar los trabajos a una cola en un clúster, que siguen pendientes de algunos minutos después de que se inicia, pero la hora de inicio es impredicible, puede ser que dos puestos de trabajo se encienden al mismo tiempo (segundos), por lo que cambiar a:

setseet(int(time.time()*100)) 

pero no estoy feliz. ¿Cuál es la mejor solución? Tal vez pueda combinar información de: tiempo, ID de la máquina, ID del proceso. ¿O tal vez la mejor solución es leer desde/dev/random (máquinas Linux)?

Cómo leer 4 bytes de/dev/random?

f = open("/dev/random","rb") 
f.read(4) 

dame una cadena, ¡quiero un número entero!

+1

En realidad, no has dicho lo que consitutes "mejor". Supongo que está tratando de asegurarse de que cada instancia use una semilla diferente. Pero, ¿deberían ser únicos entre diferentes trabajos en una sola ejecución, o necesita algo que se aproxime (o garantice ser) globalidad global (todos los trabajos ejecutados y todos). En segundo lugar, ¿alguna vez debe ser capaz de repetir una ejecución con las mismas semillas (a veces útil en la depuración intermitente). Y puede haber otras complicaciones. – dmckee

+0

Quiero semilla al azar para cada instancia, por lo que si la semilla es de 0 a 2^(8 * 4) -1 es muy probable que las semillas sean diferentes para cada instancia. No obligo a las semillas a ser diferentes, incluso si tal vez sería mejor si lo fueran. Creo que no es un gran problema. No necesito repetir la ejecución con la misma semilla. –

+0

Bueno, ese es el caso fácil y ya tienes buenas respuestas. Aclamaciones. – dmckee

Respuesta

5

Lectura de /dev/random es una buena idea. Sólo convertir la cadena de 4 bytes en un entero:

f = open("/dev/random","rb") 
rnd_str = f.read(4) 

ya sea usando struct:

import struct 
rand_int = struct.unpack('I', rnd_string)[0] 

actualización mayúsculas que se necesita.

o múltiple y añadir:

rand_int = 0 
for c in rnd_str: 
    rand_int <<= 8 
    rand_int += ord(c) 
+0

Tenga en cuenta que si baja por ese carril, recuerde guardar sus semillas para asegurarse de que luego puede reproducir los resultados exactos. – Joey

+0

Guardo la semilla en el nombre del archivo de salida –

+0

Gracias, pero cambie 'i' a 'I' y rnd_string a rnd_str –

2

Usted puede simplemente copiar las cuatro bytes en un entero, que debe ser el menor de sus preocupaciones.

Pero la generación de números pseudoaleatorios paralelos es un tema bastante complejo y muy a menudo no se hace bien. Usualmente generas semillas en una máquina y las distribuyes a las otras.

Eche un vistazo a SPRNG, que maneja exactamente su problema.

0

Se puede utilizar un número aleatorio como la semilla, que tiene la ventaja de ser del sistema operativo agnóstico (sin/dev/random es necesario), sin conversión de String a int:

Por qué no simplemente usar

random.randrange(-2**31, 2**31) 

como la semilla de cada proceso? Ligeramente diferentes tiempos de inicio dan muy diferentes semillas, de esta manera ...

también se podría utilizar como alternativa al método random.jumpahead, si usted sabe más o menos la cantidad de números al azar cada proceso se va a utilizar (la documentación de random.WichmannHill.jumpahead es útil).

1

Si esto es Linux o un sistema operativo similar, quiere /dev/urandom - siempre produce datos inmediatamente.

/dev/random puede detenerse esperando a que el sistema reúna aleatoriedad. Produce números aleatorios de grado criptográfico, pero eso es excesivo para su problema.

+0

Lo sé, pero prefiero al azar. Necesito solo 4 bytes de número aleatorio, no es demasiado –

Cuestiones relacionadas