控制工作单元上的随机数流
与您的 MATLAB® 客户端相比,随机数生成函数 rand、randi 和 randn 在并行计算中的行为有所不同。您可以更改并行工作单元或客户端上的随机数生成器的行为,以生成可重现的随机数流。
默认情况下,MATLAB 客户端和 MATLAB 工作单元使用不同的随机数生成器,即使工作单元是与客户端位于同一台计算机上的本地集群的一部分。下表总结了客户端和工作单元的默认设置:
| 生成器 | 种子 | 正态变换 | |
|---|---|---|---|
| 客户端 | 'Twister' 或 'mt19937ar' | 0 | 'Ziggurat' |
| 工作单元(本地或远程) | 'Threefry' 或 'Threefry4x64_20' | 0 | 'Inversion' |
有关可用生成器和正态变换的更多信息,请参阅 选择随机数生成器。集群中的每个工作单元从具有表中属性的独立流中抽取随机数。默认情况下,parfor 循环中每个工作单元上生成的随机数彼此不同,并且与客户端上生成的随机数也不同。
注意
如果您的工作单元上有 GPU,则不同的设置适用于 GPU 上的随机数流。有关详细信息,请参阅GPU 上的随机数流。
客户端和工作单元
如果需要在客户端和工作单元中生成相同的数字流,则可以设置一个来匹配另一个。您可以使用 rng 设置生成器算法和种子。
例如,您可能在工作单元上运行一个脚本作为批处理作业,并且需要与客户端相同的生成器或序列。假设您从一个名为 randScript1.m 的脚本文件开始,其中包含以下行:
R = rand(1,4);
您可以在客户端运行该脚本,然后将其作为批处理作业在工作单元上运行。请注意,结果中默认生成的随机数序列是不同的。
randScript1; % In client
R
R =
0.8147 0.9058 0.1270 0.9134
parallel.defaultClusterProfile('Processes') c = parcluster(); j = batch(c,'randScript1'); % On worker wait(j);load(j); R
R =
0.1349 0.6744 0.9301 0.5332为了获得相同的结果,您可以将客户端和工作单元设置为使用相同的生成器和种子。其中,文件 randScript2.m 包含以下代码:
rng(1,'Threefry');
R = rand(1,4);现在,在客户端和工作单元上运行新脚本:
randScript2; % In client
R
R =
0.1404 0.8197 0.1073 0.4131j = batch(c,'randScript2'); % On worker wait(j); load(j); R
R =
0.1404 0.8197 0.1073 0.4131要将客户端和工作单元上的随机数生成器设置重置为默认值,您可以将此代码添加到 randScript2.m 的末尾。
rng('default')不同的工作单元
默认情况下,集群中执行同一项作业的每个工作单元都有一个独立的随机数流。如果并行调用 rand、randi 或 randn,则每个工作单元都会产生一个唯一的随机数序列。
注意
因为 rng('shuffle') 根据当前时间为随机数生成器设定种子,所以如果您想确保流独立,请不要使用此命令在不同的工作单元上设置随机数流。当命令同时发送给多个工作单元时尤其如此,例如在 parfor、spmd 或通信作业内部。对于工作单元上的独立流,使用默认行为;或者如果这不能满足您的需求,请考虑在每个工作单元上使用 RandStream 使用唯一的子流。
此示例使用并行池中的两个工作单元来显示它们生成唯一的随机数序列。
p = parpool(2); spmd R = rand(1,4); % Different on each worker end R{1},R{2}
ans =
0.1349 0.6744 0.9301 0.5332
ans =
0.6383 0.5195 0.1398 0.6509
delete(p)
如果需要所有工作单元生成相同的数字序列,您可以将每个工作单元设置为使用相同的生成器设置:
p = parpool(2); spmd rng(0,'Philox'); % Default seed 0. R = rand(1,4); % Same on all workers end R{1},R{2}
ans =
0.3655 0.6975 0.1789 0.4549
ans =
0.3655 0.6975 0.1789 0.4549delete(p)
如果您需要控制 parfor 循环每次迭代的随机数,请参阅 在 parfor 循环中重复随机数。
正态分布的随机数
如果您使用 randn 函数处理正态分布的随机数,则可以使用与上述相同的方法通过 RandStream 在每个工作单元和客户端上设置生成器类型、种子和正态变换算法。
例如,假设文件 randScript3.m 包含代码:
stream = RandStream('Threefry','Seed',0,'NormalTransform','Inversion'); RandStream.setGlobalStream(stream); R = randn(1,7)
batch 或 spmd)来生成相同的随机数序列:R =
-0.3479 0.1057 0.3969 0.6544 -1.8228 0.9587 0.5360