cython,加速python,保護代碼(2):Faster code via static typing__python

來源:互聯網
上載者:User


http://docs.cython.org/src/quickstart/cythonize.html


Cython is a Python compiler. This means that it can compile normal Python code without changes (with a few obvious exceptions of some as-yet unsupported language features). However, for performance critical code, it is often helpful to add static type declarations, as they will allow Cython to step out of the dynamic nature of the Python code and generate simpler and faster C code - sometimes faster by orders of magnitude.

cython可以完全相容python,但是顯示的聲明變數類別對cython有很大協助:

1)消除python代碼的動態特性

2)產生速度更快的c代碼


常見的型別宣告包括變數聲明和函式宣告.



原始python代碼:

def f(x):    return x**2-xdef integrate_f(a, b, N):    s = 0    dx = (b-a)/N    for i in range(N):        s += f(a+i*dx)    return s * dx
直接編譯成cython,有35%的speedup。




聲明變數類型:

def f(double x):    return x**2-xdef integrate_f(double a, double b, int N):    cdef int i    cdef double s, dx    s = 0    dx = (b-a)/N    for i in range(N):        s += f(a+i*dx)    return s * dx
參與類似於迴圈這樣計算的變數進行聲明非常關鍵,比如 i,a,s,dx。即使 N 和 b 不那麼關鍵,也建議都進行聲明。

提速4倍。



函式宣告類型:

使用cdef,cpdef

cdef double f(double x) except? -2:    return x**2-x
150倍提速。

壞處:python編譯器不再能識別該函數(不知道怎麼調用cdef的函數),python動態類似的特性不再能用(runtime的時候不可能再更改f()函數,固定位double了)。


使用cpdef的區別:Using the cpdef keyword instead of cdef, a Python wrapper is also created, so that the function is available both from Cython (fast, passing typed values directly) and from Python (wrapping values in Python objects). In fact, cpdef does not just provide a Python wrapper, it also installs logic to allow the method to be overridden by python methods, even when called from within cython. This does add a tiny overhead compared to cdef methods.

1)同時產生python wrapper;2)使函數可被重寫




決定何時添加型別宣告:

Because static typing is often the key to large speed gains, beginners often have a tendency to type everything in sight. This cuts down on both readability and flexibility, and can even slow things down (e.g. by adding unnecessary type checks, conversions, or slow buffer unpacking). On the other hand, it is easy to kill performance by forgetting to type a critical loop variable. Two essential tools to help with this task are profiling and annotation. Profiling should be the first step of any optimization effort, and can tell you where you are spending your time. Cython’s annotation can then tell you why your code is taking time.

Using the -a switch to the cython command line program (or following a link from the Sage notebook) results in an HTML report of Cython code interleaved with the generated C code. Lines are colored according to the level of “typedness” – white lines translate to pure C, while lines that require the Python C-API are yellow (darker as they translate to more C-API interaction). Lines that translate to C code have a plus (+) in front and can be clicked to show the generated code.

This report is invaluable when optimizing a function for speed, and for determining when to release the GIL: in general, a nogil block may contain only “white” code.





下面這個很好:

http://blog.septicmk.com/Python/use-Cython.html

如果需要對python代碼添加C/C++的代碼,我認為最優先考慮使用的應當是Cython,當然也有其他的方法,比如這篇文章所說。Cython除了能調用原生的C/C++模組外,還可以讓你以python的文法來寫C/C++的擴充。不過這當中有不少的Tips和Tricks值得注意.  本文中python==2.7.10, Cython=0.22.1 Cython怎麼工作?

首先,Python-C-API是Python解譯器中原生的python模組,通過這個API就可以使用C/C++來編寫Python擴充。不過為了使Python成功的調用C/C++模組,你得花大量的時間寫低級的控制,來包裹原來的代碼。而Cython所做的就是通過編譯利用Python-C-API幫你完成了這個工作,並最終把它編進一個共用庫檔案(.so)中。使得你可以在python代碼中通過import直接匯入進來。

一般來講,在python中使用C/C++模組兩種常見的情境是: 原來的python代碼效能太差 有現成的C/C++可供直接調用

首先,你至少得寫一個.pyx的檔案,寫好外部調用的介面函數,然後一個setup.py檔案,順利的話,會產生一個共用庫檔案(.so),就可以在python代碼中import它了.
比如說,如果你要寫一個add(x,y)函數,首先:

123
# add.pyxdef add(x, y):    return x + y

然後一個編譯檔案:

12345678
# setup.pyfrom distutils.core import setupfrom Cython.Build import cythonizesetup(  name = 'add',  ext_modules = cythonize("add.pyx"),)

然後編譯:

1
python setup.py build_ext --inplace

在你需要調用的地方:

123
# main.pyimport addprint add.add(1, -1)
使用Cython文法 定義變數

使用cdef來定義變數,結構體,常量。

1234567
cdef int i, *j, k[100]cdef struct node:    int key    float valuecdef enum:    const = 1cdef bint flag # bool類型使用bint代替

你可以用一個cdef來把他們寫到一起:

1234567
cdef:    cdef struct node:        int key        float value    int i, *j, k[100]    void add(int x, int y):        return x + y

還可以使用ctypedef來定義類型名稱。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.