在Matlab中的并行循环中使用不同的(伪)随机数

3
在并行循环中请求随机数总是返回相同的伪随机数。我该如何避免这种情况?
% workers initialization:
if matlabpool('size') == 0
    matlabpool('open',2);
else
    matlabpool('close');
    matlabpool('open',2);
end

% parallel loop always give the same random numbers...
parfor k = 1:10
    fprintf([num2str(rand(1,1)), ' ']);
end

一个理想的解决方案是通过 CPU 时间或类似方式在每个线程中初始化伪随机数生成器。像 rng('shuffle') 这样的东西似乎在这里无济于事...

控制台输出:

Sending a stop signal to all the workers ... stopped.
Starting matlabpool using the 'local' profile ... connected to 2 workers.
0.32457 0.66182 0.63488 0.64968 
0.26459 0.096779 0.50518 0.48662 0.034895 0.85227 

1
但是你那里有10个不同的数字,重复的在哪里?或者你是说你总是得到那10个数字? - Dan
可能是Random Number Generator Matlab with Multiple CPUs的重复问题。 - horchler
@Dan:是的,这就是我所说的 :-) 就像伪随机数生成器在每个线程中始终使用相同的数字进行初始化(也许是基于线程编号?) - matheburg
这可能会有所帮助,特别是关于RandStream.shuffleSeed方法的部分。 - chappjc
可能是重复的问题:在Matlab中,我如何生成10个随机种子? - Robert Seifert
在 thewaywewalk:这绝对不是你建议的重复。在 horchler:你是对的,问题是相同的,然而 Edric 给出的答案与那里给出的答案不同,同时也很有趣;总之,关闭问题不应该是一个选项。 - matheburg
1个回答

3

这里有关于各种选项的文档。下面是一种实现类似功能的方法。

numWorkers = matlabpool('size');
[streams{1:numWorkers}] = RandStream.create('mrg32k3a', ...
    'Seed', 'shuffle', 'NumStreams', numWorkers);
spmd
    RandStream.setGlobalStream(streams{labindex});
end

或者,为了避免在客户端创建所有流,您可以尝试以下操作:

rng('shuffle'); % shuffle the client
workerSeed = randi([0, 2^32-1]);
spmd
    stream = RandStream.create('mrg32k3a', ...
        'Seed', workerSeed, ...
        'NumStreams', numlabs, ...
        'StreamIndices', labindex);
    RandStream.setGlobalStream(stream);
end

谢谢,非常有帮助!说实话,我并不太理解你们的方法之间的区别。 - matheburg
1
主要的区别在于,在第二种情况下,我在每个工作进程上构建单独的RandStream对象,而不是在客户端构建所有对象并将它们发送过去。如果您有大量的工作进程,这将更为重要。 - Edric

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接