Domanda

Ho un codice Fortran90 parallelo in cui ogni thread deve generare la stessa sequenza di numeri casuali.

Ho un generatore di numeri casuali che sembra essere thread-safe, poiché, per un dato seed, non riesco completamente a ripetere gli stessi risultati ogni volta che eseguo il programma.

Ho navigato senza successo (quasi) tutto il web alla ricerca di un codice di un RNG thread-safe. Qualcuno potrebbe fornirmi (il link per) il codice di uno?

Grazie in anticipo!

È stato utile?

Soluzione

Un buon Generatore di numeri pseudorandom per Fortran90 può essere trovato nel Libreria statistica vettoriale Intel Math Kernel . Sono sicuri per i thread. Inoltre, perché deve essere thread-safe? Se vuoi che ogni thread ottenga lo stesso elenco, crea un'istanza di un nuovo PRNG per ogni thread con lo stesso seed.

Altri suggerimenti

I generatori di numeri casuali più ripetibili necessitano dello stato in qualche forma. Senza stato, non possono fare ciò che verrà dopo. Per essere thread-safe, hai bisogno di un modo per mantenere te stesso lo stato (cioè, non può essere globale).

Quando dici "devi generare la stessa sequenza di numeri casuali" vuoi dire che

  • Ogni thread deve generare un flusso di numeri identici all'altro thread? Ciò implica scegliere il seme prima di staccare i thread, quindi creare un'istanza di un PRNG locale del thread in ogni thread con lo stesso seed.

o

  • Vuoi essere in grado di ripetere la stessa sequenza di numeri tra diverse esecuzioni dei programmi, ma ogni thread genera la propria sequenza indipendente? In questo caso, non è ancora possibile condividere un singolo PRNG perché la sequenza di operazioni del thread non è deterministica. Quindi semina un singolo PRNG con un seme noto prima di avviare i thread e utilizzalo per generare i seed iniziali per i thread. Quindi crei un'istanza di generatori locali di thread in ogni thread ...

In ciascuno di questi casi dovresti notare cosa Neil Butterworth dire delle statistiche: la maggior parte delle solite garanzie che il PRNG piace rivendicare sono non affidabili quando i flussi di mix generati in questo modo.


In entrambi i casi è necessario un PRNG locale thread. Non so cosa sia disponibile in f90 ... ma puoi anche scriverne uno tuo (cerca Mersenne Twister e scrivi una routine che prende lo stato salvato come parametro ...).

In fortran 77, questo sarebbe simile a

      function PRNGthread (state)

      double state(statesize)

c stuff happens here which uses and manipulates the state vector...

      PRNGthread = result
      return 

e ognuno dei tuoi thread dovrebbe mantenere un vettore di stato separato, sebbene tutti utilizzino lo stesso valore iniziale.

Capisco che hai bisogno di ogni thread per produrre lo stesso flusso di numeri casuali.

Un ottimo generatore di pseudo-casuali che genererà un flusso riproducibile di numeri ed è abbastanza veloce è MT19937 . Assicurati solo di generare il seme prima di generare i thread, ma genera un'istanza separata di MT in ogni thread (rendi locale l'istanza del thread MT). In questo modo sarà garantito che ogni MT produrrà lo stesso flusso di numeri.

Che ne dici di SPRNG ? Non l'ho provato io stesso.

Ho codificato una versione Fortran 90 thread-safe di Mersenne Twister / MT19973. Lo stato del PRNG viene salvato in un tipo derivato (randomNumberSequence) e si utilizzano le procedure per eseguire il seeding del generatore o ottenere l'elemento successivo nella sequenza.

Vedi http: //code.google.com/p/i3rc-monte-carlo-model/source/browse/trunk/Code/RandomNumbersForMC.f95

Le alternative sembrano essere:

  • Utilizza un oggetto di sincronizzazione (come un mutex) sul seme del generatore valore. Questo sfortunatamente serializzare il codice sugli accessi a generatore
  • Utilizza l'archiviazione locale thread nel file generatore in modo che ogni thread abbia il suo seme - questo può causare statico problemi per la tua app
  • Se la tua piattaforma supporta un adatto operazione atomica, usare quella sul seed (probabilmente non lo farà, comunque)

Non un elenco molto incoraggiante, lo so. E per aggiungere ad esso, non ho idea di come implementarli in FORTRAN!

Questo articolo https://www.cmiss.org/openCMISS/wiki/RandomNumberGenerationWithOpenMP non si collega solo all'implementazione di Fortran, ma menziona i punti chiave necessari per rendere un PRNG utilizzabile con i thread. Il punto più importante è:

La versione Fortran90 di Ziggurat ha diverse variabili e matrici con l'attributo 'SALVA'. Al fine di parallelizzare l'RNG uniforme, quindi, sembra che le modifiche richieste siano quelle di creare array di variabili con un valore separato per ogni thread (attenzione alla falsa condivisione). Quindi quando viene chiamata la funzione PRNG, dobbiamo passare il numero di thread e utilizzare il valore di stato corrispondente.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top