【问题标题】:Function in cython changes numpy array typecython 中的函数更改 numpy 数组类型
【发布时间】:2019-07-02 09:29:10
【问题描述】:

我正在使用 Cython 和 numpy,并且有一个奇怪的问题与改变 numpy 数组元素的 dtype 的 cython 函数有关。奇怪的是,只有当实际指定数组的输入类型时,dtype才会改变。

我在 Ubuntu 18.04 上使用 Cython==0.29.11、numpy==1.15.4、python 3.6。

# cyth.pyx
cimport numpy as np

def test(x):
    print(type(x[0]))

def test_np(np.ndarray[np.uint32_t, ndim=1] x):
    print(type(x[0]))

现在对这个文件进行 cythonising 并使用函数:

>>> from cyth import test, test_np
>>> import numpy as np
>>> a = np.array([1, 2], dtype=np.uint32)
>>> test(a)
<class 'numpy.uint32'>
>>> test_np(a)
<class 'int'>

所以test 按预期工作,打印输入数组中第一个元素的类型 - 一个 uint32。但是test_np,它实际上确保传入数组的类型是 uint32,现在将常规 Python int 显示为第一个元素的类型。

即使试图强制元素为正确类型也不起作用,即使用:

def test_np(np.ndarray[np.uint32_t, ndim=1] x):
    cdef np.uint32_t el
    el = x[0]
    print(type(el))

还是有结果

>>> test_np(a)
<class 'int'>

对于理解这种差异的任何帮助将不胜感激。

【问题讨论】:

    标签: python numpy cython


    【解决方案1】:

    Cython 不会改变数组的类型,而是返回一个类型稍有不同的元素。

    numpy-array 中的数据存储为 32 位无符号整数的连续字段。访问 x[0] 意味着创建一个 Python 对象(因为 Python 解释器无法处理原始 C-int) - numpy 为每个 numpy-dtype 都有一个专用的包装类并返回一个 np.uint32-object。

    另一方面,Cython 将所有 C 整数类型(例如 longint 等)简单地映射到 Python 整数(这很有意义)。

    现在,当 cimported numpy 时,x[0] 不再意味着使用 numpy-array 的 __getitem__()(将返回 np.uint32-object),而是使用 C 整数(在本例中为无符号 4 字节),即转换为 Python 整数,因为“返回 XXX”在 def 函数中意味着结果必须是 Python 对象。

    这确实意味着该数组具有不同的类型 - 当 Cython 转换为 Python 对象时,类型的映射不同。


    如果您想以np.uint32-objects 的身份访问数据,您可以调用__getitem__ 而不是[..][..] 被 Cython 翻译为对原始 C 数据的访问):

    %%cython
    cimport numpy as np
    
    def test_np(np.ndarray[np.uint32_t, ndim=1] x):
        print(type(x[0]))                     # int
        print(type(x.__getitem__(0)))         # numpy.uint32
    

    当您使用类型化内存视图而不是 ndarray 时,直接调用 __getitem__ 将返回内存视图的 Python 整数 __getitem__ 不会调用底层 ndarray 的 __getitem__ 而是访问 C 上的数据-等级。调用底层对象的__getitem__进行内存查看:

    def test_np(np.uint32_t[:] x):
        print(type(x[0]))
        print(type(x.base.__getitem__(0))) # instead of x.__getitem__(0)
    

    【讨论】:

      猜你喜欢
      • 2012-03-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-05-31
      相关资源
      最近更新 更多