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
and fetchOutputs
?.
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 running listAutoAttachedFiles
, i.e.
job.listAutoAttachedFiles()
If this isn't showing your objectiveFunction
, then you can manually attach this by modifying the AttachedFiles
property of the job
.
It seems as though objectiveFunction
is a function_handle
though, so you might need to something like this:
f = functions(objectiveFunction)
job.AttachedFiles = {f.file}