为什么 Cython 期望 0 维?

Why does Cython expect 0 dimensions?

我已将我的问题归结为一个可重现的小测试用例:

在文件 1 (custom_cython.pyx) 中我有以下内容:

import numpy as np
cimport numpy as np
cimport cython

ctypedef np.uint8_t DTYPE_B_t
ctypedef np.uint16_t CELL_ID_t
ctypedef np.int64_t DTYPE_INT64_t


cdef struct LOOKUPMEM_t:
    DTYPE_B_t filled_flag
    CELL_ID_t key_i
    CELL_ID_t key_j
    CELL_ID_t key_k
    DTYPE_INT64_t offset
    DTYPE_INT64_t num_elements  


cdef LOOKUPMEM_t[:] lookup_memory


my_dtype = [("filled_flag", np.uint8, 1),
            ("ijk", np.uint16, 3),
            ("offset_and_num", np.int64, 2)]

input_numpy_dtype = np.dtype(my_dtype, align=True)

lookup_memory = np.zeros(5000, dtype=input_numpy_dtype)

在文件 2 (custom_cython_test.py) 中,我有以下内容:

from custom_cython import lookup_memory

print(lookup_memory)

当我 运行 python custom_cython_test.py 我最终在 lookup_memory = np.zeros(5000, dtype=input_numpy_dtype)

行上得到 ValueError: Expected 0 dimension(s), got 1

在我的结构定义中,我尝试在 dtype 创建中使用 cdef packed struct LOOKUPMEM_talign=False,这会产生相同的错误。

我正在使用 Python 3.7.3,Cython 版本 0.29.12 和 Numpy 1.16.4。

我之前已经成功地将 cython memoryviews 分配给一维 numpy 数组,所以我很困惑为什么我明显的 1d cdef LOOKUPMEM_t[:] lookup_memory 期望 0 维。谁能告诉我这是怎么回事?

问题似乎出在你的结构的这一部分:

    CELL_ID_t key_i
    CELL_ID_t key_j
    CELL_ID_t key_k

结合你的数据类型的这一部分:

("ijk", np.uint16, 3)

对于您的组合 offset_and_num 字段也是如此。

问题是,当 memoryview 接口看到像 ("ijk", np.uint16, 3) 这样的类似元组的字段时,它想将其解压缩为 3 个元素的一维数组,但结构中的下一个键只是 CELL_ID_t key_i,一个 0-D 标量。

如果我更改您的结构以更接近地匹配 Numpy dtype 它会起作用:

cdef struct LOOKUPMEM_t:
    DTYPE_B_t filled_flag
    CELL_ID_t ijk[3]
    DTYPE_INT64_t offset_num_elements[2]

所以你有几个选择如何继续。如果你真的想保持你的结构不变,你可以这样做,并以不同的方式格式化数据类型。由于很容易查看具有不同 dtype 的 Numpy 数组,如果您想为其他用例保留现有的 dtype 格式,您也可以使用不同的 dtype 进行内存视图初始化。