我正在尝试评估一个大的分段多项式中的点,这是从三次样条求得的。这需要很长时间才能完成,我想加快速度。
因此,我想用并行过程来评估分段多项式的点,而不是顺序。
代码:
z = zeros(1e6, 1) ; % preallocate some memory for speed
Y = rand(11220,161) ; %some data, rand for generating a working example
X = 0 : 0.0125 : 2 ; % vector of data sites
pp = spline(X, Y) ; % get the piecewise polynomial form of the cubic spline.
结果结构很大。
for t = 1 : 1e6 % big number
hcurrent = ppval(pp,t); %evaluate the piecewise polynomial at t
z(t) = sum(x(t:t+M-1).*hcurrent,1) ; % do some operation of the interpolated value. Most likely not relevant to this question.
end
不幸的是,使用矩阵形式并使用:
hcurrent = flipud(ppval(pp, 1: 1e6 ))
需要太多内存才能处理,因此无法完成。有没有办法可以批处理这段代码来加快速度呢?
答案 0 :(得分:0)
使用parfor
命令进行并行循环。请参阅here,同时将z向量预先计算为z(j) = x(j:j+M-1)
,并将parfor
中的hcurrent计算为加速。
答案 1 :(得分:0)
样条参数估计可以用矩阵形式编写。
一旦用Matrix形式编写并解决它,您可以使用模型矩阵使用矩阵乘法来评估所有数据点上的样条曲线,这可能是MATLAB中调整最多的操作。
答案 2 :(得分:0)
对于标量第二个参数,如在您的示例中,您正在处理两个问题。首先,存在大量的函数调用开销和冗余计算(例如,每次循环迭代都调用unmkpp(pp)
)。其次,ppval
被认为是通用的,所以它没有完全矢量化,并且做了许多在你的情况下不必要的事情。
下面是利用问题结构的矢量化代码(例如,t
是一个大于0的整数),避免函数调用开销,将一些计算移到主{{1循环(以一点额外的内存为代价),摆脱for
内的for
循环:
ppval
结果代码占用n = 1e6;
z = zeros(n,1);
X = 0:0.0125:2;
Y = rand(11220,numel(X));
pp = spline(X,Y);
[b,c,l,k,dd] = unmkpp(pp);
T = 1:n;
idx = discretize(T,[-Inf b(2:l) Inf]); % Or: [~,idx] = histc(T,[-Inf b(2:l) Inf]);
x = bsxfun(@power,T-b(idx),(k-1:-1:0).').';
idx = dd*idx;
d = 1-dd:0;
for t = T
hcurrent = sum(bsxfun(@times,c(idx(t)+d,:),x(t,:)),2);
z(t) = ...;
end
示例的大约34%的时间。请注意,由于矢量化,计算以不同的顺序执行。由于浮点数学的性质,这将导致n=1e6
的输出与我的优化版本之间的细微差别。任何差异都应该是ppval
的几次。你仍然可以尝试使用eps(hcurrent)
来进一步加快计算速度(有四个已经在运行的工作人员,我的系统只占你代码原始时间的12%)。
我认为以上是概念证明。如果您的示例与您的实际代码和数据不符,我可能会过度优化上面的代码。在这种情况下,我建议您创建自己的优化版本。您可以在命令窗口中键入parfor
来查看ppval
的代码。您可以通过查看问题的结构以及edit ppval
向量中最终需要的内容来实现进一步的优化。
在内部,z
仍然使用已被弃用的histc
。我上面的代码使用discretize
执行相同的任务as suggested by the documentation。