2012-10-25 91 views
3

我想加快我的代碼,目前需要一個多小時才能在Python/Numpy中運行。大部分計算時間出現在粘貼在下面的函數中。向Python化/ Numpy中的循環向量化可能嗎?

我想向量化Z,但是我發現它對於三重循環很難。我能否在某處實施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 = 75xdim = 25

+0

嘗試行'Z [1 :, 1:-1,1:-1] = Z [: - 1,1:-1,1:-1 ] + R * q1 * Z [:-1,1:-1,1:-1] *(KK-Z [:-1,1:-1,1:-1])+ D * q2 *(Z [:-1,... -2,1:-1] -4 * Z [:-1,1:-1,1:-1] + Z [:-1,2 :, 1:-1] + Z [:-1,1:-1,:-2] + Z [: - 1,1:-1,2:])'而不是你的三元組。 – halex

+1

不相關,但很重要:您可能想重新檢查使用'global'關鍵字。你的情況沒用。 – Simon

回答

2

這看起來像用Cython理想的情況下。我建議在Cython中編寫這個函數,它可能會快幾百倍。

4

我同意,這很棘手,因爲所有四邊的BCs都破壞了剛度矩陣的簡單結構。你可以擺脫空間的循環這樣:

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中製作副本,而你想要的是一個視圖 - 如果你能想出如何做到這一點 - 它應該更快(多少?)

最後,我同意其餘的回答者 - 來自經驗e,這種循環最好在C中完成,然後包裝成numpy。但上面應該比原來快...

+2

是的,除了時間循環外,其他所有的東西都可以矢量化。 Numpy總是爲切片操作創建視圖。 – seberg