2013-06-14 14 views
5

ho creato il seguente esempio minimale:MATLAB: Come impostare un seme casuale in parfor per produrre gli stessi risultati come seriale?

rng(0); 

randseedoffset = random('unid', 10^5) + 1; 

t = cell(10,1); 
for i = 1:10 
    rng(randseedoffset+i); 
    t{i} = random('unid', 1000); 
end 

disp(t); 

Questo genererà 10 numeri casuali e memorizzarli in t. Produrrà sempre gli stessi numeri casuali in modo affidabile perché ho impostato il seme con rng nel ciclo for.

Se ora cambio for a parfor, ottengo diversi risultati! Anche se saranno sempre riproducibili.

Voglio accelerare il mio codice con parfor ed ancora ottenere gli stessi numeri esatti stessi casuali come con la ...

risposta

6

Ok, ho appena trovato il motivo:

MATLAB supporta diversi algoritmi Genereation di numeri casuali . Mentre nella consueta impostazione della versione attuale questo è il Mersenne Twister. Quando entrate nel ciclo parfor, questo cambia in quello che chiamano 'Metodo ricorsivo combinato'.

Il problema può essere risolto impostando esplicitamente il tipo da 'twister' nel circuito:

parfor i = 1:10 
    rng(randseedoffset+i, 'twister'); 
    t{i} = random('unid', 1000); 
end 
+0

Interessante. Non riesco a trovare la modifica del generatore di default menzionata in qualsiasi punto della documentazione. Sai se questo riguarda anche 'rand' e' randn'? A proposito, puoi accettare la tua risposta alla tua domanda. – horchler

+0

+1 Molto interessante. Attenzione però a questo hack in contesti di codice più ampi: sembra che i lavoratori paralleli siano stati impostati per avere stati RNG quasi paralleli e future 'parfor' o altre chiamate DCT che non reimpostano il seed potrebbero avere stranezze risultati. Pre-generare i numeri casuali al di fuori del ciclo potrebbe essere più pulito se hai bisogno di riproducibilità totale. –

+0

ho la situazione opposta. Potresti rispondere alla mia domanda: http: //stackoverflow.com/questions/40190243/matlab-generating-random-numbers-in-parfor-or-parallel-computing? Noredirect = 1 # comment67680730_40190243 – kyle

0

sento il bisogno di elaborare su questo. Non reimpostare il seed in un ciclo parfor e inoltre non utilizzare l'algoritmo di Mersenne Twister in parallelo (otterrete scarsi risultati di indipendenza statistica).

Il motivo per cui si ottengono risultati diversi è perché l'algoritmo è diverso a causa delle proprietà statistiche che questi numeri dovrebbero mantenere. In un pool parallelo MATLAB imposta l'algoritmo su "combRecursive" e imposta un diverso sottostream su ciascun worker, quindi per i numeri casuali che sei a posto. Inoltre, il ciclo parfor non garantisce —

  • L'ordine in cui i loop procedono,
  • cui i lavoratori saranno in esecuzione ogni pezzo, o
  • quante delle iterazioni sono eseguite su ogni lavoratore.

Pertanto, la generazione di numeri casuali in cicli parfor non restituirà generalmente gli stessi numeri casuali anche con lo stesso stato su ciascun lavoratore. Invece fare un RandStream con substreams dell'algoritmo combRecursive, impostare il flusso globale su ogni lavoratore in un blocco SPMD, quindi generare i numeri su ogni lavoratore in un blocco SPMD:

p = gcp; % Get or open a pool 

numWork = p.NumWorkers; % Get the number of workers 

s = RandStream.create('mrg32k3a','NumStreams',numWork,... 
    'CellOutput',true); % create numWork independent streams 

n = 200; % number of values to generate on each worker 
spmd 
    RandStream.setGlobalStream(s{labindex}); 
    x = rand(1,n); 
end 

% I generate row vectors as the Composite matrix x will return a 
% comma-separated list using the syntax, x{:}, which can then be 
% concatenated into a single vector: 
randVals2 = [x{:}]'; 
+0

molto interessante. parfor sembra rovinare le cose quando passo da loop a parfor: potresti rispondere alla mia domanda: http://stackoverflow.com/questions/40190243/matlab-generating-random-numbers-in-parfor-or-parallel- computing? noredirect = 1 # comment67680730_40190243 – kyle

0

provare questo:

p = gcp; % Get or open a pool 

numWork = p.NumWorkers; % Get the number of workers 

stream = RandStream('mrg32k3a','seed',mydata.seed); 
RandStream.setGlobalStream(stream); 

% s = RandStream.create('mrg32k3a','NumStreams',numWork,'CellOutput',true,'Seed',mydata.seed); % create numWork independent streams 

n = 200; % number of values to generate on each worker 
spmd 
RandStream.setGlobalStream(stream); 
x = rand(1,n); 
end 
Problemi correlati