我有一筆我想要加快的款項。在一種情況下,它是:如何做總和的平方和的總和?
S_ {X,Y,K,L} Fu_ {ク} Fv_ {LV} Fx_ {KX} Fy_ {LY}
在其他情況下,它是:
S_ {X,Y}(S_ {K,L} Fu_ {ク} Fv_ {LV} Fx_ {KX} Fy_ {LY})^ 2
注:S_ {指數}:是對這些總和指數
第一個案例我已經想出瞭如何使用numpy的einsum
,它導致了驚人的加速〜x160。
此外,我曾試圖擴大平方,但不會是一個殺手,因爲我需要總結x,y,k,l,k,l而不是x,y,k,l ?
這是一個實現,它演示了我與einsum
的區別和解決方案。
Nx = 3
Ny = 4
Nk = 5
Nl = 6
Nu = 7
Nv = 8
Fx = np.random.rand(Nx, Nk)
Fy = np.random.rand(Ny, Nl)
Fu = np.random.rand(Nu, Nk)
Fv = np.random.rand(Nv, Nl)
P = np.random.rand(Nx, Ny)
B = np.random.rand(Nk, Nl)
I1 = np.zeros([Nu, Nv])
I2 = np.zeros([Nu, Nv])
t = time.time()
for iu in range(Nu):
for iv in range(Nv):
for ix in range(Nx):
for iy in range(Ny):
S = 0.
for ik in range(Nk):
for il in range(Nl):
S += Fu[iu,ik]*Fv[iv,il]*Fx[ix,ik]*Fy[iy,il]*P[ix,iy]*B[ik,il]
I1[iu, iv] += S
I2[iu, iv] += S**2.
print time.time() - t; t = time.time()
# 0.0787379741669
I1_ = np.einsum('uk, vl, xk, yl, xy, kl->uv', Fu, Fv, Fx, Fy, P, B)
print time.time() - t
# 0.00049090385437
print np.allclose(I1_, I1)
# True
# Solution by expanding the square (not ideal)
t = time.time()
I2_ = np.einsum('uk,vl,xk,yl,um,vn,xm,yn,kl,mn,xy->uv', Fu,Fv,Fx,Fy,Fu,Fv,Fx,Fy,B,B,P**2)
print time.time() - t
# 0.0226809978485 <- faster than for loop but still much slower than I1_ einsum
print np.allclose(I2_, I2)
# True
如圖所示我已經成功地做到I1_與我已經找到了如何做到以上einsum
爲I1
。
編輯:
我加了如何通過擴大正方形,但速度可達做I2_
是有點令人失望,也值得期待...〜x3.47增速相比,X160〜
編輯2:
加速似乎並不一致,我得到了x40和x1.2之前,但現在得到不同的數字。無論哪種方式,差異和問題依然存在。
EDIT3: 我試圖簡化實際上我不過之後搞砸及以上的總和允許通過@ user5402提供的出色答卷的總和。
我已經編輯上面的代碼以證明其是下面的總和:
I1 = S_ {X,Y,K,L} Fu_ {ク} Fv_ {LV} Fx_ {KX} Fy_ {LY } P_ {xy} B_ {kl}
I2 = S_ {x,y} {S_ {k,l} Fu_ {ku} Fv_ {lv} Fx_ {kx} Fy_ {ly} P_ {xy} B_ { kl})^ 2
退房numba? – 2014-12-11 05:21:59
有一些開銷進入C領域......嘗試使用更大的陣列......我認爲你會看到加速度與數據集的大小成正比( – 2014-12-11 05:26:38
@SlaterTyranus哪部分?那是一個JIT編譯器是否正確?我會用它做for循環的函數嗎? – evan54 2014-12-11 05:27:16