2012-01-21 16 views
32

私は3GBのCSVファイルをPythonで読み込もうとしていますが、中央値の列が必要です。私はそれだけでメモリ不足エラーだと思う大規模なCSVファイル(numpy)でPythonがメモリ不足

Python(1545) malloc: *** mmap(size=16777216) failed (error code=12) 

*** error: can't allocate region 

*** set a breakpoint in malloc_error_break to debug 

Traceback (most recent call last): 

    File "Normalize.py", line 40, in <module> 

    data = data() 

    File "Normalize.py", line 39, in data 

    return genfromtxt('All.csv',delimiter=',') 

File "/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/site- 
packages/numpy/lib/npyio.py", line 1495, in genfromtxt 

for (i, line) in enumerate(itertools.chain([first_line, ], fhd)): 

MemoryError 

from numpy import * 
def data(): 
    return genfromtxt('All.csv',delimiter=',') 

data = data() # This is where it fails already. 

med = zeros(len(data[0])) 
data = data.T 
for i in xrange(len(data)): 
    m = median(data[i]) 
    med[i] = 1.0/float(m) 
print med 

私が手にエラーがこれです。私は4GBのRAMとnumpyとPythonの両方を64bitモードでコンパイルした64bit MacOSXを実行しています。

これを修正するにはどうすればよいですか?メモリ管理のためだけに、分散アプローチを試すべきですか?

おかげ

EDIT:また、これを試みたが、運...

genfromtxt('All.csv',delimiter=',', dtype=float16) 
+1

使用[pandas.read_csv](http://wesmckinney.com/blog/?p=543)それは非常に高速です。 –

答えて

58

他の人にも言われているように、本当に大きなファイルの場合は、繰り返しの方がよいでしょう。

しかし、一般的には、さまざまな理由でメモリ全体が全体的に必要になります。 (それが欠落しているデータを扱うのにloadtxtがなぜ二つの機能共存している、「リーンと平均」よりであるのに対し、)

genfromtxtはあまり効率的でloadtxt以上です。

データが非常に規則的な場合(同じタイプの単純な区切りの行など)は、numpy.fromiterを使用していずれかを改善することもできます。

あなたは十分なRAMを持っている場合は、np.loadtxt('yourfile.txt', delimiter=',')を使用することを検討してください(また、あなたは、ファイルのヘッダを持っている場合skiprowsを指定する必要があります。)

簡単な比較として、loadtxtとロード〜500MBのテキストファイルは、使用しています〜900メガバイト最大使用時にはRAMを使用し、genfromtxtと同じファイルをロードするときは〜2.5GBを使用します。

Loadtxt Memory and CPU usage of numpy.loadtxt while loading a ~500MB ascii file


Genfromtxt Memory and CPU usage of numpy.genfromtxt while loading a ~500MB ascii file


代わりには、次のようなものを考えます。非常にシンプルで通常のデータの場合にのみ機能しますが、かなり高速です。 (loadtxtgenfromtxtは、多くの推測とエラーチェックを行います。データが非常に単純で定期的なものであれば、大幅に改善することができます。)

import numpy as np 

def generate_text_file(length=1e6, ncols=20): 
    data = np.random.random((length, ncols)) 
    np.savetxt('large_text_file.csv', data, delimiter=',') 

def iter_loadtxt(filename, delimiter=',', skiprows=0, dtype=float): 
    def iter_func(): 
     with open(filename, 'r') as infile: 
      for _ in range(skiprows): 
       next(infile) 
      for line in infile: 
       line = line.rstrip().split(delimiter) 
       for item in line: 
        yield dtype(item) 
     iter_loadtxt.rowlength = len(line) 

    data = np.fromiter(iter_func(), dtype=dtype) 
    data = data.reshape((-1, iter_loadtxt.rowlength)) 
    return data 

#generate_text_file() 
data = iter_loadtxt('large_text_file.csv') 

Fromiter

Using fromiter to load the same ~500MB data file

+0

おかげさまで、どのようにメモリプロファイルを取得しましたか? – huon

+5

基本的に、ブルートフォース。 :)あなたが興味を持っているのなら、私のシェルスクリプトです:https://gist.github.com/2447356これは、エレガントなものではありませんが、十分に近いです。 –

+0

ああ、いいですね! (私は 'import memoryprofile'か何か、drat!)を期待していましたが、 – huon

4

はgenfromtxt()を使用しての問題点、すなわちに、それはメモリにファイル全体をロードしようということではありません数列。これは小さなファイルには最適ですが、あなたのような3GBの入力に対してはBADです。列中央値を計算するだけなので、ファイル全体を読む必要はありません。シンプルですが、最も効果的な方法は、ファイル全体を複数回読み取って列を繰り返し処理することです。

+0

さて、大丈夫です。しかし、これにはより持続可能な解決策がありますか? Javaプログラムのように、5GBのメモリで起動することもできます。 Pythonに相当するものはありますか?つまり、次回は4Gbの1行でCSVファイルを作成するかもしれません。 – Ihmahr

+1

Pythonは割り当て可能なメモリの量を制限しません。 64ビットPythonで 'MemoryError'を取得した場合、実際にはメモリ不足です。 –

+1

残念ながら、すべてのPythonモジュールが64ビットアーキテクチャをサポートしているわけではありません。 – cjohnson318

1

なぜPython csvモジュールを使用していませんか?

>> import csv 
>> reader = csv.reader(open('All.csv')) 
>>> for row in reader: 
...  print row 
+0

私の全プログラムでは、numpyと基本線形代数を使用しているので、読者はすべてのことができません。 – Ihmahr

+0

kz26の回答と組み合わせると、実際には回避可能な回避策が得られます。また面白い:1回の反復の後にファイルはキャッシュされ、プロセスは60から99%のCPUにジャンプします。 – Ihmahr

関連する問題