English 中文(简体)
My python方案的执行速度快于我对同一方案的java版本。 什么?
原标题:
  • 时间:2009-05-27 22:48:42
  •  标签:

<>Update: 2009-05-29

感谢所有建议和建议。 I利用你的建议,使我的生产法平均执行速度比我几天前的最佳结果快2.5倍。 最后,我能够使支尔瓦法典成为最快的。

经验教训:

  • 我下面的示范守则表明,增加了原始内ts,但生产法实际上储存了胎体。 当我更正时, p执行时间从2.8秒到9.6。 因此,在集束物体时, j鱼实际上较快。

  • 但它没有停止。 我一直在执行 j计划如下:

    java -Xmx1024m 速度

但是,如果你确定最初的肥皂面积如下,就会大大改善:

java -Xms1024m -Xmx1024m SpeedTest

这一简单变化使执行时间减少了50%以上。 因此,我的快速试验的最终结果为9.6秒。 Java 6.5秒。

www.un.org/Depts/DGACM/index_spanish.htm

我有以下文字:

import time
import sys

def main(args):    
    iterations = 10000000
    counts = set()
    startTime = time.time();    
    for i in range(0, iterations):
        counts.add(i)
    totalTime = time.time() - startTime
    print  total time = ,totalTime
    print len(counts)

if __name__ == "__main__":
    main(sys.argv)

它在我的机器上执行了大约3.3秒,但我希望使其更快,因此我决定在 j进行规划。 我假定,由于将java汇编成册,而且一般认为比平时快,我会看到一些大的退款。

这里是《 j法》:

import java.util.*;
class SpeedTest
{    
    public static void main(String[] args)
    {        
        long startTime;
        long totalTime;
        int iterations = 10000000;
        HashSet counts = new HashSet((2*iterations), 0.75f);

        startTime = System.currentTimeMillis();
        for(int i=0; i<iterations; i++)
        {
            counts.add(i);
        }
        totalTime = System.currentTimeMillis() - startTime;
        System.out.println("TOTAL TIME = "+( totalTime/1000f) );
        System.out.println(counts.size());
    }
}

因此,这一 j法基本上与 p法相同。 但它在8.3秒而不是3.3秒中执行。

我从真正的世界实例中提取了这一简单的例子,以简化事情。 关键因素是,我(制定或草原)最终有许多成员,如上。

我的问题是:

  1. 如何比我的 j瓦执行工作更快地实施我的 p?

  2. 是否有比 has(java)更好的数据结构来进行独特的收集?

  3. 如何使 p执行工作更快?

  4. 怎样才能更快地实施 j。

最新资料:

感谢迄今作出贡献的所有人。 请让我补充一些细节。

我没有列入我的生产法典,因为它非常复杂。 这将产生许多分歧。 以上所述情况最简化。 顺便说一句,“java”的呼声似乎比“Python”的增加要慢得多。

《生产法》的实施也比 p版低2.5-3倍。

我对暖气或开立的间接费用不感到关切。 我只是想把法典从我的开始时间到我的全时。 请不要与你的律师讨论其他事项。

我以足够的桶子开始洗.,以便它永远不必再洗。 (我将永远知道收集的内容最终将包含多少内容。) 我可以认为,我本来应该先把它交给它。 但是,如果你尝试,你就会看到执行时间不会受到严重影响。

我为那些贪 cur的人定了Xmx1024m(我的机器有4GB ram)。

我正在使用java版本:Java(TM) SE Runtime Environment(build 1.6.0_13-b03)。

在我制作的版本中,我存放了一辆拖拉机(2-15个char子),因此我不能使用原始材料,尽管这是一个有趣的例子。

我已多次执行该守则。 我非常相信, p法比 j法高2.5至3倍。

问题回答

我怀疑,这就是说,斯图尔将自己作为它的 has,并且直接使用固定用途。 http://svn.python.org/view/python/trunk/Objects/dictobject.c?revision=72958&view=markup”rel=“nofollow noreferer”>source/a>:

This isn t necessarily bad! To the contrary, in a table of size 2**i, taking the low-order i bits as the initial table index is extremely fast, and there are no collisions at all for dicts indexed by a contiguous range of ints. The same is approximately true when keys are "consecutive" strings. So this gives better-than-random behavior in common cases, and that s very desirable.

这一缩微标值在某种程度上是沙捞越的最佳案例,因为它造成了完全零散的 collision碰撞。 而如果Javas HashSet正在收回它必须从事额外工作的钥匙,并且由于碰撞而使行为更加恶化。

如果你在临时变数中储存范围(电池),则随机。 整整整整整整整整整整整整整整整整整整整整整整整整整整整整整整整整整整整整整整整整整整整整整整整整整整整整整整整整整整整整整整整整整整整整整整整整整整整整整整整整整整整整整整整整整整整整整整整整整整整整整整整整整整整整整整整整整整整整整整整整整整整整整整整整整整整整整整整整整整整整整整整整整整整整整整整整整整整整整整整整整整整整整整整整整整整整整整整整整整整整整整整整整整整整整整整整整整整整整整整整整整整整整整整整整整整整整整整整整整整整整整整整整整整整整整整整整整整整整整整整整整整整整整整整整整整整整整整

另一种可能的解释是,在C部法典中,沙尔赫语是在当地实施的,而 Java的哈希特语则在 Java里实施。 因此,在沙尔的电梯本来应该更快得多。

总的来说,我的经验是,尽管 j是一种“低级”语言,但 p方案的实施速度比 j方案快。 顺便提一句,两种语文均按代号汇编成册(根据这些卷宗——你可以认为这些语文是同类档案)。 两种语言都是用虚拟打字机解释的密码。

您希望,例如,a.b, python会放缓。 在java,a.b将溶入参考。 另一方面,Zar必须做一次或多次洗衣检查:检查当地范围、检查模块范围、检查全球范围、检查建筑。

另一方面,在某些业务中,如制造物体(如你可能的话,是主角)和序列化,java臭名昭著。

总之,没有简单的答案。 我预计,对于所有法典实例来说,这两种语言都会更快。

Correction:数人已经指出,在制造物体时,java是 bad。 因此,在你的例子中,它有别的东西。 或许可以把昂贵的、或许是平常的缺省洗.算作自动箱子,在这种情况下会更好。 在我的实际经验中,当我把java法典改写到晚上时,我总是看到业绩的提高,但这可能是由于语言的缘故,因为语言的改写一般会导致业绩的改善。

我愿驳斥我在答复中看到的两条神话:

Java的汇编是,是的,是按字母顺序排列的,但最终是在大多数运行环境中按本地编码编制。 说C的人必然要更快地掌握整个故事,我可以说,由于JIT编纂者能够使机器规格最佳化,因此,通过编造的语文必然要更快。

可能产生差异的一些事情是:

  • Python s hash tables and sets are the most heavily optimized objects in Python, and Python s hash function is designed to return similar results for similar inputs: hashing an integer just returns the integer, guaranteeing that you will NEVER see a collision in a hash table of consecutive integers in Python.
  • A secondary effect of the above is that the Python code will have high locality of reference as you ll be accessing the hash table in sequence.
  • Java does some fancy boxing and unboxing of integers when you add them to collections. On the bonus side, this makes arithmetic way faster in Java than Python (as long as you stay away from bignums) but on the downside it means more allocations than you re used to.

www.un.org/Depts/DGACM/index_spanish.htm Edit:根据分配模式,树苗对实际使用来说可能更快。 我的下列评论仅涉及这一简化方案。 然而,我认为这不会带来巨大变化。 真正的问题存在于其他地方。

这里有几个人建议用TreeSet替换HashSet。对我来说,这听起来非常奇怪,因为没有一种数据结构的插入时间是O(log n)比预先分配足够的存储所有元素的桶的O(1)结构更快。

这里有一些基准:

import java.util.*;
class SpeedTest
{    
    public static void main(String[] args)
    {        
        long startTime;
        long totalTime;
        int iterations = 10000000;
        Set counts;

        System.out.println("HashSet:");
        counts = new HashSet((2*iterations), 0.75f);
        startTime = System.currentTimeMillis();
        for(int i=0; i<iterations; i++) {
            counts.add(i);
        }
        totalTime = System.currentTimeMillis() - startTime;
        System.out.println("TOTAL TIME = "+( totalTime/1000f) );
        System.out.println(counts.size());

        counts.clear();

        System.out.println("TreeSet:");
        counts = new TreeSet();
        startTime = System.currentTimeMillis();
        for(int i=0; i<iterations; i++) {
            counts.add(i);
        }
        totalTime = System.currentTimeMillis() - startTime;
        System.out.println("TOTAL TIME = "+( totalTime/1000f) );
        System.out.println(counts.size());
    }
}

我的机器是:

$ java -Xmx1024M SpeedTest
HashSet:
TOTAL TIME = 4.436
10000000
TreeSet:
TOTAL TIME = 8.163
10000000

一些人还争辩说,箱子 is不是一种绩效问题,而设定标语是费用不高的。 固然物体的制造速度快,但肯定不会像原始材料一样快:

import java.util.*;
class SpeedTest2
{    
    public static void main(String[] args)
    {        
        long startTime;
        long totalTime;
        int iterations = 10000000;

        System.out.println("primitives:");
        startTime = System.currentTimeMillis();
        int[] primitive = new int[iterations];
        for (int i = 0; i < iterations; i++) {
            primitive[i] = i;
        }
        totalTime = System.currentTimeMillis() - startTime;
        System.out.println("TOTAL TIME = "+( totalTime/1000f) );

        System.out.println("primitives:");
        startTime = System.currentTimeMillis();
        Integer[] boxed = new Integer[iterations];
        for (int i = 0; i < iterations; i++) {
            boxed[i] = i;
        }
        totalTime = System.currentTimeMillis() - startTime;
        System.out.println("TOTAL TIME = "+( totalTime/1000f) );
    }
}

结果:

$ java -Xmx1024M SpeedTest2
primitives:
TOTAL TIME = 0.058
primitives:
TOTAL TIME = 1.402

此外,由于制造大量物品,垃圾收集器增加了间接费用。 当你开始忘掉数以千万计的活物体时,这一点就变得很重要。

我认为,这样的基准毫无意义。 我没有解决像试验案例这样的问题。 它并不令人可怕。

我非常希望看到利用NumPy和JAMA找到有意义的线性黄色解决办法。 Maybe 我试图这样做,并报告结果。

I m 不太熟悉python,但我确实知道HashSet 可能含有原始缩略语,如你说counts.add(i)。 正在把自动箱装成<代码>新 Integer(i)。 这很可能是你的问题。

如果出于某种原因,你确实需要一套0到某些大纳米之间的分类,那么,它很可能被宣布为一种 b子,即新的 b子。 然后,你可以穿透所装的阵列和标记项目,而不必承担制造 n子的费用。 如果你想继续使用第8号大体,并直接使用个别轨道。 或许是BigInteger。

EDIT

请停止为我的回答投赞成票。它是错误的。

EDIT

毫无疑问,它是错误的。 如果我回答问题,把这套住房与N Integers混为一谈,我就会获得类似的业绩。 如果我把休息内容改为:

    Integer[] ints = new Integer[N];
    for (int i = 0; i < N; ++i) {
        ints[i] = i;
    }

之后只有2秒。 如果你根本不储存Integer,它就花费不到200米。 拨款1 000 000 000美元 愤怒物体确实需要一定时间,但看起来像大多数时间一样在哈希特行动区内使用。

在此,我要集中谈谈若干问题。

首先,如果它只是执行一次方案,它是否需要另外几秒?

第二,这只是一个缩影。 微观基准对于比较业绩是毫无意义的。

启动有几个问题。

贾瓦的运行时间比沙里花得更长,需要从磁盘上装载,并且需要更多的记忆,如果你正在打捞,这种记忆可能很重要。

如果您有打下<代码>-Xms>,那么你只能管理GC,以便转播。 从一开始,肥料也出现适当规模。

确实, Java开始解释,然后汇编。 大约1 500个供太阳客户使用的频率[C1]热点和10 000个服务器[C2]。 服务器热点将最终给你更好的业绩,但会获得更多的记忆。 我们可能看到用户热电站使用服务器,以达到两个世界的最佳标准。 然而,这通常不应是一个二者的问题。

www.un.org/Depts/DGACM/index_spanish.htm 最重要的是,你可能会制造两个物体。 就大多数法典而言,你不会为这种执行的比例制造这些微小物体。 树木 点数可能更好,点数为6u14,和谐甚至更好。

也许可以通过在参考文献中储存小的喷雾器胜出,而不是实际上有物体。 这无疑是一种良好的选择。

存在许多基准的问题,就是你正在用一种方法混合许多不同的法典。 请不要写一下你所关心的那种法典吗? 因此,你为什么试图进行业绩测试,而这种测试与你实际上希望迅速运行的守则不同?

改进数据结构: 诸如<条码>BitSet等一些内容似乎具有意义(尽管如此,这可能会或不会影响业绩)。

你们需要多驾车,以获得“how快”的真正想法。 联合核查机制启动时间[一个]是 Java版单一运行时间。

你还重新创建了一个具有大量初步能力的哈希斯特,这意味着将利用许多现有位置来创建支持哈希姆博,与你创建一套基本文件时的沙尔格不同。 很难说这是否会阻碍,因为正如你的哈希特种植一样,它必须重新定位所储存的物体。

你们是否使用悬挂守卫国旗? 否则,你就可以检验业绩。 (在进行试验之前,你还必须热情地放弃。)

另外,你可能希望使用<代码>TreeSet<Integer>。 Hash 从长远来看,一套办法将比较缓慢。

你们是谁? 我希望这是最新的。

http://www.ohchr.org。

当我说使用TreeSet时,我是指一般情况,而不是针对这个基准测试。TreeSet可以处理对象非均匀散列的现实问题。如果在HashSet中有太多对象在同一个容器中,你的性能将大约为O(n)。

如果你真的想要在一套套房中储存原始类型,并做繁重的工作,就会在 Java开你自己的套头。 普通班级不足以进行科学计算。

正如Ants Aasma提到的那样,斯堪的列斯 has洗并直接使用ger。 Java创建了一个Integer物体(auto Box,然后将其投向一个目标(在你执行过程中)。 该物体也必须被 ha灭,以便用于一 set。

比较:

<Java

import java.util.HashSet;
class SpeedTest
{ 
  public static class Element {
    private int m_i;
    public Element(int i) {
      m_i = i;
    }
  }

  public static void main(String[] args)
  {        
    long startTime;
    long totalTime;
    int iterations = 1000000;
    HashSet<Element> counts = new HashSet<Element>((int)(2*iterations), 0.75f);

    startTime = System.currentTimeMillis();
    for(int i=0; i<iterations; ++i)
    {
      counts.add(new Element(i));
    }
    totalTime = System.currentTimeMillis() - startTime;
    System.out.println("TOTAL TIME = "+( totalTime/1000f) );
    System.out.println(counts.size());
  }
}

成果:

$java SpeedTest
TOTAL TIME = 3.028
1000000

$java -Xmx1G -Xms1G SpeedTest
TOTAL TIME = 0.578
1000000

<>Python

#!/usr/bin/python
import time
import sys

class Element(object):
  def __init__(self, i):
    self.num = i

def main(args):    
    iterations = 1000000
    counts = set()
    startTime = time.time();    
    for i in range(0, iterations):
        counts.add(Element(i))
    totalTime = time.time() - startTime
    print  total time = ,totalTime
    print len(counts)


if __name__ == "__main__":
  main(sys.argv)

成果:

$./speedtest.py 
total time = 20.6943161488
1000000

p子的生长速度比 j瓦快?

你们以多少记忆开始核查机制? 它取决于吗? 在我管理核查和核查机制时,有1吉奥拉办事处。

$ java -Xmx1024M -Xms1024M -classpath . SpeedTest 
TOTAL TIME = 5.682
10000000
$ python speedtest.py 
total time = 4.48310899734
10000000

如果我使用更少的内存运行JVM,它会花费更长的时间……相当长的时间。

$ java -Xmx768M -Xms768M -classpath . SpeedTest 
TOTAL TIME = 6.706
10000000
$ java -Xmx600M -Xms600M -classpath . SpeedTest 
TOTAL TIME = 14.086
10000000

我认为,是这一特定情况下的业绩瓶颈。 如果将改为LinkedList ,则该方案将大大加快。

最后,我们注意到, Java方案最初是解释的,只有那些被称作多次的方法汇编。 因此,你也许会把沙夫与贾瓦语译员而不是汇编者进行比较。

这里的黑暗中只是一个tab子,但灰色的一些优化使 Java可能n:

  • The range() call in Python is creating all 10000000 integer objects at once, in optimized C code. Java must create an Integer object each iteration, which may be slower.
  • In Python, ints are immutable, so you can just store a reference to a global "42", for example, rather than allocating a slot for the object. I m not sure how Java boxed Integer objects compare.
  • Many of the built-in Python algorithms and data structures are rather heavily optimized for special cases. For instance, the hash function for integers is, simply the identity function. If Java is using a more "clever" hash function, this could slow things down quite a bit. If most of your time is spent in data structure code, I wouldn t be surprised at all to see Python beat Java given the amount of effort that has been spent over the years hand-tuning the Python C implementation.

更快的沙捞越量变化。

#!/usr/bin/python
import time
import sys

import psyco                 #<<<<  
psyco.full()

class Element(object):
    __slots__=["num"]        #<<<<
    def __init__(self, i):
        self.num = i

def main(args):    
    iterations = 1000000
    counts = set()
    startTime = time.time();
    for i in xrange(0, iterations):
        counts.add(Element(i))
    totalTime = time.time() - startTime
    print  total time = ,totalTime
    print len(counts)

if __name__ == "__main__":
  main(sys.argv)

以前

(env)~$ python speedTest.py
total time = 8.82906794548
1000000

之后

(env)~$ python speedTest.py
total time = 2.44039201736
1000000

如今,一些老的che和......

#!/usr/bin/python
import time
import sys
import psyco

psyco.full()

class Element(object):
    __slots__=["num"]
    def __init__(self, i):
        self.num = i

def main(args):    
    iterations = 1000000
    counts = set()
    elements = [Element(i) for i in range(0, iterations)]
    startTime = time.time();
    for e in elements:
        counts.add(e)
    totalTime = time.time() - startTime
    print  total time = ,totalTime
    print len(counts)

if __name__ == "__main__":
  main(sys.argv)

(env)~$ python speedTest.py
total time = 0.526521921158
1000000

如果你重新调整贾瓦方案,你也可以很好地调整沙尔方案。

>>> import timeit
>>> timeit.Timer( x = set()
for i in range(10000000):
    x.add(i) ).repeat(3, 1)
[2.1174559593200684, 2.0019571781158447, 1.9973630905151367]
>>> timeit.Timer( x = set()
for i in xrange(10000000):
    x.add(i) ).repeat(3, 1)
[1.8742368221282959, 1.8714439868927002, 1.869229793548584]
>>> timeit.Timer( x = set(xrange(10000000)) ).repeat(3, 1)
[0.74582195281982422, 0.73061800003051758, 0.73396801948547363]

仅使用<条码>x,即可在我的机器上提高约8%。 <代码>(xrange(10000000)> 的确切内容是相同的,但2.5x”的更快(从1.87秒到0.74)。

我也想到,如何调整一项“灰色”方案,使之缩短。 但是, Java可以做同样的trick。 大家都知道,如果你想要在 Java有一套密集的细小的愤怒,那么你就不使用一个黑板。 页: 1 页: 1

BitSet bits = new BitSet(iterations);

startTime = System.currentTimeMillis();
bits.set(0, iterations, true);
totalTime = System.currentTimeMillis() - startTime;
System.out.println("TOTAL TIME = "+( totalTime/1000f) );
System.out.println(bits.cardinality());

这应当相当迅速。 不幸的是,现在我没有时间考验它。

我同意甘达夫关于启动时间的看法。 此外,你正在分配一个大的哈希特,这根本与你的平常法典不相类似。 如果你把这一信息放在一个画面上,那儿将花费大量时间。 此外,插入新内容实际上会随着这一规模而缓慢。 我将按建议研究树木。

可以通过<>填满使 Java缩微镜子更快。 只是略微增加一点。

    HashSet counts = new HashSet((2*iterations), 0.75f);

......

    HashSet counts = new HashSet((2*iterations), 0.75f) {
        @Override public boolean add(Object element) { return false; }
    };

简单、快捷,结果相同。

您也许会想看到,如果你能够“主人”地汇编你所希望的法典部分,也许会把这一节作为先天的功能,并睡在短言之后。 这可能使科索沃信托机构能够将这项职能汇编成本地法典。





相关问题