2012-03-31 3 views
1

アルゴリズムで使用される多数の多次元NP配列(2Dおよび3D)があります。これには多数の反復があり、各反復中に、計算を実行して同じサイズの一時的な配列に保存することによって配列が再計算されます。 1回の反復の終了時に、一時配列の内容が実際のデータ配列にコピーされます。NumPyのスワップアレイデータ

例:AとBがちょうど入れ替えることができるとき

global A, B # ndarrays 
A_temp = numpy.zeros(A.shape) 
B_temp = numpy.zeros(B.shape) 
for i in xrange(num_iters): 
    # Calculate new values from A and B storing in A_temp and B_temp... 
    # Then copy values from temps to A and B 
    A[:] = A_temp 
    B[:] = B_temp 

これは正常に動作しますが、しかし、すべてのそれらの値をコピーするには少し無駄なようです。以下は、配列を交換します:

A, A_temp = A_temp, A 
B, B_temp = B_temp, B 

しかし、これは変更されません他のスコープ内の配列への他の参照が存在することができます。

NumPyは、numpy.swap(A, A_temp)のように、2つの配列の内部データポインタをスワップするための内部的な方法があるようです。 Aを指すすべての変数は、変更されたデータを指しています。あなたが道(私は、問題がどこか別の場所である疑いがある)としては良い動作するはずにもかかわらず

+0

「これは変更されない他のスコープのアレイへの他の参照」の例を挙げることができますか? – dmytro

+0

たとえば、計算ステップでは、フィールドが引数として渡される関数で呼び出される複数のスレッドを持つことができます。複数のスレッドをインスタンス化するオーバーヘッドを減らすために、それらも循環します。 – coderforlife

+0

正しく思い出した場合、sharedctypes配列などの特定の機能を使用していない限り、コピーなしでスレッド/プロセス間でデータを渡すことはできません。しかし、私は間違っているかもしれません... – dmytro

答えて

1

を切り替えます。

"アレイホルダー"クラスを持つことができます。基本的なNumPy配列への参照を保持するだけです。これらのペアに対して安価なスワップ操作を実装するのは簡単です。

すべての外部参照がこれらのホルダーオブジェクトに対してで、配列に直接ではない場合、これらの参照はスワップによって無効になりません。

+0

これは確かに実行可能な選択肢です。 ndarrayは既に変更可能な適切なデータへのポインタを持っているので、馬鹿げているように見えます。ビューを使用する方法を理解できない場合、これが答えになります。 – coderforlife

+0

@thaimin:2つのものを交換するPythonの方法は 'a、b = b、a'です。これは参照を交換します。私はあなたが探しているようなスワップインタフェースを実装する単一の標準クラスを考えることはできません。 Pythonではほとんど必要とされていないので、これだけではできません。 – NPE

+0

私は理解しています。私はあなたが "ベース"フィールドを再割り当てできる場合に動作するビューを使用しようとしました。私はほぼ成功したがスワッピングを許さない "データ"フィールドを割り当てようとしたが(最初の割り当ては正確には私が望むもので、a.data、b.data = b.data、a.dataはそれら)。 – coderforlife

0

、明示的にそれをやってみることができます:それはあなたの方法が同様に動作することを確認するためには難しいことではありません

import numpy as np 
A, A_temp = np.frombuffer(A_temp), np.frombuffer(A) 

>>> import numpy as np 
>>> arr = np.zeros(100) 
>>> arr2 = np.ones(100) 
>>> print arr.__array_interface__['data'][0], arr2.__array_interface__['data'][0] 
152523144 152228040 

>>> arr, arr2 = arr2, arr 
>>> print arr.__array_interface__['data'][0], arr2.__array_interface__['data'][0] 
152228040 152523144 

は...ポインタがsuccsessfullyおそらく、あなたは、間接のレベルを追加することによってこの問題を解決でき

+0

frombufferのアイデアは面白いですが、 "reshape(A.shape)"コマンドが必要です1D配列のみを返します。それ以外にも、これは代替参照の問題を解決しません。私はそれを使っていくつかのことを試してみましたが、必要なのは "セットバッファ"の機能です...これは私の意見を見てくれました。 – coderforlife

1

私はこれが古い質問です実現するが、それは価値があるもののためにあなたはまた、XORスワップ行うことで、(一時コピーなし)2つのndarrayバッファ間でデータを交換できます。これは上行われていたので

A_bytes = A.view('ubyte') 
A_temp_bytes = A.view('ubyte') 
A_bytes ^= A_temp_bytes 
A_temp_bytes ^= A_bytes 
A_bytes ^= A_temp_bytes 

を元のAA_temp配列(元のdtypeが何であったとしても)を見ると、その値は正しく交換されるはずです。これは基本的にあなたが探していたnumpy.swap(A, A_temp)に相当します。それは3つのループを必要とすることは残念です - もしこれがufuncとして実装されていれば(多分そうでなければならないかもしれませんが)はるかに高速です。