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...

相关推荐
猫头虎40 分钟前
永久免费白嫖多个域名,一键托管Cloudflare,免费申请SSL加密证书,轻松建站、搭建线路伪装
服务器·开发语言·网络·数据库·python·网络协议·ssl
沙虫一号41 分钟前
线上python问题排查思路
后端·python
B站_计算机毕业设计之家2 小时前
深度学习:Yolo水果检测识别系统 深度学习算法 pyqt界面 训练集测试集 深度学习 数据库 大数据 (建议收藏)✅
数据库·人工智能·python·深度学习·算法·yolo·pyqt
闲人编程2 小时前
用Python分析你的Spotify/网易云音乐听歌数据
开发语言·python·ai·数据分析·spotify·网易云·codecapsule
“负拾捌”2 小时前
LangChain 中 ChatPromptTemplate 的几种使用方式
python·langchain·prompt
咋吃都不胖lyh3 小时前
小白零基础教程:安装 Conda + VSCode 配置 Python 开发环境
人工智能·python·conda
闲人编程4 小时前
构建一个短链接生成器服务(FastAPI + SQLite)
jvm·python·sqlite·fastapi·生成器·短链接·caodecapsule
杰瑞哥哥4 小时前
标准 Python 项目结构
开发语言·python
西部森林牧歌5 小时前
Arbess零基础学习 - 使用Arbess+GitLab实现Python项目构建/主机部署
python·ci/cd·gitlab·tiklab devops