3

現在、Python / Numpy で実行するのに 1 時間強かかるコードを高速化しようとしています。計算時間の大部分は、下に貼り付けられた関数で発生します。

Z をベクトル化しようとしていますが、トリプル for ループではかなり難しいことがわかりました。numpy.diff関数をどこかに実装できますか?見てみましょう:

def MyFESolver(KK,D,r,Z):
    global tdim
    global xdim
    global q1
    global q2
    for k in range(1,tdim):
        for i in range(1,xdim-1):
            for j in range (1,xdim-1):
                Z[k,i,j]=Z[k-1,i,j]+r*q1*Z[k-1,i,j]*(KK-Z[k-1,i,j])+D*q2*(Z[k-1,i-1,j]-4*Z[k-1,i,j]+Z[k-1,i+1,j]+Z[k-1,i,j-1]+Z[k-1,i,j+1])
    return Z

tdim = 75 xdim = 25

4

2 に答える 2

4

同意します。4つの側面すべてのBCが剛性マトリックスの単純な構造を台無しにするため、注意が必要です。あなたはそのようにスペースループを取り除くことができます:

from pylab import *
from scipy.sparse.lil import lil_matrix
tdim = 3;     xdim = 4;  r = 1.0;  q1, q2 = .05, .05; KK= 1.0; D = .5  #random values
Z = ones((tdim, xdim, xdim))
#Iterate in time
for k in range(1,tdim):
    Z_prev = Z[k-1,:,:] #may need to flatten
    Z_up = Z_prev[1:-1,2:]
    Z_down = Z_prev[1:-1,:-2]

    Z_left = Z_prev[:-2,1:-1]
    Z_right = Z_prev[2:,1:-1]

    centre_term  = (q1*r*(Z_prev[1:-1,1:-1] + KK) - 4*D*q2)* Z_prev[1:-1,1:-1] 

    Z[k,1:-1,1:-1]= Z_prev[1:-1,1:-1]+ centre_term + q2*(Z_up+Z_left+Z_right+Z_down)

しかし、私はあなたがタイムループを取り除くことができるとは思わない...

私はその表現を考えます:

Z_up = Z_prev[1:-1,2:]

numpyでコピーを作成しますが、必要なのはビューです-これを行う方法を理解できれば-それはさらに高速になるはずです(いくらですか?)

最後に、私は残りの回答者に同意します-経験から、この種のループはCで実行してから、numpyにラップする方が適切です。しかし、上記は元のよりも速いはずです...

于 2012-10-25T12:17:22.750 に答える
2

これは、Cython にとって理想的なケースのように見えます。その関数を Cython で作成することをお勧めします。おそらく数百倍高速になるでしょう。

于 2012-10-25T11:07:59.450 に答える