2011-09-16 223 views
3

我想加快一些與cython的python代碼,我正在使用cython的-a選項來查看我可以改進的地方。我的理解是,在生成的html文件中,突出顯示的行是調用python函數的行 - 是否正確?Cython numpy數組索引

在下面的普通函數中,我使用緩衝區語法聲明瞭numpy數組參數arr。我認爲這允許索引操作純粹以C語言進行,而無需調用python函數。然而,cython -a(版本0.15)突出顯示了我設置arr元素的值的那一行,但不是我讀取其元素之一的那一行。爲什麼會發生?有訪問numpy數組元素的更有效方法嗎?

import numpy 
cimport numpy 

def foo(numpy.ndarray[double, ndim=1] arr not None): 
    cdef int i 
    cdef double elem 
    for i in xrange(10): 
     elem = arr[i]   #not highlighted 
     arr[i] = 1.0 + elem #highlighted 

編輯:另外,請問mode緩衝參數與numpy的互動?假設我沒有將numpy.arrayorder參數從默認值更改爲0,那麼使用mode='c'總是安全嗎?這實際上是否會影響性能?

delnan的評論後編輯:arr[i] += 1也得到突出顯示(這就是爲什麼我首先分裂它,看看哪部分操作導致問題)。如果我關閉邊界檢查,以簡化的東西(這使什麼得到強調沒有區別),生成C代碼:

/* "ct.pyx":11 
* cdef int i 
* cdef double elem 
* for i in xrange(10):    # <<<<<<<<<<<<<< 
*  elem = arr[i] 
*  arr[i] = 1.0 + elem 
*/ 
    for (__pyx_t_1 = 0; __pyx_t_1 < 10; __pyx_t_1+=1) { 
    __pyx_v_i = __pyx_t_1; 

    /* "ct.pyx":12 
* cdef double elem 
* for i in xrange(10): 
*  elem = arr[i]    # <<<<<<<<<<<<<< 
*  arr[i] = 1.0 + elem 
*/ 
    __pyx_t_2 = __pyx_v_i; 
    __pyx_v_elem = (*__Pyx_BufPtrStrided1d(double *, __pyx_bstruct_arr.buf, __pyx_t_2, __pyx_bstride_0_arr)); 

    /* "ct.pyx":13 
* for i in xrange(10): 
*  elem = arr[i] 
*  arr[i] = 1.0 + elem    # <<<<<<<<<<<<<< 
*/ 
    __pyx_t_3 = __pyx_v_i; 
    *__Pyx_BufPtrStrided1d(double *, __pyx_bstruct_arr.buf, __pyx_t_3, __pyx_bstride_0_arr) = (1.0 + __pyx_v_elem); 
    } 
+0

是'改編[1] + = 1'突出?另外,我相信你可以在由'cython -a'生成的HTML文檔中查看爲特定行生成的代碼,這可能有助於查看該行上發生了哪些Python API調用。 – delnan

回答

4

的答案是,熒光筆愚弄讀者。 我編譯你的代碼,並在高亮下產生的指令是需要的那些 來處理錯誤情況和返回值,它們與數組賦值無關。

事實上,如果你改變了代碼如下:

def foo(numpy.ndarray[double, ndim=1] arr not None): 
    cdef int i 
    cdef double elem 
    for i in xrange(10): 
     elem = arr[i] 
     arr[i] = 1.0 + elem 
    return # + add this 

的亮點將是在最後一行,並在作業不多。

您可以進一步加快使用@ cython.boundscheck代碼:

import numpy 
cimport numpy 
cimport cython 

@cython.boundscheck(False) 
def foo(numpy.ndarray[double, ndim=1] arr not None): 
    cdef int i 
    cdef double elem 
    for i in xrange(10): 
     elem = arr[i] 
     arr[i] = 1.0 + elem 
    return 
+0

提供的C代碼顯示沒有綁定檢查,沒有環繞索引計算。所以我假設提問者在他的setup.py中停用了它們。 – rocksportrocker