从 C 扩展对 Numpy 数组进行操作,无需内存复制
Posted
技术标签:
【中文标题】从 C 扩展对 Numpy 数组进行操作,无需内存复制【英文标题】:Operate on Numpy array from C extension without memory copy 【发布时间】:2022-01-22 15:18:21 【问题描述】:我是 NumPy 的 C extensions 的新手,我想知道以下工作流程是否可行。
-
在 NumPy 中预分配一个数组
将此数组传递给 C 扩展
在 C 中就地修改数组数据
在 Python 中将更新后的数组与标准 NumPy 函数结合使用
特别是,我希望这样做,同时确保我在任何步骤都制作零个新副本。
我熟悉 C 端的样板,例如 PyModuleDef
、PyMethodDef
和 PyObject*
参数,但我见过的很多例子都涉及对 C 数组的强制转换,据我所知,这涉及复制和/或铸造。我也知道 Cython,尽管我不知道它是否会在后台进行类似的强制或复制。我对具有数字(例如int32
)值的ndarray
上的简单索引get 和set 操作特别感兴趣。
有人可以提供一个创建 NumPy 数组、在 C 扩展中就地修改它并随后在 Python 中使用结果的最小工作示例吗?
【问题讨论】:
你想到了什么样的修改?您对numpy
数据模型的熟悉程度如何?它使用shape
、strides
和dtype
来访问data-buffer
中的元素?
cython 不会创建 numpy 数组的新副本(除非您自己专门创建它们),请参阅 Working with NumPy
@hpaulj 不是很; Array API 会是一个好的起点吗?
@AhmedAEK 通常比原始 C 扩展更喜欢 cython?
【参考方案1】:
Cython 不会创建 numpy 数组的新副本,除非您使用 numpy 函数明确要求它这样做,因此它在处理 numpy 数组时尽可能高效,请参阅Working with NumPy
在编写原始 C 模块和使用 cython 之间进行选择取决于编写模块的目的。 如果您正在编写一个仅由 python 使用的模块,以尽可能快地使用 numpy 数组执行非常小的特定任务,那么一定要使用 cython,因为它会自动正确注册模块并处理内存并防止人们在编写 C 代码时犯的常见错误(如内存管理问题),以及自动化编译器包含并允许更轻松地访问复杂的功能(如使用 numpy 迭代器)。
但是,如果您的模块要在其他语言中使用并且必须独立于 python 运行并且必须与 python 一起使用而没有任何开销,并且实现了一些复杂的 C 数据结构并且需要大量 C 功能,那么一切都意味着创建你自己的 C 扩展(甚至是 dll),你可以从 python 传递指向 numpy 数组的指针(使用numpy.ctypeslib.as_ctypes_type),或者传递 python 对象本身并返回它(但你必须创建一个 .pyd/so而不是 dll),甚至在 C 端创建 numpy 数组并由 python 管理(但您必须了解numpy C API)。
【讨论】:
谢谢,我最终选择了scikit-build 和一个 C++ 扩展。以上是关于从 C 扩展对 Numpy 数组进行操作,无需内存复制的主要内容,如果未能解决你的问题,请参考以下文章