I recently asked about trying to optimise a Python loop for a scientific application,並且收到我的an excellent, smart way of recoding it within NumPy which reduced execution time by a factor of around 100!在純NumPy中重寫for循環以減少執行時間
但是,B
值的計算實際上嵌套在其他幾個循環中,因爲它是在常規的位置網格中進行計算的。是否有類似智能的NumPy重寫來縮短這個過程的時間?
我懷疑這個部分的性能增益不會很明顯,並且其缺點大概是不可能向用戶報告計算進度,結果不能寫入輸出文件直到計算結束,並且可能在一個巨大的步驟中這樣做會產生內存影響?是否有可能繞過這些?你可以做
import numpy as np
import time
def reshape_vector(v):
b = np.empty((3,1))
for i in range(3):
b[i][0] = v[i]
return b
def unit_vectors(r):
return r/np.sqrt((r*r).sum(0))
def calculate_dipole(mu, r_i, mom_i):
relative = mu - r_i
r_unit = unit_vectors(relative)
A = 1e-7
num = A*(3*np.sum(mom_i*r_unit, 0)*r_unit - mom_i)
den = np.sqrt(np.sum(relative*relative, 0))**3
B = np.sum(num/den, 1)
return B
N = 20000 # number of dipoles
r_i = np.random.random((3,N)) # positions of dipoles
mom_i = np.random.random((3,N)) # moments of dipoles
a = np.random.random((3,3)) # three basis vectors for this crystal
n = [10,10,10] # points at which to evaluate sum
gamma_mu = 135.5 # a constant
t_start = time.clock()
for i in range(n[0]):
r_frac_x = np.float(i)/np.float(n[0])
r_test_x = r_frac_x * a[0]
for j in range(n[1]):
r_frac_y = np.float(j)/np.float(n[1])
r_test_y = r_frac_y * a[1]
for k in range(n[2]):
r_frac_z = np.float(k)/np.float(n[2])
r_test = r_test_x +r_test_y + r_frac_z * a[2]
r_test_fast = reshape_vector(r_test)
B = calculate_dipole(r_test_fast, r_i, mom_i)
omega = gamma_mu*np.sqrt(np.dot(B,B))
# write r_test, B and omega to a file
frac_done = np.float(i+1)/(n[0]+1)
t_elapsed = (time.clock()-t_start)
t_remain = (1-frac_done)*t_elapsed/frac_done
print frac_done*100,'% done in',t_elapsed/60.,'minutes...approximately',t_remain/60.,'minutes remaining'
我認爲賈斯汀對配置文件的建議可能是明智的,但非常感謝......雖然我不確定我會使用它,但我認爲試圖理解這個例子可能是一種非常好的學習方式。 :) – Statto 2010-04-07 16:10:52