parfor treats variable as function

2 views (last 30 days)
Arek
Arek on 10 Feb 2022
Commented: Stephen23 on 10 Feb 2022
I am using my own genetic algorithm and I want to compute all genotypes in generation in parallel. The problem is that Matlab treats my variable dronesPaths as a function and then can't find the file it's code is stored in (there is no file because it is not a function).
My command window:
-----------------------------------------------------------------------------------------------------------------------------
Analyzing and transferring files to the workers ...done.
Error using sim_fitness (line 7)
The source code (E:\Matlab_test_sim\voronoi_v1\GA_mat_files\sim_fitness.m) for the parfor-loop that is
trying to execute on the worker could not be found.
Error in GA_main_potential_field (line 29)
[fitness] = sim_fitness(new_population);
Caused by:
Undefined function 'dronePaths' for input arguments of type 'double'.
Error using remoteParallelFunction (line 84)
Worker unable to find file.
Undefined function 'dronePaths' for input arguments of type 'double'.
-----------------------------------------------------------------------------------------------------------------------------
The dronePaths is earlier (before parfor starts) loaded from hard drive with other variables.
The dronePaths is a cell array containing some intigers ( something like {[ 12 54 2 5 ]} )
How to solve it?
-----------------------------------------------------------------------------------------------------------------------------
My code:
function [ fitness] = sim_fitness( population)
load('variables\map44.mat')
[x,y] = size(population);
parfor genome_id=1:x
fprintf('\n object: %i \n\n', genome_id)
dt = datetime
fprintf('%s \n',dt)
% run this generation simulation
dronesCount = 25; % take value from test4, but can be reduced
timeStep = 0.01; % [s]
colision_distance = 0.5; % [m] ,repulsive_potential_radius_shift
IRR = 20; % IRR -> initRandRadious - used for initialising random star positions
allDrones = {};
for i = 1 : dronesCount
drone = {i}; % drone index
drone(2) = dronePaths(i); % path assigned to that drone
drone{3} = drone{2}(1); % current goal-node of the drone
drone{4} = [ 0 0 ]; % history of drone positions [x1, y1; x2, y2; ...]
drone{5} = [ 0 0 ]; % history of drone velocities [x1, y1; x2, y2; ...]
drone{6} = [ 0 0 ]; % history of drone accelerations [x1, y1; x2, y2; ...]
drone{7} = false; % indicates that this drone finished its run, either reaching the final destination or crashing
drone{8} = false; % indicates if the drone crashed
drone{9} = [ 0 0 ]; % obstacles rep. potential
drone{10} = [ 0 0 ]; % drones rep. potential
drone{11} = [ 0 0 ]; % attractive pot
drone{12} = [ 0 0 ]; % resultant pot.
drone{13} = [ -1 ]; % indicates a moment in time when drone finished its run
allDrones{i} = drone;
% updating drone{4:6} -> drone{4}(end+1, :) = [posX posY]
end
....
some more code
....
end
  1 Comment
Stephen23
Stephen23 on 10 Feb 2022
Another example of why making variables magically appear in a workspace is a bad way to write code.
The moral of the story: always LOAD into an output variable!

Sign in to comment.

Answers (2)

Edric Ellis
Edric Ellis on 10 Feb 2022
This is a limitation of parfor. The documentation here describes the principle reason, but doesn't quite show an example exactly like you have it. Basically, parfor works by performing a static analysis on the code of your loop, and it has to be able to tell from the text of the program whether names that you use refer to functions or variables. In cases where the static analysis cannot prove the name refers to a variable, it assumes the name will refer to a function.
When you use load, you introduce names into the workspace that parfor's static analysis cannot see. The workaround is to use the output-argument form of load, like this:
myExample();
function myExample
% Here's the working version
data = load('durer.mat','X'); % data is now a struct with a field X
nRows = size(data.X, 1);
parfor idx = 1:nRows
out(idx) = sum(data.X(idx,:));
end
% Here's the non-working version
load('durer.mat');
parfor idx = 1:nRows
out(idx) = sum(X(idx,:));
Invalid syntax for calling function 'X' on the path. Use a valid syntax or explicitly initialize 'X' to make it a variable.
end
end
One more thing to note - in the example above, I had to put the code inside a function workspace - the rules for parfor in scripts or at the prompt are actually slightly different - in that case, the analysis is done dynamically with knowledge of the workspace contents. For functions, the contents of the workspace aren't used.

Paul
Paul on 10 Feb 2022
Edited: Paul on 10 Feb 2022
Is dronePaths loaded from map44.mat? If so, that could be the cause of the problem. See this link for discussion of similar issue and some mitigation options.

Products


Release

R2021a

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!