当前位置: 首页 > 科技观察

使用Cython编写更快的PythonC扩展

时间:2023-03-12 22:13:49 科技观察

在我们的7个PyPI库系列中学习常见Python问题的解决方案。Python是当今最流行的编程语言之一,因为:它是开源的,用途广泛(例如网络编程、商业应用程序、游戏、科学编程等),它由充满活力的并致力于社区吧。这个社区使我们能够在Python包索引(PyPI)中拥有如此庞大而多样的包集,以扩展和改进Python并解决不可避免的问题。在本系列中,我们将介绍七个PyPI库,它们可以帮助您解决常见的Python问题。第一个是Cython,一种简化将C扩展写入Python的语言。Cython与Python一起使用很有趣,但有时用它编写的程序可能会很慢。所有这些运行时动态调度都付出了巨大的代价:有时它比用C或Rust等系统语言编写的等效代码慢10倍。将代码迁移到一种全新的语言可能会在成本和可靠性方面付出巨大的代价:所有手动重写都将不可避免地引入错误。我们可以两者兼得吗?为了练习优化,我们需要一些慢代码。什么比斐波那契数列的意外指数实现更慢?deffib(n):ifn<2:return1returnfib(n-1)+fib(n-2)由于对fib的调用导致再次调用两次,因此这种效率极低的算法需要很长时间才能执行。例如,fib(36)在我的新笔记本电脑上大约需要4.5秒。这4.5秒将作为我们探索Python的Cython扩展如何提供帮助的基准。Cython的正确使用方法是将其集成到setup.py中。但是,有一种使用pyximport进行试用的快速方法。让我们将fib代码放入fib.pyx并使用Cython运行它。>>>导入pyximport;pyximport.install()>>>importfib>>>fib.fib(36)在不修改代码的情况下只使用Cython,这个算法在我的笔记本电脑上花费的时间减少到大约2.5秒。这几乎可以毫不费力地将运行时间减少近50%。当然,取得了不错的成绩。来吧,我们可以让它更快。cpdefintfib(intn):ifn<2:return1returnfib(n-1)+fib(n-2)我们将fib中的代码变成一个用cpdef定义的函数,并添加两个类型注释:它需要一个整数并返回一个整数。这个速度更快,大约需要0.05秒。它是如此之快以至于我可能开始怀疑我的测量包含噪声:之前,这种噪声在信号中丢失了。下次你的Python代码占用太多CPU时间,可能导致风扇狂转,为什么不看看Cython是否可以解决问题呢?在本系列的下一篇文章中,我们将了解Black,一个自动纠正格式错误代码的项目。(标题图片:SubgrafikSan)