2013-06-03 127 views
1

我正逐漸從Matlab轉向Python,並希望得到一些優化迭代循環的建議。 這就是我目前正在運行的循環,並且我已經包含了定義變量的代碼。優化迭代循環

nh = 2000 
h = np.array(range(nh)) 
nt = 10000 
wmin = 1 
wmax = 10 
hw = np.array(wmin + (wmax-wmin)*invlogit(randn(1,nh))); 
sl = np.array(zeros((nh,1))+radians(40)) 
fa = np.array(zeros((nh,1))+radians(35)) 
c = np.array(zeros((nh,1))+4.4) 
y = np.array(zeros((nh,1))+17.6) 
yw = np.array(zeros((nh,1))+9.81) 
ir = 0.028 
m = np.array(zeros((nh,nt))); 
m[:,49] = 0.1 
z = np.array(zeros((nh,nt))) 
z[:,0] = 0+(3.0773-0)*rand(nh,1).T 
reset = np.array(zeros((nh,nt))) 
fs = np.array(zeros((nh,nt))) 

for t in xrange(0, nt-1): 
    fs[:,t] = (c.T+(y.T-m[:,t]*yw.T)*z[:,t]*(np.cos(sl.T)**2)*np.tan(fa.T))/(y.T*z[:,t]*np.sin(sl.T)*np.cos(sl.T)) 
    reset[fs[:,t]<=1,t+1] = 1; 
    z[fs[:,t]<=1,t+1] = 0; 
    z[fs[:,t]>1,t+1] = z[fs[:,t]>1,t]+(ir/hw[0,fs[:,t]>1]).T 

這是我會怎樣優化在Matlab代碼,但它運行很慢的蟒蛇。我懷疑這樣做會有更多pythonic的方式,並會真正感謝在正確的方向推動。 非常感謝!

+0

有沒有一種方法可以讓你找出其在循環中的4個操作是最耗時?這可能有助於我們確定需要最多幫助的位置(我可能會猜測它是第一個...... trig函數非常慢)。 – SethMMorton

+1

我還注意到,您正以比C存儲更適合Fortran存儲的方式編制數組索引。您可能會考慮讓numpy將您的陣列存儲在Fortran中。 – SethMMorton

+0

感謝Seth,Fortran命令加快了一點。對於信息/例如,這可以使用z = np.zeros((nh,nt),order ='F')來完成 – user2448817

回答

0

未進行具體有關環路,你做一噸的額外的工作,看起來像電話:

np.array(zeros((nh,nt))) 

只需使用:

np.zeros((nh,nt)) 
在其位置

。此外,您可以取代:

h = np.array(range(nh)) 

有:

h = np.arange(nh) 

其他評論:

  • 你調用每一個循環np.sin(sl.T)*np.cos(sl.T)雖然,sl似乎並沒有在所有變化。只需計算一次並將其分配給您在循環中使用的變量。你在一堆trig調用中做到這一點。
+0

感謝Josh,我已經在循環之前分配了trigs並整理了數組定義。速度略有改善,看起來更加整齊。歡呼 – user2448817

+0

在numpy中查看關於廣播規則的文檔也是值得的。 – JoshAdel

0

表達

(c.T+(y.T-m[:,t]*yw.T)*z[:,t]*(np.cos(sl.T)**2)*np.tan(fa.T))/(y.T*z[:,t]*np.sin(sl.T)*np.cos(sl.T)) 

使用c, y, m, yw, sl, fa不循環內改變。你可以在循環之前計算幾個子表達式。

此外,大多數這些數組包含一個重複的值。你可以用標量,而不是計算:

sl = radians(40) 
fa = radians(35) 
c = 4.4 
y = 17.6 
yw = 9.81 

然後,在預先計算的子表達式:

A = cos(sl)**2 * tan(fa) * (y - m*yw) 
B = y*sin(sl)*cos(sl) 

for t in xrange(0, nt-1): 
    fs[:,t] = (c + A[:,t]*z[:,t])/(B*z[:,t]) 
    less = fs[:,t]<=1 
    more = np.logical_not(less) 
    reset[less,t+1] = 1 
    z[less,t+1] = 0 
    z[more,t+1] = z[more,t]+(ir/hw[0,more]).T