python jit_全新模式的 Python JIT—— Pyston v2

几年前,我曾经参与过 Pyston的开发。Pyston 是 Dropbox 对 Python JIT 的又一次尝试。

和其他一些 Python JIT 尝试一样,Pyston 的第一次尝试也失败了。

不过现在 Pyston v2 将尝试一种新的方式。

以前的 JIT 方式

在介绍新的方式之前,先回顾一下已有的 JIT。具体来说,之前的 Python JIT都遵循着一种模式:把 Python 源码翻译成一种中间模式(字节码)

用栈式虚拟机或寄存器式虚拟机执行这些字节码

当一段代码执行很多次的时候,将这些代码编译成机器码,替换掉之前的字节码。从而节省速度

因此,JIT 对 Python 代码的提升,主要来自与用机器码替换掉字节码而节省的时间。

CPython 为什么慢?

CPython 慢已经是众所周知的事了,但 CPython 速度慢并仅仅是因为这一点。

CPython 速度慢还有几点来源:

漫长的分派过程:

如果剖析过 CPython 代码,不难发现在 CPython 中,哪怕一个最基本的加减法。在 CPython 中都要在主循环 PyEval_EvalFrameEx 中花费大量的时间。检查这个加减法的操作数能不能做运算,能不能原地处理,不能原地处理就要创建新的临时变量。

简单来说,就是不停的检测操作数的类型,然后看对应的类型中是否有对应的执行函数。如果A操作数中所有执行函数都检查完了,但还是没有可用的,那么再检测第二个操作数。如果两个操作数都有可用的执行函数,但一个是另一个的子类,那么应该先调用子类的函数。

总之,许多时间浪费在这种寻找真正的执行函数的路上了。

成员属性访问:

有些语言访问成员属性,a.b,本质上就是一个偏移量内存地址的访问。而 CPython 访问成员属性,本质上是在查询一个字典。同时由于 CPython 可以随意改变同一个成员名称的变量类型,比如可以先执行 a.b =foo,然后再执行 a.b() 。这时候这个成员属性已经不是之前的那个了,因此给查找带来了很大困难。

这一点可以通过内联缓存解决(inline caches)。

出路

之前的许多次 Python JIT 尝试,都在 JIT (即将部分代码转换成机器代码)和成员属性访问上取得了一些成功。但由于 Python 的动态性过强,已有的 Python JIT,要么在分派上节省的时间并不多,要么由于大规模重写运行时,带来了比较严重的兼容性问题。

Pyston v2 的思路是, 将 CPython 编译成 LLVM,在运行的时候,根据调用函数中参数的类型,比对被调用函数的参数类型,如果一致的话,就动态“指导”CPython 跳过某些分派,直接抵达对应的执行函数。

由于是在 CPython 的基础上动态修改 CPython 的运行时,所以并没有显著的兼容性问题。

目前这个计划刚刚重启,具体细节还在讨论中,现在的设想是直接以 Python 3.9 起步。如果能成功,那么将会是一个值得关注的新尝试。

这次我继续打算参与,如果其中的 JIT 涉及到与国产 CPU 的施配,我也会尝试支持。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值