2017-05-15 9 views
0

下の例では、大きな数字のnumpyオブジェクトを作成しています。対角線に乱数を入れてから、scipyスパース行列に変換します。私のメモリ使用量の報告は、タスクマネージャからのものです。スパース行列はどのようにメモリ使用量に影響しますか?

>>> import sys, random 
>>> import numpy as np 
>>> from scipy import sparse 
## Memory in use at this point: 3.1 Gb 
>>> m = np.zeros(shape = (40000, 40000), dtype = float) 
>>> sys.getsizeof(m) 
12800000112 
## Memory in use at this point: 3.3 Gb 
>>> for i in range(40000): 
     m[i][i] = round(random.random(),3)   
>>> sys.getsizeof(m) 
12800000112 
## Memory in use at this point: 3.3 Gb 
>>> mSp = sparse.csr_matrix(m) 
>>> sys.getsizeof(mSp) 
56 
## Memory in use at this point: 14.9 Gb 
>>> del m 
## Memory in use at this point: 3.1 Gb 

スパース行列の作成中にメモリ使用量が15ギガバイトにジャンプし、私が最初にメモリの唯一の200 Mbのを取り上げたオリジナルのnumpyのオブジェクトを削除していたときにのみ、3.1 GBに倒れ、なぜ私の質問は、あります?

これは、使用されているメモリとコミットされているメモリと何らかの関係があると考えられていますが、メカニズムを理解するためには不安定です。

編集:私はこれは疎行列でなく、現代のオペレーティングシステムの方法とは何の関係もないのWindows 10上で

+0

LinuxまたはUnixにはありますか? –

+0

いいえ、この例はWindows 10で作成されました – Tony

答えて

2

これを実行していますがメモリを割り当てる:メモリを要求すると、あなたのOSは、すぐにアドレスを返しますが、実際に物理メモリにページを割り当てることはありません。ページ内のデータに最初に触れたとき(読み取りまたは書き込み)にのみ、個々のページが割り当てられます。いくつかの値を設定するだけなので、いくつかのページが割り当てられ、タッチされなかったすべてのページは実際にはメモリにありません。

これは通常、仮想メモリ(VIRT)と物理メモリ(PHYS)として表示されます。 VIRTで説明されているが、そこには存在しないものはすべてPHYSに割り当てられていますが、まだ触れられていないメモリです。

行列をsparse.csr_matrixに変換すると、配列全体を読み取るためにSciPyが必要になるため、メモリ消費量が増加しています。これにより、オペレーティングシステムはすべてのページを割り当て、ゼロで埋め尽くします。この私たちは次の例を使用することができます理解する

:何かをインポートする前に、私のipythonカーネルは

# 2GB VIRT, 44MB PHYS 

であると我々はメモリを割り当てるが、ゼロでそれを埋めるので、私たちは何も触れていません。 VIRTをたくさん使用しますが、RAMはほとんどありません。PHYS RAMです。ランダムな値で、当社の対角を設定した後

import numpy 
array = numpy.zeros((10000, 50000)) 
# 6GB VIRT, 50MB PHYS 

私達のページのほとんどは、実際に物理的に存在し、RAMにはまだありませんので、我々は、PHYSのわずかな増加を参照してください。

# this is a more efficient way of setting the main diagonal of your array, by the way 
array[numpy.arange(10000), numpy.arange(10000)] = numpy.random.rand(10000) 
# 6GB VIRT, 90MB PHYS 

はメモリの読み取りがphyiscal割り当てトリガーするため、私たちは今、突然、使用量が増加し、当社の配列の合計を計算した場合:ランダムな値で満たされた配列を作成するときに

numpy.sum(array) 
# 6GB VIRT, 4GB PHYS 

と同じことをそれはすべてすぐに物理的に割り当てられます。

array = numpy.random.rand(10000, 50000) 
# 6GB VIRT, 4GB PHYS 

これは、スパース形式で直接スパース配列の作成が推奨される理由です:

import scipy.sparse 
sparse_array = scipy.sparse.dok_matrix((10000, 50000)) 
# 2GB VIRT, 50MB PHYS 

DOKがインデックス化することができますので、私たちは効率的

sparse_array[numpy.arange(10000), numpy.arange(10000)] = numpy.random.rand(10000) 
# 2GB VIRT, 54MB PHYS 

を行うことができ、効率的な変換ができますCSRへ:

これらの値はOSXで計算されましたが、Linux、OSX、Windowsでは一般的な原則が適用されます。

+0

詳細な応答に感謝します。仮想 '(VIRT)'メモリは 'committed'に対応しているのに対し、物理的な '(PHYS)'メモリはWindowsのタスクマネージャに表示されているように 'Memory in use'私は、私の例でゼロを使って初期行列を作成すると、「メモリが使用されていますが〜3Gbですが、コミットされたものが〜15Gbに上がります – Tony

関連する問題