在Cython中声明一个numpy布尔掩码

问题描述 投票:0回答:1

我应该如何在Cython中声明一个布尔掩码的类型?我真的需要申报吗?这是一个例子:

cpdef my_func(np.ndarray[np.double_t, ndim = 2] array_a,
            np.ndarray[np.double_t, ndim = 2] array_b,
            np.ndarray[np.double_t, ndim = 2] array_c):

    mask = ((array_a > 1) & (array_b == 2) & (array_c == 3)
    array_a[mask] = 0.
    array_b[mask] = array_c[mask]
    return array_a, array_b, array_c
python numpy cython cythonize
1个回答
2
投票

你需要通过np.uint8_tbool“施放”到np.ndarray[np.uint8_t, ndim = 2, cast=True] mask = ...,即

cimport numpy as np
cpdef my_func(np.ndarray[np.double_t, ndim = 2] array_a,
            np.ndarray[np.double_t, ndim = 2] array_b,
            np.ndarray[np.double_t, ndim = 2] array_c):
    cdef np.ndarray[np.uint8_t, ndim = 2, cast=True] mask = (array_a > 1) & (arr
ay_b == 2) & (array_c == 3)
    array_a[mask] = 0.
    array_b[mask] = array_c[mask]
    return array_a, array_b, array_c

否则(没有cast=True)代码编译但由于类型不匹配而在运行时抛出。

但是,你根本不需要定义mask的类型,并且可以将它用作python-object:会有一些性能损失,或者更确切地说,错过了通过早期类型绑定加速一点事情的机会,但在你的情况下,无论如何它可能无关紧要。


还有一件事:我不知道你的真实代码是怎样的,但我希望你知道,cython根本不会加速你的例子 - 与numpy相比没有任何好处。


我们可以很容易地验证bool-np.array每个值使用8位(至少在我的系统上)。这根本不明显,例如它每个值只能使用一点(很像bitset):

import sys
import numpy as np
a=np.random.random((10000,))
sys.getsizeof(a)
>>> 80096
sys.getsizeof(a<.5)
>>> 10096

很明显,双数组每个元素需要8个字节+ 86个字节开销,每个元素只需要一个字节。

我们还可以看到,False0代表True1

print (a<.5).view(np.uint8)
[1 0 1 ..., 0 0 1]

使用cast=True可以访问底层数组中的原始字节,这是一种数组内存的reinterpret_cast。

Here是一些虽然陈旧的信息。

© www.soinside.com 2019 - 2024. All rights reserved.