Python:使用numpy和列表进行计时

时间:2017-09-28 10:35:45

标签: python list numpy

我正在为学校做任务,我应该计算一个集成函数的python实现以及同样的numpy实现。我通常希望numpy比python实现更好,但事实并非如此。与numpy数组相比,我使用python中的list comprehension获得大约4倍的速度。从N = 1000到N = 100 000都是如此。没有测试任何更高的值,因为N = 100 000是我需要在估计中得到可接受误差的地方。

常规python代码:
    f是要集成的函数,a和b是限制,N是要集成的点数

def integrate(f, a, b, N):
    x_val = [a + (i*b) / N for i in range(N+1)]
    return sum([f(x_val[i]) * (x_val[i] - x_val[i-1]) for i in range(1, len(x_val))])

Numpy代码:

def numpy_integrate(f, a, b, N):
    x_val = numpy.zeros(N+1)
    x_val[0] = a
    res = 0
    for i in numpy.arange(1, len(x_val)):
        x_val[i] = a + (i*b)/N
        res += f(x_val[i]) * (x_val[i] - x_val[i - 1])

    return res

我的numpy实现可能正在做一些可怕的错误,或者这种规模的常规列表理解是否快得多?

2 个答案:

答案 0 :(得分:0)

首先,您的代码中存在错误,它只为a=0提供了正确的结果。您需要将a + (i*b)/N替换为a + i*(b - a)/N

正如COLDSPEED在评论中所说,你没有通过使用for循环来充分利用numpy功能。这是使用数组切片的更高效版本:

def numpy_integrate2(f, a, b, N):
    x_val = a + numpy.arange(N+1)*(b - a)/N
    return (f(x_val[1:]) * (x_val[1:] - x_val[:-1])).sum()

当我使用平方函数a = 1,b = 2和N = 100000进行测试时,此版本比intergrate函数快50倍。

编辑:我注意到定义x_val的速度更快:

x_val = numpy.arange(a, b + (b - a)/N, (b - a)/N)

备注:仅当函数f可以应用于数组时,此答案才有效。

答案 1 :(得分:0)

这取决于您的f,如果它允许处理数组,那么您可以使用:

import numpy as np

def integrate(f, a, b, N):
    x_val = a + b / N * np.arange(N+1)
    return (f(x_val[1:]) * np.diff(x_val)).sum()

这是使用矢量化和广播操作使其(更快)更快。

如果你的f无法按元素处理数组,你应该使它成为进程数组,或者你需要在那里创建另一个数组:

def integrate(f, a, b, N):
    x_val = a + b / N * np.arange(N+1)
    return (np.array([f(val) for val in x_val[1:].tolist()]) * np.diff(x_val)).sum()

请注意,您还可以更快地制作列表方法。这是因为迭代元素通常比迭代元素更快,并且你不需要sum的列表理解,生成器也会做得很好(并且更多的内存 - 有效):

from itertools import tee

def pairwise(iterable):  
    # taken from https://docs.python.org/3/library/itertools.html#itertools-recipes 
    a, b = tee(iterable)
    next(b, None)
    return zip(a, b)

def integrate(f, a, b, N):
    x_val = [a + (i*b) / N for i in range(N+1)]
    return sum(f(nxt) * (nxt - prev) for prev, nxt in pairwise(x_val))