为什么没有针对本地机器代码的python编译器?


25

据我了解,造成编译语言与python之间速度差异的原因是,第一个方法将代码一直编译到本机计算机的代码,而python编译为python字节码,由PVM解释。我看到这种方式python代码可以在多个操作系统上使用(至少在大多数情况下),但是我不明白,为什么没有额外的(和可选的)python编译器,其编译方式与传统编译器相同。这将留给程序员选择,这对他们来说更重要。本机上的多平台可执行性或性能。一般来说; 为什么没有可以同时编译和解释的语言?


4
还有就是。Haskell也可以像通过GHCI编译或解释的那样运行
toasted_flakes 2014年

C ++也有解释器。可能还有数种其他语言同时具有这两种实现。
2014年

2
实际上,通过选择IronPythong(ironpython.net)并使用“ ngen”(msdn.microsoft.com/de-de/library/6t9t5wcf%28v=vs.110%29.aspx)编译生成的IL代码,可以找到一种方法将Python编译为本机代码。并不是说我已经测试过该工具链。
Doc Brown

10
可以编写Python到本机的编译器。它们并不是很有趣,因为它们实际上并没有实质性地提高性能,除非它们实际实现的语言看起来像Python,但受到的限制更大。我之前在其他地方解释了原因。

Answers:


29

不会。Python和C ++之类的语言之间存在速度差异的原因是因为静态类型的语言为编译器提供了大量有关程序结构及其数据的信息,从而使程序可以优化计算和内存访问。因为C ++知道变量的类型为int,所以即使在程序运行之前,它也可以确定操作该变量的最佳方式。另一方面,在Python中,运行时直到解释器到达该行才知道变量中的值。这对于结构非常重要,因为在C ++中,编译器可以在编译过程中轻松分辨出结构的大小及其字段在内存中的每个位置。这使它在预测如何使用数据方面具有强大的功能,并可以根据这些预测进行优化。

要有效地编译Python之类的语言,您需要:

  1. 确保在程序执行期间数据结构是静态的。这是有问题的,因为Python具有eval和元类。两者都使得可以基于程序的输入来改变程序的结构。这是赋予Python如此强大的表达能力的一件事。
  2. 从源代码本身推断所有变量,结构和类的类型。尽管在某种程度上有可能,但是静态类型的系统和算法是如此复杂,几乎不可能以可用的方式实现。您可以为某种语言的子集执行此操作,但绝对不能为整个语言功能集执行此操作。

6
值得一提的,这确实让这个问题很难,但并非不可能。sbcl编译Common Lisp,它也是动态的,具有eval,以及其他许多特性,使编译器编写者感到沮丧。它没有达到gcc的水平,但是肯定比CPython的解释器快。
Daniel Gratzer

3
我说@jozefg有效编译。不只是编译。Python也有它的Cython编译器来生成本机代码。关键是那些编译器甚至无法完成静态类型语言的编译器可以进行的部分优化。当您比较性能时,请将其与已编译的C ++而不是解释的Python进行比较。
欣快2014年

2
好吧,实际上,您会对sbcl可以做什么感到惊讶。基准游戏显示它的运行速度与Java一样快,几乎与GHC一样快,并且在C的1到10倍之内。按任何标准,这都不算慢。是的,动态类型在某种程度上抑制了编译,但并不像您想象的那样多。
Daniel Gratzer 2014年

3
比较解释型python和编译型python的速度本身很有趣。停止说“使用C ++”。也许您已经有用Python编写的代码。也许代码更容易用python编写。谁在乎。我关心的是1.5倍的加速(无论它是什么)。那可以带来巨大的变化。
Thomas Eding

3
换句话说,如果要编译,请选择另一种为此调整的语言,例如C ++或Pascal。
Please_Dont_Bully_Me_SO_Lords

0

有两个概念可以帮助我们更好地理解为什么编译为本机代码的Python可能不如编译后的C或其他常用编译语言运行得那么快。它们被称为早期绑定和后期绑定。

首先,我不是Python专家,而我是无意中来到了此站点。但是我喜欢这个网站。

如此处的另一个答复中所述,C ++编译器可以对程序有很多了解,并可以决定对特定数据结构使用哪些操作。例如,如果需要将两个整数变量加在一起,则编译器知道它们是本地整数,例如32位宽,并且可以将它们与一条“ ADD”指令加在一起。因此,它将ADD指令编译为代码。它已锁定,并且在程序运行时无法更改。那是早期的约束力。

另一方面,在像Python这样的语言中,我们可以期望程序以复杂的方式将不同类型的数据组合在一起。现在,编译器不知道我们的2个变量是整数,浮点数,字符串还是列表。因此,它必须编译在运行时确定该信息的代码,并在程序运行时选择正确的操作。这是后期绑定,我们可以理解,在程序运行时进行额外的工作会对性能产生影响。这是保持这些选项以Python之类的语言开放所要付出的代价,但它提供了最大的运行时灵活性。


-4

我认为它与Python细节本身有关,这与您无法将C#编译为机器代码的原因相同。即使由于语言的性质,特定于语言的内容实际上也会使您的程序有错误。为什么不只是学习C语言呢?它比C ++容易得多,比Python稍先进,但仍然可以实现。


5
C#可以直接转到机器代码:通用中间语言:提前编译 -“与CLI兼容的执行环境还提供了对程序集进行提前编译(AOT)的选项,以通过删除而使其执行更快。在.NET Framework中,有一个称为本机映像生成器(NGEN)的特殊工具可以执行AOT。在Mono中,还可以选择执行AOT。
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.