【发布时间】:2015-11-12 08:26:23
【问题描述】:
我有一个函数(卷积),如果它在许多列的矩阵上运行(函数代码如下),它会变得非常慢。因此我想并行化代码。
示例 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 语句,但它出错了(见结束语 em> 下面)。
我的第二次尝试是关注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 告诉我:
使用“本地”配置文件启动并行池(parpool)...连接到 4 个工作人员。
警告:此作业将一直排队,直到并行池关闭。
MATLAB 终端一直处于等待状态,等待完成。然后我通过Home -> Parallel -> Monitor jobs 打开Jobs Monitor,看到有两个工作,其中一个状态为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 给了我一个奇怪的错误:
使用 matlabpool 时出错(第 27 行) matlabpool 已被删除。
要查询已启动的并行池的大小,请查询池的“NumWorkers”属性。
要检查池是否已启动,请使用 'isempty(gcp('nocreate'))'。
parallel_function 中的错误(第 317 行) Nworkers = matlabpool('size');
convContinuous 中的错误(第 18 行) parfor i = 1:n
我的version 命令输出
Parallel Computing Toolbox Version 6.6 (R2015a)
与我的 MATLAB 版本兼容。差不多all other tests我做的都OK。然后我不得不认为这是一个 MATLAB 错误。
我尝试将matlabpool 更改为gcp,然后通过parPoolObj.NumWorkers 检索工作人员的数量,在两个不同的内置函数中更改此详细信息后,我收到另一个错误:
convContinuous 中的错误>makeF%1/F%(第 1 行)
函数 res = convContinuous(tData, sData, smoothFun, par)
在调用“convContinuous>makeF%1/F%”期间未分配输出参数“res”(可能还有其他参数)。
parallel_function 中的错误>iParFun(第 383 行) output.data = processInfo.fun(input.base, input.limit, input.data);
parProcess 中的错误(第 167 行) data = processFunc(processInfo, data);
parallel_function 中的错误(第 358 行) stateInfo = parProcess(@iParFun, @iConsume, @iSupply, ...
convContinuous 中的错误(第 14 行) parfor i = 1:numel(sData(1,:))
我怀疑最后一个错误的产生是因为parfor循环内的函数调用需要很多参数,但我真的不知道。
解决错误
感谢这里的谨慎 cmets(说他们无法重现我的错误),我继续寻找错误的来源。我意识到这是一个本地错误,因为我的pathdef.m 中有pforfun 而I downloaded long ago from File Exchange。
一旦我从pathdef.m 中删除pforfun,parfor(convContinuous 函数中的第 18 行)就开始正常工作了。
提前谢谢你!
【问题讨论】:
-
关于您的最后一个错误:这是完整的错误堆栈吗?它属于哪个代码,我无法在您的代码中找到这些行。
-
在尝试运行文档中的批处理示例时,我注意到并行池也无限期地持有作业。它只是去某个地方,当你等待(工作)时它只是很忙,直到你强制杀死 matlab。
-
convContinuous>makeF%1/F%是由parfor机器制造的函数的名称。拥有可执行的复制步骤以查看问题所在会很有帮助。我不清楚你为什么会看到这个 - 当然你的convolveSeries函数无条件地提供了它的输出参数。 -
感谢您的反馈。然后我发现最后一个错误是由函数
parallel_function生成的,我认为它是一个内置函数。但实际上它是文件交换中名为pforfun的代码的一部分。我从我的pathdef.m和parfor中删除了pforfun工作!
标签: multithreading matlab parallel-processing