题 了解Python中大整数的内存分配


Python如何为大整数分配内存?

一个 int type的大小 28 bytes 随着我不断增加的价值 int,大小以增量递增 4 bytes

  1. 为什么 28 bytes 最初的任何值都低至 1

  2. 为什么增量 4 bytes

PS:我在x86_64(64位机器)上运行Python 3.5.2。关于(3.0+)解释器如何处理如此庞大的数字的任何指针/资源/ PEP都是我正在寻找的。

代码说明尺寸:

>>> a=1
>>> print(a.__sizeof__())
28
>>> a=1024
>>> print(a.__sizeof__())
28
>>> a=1024*1024*1024
>>> print(a.__sizeof__())
32
>>> a=1024*1024*1024*1024
>>> print(a.__sizeof__())
32
>>> a=1024*1024*1024*1024*1024*1024
>>> a
1152921504606846976
>>> print(a.__sizeof__())
36

29
2017-10-31 14:25


起源




答案:


为什么 28 最初的字节数为低至的任何值 1

我相信 @bgusach回答说 彻底; Python使用 C 用于表示Python世界中任何对象的对象的结构 包含 int小号

struct _longobject {
    PyObject_VAR_HEAD
    digit ob_digit[1];
};

PyObject_VAR_HEAD 是一个宏,当展开时添加结构中的另一个字段(字段 PyVarObject 它专门用于有一些长度概念的物体)和 ob_digits 是一个包含数字值的数组。锅炉板尺寸来自该结构,小型  大型Python数字。

为什么增量 4 字节?

因为,当创建一个更大的数字时,大小(以字节为单位)是该数字的倍数 sizeof(digit);你可以看到 _PyLong_New 在哪里为新的内存分配 longobject 是用。进行的 PyObject_MALLOC

/* Number of bytes needed is: offsetof(PyLongObject, ob_digit) +
   sizeof(digit)*size.  Previous incarnations of this code used
   sizeof(PyVarObject) instead of the offsetof, but this risks being
   incorrect in the presence of padding between the PyVarObject header
   and the digits. */
if (size > (Py_ssize_t)MAX_LONG_DIGITS) {
    PyErr_SetString(PyExc_OverflowError,
                    "too many digits in integer");
    return NULL;
}
result = PyObject_MALLOC(offsetof(PyLongObject, ob_digit) +
                         size*sizeof(digit));

offsetof(PyLongObject, ob_digit) 是长对象的'样板'(以字节为单位),与保持其值无关。

digit 是在头文件中定义的 struct _longobject 作为一个 typedef 对于 uint32

typedef uint32_t digit;

sizeof(uint32_t) 是 4 字节。这是你看到的大小以字节为单位的数量 size 论证 _PyLong_New 增加。


当然,这只是如何 CPython已选择实现它。这是一个实现细节,因此您不会在PEP中找到太多信息。如果你能找到相应的线程,python-dev邮件列表将进行实现讨论:-)。

无论哪种方式,您可能会在其他流行的实现中发现不同的行为,因此不要认为这是理所当然的。


22
2017-10-31 16:03





这很容易。 Python的 int 不是你可能习惯于其他语言的原始类型,而是一个完整的对象,它的方法和所有的东西。这就是开销来自的地方。

然后,您拥有有效负载本身,即正在表示的整数。除了记忆之外,没有限制。

Python的大小 int 是什么需要代表数字加上一点开销。

如果您想进一步阅读,请查看 文件的相关部分

整数具有无限的精度


16
2017-10-31 14:32



谢谢。是否有一个PEP解释了如何在最近的Python版本(3.0+)中完成此操作? - Vigneshwaren
@Vigneshwaren这是您正在使用的任何解释器的实现细节。 Python-the-language只保证一个 int 有任意精度,而不是如何完成。 - chepner
@Vigneshwaren:您可以查看CPython的基本信息 sys.int_info (long_info 在2.7)。基本上,每个 sys.int_info.bits_per_digit 绝对量值(符号无关)或其中的一部分需要额外的 sys.int_info.sizeof_digit 要存储的字节数。注意:小 ints被缓存在CPython中,因此作为实现细节,从(IIRC)-5到256的值是单例;你只需要为引用它们的指针支付4-8个字节,而不是对象本身的成本。 - ShadowRanger