[英]Can I use Numpy operations like reshape in Cython code without Python interaction?
我有一些Python代碼,我希望通過使用Cython來加速。 在使用ndarrays時,我在我的腳本中使用了很多Numpy操作,比如np.reshape和np.sum。 當我在我的代碼中使用操作時,我不知道如何使它們不與python交互,因此它們將我的Cython代碼減慢到大約Python的速度。
這是一個例子。 這是Python代碼,它以任意數量的方式存儲數組。
import numpy as np
def binarray (array,nbin):
temp=array.reshape(int(array.shape[0]/nbin),nbin,int(array.shape[1]/nbin),nbin)
temp=temp.sum(axis=(3,1))
return temp
我已經定義了數據成員類型,並按照Cython文檔中的描述聲明了np.ndarray實例。
import numpy as np
cimport numpy as np
DTYPE = np.double
ctypedef np.int_t DTYPE_t
def binarray (np.ndarray[DTYPE_t, ndim=2] array,int nbin):
cdef int x0 = int(array.shape[0]/nbin)
cdef int x2 = int(array.shape[1]/nbin)
cdef np.ndarray[DTYPE_t, ndim=4] temp = np.zeros([x0,nbin,x2,nbin], dtype=DTYPE)
temp = array.reshape(x0,nbin,x2,nbin)
return temp.sum(axis=(3,1))
但我無法在任何地方找到我如何在Cython中使用Numpy操作。 這是我第一次使用Cython,因為據我所知,Numpy數組和對它們的操作是用c編譯的,所以我想我可以在Cython中使用它們,是這樣的嗎? 或者我是否必須自己重寫這些功能?
所以這個函數應該做這樣的事情:
In [474]: arr = np.arange(24).reshape(4,6)
In [475]: arr
Out[475]:
array([[ 0, 1, 2, 3, 4, 5],
[ 6, 7, 8, 9, 10, 11],
[12, 13, 14, 15, 16, 17],
[18, 19, 20, 21, 22, 23]])
In [476]: binarray(arr,2)
Out[476]:
array([[14, 22, 30],
[62, 70, 78]])
時間對我來說看起來不太古怪(這是在一台相對較舊的筆記本電腦上):
In [483]: timeit binarray(arr,2)
The slowest run took 4.93 times longer than the fastest. This could mean that an intermediate result is being cached.
100000 loops, best of 3: 14.6 µs per loop
In [484]: arr=np.ones((1000,1000),int)
In [485]: timeit binarray(arr,50)
100 loops, best of 3: 2.96 ms per loop
In [486]: timeit binarray(arr,100)
100 loops, best of 3: 2.78 ms per loop
In [487]: timeit binarray(arr,10)
100 loops, best of 3: 4.91 ms per loop
供參考, sum
沒有重塑:
In [489]: timeit arr.sum()
100 loops, best of 3: 2.28 ms per loop
而次要的重塑成本:
In [551]: %%timeit arr=np.ones((1000,1000));nbin=100
temp = arr.reshape(int(arr.shape[0]/nbin), nbin, int(arr.shape[1]/nbin), nbin)
...:
...
100000 loops, best of 3: 2.55 µs per loop
======================
我建議通過這個nditer
turtorial,一直到cython實現:
https://docs.scipy.org/doc/numpy/reference/arrays.nditer.html
這是一個概念測試 - 使用nditer
在2個軸上求和:
In [543]: arr = np.arange(24).reshape(4,6)
In [544]: res = np.zeros((2,3),int)
In [545]: it = np.nditer([arr.reshape(2,2,3,2),res.reshape(2,1,3,1)],
flags=['reduce_ok','external_loop'],
op_flags=[['readonly'],['readwrite']])
In [546]: for x,y in it:
...: print(x,y)
...: y[...] += x
...:
[0 1] [0 0]
[2 3] [0 0]
[4 5] [0 0]
[6 7] [1 1]
[8 9] [5 5]
[10 11] [9 9]
[12 13] [0 0]
[14 15] [0 0]
[16 17] [0 0]
[18 19] [25 25]
[20 21] [29 29]
[22 23] [33 33]
In [547]: res
Out[547]:
array([[14, 22, 30],
[62, 70, 78]])
在Cython中,有可能像temp.sum(axis=(3,1))
一樣快temp.sum(axis=(3,1))
。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.