Я пытаюсь ускорить некоторый код, который я написал, но у меня большие проблемы с этим. Я знаю, что возможность удаления для циклов и использование numpy может помочь сделать это, поэтому я пытался без особого успеха.
Рабочая функция без ускорений -
def acf(x, y, z, cutoff=0):
steps = x.shape[1]
natoms = x.shape[0]
z_x = np.zeros((steps,natoms))
z_y, z_z = np.zeros_like(z_x), np.zeros_like(z_x)
xmean = np.mean(x, axis=1)
ymean = np.mean(y, axis=1)
zmean = np.mean(z, axis=1)
for k in range(steps-cutoff): # x.shape[1]
xtemp, ytemp, ztemp = [], [], []
for i in range(x.shape[0]): # natoms
xtop, ytop, ztop = 0.0, 0.0, 0.0
xbot, ybot, zbot = 0.0, 0.0, 0.0
for j in range(steps-k): # x.shape[1]-k
xtop += (x[i][j] - xmean[i]) * (x[i][j+k] - xmean[i])
ytop += (y[i][j] - ymean[i]) * (y[i][j+k] - ymean[i])
ztop += (z[i][j] - zmean[i]) * (z[i][j+k] - zmean[i])
xbot += (x[i][j] - xmean[i])**2
ybot += (y[i][j] - ymean[i])**2
zbot += (z[i][j] - zmean[i])**2
xtemp.append(xtop/xbot)
ytemp.append(ytop/ybot)
ztemp.append(ztop/zbot)
z_x[k] = xtemp
z_y[k] = ytemp
z_z[k] = ztemp
z_x = np.mean(np.array(z_x), axis=1)
z_y = np.mean(np.array(z_y), axis=1)
z_z = np.mean(np.array(z_z), axis=1)
return z_x, z_y, z_z
Входы x, y и z для этой функции numpy массивы с одинаковыми размерами. Пример x (или y или z в этом отношении):
x = np.array([[1,2,3],[4,5,6]])
Пока что я смог сделать это:
def acf_quick(x, y, z, cutoff=0):
steps = x.shape[1]
natoms = x.shape[0]
z_x = np.zeros((steps,natoms))
z_y, z_z = np.zeros_like(z_x), np.zeros_like(z_x)
x -= np.mean(x, axis=1, keepdims=True)
y -= np.mean(y, axis=1, keepdims=True)
z -= np.mean(z, axis=1, keepdims=True)
for k in range(steps-cutoff): # x.shape[1]
for i in range(natoms):
xtop, ytop, ztop = 0.0, 0.0, 0.0
xbot, ybot, zbot = 0.0, 0.0, 0.0
for j in range(steps-k): # x.shape[1]-k
xtop += (x[i][j]) * (x[i][j+k])
ytop += (y[i][j]) * (y[i][j+k])
ztop += (z[i][j]) * (z[i][j+k])
xbot += (x[i][j])**2
ybot += (y[i][j])**2
zbot += (z[i][j])**2
z_x[k][i] = xtop/xbot
z_y[k][i] = ytop/xbot
z_z[k][i] = ztop/xbot
z_x = np.mean(np.array(z_x), axis=1)
z_y = np.mean(np.array(z_y), axis=1)
z_z = np.mean(np.array(z_z), axis=1)
return z_x, z_y, z_z
Это ускоряет его примерно на 33 %, но я считаю, что есть способ удалить for i in range(natoms)
, используя что-то вроде x[:][j]
. До сих пор я был неудачен, и любая помощь будет принята с благодарностью.
Прежде чем кто-либо спросит, я знаю, что это автокорреляционная функция, и есть несколько встроенных в numpy, scipy, et c, но я нужно написать свое.