我有一個用Cython類像下面的有點人爲例如:爲什麼在C編寫這個緩慢的C數組?
cdef class Differential:
cdef int *SX
cdef int *X
cdef int nmax
def __init__(self, int nmax):
self.nmax = nmax ## usually around 10*1000
return
def __cinit__(self, int nmax, *arg, **args):
self.SX = <float *>malloc(nmax*cython.sizeof(float))
## assume self.X has some content.
self.X = <float *>malloc(nmax*cython.sizeof(float))
return
def __dealloc__(self):
free(self.SX)
free(self.X)
return
@cython.wraparound(False)
@cython.boundscheck(False)
@cython.nonecheck(False)
@cython.cdivision(True)
cdef void __reject(self, float step) nogil:
cdef unsigned int v
cdef unsigned int k
cdef double x
cdef double dx
float_array_init(self.SX,1000,0.) ## writes 0. to the 100000 first elements
for v in range(1000):
x = self.X[v]
for k in range(v+1,1000):
dx = x-self.X[k]
# the following line is the "problem":
self.SX[k] -= dx
## some more code
# manipulate SX some more. this section has less performance impact because it
# is not a double for-loop, so i have not included it in the example
# update X
for v in range(1000):
self.X[v] += self.SX[v]
def reject(self, float step):
self.__reject(step)
該代碼是相當多的參與,但我試圖剝離下來爲仍然示出了我的代碼的流的最小量。
在我的主腳本我簡單地創建差異的一個實例,我多次撥打Differential.reject()(和之間的一些其他的事情要真正改變X的值)
我知道我可以使用cpdef
來避免額外的包裝調用(__reject()和reject()),但是我的測試表明這沒有區別。
我的問題是:
當我註釋掉self.SX[k] -= dx
代碼似乎由10有關的因素是這有望加快?
我明白,訪問內存有成本,但我沒想到代碼會減慢那麼多。
更新
如下建議,改變線
cdef double x
cdef double dx
到
cdef float x
cdef float dx
刪除某些鑄造操作的需要,並通過一個因素加快碼約2.
發佈Cython生成的C代碼(的相關部分)會很有用。 – BluePeppers 2014-09-03 12:01:21
雖然它可能只是緩存;沒有這一行,雙循環中唯一使用的內存區域是self.X,所以它很可能一直保留在緩存中。當你添加self.SX行時,堆的數量會增加兩倍,這可能會將它從緩存中推出?取決於nmax的值是什麼 – BluePeppers 2014-09-03 12:03:37
我稍後會試着做。問題是我的實際代碼更加複雜,因此剝離它有點困難。我目前的理論還認爲它是緩存,@BluePeppers。感謝您的輸入。 – inconvergent 2014-09-03 12:04:32