Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/performance/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Performance 提高插值性能(重心公式)_Performance_Matlab_Interpolation_Vectorization - Fatal编程技术网

Performance 提高插值性能(重心公式)

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表示重心权重,在运

我被分配了一个任务,我要写一个算法,用重心公式进行多项式插值。公式表明:

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
表示重心权重,在运行算法之前已计算出重心权重。而
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。我明白了,我已经取下了标签。谢谢你通知我。哇!非常感谢你的帮助。我真的很感激。