在 Cython 中访问 NumPy 记录数组列
我是一位相对经验丰富的 Python 程序员,但很长一段时间没有编写任何 C 语言,并且正在尝试理解 Cython。我正在尝试编写一个 Cython 函数,该函数将在 NumPy 记录的列上进行操作。
到目前为止我的代码如下。
recarray_func.pyx:
import numpy as np
cimport numpy as np
cdef packed struct rec_cell0:
np.float32_t f0
np.int64_t i0, i1, i2
def sum(np.ndarray[rec_cell0, ndim=1] recarray):
cdef Py_ssize_t i
cdef rec_cell0 *cell
cdef np.float32_t running_sum = 0
for i in range(recarray.shape[0]):
cell = &recarray[i]
running_sum += cell.f0
return running_sum
在解释器提示符下:
array = np.recarray((100, ), names=['f0', 'i0', 'i1', 'i2'],
formats=['f4', 'i8', 'i8', 'i8'])
recarray_func.sum(array)
这只是对 rearray 的 f0
列求和。它编译并运行没有问题。
我的问题是,如何修改它以便它可以在任何列上运行?在上面的示例中,要求和的列是硬编码的,并通过点表示法访问。是否可以更改函数,以便将要求和的列作为参数传入?
I'm a relatively experienced Python programmer, but haven't written any C in a very long time and am attempting to understand Cython. I'm trying to write a Cython function that will operate on a column of a NumPy recarray.
The code I have so far is below.
recarray_func.pyx:
import numpy as np
cimport numpy as np
cdef packed struct rec_cell0:
np.float32_t f0
np.int64_t i0, i1, i2
def sum(np.ndarray[rec_cell0, ndim=1] recarray):
cdef Py_ssize_t i
cdef rec_cell0 *cell
cdef np.float32_t running_sum = 0
for i in range(recarray.shape[0]):
cell = &recarray[i]
running_sum += cell.f0
return running_sum
At the interpreter prompt:
array = np.recarray((100, ), names=['f0', 'i0', 'i1', 'i2'],
formats=['f4', 'i8', 'i8', 'i8'])
recarray_func.sum(array)
This simply sums the f0
column of the recarray. It compiles and runs without a problem.
My question is, how would I modify this so that it can operate on any column? In the example above, the column to sum is hard coded and accessed through dot notation. Is it possible to change the function so the column to sum is passed in as a parameter?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
我相信使用 Cython 的 memoryviews 应该可以实现这一点。按照这些思路应该可以工作(代码未测试):
通过确保传递给 Cython 的记录数组是连续的,可以提高速度。在Python(调用)端,您可以使用
np.require
,而函数签名应更改为rec_cell0[::1] recview
以指示该数组可以是假设是连续的。与往常一样,一旦代码经过测试,请关闭boundscheck
、wraparound
和nonecheck
编译器指令 可能会进一步提高速度。I believe this should be possible using Cython's memoryviews. Something along these lines should work (code not tested):
Speed can probably be increased by ensuring that the record array you pass to Cython is contiguous. On the python (calling) side, you can use
np.require
, while the function signature should change torec_cell0[::1] recview
to indicate that the array can be assumed to be contiguous. And as always, once the code has been tested, turning off theboundscheck
,wraparound
andnonecheck
compiler directives in Cython will likely further improve speed.你想要的需要弱类型,而 C 没有。如果您的所有记录类型都相同,您可能能够完成类似的操作:(免责声明,我在这台机器上没有 Cython,所以我是盲码)。
What you want requires weak typing, which C doesn't have. If all your record types are the same you might be able to pull off something like: (disclaimer I don't have Cython on this machine so I am coding blind).