У меня есть функция (свертка), которая может стать очень медленной, если она работает с матрицами многих столбцов (код функции ниже). Поэтому я хочу распараллелить код.Почему работа MATLAB длится долго?
Пример MATLAB код:
x = zeros(1,100);
x(rand(1,100)>0.8) = 1;
x = x(:);
c = convContinuous(1:100,x,@(t,p)p(1)*exp(-(t-p(2)).*(t-p(2))./(2*p(3).*p(3))),[1,0,3],false)
plot(1:100,x,1:100,c)
если x
матрица из многих рубрик, код становится очень медленно ... Моя первая попытка была изменить for
на parfor
заявление, но это пошло не так (см Заключительные замечания ниже).
Моя вторая попытка состояла в следующем: this example, в котором показано, как планировать задания в задании, а затем отправлять задание на локальный сервер. Этот пример реализован в моей функции ниже, разрешив последнему аргументу isParallel
true
.
В примере MATLAB код будет:
x = zeros(1,100);
x(rand(1,100)>0.8) = 1;
x = x(:);
c = convContinuous(1:100,x,@(t,p)p(1)*exp(-(t-p(2)).*(t-p(2))./(2*p(3).*p(3))),[1,0,3],true)
Теперь, MATLAB говорит мне:
Starting parallel pool (parpool) using the 'local' profile ... connected to 4 workers.
Warning: This job will remain queued until the Parallel Pool is closed.
И MATLAB терминал продолжает трюме, ожидая чего-то, чтобы закончить. Затем я открываю Jobs Monitor
Home -> Parallel -> Monitor jobs
и вижу, что есть два задания, одно из которых имеет состояние running
. Но никто из них никогда не закончит.
Вопросы
Почему слишком долго работать, учитывая, что это действительно простая задача?
Что было бы лучшим способом распараллеливать мою функцию ниже? ("Тяжелая" часть находится в отделенной функции
convolveSeries
)
convContinuous.m Файл
function res = convContinuous(tData, sData, smoothFun, par, isParallel)
% performs the convolution of a series of delta with a smooth function of parameters par
% tData = temporal space
% sData = matrix of delta series (each column is a different series that will be convolved with smoothFunc)
% smoothFun = function used to convolve with each column of sData
% must be of the form smoothFun(t, par)
% par = parameters to smoothing function
if nargin < 5 || isempty(isParallel)
isParallel = false;
end
if isvector(sData)
[mm,nn] = size(sData);
sData = sData(:);
end
res = zeros(size(sData));
[ ~, n ] = size(sData);
if ~isParallel
%parfor i = 1:n % uncomment this and comment line below for strange error
for i = 1:n
res(:,i) = convolveSeries(tData, sData(:,i), smoothFun, par);
end
else
myPool = gcp; % creates parallel pool if needed
sched = parcluster; % creates scheduler
job = createJob(sched);
task = cell(1,n);
for i = 1:n
task{i} = createTask(job, @convolveSeries, 1, {tData, sData(:,i), smoothFun, par});
end
submit(job);
wait(job);
jobRes = fetchOutputs(job);
for i = 1:n
res(:,i) = jobRes{i,1}(:);
end
delete(job);
end
if isvector(sData)
res = reshape(res, mm, nn);
end
end
function r = convolveSeries(tData, s, smoothFun, par)
r = zeros(size(s));
tSpk = s == 1;
j = 1;
for t = tData
for tt = tData(tSpk)
if (tt > t)
break;
end
r(j) = r(j) + smoothFun(t - tt, par);
end
j = j + 1;
end
end
Заключительные замечания
Как примечание стороны, я не был в состоянии чтобы сделать это, используя parfor
, потому что MATLAB R2015a
дал мне странную ошибку:
Error using matlabpool (line 27) matlabpool has been removed.
To query the size of an already started parallel pool, query the 'NumWorkers' property of the pool.
To check if a pool is already started use 'isempty(gcp('nocreate'))'.
Error in parallel_function (line 317) Nworkers = matlabpool('size');
Error in convContinuous (line 18) parfor i = 1:n
Мои version
команда выводит
Parallel Computing Toolbox Version 6.6 (R2015a)
, который совместим с моей версией MATLAB. Почти all other tests У меня все в порядке. Затем я вынужден думать, что это ошибка MATLAB.
Я попытался изменить matlabpool
к gcp
, а затем извлечения числа рабочих по parPoolObj.NumWorkers
, и после изменения этой детали в двух различных встроенных функций, я получил еще одну ошибку:
Error in convContinuous>makeF%1/F% (line 1)
function res = convContinuous(tData, sData, smoothFun, par)
Output argument "res" (and maybe others) not assigned during call to "convContinuous>makeF%1/F%".
Error in parallel_function>iParFun (line 383) output.data = processInfo.fun(input.base, input.limit, input.data);
Error in parProcess (line 167) data = processFunc(processInfo, data);
Error in parallel_function (line 358) stateInfo = parProcess(@iParFun, @iConsume, @iSupply, ...
Error in convContinuous (line 14) parfor i = 1:numel(sData(1,:))
Я подозреваю, что это последнее ошибка возникает, потому что вызов функции внутри цикла parfor
требует много аргументов, но я этого не знаю.
Решения ошибки
Благодаря осторожным комментариям людей здесь (говорят, что они не смогли воспроизвести мои ошибки), я продолжал искать источник ошибки. Я понял, что это была локальная ошибка из-за наличия pforfun
в моем pathdef.m
, который I downloaded long ago from File Exchange.
Как только я удалил pforfun
из моего pathdef.m
, parfor
(строка 18 в convContinuous
функция) начал хорошо работать.
Спасибо заранее!
Что касается вашей последней ошибки: Это полный стек ошибок? К какому коду это принадлежит, я не могу найти строки в вашем коде. – Daniel
Я заметил, что параллельный пул удерживает задания на неопределенный срок, пытаясь запустить примеры партий из документации. Он просто уходит куда-то, и когда вы ждете (работа), он просто занят, пока вы не нажмете kill matlab. – Adriaan
'convContinuous> makeF% 1/F%' - это имя функции, созданной машиной 'parfor'. Было бы полезно иметь исполняемые шаги воспроизведения, чтобы увидеть, что происходит неправильно. Мне не сразу понятно, почему вы это видите - безусловно, ваша функция 'convolveSeries' безоговорочно предоставляет свой выходной аргумент. – Edric