-1

次のスクリプト用のメモリ効率の高い Python スクリプトを探しています。次のスクリプトは小さい次元でうまく機能しますが、実際の計算では行列の次元は 5000X5000 です。そのため、完成までに非常に時間がかかります。どうすればそれを行うことができますか?

def check(v1,v2):
    if len(v1)!=len(v2):
        raise ValueError,"the lenght of both arrays must be the same"
    pass
def d0(v1, v2):
    check(v1, v2)
    return dot(v1, v2)
import numpy as np
from pylab import *
vector=[[0.1, .32, .2, 0.4, 0.8], [.23, .18, .56, .61, .12], [.9, .3, .6, .5, .3], [.34, .75, .91, .19, .21]]
rav= np.mean(vector,axis=0)
#print rav
#print vector
m= vector-rav
corr_matrix=[]
for i in range(0,len(vector)):
    tmp=[]
    x=sqrt(d0(m[i],m[i]))
    for j in range(0,len(vector)):
        y=sqrt(d0(m[j],m[j]))
        z=d0(m[i],m[j])
        w=z/(x*y)
        tmp.append(w)
    corr_matrix.append(tmp)
print corr_matrix
4

1 に答える 1

1

あなたのmatrix(そしてあなたの)を Python の代わりにvectornumpyにします。これにより、使用するメモリが大幅に削減されます (また、実行速度も向上します)。arraylist

理由を理解するには:

Pythonlistは、Python オブジェクト インスタンスのリストです。これらのそれぞれには、型情報、ポインター、および 8 バイトの数値だけでなく、他のすべての種類のものがあります。それぞれが 8 バイトではなく 64 バイトになるとしましょう。つまり、要素あたり 64 バイトに 25M 要素を掛けると、1600M バイトになります。

対照的に、numpyarrayは生の値だけのリストであり、すべての追加情報の単一のコピー ( dtype. したがって、64 * 25M バイトではなく、8 * 25M + 64 バイトになり、サイズはわずか 1/8 になります。

速度の向上について: 5000x5000 の行列を反復処理すると、内側のループでコードを 25M 回呼び出すことになります。次のような派手な表現をしている場合m + mループ内のコードは、数行の C コードであり、数十のマシンコード操作にコンパイルされます。これは非常に高速です。Python でループを明示的に実行している場合、そのループの内部では、ループを通過するたびに Python インタープリターを駆動する必要があり、これは非常に遅くなります。(さらに、C コンパイラはコードを最適化し、numpy にもいくつかの明示的な最適化がある場合があります。) ループ内の作業がどれほど些細なことかによって、スピードアップは 2 倍から 10000 倍になります。したがって、少し複雑にする必要がある場合でも、各ステップをループではなく配列ブロードキャストとして表現する方法を見つけてみてください。そうすれば、はるかに高速になります。


それで、どうやってそれをしますか?単純。これの代わりに:

corr_matrix=[]
for i in range(len(vector)):
    tmp=[]
    # …
    for j in range(len(vector)):
        # …
        tmp.append(w)
    corr_matrix.append(tmp)

これを行う:

corr_matrix=np.zeros((len(vector), len(vector))
for i in range(len(vector)):
    # …
    for j in range(len(vector)):
        # …
        corr_matrix[i, j] = w

これにより、約 25M の Python オブジェクトを保持するオーバーヘッドによって引き起こされるすべてのメモリの問題がすぐに解消され、float速度も大幅に向上します。一度に全体をメモリに保持しないことを除いて、メモリをこれ以上減らすことはできませんがarray、すでに問題ないはずです。(ループの代わりにブロードキャスト操作を使用すると、さらに速度を上げることができますが、メモリに問題があり、パフォーマンスが問題ない場合は、必要ない場合があります。)

于 2013-02-06T02:01:20.653 に答える