对于这种算法,Python与Java相比速度非常慢
我正在研究算法,并决定将教科书中的Java程序移植到Python中,因为我不喜欢Java开销,特别是对于小程序,并且作为练习 该算法本身非常简单,它只是以一种蛮力的方式从数组中取出所有三元组,并计算有多少三元组的总和为零(例如:[-2,7,-5]) 现在,仅测量这些功能需要:对于这种算法,Python与Java相比速度非常慢,java,python,performance,Java,Python,Performance,我正在研究算法,并决定将教科书中的Java程序移植到Python中,因为我不喜欢Java开销,特别是对于小程序,并且作为练习 该算法本身非常简单,它只是以一种蛮力的方式从数组中取出所有三元组,并计算有多少三元组的总和为零(例如:[-2,7,-5]) 现在,仅测量这些功能需要: java : array of 2000 elements --> 3 seconds python : array of 2000 elements --> 2 minutes, 19 seconds
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做过一些编程,但没有意识到这一巨大的差异
问题归结为:我们如何克服这一点?更具体地说:
正如Bakuriu在一篇评论中所指出的,运行时环境可能非常重要,但是对于这种算法来说运行时环境更快并不一定对任何算法都更快…尝试使用PyPy而不是CPython来运行它。它很可能会快得多。正如你在《开始》帖子的评论中所说的,没有什么好方法可以让它快得多(除了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
我还用C和PHP实现了这个函数。结果如下: PHP:23.977946043015秒
Python:19.31秒
C:0.4秒
Java:0.42秒
我们正在研究具有不同类型系统的语言。PHP和Python是动态类型的,而C和Java是静态类型的 因此,PHP和Python解释器花费大量时间猜测所用变量的类型,因此运行速度非常慢。而在C和Java中,变量的类型(以及数组的元素)是静态的,即整数,因此可以节省猜测时间。显然,从上面的数字可以看出,这个猜测时间太长了
使用PyPY,猜测时间大大减少,因为PyPY使用即时(JIT)编译。此方法非常擅长猜测所用变量的类型,因此可以获得性能提升。对于Python,请使用标准库中的itertools组合,它会将for循环移到C。这比python的Java开销要大:-2分21秒:慢1/48倍/joke>您在移植算法时使用了错误的方法-使用更具python风格的方法可能会快得多。在这种情况下,您可以使用slices、sum和一个生成器表达式来替换嵌套的for循环:
cnt=sum(1代表xrange(0,ln-3)中的x,如果不是sum(a[x:x+3]),
@l4mpi您在注释中编写的代码解决了一个更简单的问题。OP不是在寻找连续的元素。@Peteritertools。排列应该是相同的算法,按结果的模顺序排列。请考虑到PyPy仅在某些类型的算法上运行得更快。例如,如果您处理的是长整数运算,那么CPython会更快。无论如何,您应该从这个基准测试中推断出,JIT可以大大提高性能,而不是说CPython通常很慢。您可以尝试使用在CPython上运行您的算法,您可能会看到类似于PyPy的结果。(不幸的是,它不再被维护)。您自己进行过基准测试吗?在我的例子中,它的速度要慢很多(pypy:50秒,而不是2K元素数组的4秒),我用Python2.7.3(没有pypy)对它进行了基准测试,1.4秒对1.1秒用islice和一个比2000I小的测试列表,使用pypy时,我得到了2秒对1秒,但是使用pypy:0.1秒对0.5秒,所以慢了5倍,奇怪:在pypy中,这种方法比常规方法慢得多,但比常规python中的快得多…+1:答案不太清楚,但我喜欢不用写的基准测试:-)尝试从计算机科学的角度来看一些东西:顺便说一句,数组的大小是1000。-1:“因此,PHP和Python解释器花费大量时间猜测所用变量的类型,因此运行速度非常慢”-这显然是错误的和误导性的。Python不猜测任何对象的类型,每个对象都有一个已知的类型。诚然,部分开销是由于缺少编译时类型信息造成的(或跟踪JIT)阻止CPython获得静态类型语言通常的性能水平,它不会在任何地方“猜测类型”。事实上,PyPy之所以更快,是因为它对变量的类型进行了有根据的猜测!-1:“…但我喜欢不用编写的基准测试“-OTOH,其他人无法复制的基准测试结果(因为除了作者之外没有人拥有源代码)是毫无价值的。-1:这完全是胡说八道。类型无法猜测,因为数据没有固有的类型,这一切都是一样的。如果Python有
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 ( :-) )
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