LLVM、Parrot、JVM、PyPy + Python

15 投票
3 回答
8771 浏览
提问于 2025-04-16 13:50

在开发一些编程语言时,比如说 Python,使用一些优化技术和 LLVM 或 Parrot 会遇到什么问题呢?

PyPy、LLVM 和 Parrot 是开发通用平台的主要技术。
我把它们理解为:

  • PyPy - 是一个用来构建虚拟机的框架,里面有为 Python 优化的虚拟机。
    所以这算是一个比较通用的解决方案。整个过程可以分为以下几个步骤:
    1. 动态语言代码 ->
    2. PyPy 前端 ->
    3. PyPy 内部代码 - 字节码 ->
    4. PyPy 优化 ->
    5. 生成 PyPy 代码,然后:
      a. PyPy 后端用于某个虚拟机(比如 JVM)
      b. 一些工具包用来创建自己的虚拟机
      c. 处理/运行 PyPy 内部代码

我对这个过程理解得对吗?对于 Python 来说,有优化过的虚拟机吗?特别是默认情况下,PyPy 代码(步骤 5.c)有一个内置的优化虚拟机,这个虚拟机是为 Python 设计的,每种语言的处理都可以在这里停止并运行吗?

  • Parrot - 和 PyPy 很像,但没有步骤 5.a 和 5.b?它有一些内部改进,用于动态处理(Parrot 魔法饼干)。

ParrotPyPy 都是为了创建一个可以运行动态语言的平台,但 PyPy 想要更多 - 还想创建更多的虚拟机。
那么 PyPy 的意义在哪里呢?我们为什么需要创建更多的虚拟机?难道不应该像 Parrot 那样专注于一个虚拟机吗?因为无论是 PyPy 的内部字节码还是 Parrot 的字节码,都是在同一个代码层面上。我觉得把 PyPy 的字节码转换成用 PyPy 创建的新虚拟机的字节码并没有什么好处。

  • LLVM - 我觉得它和 PyPy 很相似,但没有虚拟机生成器。
    它是一个成熟、设计良好的环境,目标和 PyPy 类似(但没有虚拟机生成器),但它在低级结构和优化/即时编译技术方面做得很好。

我认为:LLVM 是通用的,而 ParrotPyPy 是专为动态语言设计的。在 PyPy 和 Parrot 中,引入一些复杂技术会更容易,因为它们的层次更高,像是一个复杂的编译器,可以更好地理解高级代码并生成更好的汇编代码(人类在合理的时间内无法编写),而 LLVM 则不一定能做到这一点。

问题:

  1. 我理解得对吗?有没有理由认为将某种动态语言移植到 LLVM 比移植到 Parrot 更好呢?

  2. 我没有看到在 Parrot 上开发 Python 的活动。是因为使用 Python 的 C 扩展在 Parrot 上无法工作吗?在 PyPy 上也是同样的问题。

  3. 为什么其他虚拟机不想转向 LLVM 或 Parrot?比如说 Ruby 转向 Parrot,CLR/JVM 转向 LLVM。对它们来说,转向更复杂的解决方案不是更好吗?LLVM 正在快速发展,并且有大公司在投资。

  4. 我知道问题可能出在重新编译的资源上,如果需要更改字节码,但这并不是强制性的 - 因为我们可以尝试将旧字节码移植到新字节码,而新的编译器会生成新的字节码(尽管 Java 仍然需要解释自己的字节码 - 这样前端可以检查并将其转换为新字节码)?

  5. 如果我们以某种方式将 Java/JVM/Scala 移植到 LLVM,链接 JVM 库会有什么问题?

  6. 如果我哪里错了,请纠正我。

补充说明:

=============

澄清一下

我想弄清楚这些软件是如何构成的,以及将它们移植到其他平台时会遇到什么问题。

3 个回答

7

主要原因是什么呢?因为虚拟机(VM)的设计还没有一个固定的标准,拥有多种不同目标和用途的虚拟机,可以让我们同时尝试多种不同的方法,而不是一个接一个地试。

像JVM、CLR、PyPy、Parrot、LLVM等,都是以不同的方式解决不同类型的问题。这就像Chrome、Firefox、Safari和IE各自使用自己的JavaScript引擎一样。

Unladen Swallow这个项目试图把LLVM应用到CPython上,但他们花在修复LLVM问题上的时间,比专注于Python特定问题的时间还要多。

Python-on-Parrot项目因为Perl 6和Python之间的语义差异,导致前端编译过程出现问题,所以未来在这方面的努力可能会使用PyPy的前端来针对Parrot虚拟机。

不同的虚拟机开发者当然会关注其他人的进展,但即使他们借鉴了好的想法,也会在此基础上进行改进,加入自己的特色。

11

你想实现什么呢?你的问题表达得有点混乱(我知道英语可能不是你的母语)。

LLVM和PyPy都是成熟且有用的项目,但目前它们之间的重叠不多。(曾经,PyPy可以生成LLVM字节码——这是一种静态编译到解释器的方式,而不是生成C代码,但这并没有带来太大的性能提升,现在也不再支持了。)

PyPy允许你用RPython编写一个解释器,并用这个解释器的描述来生成本地代码的解释器或即时编译器(JIT);而LLVM是一个用C++构建编译工具链的框架,也可以用来实现JIT。LLVM的优化器、代码生成和平台支持比PyPy要先进得多,但它不太适合构建动态语言的运行时(可以参考Unladen Swallow的回顾,里面有一些例子说明原因)。特别是,LLVM在收集和使用运行时反馈方面不如PyPy的基于跟踪的JIT有效,而这些反馈对于让动态语言表现良好是非常重要的。此外,LLVM的垃圾回收支持仍然有些原始,缺乏PyPy自动生成JIT的独特能力。

顺便提一下,有两个Java实现是基于LLVM的——J3/VMKitShark

你可以考虑观看上周斯坦福大学的PyPy讲座;它提供了一个关于PyPy工作原理的不错概述。Carl Friedrich Bolz的演示文稿也很好地概述了虚拟机实现的现状。

25

这个问题在StackOverflow上可能没人能回答,但我试着简单说一下。

首先,这三个项目解决了什么问题呢?

  1. pypy让你可以用高级语言来实现一个解释器,并且你可以免费获得一个生成的JIT(即时编译器)。这点很不错,因为这样你就不需要担心语言和平台之间的依赖问题。这也是为什么pypy-clr比IronPython快的原因。更多信息可以查看这里:http://codespeak.net/pypy/dist/pypy/doc/extradoc.html --> 这是一个为CLI/.NET提供高性能Python实现的项目,支持动态的JIT编译。

  2. llvm是一个为编译器提供的低级基础设施。它的基本思想是有一种“高级汇编语言”。所有的优化都是基于这种语言进行的。然后有很多工具可以帮助你构建编译器(无论是JIT还是AOT)。在llvm上实现动态语言是可行的,但比在pypy或parrot上需要更多的工作。例如,你不能免费获得垃圾回收(GC),虽然有一些GC可以和LLVM一起使用,具体可以参考这里:http://llvm.org/devmtg/2009-10/ --> vmkit视频)。目前也有一些尝试在llvm基础上构建更适合动态语言的平台:http://www.ffconsultancy.com/ocaml/hlvm/

  3. 我对parrot了解不多,但据我所知,他们想建立一个专门为动态语言(如perl、php、python等)设计的标准虚拟机。这里的问题和编译到JVM/CLR时一样,都是依赖不匹配,只是小得多。这个虚拟机仍然不知道你的语言的语义。根据我的理解,parrot在用户代码的执行上还是比较慢的。(http://confreaks.net/videos/118-elcamp2010-parrot

关于你的问题:

我说得对吗?把某些动态语言移植到llvm上比移植到parrot上更有理由吗?

这取决于付出的努力。自己构建一切并为自己量身定制最终会更快,但这需要付出很多努力。

我没有看到在Parrot上开发Python的活动。是因为使用Python的C扩展在Parrot上不工作吗?PyPy也有同样的问题。

目前针对parrot的开发(在这个阶段)不太可能比pypy有更多的好处。我不知道为什么其他人不这样做。

为什么其他虚拟机不想转向LLVM或parrot。例如,ruby转向parrot,CLR/JVM转向LLVM。对他们来说,转向更复杂的解决方案不是更好吗?LLVM正在快速发展,并且有大公司在投资。

这个问题包含很多内容。

  • 正如我所说,转向LLVM是很困难的,而parrot的速度也不快(如果我错了请纠正我)。
  • Ruby有Rubinius,它尝试在Ruby中做很多事情,并将JIT编译到llvm上(http://llvm.org/devmtg/2009-10/ --> 用LLVM加速Ruby)。
  • 在LLVM上有CLR/JVM的实现,但它们已经有非常成熟的实现,并且投入了大量资金。
  • LLVM并不是高级的。

我知道问题可能出在重新编译的资源上,如果需要更改字节码,但这并不是强制的——我们可以尝试将旧字节码移植到新字节码,而新的编译器会生成新的字节码(尽管Java仍然需要解释自己的字节码,以便前端可以检查并将其转换为新的字节码)?

我不知道这个问题是什么。

如果我们以某种方式将Java/JVM/Scala移植到LLVM,链接JVM库会有什么问题?

看看我上面提到的VMKit视频,看看他们取得了多大进展以及遇到了什么问题(以及他们是如何解决的)。

如果我哪里错了,请纠正我。

你写的很多内容是错误的,或者我根本不理解你的意思,但我提供的链接应该能让很多事情变得更清楚。


一些例子:

Clojure

创建者不想花所有的精力去实现自己的虚拟机和所有的库。那么该去哪里呢?由于Clojure是一种新语言,你可以通过限制很多动态特性来使其在像JVM这样的平台上运行得很好,而这些特性在Python或Ruby中是常见的。

Python

这种语言(Python)实际上无法更改以便在JVM/CLR上运行得很好。因此,在这些平台上实现Python不会带来巨大的速度提升。静态编译器也不太好用,因为没有很多静态保证。用C编写JIT会很快,但很难修改(参见psyco项目)。使用llvm的JIT可能可行,并且正在被Unladen Swallow项目探索(再次参考:http://llvm.org/devmtg/2009-10/ --> Unladen Swallow: Python on LLVM)。一些人想要在Python中实现Python,所以他们开始了pypy,他们的想法似乎运作得很好(见上文)。Parrot也可能可行,但我还没看到有人尝试过(欢迎尝试)。


关于一切:

我觉得你可能有些困惑,我能理解。慢慢来,阅读、倾听、观看你能找到的所有资料。不要给自己太大压力。这其中有很多部分,最终你会看到这些部分是如何结合在一起的,什么是有意义的。即使你知道很多,仍然有很多讨论可以进行。关于在哪里实现新语言或如何加速旧语言的问题有很多答案,如果你问三个人,你可能会得到三个不同的答案。

撰写回答