2010-03-07 7 views
5

Ho bisogno di eseguire simulazioni MonteCarlo in parallelo su macchine diverse. Il codice è in C++, ma il programma è impostato e lanciato con uno script python che imposta molte cose, in particolare il seed casuale. La funzione setSeed thake un 4 byte unsigned integerMiglior seme per processo parallelo

Utilizzando un semplice

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

non è molto buona, perché presento i lavori a una coda in un cluster, rimangono in attesa per qualche minuto poi si inizia, ma l'ora di inizio è impredicible, può essere che due lavori iniziano allo stesso tempo (secondi), in modo da passare a:

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

ma non sono felice. Qual è la soluzione migliore? Forse posso combinare le informazioni da: tempo, id macchina, id processo. O forse la soluzione migliore è leggere da/dev/random (macchine Linux)?

Come leggere 4 byte da/dev/random?

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

dammi una stringa, voglio un numero intero!

+1

In realtà non hai detto cosa consiti "il migliore". Suppongo che tu stia cercando di assicurare che ogni istanza usi un seme diverso. Ma, dovrebbero essere unici tra i diversi lavori in una singola corsa, o avete bisogno di qualcosa che si avvicini (o che sia garantito) all'unicità globale (tutti eseguiti e tutti i lavori). In secondo luogo, è necessario essere in grado di ripetere una corsa con gli stessi semi (a volte utile nel debugging intermittente). E potrebbero esserci altre complicazioni. – dmckee

+0

Voglio seme casuale per ogni istanza, quindi se il seme è da 0 a 2^(8 * 4) -1 è molto probabile che i semi siano diversi per ogni istanza. Non costringo i semi a essere diversi, anche se forse sarebbe meglio se lo fossero. Penso che non sia un grosso problema. Non è necessario ripetere l'esecuzione con lo stesso seme. –

+0

Bene, questo è il caso facile e hai già buone risposte. Saluti. – dmckee

risposta

5

La lettura da /dev/random è una buona idea. Basta convertire la stringa 4 byte in un numero intero:

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

Sia utilizzando struct:

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

Aggiornamento I maiuscola è necessario.

o moltiplicare e aggiungere:

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

Si noti che se si scende in quella corsia, ricordarsi di salvare i semi per assicurarsi di poter riprodurre in seguito i risultati esatti. – Joey

+0

Ho salvato il seme nel nome del file di output –

+0

Grazie, ma modifica "i" in "I" e rnd_string in rnd_str –

2

Si potrebbe semplicemente copiare i quattro byte in un intero, che dovrebbe essere l'ultima delle vostre preoccupazioni.

Ma la generazione parallela di numeri pseudo-casuali è un argomento piuttosto complesso e molto spesso non ben eseguito. Generalmente generi semi su una macchina e li distribuisci agli altri.

Dai uno sguardo allo SPRNG, che gestisce esattamente il tuo problema.

0

È possibile utilizzare un numero casuale come il seme, che ha il vantaggio di essere del sistema operativo agnostico (senza/dev/random necessario), senza alcuna conversione da stringa a int:

Perché non usare semplicemente

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

come seme di ogni processo? Tempi di inizio leggermente diversi danno semi molto diversi, in questo modo ...

In alternativa, è possibile utilizzare il metodo random.jumpahead, se si conosce approssimativamente il numero di numeri casuali che ciascun processo utilizzerà (la documentazione di random.WichmannHill.jumpahead è utile).

1

Se questo è Linux o un SO simile, si desidera /dev/urandom - produce sempre immediatamente i dati.

/dev/random potrebbe bloccarsi in attesa che il sistema raccolga casualità. Produce numeri casuali di grado crittografico, ma questo è eccessivo per il tuo problema.

+0

Lo so, ma preferisco casuale. Ho bisogno solo di 4 byte di numero casuale, non è troppo –