7

我有一个 numpy 布尔数组:

myarr = np.array([[False, True], [True, False]])

如果我尝试用它初始化 Cython MemoryView,如下所示:

cdef bint[:,:] mymem = myarr

我收到此错误:

ValueError: Does not understand character buffer dtype format string ('?')

如果我这样做,它工作正常:

cdef np.int_t[:,:] mymem = np.int_(myarr)

如何使用 Cython MemoryViews 存储布尔 numpy 数组?

4

3 回答 3

8

这些信息似乎不容易找到,我的参考资料很旧(2011 年),但从那时起似乎没有太大变化。

Numpy 的布尔数组对 False/True 使用 8 位值(这本身并不明显 - C++std::vector<bool>使用例如每个值 1 位)与0-meaningFalse1-meaning True。您可以使用cast=True-arrayunit8以将其用作bool-array,例如:

 %%cython
 import numpy as np
 cimport numpy as np
 def to_bool_array(lst):
    cdef np.ndarray[np.uint8_t, ndim = 1, cast=True] res
    res=np.array(lst, dtype=bool)
    return res

现在:

 >>> to_bool_array([True,False,True,False])
 array([ True, False,  True, False], dtype=bool)

设置使 Cython 的类型检查有些松懈,因此可以重新解释cast=True具有相同元素大小(例如uint8int8和)的 numpy 数组。bool但是,如果元素大小不同,这将不起作用:例如np.int8(1byte) 和np.int16(2bytes)。

于 2018-03-06T07:01:57.420 回答
4

前段时间我遇到了同样的问题。不幸的是,我没有找到直接的解决方案。但是还有另一种方法:由于布尔值数组具有与 相同的数据类型大小uint8,因此您也可以使用具有这种类型的内存视图。内存视图中的值uint8也可以与布尔值进行比较,因此行为大多等于实际的bint内存视图:

cimport cython
cimport numpy as np
import numpy as np
ctypedef np.uint8_t uint8

cdef int i
cdef np.ndarray array = np.array([True,False,True,True,False], dtype=bool)
cdef uint8[:] view = np.frombuffer(array, dtype=np.uint8)
for i in range(view.shape[0]):
    if view[i] == True:
        print(i)

输出:

0
2
3
于 2018-03-02T10:49:32.300 回答
0

我发现这样做最简单:

cdef uint8_t[:] arr_memview8 = data.astype(np.uint8)
bool* ptr = <bool*>&arr_memview8[0]
于 2018-07-30T17:00:44.963 回答