在 Cython 中声明一个 numpy 布尔掩码
Declaring a numpy boolean mask in Cython
我应该如何在 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
您需要通过 np.ndarray[np.uint8_t, ndim = 2, cast=True] mask = ...
"cast" np.uint8_t
到 bool
,即
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
很明显,double 数组每个元素需要 8 个字节 + 86 个字节的开销,掩码每个元素只需要一个字节。
我们还可以看到,False
由0
表示,True
由1
表示:
print (a<.5).view(np.uint8)
[1 0 1 ..., 0 0 1]
使用 cast=True
可以访问底层数组中的原始字节,这是数组内存的一种 reinterpret_cast。
Here 是一些旧信息。
我应该如何在 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
您需要通过 np.ndarray[np.uint8_t, ndim = 2, cast=True] mask = ...
"cast" np.uint8_t
到 bool
,即
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
很明显,double 数组每个元素需要 8 个字节 + 86 个字节的开销,掩码每个元素只需要一个字节。
我们还可以看到,False
由0
表示,True
由1
表示:
print (a<.5).view(np.uint8)
[1 0 1 ..., 0 0 1]
使用 cast=True
可以访问底层数组中的原始字节,这是数组内存的一种 reinterpret_cast。
Here 是一些旧信息。