2012-01-10 25 views
20

我想要一個帶有NumPy成員的Cython「cdef」對象,並且能夠使用快速緩衝區訪問。理想情況下,我會做這樣的事情:對象成員的Cython緩衝區聲明

import numpy as np 
cimport numpy as np 

cdef class Model: 
    cdef np.ndarray[np.int_t, ndim=1] A 

    def sum(self): 
    cdef int i, s=0, N=len(self.A) 
    for 0 <= i < N: 
     s += self.A[i] 
    return s 

    def __init__(self): 
    self.A = np.arange(1000) 

不幸的是,用Cython不能編譯這一點,與錯誤Buffer types only allowed as function local variables

我使用的解決方法是申報緩衝屬性上一個新的局部變量,分配給對象的成員:

cdef class Model: 
    cdef np.ndarray A 

    def sum(self): 
    cdef int i, s=0, N=len(self.A) 
    cdef np.ndarray[np.int_t, ndim=1] A = self.A 
    for 0 <= i < N: 
     s += A[i] 
    return s 

如果你想有多種方法訪問相同的數據,這變得真的很煩人結構 - 這似乎是一個很常見的用例,不是嗎?

有沒有更好的解決方案,不需要重新聲明每種方法內的類型?

回答

6

您目前使用的解決方案是我傾向於使用的方法,即在函數中創建本地副本。這並不優雅,但我認爲你沒有受到巨大的性能影響(或者至少在我的情況下,我在這個方法上做了很多工作,所以它沒有產生明顯的差異)。我還在__cinit__方法中創建了一個C數組,然後在__init__中填充數據(確保使用__dealloc__正確清理)。你失去了numpy數組的一些特性,但你仍然可以像使用c數組一樣使用它。

您也可能會在用Cython名單上這個舊的電子郵件檢查了討論:

http://codespeak.net/pipermail/cython-dev/2009-April/005214.html

+2

更新工作選項鍊接http://www.mail-archive.com/[email protected]/msg05166.html – gg349 2013-08-23 09:57:40

+0

這可能會失去表現嗎? – machen 2017-09-29 15:32:22

13

沒有與存儲器片或用Cython陣列 http://docs.cython.org/src/userguide/memoryviews.html

import numpy as np 
cimport numpy as np 

    cdef class Model: 

    cdef int [:] A 

    def sum(self): 

     for 0 <= i < N: 
      s += self.A[i] 
     return s 

    def __init__(self): 
     self.A = np.arange(1000) 
+0

當你使用這種memoryviews方法時,你可能會失去性能?我描述這個:stringsource:368(__ dealloc__)和stringsource:341(__ cinit__)。順便說一下,這也是在https://stackoverflow.com/questions/21056696/when-profiling-cython-code-what-is-stringsource中討論的 – machen 2017-09-29 15:30:56

+0

關於這個需求問題的優雅解決方案是什麼? – machen 2017-09-29 15:31:32