簡體   English   中英

優化python for循環

[英]Optimizing python for loops

這是兩個程序,天真地計算素數<= 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 && time 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)

正如已經指出的那樣,直接Python真的不是為了這種事情。 主要檢查算法是天真的也不是重點。 但是,通過兩個簡單的事情,我可以在使用原始算法時大大減少Python的時間。

首先,將所有內容放在函數內部,將其稱為main()或其他內容。 這使我的機器在Python上的時間從20.6秒減少到14.54秒。 全局做事比在函數中做得慢。

其次,使用JIT編譯器Psyco。 這需要在文件頂部添加兩行(當然還安裝了psyco):

import psyco
psyco.full()

這使最后時間達到2.77秒。

最后一點。 我決定在此使用Cython並將時間降至0.8533。 但是,知道如何進行一些更改以使其快速Cython代碼不是我推薦給臨時用戶的東西。

是的,Python很慢,比C慢大約一百倍。你可以使用xrange而不是range來獲得一個小的加速,但xrange它沒關系。

最終你做錯的是你用普通的Python做到這一點,而不是使用像Numpy或Psyco這樣的優化庫。

Java附帶了一個jit編譯器,在你只是處理數字時會產生很大的不同。

通過使用替換復雜的測試,您可以使Python的速度提高兩倍

if i % k == 0: isp = False

您也可以比isp = False之后添加一個中斷快八倍(對於n = 10000)。

另外,幫自己一個忙,跳過偶數(加一到nps開始包括2)。

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

當然,如果您在Java中進行相同的更改,它仍然比優化的Python快10倍。

男孩,當你說這是一個天真的實施,你肯定不是在開玩笑!

但是,當將JIT編譯的優化機器代碼與解釋語言進行比較時,性能上的一到兩個數量級的差異並不出乎意料。 在Java VM上運行的替代Python實現(如Jython)可能會更快地執行此任務; 你可以給它一個旋轉。 Cython,允許您向Python添加靜態類型並在某些情況下獲得類似C的性能,也可能值得研究。

即使在考慮標准的Python解釋器CPython時,問題是:Python是否足夠快以完成手頭的任務? 您是否節省了使用Python等動態語言編寫代碼的時間,以彌補運行它所花費的額外時間? 如果你不得不用Java編寫一個給定的程序,那么看起來太值得做的事情值得嗎?

例如,考慮在現代計算機上運行的Python程序與在具有10年歷史的計算機上運行的Java程序一樣快。 你十年前的電腦對很多東西都足夠快,不是嗎?

Python確實具有許多功能,使其非常適合數字工作。 這些包括支持無限數量的數字的整數類型,具有無限精度的十進制類型,以及專門用於計算的名為NumPy的可選庫。 然而,執行速度通常不是其聲名鵲起的主要原因之一。 它擅長的地方在於讓計算機以最小的認知摩擦做你想做的事。

如果你想快速做到這一點,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 ......)。

你為什么不發布關於內存使用的東西 - 而不僅僅是速度? 試圖在tomcat上獲得一個簡單的servlet在我的服務器上浪費了3GB。

你對這些例子做了什么並不是很好。 你需要使用numpy。 用while循環替換/ range,從而避免創建列表。

最后,python非常適合數字運算,至少是以正確的方式執行它的人,並且知道Eratosthenes的Sieve是什么,或mod操作是什么。

你可以對這個算法做很多事情來加速它,但是大多數它們也會加速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 

具有諷刺意味的是,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)

還是更快。 或試試這些

問題是,python通常足夠快以設計您的解決方案。 如果它的生產速度不夠快,可以使用numpy或Jython來提高性能。 或者將其移動到編譯語言,隨身攜帶在python中學習的算法觀察。

是的,Python是您將遇到的最慢的實用語言之一。 While循環比for i in xrange()循環快一些,但最終Python總是比其他任何東西慢得多。

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

Python是一種腳本語言。 不是編程語言。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM