为了在Cython与SIMD内在函数(AVX)VS Numpy方法之间进行速度比较(据我所知,还提供矢量化),我建立了一个简单的求和函数:
import time
import numpy as np
cimport numpy as np
cimport cython
cdef extern from 'immintrin.h':
ctypedef double __m256d
__m256d __cdecl _mm256_load_pd(const double *to_load) nogil
void __cdecl _mm256_store_pd(double *to_store, __m256d __M) nogil
__m256d __cdecl _mm256_add_pd(__m256d __M1, __m256d __M2) nogil
@cython.boundscheck(False) # Deactivate bounds checking
@cython.wraparound(False) # Deactivate negative indexing
def sum(len,n_sums):
cdef __m256d __madd1, __madd2 , __msum
cdef double sum4[4]
len=len-(len%4)
a=np.random.rand(len)
cdef double [::1] a_view=a
cdef np.ndarray[np.float64_t,ndim=1] ca=np.copy(a)
cdef long N=n_sums, L=len, i
cdef double s=0.0
cdef Py_ssize_t j
t1=time.clock()
for i in range(N):
s=0.0
with nogil:
__madd1=_mm256_load_pd(&a_view[0])
for j in range(4,L,4):
__madd2=_mm256_load_pd(&a_view[j])
__msum=_mm256_add_pd(__madd1,__madd2)
__madd1=__msum
_mm256_store_pd(&sum4[0],__msum)
s=sum4[0]+sum4[1]+sum4[2]+sum4[3]
t2=time.clock()
print(s, sum4)
print("Cython sum", t2-t1)
t1=time.clock()
for i in range(N):
s=np.sum(ca)
t2=time.clock()
print(s)
print("np sum", t2-t1)
使用cython sum可以很好地提高速度,特别是使用小尺寸数组时。
现在,我想进一步将nogil块与OpenMP并行化。不幸的是,我找不到用cython.parallel.prange / parallel
做到这一点的方法。