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

为什么Python看起来比C / C ++平均速度慢? 我学习了Python作为我的第一个编程语言,但我只是刚刚开始使用C,而且我已经觉得我可以看到明显的差异。

Python是一种比C更高级的语言,这意味着它会从你的内存中抽象出计算机的细节 – 内存pipe理,指针等等,并允许你用更接近人们思维的方式来编写程序。

确实,如果您只测量执行时间,C代码通常比Python代码快10到100倍。 但是,如果你还包括开发时间,Python往往会跳过C.对于许多项目来说,开发时间比运行时间性能要关键得多。 更长的开发时间直接转换成额外的成本,更less的function和更慢的上市时间。

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

其他解释型语言(如Java字节码和.NET字节码)的运行速度比Python快,因为标准分布包括JIT编译器 ,该JIT编译器在运行时将字节码编译为本地代码。 CPython之所以没有JIT编译器,是因为Python的dynamic特性使其很难编写。 正在进行的 工作是编写一个更快的Python运行时,所以你应该期望在将来降低性能差距,但是在标准的Python发行版中包含一个function强大的JIT编译器可能还需要一段时间。

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

有一件事情可以说Python会让Python慢​​下来,这是因为它是dynamictypes的,每个属性访问都有很多的查找。

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

关于dynamictypes,如果你知道你正在处理什么types的数据,可以做许多优化。 例如在Java或C中,如果你有一个整数的直接数组,那么最后的汇编代码就可以像索引i处的值一样简单,把它加到accumulator ,然后递增i

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

值得注意的是,诸如bigint(int 3,long 2,Python 2 x),list,set,dict等原始types是人们在Python中使用的很多。 这些对象的内置操作有很多已经被优化了。 例如,对于上面的例子,您只需调用sum(list)而不是使用累加器和索引。 坚持这些,用int / float / complex来处理一些数字,你通常不会遇到速度问题,如果你这样做的话,可能会有一个小的时间关键单元(例如SHA2摘要函数),你可以只需迁移到C(或Jython中的Java代码)即可。 事实是,当你编写C或C ++代码时,你将会浪费大量的时间来处理Python代码几秒钟或者几行内容。 我会说,除非你正在做一些像embedded式或实时编程这样的东西,而且买不起它,否则这种折衷总是值得的。

python和C之间的区别是解释(字节码)和编译(本地)语言之间的差别。 就个人而言,我并没有真正看到Python慢​​,它pipe理得很好。 如果你尝试在它的领域之外使用它,那当然会慢一些。 但是为此,您可以编写Python的C扩展,将时间关键型algorithm放在本机代码中,使其更快。

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

主要的成本是:缺less一个对应于本地整数的整数types(使所有的整数操作更加昂贵),缺less静态types(这使得parsing方法更加困难,并且意味着必须检查值的types在运行时),以及缺less取消装箱值(这减less了内存使用,并可以避免一个间接的水平)。

并不是说这些东西在Python中是不可能或不能提高效率的,但是select是为了方便程序员的方便性和灵活性,以及​​在运行速度方面的语言清洁。 其中一些成本可以通过巧妙的JIT编译来克服,但是Python提供的好处总是会带来一些代价的。

Python通常被实现为脚本语言。 这意味着它会通过一个解释器,这意味着它将dynamic代码转换为机器语言,而不是从一开始就使用机器语言来执行可执行文件。 因此,除了执行代码之外,还必须支付翻译代码的成本。 即使CPython编译为与机器语言更接近的字节码,因此也可以更快地进行翻译。 Python也带有一些非常有用的运行时特性,比如dynamicinput,但是即使在最有效的实现中也不能实现这样的function,而没有大量的运行时间成本。

如果你正在做像着色器这样的处理器密集型工作,Python比C ++慢200倍左右的情况并不罕见。 如果你使用CPython,那么这个时间可以缩短一半,但仍然没有那么快。 所有这些runtmie好东西来了一个价格。 有很多基准来展示这个, 这里是一个非常好的。 正如前面所承认的,基准是有缺陷的。 它们都是由用户提交的,他们尽力用自己select的语言编写高效的代码,但它给你一个很好的总体思路。

如果你关心效率,我build议你把两者混合在一起,那么你可以得到两全其美的好处。 我主要是一个C ++程序员,但是我认为很多人倾向于在C ++中编写太多普通的高级代码,这样做只是一个麻烦(编译时间只是一个例子)。 将脚本语言与像C / C ++这样更有效率的语言混合在一起是真正实现程序员效率(生产力)与处理效率的平衡的方法。

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

令人惊讶的是,与其他dynamic语言的同行相比,Python的速度有多快。 虽然这种方法经常被认为是有缺陷的,但请看“计算机语言基准游戏”,以查看类似algorithm的相对语言速度。

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

除了已经发布的答案之外,有一件事情是pythons能够在运行时改变你不能改变的东西,例如C.你可以随时添加成员函数到类中去。 另外,python的dynamic特性使得不可能说什么types的参数会被传递给一个函数,这反过来使得整个优化变得更加困难。

RPython似乎是解决优化问题的一种方法。

尽pipe如此,它可能不会接近C的性能来进行编号等等。

C和C ++编译为本地代码 – 也就是说,它们直接在CPU上运行。 Python是一种解释型语言,这意味着您编写的Python代码在成为可执行的机器代码之前必须经过许多抽象阶段。