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

对于这种算法,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程序移植到Python中,因为我不喜欢Java开销,特别是对于小程序,并且作为练习

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

现在,仅测量这些功能需要:

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做过一些编程,但没有意识到这一巨大的差异

问题归结为:我们如何克服这一点?更具体地说:

  • 这段代码是一个好端口,还是我遗漏了一些琐碎的东西
  • 例如,切换到另一个运行时Jython是一种解决方案吗?在eclipse中保存代码库并只添加一个解释器(编译器)容易吗?或者切换到另一个解释器/编译器只会让事情稍微好一点
  • 现在我正在Windows7上使用Python2.7.3和Java1.7 32ibts

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

    我想知道的是,这些运行时中的一些是否可以弥补这一巨大差距,是否值得重新部署

    更新:

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

    更新2:

    我注意到了一些非常有趣的事情:这里的答案中的islice方法在“常规”python上更快,但在pypy上要慢得多。即使如此,pypy仍然保持了更快的使用速度,无论它在该算法中使用常规循环还是孤岛


    正如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不是在寻找连续的元素。@Peter
    itertools。排列应该是相同的算法,按结果的模顺序排列。请考虑到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