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 个小 int
s(但大于 256 以避免小 int
缓存)是(在我的 3.5.1 Windows x64 安装):
>>> sys.getsizeof([0] * 100) + sys.getsizeof(0) * 100
3264
或大约需要 3 KB 的内存。如果这些相同的值存储在 numpy
array
个 int32
中,每个数字没有 Python 个对象,也没有每个对象的指针,则大小将下降到大约 100 * 4(加上另外几十个字节,用于 array
对象开销本身),低于 500 字节。每个额外的 small int
的增量成本是对象的 24 个字节(尽管如果它在 small int 缓存中的值从 -5 到 256 IIRC 是免费的),[=12 中的存储是 8 个字节=],总共 32 个字节,而 C 级类型为 4 个字节,大约是存储要求的 8 倍(而且您仍在存储原始对象)。
如果你有足够的内存来处理它,那就这样吧。但除此之外,您可能会尝试查看一个包装,它可以让您传入缓冲协议支持对象(Py3 上的 numpy.array
、array.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);
我正在使用 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 个小 int
s(但大于 256 以避免小 int
缓存)是(在我的 3.5.1 Windows x64 安装):
>>> sys.getsizeof([0] * 100) + sys.getsizeof(0) * 100
3264
或大约需要 3 KB 的内存。如果这些相同的值存储在 numpy
array
个 int32
中,每个数字没有 Python 个对象,也没有每个对象的指针,则大小将下降到大约 100 * 4(加上另外几十个字节,用于 array
对象开销本身),低于 500 字节。每个额外的 small int
的增量成本是对象的 24 个字节(尽管如果它在 small int 缓存中的值从 -5 到 256 IIRC 是免费的),[=12 中的存储是 8 个字节=],总共 32 个字节,而 C 级类型为 4 个字节,大约是存储要求的 8 倍(而且您仍在存储原始对象)。
如果你有足够的内存来处理它,那就这样吧。但除此之外,您可能会尝试查看一个包装,它可以让您传入缓冲协议支持对象(Py3 上的 numpy.array
、array.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);