【问题标题】:How to limit amount of memory used to store integers?如何限制用于存储整数的内存量?
【发布时间】:2017-08-02 23:23:33
【问题描述】:

当我调用sys.getsizeof(4) 时,它返回14。假设这与 C 中的 sizeof() 相同,那么这个值高得无法接受。

我想像使用一个大的原始字节数组一样使用内存数组。由于相关项目中数组的大小,内存开销是最重要的。可移植性也是一个大问题,因此使用 C 或使用更奇特的库并不是最佳选择。

有没有办法强制 Python 只使用标准 Python 3 为单个正符号字节列表或元组成员使用更少的内存?

【问题讨论】:

  • 如果您能够使用库,numpy 提供优化的数组以及用于操作它们的高效函数。您可以使用数组的 dtype 参数指定元素的内存大小。
  • 尝试使用带有合适 typecodearray.array()
  • 跟进 Marineau 的评论:array module 的文档,是标准库的一部分。
  • 太棒了,array.array() 正是我想要的,谢谢 martineau 和 Kevin!如果可能的话,我试图避免使用 numpy,numpy 很棒,只是不能 110% 确定它在这种情况下会起作用。

标签: python python-3.x memory integer byte


【解决方案1】:

(向 ma​​rtineau 致敬 his comment...)

如果您只关心无符号字节(值 [0, 255]),那么最简单的答案可能是内置的bytearray 及其不可变的兄弟bytes。 一个潜在的问题是它们旨在表示编码字符串(从外部世界读取或写入),因此它们的默认 __repr__ 是“类似字符串”,而不是整数列表:

>>> lst = [0x10, 0x20, 0x30, 0x41, 0x61, 0x7f, 0x80, 0xff]
>>> bytearray(lst)
bytearray(b'\x10 0Aa\x7f\x80\xff')
>>> bytes(lst)
b'\x10 0Aa\x7f\x80\xff'

请注意,空格、'0''A''a' 按字面意思显示,而“不可打印”值显示为 '\x##' 字符串转义序列。 如果您试图将这些字节视为一堆整数,这不是您想要的。

对于固定宽度整数或浮点数的同构数组(很像 C 语言),请使用标准库的 array module

>>> import array

# One megabyte of unsigned 8-bit integers.
>>> a = array.array('B', (n % 2**8 for n in range(2**20)))
>>> len(a)
1048576
>>> a.typecode
'B'
>>> a.itemsize
1
>>> a.buffer_info()  # Memory address, memory size.
(24936384, 1048576)

>>> a_slice = a[slice(1024, 1040)]  # Can be sliced like a list.
>>> a_slice
array('B', [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15])
>>> type(a_slice)  # Slice is also an array, not a list.
<class 'array.array'>

对于更复杂的数据,struct module 用于打包异构记录,很像 C 的 struct 关键字。 与 C 不同,我看不到任何明显的方法来创建 arraystructs。

这些数据结构都使用了 Python 的 Buffer Protocol,它(至少在 CPython 中)允许 Python 类将其内部的类 C 数组直接暴露给其他 Python 代码。 如果你需要做一些复杂的事情,你可能必须学习这个...... 或者放弃使用NumPy

【讨论】:

    【解决方案2】:

    考虑到 Python 对象必须至少具有 a pointer to its type struct and a refcount,我觉得 14 相当低。

    PyObject

    所有对象类型都是这种类型的扩展。这是一种包含 Python 需要将指向对象的指针视为对象的信息的类型。在正常的“发布”构建中,它只包含对象的引用计数和指向相应类型对象的指针。实际上没有任何东西被声明为 PyObject,但每个指向 Python 对象的指针都可以转换为 PyObject*。必须使用宏 Py_REFCNT 和 Py_TYPE 来访问成员。

    每个 Python 对象都会产生这种开销。降低开销/有效负载比率的唯一方法是拥有更多有效负载,例如在数组中(纯 Python 和 numpy)。

    这里的诀窍是数组元素通常不是 Python 对象,因此它们可以省去 refcount 和类型指针,并占用与底层 C 类型一样多的内存。

    【讨论】:

      猜你喜欢
      • 2022-08-13
      • 2013-09-02
      • 2012-09-05
      • 2020-02-06
      • 1970-01-01
      • 1970-01-01
      • 2013-09-07
      • 1970-01-01
      相关资源
      最近更新 更多