代码之家  ›  专栏  ›  技术社区  ›  user1179317

Python:加速函数调用

  •  -1
  • user1179317  · 技术社区  · 4 年前

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

    为每个任务创建函数可以使代码更清晰、更易于阅读,但似乎会大大减慢代码的速度,特别是在这些函数被调用数百万次的情况下。

    下面举一个简单的例子。当然,实际上这些函数更复杂,但我只是为每个函数使用了一个简单的函数,以显示函数调用可能带来的额外开销。第一个例子使用函数,其中 get_type 被调用5000万次, do_even 被调用2500万次,以及 do_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)中的输出:

    with_functions took: 0:00:18.344544
    no_functions took: 0:00:09.707193
    generators took: 0:00:12.016994
    

    pypy3(linux)中的输出:

    with_functions took: 0:00:01.562282
    no_functions took: 0:00:01.513855
    generators took: 0:00:02.496888
    

    在pypy3中,有函数和没有函数似乎没有太大区别。有没有一种方法可以在常规python解释器中做到这一点?或者我真的不应该担心,因为实际上更复杂的逻辑可能需要更长的时间,额外的9秒真的没什么。但在这里,由于示例非常简单快捷,9秒似乎占了总执行时间的很大一部分(约50%)。。

    0 回复  |  直到 4 年前