前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >让你的Python提速30%!(上)

让你的Python提速30%!(上)

作者头像
AiTechYun
发布2020-02-21 13:01:00
4310
发布2020-02-21 13:01:00
举报
文章被收录于专栏:ATYUN订阅号
讨厌Python的人总是说,他们不想使用Python的原因之一是它的速度太慢。好吧,不管使用哪种编程语言,具体的程序是快还是慢,很大程度上取决于编写程序的开发人员以及他们编写优化的快速程序的技能和能力。

所以,让我们来证明一些人是错的,让我们看看如何提高Python程序的性能并使它们变得非常快!

时间和剖析

在开始优化任何东西之前,我们首先需要找出代码的哪些部分实际上会减慢整个程序的速度。有时,程序的瓶颈可能很明显,但如果您不知道它在哪里,那么下面是您可以找到的选项:

注:这是我将用于演示目的的程序,它计算e的X次方(取自Python文档):

代码语言:javascript
复制
# slow_program.py
from decimal import *

def exp(x):
    getcontext().prec += 2
    i, lasts, s, fact, num = 0, 0, 1, 1, 1
    while s != lasts:
        lasts = s
        i += 1
        fact *= i
        num *= x
        s += num / fact
    getcontext().prec -= 2
    return +s

exp(Decimal(150))
exp(Decimal(400))
exp(Decimal(3000))

最懒的“剖析”

首先,最简单、最懒的解决方案-Unix time命令:

代码语言:javascript
复制
~ $ time python3.8 slow_program.py

real    0m11,058s
user    0m11,050s
sys     0m0,008s

如果你只想给你的整个程序计时,这是可行的,但这通常是不够的…

最详细的剖析

在光谱的另一端是cProfile,它会给你提供太多的信息:

代码语言:javascript
复制
~ $ python3.8 -m cProfile -s time slow_program.py
         1297 function calls (1272 primitive calls) in 11.081 seconds

   Ordered by: internal time

   ncalls  tottime  percall  cumtime  percall filename:lineno(function)
        3   11.079    3.693   11.079    3.693 slow_program.py:4(exp)
        1    0.000    0.000    0.002    0.002 {built-in method _imp.create_dynamic}
      4/1    0.000    0.000   11.081   11.081 {built-in method builtins.exec}
        6    0.000    0.000    0.000    0.000 {built-in method __new__ of type object at 0x9d12c0}
        6    0.000    0.000    0.000    0.000 abc.py:132(__new__)
       23    0.000    0.000    0.000    0.000 _weakrefset.py:36(__init__)
      245    0.000    0.000    0.000    0.000 {built-in method builtins.getattr}
        2    0.000    0.000    0.000    0.000 {built-in method marshal.loads}
       10    0.000    0.000    0.000    0.000 <frozen importlib._bootstrap_external>:1233(find_spec)
      8/4    0.000    0.000    0.000    0.000 abc.py:196(__subclasscheck__)
       15    0.000    0.000    0.000    0.000 {built-in method posix.stat}
        6    0.000    0.000    0.000    0.000 {built-in method builtins.__build_class__}
        1    0.000    0.000    0.000    0.000 __init__.py:357(namedtuple)
       48    0.000    0.000    0.000    0.000 <frozen importlib._bootstrap_external>:57(_path_join)
       48    0.000    0.000    0.000    0.000 <frozen importlib._bootstrap_external>:59(<listcomp>)
        1    0.000    0.000   11.081   11.081 slow_program.py:1(<module>)
...

在这里,我们使用cProfile模块和time参数运行测试脚本,以便按内部时间(cumtime)对行进行排序。这给了我们很多信息,你可以看到上面的行大约是实际输出的10%。从这里,我们可以看出exp函数是罪魁祸首(惊喜,惊喜),现在我们可以得到更具体的时间和分析…

时间特定功能

现在我们知道了应该将注意力放在哪里,我们可能希望对慢速函数计时,而不需要测量代码的其余部分。为此,我们可以使用简单的decorator:

代码语言:javascript
复制
def timeit_wrapper(func):
    @wraps(func)
    def wrapper(*args, **kwargs):
        start = time.perf_counter()  # Alternatively, you can use time.process_time()
        func_return_val = func(*args, **kwargs)
        end = time.perf_counter()
        print('{0:<10}.{1:<8} : {2:<8}'.format(func.__module__, func.__name__, end - start))
        return func_return_val
    return wrapper

这个decorator随后可以应用于测试中的函数,如下所示:

代码语言:javascript
复制
@timeit_wrapper
def exp(x):
    ...

print('{0:<10} {1:<8} {2:^8}'.format('module', 'function', 'time'))
exp(Decimal(150))
exp(Decimal(400))
exp(Decimal(3000))

这会给我们这样的输出:

代码语言:javascript
复制
~ $ python3.8 slow_program.py
module     function   time  
__main__  .exp      : 0.003267502994276583
__main__  .exp      : 0.038535295985639095
__main__  .exp      : 11.728486061969306

要考虑的一件事是我们实际(想要)测量的是什么样的时间。时间包提供Time.perf_计数器和Time.process_时间。这里的区别在于perf_计数器返回绝对值,其中包括Python程序进程未运行的时间,因此它可能会受到机器负载的影响。另一方面,process_time只返回用户时间(不包括系统时间),这只是进程的时间。

原文链接:

https://towardsdatascience.com/making-python-programs-blazingly-fast-c1cd79bd1b32

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2020-01-24,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 ATYUN订阅号 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 最懒的“剖析”
  • 最详细的剖析
  • 时间特定功能
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档