我的python程序比java版本的同一程序执行得更快。什么给予?

2024-10-01 19:16:15 发布

您现在位置:Python中文网/ 问答频道 /正文

更新:2009-05-29

谢谢你的建议和建议。我使用了您的建议,使我的生产代码比几天前的最佳结果平均快2.5倍。最后,我能够使java代码最快。在

经验教训:

  • 下面我的示例代码显示了原始int的插入,但生产代码实际上存储的是字符串(我的错)。当我更正python的执行时间从2.8秒变为9.6秒时。所以一开始,java在存储对象时实际上速度更快。

  • 但这还不止于此。我一直在执行以下java程序:

    java-Xmx1024m速度测试

但是,如果将初始堆大小设置为如下所示,则会获得巨大的改进:

java -Xms1024m -Xmx1024m SpeedTest

这个简单的更改将执行时间减少了50%以上。我的python speed6.seconds是最后的测试结果。Java 6.5秒。在

原始问题:

我有以下python代码:

^{pr2}$

它在我的机器上执行了大约3.3秒,但我想让它更快,所以我决定用java编程。我假设,由于java是编译的,而且通常被认为比python快,我会看到一些巨大的回报。在

以下是java代码:

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());
    }
}

所以这个java代码和python代码基本上是一样的。但它只需8.3秒而不是3.3秒。在

我从一个真实的例子中提取了这个简单的例子来简化事情。关键的元素是,我有(set或hashSet)以很多成员结束,就像示例一样。在

以下是我的问题:

  1. 为什么我的python实现比java实现快?

  2. 有没有比hashSet(java)更好的数据结构来保存一个惟一的集合?

  3. 怎样才能使python实现更快?

  4. 什么能使java实现更快?

更新:

感谢所有到目前为止做出贡献的人。请允许我补充一些细节。在

我没有包括我的生产代码,因为它相当复杂。会让你分心。我上面的例子是最简单的。我的意思是javaput调用似乎比python set的add()慢得多。在

生产代码的java实现也比python版本慢2.5-3倍——就像上面提到的。在

我不关心虚拟机预热或启动开销。我只想比较一下我的起始时间和总时间的代码。请不要关心其他事情。在

我用足够多的桶初始化hashset,这样它就不必重新计算了。(我总是提前知道集合最终将包含多少元素)我想有人可能会认为我应该将它初始化为iterations/0.75。但如果您尝试它,您将看到执行时间不会受到显著影响。在

我为那些好奇的人设置了Xmx1024m(我的机器有4GB的ram)。在

我使用的是java版本:java(TM)SE运行时环境(build 1.6.0_13-b03)。在

在生产版本中,我在hashSet中存储了一个字符串(2-15个字符),因此我不能使用原语,尽管这是一个有趣的例子。在

我已经运行代码很多次了。我非常确信python代码比java代码快2.5到3倍。在


Tags: 代码版本示例时间javasystem建议例子
3条回答

另一个可能的解释是,Python中的集合是用C代码本机实现的,而Java中的HashSet是用Java本身实现的。因此,Python中的set应该天生就快得多。在

实际上,您并不是在测试Java与Python的比较,而是在测试java.util.HashSet与Python的原生集和整数处理相比。在

显然,在这个特殊的微博客中,Python方面的速度确实更快。在

我尝试用GNU trove中的TIntHashSet替换HashSet,并获得了介于3到4之间的加速因子,使Java稍微领先于Python。在

真正的问题是您的示例代码是否真的如您所想的那样代表您的应用程序代码。您是否运行了一个探查器并确定大部分的CPU时间都花在将大量的int放入一个HashSet中?如果没有,这个例子就无关紧要了。即使唯一的区别是您的产品代码存储的是除int之外的其他对象,它们的创建和哈希代码的计算也很容易控制set插入(并完全破坏Python处理int的优势),使整个问题变得毫无意义。在

我怀疑Python使用整数值本身作为散列值,而基于散列表的set实现直接使用该值。根据source中的注释:

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.

对于Python来说,这个microbenchmark是一个最好的例子,因为它会导致完全零散列冲突。然而,如果Javas HashSet要重新散列密钥,它必须执行额外的工作,并且在发生碰撞时会出现更糟糕的行为。在

如果你在一个范围内随机洗牌在循环之前,即使在循环之外完成随机播放和列表创建,运行时也要慢2倍多。在

相关问题 更多 >

    热门问题