2014-02-03 3 views
0

У меня есть сценарий numpy, который в настоящее время работает довольно медленно. тратит подавляющее большинство пришло время выполнения следующей операции внутри цикла:ускорение numpy.dot внутри списка понимание

terms=zip(Coeff_3,Coeff_2,Curl_x,Curl_y,Curl_z,Ex,Ey,Ez_av) 
res=[np.dot(C2,array([C_x,C_y,C_z]))+np.dot(C3,array([ex,ey,ez])) for (C3,C2,C_x,C_y,C_z,ex,ey,ez) in terms] 
res=array(res) 

Ex[1:Nx-1]=res[1:Nx-1,0] 
Ey[1:Nx-1]=res[1:Nx-1,1] 

Это список понимание, что действительно замедляет этот код вниз. В этом случае Coeff_3 и Coeff_2 являются 1000 списками, элементы которых являются матрицами 3x3 numpy, а Ex, Ey, Ez, Curl_x и т. Д. - это все массивы длиной 1000 numpy. Я понимаю, что это может быть быстрее, если я делал такие вещи, как установка одного вектора 3x1000 E, но мне нужно выполнить значительное количество усреднения разных векторов E между шагами, что сделало бы вещи очень громоздкими.

Любопытно, однако, я выполнить эту операцию дважды в цикле (один раз для Ex, Ey, один раз для Ег), и выполняя ту же операцию для Ez занимает почти в два раза дольше:

terms2=zip(Coeff_3,Coeff_2,Curl_x,Curl_y,Curl_z,Ex_av,Ey_av,Ez) 
res2=array([np.dot(C2,array([C_x,C_y,C_z]))+np.dot(C3,array([ex,ey,ez])) for (C3,C2,C_x,C_y,C_z,ex,ey,ez) in terms2]) 

Кто-нибудь есть идея, что происходит? Простите меня, если это что-то очевидное, я очень новичок в python.

+3

Вы должны написать представление списка как операцию массива –

+0

Как это сделать? Я не совсем уверен, как это сделать/ – Mdupont

+1

Если вы можете переписать эту операцию, используя n-мерные тензоры и нотацию суммирования эйнштейнов, тривиально векторизовать операцию в numpy. По крайней мере, напишите размер каждого объекта. Например, «Coeff_3» имеет форму (1000,3,3). – Daniel

ответ

0

Как указано в предыдущих комментариях, используйте операции с массивами. np.hstack(), np.vstack(), np.outer() и np.inner() полезны здесь. Вы код может стать чем-то вроде этого (не уверен, что о ваших размеров):

Cxyz = np.vstack((Curl_x,Curl_y,Curl_z)) 
C2xyz = np.dot(C2, Cxyz) 
... 

Проверьте форму ваших полученных размеров, чтобы убедиться, что вы перевели проблему правильно. Иногда numexpr также может значительно ускорить выполнение таких задач с небольшим дополнительным усилием,

+0

Это похоже на работу. Я уложил все свои векторы и использовал суммирование по эйнштейну, как это было предложено опцией, и оно прошло от 15 циклов в секунду до 77 циклов в секунду. Благодаря! – Mdupont

Смежные вопросы