Performance 提高插值性能(重心公式)
我被分配了一个任务,我要写一个算法,用重心公式进行多项式插值。公式表明: p(x)=(SIGMA_uj=0到n)w(j)*f(j)/(x-x(j))/(SIGMA_j=0到n)w(j)/(x-x(j))) 我写了一个算法,它工作得很好,我得到了我想要的多项式输出。然而,这需要使用一些相当长的循环,对于大量的网格,必须执行大量的nastly循环操作。因此,如果有人对我如何改进这一点有任何提示,我将不胜感激,这样我就可以避免所有这些循环 在该算法中,Performance 提高插值性能(重心公式),performance,matlab,interpolation,vectorization,Performance,Matlab,Interpolation,Vectorization,我被分配了一个任务,我要写一个算法,用重心公式进行多项式插值。公式表明: p(x)=(SIGMA_uj=0到n)w(j)*f(j)/(x-x(j))/(SIGMA_j=0到n)w(j)/(x-x(j))) 我写了一个算法,它工作得很好,我得到了我想要的多项式输出。然而,这需要使用一些相当长的循环,对于大量的网格,必须执行大量的nastly循环操作。因此,如果有人对我如何改进这一点有任何提示,我将不胜感激,这样我就可以避免所有这些循环 在该算法中,x和f代表我们应该插值的给定点w表示重心权重,在运
x
和f
代表我们应该插值的给定点w
表示重心权重,在运行算法之前已计算出重心权重。而grid
是应在其上进行插值的邻域空间:
function p = barycentric_formula(x,f,w,grid)
%Assert x-vectors and f-vectors have same length.
if length(x) ~= length(f)
sprintf('Not equal amounts of x- and y-values. Function is terminated.')
return;
end
n = length(x);
m = length(grid);
p = zeros(1,m);
% Loops for finding polynomial values at grid points. All values are
% calculated by the barycentric formula.
for i = 1:m
var = 0;
sum1 = 0;
sum2 = 0;
for j = 1:n
if grid(i) == x(j)
p(i) = f(j);
var = 1;
else
sum1 = sum1 + (w(j)*f(j))/(grid(i) - x(j));
sum2 = sum2 + (w(j)/(grid(i) - x(j)));
end
end
if var == 0
p(i) = sum1/sum2;
end
end
这是matlab“矢量化”的经典案例。我会说——只要去掉这些环就行了。几乎就这么简单。首先,请查看以下代码:
function p = bf2(x, f, w, grid)
m = length(grid);
p = zeros(1,m);
for i = 1:m
var = grid(i)==x;
if any(var)
p(i) = f(var);
else
sum1 = sum((w.*f)./(grid(i) - x));
sum2 = sum(w./(grid(i) - x));
p(i) = sum1/sum2;
end
end
end
我已经移除了j
上的内环。事实上,我在这里所做的就是删除(j)
索引,并将算术运算符从/
更改为/
,从*
更改为*
——相同,但前面有一个点,表示该操作是在逐元素的基础上执行的。这与普通的矩阵运算符不同。还要注意,处理网格点落在x
上的特殊情况与原始实现中的情况非常相似,只使用向量var
,从而x(var)=网格(i)
现在,您还可以删除最外层的循环。这有点棘手,有两种主要方法可以在MATLAB中实现这一点。我会用更简单的方法来做,效率可能会更低,但阅读起来更清晰-使用repmat
:
function p = bf3(x, f, w, grid)
% Find grid points that coincide with x.
% The below compares all grid values with all x values
% and returns a matrix of 0/1. 1 is in the (row,col)
% for which grid(row)==x(col)
var = bsxfun(@eq, grid', x);
% find the logical indexes of those x entries
varx = sum(var, 1)~=0;
% and of those grid entries
varp = sum(var, 2)~=0;
% Outer-most loop removal - use repmat to
% replicate the vectors into matrices.
% Thus, instead of having a loop over j
% you have matrices of values that would be
% referenced in the loop
ww = repmat(w, numel(grid), 1);
ff = repmat(f, numel(grid), 1);
xx = repmat(x, numel(grid), 1);
gg = repmat(grid', 1, numel(x));
% perform the calculations element-wise on the matrices
sum1 = sum((ww.*ff)./(gg - xx),2);
sum2 = sum(ww./(gg - xx),2);
p = sum1./sum2;
% fix the case where grid==x and return
p(varp) = f(varx);
end
完全矢量化版本可以使用bsxfun
而不是repmat
实现。这可能会快一点,因为矩阵不是显式形成的。但是,对于较小的系统尺寸,速度差可能不大
此外,第一个具有一个循环的解决方案在性能方面也不算太差。我建议你测试一下,看看有什么更好。也许完全矢量化不值得?第一段代码看起来可读性更强。家庭作业标签不推荐使用,从技术上讲,我已经解决了这个问题,我并不是真的要求别人帮我做家庭作业。毕竟,我得到了我应该得到的多项式值。但就我自己的学习而言,如果有人对如何避免上述长循环有任何建议,我将不胜感激。但是,如果这个问题被认为不合适,我理解,你可以删除它。我认为询问家庭作业是可以的,只是你不需要明确地将它们标记为家庭作业。将鼠标悬停到家庭作业标记处,你会看到。它说
请不要将此标签添加到问题中
OK。我明白了,我已经取下了标签。谢谢你通知我。哇!非常感谢你的帮助。我真的很感激。