У меня есть код python, который импортирует 4 столбца txt-файла с цифрами Первые три столбца - это координаты x, y, z, а четвертый столбец - плотность в этой координате.Ускорение анализа массивов в numpy
Ниже приведен код, который читает, преобразует в ndarray, преобразовывает это поле в Фурье, вычисляет расстояние от начала координат (k = (0,0,0)) и преобразует координату, принимает среднее значение и записывает их. Благодаря pandas (библиотека 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'. –
Спасибо, я сокращу и отредактирую. – Tom
Было бы также полезно, если бы вы были более конкретными, какие части медленны. Я думаю, что могу разобраться в том, что вы имеете в виду, но вы должны четко указать на них, чтобы никто не тратил слишком много времени на размышления о неправильных частях вашего кода. – Mike