簡體   English   中英

我可以在沒有Python交互的情況下在Cython代碼中使用Numpy操作,例如reshape嗎?

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM