Python:加速函数调用

Python:加速函数调用,python,optimization,generator,Python,Optimization,Generator,如何加快python函数调用的速度。我知道我可以使用pypy来大大提高速度,但我想看看通过使用常规的python解释器我可以获得多快的速度 为每个任务创建函数可以使代码更干净、更易于阅读,但似乎会使代码速度降低很多,特别是在调用这些函数数百万次的情况下 举一个简单的例子。当然,在现实中,这些函数更复杂,但我只是对每个函数使用了一个简单的函数,以显示函数调用可能会有多少额外开销。第一个示例使用函数,其中get\u type被调用5000万次,do\u偶数被调用2500万次,do\u odd被调用2

如何加快python函数调用的速度。我知道我可以使用pypy来大大提高速度,但我想看看通过使用常规的python解释器我可以获得多快的速度

为每个任务创建函数可以使代码更干净、更易于阅读,但似乎会使代码速度降低很多,特别是在调用这些函数数百万次的情况下

举一个简单的例子。当然,在现实中,这些函数更复杂,但我只是对每个函数使用了一个简单的函数,以显示函数调用可能会有多少额外开销。第一个示例使用函数,其中
get\u type
被调用5000万次,
do\u偶数
被调用2500万次,
do\u odd
被调用2500万次。第二个示例删除了所有这些函数调用,并直接放置了逻辑。对于这个例子来说,这看起来还可以,但是对于逻辑更复杂、代码更清晰的实际例子,这可能是不可能实现的。第三个示例使用生成器,它比使用函数快一点,但不如不使用函数快

import datetime


TOTAL = 50000000


def timer(func):
    def wrapper(*args, **kwargs):
        start = datetime.datetime.now()
        res = func(*args, **kwargs)
        print("{} took: {}".format(func.__name__, datetime.datetime.now() - start))
        return res
    return wrapper


def get_type(num):
    if num%2:
        return "even"
    else:
        return "odd"


def do_even(counter):
    counter["even"] += 1


def do_odd(counter):
    counter["odd"] += 1


@timer
def with_functions():
    counter = {"even": 0, "odd": 0}
    for num in range(TOTAL):
        type = get_type(num)
        if type == "even":
            do_even(counter)
        else:
            do_odd(counter)


@timer
def no_functions():
    counter = {"even": 0, "odd": 0}
    type = None
    for num in range(TOTAL):
        if num % 2:
            type = "even"
        else:
            type = "odd"

        if type == "even":
            counter["even"] += 1
        else:
            counter["odd"] += 1


def g_evens(counter):
    while 1:
        counter["even"] += 1
        yield


def g_odds(counter):
    while 1:
        counter["odd"] += 1
        yield

@timer
def generators():
    counter = {"even": 0, "odd": 0}
    g_even = g_evens(counter)
    g_odd = g_odds(counter)

    for num in range(TOTAL):
        if num % 2:
            next(g_even)
        else:
            next(g_odd)


with_functions()
no_functions()
generators()
python 3(linux)中的输出:

以Py3(linux)格式输出:


在pypy3中,带函数和不带函数似乎没有太大区别。在常规python解释器中是否有这样做的方法?或者我真的不应该担心,因为在现实中,更复杂的逻辑可能需要更长的时间,而额外的9秒实际上什么都不是。但是,由于这个示例非常简单和快速,9秒似乎占总执行时间的50%。

也许这会回答您的问题。谢谢你。对不起,这个问题让人困惑。我有点知道,我已经排除了
为什么
的问题,我真的想把重点放在
如何
来加速它。函数调用是昂贵的,我想这是你在这里看到的主要问题。PyPy的JIT可以通过排列调用来消除调用。如果您想使用带有常规包的常规解释器,不,您不能做更多的事情来防止这种情况。这正是PyPy团队创建PyPy的原因。。。如果您可以使用一些额外的包,那么您可以对此进行改进(有一些限制)。更具体地说,我正在考虑使用Cython、Numba、Numpy等。
with_functions took: 0:00:18.344544
no_functions took: 0:00:09.707193
generators took: 0:00:12.016994
with_functions took: 0:00:01.562282
no_functions took: 0:00:01.513855
generators took: 0:00:02.496888