Search code examples
matlabparallel-processingparformle

Parallelize MATLAB for loop to calculate MLE


I am attempting to speed up my MATLAB code by using parfor, however, I am doing it incorrectly. My code is rather simple, I am fitting some data using MATLAB's built-in mle function by using varying initial guesses for the mean (mm) and variance (vv). onestagepdf2 is my probability density function.

Here is the code snippit:

mm=linspace(.1, 1, 2); % mean
vv=linspace(.1, 2, 2); % variance
N=length(mm);
n=length(vv);

pd=zeros(n*N,2);
ld = NaN*ones(n*N,1);

options = statset('MaxIter',10000, 'MaxFunEvals',10000);

parfor i=1:N  % pick a mean
    m=mm(i);
    parfor j=1:n  %  pick a variance
        v=vv(j);
        x0=[m,v];
        [p,conf1]=mle(data,'pdf',@onestagepdf2,'start',x0, 'upperbound', [Inf Inf],'lowerbound',[0 0],'options',options)
        pd(n*(i-1)+j,:)=p;  % store parameter values from mle
        l=onestagepdf2(data,p(1),p(2)); % evaluate pdf with parameter values
        ld(n*(i-1)+j)=sum(log(l));  % store likelihood value

    end
end

The error that I receive is:

'The variable pd in a parfor cannot be classified.'


Solution

  • pd = zeros(n, N, 2); %initialise culprits
    ld= zeros(n,N);
    parfor ii=1:N  % pick a mean
        m=mm(ii);
        for jj=1:n  %  Parallellise the second parfor
            v=vv(jj);
            x0=[m,v];
            [p,conf1]=mle(data,'pdf',@onestagepdf2,'start',x0, 'upperbound', [Inf Inf],'lowerbound',[0 0],'options',options)
            pd(ii, jj, :) = p;=p;  % store parameter values from mle
            l=onestagepdf2(data,p(1),p(2)); % evaluate pdf with parameter values
            ld(ii,jj)=sum(log(l));  % store likelihood value
    
        end
    end
    

    Your pd was indeed the culprit, as @Trilarion stated, for the error you got. Probably ld also isn't too great, with the same syntax, so initialise that as well. This happened because parfor wants to know what the size of all variables within the loop is before executing. That this is a fixed maximum size is unknown to MATLAB, since you are using the loop variables to "change" the size.

    Probably you had "orange wiggles" below those two lines (like spell-check errors) when you ran this as a for loop saying that "pd appears to be growing in size each iteration. Please consider preallocating for speed". This is required by parfor, since the order of iteration is not sequential it is impossible to grow arrays this way.

    Secondly, you cannot nest parfor loops. You can use things like a function with a parfor and run that within the parfor, but that won't get you a speed-up since you are already using all your workers.

    See Saving time and memory using parfor in Matlab? for more general information on parfor especially on speed.