appdata是否在并行池中的工作人员之间共享?

时间:2018-10-03 08:56:08

标签: matlab parallel-processing global-variables persistent-storage app-data

我正在处理一个复杂的函数,该函数调用多个子函数(在同一文件中)。为了传递数据,偶尔使用setappdata / getappdata机制。此外,某些子函数包含persistent变量(初始化一次以便以后保存计算)。

我一直在考虑是否可以在并行池中的多个工作程序上执行此功能,但是我担心可能会有一些意外的数据共享(否则每个工作程序都是唯一的)。

我的问题是-如何确定global和/或persistent和/或appdata中的数据是否在工作人员之间共享或唯一每个人?

可能与之相关的几件事:

  1. 就我而言,任务是完全并行的,它们的结果不应以任何方式相互影响(并行化只是为了节省时间)。
  2. 没有创建任何临时文件或文件夹,因此不会有一个工人错误地读取另一个工人留下的文件的风险。
  3. 所有persistent和应用数据存储的变量都是在parfor的子功能中内创建/分配的。

我知道每个工作程序都对应一个具有自己的内存空间(可能是global / persistent / appdata工作空间的新进程)。基于此,并基于this official comment,我想很可能不会发生这种共享...但是我们如何确定呢?

相关材料:

  1. This Q&A
  2. This documentation page

2 个答案:

答案 0 :(得分:3)

这很容易测试,我们将分两个阶段进行。

第1步:手动产生“工人”

首先,创建以下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!

这意味着不共享数据。到目前为止,一切都很好,但是您可能想知道这是否代表一个实际的并行池。因此,我们可以稍微调整一下功能,然后继续下一步。

第2步:自动派生工人

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,它就可以正常工作并看起来很优雅……但后来却令人震惊。使用对象。