如何使 python 代码的求和速度更快?

How do I make my python code for summing much faster?

下面的代码是从下限 2 求和的定义函数,我改变了和的上限,因为我想找出和收敛的地方。我发现上限越大代码运行s越慢。对于任何大的上限值,如何使此代码 运行 快速?代码如下:

def h(i):
    x = (-1)**(i+1)
    y = 1000000000-(i-1)
    z = (log(i))**20
    return x*y*z

 gx = sum(h(i) for i in range (2, 1000000000+1))
 d_gx = gx/1000000000
 print(d_gx)

Numba 是一个 python 库,用于即时优化纯 python 代码,无需外部编译步骤。

这里要介绍的两个重要函数是numba.njitnumba.vectorize,它们都是装饰器。 njit 优化任意纯函数,vectorize 使函数在标量和 ndarray 上运行。

In [1]: from numba import vectorize, njit; from math import log

In [2]: def h(i):
   ...:     x = (-1)**(i+1)
   ...:     y = 1000000000-(i-1)
   ...:     z = (log(i))**20
   ...:     return x*y*z
   ...:

In [3]: %timeit sum(h(i) for i in range (2, 1000000+1))
646 ms ± 9.16 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

正如您在此处看到的那样,您的函数的简单实现平均需要 646 毫秒,减少了输入量 space。我们可以通过调整您的功能来改进这一点:

In [4]: jit_h = njit()(h)

In [5]: %timeit sum(jit_h(i) for i in range (2, 1000000+1))

179 ms ± 3.88 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
    

我们已将其缩短为 179 毫秒,与原来的 646 毫秒相比有了巨大的改进。因为 for 循环很慢,我们可以尝试使用 numpy 数组作为输入来向量化操作:

In [6]: vectorize_h = vectorize()(h)

In [7]: %timeit sum(vectorize_h(i) for i in range (2, 1000000+1))
657 ms ± 4.55 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

正如预期的那样,矢量化输入允许传递标量,但不会显着提高性能——事实上,它有点慢!如果我们对整个 numpy 数组进行操作会怎么样?

In [8]: import numpy as np

In [9]: %timeit sum(vectorize_h(np.arange(2,1000000+1))) 

149 ms ± 1.78 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)

最后,如果我们用 numpy ndarray sum 替换 sum 内置函数会怎样?

In [10]: %timeit vectorize_h(np.arange(2,1000000+1)).sum() 
17.2 ms ± 207 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

进一步减少到 17.2 毫秒 -- 与原始实现相比有了巨大的改进。