Mnożenie macierzy MATLAB (najlepsze podejście obliczeniowe)

10

Muszę dokonać transformacji współrzędnych między dwoma układami odniesienia (osiami). W tym celu należy pomnożyć trzy macierze ( ) ze względu na zastosowanie niektórych osi pośrednich. Pomyślałem o dwóch podejściach do rozwiązania tego:3×3

Metoda nr 1 : Wykonanie mnożenia bezpośrednio, to znaczy

vf=R1 R2 R3 vi

Metoda nr 2 : Podziel się na kroki:

  1. v3i=R3 vi
  2. v23=R2 v3i
  3. vf=R1 v23

gdzie:

, R 2 i R 3 3 x 3 matryceR1R2R33×3

, v i , v 3 i , v 23 towektory 3 × 1vfviv3iv233×1

Chciałbym wiedzieć, która metoda jest bardziej wydajna obliczeniowo (mniej czasu) na wykonanie transformacji (będzie to robione wiele razy).

julianfperez
źródło
4
Użyj czwartorzędów .
Chris Taylor
@ChrisTaylor: Dziękuję bardzo za sugestię.
julianfperez
2
Proszę nie krzyżować.
Zerwano
2
Zauważ, że zostały tu wysłane dwa pytania i StackOverflow. Pytania, ich komentarze i odpowiedzi zostały połączone w jedno.
Aron Ahmadia
@Will and AronAhmadia: Przepraszam. Nie wiedziałem, że crosssposting jest zabroniony. Zawsze zamieszczałem moje pytania na StackOverflow, ale dzisiaj znalazłem tę nową stronę i pomyślałem, że może też tutaj znajdę pomoc.
julianfperez

Odpowiedzi:

17

ABCvA(B(Cv))

A(B(Cv))

Aby ogólnie dowiedzieć się, jak zmierzyć wpływ niewielkich różnic programistycznych na obliczenia na dużą skalę, napisz w wierszu polecenia Matlab „profil pomocy”.

Arnold Neumaier
źródło
Dziękujemy za interesujące informacje podane w odpowiedzi.
julianfperez
Dlaczego szybciej jest, jeśli zapisujesz półprodukty?
Federico Poloni
@FedericoPoloni: Napisałem, że nieco szybciej jest nie zapisywać półproduktów.
Arnold Neumaier
@ArnoldNeumaier Ooh przepraszam, że źle przeczytałem. :)
Federico Poloni,
14

Na początek nie używałbym zmiennych pośrednich, ale nawiasów. Chyba, że ​​oczywiście interesują cię wyniki pośrednie, ale chyba nie.

Próbowałem następujące w Matlab:

>> N = 500;                                             
>> A = rand(N); B = rand(N); C = rand(N); v = rand(N,1);

>> tic, for k=1:100, A*B*C*v; end; toc
Elapsed time is 3.207299 seconds.

>> tic, for k=1:100, A*(B*(C*v)); end; toc
Elapsed time is 0.108095 seconds.

Muszę jednak powiedzieć, że jest to dość przerażające. Zawsze zakładałem, że Matlab byłby mądry w kwestii kolejności mnożenia macierzy, ponieważ jest to znany problem z prostymi i wydajnymi rozwiązaniami.

Pedro
źródło
Czy przegapiłeś część, w której matryce są 3x3? :)
Aron Ahmadia
2
@AronAhmadia: Ups ... Nie udało mi się, dzięki. Myślę, że dla tych rozmiarów matryc cały problem jest dyskusyjny, ale nadal jestem zaskoczony wynikami dla dużych N.
Pedro
7
Zgaduję, że MATLAB przestrzega reguł pierwszeństwa C do oceny wyrażeń, ponieważ matematyka zmiennoprzecinkowa nie jest asocjacyjna i muszą założyć, że wiesz, co robisz :)
Aron Ahmadia
2
@Pedro: Dziękuję za odpowiedź. Dla wymiaru macierzy 3x3 sprawdziłem, czy twoje rozwiązanie jest również lepsze niż zwykłe (bez nawiasów) mnożenie macierzy.
julianfperez
+1 dziękuję za pokazanie prostego i łatwego sposobu pomiaru czasu pracy
Steven Magana-Zook
14

Ponieważ matryce są tak małe, cały koszt będzie narzut na połączenie. Jeśli wykonasz transformację wiele razy, szybsze będzie wstępne obliczenie D=A*B*Craz, a następnie dla każdego wektora zastosuj v_f=D*v_i. Możesz również rozważyć przeniesienie tego do pliku mex.

Aron Ahmadia
źródło
Dziękuję za Twoją odpowiedź. W moim przypadku macierze są macierzami obrotowymi (zależą od wartości kątowej i to się zmienia), więc iloczyn A B C nie zawsze jest taki sam.
julianfperez