SORU
10 ŞUBAT 2011, PERŞEMBE


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ıagjbgkcgldTatoplam sağ tarafta tekrarlanan endeksleri üzerinde olmak. T ve Tprime diziler ve dönme matrisi g 3*3 NumPy bir dizidir 3

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
10 ŞUBAT 2011, PERŞEMBE


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

Bunu Paylaş:
  • Google+
  • E-Posta
Etiketler:

YORUMLAR

SPONSOR VİDEO

Rastgele Yazarlar

  • Dogbert files

    Dogbert file

    12 Ocak 2012
  • El SalvaLobo

    El SalvaLobo

    10 Temmuz 2006
  • Tracy Hairston

    Tracy Hairst

    22 Mayıs 2009