Отправка данных работникам
Я пытаюсь создать кусок параллельного кода, чтобы ускорить обработку очень большого (пара сотен миллионов строк) массивов. Чтобы распараллелить это, я разбил свои данные на 8 (количество ядер) частей и попытался отправить каждому работнику по 1 части. Однако, глядя на использование моей оперативной памяти, кажется, что каждая часть отправляется каждому работнику, эффективно умножая использование моей оперативной памяти на 8. Минимальный рабочий пример:
A = 1:16;
for ii = 1:8
data{ii} = A(2*ii-1:2*ii);
end
Теперь, когда я отправляю эти данные работникам, использующим parfor
кажется, что отправляется полная ячейка, а не только нужный кусок:
output = cell(1,8);
parfor ii = 1:8
output{ii} = data{ii};
end
Я на самом деле использую какую-то функцию в parfor
цикл, но это иллюстрирует случай. Действительно ли MATLAB отправляет полную ячейку data
каждому работнику, и если да, то как заставить его отправлять только нужный кусок?
3 ответа
По своему личному опыту я обнаружил, что используя parfeval
лучше в отношении использования памяти, чем parfor
, Кроме того, ваша проблема кажется более решаемой, поэтому вы можете использовать parfeval
за предоставление более мелких рабочих мест работникам MATLAB.
Допустим, у вас есть workerCnt
Работники MATLAB, с которыми ты будешь обращаться jobCnt
рабочие места. Позволять data
быть размером с ячейку jobCnt x 1
и каждый из его элементов соответствует вводу данных для функции getOutput
который делает анализ данных. Результаты затем сохраняются в массиве ячеек output
размера jobCnt x 1
,
в следующем коде задания назначаются в первом for
цикл и результаты извлекаются во втором while
петля. Булева переменная doneJobs
указывает, какая работа выполнена.
poolObj = parpool(workerCnt);
jobCnt = length(data); % number of jobs
output = cell(jobCnt,1);
for jobNo = 1:jobCnt
future(jobNo) = parfeval(poolObj,@getOutput,...
nargout('getOutput'),data{jobNo});
end
doneJobs = false(jobCnt,1);
while ~all(doneJobs)
[idx,result] = fetchnext(future);
output{idx} = result;
doneJobs(idx) = true;
end
Кроме того, вы можете сделать этот подход еще на шаг дальше, если хотите сэкономить больше памяти. Что вы можете сделать, так это то, что после извлечения результатов выполненной работы вы можете удалить соответствующий элемент future
, Причина в том, что этот объект хранит все входные и выходные данные getOutput
функция, которая, вероятно, будет огромной. Но нужно быть осторожным, так как удаляя членов future
сдвиг индекса результатов.
Ниже приведен код, который я написал для этого porpuse.
poolObj = parpool(workerCnt);
jobCnt = length(data); % number of jobs
output = cell(jobCnt,1);
for jobNo = 1:jobCnt
future(jobNo) = parfeval(poolObj,@getOutput,...
nargout('getOutput'),data{jobNo});
end
doneJobs = false(jobCnt,1);
while ~all(doneJobs)
[idx,result] = fetchnext(future);
furure(idx) = []; % remove the done future object
oldIdx = 0;
% find the index offset and correct index accordingly
while oldIdx ~= idx
doneJobsInIdxRange = sum(doneJobs((oldIdx + 1):idx));
oldIdx = idx
idx = idx + doneJobsInIdxRange;
end
output{idx} = result;
doneJobs(idx) = true;
end
Комментарий от @ms правильный - когда parfor
разрезает массив, затем каждому рабочему отправляется только тот фрагмент, который необходим для итераций цикла, над которыми он работает. Тем не менее, вы можете увидеть увеличение использования ОЗУ сверх того, что вы изначально ожидали, поскольку, к сожалению, требуются копии данных, так как они передаются от клиента к работникам через parfor
механизм связи.
Если вам нужны данные только о работниках, то лучшим решением будет создание / загрузка / доступ к ним только по работникам, если это возможно. Похоже, вы после параллелизма данных, а не параллелизма задач, для которых spmd
действительно лучше подходит (как предполагает @Kostas).
Я бы предложил использовать spmd
команда MATLAB.
Вы можете написать код почти так же, как это было бы для непараллельной реализации, а также иметь доступ к текущему работнику с помощью labindex
системная переменная.
Посмотрите здесь:
http://www.mathworks.com/help/distcomp/spmd.html
А также на этот так вопрос о spmd
против parfor
: