1. 程式人生 > 程式設計 >提高python程式碼執行效率的一些建議

提高python程式碼執行效率的一些建議

1. 優化程式碼和演算法

一定要先好好看看你的程式碼和演算法。許多速度問題可以通過實現更好的演算法或新增快取來解決。本文所述都是關於這一主題的,但要遵循的一些一般指導方針是:

  • 測量,不要猜測。 測量程式碼中哪些部分執行時間最長,先把重點放在那些部分上。
  • 實現快取。 如果你從磁碟、網路和資料庫執行多次重複的查詢,這可能是一個很大的優化之處。
  • 重用物件,而不是在每次迭代中建立一個新物件。Python 必須清理你建立的每個物件才能釋放記憶體,這就是所謂的“垃圾回收”。許多未使用物件的垃圾回收會大大降低軟體速度。
  • 儘可能減少程式碼中的迭代次數,特別是減少迭代中的操作次數。
  • 避免(深度)遞迴。 對於 Python 直譯器來說,它需要大量的記憶體和維護(Housekeeping)。改用生成器和迭代之類的工具。
  • 減少記憶體使用。 一般來說,儘量減少記憶體的使用。例如,對一個巨大的檔案進行逐行解析,而不是先將其載入到記憶體中。
  • 不要這樣做。 聽起來很傻是吧?但是你真的需要執行這個操作嗎?不能晚點兒再執行嗎?或者可以只執行一次,並且它的結果可以儲存起來,而不是一遍又一遍地反覆計算?

2. 使用 PyPy

你可能正在使用 Python 的參考實現 CPython。之所以稱為 CPython,是因為它是用 C 語言編寫的。如果你確定你的程式碼是 CPU 密集型(CPU bound)(如果你不知道這一術語,請參見本文“使用執行緒”一節)的話,那麼你應該研究一下 PyPy,它是 CPython 的替代方案。這可能是一種快速解決方案,無需更改任何一行程式碼。

PyPy 聲稱,它的平均速度比 CPython 要快 4.4 倍。它是通過使用一種稱為 Just-in-time(JIT,即時編譯)技術來實現的。Java 和 .NET 框架就是 JIT 編譯的其他著名的例子。相比之下,CPython 使用解釋來執行程式碼。雖然這一做法提供了很大的靈活性,但速度也變得慢了下來。

使用 JIT,你的程式碼是在執行程式時即時編譯的。它結合了 Ahead-of-time(AOT,提前編譯)技術的速度優勢(由 C 和 C++ 等語言使用)和解釋的靈活性。另一個優點是 JIT 編譯器可以在執行時不斷優化程式碼。程式碼執行的時間越長,它就會變得越優化。

PyPy 在過去幾年中取得了長足的進步,通常情況下,它可以作為 Python 2 和 Python 3 的簡易替換方案。使用 Pipenv 這樣的工具,它也可以完美地工作,試試看吧!

3. 使用執行緒

大部分軟體都是 IO 密集型,而不是 CPU 密集型。如果你對這些術語還不熟悉的話,請看看下面的解釋:

  • IO 密集型(I/O bound):軟體主要是等待輸入 / 輸出操作完成才能工作。在從網路或緩慢的儲存中獲取資料時,通常會出現這種情況。
  • CPU 密集型(CPU bound):軟體佔用了大量的 CPU 資源。它使用了 CPU 所有的能力來產生所需的結果。

在等待來自網路或磁碟的應答時,你可以使用多個執行緒使其他部分保持執行狀態。

一個執行緒是一個獨立的執行序列。預設情況下,Python 程式有一個主執行緒。但你可以建立更多的主執行緒,並讓 Python 在它們之間切換。這種切換髮生得如此之快,以至於它們看上去就好像是在同時並排執行一樣。

提高python程式碼執行效率的一些建議

但與其他程式語言不同的是,Python 並不是同時執行的,而是輪流執行。這是因為 Python 中有一種全域性直譯器鎖( Global Interpreter Lock,GIL)機制。這一點,以及 threading 庫在 我撰寫的關於 Python 併發性的文章 有詳細的解釋。

我們得到的結論是,執行緒對於 IO 密集型的軟體有很大的影響,但對 CPU 密集型的軟體毫無用處。

這是為什麼呢?很簡單。當一個執行緒在等待來自網路的答覆時,其他執行緒可以繼續執行。如果你要執行大量的網路請求,執行緒可以帶來巨大的差異。如果你的執行緒正在進行繁重的計算,那麼它們只是等待輪到它們繼續計算,執行緒化只會帶來更多的開銷。

4. 使用 Asyncio

Asyncio 是 Python 中一個相對較新的核心庫。它解決了與執行緒相同的問題:它加快了 IO 密集型軟體的速度,但這是以不同的方式實現的。我將立即坦承我並非 Python 的 asyncio 擁躉。它相當複雜,特別是對於初學者來說。我遇到的另一個問題是, asyncio 庫在過去幾年中有了很大的發展。網上的教程和示例程式碼常常已經過時。不過,這並不意味著它就毫無用處。

5 同時使用多個處理器

如果你的軟體是 CPU 密集型的,你通常可以用一種可以同時使用更多處理器的方式重寫你的程式碼。通過這種方式,你就可以線性地調整執行速度。

這就是所謂的並行性,但並不是所有的演算法都可以並行執行。例如,簡單的將遞迴演算法進行並行化是不可能的。但是幾乎總有一種替代演算法可以很好地並行工作。

使用更多處理處理器有兩種方式:

  1. 在同一臺機器內使用多個處理器和 / 或核心。在 Python 中,這可以通過 multiprocessing 庫來完成。
  2. 使用計算機網路來使用多個處理器,分佈在多臺計算機上。我們稱之為分散式計算。

這篇 關於 Python 併發性的文章 側重於介紹如何在一臺機器的範圍內擴充套件 Python 軟體的方法。它還介紹了 multiprocessing 庫。如果你認為這是你需要的資料,一定要去看看。

與 threading 庫不同, multiprocessing 庫繞過了 Python 的全域性直譯器鎖。它實際上是通過派生多個 Python 例項來實現這一點的。因此,現在你可以讓多個 Python 程序同時執行你的程式碼,而不是在單個 Python 程序中輪流執行執行緒。

提高python程式碼執行效率的一些建議

multiprocessing 庫和 threading 庫非常相似。可能出現的問題是:為什麼還要考慮執行緒呢?答案是可以猜得到的。執行緒是“輕量”的:它需要更少的記憶體,因為它只需要一個正在執行的 Python 直譯器。產生新程序也還有其開銷。因此,如果你的程式碼是 IO 密集型的,執行緒可能就足夠好了。

一旦你實現了軟體的並行工作,那麼在使用 Hadoop 之類的分散式計算方面就前進了一小步。通過利用雲端計算平臺,你可以相對輕鬆地進行擴充套件規模。例如,你可以在雲端中處理大型資料集,並在本地使用結果。使用混合操作的方式,你可以節省一些資金,因為雲端中的算力非常昂貴。

總結

總結起來就是:

  • 首先考慮優化你的演算法和程式碼。
  • 如果原始速度可以解決你的問題,請考慮使用 PyPy。
  • 對 IO 密集型軟體使用 threading 庫和 asyncio 。
  • 使用 multiprocessing 庫解決 CPU 密集型問題。
  • 如果所有這些措施還不夠的話,可以利用 Hadoop 等雲端計算平臺進行擴充套件規模。

以上就是提高python程式碼執行效率的一些建議的詳細內容,更多關於提高python程式碼執行效率的資料請關注我們其它相關文章!