从 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 端的样板,例如 PyModuleDefPyMethodDefPyObject* 参数,但我见过的很多例子都涉及对 C 数组的强制转换,据我所知,这涉及复制和/或铸造。我也知道 Cython,尽管我不知道它是否会在后台进行类似的强制或复制。我对具有数字(例如int32)值的ndarray 上的简单索引get 和set 操作特别感兴趣。

有人可以提供一个创建 NumPy 数组、在 C 扩展中就地修改它并随后在 Python 中使用结果的最小工作示例吗?

【问题讨论】:

你想到了什么样的修改?您对numpy 数据模型的熟悉程度如何?它使用shapestridesdtype来访问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 数组进行操作,无需内存复制的主要内容,如果未能解决你的问题,请参考以下文章

NumPy:数组计算

Numpy基本操作

学习基础知识:数组和矢量计量Numpy

Numpy库使用

利用Python进行数据分析——Numpy基础:数组和矢量计算

Numpy基础学习