web-dev-qa-db-ja.com

numpy配列の最速の保存およびロードオプション

2次元のnumpyarraysをdtype=floatおよび(1e3, 1e6)のオーダーで生成するスクリプトがあります。現在、np.savenp.loadを使用して、配列でIO操作を実行しています。ただし、これらの関数は配列ごとに数秒かかります。配列全体を保存およびロードする(つまり、その内容について仮定せずにそれらを削減する)?データが正確に保持されている限り、保存する前にarraysを別のタイプに変換できます。

33
dbliss

本当に大きなアレイの場合、いくつかのソリューションについて聞いたことがありますが、それらは主にI/Oで怠け者です。

  • NumPy.memmap 、大きな配列をバイナリ形式にマッピングします
    • 長所:
      • Numpy以外の依存関係はありません
      • ndarrayの透過的な置換(ndarrayを受け入れるクラスはmemmapを受け入れます)
    • 短所:
      • アレイのチャンクは2.5Gに制限されています
      • Numpyのスループットによってまだ制限されています
  • Python HDF5のバインディング、 PyTables または h5py などのビッグデータ対応ファイル形式

    • 長所:
      • 形式は、圧縮、インデックス作成、およびその他の素晴らしいNice機能をサポートします
      • どうやら究極のPetaByte-largeファイル形式
    • 短所:
      • 階層形式を持つ学習曲線?
      • パフォーマンスのニーズを定義する必要があります(後述)
  • Pythonのpickling system(レースではなく、速度ではなくPythonicityで言及)

    • 長所:
      • Pythonicです! (笑)
      • あらゆる種類のオブジェクトをサポート
    • 短所:
      • おそらく他のものよりも遅い(配列ではなくオブジェクトを対象としているため)

Numpy.memmap

NumPy.memmap のドキュメントから:

ディスク上のバイナリファイルに格納されている配列へのメモリマップを作成します。

メモリマップファイルは、ファイル全体をメモリに読み込まずに、ディスク上の大きなファイルの小さなセグメントにアクセスするために使用されます

Memmapオブジェクトは、ndarrayが受け入れられる場所であればどこでも使用できます。任意のmemmap fpを指定すると、isinstance(fp, numpy.ndarray)はTrueを返します。


HDF5アレイ

h5py doc から

大量の数値データを保存し、NumPyからそのデータを簡単に操作できます。たとえば、実際のNumPyアレイであるかのように、ディスクに保存されたマルチテラバイトデータセットにスライスできます。何千ものデータセットを単一のファイルに保存し、必要に応じて分類およびタグ付けすることができます。

この形式はさまざまな方法でデータの圧縮をサポートします(同じI/O読み取りに対してより多くのビットがロードされます)が、これはデータが個別にクエリするのが難しくなることを意味しますが、あなたの場合(純粋に配列をロード/ダンプする)は効率的かもしれません

36
Jiby

以下はPyTablesとの比較です。

(int(1e3), int(1e6)メモリ制限のため。したがって、より小さな配列を使用しました。

data = np.random.random((int(1e3), int(1e5)))

NumPy save

%timeit np.save('array.npy', data)
1 loops, best of 3: 4.26 s per loop

NumPy load

%timeit data2 = np.load('array.npy')
1 loops, best of 3: 3.43 s per loop

PyTablesの作成:

%%timeit
with tables.open_file('array.tbl', 'w') as h5_file:
    h5_file.create_array('/', 'data', data)

1 loops, best of 3: 4.16 s per loop

PyTablesの読み取り:

 %%timeit
 with tables.open_file('array.tbl', 'r') as h5_file:
      data2 = h5_file.root.data.read()

 1 loops, best of 3: 3.51 s per loop

数字は非常に似ています。したがって、ここではPyTablesに本当の利益はありません。しかし、SSDの最大書き込み速度と読み取り速度にかなり近づいています。

書き込み:

Maximum write speed: 241.6 MB/s
PyTables write speed: 183.4 MB/s

読書:

Maximum read speed: 250.2
PyTables read speed: 217.4

データのランダム性のため、圧縮は実際には役立ちません。

%%timeit
FILTERS = tables.Filters(complib='blosc', complevel=5)
with tables.open_file('array.tbl', mode='w', filters=FILTERS) as h5_file:
    h5_file.create_carray('/', 'data', obj=data)
1 loops, best of 3: 4.08 s per loop

圧縮データの読み取りが少し遅くなります。

%%timeit
with tables.open_file('array.tbl', 'r') as h5_file:
    data2 = h5_file.root.data.read()

1 loops, best of 3: 4.01 s per loop

これは通常のデータとは異なります。

 reg_data = np.ones((int(1e3), int(1e5)))

書き込みは非常に高速です。

%%timeit
FILTERS = tables.Filters(complib='blosc', complevel=5)
with tables.open_file('array.tbl', mode='w', filters=FILTERS) as h5_file:
    h5_file.create_carray('/', 'reg_data', obj=reg_data)

1ループ、ベスト3:ループあたり849ミリ秒

同じことが読書にも当てはまります。

%%timeit
with tables.open_file('array.tbl', 'r') as h5_file:
    reg_data2 = h5_file.root.reg_data.read()

1 loops, best of 3: 1.7 s per loop

結論:データがより規則的になればなるほど、PyTablesを使用して速くなるはずです。

21
Mike Müller

私の経験によると、np.save()&np.load()は、これまでにハードディスクとメモリ間でデータを転送する際の最速のソリューションです。この結論に気付く前に、データベースとHDFSシステムにデータをロードすることに大きく依存していました。私のテストでは、データベースデータの読み込み(ハードディスクからメモリ)の帯域幅は約50 MBps(Byets/Second)ですが、np.load()帯域幅は私のハードディスクの最大帯域幅とほぼ同じです:2GBps(Byets/2番目)。両方のテスト環境は、最も単純なデータ構造を使用します。

そして、形状のある配列をロードするのに数秒を使うことは問題ではないと思います:(1e3、1e6)。例えば。配列の形状は(1000、1000000)、データ型はfloat128、純粋なデータサイズは(128/8)* 1000 * 1,000,000 = 16,000,000,000 = 16GBytesで、4秒かかる場合、データロード帯域幅は16GBytes/4秒= 4GBps。 SATA3の最大帯域幅は600MBps = 0.6GBpsであり、データ読み込み帯域幅は既に6倍です。データ読み込みパフォーマンスはほとんど競合する可能性があります DDRの最大帯域幅 、他に何が必要ですか?

私の最終的な結論は次のとおりです。

np.save()およびnpを使用できる場合、pythonのPickleを使用しないでください。データベースを使用せず、ビッグデータシステムを使用してデータをハードディスクに保存しないでください。 。負荷()。これら2つの機能は、これまでにハードディスクとメモリ間でデータを転送するための最速のソリューションです。

HDF5 もテストしましたが、np.load()およびnp.save()よりも遅いことがわかったので、np.save()&np.load()を使用している場合は、プラットフォームに十分なDDRメモリ。

6
Clock ZHONG