将带有字符串的结构化 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 函数没有正确检测 c
和 d
字段之间的边界,并且认为您正在传递长度总和的 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
放在c
和d
之间),那么一切都可以正常工作预期的。问题是相邻字符串之间的边界似乎没有被正确检测到。
@Magellan88 真的没有魔法。 Cython 为类型检查生成代码。我跟着它,我发现循环遍历结构元素以计算长度等的部分。出于某种原因,当两个字符串一个接一个时,它只是将两个字段的长度相加。我不完全清楚为什么,以及确切的错误在哪里,因为我不熟悉 Cython 的代码
【参考方案1】:
这是截至 2014 年 2 月 22 日在 Github 上的主 cython 分支中修复的错误,该补丁计划包含在 v0.20.2 中:https://github.com/cython/cython/commit/58d9361e0a6d4cb3d4e87775f78e0550c2fea836
【讨论】:
以上是关于将带有字符串的结构化 numpy 数组传递给 cython 函数的主要内容,如果未能解决你的问题,请参考以下文章
如何使用 PyOpenCL 将带有数组和变量的 C 结构传递给 OpenCL 内核
如何在numpy.array中以热量方式将numpy.array传递给对象的方法