我试图通过使用并行性来加速MATLAB中大量数据的拟合,并且我面临着一个非常奇怪的问题。
我试图找出问题,希望有人可能知道发生了什么。这是示例代码:
f = @(a, x) a*x;
fitopt = fitoptions(f);
for i = 1:5
disp(fitopt);
end
如果我运行上面的代码,fitopt
的内容将按预期写入5次。但是,如果我将for
替换为parfor
循环,fitopt
将设置为空并且不会显示任何内容。
有什么可能出错的线索?
我的配置:Windows 7上的MATLAB 2014a,64位
答案 0 :(得分:2)
以下内容基于MATLAB版本R2016b ...
据我所知,这似乎是MATLAB能够正确broadcast(或不)某些parfor
工人的类对象的问题。 fitoptions
函数返回示例中的类curvefit.nlsqoptions
的对象。通过Curve Fitting Toolbox代码,可以看到这些对象仍然使用较旧的UDD类系统定义(Donn Shull的一个很好的介绍可以在Undocumented MATLAB上找到)。虽然多年前引入了较新的MCOS(MATLAB类对象系统),但您仍然可以找到使用UDD定义的大量对象。
在您的示例中,fitopt
应该broadcast(即复制)给每个工作人员,而fitopt
在[]
内设置为parfor
}循环。如果我们尝试使用更新的类系统定义的另一个类对象(如fittype
创建的那个),那么广播工作正常。例如,此测试代码:
f = @(a, x) a*x;
uddObj = fitoptions(f);
mcosObj = fittype(f);
parfor i = 1:3
fprintf('\nWorker %d:\n', i);
uddObj
mcosObj
end
生成此输出:
Worker 2:
uddObj =
[]
mcosObj =
General model:
mcosObj(a,x) = a*x
Worker 1:
uddObj =
[]
mcosObj =
General model:
mcosObj(a,x) = a*x
Worker 3:
uddObj =
[]
mcosObj =
General model:
mcosObj(a,x) = a*x
因此,简而言之,parfor
循环似乎无法正确地广播UDD样式对象。一种解决方法是在parfor循环中创建这些对象,避免广播:
f = @(a, x) a*x;
parfor i = 1:5
fitopt = fitoptions(f); % Function handle f broadcasts just fine
disp(fitopt);
end
您还可以通过创建索引的对象数组来创建sliced variable:
f = @(a, x) a*x;
fitopt = repmat(fitoptions(f), [1 5]);
parfor i = 1:5
disp(fitopt(i));
end