![](/img/trans.png)
[英]Why does TreeBagger in Matlab 2014a/b only use few workers from a parallel pool?
[英]Is appdata shared between workers in a parallel pool?
我正在研究一個復雜的函數,它調用多個子函數(在同一個文件中)。 為了傳遞數據,偶爾會使用setappdata
/ getappdata
機制。 此外,一些子函數包含persistent
變量(初始化一次以便稍后保存計算)。
我一直在考慮是否可以在並行池中的幾個worker上執行此函數,但是擔心可能會有一些意外的數據共享(否則每個worker都是唯一的)。
我的問題是 - 如何判斷global
和/或persistent
和/或appdata
是在工作者之間共享還是每個人都是唯一的?
幾個可能相關的事情:
persistent
和appdata存儲的變量都在parfor
子函數內創建/分配。 我知道每個工作者都對應一個具有自己的內存空間的新進程(可能是global
/ persistent
/ appdata
工作空間)。 基於此以及在此官方評論中 ,我會說這種共享很可能不會發生......但我們如何確定呢?
這非常簡單,我們將分兩個階段進行測試。
首先,創建這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
上運行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
本次測試的目的。
還有另一種不共享的數據讓我感到困惑。
永久變量甚至不會從當前工作空間復制到工作者。
為了演示,創建了一個帶有持久變量的簡單函數(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,它工作得很好,看起來很優雅......但之后又破壞了。 使用對象。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.