python numpy tolist() 添加了多少开销?

How much overhead does python numpy tolist() add?

我正在使用 python 程序,该程序使用 numpy 数组作为数组的标准数据类型。对于繁重的计算,我将数组传递给 C++ 库。为此,我使用 pybind。但是,我必须使用 python list。我通过 numpy 数组和 list 进行转换:

NativeSolver.vector_add(array1.tolist(), array2.tolist(), ...)

此转换会产生多少开销?我希望它不会创建一个全新的副本。 Numpy 参考资料说:

ndarray.tolist()

Return a copy of the array data as a (nested) Python list. Data items are converted to the nearest compatible Python type.

很多。对于简单的内置类型,您可以在对象上使用 sys.getsizeof 来确定与该对象关联的内存开销(对于容器,这不包括存储在其中的值,仅包括用于存储它们的指针)。

因此,例如,一个 list 的 100 个小 ints(但大于 256 以避免小 int 缓存)是(在我的 3.5.1 Windows x64 安装):

>>> sys.getsizeof([0] * 100) + sys.getsizeof(0) * 100
3264

或大约需要 3 KB 的内存。如果这些相同的值存储在 numpy arrayint32 中,每个数字没有 Python 个对象,也没有每个对象的指针,则大小将下降到大约 100 * 4(加上另外几十个字节,用于 array 对象开销本身),低于 500 字节。每个额外的 small int 的增量成本是对象的 24 个字节(尽管如果它在 small int 缓存中的值从 -5 到 256 IIRC 是免费的),[=12 中的存储是 8 个字节=],总共 32 个字节,而 C 级类型为 4 个字节,大约是存储要求的 8 倍(而且您仍在存储原始对象)。

如果你有足够的内存来处理它,那就这样吧。但除此之外,您可能会尝试查看一个包装,它可以让您传入缓冲协议支持对象(Py3 上的 numpy.arrayarray.array、通过 memoryview 切片分配填充的 ctypes 数组等)所以不需要转换为 Python 级别类型。

是的,它将是新副本。数组的数据布局与列表的数据布局非常不同。

数组具有形状和步幅等属性,以及包含元素的一维数据缓冲区 - 只是一组连续的字节。这是将它们视为浮点数、整数、字符串、1d、2d 等的其他属性和代码。

列表是指针缓冲区,每个指针指向内存中其他地方的对象。它可能指向一个数字、一个字符串或另一个列表。它不会指向数组的数据缓冲区或其中的元素。

有使用数组数据缓冲区的编译代码和 C 数组的接口 numpy 数组。 cython 是常见的。还有一个关于 numpy 的 C API 的完整文档部分。我对pbind一无所知。如果它需要一个列表界面,它可能不是最好的。

当我用 tolist() 完成 timeit 测试后,它似乎并没有那么昂贵。

=======================

但是查看 pybind11 github 我发现了很多对 numpy 和这个

的引用

http://pybind11.readthedocs.io/en/latest/advanced.html#numpy-support

文档页面。它支持缓冲协议和 numpy 数组。所以您不必完成 tolist 步骤。

#include <pybind11/numpy.h>
void f(py::array_t<double> array);