Reproducible results when creating random matrices across parallel calls in MATLAB

You can post your problem related to MATLAB Projects here. We will try our best to help you out.
Post Reply
Charles
Posts: 20
Joined: Sat Feb 18, 2017 7:12 am

Reproducible results when creating random matrices across parallel calls in MATLAB

Post by Charles » Mon Mar 06, 2017 12:36 pm

I want to create a number of random matrices, but they are really big to fit in memory, so I'd like to find a way to reproduce them across computers, so that when I need to send them to another machine, I'd just need to send the code. Here is how I want to do it:

Code: Select all

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
What I'm worried about is the parfor loop, I need to be able to reproduce the random matrices no matter what the order of indices in the parfor is. So I decided to use a MATLAB stream for this:

Save the global stream
Create a new stream, set the seed and appropriate substream (which depends on iter and j)
Do the math
Put back the global stream
Here is my code (the variables n,p,R_type control how the random matrices are made, but they are not important, and K is the same variable as the one from above, I need it in the line substream_id = (iter - 1) * K + j;) :

Code: Select all

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
Tried some code and here it is:

Code: Select all

>> 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
I wonder if the code is correct, and does it retain the state of the global stream after the function call? Please help me, thank you very much

Post Reply