【问题标题】:Convert a std::vector to a NumPy array without copying data将 std::vector 转换为 NumPy 数组而不复制数据
【发布时间】:2013-04-10 12:27:21
【问题描述】:

我有一个 C++ 库,其中当前有一些方法返回 std::vector,定义如下

public:
  const std::vector<uint32_t>& getValues() const;

我目前正在使用 SWIG 为 Python 包装整个库,目前运行良好。

SWIG 很好地包装了这个 getValues() 函数,以便它返回一个 Python 元组。问题出在我的 Python 端代码中,我想将其转换为 NumPy 数组。当然我可以这样做:

my_array = np.array(my_object.getValues(), dtype='uint32')

但这会导致原始向量中的所有条目首先由 SWIG 复制到 Python 元组中,然后由我再次复制到 numpy 数组中。由于这个向量可能非常大,我宁愿避免制作这两个副本,并希望有一种方法让 SWIG 在内存中的原始向量数据周围创建一个 numpy.array 包装器。

我已阅读 numpy.i 的文档,但其中明确提到不支持输出数组,因为它们似乎在 C 样式数组而不是 C++ 向量的假设下工作。

numpy.array 的底层数据结构和 C++ std::vector 一样只是一个 C 样式的数组,所以我希望在内存中访问相同的数据是可行的。

有没有办法让 SWIG 返回一个不复制原始数据的 numpy.array?

【问题讨论】:

    标签: c++ python numpy swig


    【解决方案1】:

    显然将 C++ 向量“转换”为 (C) 数组是微不足道的,请参阅此问题的答案:How to convert vector to array in C++

    接下来,您可以创建一个 numpy 数组,该数组将使用该 C 数组而无需复制,请参阅 discussion here,或在 google 上查找 PyArray_SimpleNewFromData

    我不希望 SWIG 自动为您完成所有这些工作,相反,您可能应该为您的函数 getValues 自己编写一个包装器,例如 getValuesAsNumPyArray

    【讨论】:

    • 记住在调用任何PyArray_*函数之前调用import_array函数。
    【解决方案2】:

    似乎PyArray_SimpleNewFromData 需要您自己进行内存管理;如果内存管理已经在 C++ 端处理了,也就是说,Python 不负责内存,你可以使用np.asarray 来获取一个与 C++ 向量共享内存的 numpy 数组,如下所示:

    from libcpp.vector cimport vector
    import numpy as np
    cdef vector[double] vec
    vec.push_back(1)
    vec.push_back(2)
    cdef double *vec_ptr = &vec[0]    # get hold of data array underlying vec; also vec.data() if you have C++11
    cdef double[::1] vec_view = <double[:vec.size()]>vec_ptr    # cast to typed memory view
    vec_npr = np.asarray(vec_view)    # get numpy array from memory view
    print(vec_npr)    # array([1.0, 2.0])
    

    Kurt Smith 的 Cython 书籍第 10 章中的“包装 C 和 C++ 数组”部分提供了很好的示例。另见Coercion to Numpy from official user guide

    【讨论】:

    • 这导致 python 崩溃了。
    • 这行得通,但np.asarray 很慢。使用 PyArray_SimpleNewFromData 以获得更好的性能。
    猜你喜欢
    • 2017-09-29
    • 1970-01-01
    • 2020-11-07
    • 2010-12-16
    • 1970-01-01
    • 1970-01-01
    • 2017-05-09
    • 2017-05-13
    • 1970-01-01
    相关资源
    最近更新 更多