具有多个CPU的随机数发生器Matlab

时间:2013-08-09 15:34:14

标签: matlab random parallel-processing

我想编写一个使用多个CPUS并行运行的matlab脚本。然后,该脚本应打印出一系列正态分布的随机数。目前我的脚本看起来像这样:

matlabpool close force local
clusterObj = parcluster;
matlabpool(clusterObj);

parfor K = 1:10
    disp(randn)
end

按预期打印出一系列随机数。但是,当我再次运行代码时,再次打印出完全相同的数字序列。我不想要这个。每次我运行我的脚本时,它应该打印出一个独立的随机数字序列。同样,每次我启动matlab时,我的脚本应该在我第一次运行时打印出10个随机生成的数字的不同序列。我该怎么做呢?

4 个答案:

答案 0 :(得分:4)

到目前为止给出的解决方案确实不正确,甚至可能是坏主意。应该避免反复设置发电机的种子。更重要的是,两个流分别使用不同的种子are not necessarily independent创建。这在this page上解决,描述了多个流的创建:

  

对于不明确支持独立流的生成器类型,不同的种子提供了创建多个流的方法。但是,使用专门为多个独立流设计的生成器是一个更好的选择,因为可以更好地理解跨流的统计属性。

因此,为了保证最佳的统计特性,最好使用支持子流的发生器。不幸的是,只有乘法滞后的Fibonacci生成器('mlfg6331_64')和组合的多个递归生成器('mrg32k3a')当前support this property。与默认的Mersenne Twister生成器('mt19937ar')相比,它们具有明显更小的周期。以下是如何创建和使用带子流的随机数流:

seed = 1;
n = 10;
[stream{1:n}] = RandStream.create('mrg32k3a','NumStreams',n,'Seed',seed);
parfor k = 1:n
    r = randn(stream{k},[1 3]);
    disp(r);
end

有几件事。只需在循环外的一个调用中生成所有随机数,您可以获得更好的性能。这也允许您使用默认的Mersenne Twister算法,例如,如果您计划进行大规模蒙特卡罗模拟,这可能很重要。如果您要使用随机数(和并行化),我建议您花一些时间阅读RandStream class的文档并浏览examples here

答案 1 :(得分:2)

将rand,randi和randn使用的随机数生成器重置为其默认启动设置,以便rand生成与重新启动MATLAB®时相同的随机数:

rng('default')
rand(1,5)
ans =
    0.8147    0.9058    0.1270    0.9134    0.6324

保存rand,randi和randn使用的随机数生成器的设置,从rand生成5个值,恢复设置,然后重复这些值:

s = rng;
u1 = rand(1,5)
u1 =
    0.0975    0.2785    0.5469    0.9575    0.9649

rng(s);
u2 = rand(1,5)
u2 =
    0.0975    0.2785    0.5469    0.9575    0.9649

使用基于当前时间的种子重新初始化rand,randi和randn使用的随机数生成器。每次执行此操作时,rand都会返回不同的值。请注意,每个MATLAB会话通常不需要多次执行此操作,因为它可能会影响MATLAB生成的随机数的统计属性:

rng('shuffle');
rand(1,5);

我会尝试不同的发电机:

rng('shuffle', generator)

rng('shuffle',generator)另外指定rand,randi和randn使用的随机数生成器的类型。生成器输入是以下之一:

'twister'       Mersenne Twister
'combRecursive'     Combined Multiple Recursive
'multFibonacci'     Multiplicative Lagged Fibonacci
'v5uniform'         Legacy MATLAB® 5.0 uniform generator
'v5normal'      Legacy MATLAB 5.0 normal generator
'v4'                Legacy MATLAB 4.0 generator

答案 2 :(得分:0)

您可以为每次迭代将随机种子设置为不同的值:

matlabpool close force local
clusterObj = parcluster;
matlabpool(clusterObj);

rng('shuffle');
seeds = round(10000*abs(randn(10,1)));

parfor K = 1:10
    rng(seeds(K))
    disp(randn)
end 

答案 3 :(得分:0)

某些随机数生成器存储的值实际上是特定种子值的伪随机数序列的索引。

当并行运行时,不同的CPU可能会覆盖该索引值的每个其他设置。

您可以使用一个CPU预先分配一个随机数向量,然后执行从该向量中提取数字的并行for循环。