并行化 MATLAB for 循环以计算 MLE
Parallelize MATLAB for loop to calculate MLE
我试图通过使用 parfor
来加速我的 MATLAB 代码,但是,我做错了。我的代码相当简单,我使用 MATLAB 的内置 mle
函数拟合一些数据,方法是对均值 (mm
) 和方差 (vv
) 使用不同的初始猜测。 onestagepdf2
是我的概率密度函数。
这是代码片段:
mm=linspace(.1, 1, 2); % mean
vv=linspace(.1, 2, 2); % variance
N=length(mm);
n=length(vv);
pd=zeros(n*N,2);
ld = NaN*ones(n*N,1);
options = statset('MaxIter',10000, 'MaxFunEvals',10000);
parfor i=1:N % pick a mean
m=mm(i);
parfor j=1:n % pick a variance
v=vv(j);
x0=[m,v];
[p,conf1]=mle(data,'pdf',@onestagepdf2,'start',x0, 'upperbound', [Inf Inf],'lowerbound',[0 0],'options',options)
pd(n*(i-1)+j,:)=p; % store parameter values from mle
l=onestagepdf2(data,p(1),p(2)); % evaluate pdf with parameter values
ld(n*(i-1)+j)=sum(log(l)); % store likelihood value
end
end
我收到的错误是:
'The variable pd in a parfor cannot be classified.'
你想要一个切片的输出变量,但 Matlab 不够聪明,无法检测到 n*(i-1)+j
实际上是合理的,不会干扰异步计算。
只做单独的维度
pd = zeros(n, N, 2);
...
% in the loop
pd(i, j, :) = p;
那行得通。
请注意,Matlab 不允许嵌套的 parfors。但是,如果 N
大于工人数,您也不需要它们。另见 documentation.
pd = zeros(n, N, 2); %initialise culprits
ld= zeros(n,N);
parfor ii=1:N % pick a mean
m=mm(ii);
for jj=1:n % Parallellise the second parfor
v=vv(jj);
x0=[m,v];
[p,conf1]=mle(data,'pdf',@onestagepdf2,'start',x0, 'upperbound', [Inf Inf],'lowerbound',[0 0],'options',options)
pd(ii, jj, :) = p;=p; % store parameter values from mle
l=onestagepdf2(data,p(1),p(2)); % evaluate pdf with parameter values
ld(ii,jj)=sum(log(l)); % store likelihood value
end
end
正如@Trilarion 所说,您的 pd
确实是您所犯错误的罪魁祸首。可能 ld
也不太好,具有相同的语法,因此也将其初始化。发生这种情况是因为 parfor
在执行 之前想知道循环内所有变量的大小 。 MATLAB 不知道这是一个固定的最大大小,因为您正在使用循环变量 "change" 大小。
当您 运行 将此作为 for
循环表示 "pd appears to be growing in size each iteration. Please consider preallocating for speed" 时,可能您在这两行下方有 "orange wiggles"(如拼写检查错误)。这是 parfor
所要求的,因为迭代的顺序不是连续的,所以不可能以这种方式增长数组。
其次,您不能嵌套 parfor
循环。您可以在 parfor
中使用带有 parfor
和 运行 的函数之类的东西,但这不会让您加速,因为您已经在使用所有工作人员。
有关 parfor
尤其是速度方面的更多一般信息,请参阅 。
我试图通过使用 parfor
来加速我的 MATLAB 代码,但是,我做错了。我的代码相当简单,我使用 MATLAB 的内置 mle
函数拟合一些数据,方法是对均值 (mm
) 和方差 (vv
) 使用不同的初始猜测。 onestagepdf2
是我的概率密度函数。
这是代码片段:
mm=linspace(.1, 1, 2); % mean
vv=linspace(.1, 2, 2); % variance
N=length(mm);
n=length(vv);
pd=zeros(n*N,2);
ld = NaN*ones(n*N,1);
options = statset('MaxIter',10000, 'MaxFunEvals',10000);
parfor i=1:N % pick a mean
m=mm(i);
parfor j=1:n % pick a variance
v=vv(j);
x0=[m,v];
[p,conf1]=mle(data,'pdf',@onestagepdf2,'start',x0, 'upperbound', [Inf Inf],'lowerbound',[0 0],'options',options)
pd(n*(i-1)+j,:)=p; % store parameter values from mle
l=onestagepdf2(data,p(1),p(2)); % evaluate pdf with parameter values
ld(n*(i-1)+j)=sum(log(l)); % store likelihood value
end
end
我收到的错误是:
'The variable pd in a parfor cannot be classified.'
你想要一个切片的输出变量,但 Matlab 不够聪明,无法检测到 n*(i-1)+j
实际上是合理的,不会干扰异步计算。
只做单独的维度
pd = zeros(n, N, 2);
...
% in the loop
pd(i, j, :) = p;
那行得通。
请注意,Matlab 不允许嵌套的 parfors。但是,如果 N
大于工人数,您也不需要它们。另见 documentation.
pd = zeros(n, N, 2); %initialise culprits
ld= zeros(n,N);
parfor ii=1:N % pick a mean
m=mm(ii);
for jj=1:n % Parallellise the second parfor
v=vv(jj);
x0=[m,v];
[p,conf1]=mle(data,'pdf',@onestagepdf2,'start',x0, 'upperbound', [Inf Inf],'lowerbound',[0 0],'options',options)
pd(ii, jj, :) = p;=p; % store parameter values from mle
l=onestagepdf2(data,p(1),p(2)); % evaluate pdf with parameter values
ld(ii,jj)=sum(log(l)); % store likelihood value
end
end
正如@Trilarion 所说,您的 pd
确实是您所犯错误的罪魁祸首。可能 ld
也不太好,具有相同的语法,因此也将其初始化。发生这种情况是因为 parfor
在执行 之前想知道循环内所有变量的大小 。 MATLAB 不知道这是一个固定的最大大小,因为您正在使用循环变量 "change" 大小。
当您 运行 将此作为 for
循环表示 "pd appears to be growing in size each iteration. Please consider preallocating for speed" 时,可能您在这两行下方有 "orange wiggles"(如拼写检查错误)。这是 parfor
所要求的,因为迭代的顺序不是连续的,所以不可能以这种方式增长数组。
其次,您不能嵌套 parfor
循环。您可以在 parfor
中使用带有 parfor
和 运行 的函数之类的东西,但这不会让您加速,因为您已经在使用所有工作人员。
有关 parfor
尤其是速度方面的更多一般信息,请参阅