Python3.13的JIT是如何实现的

去年圣诞节前,CPython的core dev向世界宣布了一条令人振奋的消息,即Python虚拟机可以以JIT的形式执行字节码。

什么是JIT

JIT(Just In Time)是一个老生常谈的话题了。通俗来讲,JIT是指虚拟机可以将IR(比如Python字节码)编译成机器能理解的机器码,从而加速程序运行。这里的Time应该理解成Runtime,也就是说在运行期间生成了机器码并执行的方式就算JIT,这区别于传统的先编译后执行的AOT方式。

在Python3.13中,虚拟机仍然会读取前端生成的字节码,但是不是解释执行,而是翻译成CPU能理解的机器码让CPU执行。由于是机器指令,所以程序的执行效率会比C语言代码快得多。

然而,CPython的JIT实现起来并不简单。由于CPython的字节码过于"动态",直接翻译成静态的机器码难度非常大。在本次PR的作者Brandt Bucher的演讲中,他总结了三点困难,一是去掉解释器架构(overhead)、二是静态编译优化的字节码(原文是trace,指一次运行中执行到的字节码)、三是映射成机器码(即reduce indirection)。

什么是微指令(UOP)

CPython的JIT不是一个PR就能实现的,它需要前面版本提供的微指令支持。其实在去年7月份,CPython就加入了微指令的概念。它是将基本的字节码再次拆分成粒度更细的原子操作 ,也就是微指令。举一个例子,当python程序执行到了字节码JUMP_BACKWARD,它会往回跳转到某个已经执行过的字节码。但是这个跳转指令也可以拆分成更详细的微指令。比如跳回当前trace的顶部,那它会被替换为JUMP_TO_TOP微指令。比如跳到当前trace外的其他地方,它会被替换为SAVE_IPEXIT_TRACE两个微指令。

虽然JUMP_BACKWARDSAVE_IP都是字节码,但是已经不是一个维度了。处于粒度更细的维度叫做Tire2字节码,反之是Tire1字节码。

什么是copy-and-patch

copy-and-patch是实现JIT的一种方式。它是一种通过指令模板的方式简化经常执行的Tire2字节码。所谓的指令模板就是一些预设的机器码,当解释器在第一次执行代码的时候会观察有哪些字节码是循环调用的,这样在后续执行中它们会被替换成预设的机器码以提升速度。

比如LOAD_FAST字节码对应的是这样的C代码------

我们把精髓提取出来做成模板(注意相似代码部分)------

然后再把这部分代码转换成机器码------

最后,再把这些机器码重新织入CPython中------

这样,在CPython中可以直接执行机器码了,远远快于原本的C语言代码。

实操

为了感受一下CPython的JIT,我租了一台Ubuntu22.04。

首先,需要安装LLVM,而且必须是LLVM-16。最快的方法是在GitHub上下载编译好的安装包。

ruby 复制代码
wget https://github.com/llvm/llvm-project/releases/download/llvmorg-16.0.4/clang+llvm-16.0.4-x86_64-linux-gnu-ubuntu-22.04.tar.xz

然后解压安装包,在目录bin内有现成的clang-16。将其配置成环境变量。

其次,准备一个bootstrap的Python。 因为CPython项目内有很多代码是靠Python脚本生成的,所以需要一个低版本的Python来生成这些代码。这里建议使用Python3.11以上的Python作为bootstrap Python,因为更低版本的Python有些脚本运行不了。

然后运行以下指令

go 复制代码
./configure --enable-experimental-jit
make
make install

这样,你就拥有了一个支持JIT的python。接下来下载pip------

arduino 复制代码
wget https://bootstrap.pypa.io/get-pip.py
python3.13 get-pip.py

用pip安装pyperformance,并跑测试用例------

arduino 复制代码
python3.13 -m pip install pyperformance
python3.13 -m pyperformance run -o py313-jit.json

同样用常规版本的Python3.13跑相同的测试用例,并比较它们------

vbnet 复制代码
python -m pyperformance compare py313.json py313-jit.json

Emmm,几乎都是变慢的。所以说运行速度并没有提升,就像Brandt Bucher说的,这个只是实验版本,如果效果不好的话完全可以在未来版本中删去这个功能。目前,也是在考虑不断优化提升这些微指令模板。

参考资料

Youtube链接:link.zhihu.com/?target=htt...

Github PR:link.zhihu.com/?target=htt...

pyperformance链接:link.zhihu.com/?target=htt...

相关推荐
Yan-英杰32 分钟前
百度搜索和文心智能体接入DeepSeek满血版——AI搜索的新纪元
图像处理·人工智能·python·深度学习·deepseek
weixin_307779132 小时前
Azure上基于OpenAI GPT-4模型验证行政区域数据的设计方案
数据仓库·python·云计算·aws
玩电脑的辣条哥3 小时前
Python如何播放本地音乐并在web页面播放
开发语言·前端·python
多想和从前一样5 小时前
Django 创建表时 “__str__ ”方法的使用
后端·python·django
小喵要摸鱼7 小时前
【Pytorch 库】自定义数据集相关的类
pytorch·python
bdawn7 小时前
深度集成DeepSeek大模型:WebSocket流式聊天实现
python·websocket·openai·api·实时聊天·deepseek大模型·流式输出
Jackson@ML7 小时前
Python数据可视化简介
开发语言·python·数据可视化
mosquito_lover17 小时前
怎么把pyqt界面做的像web一样漂亮
前端·python·pyqt
mengyoufengyu7 小时前
算法12-贪心算法
python·算法·贪心算法
T_Y99438 小时前
pythonrsa加密与sha256加密
python