用Cython來提高Python代碼速度 [一]

Disclaimer:

  • 本文的對象為對Python比較熟悉的用戶。對一些基礎的Python概念將不做介紹。
  • 本文的演算法並不一定最優,主要目的是為了展示Cython的一些基本概念
  • 本文不需要精通C或C++,但是知道基本的指針,類型和內存概念會有幫助。

我在之前幾篇文章中提到過作為數據科學家的一項技能是編寫高性能的機器學習,腳本和其他程序。然而大多數情況下我們都希望只使用一種語言環境,而Python基本是默認的DS編程環境。那麼如果有需要極大壓榨程序性能的話,就可以利用Cython。這篇文章並不會觸及細節的內容,只是讓讀者自行確認是否有學習cython的必要。後續文章將通過一些例子來介紹一些常用的方法。

什麼是Cython?

Cython並不是C,也不是Python,他是一個將介於C和Python之間的語言結構編譯成C,然後在Python中運行的介面。它保持了大多數Python的語法結構,支持所有Python的命令,並通過一定方法加入C的結構,從而繞過Python的重重轉譯和類型檢查,來實現快速的程序。

大多數Python整合包都會包括Cython。你也可以通過pip來安裝:

pip install Cython

與Python不一樣,你並不能直接使用Cython的源代碼。需要通過編譯來完成從Python調用C程序的目的。此外,沒有錯,如果你有用C直接編寫的程序,可以用Cython來調用純C程序!

Cython同樣支持C++

Cython自帶一些C和C++的標準庫

ipython支持直接在命令行編譯和使用cython程序!然而我的實踐發現可能出現奇怪bug。

Cython的參考書非常少,最常用的一本是Cython A GUIDE FOR PYTHON PROGRAMMERS。然而……此書非常不詳盡,絕對不是noob friendly…… 建議有什麼問題還是stackoverflow求助大牛。

什麼時候用Cython?

切記:Cython並不是所有python速度問題的良藥。它犧牲了flexibility來換取速度,你必須要考慮所有細節問題,包括很多python新手甚至老手忽略了的、Python幫你暗地裡處理好的問題。

  • 如果你需要大量使用python的類,請慎重考慮是否使用。
  • 如果並沒有大量循環,或者最內層的循環有一些複雜python的類,請慎重使用。
  • 如果不需要重複使用腳本,請慎重使用。
  • 如果提升只有不到20%,請慎重使用。
  • 如果這個函數或者類會被很多人debug和改進,請慎重使用。除非很多人熟悉Cython,不然maintain程序會非常麻煩。
  • 如果不能確定性能瓶頸是你要改寫為cython的函數,請慎重使用。
  • 如果你不會從200%的速度提升中獲得快感,請慎重使用。

學習Cython前的思考:

你是否濫用了Python的靈活性?

如果你經常編寫類似下面的函數,你可能需要在學習cython之前改變你的習慣:

def foo(arg): if isinstance(arg, str): # Do something elif isinstance(arg, str): # Do something else: # Do something

有一個確定input類型的函數非常有用。Python沒有像C++和java那種overload的保護,很容易引起麻煩。

if foo == "astring": foo = myClass()

這本身就不是很好的python編寫習慣,除非重新賦值為不同類型變數會節省巨大內存使用,不然這種用法及其容易引起混淆。

你是否因為調用函數而沒有思考複雜度?

請參考附錄文章1. 連續使用一些內置函數確實可以實現提速作用,但是有可能進行了多餘的運算。在進行Cython編寫的時候需要在除去Python冗餘檢查的前提下(例如,請記住,在Cython中使用循環沒有任何問題,甚至可能是進行細微調整的優化的前提),儘可能地實現運算次數的最小化。

你是否對基本數據結構有所了解?

這裡的數據結構並不是數據科學意義上的資料庫結構,而是基本的整數,浮點等。使用Cython的一個重要的技巧就是盡量利用和改寫輸入數據的組成方式:

  1. 保證統一形式,確認是某種類型,確認長度,等等。
  2. 減少字元串操作。字元串操作是python的長處,如果你需要處理大量的字元串集,請考慮是否可以先創建一個dictionary來進行string -> int/long的對應。
  3. 能保證有整齊的數據為佳。list of list,如果知道每個字列都是同樣長度,轉化為齊整的array更好。

如有興趣請繼續看 :

Weiwen Gu:用Cython來提高Python代碼速度 [二]?

zhuanlan.zhihu.com圖標

附錄

1.【學習心得】寫出快速python程序【可能是一】

2. Cythons Documentation

3. Cython: A Guide for Python Programmers


推薦閱讀:

用Cython和PyPy提升Python性能
Python對象初探(《Python源碼剖析》筆記一)
為什麼Cython寫的擴展會比直接用C寫還快?

TAG:數據科學 | Python | Cython |