Pass parameters to arbitrarily deep functions in a parfor loop (write once, read multiple)

4 visualizzazioni (ultimi 30 giorni)
I'm trying to run some MATLAB code that is structured as a collection of functions that call other functions, with varying depths of call stack (some of these functions are defined in a single .m file, many are in separate .m files - as far as I gather, MATLAB uses the term "nested" only to describe functions declared within the body of another function, of which these are not).
Some of the low-lying functions require various parameters, that were until recently hardcoded to specific values. I'd now like to be able to change them.
Although ugly, this works (for non-parfor execution) using global variables and the following function:
function [value] = getValueOrDefault(varName, defaultVal)
arguments
varName string;
defaultVal;
end
eval(strjoin(["global", varName]));
if exist(varName, 'var') && ~isempty(eval(varName))
value = eval(varName);
else
value = defaultVal;
end
end
and can be used by declaring at the entrypoint a list of global variables
global myVarName; myVarName = true;
then setting them (then updating calling code to use
myVar = getValueOrDefault('myVarName', false);
or similar.
However, whilst I can run this if the bulk of the code runs inside a parfor loop, the variables are always empty (that is, as I understand, they are created by the getValueOrDefault call, and the original calls are not passed through to the parfor workers). The defaults are always used, which doesn't solve my problem.
Attempting to use something like
global myVarOuter; myVarOuter = true;
% Or indeed, since this isn't used globally, just
% myVarOuter = true;
parfor n=1:5
global myVar; myVar = myVarOuter;
doStuffThatCallsStuffThatEventuallyWantsMyVar();
end
hits errors in the declaration of global variables within parfor workers.
I don't need the variables to be linked between workers, and I don't need to be able to change them in the workers. I don't care to recover them after the loop finishes.
I tried looking at parallel.pool.constant values, but it wasn't clear to me how I might reference such a constant from an arbitrarily far-away function (that is, I don't think I can make it global in any fashion, and I'm not sure if I can make it persistent - but then I'd need to be able to make the function or class wrapping the persistent variable/struct of options global).
evalin also seems unsupported, at least in thread-based pools (would this be a workaround for processes?)
Passing the variables through the many layers of functions is of course possible, but I'd prefer to avoid it (particularly if I imagine something like the code below)
function myFunctionWithTwoTypesOfExecution(typeVar)
switch type
case "version1"
varForVersion1 = getValueOrDefault('paramForOne', 12345);
doStuffType1(varForVersion1);
case "version2"
varForVersion2a = getValueOrDefault('paramForTwo_first', 123);
varForVersion2b = getValueOrDefault('paramForTwo_second', false);
doStuffType2(varForVersion2a, varForVersion2b);
end
end
Is there a construct/mechanism that will help me with this problem? (Something like React's 'Context' comes to mind - in that case, the goal is to avoid a 'problem' they name "prop drilling", basically identical to modifying all of my functions to pass either an options struct with options for every possible function they might call, or passing a very long list of arguments to each function, which would in my opinion be really awful).
Can 2025a's workspace passing mechanisms solve this issue? (I can't get access to 2025a for our cluster, but it would at least give a route forwards when 2025b releases).
  2 Commenti
Christian Butcher
Christian Butcher il 17 Lug 2025
In relation to the goal, I'm aiming to call a script in a manner like the following:
matlab -batch "global myVar; myVar = 1234; myScript"
% or
matlab -batch "myScript(1234, true, false)" % in which those values are passed into the global context
The number of values at present are relatively few (4 or 5), but the number of executions becomes fairly large as their multiplied together to cover a parameter space (e.g. maybe 30 total calls, with not all combinations being relevant/independent).

Accedi per commentare.

Risposte (1)

Matt J
Matt J il 17 Lug 2025
Modificato: Matt J il 17 Lug 2025
I recommend that you go through the effort of revising all your function signatures to accept an additional argument for the parameters. You don't have to add an argument for each variable. I would just pass around a single struct variable containing everything.
The effort of rewriting all the function signatures can be facilitated with a multi-file search and replace tool such as,
which supports regular expressions.
Unpacking the variables from the struct into the function workspaces can be facilitated with this,
The unrecommended, but economical way to use it is, e.g.,
clear
params.a=1;
params.b=2;
params.c=3;
eval(structvars(params)'); clear params
whos
Name Size Bytes Class Attributes a 1x1 8 double b 1x1 8 double c 1x1 8 double

Categorie

Scopri di più su Parallel for-Loops (parfor) in Help Center e File Exchange

Prodotti


Release

R2024b

Community Treasure Hunt

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

Start Hunting!

Translated by