iddata object is casted to struct in parfeval

8 views (last 30 days)
Hi all,
I'm trying to train my nlarx models in a background pool to abort the training after a timeout. But input data of type iddata is always casted to its struct representations, see this example:
load dryer2_data output input; % matlab example data
data = iddata(output,input,0.08); % create the iddata object
str = feval(@testFun, data, "feval"); % simulate a "normal" call
disp(str)
fut1 = parfeval(@testFun, 1, data, "parfeval"); % should be same as above
timeoutSec = 100;
[~, str] = fetchNext(fut1, timeoutSec);
disp(str)
fut2 = parfeval(backgroundPool, @testFun, 1, data, "parfevalBackgroundPool"); % should be same as above, but in backgroundPool
timeoutSec = 100;
[~, str] = fetchNext(fut2, timeoutSec);
disp(str)
function str = testFun(data, from)
str = sprintf("Hello from '%s'\n'data' is class '%s'\n", from, class(data));
try
nlarx(data,[1 1 1],idLinear);
str = sprintf("%sNo error in testFun.\n", str);
catch E
str = sprintf("%sError in testFun: %s\n", str, E.message);
end
end
which generates this output:
Hello from 'feval'
'data' is class 'iddata'
No error in testFun.
Hello from 'parfeval'
'data' is class 'struct'
Error in testFun: Unable to validate the data input for the "nlarx" command. It should be specified using an IDDATA object.
Hello from 'parfevalBackgroundPool'
'data' is class 'struct'
Error in testFun: Unable to validate the data input for the "nlarx" command. It should be specified using an IDDATA object.
As you can see, the iddata is casted to struct and therefore can't be used in nlarx. Creating the new iddata object in testFun doesn't work either, because iddata() seems to use assignin which does not work in a parallel worker.
What can I do to implement the timeout?
Thank you!
Some side notes:
  • I know feval is not recommended but it shows the issue here pretty well due to the similar syntax
  • I do not have parallel computing toolbox
  • You'll need System Identification Toolbox
  • I'm using ML 2022a
BTW, are there any options to print/display text from the worker, i.e. from testFun?

Answers (1)

Karan Singh
Karan Singh on 30 Jan 2024
Hi Jan,
The issue you're encountering with parfeval is due to the fact that when you pass complex objects like iddata to parallel workers, MATLAB serializes these objects into a struct representation for transmission to the workers. When the workers receive the data, they do not automatically deserialize it back into the original object type. This is why class(data) returns 'struct' instead of 'iddata' within the parallel workers.
To work around this issue, you can modify your testFun function to check if the input data is a struct and, if so, convert it back into an iddata object. Here's how you can modify your testFun function:
function str = testFun(data, from)
str = sprintf("Hello from '%s'\n'data' is class '%s'\n", from, class(data));
try
% Check if 'data' is a struct and convert it to 'iddata' if necessary
if isa(data, 'struct')
data = iddata(data.OutputData, data.InputData, data.Ts, 'Name', data.Name);
end
nlarx(data, [1 1 1], idLinear);
str = sprintf("%sNo error in testFun.\n", str);
catch E
str = sprintf("%sError in testFun: %s\n", str, E.message);
end
end
Since you don't have the Parallel Computing Toolbox, you won't be able to use parfeval or backgroundPool. However, you mentioned using parfeval in your example, so I assume you have access to some parallel functionality.
To print or display text from a worker, you can use disp or other printing functions. However, the output will not be displayed in the MATLAB Command Window but in the log files associated with the parallel workers. You can also use diary to capture the output to a file.
Hope this helps!

Categories

Find more on Asynchronous Parallel Programming in Help Center and File Exchange

Products


Release

R2022a

Community Treasure Hunt

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

Start Hunting!