Układ kafelkowy


Rysunek 1.

Rysunek 1 przedstawia układ tablicy F32[3,5] w pamięci z fragmentami mapy 2 x 2. Kształt z takim układem zapisuje się jako F32[3,5]{1,0:T(2;2)}, gdzie 1,0 odpowiada fizycznemu porządkowi wymiarów (pole minor_to_major w Układzie), a (2,2) po dwukropku oznacza układanie wymiarów fizycznych kafelki 2 x 2.

Kafelki są planowane w taki sposób, aby zakrywały kształt, a następnie w obrębie każdego z nich elementy są układane bez kafelków, tak jak w przykładzie powyżej, gdzie po prawej stronie w przykładzie widać układ zapisany w pamięci, w tym białe elementy dopełniania, które zostały dodane w celu uzyskania pełnych kafelków o wymiarach 2 x 2, mimo że granice pierwotnej tablicy nie są równomierne.

Dodatkowe elementy dopełnienia nie muszą zawierać żadnej konkretnej wartości.

Wzory indeksów liniowych do powtarzania fragmentów o określonym kształcie i kafelku

Bez płytki element e=(en, en-1, ... , e1) w tablicy z granicami tablicy d=(dn, dn-1, d1) (d1 to najmniejszy wymiar) jest układany w kolejności od największych do mniejszych:

linear_index(e, d)
= linear_index((en, en-1; ... , e1), (dn, dn-1, ... , d1))
= endn-1...d1 + en-1...d1 + en-1 ...

Dla uproszczenia zapisów w tym dokumencie zakładamy, że kafelek ma taką samą liczbę wymiarów jak tablica. W implementacji kafelków w XLA zazwyczaj stosuje się to płytki o mniejszych wymiarach, pozostawiając bez zmian początkowe największe wymiary, a płytki stosuje się tylko do najmniejszych wymiarów, tak aby wspomniany kafelek zawierał przyrostek fizycznych wymiarów ułożonego kafelka.

Gdy używane są płytki z indeksami (tn, tn-1, ... , t1), element w tablicy z indeksami (en, en-1, ..., e1) jest zmapowany na tę pozycję w ostatecznym układzie:

linear_index_with_tile(e, d, t) ⌈t, ⋈, tm, ⋈n, t),
= linear_index((⌊e/t⌋, e mod t), (⌈d/t⌉, t)) n

Układ może mieć 2 części: (⌊en/tn⌋, ... , ⌊e1/t1⌋), co odpowiada indeksowi kafelków w tablicy o rozmiarze (⌈dn/tn⌉, ... , ⌈d) Funkcja ceil pojawia się w ⌈di/ti⌉, ponieważ jeśli kafelki przekroczą granice większej tablicy, dopełnienie zostanie wstawione, tak jak na rys. 1. Zarówno kafelki, jak i ich elementy są ułożone rekurencyjnie bez płytek.

Na przykład na Rysunku 1 element (2,3) ma indeks kafelków (1,1) i indeks wewnątrz kafelka (0,1) dla połączonego wektora współrzędnych (1,1,0,1). Indeksy kafelków mają progi (2,3), a sam kafelek ma wartość (2,2), czyli połączony wektor (2,3,2,2). Indeks liniowy z kafelkiem elementu o indeksie (2,3) w kształcie logicznym

indeks_liniowy((2;3); (3,5); (2;2))
= indeks_liniowy((1;1;0;1); (2,3;2;2))
= indeks_liniowy((1,1); (2,3)) ∙ 2 ∙ 2 + indeks_liniowy(0,1) (0, 1) ∙ 2 ∙ 2 + indeks_liniowy(0,1),

Sąsiadująco z transpozycją i zmianą kształtu

Układ oparty na fragmentach tekstu działa w ten sposób:
Rozważ zastosowanie tablicy wymiarów (dn, dn–1, ... , d1) (d1 to najmniejszy wymiar). Gdy układ jest ułożony z fragmentami obrazu o danym rozmiarze (tn, tn–1, ... , t1) (t1 to najmniejszy wymiar), można je opisać jako sposób transponowania pada, w ten sposób.

  1. Tablica jest dopełniana do (⌈dn/tn⌉∙tn, ... ,⌈d1/t1⌉∙t1).
  2. Każdy wymiar i jest podzielony na (⌈di/ti⌉, ti), tj. tablica jest zmieniana na
    (⌈dn/tn⌉, tn, ... , ⌈d1/t1≉, t1).
    Nie oznacza to, że sam układ nie ulegnie zmianie. Jeśli ktoś nie myśli o płytkach, to takie przekształcenie może wyrazić dowolny kształt z taką samą liczbą elementów jak kształt z dopełnieniem – tutaj widać, jak w ten sposób wyrazić kafelek.
  3. Transponowanie polega na przeniesieniu tn, ... , t1 do najmniejszych wymiarów przy zachowaniu ich względnej kolejności. W ten sposób kolejność wymiarów od największego do największego wynosi
    n/tn⌉, ... , ⌈d1/t1, tn ⌈dn.

Końcowy kształt ma prefiks
(⌈dn/tn⌉, ... , ⌈d1/t1⌉), który opisuje liczbę kafelków w każdym wymiarze. Element tablicy (en, ... , e1) jest mapowany na ten element w końcowym kształcie:
(⌊en/tn⌋, ... , ⌊e0/t0⌋, en mod tn, ... , e1 mod). Łatwo zauważyć, że indeks liniowy elementu zgodnie z oczekiwaniami spełnia powyższą formułę.

Powtórzone płytki

Płytki XLA stają się jeszcze bardziej elastyczne dzięki wielokrotnemu nakładaniu.


Rysunek 2.

Rysunek 2 przedstawia, jak tablica o wymiarach 4 x 8 jest ułożona przy użyciu 2 poziomów płytek (najpierw 2 x 4, a potem 2 x 1). Powtarzające się kafelki symbolizujemy jako (2;4)(2;1). Każdy kolor oznacza kafelek o wymiarach 2 x 4, a każde czerwone pole obramowania to kafelek o wymiarach 2 x 1. Liczby wskazują liniowy indeks w pamięci danego elementu w formacie kafelków. Ten format odpowiada formatowi stosowanemu w przypadku BF16 w TPU z tym, że początkowy kafelek jest większy, czyli kafelek to (8128)(2,1), gdzie celem drugiego podziału na 2 x 1 jest zebranie 2 16-bitowych wartości w celu utworzenia jednej 32-bitowej wartości w sposób zgodny z architekturą TPU.

Pamiętaj, że drugi lub późniejszy kafelek może odnosić się zarówno do mniejszych wymiarów wewnątrz kafelka, jak i tych, które służą tylko do zmiany kolejności danych w kafelku, tak jak w tym przykładzie (8,128)(2,1), ale może też odnosić się do głównych wymiarów kafelków z poprzednich kafelków.

Łączenie wymiarów za pomocą kafelków

Płytki XLA umożliwiają też łączenie wymiarów. Funkcja ta może np. łączyć wymiary w F32[2, 7,8,11,10]{4,3,2,1,0} z F32[112,110]{1,0}, a następnie dodawać do niego kreskę (2,3). Użyty kafelek to (∗,∗,2,∗,3). W tym przypadku gwiazdka w kafelku oznacza wybranie danego wymiaru i połączenie go z kolejnym mniejszym wymiarem. Kilka sąsiadujących wymiarów można zebrać w jednym wymiarze. Podrzędny wymiar jest reprezentowany przez wartość kafelka równą -1 w jego przypadku, co w innym przypadku nie jest prawidłowe w kafelku jako jego rozmiar.

Dokładniej rzecz ujmując, jeśli wymiar i kształtu zostanie usunięty za pomocą gwiazdki w kafelku, to przed zastosowaniem wcześniejszej definicji kafelków dany wymiar jest usuwany zarówno z układanego kafelka, jak i z wektora kafelka. Zakres i-1 kształtu zostaje zwiększony z di-1 do didi-1. Ten krok powtarza się dla każdej gwiazdki we wektorze kafelka.