我有一个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