Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

MATLAB: What happens for a global variable when running in the parallel mode?

What happens for a global variable when running in the parallel mode?

I have a global variable, "to_be_optimized_parameterIndexSet", which is a vector of indexes that should be optimized using gamultiobj and I have set its value only in the main script(nowhere else).

My code works properly in serial mode but when I switch to parallel mode (using "matlabpool open" and setting proper values for 'gaoptimset' ) the mentioned global variable becomes empty (=[]) in the fitness function and causes this error:

??? Error using ==> parallel_function at 598
Error in ==> PF_gaMultiFitness at 15 [THIS LINE: constants(to_be_optimized_parameterIndexSet) = individual;]
 In an assignment  A(I) = B, the number of elements in B and
 I must be the same.

Error in ==> fcnvectorizer at 17
        parfor (i = 1:popSize)

Error in ==> gamultiobjMakeState at 52
        Score =
        fcnvectorizer(state.Population(initScoreProvided+1:end,:),FitnessFcn,numObj,options.SerialUserFcn);

Error in ==> gamultiobjsolve at 11
state = gamultiobjMakeState(GenomeLength,FitnessFcn,output.problemtype,options);

E    rror in ==> gamultiobj at 238
[x,fval,exitFlag,output,population,scores] = gamultiobjsolve(FitnessFcn,nvars, ...

Error in ==> PF_GA_mainScript at 136
[x, fval, exitflag, output] = gamultiobj(@(individual)PF_gaMultiFitness(individual, initialConstants), ...

Caused by:
    Failure in user-supplied fitness function evaluation. GA cannot continue.

I have checked all the code to make sure I've not changed this global variable everywhere else.

I have a quad-core processor.

Where is the bug? any suggestion?

EDIT 1: The MATLAB code in the main script:

clc
clear
close all

format short g
global simulation_duration % PF_gaMultiFitness will use this variable
global to_be_optimized_parameterIndexSet % PF_gaMultiFitness will use this variable
global IC  stimulusMoment % PF_gaMultiFitness will use these variables

[initialConstants IC] = oldCICR_Constants; %initialize state
to_be_optimized_parameterIndexSet = [21    22    23    24    25    26    27    28    17    20];
LB = [ 0.97667      0.38185      0.63529     0.046564      0.23207      0.87484      0.46014    0.0030636   0.46494      0.82407 ];
UB = [1.8486      0.68292      0.87129      0.87814      0.66982       1.3819      0.64562      0.15456   1.3717       1.8168];
PopulationSize = input('Population size? ') ;
GaTimeLimit = input('GA time limit? (second)  ');
matlabpool open
nGenerations = inf;
options = gaoptimset('PopulationSize', PopulationSize, 'TimeLimit',GaTimeLimit, 'Generations', nGenerations, ...
    'Vectorized','off', 'UseParallel','always');

[x, fval, exitflag, output] = gamultiobj(@(individual)PF_gaMultiFitness(individual, initialConstants), ...
    length(to_be_optimized_parameterIndexSet),[],[],[],[],LB,UB,options);

matlabpool close

some other piece of code to show the results...

The MATLAB code of the fitness function, "PF_gaMultiFitness":

function objectives =PF_gaMultiFitness(individual, constants)
global simulation_duration IC stimulusMoment to_be_optimized_parameterIndexSet
%THIS FUNCTION RETURNS MULTI OBJECTIVES AND PUTS EACH OBJECTIVE IN A COLUMN

constants(to_be_optimized_parameterIndexSet) = individual;
[smcState , ~, Time]= oldCICR_CompCore(constants, IC, simulation_duration,2);
targetValue = 1; % [uM]desired [Ca]i peak concentration
afterStimulus = smcState(Time>stimulusMoment,14); % values of [Ca]i after stimulus
peak_Ca_value = max(afterStimulus); % smcState(:,14) is [Ca]i

if peak_Ca_value < 0.8 * targetValue
    objectives(1,1) = inf;

else
    objectives(1, 1) =  abs(peak_Ca_value - targetValue);
end

pkIDX = peakFinder(afterStimulus);
nPeaks = sum(pkIDX);
if nPeaks > 1
    peakIndexes = find(pkIDX);
    period = Time(peakIndexes(2)) - Time(peakIndexes(1));
    objectives(1,2)  = 1e5* 1/period;

elseif nPeaks ==   1 && peak_Ca_value > 0.8 * targetValue
    objectives(1,2) = 0;
else 
    objectives(1,2) = inf;

end


end
like image 683
Kamran Bigdely Avatar asked Jul 16 '11 04:07

Kamran Bigdely


2 Answers

Global variables do not get passed from the MATLAB client to the workers executing the body of the PARFOR loop. The only data that does get sent into the loop body are variables that occur in the text of the program. This blog entry might help.

like image 142
Edric Avatar answered Oct 21 '22 12:10

Edric


it really depends on the type of variable you're putting in. i need to see more of your code to point out the flaw, but in general it is good practice to avoid assuming complicated variables will be passed to each worker. In other words anything more then a primitive may need to be reinitialized inside a parallel routine or may need have specific function calls (like using feval for function handles).

My advice: RTM

like image 33
Rasman Avatar answered Oct 21 '22 11:10

Rasman