gpt4 book ai didi

python - Cython:在没有 NumPy 数组的情况下创建内存 View ?

转载 作者:太空狗 更新时间:2023-10-29 20:30:40 26 4
gpt4 key购买 nike

由于我发现内存 View 既方便又快速,因此我尽量避免在 cython 中创建 NumPy 数组并使用给定数组的 View 。但是,有时无法避免,不是更改现有数组而是创建一个新数组。在上层函数中这并不明显,但在通常被调用的子例程中却很明显。考虑以下功能

#@cython.profile(False)
@cython.boundscheck(False)
@cython.wraparound(False)
@cython.nonecheck(False)
cdef double [:] vec_eq(double [:] v1, int [:] v2, int cond):
''' Function output corresponds to v1[v2 == cond]'''
cdef unsigned int n = v1.shape[0]
cdef unsigned int n_ = 0
# Size of array to create
cdef size_t i
for i in range(n):
if v2[i] == cond:
n_ += 1
# Create array for selection
cdef double [:] s = np.empty(n_, dtype=np_float) # Slow line
# Copy selection to new array
n_ = 0
for i in range(n):
if v2[i] == cond:
s[n_] = v1[i]
n_ += 1
return s

分析告诉我,这里可以提高一些速度

我能做的是调整函数,有时会导致,例如计算这个向量的平均值,有时是总和。所以我可以重写它,用于求和或取平均值。但是有没有一种方法可以以非常小的开销直接创建内存 View ,动态定义大小。像首先创建一个c缓冲区使用malloc等,然后在函数结束时将缓冲区转换为 View ,传递指针和步幅或所以..

编辑 1:也许对于简单的情况,调整函数 e。 G。这样的方法是可以接受的。我只添加了一个参数和求和/取平均值。这样我就不必创建数组,并且可以在函数 malloc 中轻松处理。这不会变得更快,对吗?

# ...
cdef double vec_eq(double [:] v1, int [:] v2, int cond, opt=0):
# additional option argument
''' Function output corresponds to v1[v2 == cond].sum() / .mean()'''
cdef unsigned int n = v1.shape[0]
cdef int n_ = 0
# Size of array to create
cdef Py_ssize_t i
for i in prange(n, nogil=True):
if v2[i] == cond:
n_ += 1
# Create array for selection
cdef double s = 0
cdef double * v3 = <double *> malloc(sizeof(double) * n_)
if v3 == NULL:
abort()
# Copy selection to new array
n_ = 0
for i in range(n):
if v2[i] == cond:
v3[n_] = v1[i]
n_ += 1
# Do further computation here, according to option
# Option 0 for the sum
if opt == 0:
for i in prange(n_, nogil=True):
s += v3[i]
free(v3)
return s
# Option 1 for the mean
else:
for i in prange(n_, nogil=True):
s += v3[i]
free(v3)
return s / n_
# Since in the end there is always only a single double value,
# the memory can be freed right here

最佳答案

不知道如何处理 cpython 数组,所以我最终通过自制的“内存 View ”解决了这个问题,as proposed by fabrizioM .不会想到这会起作用。在一个紧密的循环中创建一个新的 np.array 是非常昂贵的,所以这给了我一个显着的加速。因为我只需要一个一维数组,所以我什至不必费心大步前进。但即使对于更高维的数组,我认为这也能顺利进行。

cdef class Vector:
cdef double *data
cdef public int n_ax0

def __init__(Vector self, int n_ax0):
self.data = <double*> malloc (sizeof(double) * n_ax0)
self.n_ax0 = n_ax0

def __dealloc__(Vector self):
free(self.data)

...
#@cython.profile(False)
@cython.boundscheck(False)
cdef Vector my_vec_func(double [:, ::1] a, int [:] v, int cond, int opt):
# function returning a Vector, which can be hopefully freed by del Vector
cdef int vecsize
cdef size_t i
# defs..
# more stuff...
vecsize = n
cdef Vector v = Vector(vecsize)

for i in range(vecsize):
# computation
v[i] = ...

return v

...
vec = my_vec_func(...
ptr_to_data = vec.data
length_of_vec = vec.n_ax0

关于python - Cython:在没有 NumPy 数组的情况下创建内存 View ?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21005656/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com