3

我想编写一个使用多个 CPU 并行运行的 matlab 脚本。然后脚本应该打印出一系列正态分布的随机数。目前我的脚本如下所示:

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

parfor K = 1:10
    disp(randn)
end

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

4

4 回答 4

4

到目前为止给出的解决方案确实不正确,甚至可能是坏主意。应避免重复设置生成器的种子。更重要的是,使用不同种子分别创建的两个流不一定是独立的。这在描述创建多个流的页面上得到了解决:

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

因此,为了保证最佳的统计特性,最好使用支持子流的生成器。不幸的是,目前只有乘法滞后斐波那契生成器 ( 'mlfg6331_64') 和组合多重递归生成器 ( 'mrg32k3a')支持此属性。与默认的 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 算法,例如,如果您计划进行大规模 Monte Carlo 模拟,这可能很重要。如果您要使用随机数(和并行化),我建议您花一些时间阅读该RandStream课程的文档并阅读此处的示例

于 2013-08-09T18:13:28.380 回答
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
于 2013-08-09T16:49:33.777 回答
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 
于 2013-08-09T16:09:59.500 回答
0

一些随机数生成器存储一个值,该值本质上是特定种子值的伪随机数序列的索引。

当并行运行时,不同的 CPU 可能会相互覆盖该索引值的设置。

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

于 2013-08-10T06:18:32.973 回答