1
votes

I'm trying to run this loop as a parfor-loop:

correlations = zeros(1,N);   
parfor i = 1:(size(timestamps,1)-1)
    j = i+1;
    dts = timestamps(j) - timestamps(i);
    while (dts < T) && (j <= size(timestamps,1))
        if dts == 0 && detectors(i) ~= detectors(j)
            correlations(1) = correlations(1) + 2;
        elseif detectors(i) ~= detectors(j)
            dts = floor(dts/binning)+1;
            correlations(dts) = correlations(dts) + 1;
        end
        j = j + 1;
        if j <= size(timestamps,1)
            dts = timestamps(j) - timestamps(i);
        end
    end
end

Matlab gives me the following error:

Error: File: correlate_xcorr.m Line: 18 Column: 17
The variable correlations in a parfor cannot be classified.
See Parallel for Loops in MATLAB, "Overview".

Line 18 is the following:

correlations(1) = correlations(1) + 2;

I can not understand why this shouldn'n be possible. The final value of correlations doesn't depend on the order in which the loop is executed, but only dts and detectors. I found similar examples in the documentation which work fine.

Why can't Matlab execute this code and how can I fix it?

2
fixing the German text would be appreciated :)fpe
Sorry I got a little confused for a second.Stein
Watch out, that's a race condition! All your parallel process are trying to access and edit that same element correlations(1) so if two of them read it at the same time and both try update it by adding 1 it will only get 1 added instead of 2. This will produce the wrong answer even if there are no errors. Maybe matlab recognizes this and is trying to stop you? You might have to block the variable with an if statement to make sure none of the other processes can read it until it has been written to?Dan
Well like I said, even if it doesn't error, you're still leaving yourself open to getting the wrong answer because that is a race condition. Try it to 1000000Dan

2 Answers

2
votes

I found the following solution and it seems to work. The program looks a litte different, but it has the same shape. This way Matlab is forced to think x/correlations is a reduction variable.

X = zeros(1,5);
parfor i= 1:1000
    a = zeros(1,5);
    dts = randi(10)-1;
    if dts == 0
        a(1) = (a(1) + 2);
    elseif dts <= 5
        a(dts) = a(dts) +1;
    end
    X = X + a;
end
2
votes

MATLAB cannot determine that your loop is order independent because of the way you're accessing correlations(1) from multiple iterations of the PARFOR loop. It looks like this value is in some way 'special', it should work to make a 'reduction' variable, i.e. replace correlations(1) with correlations_1 or something.

The next problem you'll encounter is that you are not correctly 'slicing' the remainder of correlations. For MATLAB to analyse a PARFOR loop, it needs to be able to tell that each loop iteration is writing only to its 'slice' of the output variables. In practice, this means that you must index the outputs using literally the loop index.

More about PARFOR variable classification here: http://www.mathworks.com/help/distcomp/advanced-topics.html#bq_of7_-1

EDIT:

If you want correlations to behave strictly as a reduction variable as I believe you imply in your comments, you need to give PARFOR a clue that's what you mean: in particular, you need to add to the whole variable each time you need to. In other words, something more like:

parfor ...
    dummyVec = zeros(1, N);
    dummyVec(elementToIncrement) = 1;
    correlations = correlations + dummyVec;
end

I agree this is non-obvious. See http://blogs.mathworks.com/cleve/2012/11/26/magic-squares-meet-supercomputing/ for more.