什么是最快,最有效和最pythonic的方法来执行数学西格玛和? [英] What's the fastest, most efficient, and pythonic way to perform a mathematical sigma sum?

查看:59
本文介绍了什么是最快,最有效和最pythonic的方法来执行数学西格玛和?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

假设我要进行数学求和,例如 Madhava–Leibniz公式π,在Python中:

Let's say that I want to perform a mathematical summation, say the Madhava–Leibniz formula for π, in Python:

             nbsp; b;              b;           

                                                              

在一个名为Leibniz_pi()的函数中,我可以创建一个循环来计算第n个 部分和,例如:

Within a function called Leibniz_pi(), I could create a loop to calculate the nth partial sum, such as:

def Leibniz_pi(n):
    nth_partial_sum = 0       #initialize the variable
    for i in range(n+1):
        nth_partial_sum += ((-1)**i)/(2*i + 1)
    return nth_partial_sum

我假设使用xrange()代替range()会更快.使用numpy及其内置的numpy.sum()方法会更快吗?这样的例子是什么样的?

I'm assuming it would be faster to use something like xrange() instead of range(). Would it be even faster to use numpy and its built in numpy.sum() method? What would such an example look like?

推荐答案

我想大多数人会使用numpy作为最大的Python语言,通过@zero定义最快的解决方案,但它肯定不是最快的.通过一些其他优化,您可以将已经快的numpy实现击败50倍.

I guess most people will define the fastest solution by @zero using only numpy as the most pythonic, but it is certainly not the fastest. With some additional optimizations you can beat the already fast numpy implementation by a factor of 50.

仅使用Numpy(@zero)

import numpy as np
import numexpr as ne
import numba as nb

def Leibniz_point(n):
    val = (-1)**n / (2*n + 1)
    return val

%timeit Leibniz_point(np.arange(1000)).sum()
33.8 µs ± 203 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)

使用numexpr

n=np.arange(1000)
%timeit ne.evaluate("sum((-1)**n / (2*n + 1))")
21 µs ± 354 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)

使用Numba编译函数

# with error_model="numpy", turns off division-by-zero checks 
@nb.njit(error_model="numpy",cache=True)
def Leibniz_pi(n):
  nth_partial_sum = 0.       #initialize the variable as float64
  for i in range(n+1):
      nth_partial_sum += ((-1)**i)/(2*i + 1)
  return nth_partial_sum

%timeit Leibniz_pi(999)
6.48 µs ± 38.6 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)

编辑,优化代价高昂的(-1)** n

import numba as nb
import numpy as np

#replacement for the much more costly (-1)**n
@nb.njit()
def sgn(i):
    if i%2>0:
        return -1.
    else:
        return 1.

# with error_model="numpy", turns off the division-by-zero checks
#
# fastmath=True makes SIMD-vectorization in this case possible
# floating point math is in general not commutative
# e.g. calculating four times sgn(i)/(2*i + 1) at once and then the sum 
# is not exactly the same as doing this sequentially, therefore you have to
# explicitly allow the compiler to make the optimizations

@nb.njit(fastmath=True,error_model="numpy",cache=True)
def Leibniz_pi(n):
    nth_partial_sum = 0.       #initialize the variable
    for i in range(n+1):
        nth_partial_sum += sgn(i)/(2*i + 1)
    return nth_partial_sum

%timeit Leibniz_pi(999)
777 ns ± 5.36 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)

这篇关于什么是最快,最有效和最pythonic的方法来执行数学西格玛和?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆