在MATLAB中跨并行调用创建随机矩阵时的可重现结果

Dan*_*ong 16 random matlab matrix

我想创建一些随机矩阵,但它们非常适合内存,所以我想找到一种方法在计算机上重现它们,这样当我需要将它们发送到另一台机器时,我会只需要发送代码.这是我想要的方式:

num_of_iters = 10;
K = 200;
for iter = 1:num_of_iters
    parfor j = 1:K
        R = make_random_R(iter,j,.....);
        % Do something
    end
end
Run Code Online (Sandbox Code Playgroud)

我担心的是parfor循环,无论parfor中的索引顺序如何,我都需要能够重现随机矩阵.所以我决定使用MATLAB流:

  • 保存全局流
  • 创建一个新流,设置种子和适当的子流(取决于iter和j)
  • 算一算
  • 放回全局流

这是我的代码(变量n,p,R_type控制随机矩阵是如何形成的,但它们并不重要,K与上面的变量相同,我需要它在行中substream_id = (iter - 1) * K + j;):

function [R] = make_random_R(iter,j,n,K,p,R_type)
% Data as code
% R_type: 'posneg' or 'normdist'
% 1 <= iter <= 100
% 1 <= j <= K
% K: Number of classifiers
% n: Number of observations

assert(strcmp(R_type,'posneg') || strcmp(R_type,'normdist'),'R_type must be posneg or normdist');
assert(iter >= 1,'Error: iter >= 1 not satisfied');
assert((1 <= j) && (j <= K),'Error: 1 <= j <= K not satisfied');
assert(K > 0,'Error: K > 0 not satisfied');

globalStream = RandStream.getGlobalStream;
globalState =  globalStream.State;

stream=RandStream('mlfg6331_64','Seed',1);
substream_id = (iter - 1) * K + j;
stream.Substream = substream_id;
RandStream.setGlobalStream(stream);

switch R_type
    case 'posneg'        
        q0=ceil(2*log(n)/0.25^2)+1;
        if (q0 < p)
            q = q0;
        else
            q = ceil(p/2);
        end
        R = randi([0 1],p,q);
        R(R == 0) = -1;
    case 'normdist'        
        q = 2*ceil(log2(p));
        R = normrnd(0,1,[p,q]);    
end
RandStream.setGlobalStream(globalStream);
globalStream.State = globalState;
end
Run Code Online (Sandbox Code Playgroud)

尝试了一些代码,这里是:

>> iter = 2;
>> j = 3;
>> n=100;
>> K=10;
>> p=6;
>> R_type = 'normdist';
>> for j=1:K
j
make_ran
>> parfor j=1:K
j
make_random_R(iter,j,n,K,p,R_type)
end
Starting parallel pool (parpool) using the 'local' profile ... connected to 4 workers.

ans =

     7


ans =

   -0.3660    0.8816    1.1754   -0.4987   -1.8612   -0.3683
    0.9504   -0.3067   -0.5156   -0.2383   -1.1661    0.3622
    2.0743   -0.4195    0.5021    0.3954    0.2415   -0.4552
   -0.0474   -0.1645   -0.1725   -0.4938   -0.2559    0.2188
    1.0735    0.3660    0.1043    0.4403   -0.3166    1.1241
   -1.0421   -1.4528   -0.4976   -0.7166   -1.1328   -2.0260


ans =

     2


ans =

   -1.6629    0.0213   -1.8138   -0.4375    0.3575   -0.0353
    0.6653   -1.2662   -0.3977   -0.6540   -1.2131    0.4858
    0.3421    1.1266   -0.6066   -1.2095    1.5496   -0.9341
    0.2145    0.7192   -2.2087    0.7597   -0.0110   -1.1282
   -0.3511   -0.7305   -0.1143    0.0242    0.2431   -0.8612
    0.5875    1.2665   -2.1943   -0.4879    0.0120   -1.1539


ans =

     1


ans =

   -0.5300    2.4077   -0.3478    1.8695   -1.1327   -1.0734
   -0.2540   -1.1265    0.3152    0.4265    1.2777    0.0959
    0.5005   -0.7557    0.6194    1.5873    0.0961   -1.9216
    0.7275    0.5420   -0.6237   -0.2228    0.8915    0.4644
    0.8131   -0.1492    0.9232    0.8410   -0.0637    2.1163
   -1.1995    0.2338   -1.3726    0.1604   -0.1855    1.3826


ans =

     8


ans =

   -0.5146    2.2106    2.7200   -1.2136    1.0004    1.3089
    0.7225    0.2746   -0.8798    0.2978   -0.8490    1.6744
    1.1998   -0.0363    1.9105   -0.7747   -0.8707   -0.6823
    0.6801    1.3194   -0.0685    0.5944    1.5078   -1.6821
    0.0876    1.2150   -0.0747    0.0324   -1.1552    0.0966
   -0.0624   -0.3874   -0.5356    0.6353    1.4090   -1.1014


ans =

     6


ans =

    0.5866   -1.0222   -0.2168    0.8582    1.4360    0.0699
    2.0677   -0.4740   -0.8763    1.7827    0.1930   -1.2167
   -0.3941   -0.5441    0.3719   -0.0609    0.7138   -1.0920
    0.3622   -0.0459   -0.0221    0.2030   -0.7695   -0.8963
   -0.1986   -0.2560    0.6666    0.4831   -1.2028   -0.9423
    0.1656    1.2006   -1.1131    0.7704   -0.6906   -1.3143


ans =

     5


ans =

   -0.5782   -0.3634    1.5381   -1.3173   -0.9493    0.8480
    1.5921   -0.4069    0.7795   -0.3390   -0.1071    0.4201
   -0.0184    0.2865   -0.1139   -0.1171    0.2288    0.5511
    0.1787    0.7583    0.3994    1.0457    0.3291   -0.9150
    0.3641   -0.6420   -0.2096    0.7761    0.4022   -0.7478
    0.1165    0.7142    0.7029   -1.1195    0.0905    0.6810


ans =

     4


ans =

    0.1246   -0.3173    0.8068    0.6485   -0.8572    0.2275
    0.3674   -0.0507   -0.9196    0.6161   -0.5821   -0.4291
   -1.0142   -1.1614   -2.5438    1.5915    2.0356    0.4535
   -0.2111   -0.3974    0.0376    0.3825   -1.9702    1.5318
   -0.3890    0.9210   -0.0635    0.3248    1.8666   -0.0160
    1.3908   -0.7204   -0.6772   -0.0713    0.0569    0.5929


ans =

     3


ans =

   -0.1602    0.6891    0.4725    0.0277   -2.0510   -2.2440
   -0.7497    1.8225   -0.4433    0.4090    0.9021   -1.6683
    0.0659    0.3909    0.2043    0.9065    1.4630    0.3091
   -0.3886    0.6715   -0.9742   -0.5468    0.2890    0.5625
   -0.4558    0.4770   -0.1888   -0.6504    0.3281    1.3767
    0.3983    0.5834    0.9360    0.8604   -0.9776    0.6755


ans =

    10


ans =

   -0.4843   -0.4512    0.7544    0.7585   -0.4417   -0.0208
    1.8537   -1.6935   -2.7067   -0.5077    0.9616   -1.7904
   -1.6943   -1.0988    0.1208   -0.8100    1.8778    1.1654
    1.1759   -0.7087   -1.2673   -0.1381   -0.0710    0.5343
    0.2589   -0.5128   -0.3970    0.6737    0.8097    2.7024
   -0.8933    0.2810    0.8117   -0.5428   -0.8782    1.1746


ans =

     9


ans =

    0.0254   -0.7993    1.5164    1.2921   -1.1013    1.8556
   -0.6280    0.9374   -0.1962    0.1685   -0.5079    0.4333
   -0.3962   -0.9977    0.6971   -1.0310   -1.1997   -2.1391
    0.7179    1.0177   -0.8874   -0.6732    0.7295    1.4448
   -1.1793   -1.3210    1.5292    0.2280    1.9337    1.0901
   -0.0926    0.1798   -1.1740    0.3447    2.4578    0.4170
Run Code Online (Sandbox Code Playgroud)

我想知道代码是否正确,并且它在函数调用后是否保留全局流的状态?请帮帮我,非常感谢你

Had*_*adi 4

MATLAB 从“已知”但“复杂”的函数生成随机数,因此您可以生成相同的随机序列!数字 。

\n\n

为此,您应该使用“rng”函数
\n将 rng 设置为默认值,以便重置随机数生成。

\n\n
rng(\'default\');\nrand(1,5)\nans=\n0.8147  0.9058  0.1270  0.9134  0.6324\n
Run Code Online (Sandbox Code Playgroud)\n\n

那么如果你想重现这个随机数序列,你可以写:

\n\n
rng(\'default\');\nrand(1,5)\nans=\n    0.8147  0.9058  0.1270  0.9134  0.6324\n
Run Code Online (Sandbox Code Playgroud)\n\n

另一种方法是获取/设置随机数生成的种子:

\n\n
s=rng;\nrand(1,5)\nans= 0.0975  0.2785  0.5469  0.9575  0.9649\n
Run Code Online (Sandbox Code Playgroud)\n\n

并重现相同的序列。

\n\n
rng(s);\nrand(1,5)\nans=\n     0.0975  0.2785  0.5469  0.9575  0.9649\n
Run Code Online (Sandbox Code Playgroud)\n\n

不,“rng”本身是一个丰富的函数,您可以在 matlab 文档中对其进行更多研究。

\n\n

(我希望我正确理解这个问题)

\n\n

回答@m7913d 的评论

\n\n
\n

“默认情况下,MATLAB\n是 Mersenne Twister 生成器 (\'twister\'),并且对于\n 工作器来说,默认值是组合多重递归生成器\n (\'CombRecursive\' 或 \'mrg32k3a\')。如果需要生成\n 客户端和工作人员中的数字流相同,您可以将其中一个设置为\n 与另一个匹配。”

\n
\n\n

显然,matlab工作人员使用与matlab本身不同的函数(用于生成随机数),因此您也可以在“rng”函数中设置默认函数,

\n\n
rng(5,\'twister\') % for using twister method to generate random number\n
Run Code Online (Sandbox Code Playgroud)\n\n

有关更多信息,请尝试使用 matlab 中的此文档

\n\n

新示例表明您可以在 parfor 中重现随机数序列:

\n\n
>> parfor i=1:3\nrng(3,\'twister\');\nrand(1,5)\ni\nend\n\nans =\n\n    0.5508    0.7081    0.2909    0.5108    0.8929\n\n\nans =\n\n     3\n\n\nans =\n\n    0.5508    0.7081    0.2909    0.5108    0.8929\n\n\nans =\n\n     1\n\n\nans =\n\n    0.5508    0.7081    0.2909    0.5108    0.8929\n\n\nans =\n\n     2\n
Run Code Online (Sandbox Code Playgroud)\n\n

评论的重要部分:

\n\n
\n

关于“客户端工作者”,正如我之前所说,matlab为所有客户端工作者使用默认函数,因此结果是完全可重现的,只是创建随机数的默认函数与matlab自己的默认函数不同。这不是问题,您可以使用 rng 函数在 matlab 及其工作人员中设置默认函数(答案中的最后一个示例)

\n
\n\n
\n\n
\n

关于使用全局流,使用全局流没有区别,您应该使用 rng 函数设置种子值以获得相同的可重现结果,全局流只是表明您使用哪个函数来生成随机数,matlab 有大约6 函数来完成这项工作,但如果您有自己的函数,您可以将其设置在全局流上,然后您应该再次使用 rng 函数在每次生成随机数时获得相同的序列

\n
\n