Handle object array doesn't update when parfor is used within a class method

1 view (last 30 days)
I have a class that is similar to this:
classdef Example < matlab.mixin.Copyable
properties
data = [];
end
methods
function obj = Example()
end
function process(obj)
parfor ii = 1:numel(obj)
objSlice = obj(ii);
objSlice.process_sub()
obj(ii) = objSlice;
end
end
function process_sub(obj)
obj.data = datestr(now, 'HH:MM:SS.FFF');
end
end
end
As you can probably see, I would like to process the elements of an array of this class in parallel. This works as expected when the parallel pool is closed, e.g.:
% Initialise array of objects
num = 5;
for nn = 1:num
exArray(nn) = Example();
end
% Process the object array in parallel
exArray.process();
exArray.data
ans =
11:36:56.387
ans =
11:36:56.387
% ... snip
However, when the parallel pool is open, the data is not updated correctly; e.g. (after processing):
exArray.data
ans =
[]
ans =
[]
% ... snip
Is this behaviour expected or a bug? And either way, how can I get the object array to process in parallel?
I have seen other similar questions (e.g. here , here), and the documentation ( here ), but I think my issue is different because the parfor loop is actually inside the handle object, and I haven't been able to find any ideas about this.
Thanks very much in advance for your help.

Accepted Answer

Rahul Goel
Rahul Goel on 7 Aug 2015
Hi,
As per the documentation, the workers do not propagate the changes back to the client. In the code you mentioned, you took care of this by:
obj(ii) = objSlice;
However, this change has to be propagated back to the client explicitly. This can be done by returning the changed objects from the function to the caller as:
function obj = process(obj)
and capturing this returned value in the caller function as:
exArray = exArray.process();
So, the code you provided works as expected with these modifications:
classdef Example < matlab.mixin.Copyable
properties
data = [];
end
methods
function obj = Example()
end
function obj = process(obj)
parfor ii = 1:numel(obj)
objSlice = obj(ii);
objSlice.process_sub()
obj(ii) = objSlice;
end
end
function process_sub(obj)
obj.data = datestr(now, 'HH:MM:SS.FFF');
end
end
end
When following objects are created and call the process function:
% Initialise array of objects
num = 5;
for nn = 1:num
exArray(nn) = Example();
end
% Process the object array in parallel
exArray = exArray.process();
exArray.data
It gives the following output:
>> exArray.data
ans =
11:04:54.894
ans =
11:04:54.894
ans =
11:04:54.894
ans =
11:04:54.898
ans =
11:04:54.899
Note: Before executing the enhanced version of this class, clear the class from the memory by:
>> clear classes
Hope this helps.
  1 Comment
mbar170
mbar170 on 7 Aug 2015
Thanks for your answer Rahul.
I can see that this approach works, but I think the fact that it is necessary is inconsistent with the expected behaviour of a handle object.
Even if something like the following worked it would be closer to what I expect:
classdef Example < matlab.mixin.Copyable
properties
data = [];
end
methods
function obj = Example()
end
function process(obj)
obj = obj.process_parfor();
end
function obj = process_parfor(obj)
parfor ii = 1:numel(obj)
objSlice = obj(ii);
objSlice.process_sub()
obj(ii) = objSlice;
end
end
function process_sub(obj)
obj.data = datestr(now, 'HH:MM:SS.FFF');
end
end
end
However, in the absence of another workaround, I guess I'll have to change my syntax to explicitly capture the modified object.
Thanks again, Matt

Sign in to comment.

More Answers (0)

Categories

Find more on Loops and Conditional Statements in Help Center and File Exchange

Community Treasure Hunt

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

Start Hunting!