В R2018b рассмотрим следующий класс игрушек:
classdef MyObj < handle
properties
use_parallel = true
test_value = NaN
end
methods
function myMethod(obj)
% Call one of the nested functions below:
if all([obj.use_parallel])
parallel();
disp('Parallel (inside myMethod):')
[obj.test_value]
else
sequential();
disp('Sequential (inside myMethod):')
[obj.test_value]
end
% Sequentially assign some values
function sequential()
for ii = 1:numel(obj)
obj(ii).test_value = ii; end
end
% Assign some values in parallel
function parallel()
parfor ii = 1:numel(obj)
set_value(obj(ii),labindex());
obj_copy(ii) = obj(ii);
end
obj = obj_copy;
end
end
end
end
% parfor requires subfunction (and not nested function):
function set_value(obj,index)
obj.test_value = index;
end
Хотя этот вопрос очень напоминает этот и этот вопрос , их основная проблема была по сути неким вариантомИз ограничений, изложенных в документации :
Вы можете отправлять объекты дескриптора в качестве входных данных в тело цикла parfor.Однако любые изменения, сделанные для обработки объектов на рабочих во время итераций цикла, автоматически не передаются обратно клиенту.То есть изменения, сделанные внутри цикла, не отражаются автоматически после цикла
Однако, насколько я вижу, класс игрушек, приведенный выше, соответствует правилам нарезки parfor
, а такжеподробности, касающиеся дескрипторов классов.Насколько я понимаю, он должен правильно скопировать измененное obj
обратно в myMethod's
рабочее пространство.
Однако, выполнив следующее:
clc
% Assign sequentially
M(3) = MyObj();
[M.use_parallel] = deal(false);
M.myMethod();
disp('Sequential (outside class):')
[M.test_value]
disp(' ')
% Assign in parallel
N(3) = MyObj();
[N.use_parallel] = deal(true);
N.myMethod();
disp('Parallel (outside class):')
[N.test_value]
дает на мои parpool
из 6 рабочих:
Sequential (inside myMethod):
ans =
1 2 3 % <- OK
Sequential (outside class):
ans =
1 2 3 % <- OK. Nothing unexpected
Parallel (inside myMethod):
ans =
1 1 1 % <- OK, apparently, lab 1 did everything
Parallel (outside class):
ans =
NaN NaN NaN % <- hmmm...changes did not propagate
Это означает, что obj.test_value
назначается правильно,и измененный obj
действительно правильно скопирован в myMethod's
рабочее пространство.Тем не менее, каким-то образом , этот модифицированный obj
отличается от obj
до модификации, потому что изменения не распространяются выше по стеку ...
Изменение parallel()
функция к подфункции (вместо вложенной функции) и явная передача параметра obj
, не влияет на этот результат.
Оооочень ... что здесь происходит?