我正在处理一个复杂的函数,该函数调用多个子函数(在同一文件中)。为了传递数据,偶尔使用setappdata
/ getappdata
机制。此外,某些子函数包含persistent
变量(初始化一次以便以后保存计算)。
我一直在考虑是否可以在并行池中的多个工作程序上执行此功能,但是我担心可能会有一些意外的数据共享(否则每个工作程序都是唯一的)。
我的问题是-如何确定global
和/或persistent
和/或appdata
中的数据是否在工作人员之间共享或唯一每个人?
可能与之相关的几件事:
persistent
和应用数据存储的变量都是在parfor
的子功能中内创建/分配的。我知道每个工作程序都对应一个具有自己的内存空间(可能是global
/ persistent
/ appdata
工作空间的新进程)。基于此,并基于this official comment,我想很可能不会发生这种共享...但是我们如何确定呢?
答案 0 :(得分:3)
这很容易测试,我们将分两个阶段进行。
首先,创建以下3个功能:
%% Worker 1:
function q52623266_W1
global a; a = 5;
setappdata(0, 'a', a);
someFuncInSameFolder();
end
%% Worker 2:
function q52623266_W2
global a; disp(a);
disp(getappdata(0,'a'));
someFuncInSameFolder();
end
function someFuncInSameFolder()
persistent b;
if isempty(b)
b = 10;
disp('b is now set!');
else
disp(b);
end
end
接下来,我们启动2个MATLAB实例(代表并行池的两个不同的工作程序),然后在其中一个上运行q52623266_W1
,等待其完成,然后在另一个上运行q52623266_W2
。如果共享数据 ,则2 nd 实例将打印一些内容。结果(在R2018b上)为:
>> q52623266_W1
b is now set!
>> q52623266_W2
b is now set!
这意味着不共享数据。到目前为止,一切都很好,但是您可能想知道这是否代表一个实际的并行池。因此,我们可以稍微调整一下功能,然后继续下一步。
function q52623266_Host
spmd(2)
if labindex == 1
setupData();
end
labBarrier; % make sure that the setup stage was executed.
if labindex == 2
readData();
end
end
end
function setupData
global a; a = 5;
setappdata(0, 'a', a);
someFunc();
end
function readData
global a; disp(a);
disp(getappdata(0,'a'));
someFunc();
end
function someFunc()
persistent b;
if isempty(b)
b = 10;
disp('b is now set!');
else
disp(b);
end
end
运行以上操作,我们得到:
>> q52623266_Host
Starting parallel pool (parpool) using the 'local' profile ...
connected to 2 workers.
Lab 1:
b is now set!
Lab 2:
b is now set!
再次表示数据未共享。请注意,在第二步中,我们使用了spmd
,在此测试中,该功能应与parfor
类似。
答案 1 :(得分:3)
还有另一种不共享数据的问题困扰着我。
持久性变量甚至不会从当前工作空间复制到工作程序。
为演示,创建了一个带有持久变量的简单函数(MATLAB 2017a):
function [ output_args ] = testPersist( input_args )
%TESTPERSIST Simple persistent variable test.
persistent var
if (isempty(var))
var = 0;
end
if (nargin == 1)
var = input_args;
end
output_args = var;
end
然后执行一个简短的脚本:
testPersist(123); % Set persistent variable to 123.
tpData = zeros(100,1);
parfor i = 1 : 100
tpData(i) = testPersist;
testPersist(i);
end
any(tpData == 0) % This implies the worker started from 0 instead of 123 as specified in the first row.
输出为1
-工作人员无视父工作区中的123,而是重新开始。
检查tpData
中的值还通过指出“ tpData(14)= 15-这意味着完成15个工作的工人继续执行下一个14个工作”来显示每个工人的工作方式。
因此,创建一个worker =创建与您前面打开的MATLAB实例完全无关的全新MATLAB实例。分别针对每个工人。
我从中获得的经验=不要将简单的持久变量用作模拟配置文件。只要不使用parfor,它就可以正常工作并看起来很优雅……但后来却令人震惊。使用对象。