2011-11-10 259 views
2

我有一個用Python編寫的項目,可以處理大量的數據。 我想加快執行時間。如何加快Python的執行速度?

在簡單的話,讓我們說我有這樣的樣品完全優化代碼:

def foo(x): 
    doSomething 

main(): 
    for i in range(1,10000000): 
     foo(i) 

是否有某種方式來加速這個?例如通過使用多處理或其他的東西? 最重要的是,它值得嗎?

感謝您的回覆。我想我會嘗試多處理的路線。有人可以給我一個指導或幫助我的例子嗎?

+3

你真的應該使用'的xrange'代替'range' - 否則,你把所有的「數據」的存儲只是遍歷它。 – ThiefMaster

+1

持有onx的2.x,而不是3.x ... – glglgl

回答

7

唯一的真實知道的方法是配置和測量。你的代碼可以做任何事情。 「doSomething」可能是time.sleep(10),在這種情況下,分叉10000000進程會使整個程序在大約10秒內運行(忽略分支開銷和產生的減速)。

使用http://docs.python.org/library/profile.html並檢查瓶頸位置,看看您是否可以使用更好的編碼來優化「完全優化」程序。如果它已經夠快了,停下來。

然後,根據是CPU還是I/O綁定以及硬件,您可能想嘗試多處理或線程化。如果您的問題可以被分解,您也可以嘗試分發到多臺機器,並做一些地圖/減少類型的事情。

+0

好的謝謝你的回覆。那麼,我的程序只是循環大量的數據,所以我不認爲更多的優化會提高性能。 所以我的問題是:使用多處理我將獲得多少速度? 想象一下,我的項目可以概括爲一百萬個單元格陣列中的循環。 對不起英語.. :) – blueSurfer

+0

那麼,你可以將它分成100個相同大小的部分,並使用一個工作池來處理每個部分,然後加入結果。 –

3

您可以使用內置JIT編譯器的PyPy解釋器,它可能實際上改善了像這樣的循環的性能。這裏是一個link,它解釋了PyPy解釋器提供的超過常規CPython的一些加速功能。

或者您可以使用Cython來編寫代碼,該代碼允許python中的本地c擴展。巨大塊的numpy是這樣寫的,以獲得良好的加速。

或者你可能忘記使用python,只是寫在ASM。當然,這會很難做到,但是當你看到你的程序運行速度比所有人都快1%時?你會很開心,你走得更遠。

+0

提PyPy +1。另外,我很確定在組裝中重寫它會給你提供超過1%的提升。 :) –

+1

是的,但任何那個關於優化的肛門都可以用閃光和安全膠水坐在角落裏。 –

+0

它*有可能以另一種方式。 –

2

除了已經說過的,你可以看看cython。但是,在你做之前。此外,pypy可能值得一試。不應該有任何工作需要使其工作。

+1

這是怎麼得到upvoted甚至沒有解釋什麼pypy和cython? –

+0

他提供了足夠的鏈接,儘管你的回答中的總結會更好。 –

9

要回答你最後一個問題,如果你的表現有問題,那就值得。這是唯一的標準,真的。

至於如何:

如果你的算法是緩慢的,因爲它的計算量很大,考慮重寫它作爲C extension,或使用Cython,這將讓你寫在Python式的語言快速擴展。此外,PyPy正在變得越來越快,並且可能只是能夠不加修改地運行你的代碼。

如果代碼在計算上並不昂貴,但它只是循環了大量的數據,可能會使用多處理來分解代碼,因此它可以並行完成。

最後,如果這是某種基本數據濺射任務,請考慮使用快速數據存儲。所有主要的關係數據庫都在wazoo上進行了優化,您可能會發現只需讓數據庫爲您完成任務,就可以加快您的任務速度。您甚至可以將其塑形以適合Redis商店,該商店可以出色地彙總大數據集。

+0

Redis是一款非常棒的工具 –

0

如果可以並行處理任務,則可以使用multiprocessing模塊調查使用進程池,並將作業分佈在子進程之間。

0

這真的取決於你的應用程序,但是如果doSomething可以很好地進行線程化(例如有很多沉重的C代碼),那麼你可能會感興趣產生多個線程來完成這項工作。通常的模式是這樣的:

def worker(): 
    while True: 
     item = q.get() 
     do_work(item) 
     q.task_done() 

q = Queue() 
for i in range(num_worker_threads): 
    t = Thread(target=worker) 
    t.daemon = True 
    t.start() 

for item in source(): 
    q.put(item) 

q.join()  # block until all tasks are done