为什么MATLAB作业需要很长时间才能运行?

时间:2015-08-19 07:08:37

标签: multithreading matlab parallel-processing

我有一个函数(卷积),如果它运行在许多列的矩阵上(下面的函数代码),它会变得非常慢。因此,我希望并行化代码。

示例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,其中显示了如何在作业中安排任务,然后将作业提交到本地服务器。通过让最后一个参数isParalleltrue在我的函数中实现该示例。

示例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告诉我:

  

使用&#39; local&#39;启动并行池(parpool)简介...连接到4名工人。

     

警告:此作业将保持排队,直到并行池关闭。

MATLAB终端保持等待完成任务。然后我按Jobs Monitor打开Home -> Parallel -> Monitor jobs,看到有两个作业,其中一个作业状态为running。但是他们都没有完成。

问题

  • 为什么跑的时间太长,因为这是一项非常简单的任务?

  • 下面将我的功能并行化的最佳方法是什么? (&#34;重&#34;部分位于分离的函数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”&#39;游泳池的财产。

     

要检查池是否已启动,请使用&#39; isempty(gcp(&#39; nocreate&#39;))&#39;。

     

parallel_function出错(第317行)       Nworkers = matlabpool(&#39; size&#39;);

     

convC连续出错(第18行)           parfor i = 1:n

我的version命令输出

Parallel Computing Toolbox                            Version 6.6        (R2015a)

与我的MATLAB版本兼容。差不多all other tests我做的还可以。然后我被迫认为这是一个MATLAB错误。

我尝试将matlabpool更改为gcp,然后按parPoolObj.NumWorkers检索工作人员数量,在更改了两个不同内置函数中的详细信息后,我收到了另一个错误:< / p>

  

convContinuous中的错误&gt; makeF%1 / F%(第1行)

     

function res = convContinuous(tData,sData,smoothFun,par)

     

输出参数&#34; res&#34; (也许是其他人)在致电&#34; convContinuous&gt; makeF%1 / F%&#34;时未分配。

     

parallel_function中的错误&gt; 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,...

     

convC连接错误(第14行)       parfor i = 1:numel(sData(1,:))

我怀疑最后一个错误是因为parfor循环中的函数调用需要很多参数而产生的,但我真的不知道它。

解决错误

感谢此处人们的谨慎评论(说他们无法重现我的错误),我继续寻找错误的来源。我意识到由于pforfun pathdef.m pforfun pathdef.m parfor而导致本地错误。

从我的convContinuous移除{{1}}后,{{1}}({1}}功能中的第18行)开始运作良好。

提前谢谢!

2 个答案:

答案 0 :(得分:3)

您创建的并行池阻止您的作业运行。当您使用作业和任务API时,您不需要(也不能有)池打开。当您查看Job Monitor时,您看到的正在运行的作业是支持并行池的作业,只有在删除池时才会完成。

如果您删除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)指的是什么。

答案 1 :(得分:0)

感谢此处人们的谨慎评论(说他们无法重现我的错误),我继续寻找错误的来源。我意识到由于pforfun pathdef.m pforfun pathdef.m parfor而导致本地错误。

从我的convContinuous移除{{1}}后,{{1}}({1}}功能中的第18行)开始运作良好。