代码之家  ›  专栏  ›  技术社区  ›  Dev-iL

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

  •  3
  • Dev-iL  · 技术社区  · 6 年前

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

    我一直在考虑是否可以在一个并行池中的几个工作人员上执行这个函数,但是我开始担心可能会有一些意外的数据共享(否则每个工作人员都将是唯一的)。

    我的问题是 -我怎么知道数据是否在 global 和/或 持久的 和/或 appdata 是工人之间共享的还是每个人都独有的?

    一些可能相关的事情:

    1. 在我看来, 任务 是完全平行的,它们的结果不应该以任何方式相互影响(平行化只是为了节省时间)。
    2. 没有创建任何临时文件或文件夹,因此不会有一个工作人员错误读取另一个工作人员留下的文件的风险。
    3. 所有 持久的 创建/分配AppData存储变量 在内部 的子功能 parfor .

    我知道每个工作人员都对应于一个具有自己内存空间的新进程(而且大概, 全球的 / 持久的 / 附加数据 工作区)。在此基础上 this official comment 我想说,这种分享很可能不会发生…但我们如何确定呢?

    相关材料:

    1. This Q&A .
    2. This documentation page .
    2 回复  |  直到 6 年前
        1
  •  3
  •   Dev-iL    6 年前

    这是非常简单的测试,我们将分两个阶段进行测试。

    步骤1:“工人”的人工繁殖

    首先,创建这三个函数:

    %% 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 实例将打印一些内容。结果(在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 在本试验中。

        2
  •  3
  •   Zizy Archer    6 年前

    还有另一个不共享数据的问题困扰着我。

    持久变量甚至不会从当前工作区复制到工作区。

    为了演示,创建了一个带有持久变量的简单函数(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实例。分别为每个工人。

    我从中获得的经验=不要使用简单的持久变量作为模拟配置文件。它工作得很好,看起来很优雅,只要不使用帕尔佛尔……但后来破得很惨。使用对象。