简体   繁体   English

python 中最快的多项式评估

[英]fastest polynomial evaluation in python

I'm working on an old project of building Newton Basins and I'm trying to make it as fast as possible.我正在做一个建造牛顿盆地的旧项目,我正在努力让它尽快完成。 The first thing I'm trying to speed up is how to evaluate a polynomial function at a given complex point x0 .我要加快速度的第一件事是如何在给定的复数点x0处计算多项式 function。 I thought of 4 different ways of doing this and tested them with timeit .我想到了 4 种不同的方法,并用timeit测试了它们。 The code I used is the following:我使用的代码如下:

import timeit
import numpy as np
import random
from numpy import polyval

class Test(object):
    re = random.randint(-40000, 40000)/10000
    im = random.randint(-40000, 40000)/10000
    x0 = complex(re, im)
    coefs = np.array([48,8,4,-10,2,-3,1])
    flip_coefs = np.flip(coefs)

    def solve0():
        y = np.array([Test.coefs[i]*(Test.x0**i) for i in range(len(Test.coefs))]).sum()
        return y

    def solve1():
        y = 0
        for i in range(len(Test.coefs)):
            y += Test.coefs[i]*(Test.x0**i)
        return y

    def solve2():
        y = np.dot(Test.coefs,Test.x0**np.arange(len(Test.coefs)))
        return y

    def solve3():
        y = polyval(Test.flip_coefs, Test.x0)
        return y


Test.solve0()


if __name__ == '__main__':
    print(timeit.timeit('Test.solve0()', setup="from __main__ import Test", number=10000))
    print(timeit.timeit('Test.solve1()', setup="from __main__ import Test", number=10000))
    print(timeit.timeit('Test.solve2()', setup="from __main__ import Test", number=10000))
    print(timeit.timeit('Test.solve3()', setup="from __main__ import Test", number=10000))

the thing is that I was pretty sure that numpy.polyval() would be the fastest, but it seems that, on Linux, np.dot(coefs,x**np.arange(len(coefs))) is more than twice as fast, regardless of the value of x0 (I don't know if it is the same in Windows and MacOS).问题是我很确定numpy.polyval()会是最快的,但似乎在 Linux 上, np.dot(coefs,x**np.arange(len(coefs)))是两倍以上一样快,不管x0的值如何(我不知道在 Windows 和 MacOS 中是否相同)。 This is an output example I've got:这是我得到的 output 示例:

0.1735437790002834
0.12607222800033924
0.0313361469998199
0.0796813930001008

This seems quite strange since numpy.polyval() was specifically built for solving polynomials.这看起来很奇怪,因为numpy.polyval()是专门为求解多项式而构建的。 So, my questions are: Is there something I'm missing here (maybe related to the coefficients I chose)?所以,我的问题是:我在这里遗漏了什么(可能与我选择的系数有关)吗? Are there faster ways of evaluating polynomials?是否有更快的评估多项式的方法?

Examining the source code of the polyval() function of numpy you'll observe that this is a purely pythonic function. Numpy uses Horner's method for polynomial evaluation (and facilitates the evaluation of multiple points concurrently, though this case doesn't apply here).检查 numpy 的polyval() function 的源代码,您会发现这是一个纯粹的 pythonic function。Numpy 使用霍纳的多项式评估方法(并有助于同时评估多个点,尽管这种情况不适用于此处) .

To answer your questions about evaluation cost, I believe Horner's method is optimal from the algorithmic perspective: It allows the evaluation of a polynomial of degree n with only n multiplications and n additions, in contrast to your fastest method solve2() where multiplication operations scale polynomially with input size.为了回答您关于评估成本的问题,我相信Horner 的方法从算法的角度来看是最优的:它允许仅通过n次乘法和n次加法来评估n次多项式,这与您最快的方法solve2()相比,其中乘法运算缩放与输入大小多项式。 In terms of speed of computation, I suspect that the increase in performance of your approach vs the polyval() function comes from the fact that the dot product in numpy is implemented in C and receives a substantial speedup on that front.在计算速度方面,我怀疑你的方法与polyval() function 相比性能的提高来自于 numpy 中的点积在 C 中实现并在这方面获得了显着的加速。

Addendum: For a comprehensive overview of the topic, I cannot recommend enough Knuth's The Art of Computer Programming.附录:要全面了解该主题,我强烈推荐 Knuth 的《计算机编程艺术》。 Vol. 卷。 2: Seminumerical Algorithms (3rd ed.) , of which section 4.6.4 on page 485 refers to this situation. 2: Seminumerical Algorithms (3rd ed.) ,其中第485页第4.6.4节提到了这种情况。 I believe Horner's method is optimal for a single polynomial evaluation, however if this polynomial is to be evaluated many times, then potentially further speedups can be gained if one allows preconditioning.我相信 Horner 的方法对于单个多项式评估是最佳的,但是如果要多次评估这个多项式,那么如果允许预处理,则可能会获得进一步的加速。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM