Распространяются ли appdata между работниками в параллельном пуле? - PullRequest
0 голосов
/ 03 октября 2018

Я работаю над сложной функцией, которая вызывает несколько подфункций (в одном и том же файле).Для передачи данных иногда используется механизм setappdata / getappdata.Более того, некоторые подфункции содержат переменные persistent (инициализируются один раз для последующего сохранения вычислений).

Я думал о том, можно ли выполнить эту функцию на нескольких рабочих в параллельном пуле, но беспокоился, чтоможет быть некоторый непреднамеренный обмен данными (который в противном случае был бы уникальным для каждого работника).

У меня вопрос - как я могу определить, что данные в global и / или persistent и / или appdata разделены между работниками или уникальны для каждого?

Несколько, возможно, относящихся к делу вещей:

  1. В моем случае задач полностью параллельны, и их результаты не должны влиять друг на друга (распараллеливание выполняетсяпросто для экономии времени).
  2. Временные файлы и папки не создаются, поэтому нет риска, что один работник ошибочно прочитает файлы, оставленные другим.
  3. Все persistent и хранимые в appdata переменные создаются / присваиваются в пределах подфункции parfor.

Я знаю, что каждый рабочий соответствует новому процессу с собственным пространством памяти (и, предположительно, global / persistent / appdata рабочее пространство).Исходя из этого и этого официального комментария , я бы сказал, что, вероятно, такого обмена не произойдет ... Но как мы это выясним?

Материалы по теме:

  1. Это Q & A .
  2. Эта страница документации .

Ответы [ 2 ]

0 голосов
/ 03 октября 2018

Существует еще одно не разделяемое данные, которое меня раздражает.

Постоянные переменные даже не копируются из текущего рабочего пространства в рабочие.

Комупродемонстрировать, что создается простая функция с постоянной переменной (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далее "

Итак, создание работника = создание совершенно нового экземпляра MATLAB, совершенно не связанного с экземпляром MATLAB, который вы открыли перед собой.Для каждого работника отдельно.

Урок, который я извлек из этого = не использовать простые постоянные переменные в качестве файла конфигурации симуляции.Он работал нормально и выглядел элегантно, пока не использовался parfor ... но потом ужасно сломался.Используйте объекты.

0 голосов
/ 03 октября 2018

Это довольно просто проверить, и мы сделаем это в два этапа.

Шаг 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 для целей этого теста.

...