matlab - parfor 不会将更改传播到句柄类
问题描述
在 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
参数,不会影响此结果。
呜呜……这是怎么回事?
解决方案
我可以将问题简化为:
classdef MyObj < matlab.mixin.Copyable
properties
test_value = NaN
end
methods
function myMethod(obj)
obj = obj.copy();
obj.test_value = rand;
disp('Inside method:')
obj.test_value
end
end
end
parfor
从方程中删除嵌套函数、子函数和。运行上面的代码(经过明显更改后)会导致:
Inside method:
ans =
4.8089e-01 % <- obj re-initialized OK
Outside class:
ans =
NaN % <- but this does NOT modify the handle class!
这意味着这是我不知道的语言“功能”!显然,方法可以修改现有对象,但不能完全重新定义它们。我将尝试在文档中挖掘更多信息,但这带来了一个全新的问题:如何将所做的更改复制parfor
回对象中?
TL;博士:
function myMethod(obj)
% ↓ new object ↓ old object
obj = obj.copy();
克里斯是对的。尽管新旧物体名称相同,但它们是不同的事物——它们相互影射。对新版本所做的任何更改obj
都不会修改旧版本obj
。
推荐阅读
- javascript - 从 API 获取数据时防止空数组(useEffect 初始状态),这是一种好的架构方法吗?
- botframework - [Teams][botbuilder] 配置选项卡在标题中显示 description.full 和 websiteUrl
- angular - 两次订阅 Angular 11 http?
- amazon-web-services - 使用 S3 作为原始数据的数据管道将如何工作?
- python - Python:从字符串中提取特定单词
- angularjs - 有条件的 ng 风格
- javascript - 如何比较两个异步 JavaScript 函数的结果?
- python - 使用年份规范将列“日”转换为日期时间
- excel - 在公式中添加 [空格]
- python - 使用 Python 连接一个空数组