为什么 MATLAB 作业需要很长时间 运行?
Why is MATLAB job taking a long time running?
我有一个函数(卷积),如果它在许多列的矩阵上运行(下面的函数代码),它会变得非常慢。因此我想并行化代码。
示例 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 终端一直处于等待状态,等待完成。然后,我通过 Home -> Parallel -> Monitor jobs
打开 Jobs Monitor
,看到有两个作业,其中一个状态为 running
。但是 none 将永远完成。
问题
为什么 运行 是一个非常简单的任务?
以下并行化我的函数的最佳方法是什么? ("heavy" 部分在分离函数 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我做的都OK。然后我不得不认为这是一个 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
循环中的函数调用需要很多参数,但我真的不知道。
解决错误
感谢这里的人的谨慎评论(说他们无法重现我的错误),我继续寻找错误的来源。我意识到这是一个本地错误,因为我的 pathdef.m
中有 pforfun
而 I downloaded long ago from File Exchange.
从 pathdef.m
中删除 pforfun
后,parfor
(convContinuous
函数中的第 18 行)开始运行良好。
提前致谢!
您创建的并行池正在阻止您的作业 运行。当您使用作业和任务 API 时,您不需要(也不能)打开池。当您查看作业监视器时,您看到的 运行 作业是支持并行池的作业,只有在删除池时才会完成。
如果您删除 convContinuous
中表示 myPool = gcp
的行,那么它应该可以工作。作为一种优化,您可以使用向量化形式的 createTask,这比在循环中创建任务更有效,即
inputCell = cell(1, n);
for i = 1:n
inputCell{i} = {tData, sData(:,i), smoothFun, par};
end
task = createTask(job, @convolveSeries, 1, inputCell);
然而,说了这么多,您应该能够使用 parfor 使这段代码工作。您遇到的第一个错误是由于 matlabpool
被删除,现在已被 parpool
取代。
第二个错误似乎是由您的函数未返回正确输出引起的,但错误消息似乎与您发布的代码不对应,所以我不确定。具体我不知道convContinuous>makeF%1/F% (line 1)
指的是什么。
感谢这里的人的谨慎评论(说他们无法重现我的错误),我继续寻找错误的来源。我意识到这是一个本地错误,因为我的 pathdef.m
I downloaded long ago from File Exchange.
中有 pforfun
从我的 pathdef.m
中删除 pforfun
后,parfor
(convContinuous
函数中的第 18 行)开始运行良好。
我有一个函数(卷积),如果它在许多列的矩阵上运行(下面的函数代码),它会变得非常慢。因此我想并行化代码。
示例 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 终端一直处于等待状态,等待完成。然后,我通过 Home -> Parallel -> Monitor jobs
打开 Jobs Monitor
,看到有两个作业,其中一个状态为 running
。但是 none 将永远完成。
问题
为什么 运行 是一个非常简单的任务?
以下并行化我的函数的最佳方法是什么? ("heavy" 部分在分离函数
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我做的都OK。然后我不得不认为这是一个 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
循环中的函数调用需要很多参数,但我真的不知道。
解决错误
感谢这里的人的谨慎评论(说他们无法重现我的错误),我继续寻找错误的来源。我意识到这是一个本地错误,因为我的 pathdef.m
中有 pforfun
而 I downloaded long ago from File Exchange.
从 pathdef.m
中删除 pforfun
后,parfor
(convContinuous
函数中的第 18 行)开始运行良好。
提前致谢!
您创建的并行池正在阻止您的作业 运行。当您使用作业和任务 API 时,您不需要(也不能)打开池。当您查看作业监视器时,您看到的 运行 作业是支持并行池的作业,只有在删除池时才会完成。
如果您删除 convContinuous
中表示 myPool = gcp
的行,那么它应该可以工作。作为一种优化,您可以使用向量化形式的 createTask,这比在循环中创建任务更有效,即
inputCell = cell(1, n);
for i = 1:n
inputCell{i} = {tData, sData(:,i), smoothFun, par};
end
task = createTask(job, @convolveSeries, 1, inputCell);
然而,说了这么多,您应该能够使用 parfor 使这段代码工作。您遇到的第一个错误是由于 matlabpool
被删除,现在已被 parpool
取代。
第二个错误似乎是由您的函数未返回正确输出引起的,但错误消息似乎与您发布的代码不对应,所以我不确定。具体我不知道convContinuous>makeF%1/F% (line 1)
指的是什么。
感谢这里的人的谨慎评论(说他们无法重现我的错误),我继续寻找错误的来源。我意识到这是一个本地错误,因为我的 pathdef.m
I downloaded long ago from File Exchange.
pforfun
从我的 pathdef.m
中删除 pforfun
后,parfor
(convContinuous
函数中的第 18 行)开始运行良好。