为什么Python程序通常比用C或C++编写的等效程序慢?

Rie*_*ess 56 c c++ python performance programming-languages

为什么Python平均比C/C++慢?我学习了Python作为我的第一个编程语言,但我只是从C开始,我已经觉得我可以看到明显的区别.

Mar*_*ers 71

Python是一种比C语言更高级的语言,这意味着它可以从您的内容管理,指针等中抽象出计算机的细节,并允许您以更接近人类思考方式编写程序.

如果只测量执行时间,C代码通常比Python代码快10到100倍.但是,如果您还包括开发时间,Python通常会胜过C.对于许多项目,开发时间远比运行时性能更重要.更长的开发时间可直接转化为额外成本,更少功能和更慢的上市时间.

内部Python代码执行速度较慢的原因是因为代码在运行时被解释而不是在编译时被编译为本机代码.

其他解释性语言(如Java字节码和.NET字节码)运行速度比Python快,因为标准发行版包含一个JIT编译器,可在运行时将字节码编译为本机代码.CPython之所以没有JIT编译器的原因是因为Python的动态特性使得编写它变得困难.有工作进展情况写一个更快的Python运行,所以你应该期望的性能差距在今后可以减少,但它可能会需要一段时间Python标准版包括一个强大的JIT编译器前.

  • 要迂腐:Python通常不会在编译时编译为*native*代码.仍然必须解释Python字节码. (41认同)
  • 你还没有真正解释为什么Python实现往往会如此渴望CPU.您可以抽象以上所有内容,而不会在运行时产生太多成本; 它是吞噬所有CPU的极其动态的特性:所有这些属性查找/方法调度相加,甚至给JIT带来相当困难的时间 - 而Python通常在没有JIT的情况下使用. (18认同)
  • Python*是*编译的. (4认同)
  • 我真的很好奇你所说的“是因为Python的动态特性使得编写Python变得很困难”。`` 你所说的动态是什么意思? (3认同)
  • 回想起来,我认为值得注意的是全局解释器锁以及Python中所有对象都是堆分配对象的方式,甚至是一个简单的整数.在没有涉及具体实现细节的情况下,除了更高级别的抽象之外,这些类型的东西可能在很大程度上取决于性能.也就是说,我仍然认为大多数应用程序应该主要用Python之类的脚本语言编写.正如Knuth所说的过早优化,只有大多数应用程序的一小部分实际上对性能非常关键. (2认同)

L̲̳*_*̲̳̳ 42

CPython特别慢,因为它没有Just in Time优化器(因为它是参考实现,并且在某些情况下选择简单性而不是性能).Unladen Swallow是一个将LLVM支持的JIT添加到CPython中的项目,并实现了大规模的加速.Jython和IronPython可能比CPython快得多,并且它们得到了大量优化的虚拟机(JVM和.NET CLR)的支持.

然而,有一件事情可能会让Python变慢,它是动态类型的,并且每个属性访问都有大量的查找.

例如,调用f对象A将导致可能的查找__dict__,调用 __getattr__等,然后最终调用__call__可调用对象f.

关于动态类型,如果您知道要处理的数据类型,可以进行许多优化.例如,在Java或C中,如果您想要求和的直数组,则最终的汇编代码可以像在索引处获取值i,将其添加到accumulator,然后递增一样简单i.

在Python中,很难使代码达到最佳状态.假设您有一个包含ints 的列表子类对象.在添加任何内容之前,Python必须调用list.__getitem__(i),然后通过调用将其添加到"累加器" accumulator.__add__(n),然后重复.这里可以发生大量的替代查找,因为另一个线程可能已经改变了例如__getitem__方法,列表实例的dict或类的dict,在add或getitem的调用之间.即使在本地命名空间中找到累加器和列表(以及您正在使用的任何变量)也会导致dict查找.当使用任何用户定义的对象时,同样的开销也适用,尽管对于某些内置类型,它有所缓解.

值得注意的是,bigint(Python 3中的int,Python 2.x中的long),list,set,dict等原始类型是人们在Python中使用的很多东西.这些对象上有大量内置操作已经足够优化.例如,对于上面的示例,您只需调用sum(list)而不是使用累加器和索引.坚持这些,以及使用int/float/complex进行一些数字运算,你通常不会遇到速度问题,如果你这样做,可能会有一个小的时间关键单元(例如SHA2摘要函数),你可以简单地转到C(或Java代码,在Jython中).事实是,当你编写C或C++代码时,你会浪费很多在几秒钟/几行Python代码中你可以做的事情.我会说这种权衡总是值得的,除非你正在做一些像嵌入式或实时编程这样的东西并且买不起它.


小智 16

编译与解释在这里并不重要:Python 是经过编译的,对于任何非平凡的程序来说,它只是运行成本的一小部分.

主要成本是:缺少对应于本机整数的整数类型(使所有整数运算更加昂贵),缺少静态类型(这使得方法的解决更加困难,并且意味着必须检查值的类型在运行时),并且缺少未装箱的值(这会减少内存使用量,并且可以避免间接级别).

并不是说这些东西中的任何一个都不可能或者不能在Python中更高效,但是已经选择了程序员的方便性和灵活性,以及​​语言清洁度超过运行时速度.聪明的JIT编译可以克服其中一些成本,但Python提供的好处总是需要付出一些代价.

  • 比公认的答案更好的答案,尽管重要的是要注意 python 并不总是被编译。这才是真正的执行。根据我的经验,它经常被解释。 (2认同)

Fem*_*ref 9

python和C之间的区别在于解释(字节码)和编译(到本机)语言之间的通常差异.就个人而言,我并不认为python很慢,它管理得很好.如果你试图在它的领域之外使用它,当然,它会更慢.但是为此,你可以为python编写C扩展,它将时间关键算法放在本机代码中,使其更快.

  • python编译为字节码,然后被解释.它也可以编译成机器代码,所以从本质上讲,我们都不是正确的. (4认同)
  • S /这/它.解释与编译意味着**在可优化性方面没有**.可以解释或编译JVM和C. 在任何一种情况下都可以应用不同的优化(自适应优化与编译时间+ LTO) (2认同)
  • 除了不完全正确之外,这个答案并没有谈到真正的问题,@ Longpoke在他的回答中解释得相当好. (2认同)

daw*_*awg 5

将 C/C++ 与 Python 进行比较并不是一个公平的比较。就像将 F1 赛车与多用途卡车进行比较。

令人惊讶的是,与其他动态语言的同行相比,Python 的速度有多快。虽然该方法通常被认为有缺陷,但请查看计算机语言基准游戏以了解类似算法的相对语言速度。

与 Perl、Ruby 和 C# 的比较更加“公平”

  • 我更喜欢使用兰博基尼在 5 个街区外超速工作(非内存安全语言)与遵守速度限制的街车(内存安全语言)的比喻。:) (5认同)
  • C 对我来说更像是一辆火箭车——如果你想直线行驶并且附近没有任何东西可以撞到,那就太好了,否则就没有那么多了! (5认同)

sti*_*472 5

Python 通常作为脚本语言实现。这意味着它通过一个解释器,这意味着它可以将代码即时翻译成机器语言,而不是从一开始就让可执行文件全部使用机器语言。因此,除了执行代码之外,它还必须支付翻译代码的成本。即使对于 CPython 也是如此,即使它编译为更接近机器语言的字节码,因此可以更快地翻译。Python 还带来了一些非常有用的运行时特性,比如动态类型,但即使在没有大量运行时成本的最有效的实现上,这些东西通常也无法实现。

如果您正在执行诸如编写着色器之类的处理器密集型工作,那么 Python 比 C++ 慢 200 倍左右的情况并不少见。如果您使用 CPython,那段时间可以减少一半,但仍然远远不够快。所有这些小东西都是有代价的。有很多基准可以证明这一点,这里有一个特别好的基准。正如首页所承认的,这些基准是有缺陷的。它们都是由用户提交的,他们尽最大努力用他们选择的语言编写高效的代码,但它为您提供了一个很好的总体思路。

如果您关心效率,我建议您尝试将两者混合在一起:这样您就可以两全其美。我主要是一名 C++ 程序员,但我认为很多人倾向于在 C++ 中编写太多普通的高级代码,而这样做很麻烦(编译时间只是一个例子)。将脚本语言与像 C/C++ 这样更接近金属的高效语言混合在一起,确实是平衡程序员效率(生产力)和处理效率的方法。