This has got me stumped.
I've written a function parObjectiveFunction
that runs several simulations in parallel using createJob
and createTask
. It takes as an argument an objectiveFunction
which is passed deeper into the code to calculate the objective function value for each simulation.
When I run parObjectiveFunction
from the directory where objectiveFunction
is found, it works as expected, but when I go one level up, it can no longer find objectiveFunction
. The specific error I get is
Error using parallel.Job/fetchOutputs (line 1255)
An error occurred during execution of Task with ID 1.
Error in parObjectiveFunction (line 35)
taskoutput = fetchOutputs(job);
Caused by:
Error using behaviourObjective/getPenalty (line 57)
Undefined function 'objectiveFunction' for input arguments of type 'double'.
(behaviourObjective is an object)
This is weird for several reasons.
objectiveFunction
is definitely in path
, and when I try which objectiveFunction
, it points to the correct function.
I have other components of the deeper code in other directories, and they are found without issue (they are objects rather than functions, but that shouldn't make a difference).
There's a line of code in parObjectiveFunction
that runs the simulation, and when I run that directly in the matlab command window it finds objectiveFunction
without issue.
I get the same results on my local machine and an HPC server.
My first thought was that the individual task might have its own path
which didn't include objectiveFunction
, but then that should cause problems for the other components (it doesn't). The problem is compounded because I can't work out how to debug the parallel code.
What am I doing wrong? Code that produced the issue is below.
Are there any known issues where matlab can't find functions when using parallel processing with
createJob
,createTask
,submit
andfetchOutputs
?.- How can you debug in matlab when the issue is only when operating in parallel? None of my print statements appear.
To make something work for external testing would take quite a bit of hacking, but for the sake of the question, the parallel function is:
function penalty = parObjectiveFunction(params, objectiveFunction, N)
% Takes a vector of input parameters, runs N instances of them in parallel
% then assesses the output through the objectiveFunction
n = params(1);
np = params(2);
ees = params(3);
ms = params(4);
cct = params(5);
wt = params(6);
vf = params(7);
dt = 0.001;
bt = 10;
t = 10;
c = parcluster;
job = createJob(c);
testFunction = @(run_number)behaviourObjective(objectiveFunction,n,np,ees,ms,cct,wt,vf,t,dt,bt,run_number);
for i = 1:N
createTask(job, testFunction, 1, {i});
end
submit(job);
wait(job);
taskoutput = fetchOutputs(job);
pensum = 0;
for i = 1:N
pensum = pensum + taskoutput{i}.penalty;
end
penalty = pensum/N;
end
It sounds like you need to attach some additional files to your
job
. You can see which files were picked up by MATLAB's dependency analysis by runninglistAutoAttachedFiles
, i.e.If this isn't showing your
objectiveFunction
, then you can manually attach this by modifying theAttachedFiles
property of thejob
.It seems as though
objectiveFunction
is afunction_handle
though, so you might need to something like this: