たとえば、100万(32ビット)の整数のリストを格納するために必要なメモリはどれくらいですか?
alist = range(1000000) # or list(range(1000000)) in Python 3.0
たとえば、100万(32ビット)の整数のリストを格納するために必要なメモリはどれくらいですか?
alist = range(1000000) # or list(range(1000000)) in Python 3.0
"場合によります。" Pythonは、リストに要素を追加するための償却定数時間を達成するような方法で、リストにスペースを割り当てます。
実際には、これが現在の実装で意味することは...リストには常に2の累乗の要素に割り当てられたスペースがあります。したがって、range(1000000)は、実際には2 ^ 20要素(約104万5000)を保持するのに十分な大きさのリストを割り当てます。
これは、リスト構造自体(各要素のPythonオブジェクトへのポインターの配列)を格納するために必要なスペースのみです。32ビットシステムは要素ごとに4バイトを必要とし、64ビットシステムは要素ごとに8バイトを使用します。
さらに、実際の要素を格納するためのスペースが必要です。これは大きく異なります。小さい整数(現在は-5から256)の場合、追加のスペースは必要ありませんが、大きい数の場合、Pythonは整数ごとに新しいオブジェクトを割り当てます。これは10〜100バイトを要し、メモリを断片化する傾向があります。
結論:それは複雑であり、Pythonリストは大規模な同種のデータ構造を格納するための良い方法ではありません。そのためには、array
モジュールを使用するか、ベクトル化された計算を行う必要がある場合は、NumPyを使用します。
PS-タプルは、リストとは異なり、要素が段階的に追加されるようには設計されていません。アロケータがどのように機能するかはわかりませんが、大規模なデータ構造にアロケータを使用することさえ考えていません:-)
便利なリンク:
Pythonオブジェクトのメモリサイズ/使用量を取得する方法
データをディクショナリに入れる場合、データ サイズはどのように計算しますか?
しかし、彼らは決定的な答えを与えません。行く方法:
リストの有無にかかわらず、Python インタープリターによって消費されるメモリを測定します (OS ツールを使用)。
ある種の sizeof(PyObject) を定義するサードパーティの拡張モジュールを使用します。
更新:
レシピ 546530: Python オブジェクトのサイズ (改訂版)
import asizeof
N = 1000000
print asizeof.asizeof(range(N)) / N
# -> 20 (python 2.5, WinXP, 32-bit Linux)
# -> 33 (64-bit Linux)
質問の「タプル」部分に対処する
典型的なビルド構成でのCPythonのPyTupleの宣言は、次のように要約されます。
struct PyTuple {
size_t refcount; // tuple's reference count
typeobject *type; // tuple type object
size_t n_items; // number of items in tuple
PyObject *items[1]; // contains space for n_items elements
};
PyTupleインスタンスのサイズは、構築中に固定され、後で変更することはできません。PyTupleが占めるバイト数は、次のように計算できます。
sizeof(size_t) x 2 + sizeof(void*) x (n_items + 1)
。
これにより、タプルのサイズが浅くなります。フルサイズを取得するには、PyTuple::items[]
配列をルートとするオブジェクトグラフによって消費される合計バイト数も追加する必要があります。
タプル構築ルーチンは、空のタプルの単一インスタンスのみが作成されることを確認することに注意してください(シングルトン)。
新しい関数、
getsizeof()
は、Pythonオブジェクトを受け取り、オブジェクトが使用するメモリの量をバイト単位で返します。組み込みオブジェクトは正しい結果を返します。サードパーティの拡張機能はそうではないかもしれませんが__sizeof__()
、オブジェクトのサイズを返すメソッドを定義できます。
kveretennicov@nosignal:~/py/r26rc2$ ./python
Python 2.6rc2 (r26rc2:66712, Sep 2 2008, 13:11:55)
[GCC 4.2.3 (Ubuntu 4.2.3-2ubuntu7)] on linux2
>>> import sys
>>> sys.getsizeof(range(1000000))
4000032
>>> sys.getsizeof(tuple(range(1000000)))
4000024
明らかに返される数値には、含まれているオブジェクトによって消費されたメモリは含まれていません(sys.getsizeof(1)== 12)。
これは実装固有のものであり、私はかなり確信しています。確かに、それは整数の内部表現に依存します-Pythonは任意の大きな整数を提供するため、おそらく小さな整数がよりコンパクトに格納されるため、32ビットとして格納されるとは想定できません。
私のPython(コア2デュオのFedora 9では2.5.1)では、割り当て前のVmSizeは6896kB、後は22684kBです。さらに100万個の要素が割り当てられると、VmSizeは38340kBになります。これは、1000000整数で約16000kBを非常に大まかに示しています。これは、整数あたり約16バイトです。これは、リストに多くのオーバーヘッドがあることを示しています。私はこれらの数字を塩の大きなつまみで取ります。