5

我最近开始使用Boost 的 Python库来包装一个相当大的 C++ 库的一部分。

很偶然,我发现 Boost Python 创建的每个 Python 对象至少比 Python 列表的大小要大。

简单类型

使用C-Python API 文档中的noddy_NoddyType示例,我可以很容易地公开一个新的对象类型实例,.noddy_NoddyObject

使用原始 C-Python API,这就像自定义 Python 对象一样小而简单:-

>>> import noddy, sys

>>> print sys.getsizeof( noddy.Noddy )   # PyTypeObject size?
872
>>> print sys.getsizeof( noddy.Noddy() ) # PyObject size
16

并与基础对象进行比较:-

>>> print sys.getsizeof( object )
872
>>> print sys.getsizeof( object() )
16

不出所料,但是当我noddy_NoddyObject使用 Boost Python 公开时呢?

>>> print sys.getsizeof( noddy.Noddy )
904
>>> print sys.getsizeof( noddy.Noddy() )
80

说什么?!!这并不理想......对象实例比它们需要的大 5 倍!

(这在非 64 位机器上会有所不同。)

在 Boost Python wiki 上,有一些关于额外膨胀的解释:-

内存消耗

一般来说,一个带有对应 Python 对象的包装 C++ 对象的大小为:

  • 一个新型类(派生自 Python 中的“对象”)实例加上
  • 允许实例中的可变长度数据所需的额外大小,加上
  • C++ 对象的大小,加上
  • vtable 指针的大小,加上指向 C++ 对象的实例持有者的指针,加上
  • 确保实例持有者正确对齐所需的零个或多个字节的填充。

你可以在boost/python/object/instance.hpp. instance<value_holder<T> >对于某些 C++ 类,大多数 Python 对象由 , 表示T

但显然没有迹象表明如何减少实例大小,也没有说明如何使用自定义PyTypeObject.

序列类型

因此,在 中,您可以在其基类的声明中instance.hpp看到 allboost::python::instance的使用。这可以解释 Boost Python-compiled的PyObject_VAR_HEAD大小与 Python 的大小更相似,或者:-noddy_NoddyObjectlistnumpy.array

>>> print sys.getsizeof( list )
872
>>> print sys.getsizeof( list() )
72
>>> print sys.getsizeof( numpy.array )
72
>>> print sys.getsizeof( numpy.array() )
80

(哦,这很有趣..如果我没记错的话,numpy.array是最小PyObject实例的大小,比 a 小得多PyTypeObject。我想知道那里的含义是什么..)

内存管理

除了对象大小之外,让我关注的问题是堆事务之一。我有一个 C++ 基类,它几乎完全由与内存管理相关的功能组成:它有newdelete运算符;大量与引用计数相关的方法,并被大约一百个其他 C++ 类继承。

曾经阅读过定义新类型的 C-Python API 文档,我认为这里适合使用新类型。通过定义一个新PyTypeObject结构,并将其成员(tp_alloc等)指向 C++ 类的运算符和成员函数,我想我可以让 Python 解释器直接调用 C++ 成员函数。派生类类型将不会在典型boost::python::object实例和(已托管的)C++ 类之间复制任何功能。

使用bp::class_<>模板,我认为 C++ 代码和 Python 代码都将分别管理类实例的内存,这似乎可能非常低效。

做一个新的PyTypeObject

通过使用新的PyTypeObject,我认为我所有的担忧都会得到解决。简单对象的内存占用可能要小得多(如果我能noddy_NoddyObject减少到 24 个字节,我会非常高兴),而且管理内存的方式似乎会有更大的灵活性。

那么,有没有其他人觉得需要定义一个新的PyTypeObject,不同于 Boost Python 实例的默认值?怎么办?

通过使用更大的基本类型,Boost 似乎正在失去效率和灵活性。减肥总是比增重更痛苦。

4

0 回答 0