前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >PyPy 通过采用即时编译技术,能够显著提升 Python 代码的执行效率。

PyPy 通过采用即时编译技术,能够显著提升 Python 代码的执行效率。

作者头像
叶庭云
发布2024-05-25 08:15:11
920
发布2024-05-25 08:15:11
举报
文章被收录于专栏:Python进阶之路

提升 Python 代码性能至接近 C 语言的速度,无需修改源代码。遵循 Python 之父吉多・范罗苏姆的建议:“如果你想让你的代码神奇地运行得更快,你应该试试用 PyPy。

YouTube 视频链接:https://www.youtube.com/watch?v=2wDvzy6Hgxg&t=1012s

A high-speed rocket soaring through the sky, leaving a trail of flames behind, as if propelled by the power of Just-In-Time Compilation. --version 6 --quality 1 --chaos 0 --stylize 100 --aspect 16:9
A high-speed rocket soaring through the sky, leaving a trail of flames behind, as if propelled by the power of Just-In-Time Compilation. --version 6 --quality 1 --chaos 0 --stylize 100 --aspect 16:9

研究人员需要快速编写代码来验证想法的可行性,这对于他们的工作至关重要。Python 是一个理想的选择,它能帮助人们专注于想法本身,而无需过多关注代码格式等琐碎事务。然而,Python 的一个主要缺点是其运行速度相较于 C 或 C++ 等编译型语言明显较慢

那么,当通过构建 Python 原型验证了想法后,如何将其转化为一个快速且高效的工具呢?通常情况下,人们需要进行额外的步骤,即手动将 Python 代码转换为 C 语言代码。但如果 Python 原型本身就能实现快速运行,那么转换代码的时间便可用于更具价值的工作。

PyPy 恰好能够解决这一问题,它能够显著提升 Python 代码的运行速度,甚至某些情况下可以与 C 语言相媲美。为了验证 PyPy 的性能优势,我们进行了以下实验:分别使用默认的 Python 解释器和 PyPy 来运行一段代码,该代码执行一个从整数 0 加到 100,000,000 的 for 循环,并打印出运行时间。以下是实验结果:

代码语言:javascript
复制
# 导入了 Python 的 time 模块。time 模块提供了各种与时间相关的函数,可以用来测量时间、处理日期时间等。
import time
# termcolor 是一个第三方库,用于在终端输出彩色文本。colored 函数可以根据指定的颜色来格式化文本。
from termcolor import colored

# 调用了 time 模块中的 time() 函数,并将返回值(当前时间的时间戳,单位为秒)赋值给变量 start。这里记录下开始计算之前的时间点,以便后续计算总耗时。
start = time.time()
# 初始化变量 number 为 0。这个变量将用来累加从 0 到 99,999,999 的所有整数。
number = 0
for i in range(100000000):
	# 在循环体内,每次循环都将变量 i 的值累加到变量 number 上。这样,在循环结束时,number 将包含从 0 到 99,999,999 所有整数的和。
    number += i

print(colored("FINISHED", "green"))
# 再次调用 time.time() 获取当前时间戳,并与之前记录的开始时间戳(存储在变量 start 中)相减,得到执行计算所花费的总时间(单位为秒)。然后,使用 f-string 格式化字符串,将计算出的耗时插入到字符串中并打印出来。这样用户就可以看到程序执行所需的时间。
print(f"Ellapsed time: {time.time() - start} s")
在这里插入图片描述
在这里插入图片描述

这不是学术评估,但结果令人惊叹。与默认的 Python 解释器(大约需要 10 秒)相比,PyPy 仅用 0.22 秒就完成了执行。更令人惊讶的是,无需任何修改,Python 代码即可直接在 PyPy 上运行。而在同一台计算机上,等效的 C 语言实现需要 0.32 秒。PyPy 甚至超过了最快的 C 语言实现。

为什么 PyPy 这么快?

尽管代码看起来完全相同,但其执行方式却大相径庭。PyPy 提升执行速度的关键在于采用 “即时编译”(Just-In-Time Compilation),也就是 JIT 编译技术

C、C++、Swift、Haskell、Rust 等编程语言通常采用提前编译(AOT 编译)的方式。这意味着,使用这些语言编写的代码,在程序运行之前,编译器会将其源代码转换为特定计算机架构可执行的机器码。因此,当程序执行时,实际运行的是机器码,而非原始的源代码。

在这里插入图片描述
在这里插入图片描述

不同于 C 语言等上述语言,Python、JavaScript、PHP 等语言采用的是另一种方法 —— 解释器。与将源代码转换为机器码不同,解释过程中源代码保持不变。每次运行程序时,解释器都会逐行查看代码并执行。例如,每个 Web 浏览器都内置了 JavaScript 解释器。

在这里插入图片描述
在这里插入图片描述

PyPy 利用即时编译技术来执行 Python 代码,与传统解释器不同,它不会逐行运行代码,而是在程序执行前先将部分代码编译成机器码。即时编译结合了提前编译和解释的优点。如图所示,PyPy 采用的即时编译融合了这两种方法,通过提前编译提升性能,同时保持解释型语言的灵活性和跨平台可用性

在这里插入图片描述
在这里插入图片描述

AOT 优点:

  1. 在程序运行前进行编译,可以避免运行时的编译性能消耗和内存消耗。
  2. 程序在运行初期即可达到最高性能。
  3. 显著加快程序启动速度。

AOT 缺点:

  1. 程序运行前的编译增加了程序安装的时间。无运行时性能加成,不能根据程序运行情况做进一步的优化。
  2. 提前编译的内容保存会占用更多的外部存储空间。

JIT 优点:

  1. 在程序运行时,根据算法计算出热点代码,然后进行 JIT 实时编译,这种方式吞吐量高,有运行时性能加成,可以跑得更快,并可以做到动态生成代码等。
  2. 可以根据当前程序的运行情况生成最优的机器指令序列,从而提高程序的执行效率。
  3. 当程序需要支持动态链接时,JIT 是一个优先的选择。
  4. JIT 可以根据进程中内存的实际情况调整代码,从而更充分地利用内存资源。

JIT 缺点:

  1. 编译过程会占用运行时资源,这可能导致进程卡顿,影响用户体验
  2. 相对启动速度较慢,并需要一定时间和调用频率才能触发 JIT 的分层机制。
  3. 编译时间需要占用运行时间,并且某些代码的编译优化可能无法实现,因此我们需要考虑程序流畅性和编译时间的问题。
  4. 在编译准备和识别频繁使用的方法时,需要消耗一定的时间,这使得初始编译可能无法达到最高性能。因此,JIT 需要在运行时不断优化代码,以提高程序的执行效率。

PyPy 在我们的程序已经很快或者大部分运行时间都用于调用非 Python 库时,效果较差。然而,如果我们有一个运行缓慢的程序,其中大部分时间都花在执行 Python 代码和密集的计算上,PyPy 可以发挥奇效。

总结:编译型编程语言会将源代码提前转化为机器代码,而解释型编程语言则由解释器逐行运行。即时编译技术结合了提前编译和解释的优点,实现边运行边编译。JIT 与 AOT 的主要区别在于编译时间:JIT 在运行时编译,而 AOT 则在程序运行前进行编译。PyPy 采用即时编译技术,显著提高了 Python 代码的运行速度。即时编译不仅提升了程序执行效率,还保持了解释型语言的灵活性和跨平台可用性


📚️ 相关链接:

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2024-05-07,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

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

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

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档