NumPy ile hızlı tensör dönüş
Bir uygulama (Python ile yazılmış ve NumPy kullanarak) merkezinde 4. mertebe bir tensör döndürmek istiyorum. Aslında, tensör birçok kez döndürmek istiyorum ve bu benim performans sorunu var. Saf benim uygulama (aşağıda) sekiz iç içe döngüler içeren oldukça yavaş gibi görünüyor, ama kaldıraç NumPy matris işlemleri için bir çıkış yolu görüyor ve, umarım, işler daha hızlı olamaz. np.tensordot
kullanarak olmam gerektiğini hissediyorum ama nasıl olacağını bilmiyorum.
Matematiksel olarak, bu unsurları tensör, T döndürülmüş', tarafından verilmiştir:'. T ^alt>ıjkl= Σ g
Your original code: 19.471129179
Sven's code: 0.718412876129
My first code: 0.118047952652
My second code: 0.0690279006958
3*3 NumPy. Benim yavaş uygulama (çağrı başına ~0.04 saniye alıyordu altındadır.
#!/usr/bin/env python
import numpy as np
def rotT(T, g):
Tprime = np.zeros((3,3,3,3))
for i in range(3):
for j in range(3):
for k in range(3):
for l in range(3):
for ii in range(3):
for jj in range(3):
for kk in range(3):
for ll in range(3):
gg = g[ii,i]*g[jj,j]*g[kk,k]*g[ll,l]
Tprime[i,j,k,l] = Tprime[i,j,k,l] \
gg*T[ii,jj,kk,ll]
return Tprime
if __name__ == "__main__":
T = np.array([[[[ 4.66533067e 01, 5.84985000e-02, -5.37671310e-01],
[ 5.84985000e-02, 1.56722231e 01, 2.32831900e-02],
[ -5.37671310e-01, 2.32831900e-02, 1.33399259e 01]],
[[ 4.60051700e-02, 1.54658176e 01, 2.19568200e-02],
[ 1.54658176e 01, -5.18223500e-02, -1.52814920e-01],
[ 2.19568200e-02, -1.52814920e-01, -2.43874100e-02]],
[[ -5.35577630e-01, 1.95558600e-02, 1.31108757e 01],
[ 1.95558600e-02, -1.51342210e-01, -6.67615000e-03],
[ 1.31108757e 01, -6.67615000e-03, 6.90486240e-01]]],
[[[ 4.60051700e-02, 1.54658176e 01, 2.19568200e-02],
[ 1.54658176e 01, -5.18223500e-02, -1.52814920e-01],
[ 2.19568200e-02, -1.52814920e-01, -2.43874100e-02]],
[[ 1.57414726e 01, -3.86167500e-02, -1.55971950e-01],
[ -3.86167500e-02, 4.65601977e 01, -3.57741000e-02],
[ -1.55971950e-01, -3.57741000e-02, 1.34215636e 01]],
[[ 2.58256300e-02, -1.49072770e-01, -7.38843000e-03],
[ -1.49072770e-01, -3.63410500e-02, 1.32039847e 01],
[ -7.38843000e-03, 1.32039847e 01, 1.38172700e-02]]],
[[[ -5.35577630e-01, 1.95558600e-02, 1.31108757e 01],
[ 1.95558600e-02, -1.51342210e-01, -6.67615000e-03],
[ 1.31108757e 01, -6.67615000e-03, 6.90486240e-01]],
[[ 2.58256300e-02, -1.49072770e-01, -7.38843000e-03],
[ -1.49072770e-01, -3.63410500e-02, 1.32039847e 01],
[ -7.38843000e-03, 1.32039847e 01, 1.38172700e-02]],
[[ 1.33639532e 01, -1.26331100e-02, 6.84650400e-01],
[ -1.26331100e-02, 1.34222177e 01, 1.67851800e-02],
[ 6.84650400e-01, 1.67851800e-02, 4.89151396e 01]]]])
g = np.array([[ 0.79389393, 0.54184237, 0.27593346],
[-0.59925749, 0.62028664, 0.50609776],
[ 0.10306737, -0.56714313, 0.8171449 ]])
for i in range(100):
Tprime = rotT(T,g)
Bir şekilde bunu daha hızlı gitmek yapmak için var mı? Kodu tensör diğer dereceler için genelleme yapmak yararlı olabilir, ama daha az önemli.
CEVAP
tensordot
hesaplama g
tansör dış ürünü kullanmak için:
def rotT(T, g):
gg = np.outer(g, g)
gggg = np.outer(gg, gg).reshape(4 * g.shape)
axes = ((0, 2, 4, 6), (0, 1, 2, 3))
return np.tensordot(gggg, T, axes)
Benim sistemde, bu Sven çözümü daha yaklaşık yedi kat daha hızlı. Eğer g
tensör sık değişmiyorsa eğer değil, aynı zamanda gggg
tensör önbelleğe alabilir. Bunu ve mikro-optimizasyon (tensordot
bu kod, hiçbir kontrolleri, genel şekiller satır içi uygulaması) açın, hala iki kat daha hızlı yapabilirsiniz:
def rotT(T, gggg):
return np.dot(gggg.transpose((1, 3, 5, 7, 0, 2, 4, 6)).reshape((81, 81)),
T.reshape(81, 1)).reshape((3, 3, 3, 3))
Ev benim laptop (500 yineleme) timeit
sonuçları:
Your original code: 19.471129179
Sven's code: 0.718412876129
My first code: 0.118047952652
My second code: 0.0690279006958
Benim iş makine üzerindeki numaraları:
Your original code: 9.77922987938
Sven's code: 0.137110948563
My first code: 0.0569641590118
My second code: 0.0308079719543
Numpy: değer hızlı ilk dizin bul...
Hızlı onay NaN için NumPy içinde...
Neden numpy'daha hızlı numpy daha...
Tabanlı uygulamalar Hızlı bir işletim ...
Bir csv dosyası olarak NumPy bir dizi ...