【问题标题】:Performance improvement for multiple uses of polyval function多次使用 polyval 函数的性能改进
【发布时间】:2018-10-23 14:12:06
【问题描述】:

我有一个关于在 Matlab 中使用 polyval 函数的简单性能问题。

目前,我有一个 x 向量,它可以很长(>1000 个标量)。我想对每个 x 应用不同的多项式形式。

多项式形式存储在二维数组中,并像下面的代码一样在循环中应用。随着 polyval 的优化,代码相对较快,但循环可能很长,性能至关重要,因为它是一个目标函数,可以在一个过程中计算数千次。

关于如何提高性能的任何想法?

谢谢

% ---------- Objective Function ------------------
function [obj] = obj(x, poly_objective)
    polyvalue = zeros(length(x),1);
    for index = 1: length(x)
        polyvalue (index) = polyval(poly_objective(index,:), x(index));
    end
    obj= -sum(polyvalue );
end
% -------------------------------------------------

【问题讨论】:

  • poly_objective 的大小是多少?确定length(x) 等于size(poly_objective,1) 吗?另外,您是否需要根据您的代码仅求和的单个多项式的结果?
  • 感谢您在下面的回复。你是对的,我只需要总和。这会改变问题(和答案)吗?
  • 不,我不知道如何加快计算总和的速度。只需获取polyvalue,然后获取sum(polyvalue)

标签: matlab performance polynomial-math


【解决方案1】:

您可以手动线性化您的 for 循环,这是一个示例:

p = [3,2,1;  
     5,1,3];           %polynomial coeff
x = [5,6].';           %the query points
d = size(p,2)-1:-1:0;  %the power factors
res = sum(x.^d.*p,2);  %process all the polynome without for loop.

res =

    86
   189

此外,如果您要评估您可以使用的每个多项式的每个 x 值:

res = x.^d*p.'; %using only matrix multiplication

res =
       p1    p2
x1     86    133
x2     121   189

【讨论】:

  • 谢谢!非常有帮助。 3 个非常好的答案,观点不同但观点趋同!
【解决方案2】:

最快的方法可能是直接计算不同的多项式,去掉循环(如obchardonLuis 所示)。不过,这里有一个关于polyval 性能的说明...


如果您在命令窗口中键入edit polyval,您可以看到polyval 函数的源代码。特别是顶部附近有以下条件评估:

nc = length(p);
if isscalar(x) && (nargin < 3) && nc>0 && isfinite(x) && all(isfinite(p(:)))
    % Make it scream for scalar x.  Polynomial evaluation can be
    % implemented as a recursive digital filter.
    y = filter(1,[1 -x],p);
    y = y(nc);
    return
end

我认为"Make it scream" 评论是开发人员告诉我们这是通过该功能的一条非常快速的路线!在旁边;这也是我在 MATLAB 内置中找到的最好的评论。

那么让我们试着满足这个if 语句的条件...

✓ isscalar(x)
✓ nargin < 3 
✓ length(p) > 0
✓ isfinite(x)
✓ all(isfinite(p(:)))

太棒了,所以这始终是您使用的评估。您可能会发现删除这 5 项检查的速度有所提高,只需这样做而不是 polyval。就您的变量而言,这看起来像这样:

y = filter(1,[1 -x(index)],poly_objective(index,:)); 
polyvalue (index) = y(size(poly_objective,2)); 
% Note you should get size(poly_objective,2) outside your loop

【讨论】:

  • 这也是我在 MATLAB 内置中找到的最好的评论我同意 :-)
【解决方案3】:

我觉得你的问题有点令人困惑,但我认为这是你想要的:

polyvalue = sum(poly_objective .* x(:).^(numel(x)-1:-1:0), 2);

请注意,以上使用implicit expansion。对于 R2016b 之前的 Matlab 版本,请使用 bsxfun

polyvalue = sum(poly_objective .* bsxfun(@power, x(:), (numel(x)-1:-1:0)), 2);

示例

随机数据:

>> x = rand(1,4);
>> poly_objective = randi(9,4,4);

您的代码:

>> polyvalue = zeros(length(x),1);
   for index = 1: length(x)
       polyvalue (index) = polyval(poly_objective(index,:), x(index));
   end
>> polyvalue
polyvalue =
  13.545710504297881
  16.286929525147158
  13.289183623920710
   5.777980886766799

我的代码:

>> polyvalue = sum(poly_objective .* x(:).^(numel(x)-1:-1:0), 2)
polyvalue =
  13.545710504297881
  16.286929525147158
  13.289183623920710
   5.777980886766799

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-04-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多