Maplication Matrix.

Maplication Matrix.

Tak więc, w poprzedniej lekcji zdemontowaliśmy zasady dodawania i odejmowania matryc. Są to takie proste operacje, które większość uczniów rozumie ich dosłownie z Go.

Jednak radujesz się wcześnie. Freebie się skończył - idź do mnożenia. Natychmiast cię ostrzegam: pomnóż dwie macierzy, nie pomnożą liczb w komórkach o tych samych współrzędnych, jakbyś mógł pomyśleć. Wszystko jest tutaj znacznie więcej zabawy. I zacząć od wstępnych definicji.

Konsekwentne matryce.

Jedną z najważniejszych cech macierzy jest jego rozmiar. Rozmawialiśmy już o tym sto razy: rekord $ A = Left [M \ tmkwate Prawo] $ oznacza, że ​​w macierzy dokładnie $ m $ rzędu i $ N $ kolumny. Jak nie mylić wierszy z kolumnami, już omówiliśmy. Teraz jest ważne.

Definicja. Matryce formy $ A = Left] $ i $ B = Left] $ i $ b = Left] $, w którym liczba kolumn w pierwszej matrycy pokrywa się z liczbą wierszy w drugim, są zwany Spójny .

Po raz kolejny: liczba kolumn w pierwszej matrycy jest równa liczbie wierszy w drugiej! Stąd otrzymujemy dwa wyjścia naraz:

  1. Jesteśmy ważni do kolejności matryc. Na przykład, matryce $ a = lewe [3 razy 2 Prawo] $ i $ B = Left [2 razy 5 Prawe] $ są uzgodnione (2 kolumny w pierwszej matrycy i 2 liniach w drugim) , ale wręcz przeciwnie - matryce $ b = left [2 razy 5 Prawo] $ i $ A = Left [3 razy 2 Prawo] $ - nie uzgodniono (już nie uzgodniono (5 kolumn w pierwszej matrycy - to nie 3 linie w drugim).
  2. Spójność jest łatwa do sprawdzenia, czy zapisujesz wszystkie rozmiary po sobie. Na przykładzie poprzedniego akapitu: "3 2 2 5" - w środku te same liczby, więc uzgodniono matryce. Ale "2 5 3 2" - nie uzgodnione, ponieważ na środku są różne liczby.

Ponadto kapitan jest oczywiście oczywisty, że hines, że macierze kwadratowe o tej samej ilości $ pozostawione [N razy n Prawo] $ są zawsze spójne.

W matematyce, gdy procedura przenoszenia obiektów jest ważna (na przykład w powyższej definicji procedura macierzy jest ważna), często mówić o zamówionych parach. Spotkaliśmy się z nimi w szkole: myślę, że jest również jasne, że współrzędne $ pozostawione (1; 0 prawy) $ i $ Left (0; 1 prawy) $ Ustaw różne punkty w samolocie.

Tak więc: Współrzędne są również zamówione pary, które są kompilowane z liczb. Ale nic nie uniemożliwia takiej pary matryc. Następnie można powiedzieć: "Zamówona para $ left Matrices (A; B Prawa) $ jest spójna, jeśli liczba kolumn w pierwszej matrycy pokrywa się z liczbą wierszy w drugiej."

Cóż, więc co?

Definicja mnożenia

Rozważmy dwie spójne matryce: $ A = Left [M razy n Prawo] $ i $ B = Left [n CZAS K Prawy] $. I definiujemy dla nich operacja mnożenia.

Definicja. Praca dwóch uzgodnionych matryc $ A = lewe] $ i $ b = left] $ i $ b = left] $ to nowa matryca $ C = left [m razy k Prawy] $, których elementy uznane za wzoru:

[Rozpocznij {wyrównuj} {{{} _ {i; j}} = {{a}} {i; 1}} cdot {{b} _ {1; j}} + {{A} _ {I; 2}} cdot {{b} _ {2; j}} + ldots + {{a} _ {i; n}} cdot {{b} _ {n; j}} = & = Suma limitów_ {t = 1} ^ {n} {{{a}} {i; t}} cdot {{b} _ {t; j}}}} {}}}

Standard jest standardowy: $ C = a Cdot B $.

Moim zdaniem wszystko jest oczywiste. Następnie nie możesz przeczytać. [nie całkiem]

Dla tych, którzy po raz pierwszy widzi tę definicję, natychmiast pojawiają się dwa pytania:

  1. Co to jest tylko gra?
  2. Dlaczego tak trudno jest?

Cóż, wszystko w porządku. Zacznijmy od pierwszego pytania. Co oznaczają wszystkie te indeksy? I jak nie popełniać błędu podczas pracy z prawdziwymi matrycami?

Przede wszystkim zauważamy, że długa linia do obliczania $ {{C} _ {I; J}} $ (specjalnie umieścić punkt o średniku między indeksami, aby nie zostać zdezorientowanym, ale nie jest konieczne umieszczenie Ogólnie rzecz biorąc - ja sam boli, aby wpisać formułę w definicji) faktycznie sprowadza się do prostej reguły:

  1. W pierwszej matrycy bierzemy linię $ I $ -un;
  2. Wykonujemy kolumnę $ J $ -a w drugiej matrycy;
  3. Dostajemy dwie sekwencje liczb. Alternuj elementy tych sekwencji o tych samych ilościach, a następnie złożyć otrzymane prace.

Ten proces jest łatwy do zrozumienia zdjęć:

Diagram mnożenia dwóch macierzy

Po raz kolejny: naprawię linię $ I $ w pierwszej matrycy, kolumnę $ J $ w drugiej matrycy, zmień elementy o tych samych liczbach, a następnie otrzymane prace są złożone - otrzymujemy $ {{C} _ { ij}} $. I tak za wszystkie 1 $ Le I (1 $ Le J ... Le K $. Te. Będzie suma $ k o takich "perwersji".

W rzeczywistości spotkaliśmy się już z mnożenie matryc w programie szkolnym, tylko w silnie przytulonej formie. Niech Let Let Your:

[Rozpocznij {A} = Left ({} = Left ({x} _ {A}}; {{} _ {a}}; {{z} _ {a}} Wyrośnie {b} = lewe ({{x} _ {b}}; {{y} _ {b}}; {{z} _ {b}} End {wyrównuj}]

Następnie ich praca skalarna będzie kwotą prac parami:

[Wyrośnie {A} Times \ tatrow {b} = {{x} _ {a}} cdot {{x} _ {b}} + {{} _ {a}} cdot {{y } _ {B}} + {{z} _ {a}} cdot {{z} _ {b}}

W rzeczywistości, w tych odległych latach, kiedy drzewa były bardziej zielone, a niebo jaśniejsze, po prostu pomnożone przez $ nadrightarrow {a} $ Vector do kolumny $ Prightarrow {b} $.

Dzisiaj nic się nie zmieniło. Właśnie teraz te wiersze i kolumny stały się więcej.

Ale wystarczająca teoria! Spójrzmy na prawdziwe przykłady. I zacznij od najprostszego przypadku - matryc kwadratowych.

Mnożenie matryc kwadratowych.

Zadanie 1. Wykonaj mnożenie:

[Left [Rozpocznij {Array} {* {35} {R}} 1 i 2 -3 i 4 End {Array} W prawo] CDOT Left [Deger {Array} {* {35} {R}} -2 & 4 3 & 1 End {array} Prawo]

Rozwiązanie. Mamy więc dwie macierzy: $ a = left [2 razy 2 w prawo] $ i $ b = left [2 razy 2 w prawo] $. Oczywiste jest, że są uzgodnione (matryce kwadratowe tego samego rozmiaru są zawsze spójne). Dlatego wykonujemy mnożenie:

[Rozpocznij {wyrównuj} Left [Deger {Array} {* {35} {R}} 1 & 2 -3 i 4 End {Array} Prawy] CDOT Left [Rozpocznij {Array} {* {35} {*}}}}} -2 & 4 3 & 1 {{array} w prawo] = lewe [rozpocznij {array} {* {35} {R}} 1 CDOT Left (-2 PRAWO) +2 CDOT 3 & 1 CDOT 4 + 2 CDOT 1 -3 CDOT LEWE (-2 PRAWO) +4 CDOT 3 & -3 CDOT 4 + 4 CDOT 1 END {Array} Prawo] = \\ Left [BELL {Array} {* {35} {R}} 4 i 6 {} { Array} Prawo]. end {wyrównaj}]

To wszystko!

Odpowiedź: $ Left [Rozpocznij {Array} {* {35} {R}} 4 i 6 18 & -8 End {array} Prawe] $.

Zadanie 2. Wykonaj mnożenie:

[Left [Rozpocznij {Matrix} 1 i 3 2 i 6 End {Matrix} Prawo] CDOT Left [Begin {Array} {* {35} {R}} 9 & 6 -3 & -2 End {array} Prawo]

Rozwiązanie. Ponownie uzgodnione matryce, więc wykonać działania: [

[Rozpocznij {wyrównuj} & Left [Deger {Matrix} 1 & 3 2 {End {Matrix} Prawy] Cdot Left [Begin {Array} {* {35} {R }}} End {Array} Prawo] = Lewa [Begin {Array} {* {35} {R}} 1 CDOT 9 + 3 CDOT Left ( -3 PRAWO) & 1 CDOT 6 + 3 CDOT Left (-2 Po prawej) 2 CDOT 9 + 6 CDOT Left (-3 Po prawej) i 2 CDOT 6 + 6 CDOT Lewo (-2 Po prawej) End {Array} Prawo] = & = Left [Rozpocznij {Matrix} 0 & 0 0 & 0 End {Matrix} W prawo]. end {wyrównaj}]

Jak widzimy, okazało się, że macierz wypełniony zerami

Odpowiedź: $ Left [Rozpocznij {Matrix} 0 & 0 0 end {Matrix} W prawo] $.

Z powyższych przykładów oczywiste jest, że mnożenie matryc nie jest tak trudną obsługą. Przynajmniej dla matryc kwadratowych o rozmiarze 2 przez 2.

W procesie obliczeń stanowiliśmy matrycę pośrednią, gdzie bezpośrednio malowane, jakie liczby zawarte w jednej lub innej komórce. W ten sposób powinno być wykonane podczas rozwiązywania tych zadań.

Główne właściwości pracy matrycy

W skrócie. Multiplication Matrix:

  1. Nieprzyjemne: $ a cdot b ne b pcot A $ w ogólnym przypadku. Istnieją oczywiście specjalne macierze, dla których równość wynosi $ a cdot b = b Cdot A $ (na przykład, jeśli $ B = e $ to pojedyncza matryca), ale w większości przypadków nie działa;
  2. Associatation: $ Left (a Cdot B PRAWO) CDOT C = a Cdot Left (b Cdot C Prawy) $. Tutaj bez opcji: Stojąc obok macierzy można zwielokrotnić, nie przetrwać dla następnego i prawa tych dwóch matryc.
  3. Dystrybucja: $ a CDOT Left (B + C Prawo) = a Cdot B + A CDOT C $ i $ Left (A + B Prawy) CDOT C = a CDOT C + B CDOT C $ (Ze względu na niezwiązany, praca musi oddzielnie przepisać dystrybucję po prawej i lewej stronie.

A teraz - to samo, ale bardziej szczegółowo.

Mnożenie matryc jest w dużej mierze przypominając klasyczny mnożenie liczb. Ale istnieją różnice, z których najważniejsze jest to Mnożenie matryc, ogólnie mówiących, niekomutacyjne .

Zastanów się raz po raz kolejny macierze z zadania 1. Znamy już ich bezpośrednie prace:

[Left [Rozpocznij {Array} {* {35} {R}} 1 i 2 -3 i 4 End {Array} W prawo] CDOT Left [Deger {Array} {* {35} {R}} -2 & 4 3 & 1 End {Array} Prawo] = Left [Deger {Array} {* {35} {R}} 4 i 6 & -8 End {array} Prawo]

Ale jeśli zmienisz macierze w niektórych miejscach, otrzymamy zupełnie inny wynik:

[Left [Rozpocznij {Array} {* {35} {R}} -2 & 4 3 & 1 End {Array} W prawo] CDOT Left [Begin {Array} {* {35} {R}} 1 i 2} End {Array} Prawo] = Lewa [Rozpocznij {Matrix} -14 i 4 0 & 10 End {Matrix } \ DOBRZE] \]

Okazuje się, że $ a cdot b note b Ponadto operacja mnożenia jest zdefiniowana tylko dla skoordynowanych macierzy $ A = Left [M razy n Prawo] $ i $ b = Left [n CHTAK K Prawy] $, ale nikt nie gwarantuje, że pozostaną uzgodnione, jeśli zmieniają je w miejscach. Na przykład, $ left macierzy [2 razy 3 w prawo] $ i $ Left [3 razy 5 Prawo] $ są dość zgodne w określonej kolejności, ale te same macierze $ Left [3 razy 5 \ t Prawo] $ i $ Left [2 razy 3 Prawo] $ nagrane w odwrotnej kolejności nie są już uzgodnione. Smutek. :(

Wśród matryc kwadratowych o określonej rozmiarze $ N $ zawsze znajdą takie, które dają ten sam wynik zarówno przy pomnożenie w bezpośrednim, jak iw odwrotnej kolejności. Jak opisać wszystkie podobne matryce (i ile ogólnie) jest tematem dla oddzielnej lekcji. Dzisiaj nie będziemy o tym porozmawiać. :)

Jednakże mnożenie matryc jest stowarzyszone:

[Left) CDOT C = a Cdot Left (B Cdot C Prawnie)

Dlatego, kiedy trzeba pomnożyć kilka macierzy z rzędu jednocześnie, jest to konieczne, aby zrobić to zeskikiem: jest całkiem możliwe, że niektóre pobliskie stałe matryce dają interesujący wynik. Na przykład macierz zerowy, jak w zadaniu 2, omówiono powyżej.

W prawdziwych zadaniach najczęściej musi pomnożyć kwadratowe macierze o rozmiarze o wartości $ [n razy n prawej] $. Zestaw wszystkich takich macierzy jest oznaczonych przez $ {{m.} ^ {N}} $ (tj. Rekordy $ a = lewe [n razy n prawej] $ i [A w {{m.} {n}}] Oznacza to samo), a koniecznie znajdzie macierz $ E $, która nazywa się pojedynczą.

Definicja. Pojedyncza macierz. Kwota $ N $ jest taką matrycą $ e $, która dla dowolnej matrycy kwadratowej $ a = Left [n razy n Prawo] $ odbywa się przez równość:

[A cdot e = e cdot a = a \]

Taka matryca zawsze wygląda równie: na głównej przekątnej znajdują się jednostki i we wszystkich innych komórkach - zer.

Idziemy dalej. Oprócz stowarzyszenia, mnożenie matryc jest również dystryfici

[Rozpocznij {wyrównuj} & a} Left (B + C Prawy) = a Cdot B + A \ Cdot C; & Left (A + B PRAWO) CDOT C = a CDOT C + B CDOT C. End {wyrównaj}

Innymi słowy, jeśli musisz pomnożyć jedną matrycę do sumy pozostałych dwóch, możesz pomnożyć go do każdego z tych "dwóch innych", a następnie złożyć wyniki. W praktyce zazwyczaj konieczne jest wykonanie odwrotnej pracy: zauważamy tę samą matrycę, prowadzimy go na wspornik, wykonujemy dodawanie, a tym samym uprościć swoje życie. :)

Uwaga: Aby opisać dystrybucję, musieliśmy zarejestrować dwa wzory: gdzie ilość znajduje się w drugim mnożniku i gdzie kwota jest w pierwszej kolejności. Dzieje się tak ze względu na fakt, że mnożenie matryc jest niekomutacyjne (i ogólnie, w nieinmustowej algebrze wiele żartów, które podczas pracy ze zwykłymi numerami, nawet nie przychodzą na myśl). A jeśli powiedzmy, musisz napisać tę nieruchomość na egzaminie, na pewno piszę zarówno formuły, w przeciwnym razie nauczyciel może się trochę zabrać.

Dobra, wszystkie były to bajki o placowych macierzy. Co z prostokątnym?

Przypadek matryc prostokątnych

I nic nie jest takie samo jak z kwadratem.

Zadanie 3. Wykonaj mnożenie:

[Left [Rozpocznij {Matrix} Rozpocznij {Matrix} 5 \\ 2 3 {Matrix} Rozpocznij {Matrix} 4} End {Matrix} End {Matrix} Prawo] Cdot Left [Rozpocznij {Array} {* {35} {R}} -2 & 5 3 {}}}} Prawo]

Rozwiązanie. Mamy dwie macierzy: $ a = left [3 razy 2 w prawo] $ i $ b = left [2 razy 2 w prawo] $. Pilimy liczby oznaczające wymiary z rzędu:

[3; 2; 2

Jak widać, centralne dwie liczby pokrywają się. Więc są uzgodnione macierze i mogą pomnożyć. A na wyjściu otrzymujemy matrycę $ C = Left [3 razy 2 Prawo] $:

[Rozpocznij {wyrównuj} & Left [Deger {Matrix} Rozpocznij {Matrix} 5 \\ 2 End {Matrix} Rozpocznij {Matrix} 4 \\ 1 END {Matrix} End {Matrix} Prawo] CDOT Left [Rozpocznij {Array} {* {35} {R}} -2 & 5 3} End {Array} Prawo] = Left [Rozpocznij {Array} {* {35} {R}} 5 CDOT Left (-2 Prawa) +4 CDOT 3 i 5 CDOT 5 + 4 CDOT 4 2 CDOT LEFT (-2 PRAWO) +5 CDOT 3 i 2 CDOT 5 + 5 CDOT 4 3 CDOT Left (-2 Prawa) +1 CDOT 3 i 3 CDOT 5 + 1 CDOT 4 End {macierzy prawy] = lewe [rozpocznij {array} {* {35} {R}} 2 i 41 11 & 30 -3 i 19 { Array} Prawo]. end {wyrównaj}]

Wszystko jest jasne: w końcowej matrycy 3 linii i 2 kolumn. Jest dość $ = left [3 razy 2 prawy] $.

Odpowiedź: $ Left [Rozpocznij {Array} {* {35} {R}} Rozpocznij {Array} {* {35} {R}} 2} {End}} 2 Rozpocznij {Matrix} 41 30 19 {End {Matrix} End {Array} W prawo] $.

Teraz rozważ jeden z najlepszych zadań szkoleniowych dla tych, którzy po prostu zaczynają pracę z matrycami. W nim konieczne jest po prostu pomnożyć niektórych dwóch znaków, ale najpierw ustalić, czy takie mnożenie jest dopuszczalne?

Polecam po przeczytaniu zadania, aby nie spojrzeć w rozwiązanie, ale najpierw spróbuj wykonać go samodzielnie. A następnie porównaj z odpowiedziami.

Zadanie 4. Znajdź wszystkie możliwe pary matryc:

[A = Left [Rozpocznij {Array} {* {35} {R}} Rozpocznij {Matrix} 1 End {Matrix} Rozpocznij {array} {* } -1 1 End {macierz} Rozpocznij {Matrix} 2 End {Matrix} Rozpocznij {Array} {* {35} {R}}} End {Array} End {Array} Prawo]; $ B = Left [Begin {Matrix} Rozpocznij {Matrix} 0 \\ 2 0 {End {Matrix} Rozpocznij {Matrix} 1 0 \\ 3 0 \\ Koniec {matrix} {macierz} prawy] $; $ C = Left [Begin {Matrix} 0 & 1 1 & 0 End {Matrix} W prawo] $.

Rozwiązanie. Aby rozpocząć, napisz wymiary matryc:

[A = Left]; b = Left [4 razy 2 Prawo]; C = Left [2 razy 2 Prawo]

Uzyskamy, że Matryca $ A $ A może być skoordynowana tylko z Matrix $ B $, ponieważ liczba kolumn w $ A $ A $ a 4 $, a taka liczba wierszy jest tylko $ B $. Dlatego możemy znaleźć pracę:

[A CDOT B = Left [Rozpocznij {Array} {* {35} {R}} 1 i 1 & 2 & 2} {array} Prawy] CDOT Left [Begin {Array} {* {35} {R}} 0 i 1 {0 & 3 4 & 0 End {Array} Prawo] = Left [Begin {Array} {* {35} {R}} - 10 & 7 10 & 7 End {array} Prawo]

Proponuję kroki pośrednie do wykonania czytelnika samodzielnie. Zauważam tylko, że wielkość wynikowej matrycy jest lepsza do ustalenia z góry, nawet przed każdym obliczeniami:

[A CDOT B = Left [2 razy 4 Prawy] Cdot Left [4 razy 2 Prawo] = Left [2 razy 2 Prawo]

Innymi słowy, po prostu usuwamy współczynniki "tranzytowe", które zapewniły spójność matryc.

Jakie inne opcje są możliwe? Oczywiście można znaleźć $ B Cdot A $, ponieważ $ B = Left [4 razy 2 Prawo] $, $ A = Left [2 razy 4 w prawo] $, tak zamówić Vapor $ Left (b; prawy) $ jest spójny, a wymiar pracy będzie:

[B Cdot A = Left [4 razy 2 Prawo] Cdot Left [2 razy 4 Prawo] = Left [4 razy 4 Prawo]

Krótko mówiąc, na wyjściu pojawi się macierek $ Left [4 razy 4 Prawo] $, których współczynniki są łatwo rozważyć:

[B Cdot A = Left [Rozpocznij {Array} {* {35} {R}} 0 & 1 2 & 0 0 & 3 4 & 0 End {array} ] CDOT Left [Rozpocznij {Array} {* {35} {R}} 1 & 1 & 2 & 2 {Array W prawo] = Left [Rozpocznij {Array} {* {35} { R}} 1 i 1 & 2 & 6 3 i 6 i 6 i 6 i 6 i 6 & 6 {End {Array} Prawo] ]

Oczywiście możesz zgodzić się na kolejne $ C Cdot A $ i $ B - CDOT C $ - I to jest. Dlatego po prostu piszemy uzyskane prace:

[C CDOT A = Left [Rozpocznij {Array} {* {35} {R}} 1 & 1 & 2 & 2 1 & -1 & 2 & -2 \\\ {array} DOBRZE] \]

[B cdot c = lewe [rozpocznij {array} {* {35} {R}} 1 & 0 0 & 2 3 & 0 0 & 4 End {array} ]]

To było proste.:)

Odpowiedź: $ AB = Left [Rozpocznij {Array} {* {35} {R}} --10 & 7 10 & 7 End {array} Prawe] $; $ Ba = left [rozpocznij {array} {* {35} {R}} 1 & 1 & 2 & 2 2 & 3 & 4 & 6 2 4 i 6 & 6 4 i 8 & -8 End {array} Prawo] $; $ CA = Left [Begin {Array} {* {35} {R}} 1 & 1 & 2 & 2 1 & -1 & 2 & -2 End {array} W prawo] $; $ BC = Left [Begin {Array} {* {35} {R}} 1 & 0 0 & 2 3 & 0 0 & 4 End {array} W prawo] $.

Ogólnie rzecz biorąc, bardzo zalecam wykonanie tego zadania. I jeszcze jeden podobny zadanie, które jest od pracy domowej. Te proste myślenie pomogą Ci wypracować wszystkie kluczowe etapy mnożenia matryc.

Ale na tej historii się nie kończy. Idź do specjalnych przypadków mnożenia :)

Wektorowe sznurki i kolumny wektorowe

Jedną z najczęstszych operacji matrycowych jest mnożenie na matrycy, w której jedna linia lub jedna kolumna.

Definicja. Kolumna wektorowa - Jest to macierz $ left [m razy 1 prawy] $, tj. składający się z kilku linii i tylko jednej kolumny.

Wektor sznurka - Jest to macierz w lewicy $ [1 razy n prawej] $, tj. składający się z jednego rzędu i kilku kolumn.

W rzeczywistości spotkaliśmy się już z tymi obiektami. Na przykład zwykły trójwymiarowy wektor stereometrii $ Prightarrow {A} = Left (x; y; prawy) $ to nic poza sznurkiem wektorowym. Z punktu widzenia teorii różnicy między rzędami i kolumnami, jest prawie nie. Konieczne jest, aby być uważnym za uzgodnione z otaczającymi czynnikami matrycowymi.

Zadanie 5. Wykonaj mnożenie:

[Left [Rozpocznij {Array} {* {35} {R}} 2 & -1 & 3 4 & 2 & 0 \\ -1 i 1 & 1 End {Array} Prawy] CDOT Left [Rozpocznij {Array} {* {35} {R}} 1 \\ -1 End {array} Prawo]

Rozwiązanie. Przed nami praca uzgodnionych macierzy: $ Left [3 razy 3 Prawo] Cdot Left [3 razy 1 Prawo] = Lewa [3 razy 1 Prawo] $. Znajdź tę pracę:

[Left [Rozpocznij {Array} {* {35} {R}} 2 & -1 & 3 4 & 2 & 0 \\ -1 i 1 & 1 End {Array} Prawy] CDOT Left [Rozpocznij {Array} {* {35} {R}} 1 2 {}}} 1 2,1} End {array} W prawo] = lewe [rozpocznij {array} {* {35} {R}} 2 Cdot 1+ Left (-1 Po prawej) CDOT 2 + 3 CDOT Left (-1 Po prawej) 4 CDOT 1 + 2 CDOT 2 + 0 CDOT 2 1 CDOT 1 + 1 CDOT 2 + 1 CDOT Left (-1 Po prawej) End {Array} W prawo] = Lewa [Rozpocznij {Array} {* {35} {R}} - 3 8 0 {array} prawy]

Odpowiedź: $ Left [Rozpocznij {Array} {* {35} {R}} - 3 8 0 {End {array} Prawo] $.

Zadanie 6. Wykonaj mnożenie:

[Left [Rozpocznij {Array} {* {35} {R}} 1 & 2}} 1 & 2 Prawy] Cdot Left [Rozpocznij {Array} {* {35} {R} } 3 i 1 & -1 4 & -1 & 3 2 & 6 & 0 {array} W prawo]

Rozwiązanie. Ponownie, wszystko jest spójne: $ Left [1 razy 3 Prawo] Cdot Left [3 razy 3 Prawo] = Left [1 razy 3 Prawo] $. Rozważamy pracę:

[Left [Rozpocznij {Array} {* {35} {R}} 1 & 2}} 1 & 2 Prawy] Cdot Left [Rozpocznij {Array} {* {35} {R} } 3 & 1 & -1 4 & -1 & 3 2 i 6 & 0 End {Array} W prawo] = Left [Begin {Array} {* {35} {R}} 5 & -19 i 5 {array} Prawo]

W rzeczywistości byłem w złomu liczyć wszystkie te trzy liczby - policz się. I po prostu zapisuję odpowiedź. :)

Odpowiedź: $ Left [Begin {Matrix} 5 & -19 & 5 End {Matrix} Prawo] $.

Jak widać, gdy pomnożysz sznurka wektorowe i kolumnę wektorową na matrycy kwadratowej na wyjściu, zawsze otrzymujemy ciąg lub kolumnę o tym samym rozmiarze. Fakt ten ma wiele zastosowań - od rozwiązywania równania liniowe do wszelkiego rodzaju przemian współrzędnych (co w wyniku, zmniejszają również systemy równań, ale nie bądźmy o smutni).

Myślę, że wszystko było oczywiste tutaj. Idź do ostatniej części dzisiejszej lekcji.

Budowa macierzy do stopnia

Wśród wszystkich operacji mnożącej pewną uwagę, jest podniesiony do stopnia - to wtedy mnożymy ten sam obiekt na kilka razy. Matryce nie są wyjątkiem, mogą być również wzniesione do różnych stopni.

Takie prace są zawsze uzgodnione:

[A CDOT A = Left [N razy n Prawo] CDOT Left [N razy N Prawo] = Left [N razy n Prawo]

I wskazuj dokładnie tak samo jak zwykle stopnie:

[Rozpocznij {wyrównuj} & a cdot a = {{a} ^ {2}}; & a cdot cdot a = {{a} ^ {3}}; & \ flybrace {cdot} cdots cdot a} _ {n} = {{a} ^ {n}}. End {wyrównuj}]

Na pierwszy rzut oka wszystko jest proste. Zobaczmy, jak wygląda w praktyce:

Zadanie 7. Eduge The Matrix do określonego stopnia:

$ {{Left [Begin {Matrix} 1 & 1 0 & 1 End {Matrix} Prawo]} ^ {3}} $

Rozwiązanie. Cóż, wyprostujmy się. Po pierwsze, rzuć się na placu:

[Rozpocznij {wyrównuj} { & 1 0 & 1 end {Matrix} Prawo] Cdot Left [Rozpocznij {Matrix} 1 & 1 0 & 1 End {Matrix} W prawo] = Left [ Rozpocznij {Array} {* {35} {R}} 1 CDOT 1 + 1 CDOT 0 & 1 CDOT 1 + 1 CDOT 1 CDOT 1 + 1 CDOT 0 & 0 CDOT 1 + 1 CDOT 1 END {Array} Prawo] = = lewe [Rozpocznij {Array} {* {35} {R}} 1 & 2 0 & 1 End {Array } Prawo] end {wyrównuj}]

[Rozpocznij {wyrównuj} {{Left [Deger {Matrix} 1 & 1 0 & 1 end {Matrix} Prawo]} ^ {3}} = {{Left [Begin {Matrix } 1 & 1 0 & 1 End {Matrix} Prawo]} ^ {3}} Cdot Left [Rozpocznij {Matrix} 1 & 1 0 & 1 End {Matrix} Right] = = lewe [rozpocznij {array} {* {35} {R}} 1 & 2 0 & 1 End {array} Prawy] } 1 & 1 0 & 1 End {Matrix} Prawo] = = lewe [rozpocznij {array} {* {35} {R}} 1 & 3 0 & 1 Zakończ {Array} Prawo] Koniec {Wyrównaj}

To wszystko.:)

Odpowiedź: $ Left [Rozpocznij {Matrix} 1 & 3 0 & 1 End {Matrix} Prawo] $.

Zadanie 8. Eduge macierz do określonego stopnia:

[{{Left [Rozpocznij {Matrix} 1 i 1 0 i 1 End {Matrix} Prawo]} ^ {10}}]

Rozwiązanie. Ale nie jest konieczne płakać w fakcie, że "stopień jest zbyt duży", "Świat nie jest sprawiedliwy" i "uczyny całkowicie zagubione". W rzeczywistości wszystko jest łatwe:

[Rozpocznij {wyrównuj} {{Left [Rozpocznij {Matrix} 1 i 1 0 i 1 {Matrix} Prawo]} ^ {10}} = {{Left [Begin {Matrix } 1 & 1 0 & 1 End {Matrix} Prawo]} ^ {3}} Cdot {{Left [Begin {Matrix} 1 & 1 0 & 1 End {Matrix } Prawo]} ^ {3}} Cdot {{Left [Rozpocznij {Matrix} 1 i 1 0 & 1 {Matrix} Prawo]} ^ {3}} CDOT Rozpocznij {MATRIX} 1 & 1 0 & 1} {Matrix} W prawo] = & = Left (Left [Rozpocznij {Matrix} 1 i 3 0 i 1 {Matrix} Prawo] CDOT Left [Rozpocznij {Matrix} 1 & 3 0 & 1 End {Matrix} W prawo] Prawo) CDOT Left (Left [Rozpocznij {Matrix} 1 & 3 0 & 1 End {Matrix} Prawo] CDOT Left [Rozpocznij {Matrix} 1 & 1 0 & 1 End {Matrix} W prawo] Prawo) = \\ \\ = Left [Rozpocznij {Matrix} 1 i 6 0 i 1 End {Matrix} W prawo] CDOT Left [Deger {Matrix} 1 & 4 0 & 1 End {Matrix} Prawda] = & = Left [Rozpocznij {Matrix} 1 i 10 0 i 1 end {Matrix} Prawo] End {wyrównaj}]

Uwaga: W drugim wierszu użyliśmy kojarzenia mnożenia. Właściwie wykorzystaliśmy go w poprzednim zadaniu, ale było niejawnie.

Odpowiedź: $ Left [Rozpocznij {Matrix} 1 i 10 0 i 1 {Matrix} Prawo] $.

Jak widać, nic skomplikowanego w budowie macierzy do stopnia. Ostatni przykład może być uogólniony:

[{{Left [Rozpocznij {Matrix} 1 i 1 0 i 1 {Matrix} Prawo]} ^ {N}} = Left [Begin {Array} {* {35} { R}} 1 & N 0 & 1 End {array} Prawo]

Fakt ten jest łatwy do udowodnienia za pomocą indukcji matematycznej lub bezpośredniego mnożenia. Jednak nie zawsze, gdy stopień może zostać złapany przez takie wzory. Dlatego uważa się: często mnożą kilka macierzy "Stroy" okazuje się być łatwiejsze i szybsze niż szukać niektórych regularnych wzorców.

Ogólnie rzecz biorąc, nie szukaj najwyższego znaczenia, w którym nie jest. Podsumowując, rozważ budowę większej matrycy - Alternatywnie $ pozostawiony [3 razy 3 prawy] $.

Zadanie 9. Eduge macierz do określonego stopnia:

[{{Left [Rozpocznij {Matrix} 0 i 1 & 1 1 & 0 & 1 1 i 1 & 0 {Matrix} Prawo]} ^ {3}}]

Rozwiązanie. Nie będzie szukał prawidłowości. Pracujemy "Stroy":

[{{Left [Rozpocznij {Matrix} 0 i 1 i 1 i 0 & 1 1 i 1 & 0 {Matrix} Prawo]} ^ {3}} = {{ Pozostawiono [Rozpocznij {Matrix} 0 i 1 i 1 i 0 & 1 1 i 1 & 0} {Matrix} Prawo]} ^ {2}} Cdot } 0 & 1 & 1 1 & 0 & 1 1 & 1 & 0 {Matrix} Prawo]

Aby rozpocząć, wyprostuj tę matrycę na placu:

[Rozpocznij {wyrównuj} {{Left [Rozpocznij {Matrix} 0 i 1 & 1 1 i 0 & 1 1 i 1 & 0 } = Left [Rozpocznij {Matrix} 0 i 1 & 1 1 i 0 & 1 1 i 1 & 0 {Matrix} Prawo] 1 1 i 0 & 1 1 & 1 & 0 Prawo] = & = Left [Rozpocznij {Array} {* {35} {R}} 2 i 1 & 1 1 & 2 & 1 1 & 1 & 2 End {Array} W prawo] End {wyrównaj}]

Teraz wzniesiony do kostki:

[Rozpocznij {wyrównuj} {{Left [Rozpocznij {Matrix} 0 i 1 i 1 {1 & 1 & 0 } = Left [Rozpocznij {Array} {* {35} {R}} 2 i 1 & 1 1 & 2 & 1 1 & 1 & 2 {Array} Prawy] Pozostawiono [Rozpocznij {Matrix} 0 i 1 & 1 1 i 0 & 1 1 & 1 & 0 {Matrix} Prawo] = & = Left [BELL {Array} {35} {R}} 2 i 3 i 3 {3 i 3 & 2 {{Array} Prawo] end {wyrównuj}]

To wszystko. Zadanie zostało rozwiązane.

Odpowiedź: $ Left [Rozpocznij {Matrix} 2 i 3, 3 i 2 & 3 3 i 3 & 2 \\ {Matrix} Prawo] $.

Jak widać, wolumen obliczeń stał się bardziej, ale znaczenie tego nie zmieniło od tego. :)

Na tej lekcji można zakończyć. Następnym razem spojrzymy na odwrotną obsługę: Według istniejącej pracy będziemy szukać oryginalnych czynników.

Jak już jesteś, prawdopodobnie domyślasz, będzie chodzi o matrycę powrotną i metodami jego lokalizacji.

Zobacz też:

  1. Wyznacznik
  2. odwrotna matryca
  3. Próbna EGE-2011 w matematyce, opcja numer 8
  4. Obszar okręgu
  5. Jak policzyć logarytmy jeszcze szybciej
  6. WebSinar na zadaniu 13: trygonometria

Działania z matrycami

Ta metodologiczna podręcznik pomoże Ci nauczyć się wykonać Działania z matrycami : Dodawanie (odejmowanie) matryc, transpozycji macierzy, mnożenie matryc, znalezienie matrycy odwrotnej. Wszystkie materiały są przedstawione w prostej i dostępnej formie, podano odpowiednie przykłady, więc nawet nieprzygotowany człowiek będzie mógł nauczyć się wykonywać działań z matrycami.

W przypadku samokontroli i autotestu można pobrać kalkulator macierzy za darmo >>>. Spróbuję zminimalizować teoretyczne obliczenia, w niektórych miejscach, wyjaśnień "na palcach" i wykorzystanie nieczystycznych terminów. Miłośnicy solidnej teorii, nie krytykuj, naszym zadaniem jest .

Naucz się wykonywać akcję z matrycami W celu uzyskania ultra szybkiego przygotowania na temat (który ma "spalanie") Intensywny kurs PDF

Matryca, determinant i stały!

Zaczynajmy. Matryca jest prostokątnym stołem Elementy Matryca jest prostokątnym stołem . NS Rozważymy liczby, czyli matryce numeryczne. ELEMENT

- To jest termin. Termin jest wskazany do zapamiętania, często się spotka, nie jest przypadkiem, że użyłem grubej czcionki, aby go podkreślić. Przeznaczenie:

Matryce zazwyczaj oznaczają kapitałowe litery łacińskie Przykład:

Rozważ matrycę "dwie trzy": Matryca jest prostokątnym stołem :Ta matryca składa się z sześciu Wszystkie numery (elementy) wewnątrz matrycy istnieją w sobie, że nie ma odliczenia mowy:

To tylko numery stolików (zestaw)! Zgadzam się również Nie zmieniaj się

Liczby, o ile nie wspomniano inaczej. Każdy numer ma własną lokalizację i nie można ich wyciągnąć! Matrix rozważany ma dwie linie:

I trzy kolumny: STANDARD : Kiedy mówią o rozmiarach matrycy, najpierw

Wskazać liczbę wierszy i tylko wtedy - liczba kolumn. Właśnie zdemontowaliśmy kości macierzy "dwie trzy". Jeśli liczba wierszy i kolumn macierzy zbiega się, a następnie nazywa się matryca Kwadrat , Na przykład:

- Matrix "Trzy trzy". Jeśli w kolumnie One Matrix lub jedna linia , wtedy nazywane są takie macierze .

wektory W rzeczywistości koncepcja matrycy, znamy od szkoły, rozważmy na przykład punkt z "X" współrzędnymi i "Igrek": . Zasadniczo, współrzędne punktu  и Zablokowany w matrycy "jednej". Nawiasem mówiąc, oto jest przykładem, dlaczego kwestionuje porządek liczb:

- Są to dwa zupełnie inne punkty samolotu. Teraz przejdź bezpośrednio do badania :

Działania z matrycami .

1) Pierwsza akcja. Osiągając minus z matrycy (tworzenie minus w matrycy) Wróć do naszej macierzy

. Jak pewnie zauważyłeś, istnieje zbyt wiele negatywnych liczb w tej matrycy. Jest bardzo niewygodne pod względem wykonywania różnych działań z matrycą, jest niewygodne, aby napisać jak najwięcej minusów i wygląda na brzydki w projektowaniu. :Zrobię minus poza matrycą, zmieniając każdy element znaku macierzy

Ulya, jak rozumiesz, znak nie zmienia się, zero - on i w Afryce zero. Przykład podawania:

. Wygląda brzydki. :

Zrobimy minus w matrycy, zmieniając matrycę każdego elementu Cóż, okazało się znacznie bardziej ładniejsze. I co najważniejsze, wykonaj wszelkie działania z matrycą będzie łatwiejsze. Ponieważ istnieje taki matematyczny znak ludowy: .

Im więcej minusów - im więcej zamieszania i błędów 2) .

Matryce zazwyczaj oznaczają kapitałowe litery łacińskie

Akcja sekunda. Mnożenie matrycy do numeru Wszystko jest proste, aby pomnożyć matrycę na numer, potrzebujesz każdy

Element macierzy pomnożyć na dany numer. W tym przypadku na pierwszej trzeciej.

Kolejny przydatny przykład:

- mnożenie matrycy dla frakcji Najpierw rozważ, co robić :NIE MA POTRZEBY Nie trzeba wprowadzać do matrycy, po pierwsze, utrudnia to tylko dalsze działania z matrycą, po drugie, utrudnia sprawdzenie decyzji przez nauczyciela (zwłaszcza, jeśli

- Ostateczna odpowiedź odpowiedzi). Najpierw rozważ, co robić A szczególnie,

Udostępnij każdy element matrycy dla minus siedem: Z artykułu Matematyka do manekinów lub zaczynających się

Pamiętamy, że frakcje dziesiętne z przecinkiem w wyższej matematyce próbują uniknąć każdej drogi. Jedyna rzecz pożądany

Zrób w tym przykładzie - aby zrobić minus w matrycy: Ale jeśli WSZYSTKO Elementy matrycy zostały podzielone na 7 bez pozostałości

Matryce zazwyczaj oznaczają kapitałowe litery łacińskie

Wtedy możesz (i potrzebujesz!) Byłoby podzielenia. W tym przypadku możesz i NIEZBĘDNY Pomnóż wszystkie elementy matrycy Ponieważ wszystkie liczby matryc są podzielone na 2 .

bez pozostałości

Uwaga: W teorii wyższej matematyki, koncepcja szkoły "Division" nie jest. Zamiast wyrażenia "jest to podzielone na to", zawsze można powiedzieć "pomnożyć przez frakcję". Oznacza to, że podział jest szczególnym przypadkiem mnożenia. .

3) trzecia działanie. Transponowanie matrycy.

Matryce zazwyczaj oznaczają kapitałowe litery łacińskie

Aby transponować matrycy, musisz napisać swoje linie do kolumny transponowanej matrycy.

Transpozyj Matrix.

Linia tutaj jest tylko jedna, a zgodnie z regułą, należy ją napisać do kolumny:

- transponowana matryca. Transposed macierz jest zwykle oznaczony nagłym indeksem.

lub dotyk w prawo powyżej.

Aby transponować matrycy, musisz napisać swoje linie do kolumny transponowanej matrycy.

Przykład krok po kroku:

Najpierw przepisz pierwszy ciąg do pierwszej kolumny:

Następnie przepisz drugi ciąg w drugiej kolumnie:

I wreszcie przepisać trzeci ciąg w trzeciej kolumnie:

Gotowy. Mówiąc w przenośni, transpozycji - oznacza to, że macierz na prawym górnym rogu i delikatnie obróć go "na przekątnej," drżącym "numery do kolumn transponowanej matrycy. Tutaj mam stowarzyszenie. .

4) czwarte działanie. Matryce kwoty (różnicy)

Ilość działań macierzy jest prosta.

Matryce zazwyczaj oznaczają kapitałowe litery łacińskie

Nie wszystkie macierze można złożyć. Aby wykonać dodanie (odejmujące) matryce, konieczne jest one takie same.  и

Na przykład, jeśli podano macierz "Dwa do dwóch", może być złożony tylko z "Two Dwie" matrycą i nie inne! :

Złóż matryce Aby złożyć matryce, konieczne jest złożenie odpowiednich elementów. .

Matryce zazwyczaj oznaczają kapitałowe litery łacińskie

Dla różnicy matryc reguła jest podobna ,

Konieczne jest znalezienie różnicy między odpowiednimi elementami. :

 

Znajdź matrycę różnicy

A jak rozwiązać ten przykład, łatwiej jest nie zostać zdezorientowany? Wskazane jest pozbycie się dodatkowych minusów, ponieważ zrobimy minus w matrycy .

Uwaga: W teorii wyższej matematyki, koncepcja szkoły "odejmowanie" nie jest. Zamiast frazy "z tego zawsze można powiedzieć" do tego dodać numer ujemny ". Oznacza to, że odejmowanie jest szczególnym przypadkiem dodawania.

5) Piąta akcja. Maplication Matrix.

Dalej w lesie, grubsze partyzanty. Powiem od razu, zasada mnożenia matryc wygląda bardzo dziwnie i nie jest tak proste, aby to wyjaśnić, ale nadal próbuję to zrobić za pomocą określonych przykładów. Jakie macierze można zwielokrotnić? Do matrycy. można pomnożyć przez matrycę niezbędny, .

Do liczby kolumn matrycy równy liczbie rzędów matrycy Przykład: ?

Czy można pomnożyć matrycę

na matrycy.

Tak więc można pomnożyć dane o macierzy.

Ale jeśli matryce zmieniają się w miejscach, w tym przypadku, mnożenie nie jest już możliwe!

Dlatego mnożenie jest niemożliwe:  и Nie tak rzadko napotkano zadania, gdy student jest zaproponowany do pomnożenia matrycy, której mnożenie jest oczywiście niemożliwe. Należy zauważyć, że w niektórych przypadkach możesz pomnożyć matrycę i tak.

Na przykład dla matryc,

Być może mnożenie

i mnożenie

Matryce zazwyczaj oznaczają kapitałowe litery łacińskie

Jak pomnóż matrycę? Przykład: Mnożenie matryc jest lepiej wyjaśnione na konkretnych przykładach, ponieważ ścisła definicja zostanie zdezorientowana (lub incolukcja) większość czytelników.

Zacznijmy od najprostszego:

Multiply Matrix.

Jak pomnóż matrycę? Przykład:

Natychmiast podaję formułę każdego przypadku:

- Spróbuj natychmiast wzorować wzór.

Przykład jest trudniejszy: Formuła: W rezultacie otrzymuje się tak zwaną matrycę zerowej.

Spróbuj wykonać mnożenie (poprawna odpowiedź

). Zwróć uwagę na to

! To prawie zawsze! Przykład: Zatem,

Podczas rozmnażania matrycy nie można zmienić się!

Jak pomnóż matrycę? Przykład:

Jeśli zadanie jest zaproponowane, aby pomnożyć matrycę

, Muszę pomnożyć w tej kolejności. Nigdy wręcz przeciwnie.

Przejdź do matryc trzecich: Przykład:

Wzór jest bardzo podobny do poprzednich formuł:

Teraz spróbuj wymyślić go w mnożenia następujących macierzy: .

Pomnóż matrycę.

Oto gotowe rozwiązanie, ale staraj się na to najpierw spojrzeć!

6) Szósta akcja. Znalezienie matrycy powrotnej

Ten temat jest dość obszerny i zrobiłem ten element na osobnej stronie.

W międzyczasie zakończono wydajność.

 Algorytm dla mnożenia matrycy umożliwia skuteczne wykorzystanie zasobów nowoczesnych procesorów. Ale wyraźnie pokazuje, że maksymalne wykorzystanie zasobów nowoczesnych procesorów jest daleko od zadania nietrivialnego. Podejście za pomocą mikroerra i maksymalną lokalizację danych w pamięci podręcznej procesora można skutecznie stosować do innych algorytmów.

Po opanowaniu poziomu wpisu zalecam pracę z matrycami na lekcji właściwości operacji na matrycach. Wyrażenia matrycy.

Życzę powodzenia!

Wysłany przez: EMELIN ALEXANDER

Najwyższa matematyka dla nieprawidłowości i nie tylko >>>

(Przejdź na stronę główną)

Jak możesz podziękować autorze?

"Wszystko minęło!" - Pomoc serwisowa online dla studentów

Wstęp

Mnożenie matryc jest jednym z podstawowych algorytmów, które są szeroko stosowane w różnych metodach numerycznych, aw szczególności w algorytmach uczenia maszyn. Wiele implementacji propagacji bezpośredniego i odwrotnego sygnału w warstwach nawróconych sieci Strata jest oparta na tej operacji. Czasami do 90-95% całkowitego czasu spędzonego na uczeniu się maszynowym, dotyczy to tej operacji. Dlaczego to się dzieje? Odpowiedź leży w bardzo skutecznym wdrożeniu tego algorytmu procesorów, akceleratorów graficznych (w ostatnich czasach i specjalnych akceleratorze mnożenia matrycy). Maszyny mnożenia jest jednym z niewielu algorytmów, które umożliwiają skuteczne wykorzystanie wszystkich zasobów obliczeniowych nowoczesnych procesorów i akcesoriatorów graficznych. Dlatego też nie jest zaskakujące, że wiele algorytmów próbuje zmniejszyć do mnożenia matrycowego - dodatkowe koszty związane z przygotowaniem danych są zwykle opłacane przez całkowitą przyspieszenie algorytmów.

Jak więc algorytm mnożenia matrycy? Chociaż obecnie istnieje wiele implementacji tego algorytmu, w tym w kategoriach otwartych źródeł. Niestety, kodeks tych implementacji (głównie na asemblerze) jest bardzo złożony. Jest dobry artykuł w języku angielskim.

, opisując te algorytmy szczegółowo. Do mojej niespodzianki, nie znalazłem analogów na Habré. Jak dla mnie, ten powód jest wystarczająco dość, aby napisać swój artykuł. W celu ograniczenia kwoty prezentacji ograniczam opis algorytmu jednokądrowego dla konwencjonalnych procesorów. Temat multithreading i algorytmów do akceleratorów graficznych wyraźnie zasługuje na oddzielny artykuł.

Proces prezentacji zostanie przeprowadzony przez kroki VVID z przykładami spójnego przyspieszenia algorytmu. Próbowałem napisać najbardziej uproszczenie zadania, ale nie więcej. Mam nadzieję, że ... 

Oświadczenie o problemach (krok 0 AOgólnie rzecz biorąc, funkcja mnożenia matrycy jest opisana jako: BC [I, J] = A * C [I, J] + B * Suma (A [I, K] * B [K, J]); CGdzie ma matryca

Ma rozmiar m x k, matrycy

- k x n i matryca 

- m x N.

Bez uszczerbku dla prezentacji możemy założyć, że A = 0 i B = 1: 

C [I, J] = suma (A [I, K] * B [K, J];

Jego wdrożenie na C ++ "w czole" na formule będzie wyglądać tak:

Void gemm_v0 (int m, int n, int k, const float * a, const float * b, float * c) {dla (int i = 0; i <m; ++ i) {dla (int j = 0; j <n; ++ j) {c [i * n + j] = 0; dla (int k = 0; k <k; ++ k) C [I * N + J] + = A [I * K + K] * B [K * N + J]; }}}

  1. Byłoby głupi, aby spodziewać się jakiejkolwiek produktywności z niej, a naprawdę testowane pomiary pokazują, że w (m = n = k = 1152) zajmuje prawie 1,8 sekundy (maszyna testowa - [email protected], OS - Ubuntu 16.04.6 LTS , Kompilator - opcja kompilatora G ++ - 6.5.0b - "-FPIC -O3 -march = haswell"). Minimalna liczba operacji dla mnożenia matrycy wynosi 2 * m * n * k = 2 * 10 ^ 9. Innly mówiąc, wydajność wynosi 1,6 GFLOPS, który jest bardzo daleko od teoretycznego limitu wydajności pojedynczej gwintowanej dla tego procesora (~ 120 GFLOPS (Float-32), jeśli jest ograniczony do stosowania AVX2 / FMA i ~ 200 Gflops podczas korzystania z AVX-512) . Co należy podjąć, aby zbliżyć się do limitu teoretycznego? Następnie, w trakcie wielu kolejnych optymalizacji, przyjdziemy do rozwiązania, które w dużej mierze odtworzemy to, co jest używane w wielu standardowych bibliotekach. W procesie optymalizacji użyję tylko AVX2 / FMA, AVX-512 Nie będę obawy, ponieważ ich cięcie jest nadal małe.
  2. Wyeliminuj oczywiste niedociągi (pierwszy krok) BNajpierw wyeliminuj najbardziej oczywiste wady algorytmu:
Obliczanie adresów elementów macierzy można uprościć - wykonać stałą część z cyklu wewnętrznego. 

W oryginalnej wersji dostęp do elementów tablicy

Nie jest kolejno. Można go usprawnić, jeśli zmienisz kolejność obliczania w taki sposób, że cykl wewnętrzny jest sekwencyjnym obejściem przez linię dla wszystkich trzech matryc.

Void Gemm_v1 (int m, int n, int k, const float * a, const float * b, float * c) {dla (int i = 0; i <m; ++ i) {float * c = c + i * N; dla (int j = 0; j <n; ++ j) c [j] = 0; dla (int k = 0; k <k; ++ k) {const float * b = b + k * n; Unosić A = A [I * K + K]; dla (int j = 0; j <n; ++ j) c [j] + = a * b [j]; }}}

Wynik pomiarów testowych pokazuje czas wykonania w 250 ms lub 11,4 Gflops. Te. Mamy przyspieszenie 8 razy z takimi małymi edycjami! 

Vectorizującego cyklu wewnętrznego (drugi krok)

  1. Jeśli uważnie spojrzysz na cykl wewnętrzny (zgodnie ze zmienną j), widać, że obliczenia mogą być wykonywane przez bloki (wektory). Prawie wszystkie nowoczesne procesory umożliwiają obliczenia nad takimi wektory. W szczególności zestaw instrukcji AVX działa z wektory 256 bitów. Który umożliwia wykonanie 8 operacji dla liczb rzeczywistych z pojedynczą dokładnością do taktu. AVX2 / FMA robi jeszcze jeden krok naprzód - pozwala na wykonanie funkcjonowania mnożenia fuzji i dodawania (D = A * B + C) nad wektora. Procesory Intel Desktop zaczynające się od czwartej generacji mają 2 256-bitowe moduły FMA, które pozwalają im teoretycznie wykonać 2 * 2 * 8 = 32 operacje (float-32) na takt. Na szczęście instrukcje AVX2 / FMA są dość łatwe w użyciu bezpośrednio z C / C ++ za pomocą funkcji wbudowanych (iskrę). W przypadku AVX2 / FMA są one zadeklarowane w pliku nagłówka <Immertrin.h>.
  2. Void Gemm_v2 (int m, int n, int k, const float * a, const float * b, float * c) {dla (int i = 0; i <m; ++ i) {float * c = c + i * N; dla (int j = 0; j <n; j + = 8) _mm256_storeu_ps (C + j + 0, _MM256_Setzero_ps ()); dla (int k = 0; k <k; ++ k) {const float * b = b + k * n; __m256_set1_ps (a [i * k + k]); Dla (int J = 0; J <N; J = 16) {_MMM256_Storeu_ps (C + J + 0, _MM256_FMADD_PS (A, _MM256_LOADU_PS (B + J + 0), _MM256_LOADU_PS (C + J + 0))); _MM256_storeu_ps (C + j + 8, _MM256_FMADD_PS (A, _MMM256_LOADU_PS (B + J + 8), _MM256_LOADU_PS (C + J + 8)); }}}}

Uruchom testy, zdobądź czas 217 ms lub 13.1 Gflops. Ups! Przyspieszenie wynosi tylko 15%. Jak to? Tutaj musisz wziąć pod uwagę dwa czynniki:

Kompilatory są teraz inteligentne poszli (nie wszystkie!) I w pełni poradzić sobie z zadaniem automatyzacji prostych cykli. Już w wersji pierwszej kompilator faktycznie zaangażowany instrukcje AVX2 / FMA, ponieważ ręczna optymalizacja nie dała nam prawie żadnej korzyści.

Wskaźnik obliczeniowy w tym przypadku nie spoczywa na możliwości obliczeniowych procesora, ale w prędkości pobierania i rozładowaniu danych. W tym przypadku procesor aktywacji 2 256-bitowych bloków FMA jest wymagane do pobrania 4 i wyładowania 2 256-bitowe wektor na takt. Jest to dwa razy więcej niż nawet przepustowość L1 pamięci podręcznej procesora (512/256 bit), nie wspominając o przepustowości pamięci, która jest rzędem wielkości mniej (64-bit na kanał)).

Tak więc główny problem w ograniczonej przepustowości pamięci w nowoczesnych procesorach. Procesor właściwie biedny 90% czasu, spodziewa się, gdy dane są ładowane i przechowywane w pamięci.

Dalsze kroki w celu optymalizacji algorytmu będą miały na celu minimalizację dostępu do pamięci. СPiszemy Microker (trzeci krok) СW poprzedniej wersji, 1 operację FMA kont dla 2 pobrań i 1 rozładunek. A и BWiększość wszystkich pobraniach i rozładunkowych występuje z wynikową matrycą

: Dane z niego należy pobrać, dodaj produkt C [I] [J] + = A [I] [K] * B [K] [J], a następnie oszczędzaj. I tyle razy. Najszybsza pamięć, z którą pracuje procesor, jest jego własnymi rejestratami. Jeśli utrzymywamy wynikową wartość macierzy B.

W rejestrze procesora podczas obliczania będziesz musiał załadować tylko wartość matryc С. Teraz mamy 1 konta operacji FMA dla tylko 2 pobrań.

Jeśli przechowujemy wartości dwóch sąsiednich kolumn matrycy C [I] [J] i C [I] [j + 1], możemy ponownie wykorzystać załadowaną wartość matrycy A [I] [K]. I 1 operacja FMA wymaga tylko 1,5 pobrań. Ponadto, zachowując wynik w 2 niezależnych rejestrach, pozwolimy procesorowi wykonać 2 operacje FMA dla taktu. Podobnie można przechowywać wartości dwóch sąsiednich linii w rejestrach - wówczas oszczędności zostaną zapisane na wartościach macierzystych СCałkowity procesory Desktop Intel zaczynające się od 2. generacji mają 16,256-bitowe rejestry wektorowe (ważne dla 64-bitowego trybu procesora). 12 z nich można użyć do przechowywania części otrzymanej matrycy

Rozmiar 6x16. W rezultacie możemy wykonać 12 * 8 = 96 operacji FMA, pobierając tylko 16 + 6 = 22 wartości z pamięci. Udało nam się zmniejszyć dostęp do pamięci z 2,0 do 0,23 do pobrania do 1 operacji FMA - prawie 10 razy! 

Funkcja, która wykonuje obliczenie tak małego kawałka matrycy С:

, zazwyczaj określane jako mikroner, poniższy przykład jest przykładem takiej funkcji: 

Void Micro_6x16 (int K, Const Float * A, Int LDA, Etap, Const Float * B, Int LDB, Float * C, Int LDC) {___M256 C00 = _MM256_Setzero_ps (); ___m256 c10 = _mm256_setzero_ps (); __m256 c20 = _mm256_setzero_ps (); ___m256 c30 = _mm256_setzero_ps (); ___m256 c40 = _mm256_setzero_ps (); ___m256 c50 = _mm256_setzero_ps (); ___M256 C01 = _MM256_Setzero_ps (); __m256 c11 = _mm256_setzero_ps (); ___m256 C21 = _MM256_Setzero_ps (); ___m256 c31 = _mm256_setzero_ps (); ___m256 c41 = _mm256_setzero_ps (); __m256 c51 = _mm256_setzero_ps (); CONST INT OFFSET0 = LDA * 0; CONST INT OFFSET1 = LDA * 1; CONST INT OFFSET2 = LDA * 2; CONST INT OFFSET3 = LDA * 3; CONST INT OFFSET4 = LDA * 4; CONST INT OFFSET5 = LDA * 5; ___M256 B0, B1, A0, A1; dla (int k = 0; k <k; k ++) {b0 = _MM256_LOADU_PS (B + 0); b1 = _MM256_LOADU_PS (B + 8); A0 = _MMM256_SET1_PS (A [OFFSET0]); a1 = _mm256_set1_ps (a [offset1]); C00 = _MMM256_FMADDD_PS (A0, B0, C00); C01 = _MM256_FMADD_PS (A0, B1, C01); C10 = _MMM256_FMADDD_PS (A1, B0, C10); C11 = _MMM256_FMADDD_PS (A1, B1, C11); A0 = _MMM256_SET1_PS (A [OFFSET2]); A1 = _MM256_Set1_ps (A [OFFSET3]); C20 = _MMM256_FMADDD_PS (A0, B0, C20); C21 = _MM256_FMADD_PS (A0, B1, C21); C30 = _MMM256_FMADDD_PS (A1, B0, C30); C31 = _MMM256_FMADDD_PS (A1, B1, C31); A0 = _MMM256_SET1_PS (A [OFFSET4]); A1 = _MMM256_Set1_ps (a [offset5]); C40 = _mm256_fmadd_ps (A0, B0, C40); C41 = _MMM256_FMADDD_PS (A0, B1, C41); C50 = _MMM256_FMADDD_PS (A1, B0, C50); C51 = _MM256_FMADDD_PS (A1, B1, C51); B + = ldb; A + = krok; } _mm256_storeu_ps (C + 0, _MM256_ADD_PS (C00, _MM256_LOADU_PS (C + 0))); _mm256_storeu_ps (C + 8, _MMM256_ADD_PS (C01, _MMM256_LOADU_PS (C + 8)); C + = LDC; _MMM256_storeu_ps (C + 0, _MM256_add_ps (C10, _MMM256_LOADU_PS (C + 0))); _MMM256_storeu_ps (C + 8, _MM256_ADD_PS (C11, _MMM256_LOADU_PS (C + 8))); C + = LDC; _mm256_storeu_ps (C + 0, _MM256_add_ps (C20, _MM256_LOADU_PS (C + 0))); _MMM256_storeu_ps (C + 8, _MM256_ADD_PS (C21, _MM256_LOADU_PS (C + 8))); C + = LDC; _MMM256_storeu_ps (C + 0, _MM256_add_ps (C30, _MM256_LOADU_PS (C + 0))); _mm256_storeu_ps (C + 8, _MM256_add_ps (C31, _MMM256_LOADU_PS (C + 8))); C + = LDC; _mm256_storeu_ps (C + 0, _MM256_add_ps (C40, _MMM256_LOADU_PS (C + 0))); _mm256_storeu_ps (C + 8, _MM256_add_ps (C41, _MMM256_LOADU_PS (C + 8))); C + = LDC; _mm256_storeu_ps (C + 0, _MM256_ADD_PS (C50, _MMM256_LOADU_PS (C + 0))); _mm256_storeu_ps (C + 8, _MM256_add_ps (C51, _MM256_LOADU_PS (C + 8)));}

Wprowadzamy małą funkcję pomocniczą do zainicjowania początkowej wartości matrycy

void init_c (int m, int n, float * c, int ldc) {dla (int i = 0; i <m; ++ i, c + = ldc) dla (int j = 0; j <n; j + = 8) _mm256_storeu_ps (C + j, _mm256_setzero_ps ());} 

Tutaj LDA, LDB, LDC - wiodący wymiar w ogólnym przypadku) odpowiedniej macierzy.

Następnie funkcja mnożenia zajmie następującą formę:

Void gemm_v3 (int m, int n, int k, const float * a, const float * b, float * c) {dla (int i = 0; i <m; i + = 6) {dla (int j = 0 ; J <N; J + = 16) {init_C (6, 16, C + I * N + J, N); Micro_6x16 (K, A + I * K, K, 1, B + J, N, C + I * N + J, N); }}} B.

Uruchamiamy go i zdobędziemy czas wykonania 78,5 ms lub 36,2 GFLOPS. Te. Korzystanie z mikrokernelu umożliwiło przyspieszenie mnożenia matrycy prawie 3 razy. Ale uzyskaną prędkość jest nadal daleko od maksimum. Gdzie jest teraz wąskie gardło?

  1. Zmień kolejność Matrix B (4 krok) BMicroicer dla każdej iteracji obciążenia dwa 256-bitowe wektor z matrycy
  2. I za każdym razem z nowej linii. Uniemożliwia to procesor skutecznie buforowanie tych danych. Aby poprawić tę sytuację, dokonujemy dwóch zmian: СSkopiuj dane matrycy B.

W tymczasowym buforze, aby dane niezbędne do tego samego mikrokernelu świeciły się w pobliżu.

Zmień kolejność wyszukiwania dla macierzy 

: Najpierw przejdziemy przez kolumny i tylko wtedy na rzędach. Umożliwi to efektywnie korzystać z ponownego użycia wartości macierzy.

Aby zapisać bufor, otrzymamy małą strukturę: B:

Struct buf_t {float * p; int n; BUF_T (rozmiar Int): N (rozmiar), p (float *) _ mm_malloc (rozmiar * 4, 64)) {} ~ buf_t () {_mm_free (p); }}; 

Warto tutaj odnotować, że pobieranie i rozładunek wektorów AVX działa optymalnie podczas wyrównanych danych, ponieważ funkcje specjalne są używane do podświetlenia pamięci.

Funkcja Zmień kolejność Matrix 

Void REILD_B_16 (INT K, CING Float * B, Int LDB, Float * Bufb) {dla (int K = 0; K <K; ++ K, B + = LDB, BUFB + = 16) {_MM256_Storeu_ps (Bufb + 0 , _MMM256_LOADU_PS (B + 0)); _MM256_storeu_ps (Bufb + 8, _MM256_LOADU_PS (B + 8)); }}

W rzeczywistości czwarta wersja funkcji GEMM:

Void Gemm_v4 (int m, int n, int k, const float * a, const float * b, float * c) {dla (int j = 0; j <n; j + = 16) {buf_t bufb (16 * k ); REORDER_B_16 (K, B + J, N, BUFB.P); dla (int i = 0; i <m; i + = 6) {init_c (6, 16, C + I * N + J, N); Micro_6x16 (K, A + I * K, K, 1, BUFB.P, 16, C + I * N + J, N); }}}

Wyniki testów (29,5 ms lub 96,5 GFLOPS) pokazują, że jesteśmy na właściwym miejscu. Faktycznie osiągnął około 80% możliwych teoretycznie maksimum. BZwycięstwo? Niestety nie. Tylko rozmiar macierzy, których używaliśmy do testowania (m = n = k = 1152) okazało się wygodne dla tej wersji algorytmu. Jeśli wzrosnąsz do 100 razy (m = 1152, n = 1152, K = 115200), efektywność algorytmu spadnie do 39,5 Gflops - prawie 2,5 razy. СZlokalizuj dane w pamięci podręcznej L1 (5 etap)

Dlaczego więc rosnący parametr K, skuteczność spada algorytmu? Odpowiedź polega na wielkości bufora, którą użyliśmy do przechowywania wartości zamiennych

. W przypadku dużych wartości po prostu nie staje się w pamięci podręcznej procesora. Rozwiązanie problemu zostanie ograniczone do jego wartości do rozmiaru pamięci podręcznej danych L1. W przypadku procesorów Intel rozmiar pamięci podręcznej danych L1 wynosi 32 KB. Dzięki ograniczeniu wielkości bufora MicroKeEpoe uruchomi nie we wszystkich wartościach K, ale tylko przez zakres, który jest wersetami w pamięci podręcznej L1. Wyniki obliczeń pośrednich macierzy 

Zostanie zapisany w pamięci głównej.

Przedstawiamy MacRoudro - funkcję pomocniczą, która umożliwia obliczenia powyżej obszaru danych, które zostaną pokryte w pamięci podręcznej: 

Void Macro_v5 (int M, Int N, Int K, Const Float * A, Int LDA, Const Float * B, Int LDB, Float * Bufb, Float * C, Int LDC) {FOR (Int J = 0; J <N ; j + = 16) {rederder_b_16 (k, b + j, ldb, bufb); Dla (int i = 0; i <m; i + = 6) mikro_6x16 (K, A + I * LDA, LDA, 1, BUFB, 16, C + I * LDC + J, LDC); }}

W głównej funkcji dodajemy cykl zgodnie z K, w którym zadzwonisz do MacRoyadro:

Void gemm_v5 (int m, int n, int k, const float * a, const float * b, float * c) {const int l1 = 32 * 1024; int mk = std :: min (L1 / 4/16, K); BUF_T BUFB (16 * MK); dla (int k = 0; k <k; k + = mk) {int dk = std :: min (k, k + mk) - k; Jeśli (k == 0) init_c (m, n, c, n); Macro_v5 (M, N, DK, A + K, K, B + K * N, N, BUFB.P, C, N); }} BWyniki pomiarów pokazują, że poruszamy się we właściwym kierunku: dla (m = 1152, n = 1152, k = 115200) Wydajność algorytmu wynosiła 78.1 Gflops. Jest to znacznie lepsze niż w poprzedniej wersji, ale nadal gorsza niż dla macierzy średniej wielkości. AZmień kolejność matrycy A i zlokalizuje w pamięci podręcznej L2 (6 krok)

Wykazanie rozmiaru K, który jest przetwarzany w Passie Micoker, udało nam się zlokalizować dane matrycy 

w pamięci podręcznej L1. Dane, które są ładowane z matrycy Aprawie trzy razy mniej. Ale spróbujmy zlokalizować je, jednocześnie zmieniając dane, aby były konsekwentnie. Piszemy specjalną funkcję: Void relerder_a_6 (const float * a, int lda, int m, int k, float * bufa) {dla (int i = 0; i <m; i + = 6) {dla (int k = 0; k <k; k + = 4) {const float * pa = a + k; ___m128 A0 = _MM_LOADU_PS (PA + 0 * LDA); ___m128 A1 = _MM_LOADU_PS (PA + 1 * LDA); ___m128 A2 = _MM_LOADU_PS (PA + 2 * LDA); ___m128 A3 = _MM_LOADU_PS (PA + 3 * LDA); ___M128 A4 = _MM_LOADU_PS (PA + 4 * LDA); ___m128 A5 = _MM_LOADU_PS (PA + 5 * LDA); ___M128 A00 = _MM_UNPACKLO_PS (A0, A2); ___m128 A01 = _MM_UNPACKLO_PS (A1, A3); ___m128 A10 = _MM_UNPACKHI_PS (A0, A2); ___m128 A11 = _MM_UNPACKHI_PS (A1, A3); ___M128 A20 = _MM_UNPACKLO_PS (A4, A5); ___m128 A21 = _MM_UNPACKHI_PS (A4, A5); _mm_storeu_ps (Bufa + 0, _MM_UNPACKLO_PS (A00, A01)); _mm_storel_pi ((__ M64 *) (Bufa + 4), A20); _mm_storeu_ps (Bufa + 6, _MM_UNPACKHI_PS (A00, A01)); _mm_storeh_pi ((__ M64 *) (Bufa + 10), A20); _mm_storeu_ps (Bufa + 12, _MM_UNPACKLO_PS (A10, A11)); _mm_storel_pi ((__ M64 *) (Bufa + 16), A21); _mm_storeu_ps (Bufa + 18, _MM_UNPACKHI_PS (A10, A11)); _mm_storeh_pi ((__ M64 *) (Bufa + 22), A21); Bufa + = 24; } A + = 6 * LDA; }} Od, matryca danych

Teraz idź konsekwentnie, a następnie parametr 

Lda. AW Macroyader nie potrzebujemy już. Zmieniono także parametry połączeń mikrokerowych:

Void macro_v6 (int m, int n, int k, const float * a, const float * b, int ldb, float * bufb, float * c, int ldc) {dla (int j = 0; j <n; j + = 16) {rederder_b_16 (k, b + j, ldb, bufb); dla (int I = 0; i <m; i + = 6) mikro_6x16 (K, A + I * K, 1, 6, BUFB, 16, C + I * LDC + J, LDC); }} 

Wielkość bufora do ponownej matrycy

Ograniczamy rozmiar pamięci podręcznej procesora L2 (zwykle jest to z 256 do 1024 KB dla różnych typów procesorów). Główna funkcja dodaje dodatkowy cykl według zmiennej M:

void gemm_v6 (int m, int n, int k, const float * a, const float * b, float * c) {const int l1 = 32 * 1024, L2 = 256 * 1024; Int MK = STD :: min (L1 / 4/16, K) / 4 * 4; int mm = STD :: min (L2 / 4 / MK, M) / 6 * 6; BUF_T BUFB (16 * MK); BUF_T BUFA (MK * mm); dla (int k = 0; k <k; k + = mk) {int dk = std :: min (k, k + mk) - k; dla (int i = 0; i <m; i + = mm) {int dm = std :: min (m, i + mm) - ja; Jeśli (k == 0) init_c (DM, N, C + I * N, N); REILORD_A_6 (A + I * K + K, K, DM, DK, BUFA.P); Macro_v6 (DM, N, DK, BUFA.P, B + K * N, N, BUFB.P, C + I * N, N); }}} BWyniki pomiarów testowych dla (M = 1152, N = 1152, K = 115200) - 88,9 GFLOPS - zbliżył się do jednego krok do wyniku dla matryc średnich. BUżywamy gotówki L3 (7. Krok)

W procesorach, oprócz pamięci podręcznej L1 i L2, nadal istnieje pamięć podręczna L3 (zwykle jego rozmiar wynosi 1-2 MB na jądrze). Spróbujmy go użyć, a na przykład do przechowywania wartości zmienionych macierzy. 

Aby uniknąć niepotrzebnych funkcji połączeń REORDER_B_16. Dodatkowy parametr REORDERB pojawi się w funkcji Macroyader, która zgłosi tę matrycę

Już zamówione: 

Void macro_v7 (int m, int n, int k, const float * a, const float * b, int ldb, float * bufb, vool readborb, float * c, int ldc) {dla (int j = 0; j <n J + = 16) {IF (REORDERB) REORDER_B_16 (K, B + J, LDB, BUFB + K * J); dla (int i = 0; i <m; i + = 6) mikro_6x16 (k, a + i * k, 1, 6, BUFB + K * J, 16, C + I * LDC + J, LDC); }}

Główna funkcja doda cykl dla N:

void gemm_v7 (int m, int n, int k, const float * a, const float * b, float * c) {const int l1 = 32 * 1024, L2 = 256 * 1024, L3 = 2 * 1024 * 1024; Int MK = STD :: min (L1 / 4/16, K) / 4 * 4; int mm = STD :: min (L2 / 4 / MK, M) / 6 * 6; int Mn = STD :: min (L3 / 4 / MK, N) / 16 * 16; BUF_T BUFB (MN * MK); BUF_T BUFA (MK * mm); Dla (int j = 0; j <n; j + = mn) {int dn = std :: min (n, j + mn) - j; dla (int k = 0; k <k; k + = mk) {int dk = std :: min (k, k + mk) - k; dla (int i = 0; i <m; i + = mm) {int dm = std :: min (m, i + mm) - ja; Jeśli (k == 0) init_c (DM, DN, C + I * N + J, N); REILORD_A_6 (A + I * K + K, K, DM, DK, BUFA.P); Macro_v7 (DM, DN, DK, BUFA.P, B + K * N + J, N, BUFB.P, I == 0, C + I * N + J, N); }}}}

Wyniki pomiarów dla (M = 1152, N = 1152, K = 115200) podają wyniki w 97,3 Gflops. Te. Przekroczyliśmy nawet wynik dla średnich matryc. W rzeczywistości otrzymaliśmy uniwersalny algorytm (w rzeczywistości nie, o ograniczeniach w następnej sekcji), który jest prawie taki sam sposób efektywnie (około 80% teoretycznie osiągalnych remimum) działa dla dowolnej wielkości matryc. Sugeruje się to, aby zatrzymać i opisać, że w końcu okazało się.

  • Ogólny schemat algorytmu Poniższy rysunek przedstawia schemat powstałego algorytmu: BMicro Kernel. ACykl-1. B.

Według zmiennej k. Zmienione dane z matrycy

  • Okrążenie w pamięci podręcznej L1, przywrócone dane z matrycy LA w pamięci podręcznej L2. Kwota jest nagromadzona w rejestrach (Cache L0). Wynik jest rejestrowany w pamięci głównej. Wymiary mikrokernału są określane przez długość wektora SIMD i liczbę rejestrów wektorowych. Długość cyklu jest określana przez rozmiar pamięci podręcznej L1, gdzie jest przechowywany AMakrożer
  • Cykl-2. W zmiennej i. Uruchamianie mikrokernel na przywróconych danych Matrix Bktóre leżą w pamięci podręcznej L2. B.

Cykl-3.

Przez zmienną j. Uruchamianie mikrokernel na przywróconych danych Matrix

  • które leżą w pamięci podręcznej L3. Ewentualnie zastanawiaj brakujące dane Wymiary makroyardu są określane przez wartość pamięci podręcznej. APodstawowa funkcja ACykl-4. С.
  • W zmiennej i. Makro-mężczyzna biegnie na matrycy . Każda redoratory iteracji wartości A и B.
  • . Opcjonalne inicjalizuje wartości matrycy Cykl-5. B.

Według zmiennej k. Makro-mężczyzna biegnie na matrycach

Cykl-6.

  1. Przez zmienną j. Makro-mężczyzna biegnie na matrycy
  2. Co pozostaje za kulisami?
  3. W trakcie przedstawiania podstawowych zasad stosowanych w algorytmie mnożenia matrycy, świadomie uprościłem zadanie, w przeciwnym razie nie pasowałoby do żadnego artykułu. Poniżej opisuję kilka pytań, które są nieważne, aby zrozumieć główną istotę algorytmu, ale są bardzo ważne dla ich praktycznego wdrożenia:
  4. W rzeczywistości niestety wielkość macierzy nie zawsze jest oznakowany przez rozmiary mikrokernelu, ponieważ krawędzie macierzy muszą być przetwarzane w specjalny sposób. Dla których konieczne jest wdrożenie mikrokernel o różnych rozmiarach.
  5. W przypadku różnych typów procesorów wdrażane są różne zestawy funkcji mikrolity i ponownego zamieszczenia. Ponadto jego mikrokernel będzie również dla liczb z podwójną dokładnością i numerami złożonymi. Na szczęście mikroorder zoo jest ograniczony tylko przez nich i na najwyższym poziomie kod jest dość uniwersalny.
  6. Mikroofer jest często zapisywany bezpośrednio na asemblerze. Przeprowadzaj również dodatkowe rozładowanie cykli. Ale to nie prowadzi do znacznego przyspieszenia - główne optymalizacje mają skutecznie korzystać z hierarchii pamięci podręcznej pamięci procesora.

Dla małych macierzy (dla każdego pomiaru) stosuje się algorytmy specjalne - czasami zmienia kolejność nie jest skutecznie, czasami konieczne jest stosowanie kolejnej sytuacji macierzy. A czasami wdrażać specjalny mikrokernel.

W uogólnionym algorytmie do mnożenia matrycy wszystkie trzy macierze można transponować. Wydawałoby się, że liczba możliwych algorytmów wzrasta 8 razy! Na szczęście zastosowanie danych wejściowych zmienionych dostępności pozwala na wszystkie przypadki do wykonywania niepotrzebnych mikrokerów.

Prawie wszystkie nowoczesne procesory są wielordzeniowe. A biblioteki mnożenia matrycy używają wielowątkowego do przyspieszenia obliczeń. Zwykle wykorzystywane są kolejne 1-3 dodatkowe cykle, w których zadania są łamane przez różne wątki.

.

Wniosek

Добавить комментарий