10

只需在 python 和 C++ 中运行一个近乎空的 for 循环(如下所示),速度非常不同,python 慢了一百多倍。

a = 0
for i in xrange(large_const):
  a += 1
int a = 0;
for (int i = 0; i < large_const; i++)
  a += 1;

另外,我可以做些什么来优化python的速度?

(补充:我在这个问题的第一个版本中做了一个不好的例子,我并不是说 a=1 以便 C/C++ 编译器可以优化它,我的意思是循环本身消耗了大量资源(也许我应该以 a+=1 为例).. 我的意思是如何优化是,如果 for 循环就像 a += 1 那样简单,它怎么能以与 C/C++ 相似的速度运行?练习,我使用了 Numpy,所以我不能再使用 pypy(现在),是否有一些通用方法可以更快地生成循环(例如生成列表中的生成器)?)

4

4 回答 4

15

一个聪明的 C 编译器可能会通过识别最后a将始终为 1 来优化您的循环。Python 不能这样做,因为当迭代时xrange,它需要调用__next__对象xrange直到它引发StopIteration。python 在调用它之前无法知道是否__next__会产生副作用,因此无法优化循环。本段的要点是,优化 Python“编译器”比优化 C 编译器要困难得多,因为 python 是一种动态语言,并且需要编译器知道对象在某些情况下的行为方式。在 C 中,这要容易得多,因为 C 可以提前准确地知道每个对象的类型。

当然,除了编译器,python 还需要做更多的工作。在C中,您正在使用硬件指令中支持的操作来处理基本类型。在 python 中,解释器在software中一次一行地解释字节码。显然,这将比机器级指令花费更长的时间。并且数据模型(例如__next__一遍又一遍地调用)也可能导致许多C不需要做的函数调用。当然,python 这样做是为了使它比编译语言更灵活。

加速 python 代码的典型方法是使用库或内部函数,它们为低级编译代码提供高级接口。 scipy并且numpy是这种图书馆的优秀例子。您可以查看的其他内容pypy包括使用 JIT 编译器 - 您可能无法达到本机速度,但它可能会击败 Cpython(最常见的实现),或者使用 Cpython-API 在 C/fortran 中编写扩展, cython 或 f2py 用于代码的性能关键部分。

于 2013-06-03T14:41:47.510 回答
5

仅仅因为 Python 是一种更高级的语言,并且每次迭代都必须做更多不同的事情(比如获取锁、解析变量等)。

“如何优化”是一个非常模糊的问题。没有“通用”的方法来优化任何 Python 程序(Python 的开发人员已经完成了所有可能的工作)。您的特定示例可以这样优化:

a = 1

顺便说一句,这就是任何 C 编译器都会做的事情。

如果您的程序使用数字数据,那么 usingnumpy及其矢量化例程通常会给您带来很大的性能提升,因为它在纯 C 中执行所有操作(使用 C 循环,而不是 Python 循环),并且不必使用解释器锁定和所有这些东西。

于 2013-06-03T14:41:04.280 回答
0

随着你越来越抽象,速度会下降。最快的代码是直接编写的汇编代码。

阅读这个问题为什么 Python 程序通常比用 C 或 C++ 编写的等效程序慢?

于 2013-06-03T14:46:40.853 回答
0

Python(通常)是一种解释型语言,这意味着必须在运行时逐行读取脚本,并将其指令编译成可用的字节码。

C(通常)是一种编译语言,所以当你运行它时,你正在使用纯机器代码。

出于这个原因,Python 永远不会像 C 一样快。

编辑:事实上,python 在运行时编译 INTO C 代码,这就是你得到那些 .pyc 文件的原因。

于 2013-06-03T14:39:37.240 回答