6

16 GB の RAM を搭載した Linux Mint v12 で Matlab R2011b と R バージョン 2.13.1 を実行しています。

私はcsvファイルを持っています。最初の 5 行 (およびヘッダー) は次のとおりです。

#RIC,Date[G],Time[G],GMT Offset,Type,Price,Volume
DAEG.OQ,07-JUL-2011,15:10:03.424,-4,Trade,1.68,1008
DAEG.OQ,07-JUL-2011,15:10:03.424,-4,Trade,1.68,1008
DAEG.OQ,07-JUL-2011,15:10:03.424,-4,Trade,1.66,300
DAEG.OQ,07-JUL-2011,15:10:03.424,-4,Trade,1.65,1000
DAEG.OQ,07-JUL-2011,15:10:03.464,-4,Trade,1.65,3180

ファイルが大きい(約900MB)。文字データと数値データの組み合わせが与えられた場合、次のようにこのファイルを matlab に読み込むことができます。

fid1 = fopen('/home/MyUserName/Temp/X.csv');
D = textscan(fid1, '%s%s%s%f%s%f%f', 'Delimiter', ',', 'HeaderLines', 1);
fclose(fid1);

ファイルは 900MB ですが、上記のコードを実行すると、システム モニターは RAM の使用量が約 2GB から 10GB に跳ね上がることを示します。さらに悪いことに、少し大きな csv ファイル (約 1.2 GB) でこの同じ手順を試みると、RAM が 16 GB で最大になり、Matlab はデータの読み取りを完了できません (「ビジー」モードのままになります)。

同じファイルを R に読み込みたい場合は、次を使用できます。

D <- read.csv("/home/MyUserName/Temp/X.csv", stringsAsFactors=FALSE)

これには Matlab よりも少し時間がかかりますが、システム モニターは、R​​AM の使用量が 2GB から 3.3GB にしか跳ね上がっていないことを示しています (元のファイル サイズを考えると、はるかに妥当です)。

私の質問には2つの部分があります:

1)textscanこのシナリオでメモリを大量に消費するのはなぜですか?

2) RAM を使い果たすことなく、このタイプの 1.2GB の csv ファイルをシステムの Matlab に取得するために使用できる別の方法はありますか?

編集:明確にするために、matlab のみのソリューションが存在するかどうかについて興味があります。つまり、別の言語を使用して csv ファイルを小さなチャンクに分割するソリューションには興味がありません (これは私はすでにやっています)。Trav1 様、申し訳ありませんが、最初からこれを明確にすべきでした。

4

2 に答える 2

2

問題はおそらく、これらの「%s」文字列がMatlabのcellstrsに読み込まれていることです。これは、カーディナリティの低い文字列のメモリ効率の悪いデータ構造です。Cellstrsは、このような大きな表形式のデータにはお粗末です。各文字列は最終的に個別のプリミティブchar配列に格納され、それぞれに約400バイトのオーバーヘッドと断片化の問題が発生します。900MBのファイルでは、1800万行のように見えます。行ごとに4つの文字列。これは、これらの文字列を保持するための約10〜20GBのcellstrです。うーん。

必要なのは、これらの文字列を、1800万行すべてを一度にかさばるセル文字列にまとめるのではなく、受信時にコンパクトなプリミティブデータ型に変換することです。日付とタイムスタンプはdatenumまたは使用している数値表現として、これらの低カーディナリティ文字列は2次元char配列またはカテゴリ変数に相当するものとして使用されます。(データセットのサイズを考えると、これらの文字列は、文字ではなく、ルックアップテーブルを使用して単純な数値識別子として表される必要があります。)

コンパクトなデータ構造を決定したら、それを読み込むためのいくつかのアプローチがあります。純粋なMatlabのチャンクへの読み込みを分割することができます。textscan()ループ内の呼び出しを使用して、一度に1000行を読み込み、解析して変換します。そのチャンク内のcellstrsはコンパクトな形式になり、すべての結果をバッファリングしcat、読み取りの最後に一緒にバッファリングします。これにより、ピークメモリ要件が低く抑えられます。

このような多くの作業を行う予定で、パフォーマンスが重要な場合は、Javaにドロップダウンして、文字列と日付が入ってくるときに変換できる独自のパーサーを作成してから、Matlabに戻すことができます。よりコンパクトなデータ型。難しいことではなく、JavaメソッドはMatlabから直接呼び出すことができるため、これは別の言語を使用していると見なされるだけかもしれません。

于 2012-09-26T07:56:18.150 に答える
0

2)の場合、csvreadコマンドを使用してみることができます。パフォーマンスがどのように比較されるかはわかりませんが、少なくともそれは代替手段です。

もう1つの方法は、Cやawkなどのはるかに高速な言語を使用してファイルを読み取り、それを小さなファイルに分割することです。多くの小さなファイルを順番に読み取ると、1つの大きなファイルよりもメモリ消費量が少なくなります。

于 2012-09-19T07:10:09.463 に答える