3

大規模なデータ行列を使用して計算を行うプロジェクトに取り組んでいます。10,000 行と 100 列の CSV ファイルがあり、そのうち 10 個あります。現在、各 CSV からデータを読み取り、それを配列に取り込み、データに対していくつかの行列乗算計算を実行してから、次の CSV に移動するバックグラウンド ジョブを実行しています。ジョブの処理にかかる時間の大部分は CSV を開くのに費やされているように見えるので、これを行うためのより良い方法があると確信しています。私の質問は、現在これらの CSV ファイルにあるデータをどのように保存して、簡単にアクセスし、より効率的な方法で計算を実行するかということです。どんな助けでもいただければ幸いです

編集

コメントで示唆されているように、マトリックス密度は 100% であり、数値はすべて浮動小数点であることを付け加えたいと思います。

4

3 に答える 3

4

CSV は、あらゆる種類の大規模データに対して非常に効率の悪い形式です。すべてのデータが数値であり、データ サイズが一貫しているという事実を考えると、コンパクトなバイナリ形式が最適です。データをネットワーク バイト オーダーで 1,000,000 個の 4 バイト整数のバイナリ ファイルとして保存すると、最初の 100 が最初の行、2 番目が 2 番目、というように、ファイル サイズが 12 MB から 8 MB に削減され、完全にCSV の解析の非効率性を取り除きます (これは実際には非効率的です)。データをこの形式に変換するには、次の Ruby コードを実行してみてください (データは CSV の 2 次元配列であると想定しています)。

newdat = data.flatten.map {|e| e.to_f}.pack("G*")

次に、newdat を新しいデータとしてファイルに書き込みます。

f = File.open("data.dat", 'wb')
f.write(newdat)
f.close

ファイルからこのデータを解析するには:

data = File.open("data.dat", 'rb').read.unpack("G*").each_slice(100).to_a

これにより、データが 2 次元配列としてマトリックスに設定されます。

注: フロートでいっぱいの巨大な CSV ファイルが転がっているわけではないので、実際にこれの効率について正確な数値を示すことはできません。ただし、これははるかに効率的です。

于 2013-11-01T18:43:40.343 に答える
2

Marshal配列をバイナリで保存するために使用することを検討しましたか? 私はそれを使用していませんが、非常に単純なようです:

FNAME = 'matrix4.mtx'
a = [2.3, 1.4, 6.7]

File.open(FNAME, 'wb') {|f| f.write(Marshal.dump(a))}
b = Marshal.load(File.binread(FNAME)) # => [2.3,1.4,6.7]

もちろん、配列全体をメモリに読み込む必要がありますが、配列は現在の標準ではそれほど大きくないようです。

于 2013-11-01T23:16:01.520 に答える
1

いつでもファイルを NMatrix にロードしてから、 を使用して NMatrix バイナリ形式で保存できますNMatrix#writeNMatrixにはまだ CSV リーダーとライターが必要ですが、実装はかなり簡単だと思います。

x.write("mymatrix.binary")

以降:

y = NMatrix.read("mymatrix.binary")
# => NMatrix

高密度ストレージと疎ストレージの両方を処理できます。

于 2013-11-19T00:55:05.300 に答える