web-dev-qa-db-ja.com

Python)の大きな整数のメモリ割り当てを理解する

Pythonはどのようにして大きな整数にメモリを割り当てますか?

int型のサイズは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
31
Vigneshwaren

_28_という低い値に対して、最初は_1_バイトなのはなぜですか?

私は信じています @ bgusachはそれに答えました 完全に; PythonはC構造体を使用して、Pythonの世界、任意のオブジェクト intsを含む =:

_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_を_uint32_のtypedefとして保持するヘッダーファイルで定義されています。

_typedef uint32_t digit;
_

sizeof(uint32_t)は_4_バイトです。これは、__PyLong_New_のsize引数が増加したときにバイト単位のサイズが増加するのを確認できる量です。


もちろん、これはCPythonがそれを実装するために選択した方法です。これは実装の詳細であるため、PEPには多くの情報がありません。対応するスレッドが見つかった場合、python-devメーリングリストで実装に関するディスカッションが行われます:-)。

いずれにせよ、他の一般的な実装では動作が異なる場合があるため、これを当然のことと考えないでください。

それは実際には簡単です。 Pythonのintは、他の言語で慣れている種類のプリミティブではなく、メソッドやすべてのものを備えた本格的なオブジェクトです。そこからオーバーヘッドが発生します。

次に、ペイロード自体、つまり表されている整数があります。そして、あなたの記憶を除いて、それに制限はありません。

Pythonのintのサイズは、数値と少しのオーバーヘッドを表すために必要なサイズです。

さらに読みたい場合は、 ドキュメントの関連部分 をご覧ください。

整数の精度は無制限です

16
bgusach