25

1 つまたは複数の大きなNumpy配列に対して多くの中間操作を実行しなければならない場合があります。これにより、すぐにMemoryErrors が発生する可能性があります。これまでの調査で、Pickling (Pickle、CPickle、Pytables など)gc.collect()がこれを軽減する方法であることがわかりました。経験豊富なプログラマーが大量のデータを処理するときに使用する他の手法があるかどうか疑問に思っていました (もちろん、戦略/コードの冗長性を取り除くこと以外に)。

また、私が確信していることが 1 つあるとすれば、無料のものは何もないということです。これらの手法のいくつかには、どのようなトレードオフがありますか (つまり、速度、堅牢性など)?

4

5 に答える 5

28

私はあなたの痛みを感じます...後で破棄する値に配列のサイズの数倍を格納することになることがあります。配列内の 1 つの項目を一度に処理する場合、これは無関係ですが、ベクトル化するときに失敗する可能性があります。

説明のために仕事の例を使用します。私は最近、ここで説明するアルゴリズムを numpy を使用してコーディングしました。RGB 画像を CMYK 画像に変換するカラー マップ アルゴリズムです。ピクセルごとに繰り返されるプロセスは次のとおりです。

  1. すべての RGB 値の最上位 4 ビットを、3 次元ルックアップ テーブルのインデックスとして使用します。これにより、LUT 内の立方体の 8 つの頂点の CMYK 値が決まります。
  2. 前の手順の頂点値に基づいて、すべての RGB 値の最下位 4 ビットを使用して、そのキューブ内で補間します。これを行う最も効率的な方法は、処理される画像のサイズの uint8 の 16 個の配列を計算することです。24 ビット RGB 画像の場合、処理するために画像の x6 倍のストレージが必要になるのと同じです。

これを処理するためにできることがいくつかあります。

1.分割統治

1,000x1,000 の配列を 1 回のパスで処理できない場合があります。しかし、100x1,000 の 10 個の配列を反復する python for ループでそれを実行できる場合でも、1,000,000 項目を超える python イテレーターよりはるかに優れています! はい、遅くなりますが、それほどではありません。

2. 高価な計算をキャッシュする

これは、上記の補間の例に直接関係しており、見つけにくいですが、目を光らせておく価値があります。各次元に 4 ビットの 3 次元立方体を補間しているため、16x16x16 バイトの 16 個の配列に格納できる結果は 16x16x16 しかありません。したがって、それらを事前に計算して 64KB のメモリを使用して格納し、画像全体の値を 1 つずつ検索することができます。メモリを大量に消費してすべてのピクセルに対して同じ操作をやり直す必要はありません。これは、64x64 ピクセル程度の小さな画像にはすでに効果があり、基本的に、配列を再分割することなく、ピクセル量の x6 倍の画像を処理できます。

3.dtypes賢く使う

中間値が単一の に収まる場合はuint8、 の配列を使用しないでくださいint32。これは、サイレントオーバーフローによる不可解なエラーの悪夢に変わる可能性がありますが、注意すれば、リソースを大幅に節約できます。

于 2013-01-16T05:47:34.567 に答える
10

最初の最も重要なトリック:いくつかの大きなアレイを割り当て、それらの一部を使用してリサイクルするのではなく、一時的なアレイを大量に収集して廃棄/ガベージコレクションします。少し古風に聞こえますが、注意深くプログラミングすると、スピードアップが印象的です。(アライメントとデータの局所性をより適切に制御できるため、数値コードをより効率的にすることができます。)

2番目:numpy.memmapディスクへのアクセスのOSキャッシングが十分に効率的であることを使用し、期待します。

3番目:@Jaimeが指摘しているように、行列全体が大きい場合は、部分行列のブロックを解除します。

編集:

SEのこの回答で指摘されているように、不必要なリスト内包表記は避けてください。

于 2013-01-16T16:54:55.243 に答える
6

dask.arrayライブラリは、ブロックされたアルゴリズムを使用して複数のコアを持つメモリよりも大きな配列を処理する numpy インターフェイスを提供します。

SpartanDistarray、およびBiggusを調べることもできます。

于 2015-05-03T16:57:26.370 に答える
3

可能であれば、numexprを使用してください。a**2 + b**2 + 2*a*b(配列であるために)それaのような数値計算のためにb

  1. 同じ配列が式で複数回発生した場合に、メモリの局所性を処理して(したがって、キャッシュの最適化を)、高速かつ最小限のメモリオーバーヘッドで実行されるマシンコードをコンパイルします。

  2. デュアルコアまたはクアッドコアCPUのすべてのコアを使用します。

  3. numpyの拡張であり、代替ではありません。

中規模および大規模のアレイの場合、numpyだけの場合よりも高速です。

上記のWebページを見てください。numexprがあなたに適しているかどうかを理解するのに役立つ例があります。

于 2013-01-17T16:12:48.720 に答える