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

Posted

技术标签:

【中文标题】python numpy tolist() 增加了多少开销?【英文标题】:How much overhead does python numpy tolist() add? 【发布时间】:2016-09-16 03:09:37 【问题描述】:

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

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

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

ndarray.tolist()

将数组数据的副本作为(嵌套)Python 列表返回。数据项 被转换为最接近的兼容 Python 类型。

【问题讨论】:

我在pybind github 和文档中找到了对缓冲区协议和numpy 的引用。 【参考方案1】:

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

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

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

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

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

【讨论】:

【参考方案2】:

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

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

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

有 numpy 数组与编译代码和 C 数组使用数组数据缓冲区的接口。 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);

【讨论】:

我知道。我不想为某些 pybind11 数据类型放弃 STL 数据类型。我现在结束了使用 SWIG。在我看来,SWIG 是唯一允许 python 和 c++ 文件尽可能保持原样的包装器。

以上是关于python numpy tolist() 增加了多少开销?的主要内容,如果未能解决你的问题,请参考以下文章

numpy.tolist( )函数

numpy tolist()

[Python] Scipy and Numpy

Python\Numpy:将数组与 NAN 进行比较 [重复]

Python中 list, numpy.array, torch.Tensor 格式相互转化

numpy矩阵的读取