对于这种算法,Python与Java相比非常慢

我正在研究算法,并决定将Java程序从教科书移植到Python,因为我不喜欢Java开销,特别是对于小程序,以及作为练习。

算法本身非常简单,它只是以阵风的方式从arrays中取出所有三元组,并计算有多少三元组总和为零(例如:[ – 2,7,-5])

public static int count(int[] a) { int N = a.length; int cnt = 0; for (int i = 0; i < N; i++) { for (int j = i+1; j < N; j++) { for (int k = j+1; k < N; k++) { if (a[i] + a[j] + a[k] == 0) { cnt++; } } } } return cnt; } 

我把它移植到:

 def count(a): cnt = 0 ln = len(a) for i in xrange(0,ln): for j in xrange(i + 1,ln): for k in xrange(j + 1,ln): if a[i] + a[j] + a[k] == 0: cnt+=1 return cnt 

现在测量这些function正在采取:

 java : array of 2000 elements --> 3 seconds python : array of 2000 elements --> 2 minutes, 19 seconds UPDATE python (pypy) : array of 2000 elements --> 4 seconds ( :-) ) 

当然,这不是一个好的算法,它只是在这里和教科书中展示。 我以前用Java和Python做了一些编程,但是没有意识到这个巨大的差异。

问题归结为:如何克服这个问题? 进一步来说 :

  1. 这段代码是一个很好的端口,还是我错过了一些微不足道的东西?
  2. 是否切换到另一个运行时Jython,例如解决方案? 是否容易将我的代码库保存在eclipse中并只添加一个解释器(编译器?)? 或者转换到另一个解释器/编译器只会让事情稍好一点?

现在我在Windows 7上使用python 2.7.3和Java 1.7 32ibts。

我知道关于java / python性能的问题有类似的问题,但是对于python有不同的运行时环境的答案,目前对我没有帮助。

我想知道的是,如果这些运行时间中的一些可以缩小这个巨大的差距并值得探索吗?

更新:

我安装了pypy,现在差异很大……

更新2:

我注意到一些非常有趣的事情:这里的答案中的islice方法在’常规’python上更快,但在pypy上慢得多。 即便如此,无论在这个算法中使用常规循环还是islices,pypy仍然可以使用得更快

由于Bakuriu在一个备注运行时环境中注意到了很多事情,但是对于这个算法而言,运行时环境更快,对于任何算法而言都不一定更快……

尝试使用PyPy而不是CPython运行它。 它很可能会更快。

我也用C和PHP实现了这个function。 结果如下:

PHP :23.977946043015秒
Python :19.31秒

C :0.4秒
Java :0.42秒

我们正在寻找具有不同类型系统的语言。 PHP和Python是动态类型的,而C和Java是静态类型的。

因此,PHP和Python解释器花费大量时间猜测所使用的变量的类型,因此运行速度非常慢。 而在C和Java中,变量的类型(和数组的元素)是静态的,即整数,因此节省了猜测时间。 显然,从上面的数字可以看出,这个猜测时间太长了。

使用PyPY,猜测时间大大减少,因为PyPY使用Just In Time(JIT)编译。 这种方法非常适合猜测所用变量的类型,因此可以获得性能提升。

正如在你的开始post的评论中已经说过的那样,除了PyPy之外没有什么好方法可以让它更快。 您可以尝试使用islice,它会迭代“a”而不是制作新的列表或范围,这应该更快。

 from itertools import islice def count(a): cnt = 0 for x, i in enumerate(islice(a,0, None)): for y, j in enumerate(islice(a, x + 1, None)): for k in islice(a, y + x + 2, None): if i + j + k == 0: cnt+=1 return cnt