【问题标题】:Random Number Generator Matlab with Multiple CPUs具有多个 CPU 的随机数生成器 Matlab
【发布时间】:2013-08-09 15:34:13
【问题描述】:

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

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

parfor K = 1:10
    disp(randn)
end

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

【问题讨论】:

    标签: matlab random parallel-processing


    【解决方案1】:

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

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

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

    【讨论】:

      【解决方案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
      

      【讨论】:

        【解决方案3】:

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

        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 
        

        【讨论】:

        • 不幸的是,这不起作用。当我一遍又一遍地运行脚本时,它确实给出了不同的输出。然而,在 parfor 循环内部生成的每个随机数都不是独立的。例如,代码将生成输出数字,例如此处示例试验中所示的输出数字:0.7152 -1.2560 0.7152 -0.6342 -1.4328 0.0950 -1.4328 1.3823 1.3823 1.3823。我相信这是因为不同核心调用 rng('shuffle') 的时间基本是同时的。
        【解决方案4】:

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

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

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

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2016-02-15
          • 2018-04-16
          • 2012-12-04
          • 2013-12-14
          • 1970-01-01
          • 2010-12-25
          相关资源
          最近更新 更多