将带有字符串的结构化 numpy 数组传递给 cython 函数

Posted

技术标签:

【中文标题】将带有字符串的结构化 numpy 数组传递给 cython 函数【英文标题】:Passing a structured numpy array with strings to a cython function 【发布时间】:2014-02-21 12:13:56 【问题描述】:

我正在尝试在 cython 中创建一个函数,该函数通过定义 cython 结构类型来接受 numpy 结构化数组或记录数组。假设我有数据:

a = np.recarray(3, dtype=[('a', np.float32),  ('b', np.int32), ('c', '|S5'), ('d', '|S3')])
a[0] = (1.1, 1, 'this\0', 'to\0')
a[1] = (2.1, 2, 'that\0', 'ta\0')
a[2] = (3.1, 3, 'dogs\0', 'ot\0')

(注意:下面描述的问题在有或没有空终止符的情况下都会发生)

然后我有 cython 代码:

import numpy as np
cimport numpy as np

cdef packed struct tstruct:
    np.float32_t a
    np.int32_t b
    char[5] c
    char[3] d

def test_struct(tstruct[:] x):
    cdef:
        int k
        tstruct y

    for k in xrange(3):
        y = x[k]
        print y.a, y.b, y.c, y.d

当我尝试运行 test_struct(a) 时,我收到错误:

ValueError: Expected a dimension of size 5, got 8

如果在数组和相应的结构中重新排序,使得包含字符串的字段彼此不相邻,则该函数按预期工作。似乎 Cython 函数没有正确检测 cd 字段之间的边界,并且认为您正在传递长度总和的 char 数组。

没有重新洗牌数据(这可能但不理想),是否有另一种方法将具有固定长度字符串数据的recarray传递给Cython?

更新:这似乎是一个潜在的 Cython 错误。请参阅以下有关 Cython google 组的讨论,该讨论暗示了问题出现的位置:

https://groups.google.com/forum/#!topic/cython-users/TbLbXdi0_h4

更新 2:截至 2014 年 2 月 23 日,此错误已在 Github 上的主 cython 分支中修复,该补丁计划包含在 v0.20.2 中:https://github.com/cython/cython/commit/58d9361e0a6d4cb3d4e87775f78e0550c2fea836

【问题讨论】:

我没有解决办法,只是同情。我得到与 cython 0.20 相同的错误。并且使用带有使用 align=True 创建的 dtype 的结构化数组也无济于事(请参阅 docs.scipy.org/doc/numpy/reference/generated/numpy.dtype.html)。 @WarrenWeckesser 我发布了一些类似于 cython 列表的内容,所以我希望我能在那里获得一些关注。 嗯,有没有什么魔法可以把这两个字符串加在一起? (这将使它成为 8 而不是 5)。如果在两个字符串之间插入一个 say int 数据类型会发生什么?或者省略最后一个字符串只是为了看看会发生什么。 @Magellan88 正如我在原始问题中提到的那样,如果两个字符串彼此不相邻(例如,您要将b 放在cd 之间),那么一切都可以正常工作预期的。问题是相邻字符串之间的边界似乎没有被正确检测到。 @Magellan88 真的没有魔法。 Cython 为类型检查生成代码。我跟着它,我发现循环遍历结构元素以计算长度等的部分。出于某种原因,当两个字符串一个接一个时,它只是将两个字段的长度相加。我不完全清楚为什么,以及确切的错误在哪里,因为我不熟悉 Cython 的代码 【参考方案1】:

这是截至 2014 年 2 月 22 日在 Github 上的主 cython 分支中修复的错误,该补丁计划包含在 v0.20.2 中:https://github.com/cython/cython/commit/58d9361e0a6d4cb3d4e87775f78e0550c2fea836

【讨论】:

以上是关于将带有字符串的结构化 numpy 数组传递给 cython 函数的主要内容,如果未能解决你的问题,请参考以下文章

C / C ++:将带有成员数组的结构/类按值传递给函数

如何使用 PyOpenCL 将带有数组和变量的 C 结构传递给 OpenCL 内核

如何在numpy.array中以热量方式将numpy.array传递给对象的方法

将 numpy 数组传递给 c++ 函数并返回 numpy 数组作为输出的最有效方法是啥?

将二维 C 数组传递给 python numpy

通过 SWIG 将简单的 numpy 数组传递给 C