前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >两行代码让 Python 性能超越 C++ 3 个数量级

两行代码让 Python 性能超越 C++ 3 个数量级

作者头像
初代庄主
发布于 2023-03-24 06:34:41
发布于 2023-03-24 06:34:41
65600
代码可运行
举报
文章被收录于专栏:初代庄主初代庄主
运行总次数:0
代码可运行

背景

前文(Python 搭配 C++ 让性能直接拉满)我们讲到,如果有部分热点函数其性能不行,我们可以把 Python 代码改写成 C/C++ 代码以此来提升性能。经验上来看这种做法可能提升一到两个数量级多数情况下能解决问题。

这个处理方式相对来讲要求会高一些,它要求开发者对 Python 和 C/C++ 都要熟悉,并且可以随便切换。

多年的摸爬滚打,我在 Python 标准库中发现了一些“奇技淫巧”;有些技术可以做到一两行代码让性能原地起上天。


问题回顾

还是书接上回,在算法不变的情况下,C++ 要比 Python 快几十倍。上一次测试的算法与耗时情况如下。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制

#/usr/bin/env python3

"""
测试 Python & C++ 这两种语言计算 斐波那契数列 的快慢。
"""

from datetime import datetime

# 导入我写的 C++ 库
from plugins import cppmath

def fib(n):
    """求 斐波那契数列 的第 n 位的值
    Parameter:
    ----------
    n: int
        第 n 位

    Return:
    -------
    int
        返回斐波那契数列第 n 位的值
    """
    if n == 1 or n == 2:
        return 1
    else:
        return fib(n - 1) + fib(n - 2)

def main(n):
    """分别测试 C++ 和 Python 计算同一个数的耗时
    """
    start = datetime.now()
    res = cppmath.fib(n)
    end = datetime.now()
    print("C++ 计算的结果为    {} 总的耗时 {}(s)".format(res, end-start))

    start = datetime.now()
    res = fib(n)
    end = datetime.now()
    print("Python 计算的结果为 {} 总的耗时 {}(s)".format(res, end-start))

if __name__ == "__main__":
    main(40)
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
python3 test-fib-speed.py 
C++ 计算的结果为    102334155 总的耗时 0:00:00.140350(s)
Python 计算的结果为 102334155 总的耗时 0:00:11.720886(s)

优化原理

大多数情况下我们没有性能又好,成本又低的代码实现;通常是我们要失去一部分 xxx ,来换取一部分的 zzz 。

对于有些递归算法来说,有一个非常有效果的办法就是用一部分 “内存资源” 来换取 “计算速度” 的提升。

比如我们算 fib(5) 的时候它依赖于 fib(4) + fib(3) ,当我们计算 fib(4) 的时候它依赖于 fib(3) + fib(2) 。可以看到 fib(3) 重复计算了,我们可以把第一次计算的 fib(3) 结果缓存起来,这样第二次的时候就可以不用算了。

标准库中有一个叫 functools 的模块,它里的工具函数就有专门用来做这个的,比较典型的一个就是 lru_cache 函数。下面我们改一下之前的代码,只要加两行就行了。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
from functools import lru_cache

# 这个装饰器会给我们做完成所有事
@lru_cache(maxsize=1024)
def fib(n):
    """求 斐波那契数列 的第 n 位的值
    Parameter:
    ----------
    n: int
        第 n 位

    Return:
    -------
    int
        返回斐波那契数列第 n 位的值
    """
    if n == 1 or n == 2:
        return 1
    else:
        return fib(n - 1) + fib(n - 2)

之前运行耗时是这样的

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
python3 test-fib-speed.py 
C++ 计算的结果为    102334155 总的耗时 0:00:00.140350(s)
Python 计算的结果为 102334155 总的耗时 0:00:11.720886(s)

现在的运行耗时是这样的

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
python3 test-fib-speed.py
C++ 计算的结果为    102334155 总的耗时 0:00:00.139594(s)
Python 计算的结果为 102334155 总的耗时 0:00:00.000047(s)

我算了一下性能差异,就 2900 来倍吧!

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
In [1]: 139594 /47
Out[1]: 2970.0851063829787

最后

每种方法都有它的作用范围,想要持续积累这类 “奇技淫巧” 还要多多关注我呀!

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

本文分享自 初代庄主 微信公众号,前往查看

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

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

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
Python 搭配 C++ 让性能直接拉满
本人的主力语言是 Python & JavaScript & C++;数据采集主要用 JavaScript 语言实现,后面的分析用 Python 实现。
初代庄主
2023/02/20
6520
Python 搭配 C++ 让性能直接拉满
学会这个,Python的递归再也不慢了
之前我在学 Python 的时候,第一次觉得它慢是执行一个递归函数,来求斐波那契数列,计算第 40 个数就需要 37 秒,同样的逻辑使用 java,则不到 1 秒就执行完毕。以下是在 IPython 环境下的运行耗时:
somenzz
2020/11/25
5880
Python性能提升大杀器:深入解析functools.lru_cache装饰器
在编写程序时,经常会遇到需要计算某个函数的输出,然后在稍后的代码中多次使用该输出的情况。
雷子
2024/02/06
4390
Python性能提升大杀器:深入解析functools.lru_cache装饰器
lru_cache和cache原理
LRU LRU (Least Recently Used) 是缓存置换策略中的一种常用的算法。当缓存队列已满时,新的元素加入队列时,需要从现有队列中移除一个元素,LRU 策略就是将最近最少被访问的元素移除,从而腾出空间给新的元素。
玖柒的小窝
2021/10/23
1.1K0
Python函数缓存器
平时常听说使用redis做缓存,但是redis换缓存存放的是结果数据,从Python 的 3.2 版本开始,引入了一个非常优雅的缓存机器
Autooooooo
2020/11/09
9140
Python函数缓存器
使用Python标准库functools中的lru_cache实现缓存
很简单,也很容易理解,但是不难发现这个函数在计算斐波那契数列的时候事实上进行了很多重复计算,例如:
杜逸先
2018/05/31
2.6K1
使用Python标准库functools中的lru_cache实现缓存
如何写出高性能Python之缓存的应用?
  能看到这篇文章的同学,应该都对缓存这个概念不陌生,CPU中也有一级缓存、二级缓存和三级缓存的概念。缓存可以解决哪些问题?我们直接把网上的一段话放上来:
猫叔Rex
2021/01/29
5360
有效提升Python代码性能的三个层面
使用python进入一个熟练的状态之后就会思考提升代码的性能,尤其是python的执行效率还有很大提升空间(委婉的说法)。面对提升效率这个话题,python自身提供了很多高性能模块,很多大牛开发出了高效第三方包,可谓是百花齐放。下面根据我个人使用总结出提升性能的几个层面和相关方法。
自学气象人
2023/06/20
2630
有效提升Python代码性能的三个层面
让Python程序轻松加速的方法
最近,我读了一篇有趣的文章,文中介绍了一些未充分使用的Python特性的。在文章中,作者提到,从Python 3.2开始,标准库附带了一个内置的装饰器 functools.lru_cache 。我发现这个装饰器很令人兴奋,有了它,我们有可能轻松地为许多应用程序加速。
博文视点Broadview
2020/06/12
1.2K0
让Python程序轻松加速的方法
Python并发编程:开启性能优化的大门(7/10)
在当今数字化时代,Python 已成为编程领域中一颗璀璨的明星,占据着编程语言排行榜的榜首。无论是数据科学、人工智能,还是 Web 开发、自动化脚本编写,Python 都以其简洁的语法、丰富的库和强大的功能,赢得了广大开发者的青睐。
正在走向自律
2025/05/12
1760
Python并发编程:开启性能优化的大门(7/10)
Python数据结构与算法优化技巧:提高性能和效率的实用指南
Python是一种强大而灵活的编程语言,它提供了丰富的数据结构和算法库,但是在处理大规模数据或者需要高效运行的情况下,需要考虑一些优化技巧。本文将介绍一些Python中常用的数据结构与算法优化技巧,并附带代码实例,帮助你更好地理解和运用。
一键难忘
2024/08/13
3821
动态规划详解(修订版)
这篇文章是我们号半年前一篇 200 多赞赏的成名之作 动态规划详解 的进阶版。由于账号迁移的原因,旧文无法被搜索到,所以我润色了本文,并添加了更多干货内容,希望本文成为解决动态规划的一部「指导方针」。
labuladong
2021/09/23
6190
5年 Python 功力,总结了 10 个开发技巧
当你在处理异常时,由于处理不当或者其他问题,再次抛出另一个异常时,往外抛出的异常也会携带原始的异常信息。
1480
2020/07/15
6270
一日一技:立竿见影地把你的 Python 代码提速7倍
在我们以前的文章中,曾经讲过计算斐波那契数列的几种方法,其中基于递归的方法是速度最慢的,例如计算第40项的值,需要36秒。如下图所示:
青南
2020/04/26
8810
一日一技:立竿见影地把你的 Python 代码提速7倍
C++斐波那契数列(带备忘录的递归)
这个不用多说了,学校老师讲递归的时候似乎都是拿这个举例。我们也知道这样写代码虽然简洁易懂,但是十分低效,低效在哪里?假设 n = 20,请画出递归树:
程序员小涛
2021/01/26
1.3K0
缓存淘汰算法与 python 中 lru_cache 装饰器的实现
此前的文章中,我们介绍过常见两种缓存架构 — 穿透型缓存与旁路型缓存。 常见缓存架构 — 穿透型缓存与旁路型缓存
用户3147702
2022/06/27
5570
缓存淘汰算法与 python 中 lru_cache 装饰器的实现
加推全栈之性能提升及WebAssembly畅想
函数的性能测试的一般方法 全栈A同学: 2020年要学习好多新东西,大家都在说优化,提高性能,如何入手?😶 有多个方法可以实现一个函数,到底用那种更好? 是否可以总结一些性能改变上的技巧? 2020年我们如何关注性能优化?😶 Sky:我们从构建一个通用的benchmark(性能基准测试)方法开始,切入点要小💥此方法我们希望做到以下几点 自动运行某函数多次 确定它每毫秒的执行次数 ops/ms,超过1000/ms是较优质的函数 确定它每次执行需要多少毫秒timeSpend/ms 确定它的执行稳定性,多次运行后
加推
2021/03/04
1.2K0
加推全栈之性能提升及WebAssembly畅想
这10个Python性能调优的小技巧,你知道几个?
你好,我是 zhenguo 这是我的第479篇原创,这篇文章关于Python性能调优的10个小技巧,每天花5-10分钟阅读我的文章,对你技术提升一定会有帮助。
double
2021/11/25
4830
这10个Python性能调优的小技巧,你知道几个?
Python3 编程实例(6 - 10)
实例 6 题目 斐波那契数列; 分析 利用递归计算斐波那契数列,输入斐波那契数列的n位,调用递归计算出第n位的数列值; 代码 #!/usr/bin/python3 # -*- coding: utf-8 -*- # @Time : 2018-10-3 21:10 # @Author : Manu # @Site : # @File : fib.py # @Software: PyCharm def fib(num): if num <= 2: result =
村雨遥
2022/06/15
1820
Python3 编程实例(6 - 10)
LeetCode笔记:Weekly Contest 299
显然两岸的排布方式是独立的,因此,我们只需要考察一侧的可能排布方式,然后平方一下就是我们最终需要的答案。
codename_cys
2022/06/27
2850
推荐阅读
相关推荐
Python 搭配 C++ 让性能直接拉满
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验