Berk U.
Berk U.

Reputation: 7188

Problems Generating Scrambled Quasi-Monte Carlo Numbers in Parfor Loops

I am having an issue generating scrambled quasi-monte carlo numbers in parfor loops.

The problem is that when I generate multiple sets of these numbers within a parfor loop, the numbers in each set end up being identical. I am including a very simple example below.

D = 3;
M = 1000;
numbers = cell(1,4);

mystream = qrandstream(scramble(sobolset(D),'MatousekAffineOwen'));
myfun = @(x) qrand(mystream,x);

parfor i = 1:4
    numbers{i} = myfun(M);
end

To demonstrate the issue, after running this code, the numbers in numbers{1}, numbers{2}, numbers{3} and numbers{4} are identical as:

>>numbers{1}(1:3,:)
ans =
          0.76          0.05          0.77
          0.33          0.96          0.23
          0.60          0.72          0.52

>> numbers{2}(1:3,:)
ans =
          0.76          0.05          0.77
          0.33          0.96          0.23
          0.60          0.72          0.52

I'm wondering whether anyone can think of a fix for this issue. I figure there must be something that I can do, as the problem does not occur when I use a normal random stream of numbers.

I should mention that it will not be possible for me to exploit something like the 'Skip' or 'Leap' properties of Quasi-Random Number streams. The reason is that I use the snippet of code above in a larger MATLAB program that I run in parallel...

Upvotes: 2

Views: 651

Answers (1)

Bryan P
Bryan P

Reputation: 6220

You need a separate call to scramble on each parallel worker. This can be done by moving the qrandstream related statements inside the parfor loop as in:

D = 3;
M = 1000;
numbers = cell(1,4);

parfor i = 1:4
    mystream = qrandstream(scramble(sobolset(D),'MatousekAffineOwen'));
    myfun = @(x) qrand(mystream,x);

    numbers{i} = myfun(M);
end

Why: Although MatousekAffineOwen does have a random scrambling order, MATLAB treats quasi-random sequences as a giant pre-defined array and sample data is computed on the fly each time a new sample is needed. Scrambling changes this order but the qrandstream object behaves as if it happened once, as soon as scramble is called. After that, the qrandstream is a deterministic stream of numbers. In non-parallel code (or if you use parfor without first enabling a matlabpool) this set up works fine with a single qrandstream b/c MATLAB keeps working through the (virtual) list with each call to qrand.

But in parfor, a copy of all of the needed variables, functions, etc. is passed to each worker. As a result each worker gets a duplicate, pre-determined stream of quasi-random numbers, resulting in identical stream of samples on each worker. Incidentally this does not mean that all numbers{i} will have identical values. For parfor loop ranges greater than the number of parallel workers (machine cores), multiple loop iterations will occur on the same worker and hence share the same, non-repeating qrandstream. On my two core machine your 4 iteration example code exhibits this behavior with numbers{1}==numbers{4} and numbers{2}==numbers{3}

Upvotes: 4

Related Questions