houbysoft
houbysoft

Reputation: 33412

Less strict alternative to parfor in matlab?

I have code that is structurally similar to the following in Matlab:

bestConfiguration = 0;
bestConfAwesomeness = 0;

for i=1:X
    % note that providing bestConfAwesomeness to the function helps it stop if it sees the current configuration is getting hopeless anyway
    [configuration, awesomeness] = expensive_function(i, bestConfAwesomeness);
    if awesomeness > bestConfAwesomeness
        bestConfAwesomeness = awesomeness;
        bestConfiguration = configuration;
    end
end

There is a bit more to it but the basic structure is the above. X can get very large. I am trying to make this code run in parallel, since expensive_function() takes a long time to run.

The problem is that Matlab won't let me just change for to parfor because it doesn't like that I'm updating the best configuration in the loop.

So far what I've done is:

[allConfigurations, allAwesomeness] = deal(cell(1, X));

parfor i=1:X
    % note that this is not ideal because I am forced to use 0 as the best awesomeness in all cases
    [allConfigurations{i}, allAwesomeness{i}] = expensive_function(i, 0);
end

for i=1:X
    configuration = allConfigurations{i};
    awesomeness = allAwesomeness{i};
    if awesomeness > bestConfAwesomeness
        bestConfAwesomeness = awesomeness;
        bestConfiguration = configuration;
    end
endfor

This is better in terms of time it takes to run; however, for large inputs it takes huge amounts of memory because all the configurations are always saved. Another problem is that using parfor forces me to always provide 0 as the best configuration even though better ones might be known.

Does Matlab provide a better way of doing this?

Basically, if I didn't have to use Matlab and could manage the threads myself, I'd have one central thread which gives jobs to workers (i.e. make them run expensive_function(i)) and once a worker returns, look at the data it produced and compare it to the best found so far and update it accordingly. There would be no need to save all the configurations which seems to be the only way to make parfor work.

Is there a way to do the above in Matlab?

Upvotes: 1

Views: 697

Answers (2)

Edric
Edric

Reputation: 25160

Using the bestConfAwesomeness each time round the loop means that the iterations of your loop are not order-independent, hence why PARFOR is unhappy. One approach you could take is to use SPMD and have each worker perform expensiveFunction in parallel, and then communicate to update bestConfAwesomeness. Something like this:

bestConfiguration = 0;
bestConfAwesomeness = 0;
spmd
  for idx = 1:ceil(X/numlabs)
    myIdx = labindex + ((idx-1) * numlabs);
    % should really guard against myIdx > X here.
    [thisConf, thisAwesome] = expensiveFunction(myIdx, bestConfAwesomeness);
    % Now, we must communicate to see if who is best
    [bestConfiguration, bestAwesomeness] = reduceAwesomeness(...
        bestConfiguration, bestConfAwesomeness, thisConf, thisAwesome);
  end
end

function [bestConf, bestConfAwesome] = reduceAwesomeness(...
    bestConf, bestConfAwesome, thisConf, thisAwesome)
% slightly lazy way of doing this, could be optimized
% but probably not worth it if conf & awesome both scalars.
allConfs = gcat(bestConf);
allAwesome = gcat(thisAwesome);
[maxThisTime, maxLoc] = max(allAwesome);
if maxThisTime > bestConfAwesome
    bestConfAwesome = maxThisTime;
    bestConf = allConfs(maxLoc);
end
end

Upvotes: 2

Jonas
Jonas

Reputation: 74940

I'm not sure that the kind of control over your threads is possible with Matlab. However, since X is very large, it may be worth doing the following, which costs you one more iteration of expensiveFunction:

%# calculate awesomeness
parfor i=1:X
   [~,awesomeness(i)] = expensiveFunction(i);
end
%# find the most awesome i
[mostAwesome,mostAwesomeIdx] = min(awesomeness);
%# get the corresponding configuration
bestConfiguration = expensiveFunction(mostAwesomeIdx);

Upvotes: 1

Related Questions