我有一個python代碼,它導入4列txt文件,其中第 前三列是x,y,z座標,第四列是該座標下的密度。加快對numpy數組的分析
下面是讀取代碼,轉換爲ndarray,傅立葉變換該字段,計算原點距離(k =(0,0,0))和變換後的座標,並取平均值並繪製它們。 感謝大熊貓(用於數據分析的python庫)和python FFT,加載256^3行並對它們進行傅里葉變換非常快,並在幾秒鐘內完成。
但是,將加載的txt轉換爲numpy ndarray,計算平均密度(每個座標的平均值)以及計算與原點的距離(k =(0,0,0))需要很長時間。
我認爲問題是在最後np.around部分,但我不知道如何優化它。
我有一個32核心機器的資源。
有人可以教我如何加速,使其成爲一個多進程代碼或類似的東西,以便這些可以很快完成?謝謝。
(如果你是宇宙學家和以往任何時候都需要這個代碼,你可以,如果你可以的。謝謝使用它,但請與我聯繫,)
from __future__ import division
import numpy as np
ngridx = 128
ngridy = 128
ngridz = 128
maxK = max(ngridx,ngridy,ngridz)
#making input file
f = np.zeros((ngridx*ngridy*ngridz,4))
i = 0
for i in np.arange(len(f)):
f[i][0] = int(i/(ngridy*ngridz))
f[i][1] = int((i/ngridz))%ngridy
f[i][2] = int(i%ngridz)
f[i][3] = np.random.rand(1)
if i%1000000 ==0:
print i
#This takes forever
#end making input file
#Thanks to Mike,
a = f[:,3].reshape(ngridx,ngridy,ngridz)
avg =np.sum(f[:,3])/len(f)
a /= avg
p = np.fft.fftn(a)
#This part is much much faster than before (Original Post).
#Keeping track of corresponding wavenumbers (k_x, k_y,k_z) for each element in p
#This is just a convension on fourier transformation so you can ignore this part
kValx = np.fft.fftfreq(ngridx , (1.0/ngridx))
kValy = np.fft.fftfreq(ngridy , (1.0/ngridy))
kValz = np.fft.fftfreq(ngridz , (1.0/ngridz))
kx = np.zeros((ngridx,ngridy,ngridz))
ky = np.zeros((ngridx,ngridy,ngridz))
kz = np.zeros((ngridx,ngridy,ngridz))
rangecolx = np.arange(ngridx)
rangecoly = np.arange(ngridy)
rangecolz = np.arange(ngridz)
for row in np.arange(ngridx):
for column in np.arange(ngridy):
for height in np.arange(ngridz):
kx[row][column][height] = (kValx[row])
ky[row][column][height] = (kValy[column])
kz[row][column][height] = (kValz[height])
if row%10 == 0:
print row
print 'wavenumber generate complete!'
#Calculating the average powerspectrum in terms of fixed K (Distance from origin to a point in fourier space)
#by taking the spherical shell of thickness 1 and averaging out the values inside it.
#I am sure that this process can be optimised somehow, but I gave up.
qlen = maxK/2 #Nyquist frequency
q = np.zeros(((qlen),4),dtype=complex)
#q is a four column array with length maxK/2.
#q[:,0] is integer wavenumber (K, which is the distance from the origin = sqrt(kx^2+ky^2+kz^2))
#q[:,1] is the sum of square of the fourier transformed value
#q[:,2] is the sum of the fourier transformed value,
#and q[:,3] is the total number of samples with K=q[:,0]
for i in np.arange(len(q)):
q[i][0] = i
i = 0
for i in np.arange(len(p)):
for r in np.arange(len(p[0])):
for s in np.arange(len(p[0,0])):
K = np.around(np.sqrt(kx[i,r,s]**2+ky[i,r,s]**2+kz[i,r,s]**2))
if K < qlen:
q[K][1]=q[K][1]+np.abs(p[i,r,s])**2
q[K][2]=q[K][2]+p[i,r,s]
q[K][3]=q[K][3]+1
if i%10 ==0:
print 'i = ',i,' !'
print q
請嘗試將代碼簡化爲更短的內容,這仍然表明緩慢。你有什麼比通常成功的SO問題的代碼更長。另外,請提供一個能夠生成有效輸入的簡短程序,例如使用'np.random'。 – 2015-02-06 03:13:07
謝謝,我會縮短然後編輯。 – Tom 2015-02-06 03:15:09
如果您可以更具體地瞭解哪些部件較慢,這也會有所幫助。我想我可以弄清楚你的意思,但你應該清楚地指出它們,以確保沒有人花太多時間思考代碼的錯誤部分。 – Mike 2015-02-06 03:16:07