Main Content

多个流

使用多个独立流

MATLAB® 软件提供的生成器算法使您能够创建多个独立的随机数流。例如,支持多个独立流的四种生成器类型是组合多递归 ('mrg32k3a')、乘法滞后斐波那契 ('mlfg6331_64')、Philox 4x32 ('philox4x32_10') 和 Threefry 4×64 ('threefry4x64_20') 生成器。您可以创建保证不重叠的多个独立流,并且已对这些流执行证明流之间值的(伪)独立性的测试。有关支持多个流的生成器算法的详细信息,请参阅创建和控制随机数流中的生成器算法表。

RandStream.create 函数使您能够创建三个流,这些流具有相同的生成器算法和种子值,但在统计上是独立的。

[s1,s2,s3] = RandStream.create('mlfg6331_64','NumStreams',3)
s1 = 
mlfg6331_64 random stream
      StreamIndex: 1
       NumStreams: 3
             Seed: 0
  NormalTransform: Ziggurat

s2 = 
mlfg6331_64 random stream
      StreamIndex: 2
       NumStreams: 3
             Seed: 0
  NormalTransform: Ziggurat

s3 = 
mlfg6331_64 random stream
      StreamIndex: 3
       NumStreams: 3
             Seed: 0
  NormalTransform: Ziggurat

作为独立性证据,可以看到这些流在很大程度上是不相关的。

r1 = rand(s1,100000,1);
r2 = rand(s2,100000,1); 
r3 = rand(s3,100000,1);
corrcoef([r1,r2,r3])
ans = 3×3

    1.0000    0.0007    0.0052
    0.0007    1.0000    0.0000
    0.0052    0.0000    1.0000

根据应用的不同,如果需要仿真一些事件,仅创建一组独立流中的部分流可能很有用。指定 StreamIndices 参数,从包含多个流的一组流中仅创建其中的部分流。StreamIndex 属性返回您创建的每个流的索引。

streamNum = 256;
streamId = 4;
s4 = RandStream.create('mlfg6331_64','NumStreams',streamNum,'StreamIndices',streamId)
s4 = 
mlfg6331_64 random stream
      StreamIndex: 4
       NumStreams: 256
             Seed: 0
  NormalTransform: Ziggurat

由于多个流在统计上是独立的,因此可用于验证仿真的精度。例如,可以使用一组独立的流在不同的 MATLAB 会话或不同的处理器中多次重复蒙特卡罗模拟,并确定结果的变化情况。这样使得多个流可用于大规模的并行仿真。

使用种子获得不同结果

对于未明确支持独立流的生成器类型,不同的种子提供了可创建多个流的方法。通过使用不同的种子,可以创建返回不同的值并且各自独立执行的流。但是,更好的选择是使用专为多个独立的流设计的生成器,因为各流的统计学属性已经过谨慎验证。

通过梅森旋转生成器使用不同种子创建两个流。

s1 = RandStream('mt19937ar','Seed',1)
s1 = 
mt19937ar random stream
             Seed: 1
  NormalTransform: Ziggurat

s2 = RandStream('mt19937ar','Seed',2)
s2 = 
mt19937ar random stream
             Seed: 2
  NormalTransform: Ziggurat

在一个 MATLAB 会话中使用第一个流来生成随机数。

r1 = rand(s1,100000,1);

在另一个 MATLAB 会话中使用第二个流来生成随机数。

r2 = rand(s2,100000,1);

对于不同的种子,流返回的值通常是不相关的。

corrcoef([r1,r2])
ans = 2×2

    1.0000    0.0030
    0.0030    1.0000

使用不同种子的两个流可能看起来不相关,因为梅森旋转的状态空间(容纳 219937 个种子)远大于可能的种子数量(232 个)。除非使用大量不同种子,否则在不同仿真运行中重叠的可能性非常小。使用间隔很大的种子不会增加随机性水平。事实上,将该策略发挥到极致并在每次调用之前为生成器重新提供种子,可能导致值序列在统计上不独立且分布不一致。

如果您将为流提供种子作为初始化步骤,例如在 MATLAB 启动时或在运行仿真之前,则为流提供种子是最有用的。

使用子流获得不同结果

从流中获得不同结果的另一种方法是使用子流。与种子不同(在种子中,沿随机数序列的位置并不完全已知),子流之间的间隔是已知的,因此可以消除任何重叠的机会。与独立的并行流一样,子流之间的统计独立性已经过研究证明。简而言之,子流能够以更可控的方式完成在传统上用种子所做的许多事情,也是一种比并行流更轻量级的解决方案。

通过子流,可以快速轻松地确保在不同时间从相同的代码中得到不同结果。例如,在循环中生成几个随机数。

defaultStream = RandStream('mlfg6331_64');
RandStream.setGlobalStream(defaultStream)
for i = 1:5
    defaultStream.Substream = i;
    z = rand(1,i)
end
z = 0.6986
z = 1×2

    0.9230    0.2489

z = 1×3

    0.0261    0.2530    0.0737

z = 1×4

    0.3220    0.7405    0.1983    0.1052

z = 1×5

    0.2067    0.2417    0.9777    0.5970    0.4187

在另一个循环中,您可以生成独立于第一组(包含 5 次)迭代的随机值。

for i = 6:10
    defaultStream.Substream = i;
    z = rand(1,11-i)
end
z = 1×5

    0.2650    0.8229    0.2479    0.0247    0.4581

z = 1×4

    0.3963    0.7445    0.7734    0.9113

z = 1×3

    0.2758    0.3662    0.7979

z = 1×2

    0.6814    0.5150

z = 0.5247

其中每个子流都可以重新生成其循环迭代。例如,您可以返回到循环中的第 6 个子流。

defaultStream.Substream = 6;
z = rand(1,5)
z = 1×5

    0.2650    0.8229    0.2479    0.0247    0.4581

另请参阅

|

相关主题