【问题标题】:How can an implementation of a language in the same language be faster than the language?同一种语言的语言实现如何比该语言更快?
【发布时间】:2012-03-11 21:09:24
【问题描述】:

例如,如果我用 Java 制作一个 JVM,是否有可能使我实际制作的实现比我使用的原始实现更快 em> 来构建这个实现,即使我的实现是建立在原始实现之上的,甚至可能依赖于那个实现?

(令人困惑...)

看看PyPy。这是一个用 Python 制作的用于 Python 的 JIT 编译器。没关系,但它怎么能声称比它正在使用和依赖的 Python 的原始实现更快

【问题讨论】:

  • 我不知道 pyton,但是要在 java 中做一个 JVM,你需要用另一种语言(比如 C++)编写很多本机方法。
  • 对不起。我这样做只是为了考虑可能接受的最新答案。现在查看新答案,如果比我接受的好,否则我会重新接受以前的答案。

标签: python performance jvm pypy language-implementation


【解决方案1】:

PyPy 不是在 Python 中实现的 Python 解释器,它是在 RPython 中实现的 Python 解释器和编译器,这是 Python 的受限静态类型子集:

RPython 是 Python 的一个受限子集,适用于静态 分析。虽然有语言和一些东西的补充 可能会出人意料地起作用,这是一个粗略的限制列表 应该被考虑。请注意,有大量特殊情况 你会遇到的限制。

真正的速度差异来自这样一个事实,与将整个程序解释为字节码的 CPython 不同,PyPy 对 RPython 部分使用just-in-time (JIT) compilation(机器码)。

【讨论】:

    【解决方案2】:

    pypy 翻译过程在 CPython 上运行,但输出是一个 .c 文件列表(我上次检查时是 19 个文件),然后将其编译为二进制文件:pypy-c。在运行时 pypy-c 与 CPython 没有任何关系,这就是它可以更快的原因。

    【讨论】:

      【解决方案3】:

      我认为不可能为该语言的语言实现解释器(称为 A),然后在该语言的另一个现有解释器(称为 B)之上运行它并执行程序(称为P),并且让 P 在(A 在 B 上运行)上运行比 P 在 B 上运行更快。

      A 的每一个操作都必须通过 B 的至少一个操作来实现。所以即使 B 非常糟糕而 A 是最优的,A 在 B 上运行的事实意味着 B 的坏将放慢速度。

      可以在语言本身中为语言实现解释器 + JIT 编译器,其中 JIT 编译器在运行时生成一些其他更快的代码,并且让 P 运行(A 在 B 上运行)比 P 运行更快在 B 上。不是 JIT 编译的 P 的运行时部分会更慢(通常慢得多),但如果 JIT 编译器成功识别 P 的“热”部分并执行它们的速度比B 则整个系统可能会整体运行得更快。

      但这并不是很有趣。也可以使用该语言 (C) 为一种语言实现编译器,使用现有编译器 (D) 对其进行编译,并让新的编译器语言生成比原始编译器生成的代码更快的代码。我希望这不会吓到你;应该清楚的是,D 发出的代码的速度只会影响 C 的执行时间,而不影响其他用 C 编译的程序的执行时间。

      用它们编译的语言编写编译器已经有几十年的历史了(例如,GCC 是用 C 语言编写的),并且与我认为您要问的真正问题并不真正相关; JIT 也不是使用自身编译语言。在这两种情况下,底层执行都不是您正在考虑的语言;通常是机器码。

      但是,您的问题的来源是一种误解。 PyPy 的 Python 解释器实际上并未在 Python 中实现。 PyPy 项目有一个用 RPython 编写的 Python 解释器。 RPython 是 Python 的一个子集,选择它是为了可以有效地将其编译为机器代码;作为一门语言,RPython 更像是带有类型推断和缩进块而不是大括号的 Java。 PyPy 项目还有一个用 Python 编写的 RPython 编译器,并且能够(大部分)自动将 JIT 编译器添加到它编译的任何解释器。

      当您在生产环境中实际使用 PyPy 解释器时,您使用的是从 RPython 源代码编译的机器代码解释器,就像您使用 CPython 解释器时使用的是从 C 编译的机器代码解释器一样源代码。如果您在另一个 Python 解释器之上执行 PyPy 解释器(您可以这样做,因为有效的 RPython 代码也是有效的 Python 代码;但 不是 反过来),那么它的运行速度比 CPython 慢得多口译员。

      【讨论】:

      • 如果投反对票的人想告诉他们在其中发现的问题,我会努力解决。
      • 您的第一段不正确。在实践中,如果没有设计,就很难设计一个反例,但无论如何。
      • @Marcin 如果错了,我想了解为什么错了并修改答案。即使是人为的反例也会很有用。我强烈怀疑我的第一个陈述对于所有实际案例都是正确的,即使它在理论上并不总是正确的。
      • @Ben Marcin 是对的。解释器 A 可以优化程序 P,使得当解释器 B 解释(运行)这个优化版本的 P 时,避免 B 本身的所有次优部分(参与解释/运行原始程序 P)。超级做作的例子就是这样;解释器 A 有一个查找表,它将程序(当然是它们的有限子集)映射到它们的输出。如果程序 P 恰好出现在这个表中,那么解释器 A 会给出解释器 B 已经计算好的结果。这当然比 B 解释(运行)程序 P 本身要快得多。
      • @PiotrDobrogost 这不是很像 JIT 编译器的情况吗?底层执行并不是真正的解释器 B。它还需要将您的解释器特殊封装到您正在解释的程序中。但是,是的,我会接受它作为反例。我仍然认为,在 JVM 上实现 JVM,或者在 Python 中实现 Python,运行速度通常比基础(实际使用底层 JVM/Python,而不是通过使用编译忽略)运行速度通常是不可能的,尽管我不'没有证据。
      【解决方案4】:

      当然,这是可能的。您的 JVM 实现可以将 Java 字节码编译为优化的机器码。如果您的优化器比运行 Java 编译器的 JVM 实现中的优化器更复杂,那么最终结果可能会更快。

      在这种情况下,您可以在自己的源代码上运行您的 Java 编译器,并从那时起受益于更快的编译速度。

      您说 PyPy 是 Python 的 JIT 编译器(我自己并不熟悉)。如果是这种情况,那么它将 Python 程序转换为机器代码,然后运行机器代码。另一位发帖人说 PyPy 编译器作为独立的可执行文件运行,与 CPython 分开。但即使它要在 CPython 上运行,一旦你的程序被 JIT 编译为机器代码,并且编译的机器代码正在运行,编译器的性能就不再重要了。编译器的速度只对启动时间有影响。

      【讨论】:

        【解决方案5】:

        您对一种语言和该语言的执行装置感到困惑。

        PyPy 比 CPython 更快的原因之一是因为 PyPy 被编译成一个完全独立的本机可执行文件,并且不依赖于 CPython,也不在其中执行。

        尽管如此,如果更高级别的解释器使用更有效的执行策略,则用该语言编写的解释器可以超越一种语言的低效率实现,并托管在低效率的解释器中。

        【讨论】:

          猜你喜欢
          • 2011-05-07
          • 2011-03-01
          • 2014-11-04
          • 2011-01-04
          • 2012-12-29
          • 1970-01-01
          • 2017-09-19
          • 2010-10-11
          • 2017-06-06
          相关资源
          最近更新 更多