优化python for循环

时间:2010-11-12 23:04:11

标签: python

这是两个程序,它们天真地计算素数的数量< = n 一个是Python,另一个是Java。

public class prime{
    public static void main(String args[]){
        int n = Integer.parseInt(args[0]);
        int nps = 0;
 boolean isp;

        for(int i = 1; i <= n; i++){
            isp = true;

            for(int k = 2; k < i; k++){
               if( (i*1.0 / k) == (i/k) ) isp = false;
            }
            if(isp){nps++;}
 }
        System.out.println(nps);
    }
}


`#!/usr/bin/python`                                                                                                                                        
import sys
n = int(sys.argv[1])
nps = 0

for i in range(1,n+1):
    isp = True
    for k in range(2,i):
        if( (i*1.0 / k) == (i/k) ): isp = False
    if isp == True: nps = nps + 1
print nps

在n = 10000上运行它我得到以下时间 shell:〜$ time python prime.py 10000&amp;&amp;时间java prime 10000
1230

真实0m49.833s
用户0m49.815s
sys 0m0.012s
1230

真实0m1.491s
用户0m1.468s
sys 0m0.016s

我是否在python中以不正确的方式使用for循环,或者python实际上只是这么慢?

我不是在寻找专门用于计算素数的答案,而是我想知道python代码是否通常以更智能的方式使用。

编译Java代码 javac 1.6.0_20
使用java版本“1.6.0_18”运行
OpenJDK运行时环境(IcedTea6 1.8.1)(6b18-1.8.1-0ubuntu1~9.10.1) OpenJDK客户端VM(构建16.0-b13,混合模式,共享)

Python是:
Python 2.6.4(r264:75706,2009年12月7日,18:45:15)

9 个答案:

答案 0 :(得分:9)

正如已经指出的那样,直接Python真的不是为了这种事情。主要检查算法是天真的也不是重点。但是,通过两个简单的操作,我可以在使用原始算法时大大缩短Python的时间。

首先,将所有内容放在函数中,将其称为main()或其他内容。这使我的机器在Python上的时间从20.6秒减少到14.54秒。全局做事比在函数中做事要慢。

其次,使用JIT编译器Psyco。这需要在文件顶部添加两行(当然还安装了psyco):

import psyco
psyco.full()

这使最终时间达到2.77秒。

最后一点。我决定在此使用Cython并将时间降至0.8533。但是,知道如何进行少量更改以使其快速运行Cython代码不是我为临时用户推荐的内容。

答案 1 :(得分:4)

是的,Python速度慢,比C慢一百倍。你可以使用xrange代替范围来获得一个小的加速,但除此之外它没关系。

最终你做错的是你用普通的Python做到这一点,而不是使用像Numpy或Psyco这样的优化库。

Java附带了一个jit编译器,它可以在您处理数字时产生很大的不同。

答案 2 :(得分:2)

使用

替换复杂的测试,可以使Python的速度提高一倍
if i % k == 0: isp = False

你也可以比isp = False后加入一个中断快8倍(n = 10000)。

另外,请帮个忙,跳过偶数(加1到nps开始包括2)。

最后,你只需要k到达sqrt(i)。

当然,如果你在Java中进行相同的更改,它仍然比优化的Python快10倍。

答案 3 :(得分:2)

男孩,当你说这是一个天真的实施时,你肯定不是在开玩笑!

但是,在将JIT编译的优化机器代码与解释语言进行比较时,性能上的一到两个数量级的差异并不出乎意料。在Java VM上运行的替代Python实现(如Jython)可能会更快地执行此任务;你可以给它一个旋转。 Cython,允许您向Python添加静态类型并在某些情况下获得类似C的性能,也可能值得研究。

即使在考虑标准的Python解释器CPython时,问题是:Python是否足够快以完成手头的任务?您是否节省了使用Python等动态语言编写代码的时间,以弥补运行它所花费的额外时间?如果你不得不用Java编写一个给定的程序,那么看起来太值得做的事情值得吗?

例如,考虑在现代计算机上运行的Python程序与在10年前的计算机上运行的Java程序一样快。你十年前的计算机很快就可以用很多东西了,不是吗?

Python确实具有许多功能,使其非常适合数字工作。这些包括支持无限数量的数字的整数类型,具有无限精度的十进制类型,以及专门用于计算的名为NumPy的可选库。然而,执行速度通常不是其声名鹊起的主要原因之一。它擅长的地方在于让计算机以最小的认知摩擦做你想做的事。

答案 4 :(得分:0)

如果您希望快速完成,Python可能不是前进的方法,但您可以加快速度。首先,你使用相当慢的方法来测试可分性。 Modulo更快。您也可以在检测到匹配后立即停止内循环(使用k)。我会做这样的事情:

nps = 0
for i in range(1, n+1):
    if all(i % k for k in range(2, i)): # i.e. if divisible by none of them
       nps += 1

对我来说,从25秒降到1.5秒。使用xrange将其降低到0.9秒。

你可以通过保留你已经找到的素数列表来进一步加速它,并且只测试那些,而不是每个数字直到i(如果我不能被2整除,它将不能被它整除4,6,8 ......)。

答案 5 :(得分:0)

为什么不发布有关内存使用情况的内容 - 而不仅仅是速度?试图在tomcat上获得一个简单的servlet在我的服务器上浪费了3GB。

你对这些例子做了什么并不是很好。你需要使用numpy。用while循环替换/ range,从而避免创建列表。

最后,python非常适合数字运算,至少是那些以正确方式运行的人,并且知道Eratosthenes的Sieve是什么,或者mod操作是什么。

答案 6 :(得分:0)

你可以对这个算法做很多事情来加速它,但是大多数它们也会加速Java版本。其中一些将比Java更加加速Python,所以它们值得测试。

以下是我的系统上的一些更改,从11.4秒加速到2.8秒:

nps = 0 
for i in range(1,n+1): 
    isp = True 
    for k in range(2,i):
        isp = isp and (i % k != 0)
    if isp: nps = nps + 1 
print nps 

答案 7 :(得分:0)

讽刺的是,Python是一种非常适合开发算法的语言。甚至像这样修改过的算法:

# See Thomas K for use of all(), many posters for sqrt optimization
nps = 0
for i in xrange(1, n+1):
    if all(i % k for k in xrange(2, 1 + int(i ** 0.5))):
       nps += 1

大约在一秒钟内运行。像这样的代码:

def eras(n):
    last = n + 1
    sieve = [0,0] + range(2, last)
    sqn = int(round(n ** 0.5))
    it = (i for i in xrange(2, sqn + 1) if sieve[i])
    for i in it:
        sieve[i*i:last:i] = [0] * (n//i - i + 1)
    return filter(None, sieve)

更快。或者尝试these

问题是,python通常足够快以设计您的解决方案。如果它的生产速度不够快,可以使用numpy或Jython来提高性能。或者将它移动到编译语言,随身携带你在python中学习的算法观察结果。

答案 8 :(得分:-5)

是的,Python是您遇到的最慢的实用语言之一。 While循环比for i in xrange()略快,但最终Python总是比其他任何东西慢得多。

Python有它的位置:原型理论和思想,或者在任何快速生成代码的能力比代码性能更重要的情况下。

Python是一种脚本语言。不是编程语言。