Semantyka operacji

Poniżej opisujemy semantykę operacji zdefiniowanych w interfejsie XlaBuilder. Zwykle operacje te są mapowane jeden do jednego na operacje zdefiniowane w interfejsie RPC w xla_data.proto.

Uwaga na temat nomenklatury: uogólniony typ XLA to tablica N-wymiarowa z elementami jednolitego typu (np. 32-bitowa liczba zmiennoprzecinkowa). W całej dokumentacji termin tab. oznacza tablicę o dowolnej liczbie wymiarów. Dla wygody szczególne przypadki mają bardziej szczegółowe i znane nazwy. Na przykład wektory to tablice jednowymiarowe, a macierze to tablice dwuwymiarowe.

AfterAll

Zobacz też XlaBuilder::AfterAll.

AfterAll pobiera zróżnicowaną liczbę tokenów i tworzy jeden. Tokeny to typy prymitywne, które można wplatywać między operacjami o efekcie ubocznym, aby wymuszać kolejność. AfterAll może służyć jako złączenie tokenów do sortowania operacji po zestawie operacji.

AfterAll(operands)

Argumenty Typ Semantyka
operands XlaOp zmienna liczba tokenów

AllGather

Zobacz też XlaBuilder::AllGather.

Wykonuje konkatenację w replikach.

AllGather(operand, all_gather_dim, shard_count, replica_group_ids, channel_id)

Argumenty Typ Semantyka
operand XlaOp a także tablicę do łączenia replik w replikach
all_gather_dim int64 Wymiar łączenia
replica_groups wektor wektorów int64 Grupy, między którymi dochodzi do łączenia
channel_id opcjonalnie int64 Opcjonalny identyfikator kanału do komunikacji między modułami
  • replica_groups to lista grup replik, między którymi wykonywane jest konkatenowanie (identyfikator bieżącej repliki można pobrać za pomocą funkcji ReplicaId). Kolejność replik w każdej grupie określa kolejność, w jakiej ich dane wejściowe znajdują się w wyniku. replica_groupsmusi być pusty (w tym przypadku wszystkie repliki należą do jednej grupy, uporządkowanej od 0 do N - 1) lub zawierać taką samą liczbę elementów jak liczba replik. Na przykład replica_groups = {0, 2}, {1, 3} wykonuje konkatenację replik 02 oraz 13.
  • shard_count to rozmiar każdej grupy replik. Potrzebujemy tego w przypadku pustych wartości replica_groups.
  • channel_id jest używany do komunikacji między modułami: tylko operacje all-gather z tym samym channel_id mogą się ze sobą komunikować.

Kształt wyjściowy to kształt danych wejściowych, w którym obiekt all_gather_dim jest razy większy o shard_count. Jeśli na przykład istnieją 2 repliki, a operand ma w 2 replikach odpowiednio wartość [1.0, 2.5] i [3.0, 5.25], wartość wyjściowa tego operacji, gdzie all_gather_dim to 0, będzie wynosić [1.0, 2.5, 3.0, 5.25] w obu replikach.

AllReduce

Zobacz też XlaBuilder::AllReduce.

Wykonuje niestandardowe obliczenia w replikach.

AllReduce(operand, computation, replica_group_ids, channel_id)

Argumenty Typ Semantyka
operand XlaOp Tablica lub niepusta tupla tablic do zredukowania na replikach
computation XlaComputation Obliczanie redukcji
replica_groups wektor wektorów int64 Grupy, w których przeprowadzane są redukcje
channel_id opcjonalnie int64 Opcjonalny identyfikator kanału do komunikacji między modułami
  • Jeśli operand to tablica tablic, operacja all-reduce jest wykonywana na każdym elemencie tablicy.
  • replica_groups to lista grup replik, między którymi wykonywane jest pomniejszenie (identyfikator repliki bieżącej repliki można pobrać za pomocą ReplicaId). replica_groups musi być pusta (w tym przypadku wszystkie repliki należą do jednej grupy) lub zawierać taką samą liczbę elementów, jak liczba replik. Na przykład replica_groups = {0, 2}, {1, 3} wykonuje redukcję między replikami 02 oraz 13.
  • Interfejs channel_id jest używany do komunikacji między modułami: ze sobą mogą komunikować się tylko operacje all-reduce z tym samym elementem channel_id.

Kształt wyjściowy jest taki sam jak kształt danych wejściowych. Jeśli np. są 2 repliki, a operand ma odpowiednio wartości [1.0, 2.5][3.0, 5.25] na obu replikach, wartość wyjściowa z tego działania i obliczenia sumy będzie wynosić [4.0, 7.75] na obu replikach. Jeśli danymi wejściowymi jest krotka, wynikami też jest krotka.

Obliczenie wyniku funkcji AllReduce wymaga podania 1 wejścia z każdej repliki, więc jeśli jedna z nich wykona węzeł AllReduce więcej razy niż druga, pierwsza będzie czekać w nieskończoność. Ponieważ wszystkie repliki działają w ramach tego samego programu, nie ma zbyt wielu sposobów, aby tak się stało, ale jest to możliwe, gdy warunek pętli while zależy od danych z infeedu, a dane te powodują, że pętla while jest wykonywana na jednej replice więcej razy niż na innej.

AllToAll

Zobacz też XlaBuilder::AllToAll.

AllToAll to operacja zbiorcza, która wysyła dane ze wszystkich rdzeni do wszystkich rdzeni. Składa się z 2 etapów:

  1. Faza rozrzutu. W każdym rdzeniu operand jest dzielony na split_count bloków wzdłuż split_dimensions, a bloki są rozproszone po wszystkich rdzeniach, np. i-ty blok jest wysyłany do i-tego rdzenia.
  2. Faza zbierania. Każdy rdzeń łączy odebrane bloki w ciągu concat_dimension.

Uczestniczących rdzeni można używać, konfigurując je w następujący sposób:

  • replica_groups: każda grupa replik zawiera listę identyfikatorów replik uczestniczących w obliczeniach (identyfikator repliki bieżącej repliki można pobrać za pomocą parametru ReplicaId). Operacja AllToAll zostanie zastosowana w podgrupach w określonej kolejności. Na przykład replica_groups = { {1,2,3}, {4,5,0} } oznacza, że operacja AllToAll zostanie zastosowana w ramach replik {1, 2, 3}, a w fazie zbierania otrzymane bloki zostaną spięte w tej samej kolejności: 1, 2, 3. Następnie zostanie zastosowany kolejny operator AllToAll w przypadku replik 4, 5, 0, a kolejność konkatenacji to również 4, 5, 0. Jeśli replica_groups jest pusty, wszystkie repliki należą do jednej grupy w kolejności ich występowania.

Wymagania wstępne:

  • Rozmiar wymiaru operandu w split_dimension jest podzielny przez split_count.
  • Kształt operandu nie jest krotką.

AllToAll(operand, split_dimension, concat_dimension, split_count, replica_groups)

Argumenty Typ Semantyka
operand XlaOp tablica wejściowa o n wymiarach,
split_dimension int64 Wartość w przedziale [0, n) określająca nazwę wymiaru, na którym dany operand jest dzielony
concat_dimension int64 Wartość w przedziale [0, n), która nadaje nazwę wymiaru, w którym łączą się podzielone bloki
split_count int64 Liczba rdzeni, które biorą udział w tej operacji. Jeśli parametr replica_groups jest pusty, powinien on zawierać liczbę replik. W przeciwnym razie powinien być równy liczbie replik w każdej grupie.
replica_groups ReplicaGroup wektor Każda grupa zawiera listę identyfikatorów replik.

Poniżej znajduje się przykład Alltoall.

XlaBuilder b("alltoall");
auto x = Parameter(&b, 0, ShapeUtil::MakeShape(F32, {4, 16}), "x");
AllToAll(x, /*split_dimension=*/1, /*concat_dimension=*/0, /*split_count=*/4);

W tym przykładzie w operacji Alltoall biorą udział 4 rdzenie. W każdym rdzeniu operand jest dzielony na 4 części wzdłuż wymiaru 0, więc każda część ma kształt f32[4,4]. 4 części są rozproszone na wszystkie rdzenie. Następnie każda podstawa konkatenuje otrzymane części według wymiaru 1 w kolejności podstaw 0–4. Dlatego wyjście każdego rdzenia ma postać f32[16,4].

BatchNormGrad

Szczegółowy opis algorytmu znajdziesz w artykule XlaBuilder::BatchNormGradpierwotnym artykule na temat normalizacji zbiorczej.

Oblicza gradienty normy wsadu.

BatchNormGrad(operand, scale, mean, variance, grad_output, epsilon, feature_index)

Argumenty Typ Semantyka
operand XlaOp n wymiarowa tablica do znormalizowania (x)
scale XlaOp Tablica jednowymiarowa (\(\gamma\))
mean XlaOp 1 tablica wymiarowa (\(\mu\))
variance XlaOp 1 tablica wymiarowa (\(\sigma^2\))
grad_output XlaOp Gradienty przekazane do BatchNormTraining (\(\nabla y\))
epsilon float Wartość epsilon (\(\epsilon\))
feature_index int64 Indeks do wymiaru cechy w operand

W przypadku każdej cechy w wymiarze cech (feature_index to indeks wymiaru cech w operand) operacja oblicza gradienty względem operand, offset i scale we wszystkich pozostałych wymiarach. Wartość feature_index musi być prawidłowym indeksem wymiaru cechy w elementach operand.

Te trzy gradienty są zdefiniowane za pomocą tych formuł (przy założeniu, że 4-wymiarowa tablica to operand, indeks wymiarów cech l, rozmiar wsadu m oraz rozmiary przestrzenne w i h):

\[ \begin{split} c_l&= \frac{1}{mwh}\sum_{i=1}^m\sum_{j=1}^w\sum_{k=1}^h \left( \nabla y_{ijkl} \frac{x_{ijkl} - \mu_l}{\sigma^2_l+\epsilon} \right) \\\\ d_l&= \frac{1}{mwh}\sum_{i=1}^m\sum_{j=1}^w\sum_{k=1}^h \nabla y_{ijkl} \\\\ \nabla x_{ijkl} &= \frac{\gamma_{l} }{\sqrt{\sigma^2_{l}+\epsilon} } \left( \nabla y_{ijkl} - d_l - c_l (x_{ijkl} - \mu_{l}) \right) \\\\ \nabla \gamma_l &= \sum_{i=1}^m\sum_{j=1}^w\sum_{k=1}^h \left( \nabla y_{ijkl} \frac{x_{ijkl} - \mu_l}{\sqrt{\sigma^2_{l}+\epsilon} } \right) \\\\\ \nabla \beta_l &= \sum_{i=1}^m\sum_{j=1}^w\sum_{k=1}^h \nabla y_{ijkl} \end{split} \]

Dane wejściowe meanvariance odpowiadają wartościom momentów w wymiarach zbiorczych i przestrzennych.

Typ danych wyjściowych to krotka z 3 uchwytów:

Wyniki Typ Semantyka
grad_operand XlaOp gradient względem wejścia operand ($\nabla x$)
grad_scale XlaOp gradient względem danych wejściowych scale ($\nabla \gamma$)
grad_offset XlaOp gradient względem wejścia offset ($\nabla \beta$)

BatchNormInference

Szczegółowy opis algorytmu znajdziesz w artykule XlaBuilder::BatchNormInference i pierwotnej publikacji wsadowej do normalizacji.

Normalizuje tablicę w wymiarach wsadowych i przestrzennych.

BatchNormInference(operand, scale, offset, mean, variance, epsilon, feature_index)

Argumenty Typ Semantyka
operand XlaOp n wymiarowa tablica do znormalizowania
scale XlaOp 1 tablica wymiarowa
offset XlaOp 1 tablica wymiarowa
mean XlaOp 1 tablica wymiarowa
variance XlaOp Tablica jednowymiarowa
epsilon float Wartość ypsilon
feature_index int64 Indeksuj do wymiaru cechy w operand

W przypadku każdej cechy w wymiarze cech (feature_index to indeks wymiaru cech w wymiarze operand) operacja oblicza średnią i wariację w pozostali wymiarach oraz używa średniej i wariacji do normalizacji każdego elementu w wymiarze operand. Wartość feature_index musi być prawidłowym indeksem wymiaru funkcji w parametrze operand.

Funkcja BatchNormInference jest odpowiednikiem wywołania BatchNormTraining bez obliczania mean i variance dla każdej wsadu. Zamiast tego używa wartości wejściowych mean i variance jako wartości szacunkowych. Celem tej opcji jest zmniejszenie opóźnienia w wyciąganiu wniosków, stąd nazwa BatchNormInference.

Dane wyjściowe to znormalizowany tablica n-wymiarowa o tej samej postaci co wejścieoperand.

BatchNormTraining

Szczegółowy opis algorytmu znajdziesz też w artykułach XlaBuilder::BatchNormTrainingthe original batch normalization paper.

Normalizuje tablicę w wymiarach wsadowych i przestrzennych.

BatchNormTraining(operand, scale, offset, epsilon, feature_index)

Argumenty Typ Semantyka
operand XlaOp tablica n-wymiarowa do znormalizowania (x)
scale XlaOp 1 tablica wymiarowa (\(\gamma\))
offset XlaOp Tablica jednowymiarowa (\(\beta\))
epsilon float Wartość ypsilon (\(\epsilon\))
feature_index int64 Indeksuj do wymiaru cechy w operand

Dla każdej cechy w wymiarze cech (feature_index to indeks wymiaru cech w operand), operacja oblicza średnią i wariancję dla wszystkich innych wymiarów i używa średniej oraz wariancji do normalizacji każdego elementu w operand. Wartość feature_index musi być prawidłowym indeksem wymiaru funkcji w parametrze operand.

W przypadku każdego zbioru w tablicy operand \(x\) , który zawiera melementów o wymiarach przestrzennych wh (przy założeniu, że tablica operand ma 4 wymiary):

  • Oblicza średnią zbiorczą \(\mu_l\) dla każdej cechy l w wymiarze cech:\(\mu_l=\frac{1}{mwh}\sum_{i=1}^m\sum_{j=1}^w\sum_{k=1}^h x_{ijkl}\)

  • Oblicza odchylenie standardowe partii: \(\sigma^2_l\) $\sigma^2l=\frac{1}{mwh}\sum{i=1}^m\sum{j=1}^w\sum{k=1}^h (x_{ijkl} - \mu_l)^2$

  • Normalizuje, skaluje i przesunięcia:\(y_{ijkl}=\frac{\gamma_l(x_{ijkl}-\mu_l)}{\sqrt[2]{\sigma^2_l+\epsilon} }+\beta_l\)

Aby uniknąć błędów dzielenia przez 0, dodawana jest wartość ypsilon, która zazwyczaj jest niewielka.

Typ wyjściowy to tupla 3 wartości XlaOp:

Wyniki Typ Semantyka
output XlaOp tablica n-wymiarowa o tym samym kształcie co wejście operand (y)
batch_mean XlaOp 1 tablica wymiarowa (\(\mu\))
batch_var XlaOp Tablica jednowymiarowa (\(\sigma^2\))

Wartości batch_meanbatch_var to momenty obliczone na podstawie wymiarów zbiorczego i przestrzennego za pomocą podanych powyżej wzorów.

BitcastConvertType

Zobacz też XlaBuilder::BitcastConvertType.

Podobnie jak w przypadku funkcji tf.bitcast w TensorFlow, wykonuje ona bitową operację przesunięcia bitowego elementów z kształtu danych na kształt docelowy. Rozmiar danych wejściowych i wyjściowych musi być taki sam: np. elementy s32 stają się elementami f32 za pomocą procedury bitcast, a 1 element s32 stanie się czterema elementami s8. Przekształcanie bitowe jest implementowane jako przekształcanie na niskim poziomie, więc maszyny z różnymi reprezentacjami zmiennoprzecinkowymi będą dawać różne wyniki.

BitcastConvertType(operand, new_element_type)

Argumenty Typ Semantyka
operand XlaOp tablica typu T o wymiarach D
new_element_type PrimitiveType typ U

Wymiary operandu i docelowego kształtu muszą być zgodne z wyjątkiem ostatniego wymiaru, który zmienia się o współczynnik rozmiaru podstawowego przed konwersją i po niej.

Typy elementów źródłowego i docelowego nie mogą być tablicami.

Przekształcanie bitowe w prosty typ o innej szerokości

BitcastConvert Instrukcja HLO obsługuje przypadek, gdy rozmiar typu elementu wyjściowego T' nie jest równy rozmiarowi elementu wejściowego T. Cała operacja jest teoretycznie bitowym przesyłaniem i nie zmienia podstawowych bajtów, dlatego kształt elementu wyjściowego musi się zmienić. W przypadku B = sizeof(T), B' = sizeof(T') są 2 możliwe scenariusze.

Po pierwsze, gdy B > B', kształt wyjściowy otrzymuje nowy wymiar o wymiary B/B'. Na przykład:

  f16[10,2]{1,0} %output = f16[10,2]{1,0} bitcast-convert(f32[10]{0} %input)

Reguła pozostaje taka sama w przypadku skutecznych skalarów:

  f16[2]{0} %output = f16[2]{0} bitcast-convert(f32[] %input)

W przypadku instrukcji B' > B ostatni wymiar logiczny kształtu wejściowego musi być równy B'/B, a ten wymiar jest pomijany podczas konwersji:

  f32[10]{0} %output = f32[10]{0} bitcast-convert(f16[10,2]{1,0} %input)

Pamiętaj, że konwersje pomiędzy różnymi szerokościami transmisji bitów nie są uwzględniane w obliczeniach.

Transmisja

Zobacz też XlaBuilder::Broadcast.

Dodaje wymiary do tablicy, duplikując dane w niej.

Broadcast(operand, broadcast_sizes)

Argumenty Typ Semantyka
operand XlaOp Tablica do zduplikowania
broadcast_sizes ArraySlice<int64> rozmiary nowych wymiarów,

Nowe wymiary są wstawiane po lewej stronie, czyli jeśli broadcast_sizes ma wartości {a0, ..., aN}, a kształt operandu ma wymiary {b0, ..., bM}, to kształt wyjścia ma wymiary {a0, ..., aN, b0, ..., bM}.

Nowe wymiary indeksują kopie operandu, czyli

output[i0, ..., iN, j0, ..., jM] = operand[j0, ..., jM]

Jeśli na przykład operand to skalar f32 o wartości 2.0f, a broadcast_sizes to {2, 3}, wynik będzie tablicą o kształcie f32[2, 3], a wszystkie jej wartości będą miały wartość 2.0f.

BroadcastInDim

Zobacz też XlaBuilder::BroadcastInDim.

Powiększa rozmiar i rangę tablicy przez duplikowanie danych w niej.

BroadcastInDim(operand, out_dim_size, broadcast_dimensions)

Argumenty Typ Semantyka
operand XlaOp Tablica do zduplikowania
out_dim_size ArraySlice<int64> Wymiary wymiarów kształtu docelowego
broadcast_dimensions ArraySlice<int64> Do którego wymiaru kształtu docelowego ma być dopasowany każdy wymiar kształtu operandu

Podobnie jak w przypadku rozpowszechniania, ale umożliwia dodawanie wymiarów w dowolnym miejscu i rozszerzanie dotychczasowych wymiarów o rozmiar 1.

Wiadomość operand jest przekazywana do kształtu opisanego przez element out_dim_size. broadcast_dimensions mapuje wymiary operand na wymiary kształtu docelowego, tzn. ten wymiar argumentu jest mapowany na wymiar „broadcast_dimension[i]” kształtu wyjściowego. Wymiary operand muszą mieć rozmiar 1 lub taki sam jak wymiar w kształcie wyjściowym, do którego są mapowane. Pozostałe wymiary są wypełniane wymiarami o rozmiarze 1. Następnie przesyłanie danych za pomocą wymiarów zdegenerowanych, aby uzyskać kształt wyjściowy. Semantyka została szczegółowo opisana na stronie transmisji.

Połączenie

Zobacz też XlaBuilder::Call.

Wywołuje obliczenie z danymi argumentami.

Call(computation, args...)

Argumenty Typ Semantyka
computation XlaComputation obliczenia typu T_0, T_1, ..., T_{N-1} -> S z N parametrami dowolnego typu;
args sekwencja N XlaOp N argumentów dowolnego typu

Argumenty typu args i ich elementy muszą odpowiadać parametrom computation. Nie musi być elementu args.

Cholesky

Zobacz też XlaBuilder::Cholesky.

Oblicza dekomponację Choleskiego dla zbioru symetrycznych (hermickich) dodatnio określonych macierzy.

Cholesky(a, lower)

Argumenty Typ Semantyka
a XlaOp tablica o dowolnej liczbie wymiarów typu złożonego lub zmiennoprzecinkowego.
lower bool czy należy użyć górnego, czy dolnego trójkąta w a.

Jeśli lower to true, oblicza dolne macierze trójkątne l takie, że $a = l. l^T$. Jeśli lower to false, oblicza górne macierze trójkątne u takie, że\(a = u^T . u\).

Dane wejściowe są odczytywane tylko z dolnego/górnego trójkąta a, w zależności od wartości lower. Wartości z drugiego trójkąta są ignorowane. Dane wyjściowe są zwracane w tym samym trójkącie, a wartości w drugim trójkącie są definiowane przez implementację i mogą być dowolne.

Jeśli rząd macierzy a jest większy niż 2, macierz a jest traktowana jako zbiór macierzy, w którym wszystkie wymiary z wyjątkiem 2 mniejszych wymiarów są wymiarami zbioru.

Jeśli a nie jest symetryczna (hermityczna) i oraz dodatnio określona, wynik jest zdefiniowany przez implementację.

Zacisk

Zobacz też XlaBuilder::Clamp.

Ogranicza operand do zakresu między wartością minimalną a maksymalną.

Clamp(min, operand, max)

Argumenty Typ Semantyka
min XlaOp tablica typu T
operand XlaOp tablica typu T
max XlaOp tablica typu T

Biorąc pod uwagę operand oraz wartości minimalną i maksymalną, zwraca operand, jeśli znajduje się w zakresie między wartością minimalną i maksymalną, w przeciwnym razie zwraca wartość minimalną, jeśli jest poniżej tego zakresu, lub wartość maksymalną, jeśli operand jest powyżej tego zakresu. Oznacza to, że clamp(a, x, b) = min(max(a, x), b).

Wszystkie trzy tablice muszą mieć taki sam kształt. Jako ograniczona forma transmisji zmienne min lub max mogą być skalarami typu T.

Przykład ze skalarnymi wartościami min i max:

let operand: s32[3] = {-1, 5, 9};
let min: s32 = 0;
let max: s32 = 6;
==>
Clamp(min, operand, max) = s32[3]{0, 5, 6};

Zwiń

Zapoznaj się też z tymi dokumentami dotyczącymi usługi : XlaBuilder::Collapsetf.reshape.

Zwija wymiary tablicy do jednego wymiaru.

Collapse(operand, dimensions)

Argumenty Typ Semantyka
operand XlaOp tablica typu T
dimensions int64 wektor w kolejnym podzbiorze wymiarów T.

Funkcja Collapse zastępuje podzbiór wymiarów operandu pojedynczym wymiarem. Argumenty wejściowe to dowolna tablica typu T i wektory indeksów wymiarów stałe w czasie kompilacji. Indeksy wymiarów muszą być uporządkowane według numerów wymiarów (od niższych do wyższych), w kolejnym podzbiorze wymiarów T. {0, 1, 2}, {0, 1} i {1, 2} to prawidłowe zbiory wymiarów, ale {1, 0} i {0, 2} już nie. Zostaną one zastąpione przez 1 nowy wymiar na tej samej pozycji w sekwencji wymiarów, co wymiary, które zastępuje, a nowy rozmiar wymiaru będzie równy iloczynowi rozmiarów pierwotnych wymiarów. Najmniejsza liczba wymiaru w funkcji dimensions to wymiar o najwolniejszej zmienności (najbardziej ogólny) w gnieździe pętli, które zwija te wymiary, a największa liczba wymiaru to wymiar o najszybszej zmienności (najbardziej szczegółowy). Jeśli potrzebujesz bardziej ogólnej kolejności zwijania, zapoznaj się z operatorem tf.reshape.

Na przykład niech v będzie tablicą złożoną z 24 elementów:

let v = f32[4x2x3] { { {10, 11, 12},  {15, 16, 17} },
{ {20, 21, 22},  {25, 26, 27} },
{ {30, 31, 32},  {35, 36, 37} },
{ {40, 41, 42},  {45, 46, 47} } };

// Collapse to a single dimension, leaving one dimension.
let v012 = Collapse(v, {0,1,2});
then v012 == f32[24] {10, 11, 12, 15, 16, 17,
20, 21, 22, 25, 26, 27,
30, 31, 32, 35, 36, 37,
40, 41, 42, 45, 46, 47};

// Collapse the two lower dimensions, leaving two dimensions.
let v01 = Collapse(v, {0,1});
then v01 == f32[4x6] { {10, 11, 12, 15, 16, 17},
{20, 21, 22, 25, 26, 27},
{30, 31, 32, 35, 36, 37},
{40, 41, 42, 45, 46, 47} };

// Collapse the two higher dimensions, leaving two dimensions.
let v12 = Collapse(v, {1,2});
then v12 == f32[8x3] { {10, 11, 12},
{15, 16, 17},
{20, 21, 22},
{25, 26, 27},
{30, 31, 32},
{35, 36, 37},
{40, 41, 42},
{45, 46, 47} };

CollectivePermute

Zobacz też XlaBuilder::CollectivePermute.

CollectivePermute to operacja zbiorcza, która wysyła i odbiera dane między replikami.

CollectivePermute(operand, source_target_pairs)

Argumenty Typ Semantyka
operand XlaOp tablica wejściowa o n wymiarach,
source_target_pairs <int64, int64> wektor Lista par (source_replica_id, target_replica_id). W przypadku każdej pary operand jest wysyłany z repliki źródłowej do repliki docelowej.

Pamiętaj, że source_target_pair ma następujące ograniczenia:

  • Żadne 2 pary nie mogą mieć tego samego identyfikatora docelowej repliki ani tego samego identyfikatora źródłowej repliki.
  • Jeśli identyfikator repliki nie jest celem w żadnej parze, wyjście na tej replice jest tensorem składającym się z 0(s) o tym samym kształcie co wejście.

Konkatenacja

Zobacz też XlaBuilder::ConcatInDim.

Funkcja CONCATENATE tworzy tablicę z wielu operandów tablicowych. Tablica ma tę samą rangę co każdy operand tablicy wejściowej (który musi być tego samego poziomu co pozostałe) i zawiera argumenty w kolejności, w jakiej zostały określone.

Concatenate(operands..., dimension)

Argumenty Typ Semantyka
operands sekwencja N XlaOp Tablice N typu T o wymiarach [L0, L1, ...]. Wymaga N >= 1.
dimension int64 Wartość z interwału [0, N), która określa nazwę wymiaru do połączenia z wymiarem operands.

Z wyjątkiem wymiaru dimension wszystkie wymiary muszą być takie same. Dzieje się tak, ponieważ XLA nie obsługuje „rozdrobionych” tablic. Pamiętaj też, że wartości o rankingu 0 nie można konkatenować (ponieważ nie można podać nazwy wymiaru, w którym następuje konkatenacja).

Przykład jednowymiarowy:

Concat({ {2, 3}, {4, 5}, {6, 7} }, 0)
>>> {2, 3, 4, 5, 6, 7}

Przykład dwuwymiarowy:

let a = {
{1, 2},
{3, 4},
{5, 6},
};
let b = {
{7, 8},
};
Concat({a, b}, 0)
>>> {
{1, 2},
{3, 4},
{5, 6},
{7, 8},
}

Diagram:

Warunkowy

Zobacz też XlaBuilder::Conditional.

Conditional(pred, true_operand, true_computation, false_operand, false_computation)

Argumenty Typ Semantyka
pred XlaOp Typ skalarny: PRED
true_operand XlaOp Argument typu \(T_0\)
true_computation XlaComputation XlaComputation typu \(T_0 \to S\)
false_operand XlaOp Argument typu \(T_1\)
false_computation XlaComputation XlaComputation typu \(T_1 \to S\)

Wykonuje instrukcję true_computation, jeśli pred ma wartość true, lub false_computation, jeśli pred ma wartość false, i zwraca wynik.

Funkcja true_computation musi przyjmować pojedynczy argument typu \(T_0\) i jest wywoływana za pomocą funkcji true_operand, która musi być tego samego typu. Funkcja false_computation musi przyjmować pojedynczy argument typu \(T_1\) i będzie wywoływana z argumentem false_operand, który musi być tego samego typu. Typ zwróconej wartości funkcji true_computation i false_computation musi być taki sam.

Pamiętaj, że w zależności od wartości parametru pred zostanie wykonane tylko jedno z tych instrukcji: true_computation lub false_computation.

Conditional(branch_index, branch_computations, branch_operands)

Argumenty Typ Semantyka
branch_index XlaOp Skalarnik typu S32
branch_computations sekwencja N XlaComputation XlaComputations typu \(T_0 \to S , T_1 \to S , ..., T_{N-1} \to S\)
branch_operands sekwencja N XlaOp Argumenty typu \(T_0 , T_1 , ..., T_{N-1}\)

Wykonuje instrukcję branch_computations[branch_index] i zwraca jej wynik. Jeśli branch_index to S32, który zawiera wartość < 0 lub >= N, jako gałąź domyślna wykonywana jest branch_computations[N-1].

Każda funkcja branch_computations[b] musi przyjmować 1 argument typu \(T_b\) i będzie wywoływana z argumentem branch_operands[b], który musi być tego samego typu. Typ zwracanej wartości każdego elementu branch_computations[b] musi być taki sam.

Pamiętaj, że w zależności od wartości branch_index zostanie wykonana tylko jedna funkcja branch_computations.

Konw (konwolucja)

Zobacz też XlaBuilder::Conv.

Podobnie jak w przypadku ConvWithGeneralPadding, ale wypełnienie jest określone w uproszczony sposób jako SAME lub VALID. SAME padding wypełnia dane wejściowe (lhs) zerami, aby dane wyjściowe miały taki sam kształt jak dane wejściowe, gdy nie uwzględnia się przesunięcia. VALID padding oznacza brak wypełnienia.

ConvWithGeneralPadding (convolution)

Zobacz też XlaBuilder::ConvWithGeneralPadding.

Oblicza splocenie tego typu, który jest używany w sieciach neuronowych. Konwolucję można tu traktować jako n-wymiarowe okno przesuwające się po n-wymiarowym obszarze bazowym, a obliczenia są wykonywane dla każdej możliwej pozycji okna.

Argumenty Typ Semantyka
lhs XlaOp tablica wejść o wymiarach rank n+2
rhs XlaOp ranking tablicy n+2 wag jądra
window_strides ArraySlice<int64> tablica n-wymiarowa z skokowymi przesunięciami jądra
padding ArraySlice< pair<int64,int64>> tablica n-wymiarowa (low, high) padding
lhs_dilation ArraySlice<int64> tablica współczynnika dylatacji n-d lhs
rhs_dilation ArraySlice<int64> tablica współczynników rozszerzenia po prawej stronie równania w n-wymiarach
feature_group_count int64 liczba grup cech;
batch_group_count int64 liczba grup zbiorczych

Niech n będzie liczbą wymiarów przestrzennych. Argument lhs to tablica o wymiarach n + 2, która opisuje pole podstawy. Nazywamy to wejściem, choć oczywiście prawa strona jest też wejściem. W sieci neuronowej są to aktywacje wejściowe. Wymiary n + 2 to w tej kolejności:

  • batch: każda współrzędna w tym wymiarze reprezentuje niezależny element wejściowy, dla którego wykonywana jest operacja splotu.
  • z/depth/features: Każda pozycja (y,x) w obszarze bazowym ma powiązany wektor, który jest używany w tym wymiarze.
  • spatial_dims: opisują wymiary przestrzenne n, które definiują obszar bazowy, po którym porusza się okno.

Argument rhs to tablica n+2 opisująca splotowy filtr/jądro/okno. Wymiary te są podawane w tej kolejności:

  • output-z: wymiar z danych wyjściowych.
  • input-z: rozmiar tego wymiaru pomnożony przez feature_group_count powinien być równy rozmiarowi z w polu lh.
  • spatial_dims: opisują n wymiary przestrzenne, które definiują okno n-wymiarowe poruszające się po obszarze bazowym.

Argument window_strides określa krok okna konwolucyjnego w wymiarach przestrzennych. Jeśli np. krok w pierwszym wymiarze przestrzennym wynosi 3, okno można umieścić tylko w tych współrzędnych, gdzie pierwszy indeks przestrzenny jest podzielny przez 3.

Argument padding określa wielkość dopełnienia bez dopełnienia, które ma zostać zastosowane do obszaru podstawowego. Ilość wypełnień może być ujemna – bezwzględna wartość ujemnego wypełnienia wskazuje liczbę elementów do usunięcia z wybranego wymiaru przed wykonaniem splotu. padding[0] określa wypełnienie wymiaru y, a padding[1] – wypełnienie wymiaru x. Każda para ma niskie dopełnienie jako pierwszy element i wysokie dopełnienie jako drugi. Dopełnienie dolne jest stosowane w kierunku niższych indeksów, a dopełnienie górne w kierunku wyższych indeksów. Jeśli np. padding[1] to (2,3), w drugim wymiarze przestrzennym pojawi się dopełnienie o 2 zera po lewej stronie i 3 zera po prawej stronie. Użycie wypełnienia jest równoważne wstawianiu tych samych wartości zerowych do wejścia (lhs) przed wykonaniem splotu.

Argumenty lhs_dilationrhs_dilation określają współczynnik rozszerzania, który ma być stosowany odpowiednio do wartości lhs i rhs w każdym wymiarze przestrzennym. Jeśli współczynnik dylatacji w wymiarze przestrzennym wynosi d, między poszczególnymi wpisami w tym wymiarze domyślnie umieszczane są otwory d-1, co zwiększa rozmiar tablicy. Dziury są wypełniane wartością no-op, która w przypadku splotu oznacza zera.

Dilatacja prawej strony nazywana jest też konwolucją atrosową. Więcej informacji znajdziesz w sekcji tf.nn.atrous_conv2d. Rozszerzenie lewej strony to także przekształcenie macierzowe. Więcej informacji znajdziesz w sekcji tf.nn.conv2d_transpose.

Argument feature_group_count (wartość domyślna 1) może być używany do zgrupowanych splotów. Wartość feature_group_count musi być dzielnikiem zarówno wymiaru danych wejściowych, jak i wymiaru danych wyjściowych. Jeśli feature_group_count ma wartość większą niż 1, oznacza to, że koncepcyjnie wymiar cech wejściowych i wyjściowych oraz wymiar cech wyjściowych rhs są podzielone po równo na wiele grup feature_group_count, z których każda składa się z kolejnej podsekwencji cech. Wymiar cechy wejściowej rhs musi być równy wymiarowi cechy wejściowej lhs podzielonemu przez feature_group_count (czyli ma już rozmiar grupy cech wejściowych). Grupy i-te są używane razem do obliczania funkcji feature_group_count dla wielu osobnych splotów. Wyniki tych splotów są łączone w wymiarie funkcji wyjściowej.

W przypadku konwulsji w głębi argument feature_group_count jest ustawiany na wymiar funkcji wejściowych, a filtr jest przekształcany z [filter_height, filter_width, in_channels, channel_multiplier] na [filter_height, filter_width, 1, in_channels * channel_multiplier]. Więcej informacji znajdziesz w sekcji tf.nn.depthwise_conv2d.

Argument batch_group_count (wartość domyślna 1) może być używany do filtrów grupowanych podczas propagacji wstecznej. batch_group_count musi być dzielnikiem rozmiaru wymiaru zbioru danych lhs (wejściowego). Jeśli batch_group_count jest większa niż 1, oznacza to, że wymiar wsadu wyjściowego powinien mieć rozmiar input batch / batch_group_count. Wartość batch_group_count musi być dzielnikiem rozmiaru funkcji wyjściowej.

Kształt wyjściowy ma następujące wymiary w tej kolejności:

  • batch: rozmiar tego wymiaru pomnożony przez batch_group_count powinien być równy rozmiarowi wymiaru batch po lewej stronie.
  • z: ten sam rozmiar co output-z w jądrze (rhs).
  • spatial_dims: po 1 wartości na każde prawidłowe miejsce docelowe okna splotowego.

Rysunek powyżej pokazuje, jak działa pole batch_group_count. W efekcie dzielimy każdą partię zbioru lewej strony na grupy batch_group_count, a także robimy to samo w przypadku funkcji wyjściowych. Następnie dla każdej z tych grup wykonujemy konwolucję parową i konkatenujemy dane wyjściowe wzdłuż wymiaru cechy wyjściowej. semantyka operacyjna wszystkich pozostałych wymiarów (elementu i przestrzeni) pozostaje taka sama.

Prawidłowe rozmieszczenie okna splotowego zależą od długości kroków i rozmiaru obszaru podstawy po dopełnieniu.

Aby opisać splot, rozważmy splot 2D i wybierz w wyniku jego stałe współrzędne batch, z, y i x. Następnie (y,x) to położenie rogu okna w obszarze podstawowym (np. lewy górny róg w zależności od tego, jak zinterpretujesz wymiary przestrzenne). Mamy teraz okno 2D, pochodzące z obszaru podstawowego, w którym każdy punkt 2D jest powiązany z wektorem 1D, dzięki czemu otrzymujemy pole 3D. Z kernela konwolucyjnego, ponieważ stała jest współrzędna wyjściowa z, mamy też pole 3D. Te 2 pola mają te same wymiary, więc możemy obliczyć sumę iloczynów elementów występujących w obu pudełkach (podobnie do iloczynu skalarnego). To jest wartość wyjściowa.

Pamiętaj, że jeśli output-z to np. 5, to każda pozycja okna wygeneruje 5 wartości w wyniku w wymiarze z. Wartości te różnią się rodzajem używanego jądra splotowego – dla każdej współrzędnej output-z pojawia się oddzielna ramka 3D. Możesz więc traktować to jako 5 osobnych konwolucji z różnym filtrem dla każdej z nich.

Oto pseudokod splotu 2D z dopełnieniem i krokiem:

for (b, oz, oy, ox) {  // output coordinates
  value = 0;
  for (iz, ky, kx) {  // kernel coordinates and input z
    iy = oy*stride_y + ky - pad_low_y;
    ix = ox*stride_x + kx - pad_low_x;
    if ((iy, ix) inside the base area considered without padding) {
      value += input(b, iz, iy, ix) * kernel(oz, iz, ky, kx);
    }
  }
  output(b, oz, oy, ox) = value;
}

ConvertElementType

Zobacz też XlaBuilder::ConvertElementType.

Podobnie jak funkcja static_cast oparta na elementach w C++, przeprowadza w C++ operację konwersji z kształtem danych do kształtu docelowego. Wymiary muszą być zgodne, a konwersja dotyczy pojedynczego elementu. Przykładowo elementy s32 stają się elementami f32 za pomocą rutyny konwersji s32 na f32.

ConvertElementType(operand, new_element_type)

Argumenty Typ Semantyka
operand XlaOp tablica typu T o wymiarach D
new_element_type PrimitiveType typ U

Wymiary operandu i kształtu docelowego muszą być zgodne. Typy elementów źródła i docelowego nie mogą być tablicami.

Konwersja z wartości T=s32 na U=f32 spowoduje uruchomienie rutyny normalizacji konwersji int na float, np. zaokrąglania do najbliższej liczby parzystej.

let a: s32[3] = {0, 1, 2};
let b: f32[3] = convert(a, f32);
then b == f32[3]{0.0, 1.0, 2.0}

CrossReplicaSum

Wykonuje funkcję AllReduce z wykorzystaniem obliczeń.

CustomCall

Zobacz też XlaBuilder::CustomCall.

wywołać funkcję przekazaną przez użytkownika w ramach obliczeń;

CustomCall(target_name, args..., shape)

Argumenty Typ Semantyka
target_name string Nazwa funkcji. Zostanie wyemitowana instrukcja wywołania, która będzie kierować się na nazwę tego symbolu.
args sekwencja N XlaOp N argumentów dowolnego typu, które zostaną przekazane funkcji.
shape Shape Kształt wyjściowy funkcji

Podpis funkcji jest taki sam, niezależnie od typu i typu argumentów:

extern "C" void target_name(void* out, void** in);

Jeśli na przykład użycie funkcji CustomCall jest następujące:

let x = f32[2] {1,2};
let y = f32[2x3] { {10, 20, 30}, {40, 50, 60} };

CustomCall("myfunc", {x, y}, f32[3x3])

Oto przykład implementacji myfunc:

extern "C" void myfunc(void* out, void** in) {
  float (&x)[2] = *static_cast<float(*)[2]>(in[0]);
  float (&y)[2][3] = *static_cast<float(*)[2][3]>(in[1]);
  EXPECT_EQ(1, x[0]);
  EXPECT_EQ(2, x[1]);
  EXPECT_EQ(10, y[0][0]);
  EXPECT_EQ(20, y[0][1]);
  EXPECT_EQ(30, y[0][2]);
  EXPECT_EQ(40, y[1][0]);
  EXPECT_EQ(50, y[1][1]);
  EXPECT_EQ(60, y[1][2]);
  float (&z)[3][3] = *static_cast<float(*)[3][3]>(out);
  z[0][0] = x[1] + y[1][0];
  // ...
}

Funkcja dostarczona przez użytkownika nie może mieć efektów ubocznych, a jej wykonanie musi być idempotentne.

Kropka

Zobacz też XlaBuilder::Dot.

Dot(lhs, rhs)

Argumenty Typ Semantyka
lhs XlaOp tablica typu T
rhs XlaOp tablica typu T

Dokładna semantyka tej operacji zależy od szeregów operandów:

Dane wejściowe Wyniki Semantyka
wektor [n] dot wektor [n] wartość skalarna iloczyn skalarny wektorów
macierz [m x k] dot wektor [k] wektor [m] mnożenie wektorów macierzy
macierz [m x k] dot macierz [k x n] macierz [m x n] mnożenie macierzy przez siebie,

Operacja wykonuje sumę produktów drugiego wymiaru funkcji lhs (lub pierwszego, jeśli ma on rangę 1) i pierwszego wymiaru funkcji rhs. Są to „skrócone” wymiary. Wymiary lhsrhs w trybie skompresowanym muszą być takie same. W praktyce można go używać do wykonywania iloczynów skalarnych między wektorami, mnożenia wektorów/matryc lub mnożenia macierzy/matrycy.

DotGeneral

Zobacz też XlaBuilder::DotGeneral.

DotGeneral(lhs, rhs, dimension_numbers)

Argumenty Typ Semantyka
lhs XlaOp tablica typu T
rhs XlaOp tablica typu T
dimension_numbers DotDimensionNumbers numery kontraktowe i wsadowe

Podobnie jak w przypadku kropki, ale umożliwia określenie liczby wymiarów w ramach i w ramach partii zarówno w przypadku lhs, jak i rhs.

Pola DotDimensionNumbers Typ Semantyka
lhs_contracting_dimensions powtarzany int64 lhs wymiaru z wyjątkiem liczb
rhs_contracting_dimensions powtarzany int64 rhs wymiaru z wyjątkiem liczb
lhs_batch_dimensions powtarzany int64 lhs wymiar zbiorczy: numery
rhs_batch_dimensions powtarzany int64 rhs numery wymiarów wsadu

DotGeneral wykonuje sumowanie produktów według wymiarów kontraktowania określonych w dimension_numbers.

Powiązane numery wymiarów umowy z funkcji lhs i rhs nie muszą być takie same, ale muszą mieć te same rozmiary wymiarów.

Przykład z numerami wymiarów umowy:

lhs = { {1.0, 2.0, 3.0},
{4.0, 5.0, 6.0} }

rhs = { {1.0, 1.0, 1.0},
{2.0, 2.0, 2.0} }

DotDimensionNumbers dnums;
dnums.add_lhs_contracting_dimensions(1);
dnums.add_rhs_contracting_dimensions(1);

DotGeneral(lhs, rhs, dnums) -> { {6.0, 12.0},
{15.0, 30.0} }

Powiązane numery wymiarów partii w elementach lhsrhs muszą mieć te same rozmiary wymiarów.

Przykład z liczbami wymiarów partii (partia o rozmiarze 2, macierze 2 x 2):

lhs = { { {1.0, 2.0},
{3.0, 4.0} },
{ {5.0, 6.0},
{7.0, 8.0} } }

rhs = { { {1.0, 0.0},
{0.0, 1.0} },
{ {1.0, 0.0},
{0.0, 1.0} } }

DotDimensionNumbers dnums;
dnums.add_lhs_contracting_dimensions(2);
dnums.add_rhs_contracting_dimensions(1);
dnums.add_lhs_batch_dimensions(0);
dnums.add_rhs_batch_dimensions(0);

DotGeneral(lhs, rhs, dnums) -> { { {1.0, 2.0},
{3.0, 4.0} },
{ {5.0, 6.0},
{7.0, 8.0} } }
Dane wejściowe Wyniki Semantyka
[b0, m, k] dot [b0, k, n] [b0, m, n] batch matmul
[b0, b1, m, k] dot [b0, b1, k, n] [b0, b1, m, n] wsadowy Matmul

Wynika z tego, że wynikowy numer wymiaru zaczyna się od wymiaru „partia”, następnie wymiaru „niezwiązany z kontraktem” lub „niezwiązany z partią” (lhs) i wreszcie wymiaru „niezwiązany z kontraktem” lub „niezwiązany z partią” (rhs).

DynamicSlice

Zobacz też XlaBuilder::DynamicSlice.

DynamicSlice wyodrębnia tablicę podrzędną z tablicy wejściowej w parametrze dynamicznym start_indices. Rozmiar wycinka w każdym wymiarze jest przekazywany w polu size_indices, który określa punkt końcowy wyłącznych interwałów wycinków w każdym wymiarze: [początek, początek + rozmiar). Kształt elementu start_indices musi mieć pozycję == 1, a rozmiar wymiaru musi być równy pozycji operand.

DynamicSlice(operand, start_indices, size_indices)

Argumenty Typ Semantyka
operand XlaOp N-wymiarowa tablica typu T
start_indices sekwencja N XlaOp Lista N skalarnych liczb całkowitych zawierających początkowe indeksy wycinka dla każdego wymiaru. Wartość nie może być mniejsza niż 0.
size_indices ArraySlice<int64> Lista N liczb całkowitych zawierających rozmiar wycinka dla każdego wymiaru. Każda wartość musi być większa od zera, a wartość start + size musi być równa lub mniejsza od rozmiaru wymiaru, aby uniknąć zawijania modulo rozmiar wymiaru.

Efektywne indeksy wycinków są obliczane przez zastosowanie tego przekształcenia do każdego indeksu i w narzędziu [1, N) przed jego wykonaniem:

start_indices[i] = clamp(start_indices[i], 0, operand.dimension_size[i] - size_indices[i])

Dzięki temu wyodrębniony wycinek zawsze mieści się w ramach tablicy operanda. Jeśli przed zastosowaniem przekształcenia plaster jest w zakresie, przekształcenie nie ma żadnego wpływu.

Przykład jednowymiarowy:

let a = {0.0, 1.0, 2.0, 3.0, 4.0}
let s = {2}

DynamicSlice(a, s, {2}) produces:
{2.0, 3.0}

Przykład dwuwymiarowy:

let b =
{ {0.0,  1.0,  2.0},
{3.0,  4.0,  5.0},
{6.0,  7.0,  8.0},
{9.0, 10.0, 11.0} }
let s = {2, 1}

DynamicSlice(b, s, {2, 2}) produces:
{ { 7.0,  8.0},
{10.0, 11.0} }

DynamicUpdateSlice

Zobacz też XlaBuilder::DynamicUpdateSlice.

DynamicUpdateSlice generuje wynik, który jest wartością tablicy wejściowej operand z wycinkiem update nadpisanym start_indices. Kształt argumentu update określa kształt podzbioru wyniku, który jest aktualizowany. Kształt argumentu start_indices musi być równy rank = 1, a rozmiar wymiaru musi być równy rangowi argumentu operand.

DynamicUpdateSlice(operand, update, start_indices)

Argumenty Typ Semantyka
operand XlaOp Tablica N-wymiarowa typu T
update XlaOp Tablica N-wymiarowa typu T zawierająca aktualizację sekcji. Każdy wymiar kształtu aktualizacji musi być większy od zera, a wartość start + update musi być równa rozmiarowi operandu w przypadku każdego wymiaru, aby uniknąć generowania indeksów aktualizacji poza zakresem.
start_indices ciąg N XlaOp Lista N skalarnych liczb całkowitych zawierających początkowe indeksy wycinka dla każdego wymiaru. Wartość nie może być mniejsza niż 0.

Efektywne indeksy wycinków są obliczane przez zastosowanie tego przekształcenia do każdego indeksu i w narzędziu [1, N) przed jego wykonaniem:

start_indices[i] = clamp(start_indices[i], 0, operand.dimension_size[i] - update.dimension_size[i])

Dzięki temu zaktualizowany wycinek zawsze mieści się w zakresie tablicy operanda. Jeśli przed zastosowaniem przekształcenia plaster jest w zakresie, przekształcenie nie ma żadnego wpływu.

Przykład jednowymiarowy:

let a = {0.0, 1.0, 2.0, 3.0, 4.0}
let u = {5.0, 6.0}
let s = {2}

DynamicUpdateSlice(a, u, s) produces:
{0.0, 1.0, 5.0, 6.0, 4.0}

Przykład dwuwymiarowy:

let b =
{ {0.0,  1.0,  2.0},
{3.0,  4.0,  5.0},
{6.0,  7.0,  8.0},
{9.0, 10.0, 11.0} }
let u =
{ {12.0,  13.0},
{14.0,  15.0},
{16.0,  17.0} }

let s = {1, 1}

DynamicUpdateSlice(b, u, s) produces:
{ {0.0,  1.0,  2.0},
{3.0, 12.0, 13.0},
{6.0, 14.0, 15.0},
{9.0, 16.0, 17.0} }

Elementarne operacje arytmetyczne na liczbach dwójkowych

Zobacz też XlaBuilder::Add.

Obsługiwany jest zestaw binarnych operacji arytmetycznych dotyczących elementów.

Op(lhs, rhs)

Gdzie Op to jedna z tych wartości: Add (dodawanie), Sub(odejmowanie), Mul (mnożenie), Div (dzielenie), Pow (potęga), Rem (reszta), Max (maksymalne), Min (minimalne), And (logiczne I), Or (logiczne LUB), Xor (logiczne XOR), ShiftLeft (przesunięcie logiczne 2), ShiftLeft (przesunięcie logiczne 2), ShiftRightArithmetic (przesunięcie logiczne w prawo/1), ShiftRightArithmetic (przesunięcie logiczne/5 w prawo), ShiftRightLogicalAtan2Complex

Argumenty Typ Semantyka
lhs XlaOp Lewy argument: tablica typu T
rhs XlaOp Prawy argument: tablica typu T

Kształty argumentów muszą być podobne lub zgodne. Więcej informacji o tym, co oznacza zgodność kształtów, znajdziesz w dokumentacji dotyczącej transmisji. Wynik operacji ma kształt będący wynikiem transmitowania dwóch tablic wejściowych. W tym wariancie operacje na tablicach o różnych wymiarach nie są obsługiwane, chyba że jeden z operandów jest skalarem.

Gdy Op = Rem, znak wyniku jest taki sam jak znak dzielnej, a bezwzględna wartość wyniku jest zawsze mniejsza od bezwzględnej wartości dzielnika.

Przepełnienie dzielenia liczby całkowitej (dzielenie przez dzielenie/resztę przez zero albo dzielenie/reszta ze znakiem INT_SMIN przez -1) daje zdefiniowaną wartość implementacji.

W przypadku tych operacji istnieje alternatywny wariant z obsługą transmisji o różnych poziomach:

Op(lhs, rhs, broadcast_dimensions)

Gdzie Op jest taki sam jak powyżej. Ten wariant operacji powinien być używany do operacji arytmetycznych między tablicami o różnych poziomach (np. przez dodawanie macierzy do wektora).

Dodatkowy operand broadcast_dimensions to zakres liczb całkowitych służący do rozszerzenia rangi operandu o niższym priorytecie do rangi operandu o wyższym priorytecie. broadcast_dimensions mapuje wymiary kształtu o niższej pozycji na wymiary kształtu o wyższej pozycji. Niezmapowane wymiary rozwiniętego kształtu są wypełniane wymiarami o rozmiarze 1. Przesyłanie wymiarów zdegenerowanych przesyła następnie kształty wzdłuż tych wymiarów zdegenerowanych, aby wyrównać kształty obu operandów. Semantyka jest szczegółowo opisana na stronie z transmisją.

Elementowe operacje porównywania

Zobacz też XlaBuilder::Eq.

Obsługiwany jest zestaw standardowych operacji porównywania binarnego z elementami. Podczas porównywania typów zmiennoprzecinkowych obowiązuje standardowa semantyka porównywania typu zmiennoprzecinkowego IEEE 754.

Op(lhs, rhs)

Gdzie Op to jedna z tych wartości: Eq (równe), Ne (nie równa się), Ge (większe lub równe), Gt (większe niż), Le (mniejsze lub równe), Lt (mniejsze niż). Inny zestaw operatorów, EqTotalOrder, NeTotalOrder, GeTotalOrder, GtTotalOrder, LeTotalOrder i LtTotalOrder, zapewnia te same funkcje, z tym że dodatkowo obsługuje całkowity porządek liczb zmiennoprzecinkowych, narzucając -NaN < -Inf < -Finite < -0 < +0 < +Finite < +Inf < +NaN.

Argumenty Typ Semantyka
lhs XlaOp Lewy argument: tablica typu T
rhs XlaOp Prawy argument: tablica typu T

Kształty argumentów muszą być podobne lub zgodne. Przeczytaj dokumentację transmisji, aby dowiedzieć się, co oznacza zgodność kształtów. Wynik operacji ma kształt będący wynikiem transmitowania 2 tablic wejściowych za pomocą elementu typu PRED. W tym wariancie operacje między tablicami o różnych poziomach nie są obsługiwane, chyba że jeden z operandów jest skalarny.

Istnieje alternatywny wariant z obsługą transmisji różnej rangi dla tych operacji:

Op(lhs, rhs, broadcast_dimensions)

Gdzie Op jest taki sam jak powyżej. Ten wariant operacji powinien być używany do porównywania operacji między tablicami o różnych rzędach (np. przez dodanie macierzy do wektora).

Dodatkowy operand broadcast_dimensions to wycinek liczb całkowitych określający wymiary używane do rozgłaszania operandów. Semantyka została szczegółowo opisana na stronie transmisji.

Funkcje jednoargumentowe dotyczące elementów

XlaBuilder obsługuje te funkcje jednoargumentowe:

Abs(operand) Absolwoty elementu x -> |x|.

Cbrt(operand) Operacja pierwiastka sześciennego z uwzględnieniem elementów: x -> cbrt(x).

Ceil(operand) Element-wise ceil x -> ⌈x⌉.

Clz(operand) Liczba zera na początku elementu.

Cos(operand) Cosinus pierwiastka x -> cos(x).

Erf(operand) Funkcja błędu x -> erf(x) z elementami, gdzie:

\(\text{erf}(x) = \frac{2}{\sqrt{\pi} }\int_0^x e^{-t^2} \, dt\).

Exp(operand) Elementarna potęga wykładnicza x -> e^x.

Expm1(operand) Funkcja naturalna wykładnicza z uwzględnieniem 1 elementu x -> e^x - 1.

Floor(operand) Wartość minimalna z elementami x -> ⌊x⌋.

Imag(operand) Element-wise imaginary part of a complex (or real) shape. x -> imag(x). Jeśli operand jest liczbą zmiennoprzecinkową, zwraca 0.

IsFinite(operand) Sprawdza, czy każdy element operand jest skończony, tj. nie jest dodatnią ani ujemną nieskończonością i nie jest wartością NaN. Zwraca tablicę wartości PRED o tym samym kształcie co wejście, w której każdy element jest true, o ile i tylko o ile odpowiadający element wejściowy jest skończony.

Log(operand) Elementowy logarytm naturalny x -> ln(x).

Log1p(operand) Element po element logarytm naturalny przesunięty o wartość x -> ln(1+x).

Logistic(operand) Obliczanie funkcji logistycznych z uwzględnieniem elementów x -> logistic(x).

Neg(operand) Element-wise negation x -> -x.

Not(operand) Elementowa negacja logiczna x -> !(x).

PopulationCount(operand) oblicza liczbę bitów ustawionych w każdym elemencie operand.

Real(operand) Część rzeczywista elementów złożonej (lub rzeczywistej) formy. x -> real(x). Jeśli operand jest liczbą zmiennoprzecinkową, zwraca tę samą wartość.

Round(operand) Zaokrąglanie elementu równa się od zera.

RoundNearestEven(operand) Zaokrąglanie elementu, oznacza najbliższe parzystość.

Rsqrt(operand) Odwrotność operacji pierwiastka kwadratowego z uwzględnieniem elementu x -> 1.0 / sqrt(x).

Sign(operand) Operacja znaku elementu x -> sgn(x), gdzie

\[\text{sgn}(x) = \begin{cases} -1 & x < 0\\ -0 & x = -0\\ NaN & x = NaN\\ +0 & x = +0\\ 1 & x > 0 \end{cases}\]

za pomocą operatora porównania typu elementu operand.

Sin(operand) Sinus elementowy x -> sin(x).

Sqrt(operand) Operacja pierwiastka kwadratowego z uwzględnieniem elementu x -> sqrt(x).

Tan(operand) Tangens elementu x -> tan(x).

Tanh(operand) Elementowa funkcja tangens hiperboliczny x -> tanh(x).

Argumenty Typ Semantyka
operand XlaOp Argument funkcji

Funkcja jest stosowana do każdego elementu w tablicy operand, co powoduje, że tablica ma ten sam kształt. Wartość operand może być wartością skalarną (pozycja 0).

Fft

Operacja XLA FFT implementuje transformaty Fouriera i odwrotne dla rzeczywistych i złożonych danych wejściowych/wyjściowych. Obsługiwane są wielowymiarowe FFT-y na maksymalnie 3 osiach.

Zobacz też XlaBuilder::Fft.

Argumenty Typ Semantyka
operand XlaOp Tablica, którą przekształcamy za pomocą transformaty Fouriera.
fft_type FftType Patrz tabela poniżej.
fft_length ArraySlice<int64> Długości osi w domenie czasowej, które są przekształcane. Jest to konieczne, aby IRFFT mogła prawidłowo dostosować rozmiar wewnętrznej osi, ponieważ RFFT(fft_length=[16]) ma ten sam kształt wyjściowy co RFFT(fft_length=[17]).
FftType Semantyka
FFT Przesyłanie złożonej FFT. Kształt się nie zmienił.
IFFT odwrotna transformacja Fouriera z złożonej na złożoną; Kształt się nie zmienił.
RFFT Przesyłanie FFT rzeczywistego na zespolony. Kształt wewnętrznej osi jest ograniczony do fft_length[-1] // 2 + 1, jeśli fft_length[-1] jest niezerową wartością, pomijając odwróconą część sprzężenia zwrotnego przekształconego sygnału poza częstotliwością Nyquista.
IRFFT odwrotna transformacja FFT rzeczywistej na zespoloną (czyli przyjmuje zespoloną, zwraca rzeczywistą). Kształt wewnętrznej osi jest rozszerzony do fft_length[-1], jeśli fft_length[-1] ma wartość niezerową. Z konjugaty odwrotnej elementów 1 na fft_length[-1] // 2 + 1 wywnioskowano część przekształconego sygnału poza częstotliwością Nyquista.

Wielowymiarowa transformata Fouriera

Jeśli podano więcej niż 1 wartość fft_length, jest to równoznaczne z zastosowaniem kaskady operacji FFT do każdej z najbardziej wewnętrznych osi. Pamiętaj, że w przypadku przekształceń rzeczywiste > zespolone i zespolone > rzeczywiste wewnętrzna transformacja osi jest (w zasadzie) wykonywana jako pierwsza (RFFT; jako ostatnia w przypadku IRFFT), dlatego wewnętrzna oś jest tą, która zmienia rozmiar. Inne transformacje osi będą wtedy miały wartość complex->complex.

Szczegóły implementacji

Obsługa FFT na procesorze jest realizowana przez TensorFFT w Eigen. FFT na GPU korzysta z cuFFT.

Zbieraj

Operacja zbierania danych XLA łączy kilka wycinków (każdy z nich z potencjalnie innym przesunięciem czasu działania) tablicy wejściowej.

Ogólna semantyka

Zobacz też XlaBuilder::Gather. Bardziej intuicyjny opis znajdziesz w sekcji „Nieformalny opis” poniżej.

gather(operand, start_indices, offset_dims, collapsed_slice_dims, slice_sizes, start_index_map)

Argumenty Typ Semantyka
operand XlaOp Tablica, z której pobieramy dane.
start_indices XlaOp Tablica zawierająca indeksy początkowe przedziałów, które zbieramy.
index_vector_dim int64 Wymiar w pozycji start_indices, który „zawiera” indeksy początkowe. Poniżej znajdziesz szczegółowy opis.
offset_dims ArraySlice<int64> Zbiór wymiarów w kształcie wyjściowym, które są przesunięte w tablicy wyciętej z operanda.
slice_sizes ArraySlice<int64> slice_sizes[i] to granice wycinka w wymiarze i.
collapsed_slice_dims ArraySlice<int64> Zbiór wymiarów w każdej sekcji, które są zwinięte. Te wymiary muszą mieć rozmiar 1.
start_index_map ArraySlice<int64> Mapowanie, które opisuje, jak mapować indeksy w definicji start_indices na prawidłowe indeksy w operandzie.
indices_are_sorted bool Określa, czy indeksy są sortowane przez wywołującego.

Dla wygody w tablicy wyjściowej wymiary niebędące w tablicy offset_dims mają etykietę batch_dims.

Wynikiem jest tablica batch_dims.size + offset_dims.size.

Wartość operand.rank musi być równa sumie wartości parametrów offset_dims.size i collapsed_slice_dims.size. Ponadto wartość slice_sizes.size musi być równa wartości operand.rank.

Jeśli index_vector_dim ma wartość start_indices.rank, domyślnie uznajemy, że start_indices ma wymiar 1 na końcu (np. jeśli start_indices ma kształt [6,7], a index_vector_dim to 2, domyślnie zakładamy, że kształtem start_indices ma kształt [6,7,1]).

Granice tablicy wyjściowej wzdłuż wymiaru i są obliczane w ten sposób:

  1. Jeśli w polu batch_dims występuje parametr i (tzn. w przypadku niektórych k ma ono wartość równa batch_dims[k]), wybieramy odpowiednie granice wymiaru z wymiaru start_indices.shape, pomijając index_vector_dim (czyli wybieramy start_indices.shape.dims[k], jeśli k < index_vector_dim, a w przeciwnym razie: start_indices.shape.dims[k+1]).

  2. Jeśli w polu offset_dims występuje element i (tzn. równa wartości offset_dims[k] w przypadku niektórych danych typu k), po uwzględnieniu collapsed_slice_dims wybieramy odpowiednią granicę z slice_sizes (tzn. wybieramy adjusted_slice_sizes[k], gdzie adjusted_slice_sizes jest slice_sizes z usuniętymi granicami indeksów collapsed_slice_dims).

Formalnie indeks operanda In odpowiadający danemu indeksowi wyjściowemu Out jest obliczany w ten sposób:

  1. Niech G = { Out[k] dla funkcji k w batch_dims. Użyj funkcji G, by wyciąć wektor S w taki sposób, aby S[i] = start_indices[Połącz(G, i)], gdzie Połącz(A; b) wstawia b w pozycji index_vector_dim w A. Pamiętaj, że ten parametr jest dobrze zdefiniowany nawet wtedy, gdy pole G jest puste. Jeśli pole G jest puste, wtedy S = start_indices.

  2. Utwórz indeks początkowy Sin w obszarze operand za pomocą funkcji S, rozkładając S na element start_index_map. Więcej szczegółów:

    1. Sin[start_index_map[k]] = S[k] if k < start_index_map.size.

    2. Sin[_] = 0 w innych przypadkach.

  3. Utwórz indeks Oin w tabeli operand, rozpraszając indeksy w wymiarach offsetowych w tabeli Out zgodnie z zbiorem collapsed_slice_dims. Więcej szczegółów:

    1. Oin[remapped_offset_dims(k)] = Out[offset_dims[k]] jeśli k < offset_dims.size(remapped_offset_dims jest zdefiniowany poniżej).

    2. Oin[_] = 0 w innym przypadku.

  4. In to Oin + Sin, gdzie + oznacza dodawanie elementów.

remapped_offset_dims to monotoniczna funkcja o domenie [0,offset_dims.size] i zakresie [0, operand.rank] \ collapsed_slice_dims. Jeśli na przykład offset_dims.size to 4, operand.rank to 6, a collapsed_slice_dims to {0, 2}, a następnie remapped_offset_dims to {01, 13, 24, 35}.

Jeśli indices_are_sorted ma wartość Prawda, XLA może zakładać, że wartości start_indices są posortowane (w kolejności rosnącej, po rozproszeniu wartości według wartości start_index_map) przez użytkownika. Jeśli nie, semantyka jest definiowana przez implementację.

Opis nieformalny i przykłady

Nieformalnie każdy indeks Out w tablicy wyjściowej odpowiada elementowi E w tablicy operandów, obliczonemu w ten sposób:

  • Używamy wymiarów partii w elementach Out, aby pobrać indeks początkowy z elementu start_indices.

  • Używamy funkcji start_index_map do mapowania indeksu początkowego (którego rozmiar może być mniejszy niż operand.rank) na „pełny” indeks początkowy w operand.

  • Wycinamy dynamicznie wycinek o rozmiarze slice_sizes, używając pełnego indeksu początkowego.

  • Zmieniamy kształt wycinka, zwijając wymiary collapsed_slice_dims. Ponieważ wszystkie zwinięte wymiary sekcji muszą mieć wartość 1, ta zmiana kształtu jest zawsze dozwolona.

  • Aby zindeksować ten wycinek, używamy wymiarów przesunięcia w polu Out, aby uzyskać element wejściowy (E) odpowiadający indeksowi wyjściowemu Out.

We wszystkich przykładach index_vector_dim ma wartość start_indices.rank – 1. Bardziej interesujące wartości dla index_vector_dim nie zmieniają w zasadzie operacji, ale powodują, że wizualizacja staje się bardziej niewygodna.

Aby zrozumieć, jak wszystkie te elementy się ze sobą łączą, przyjrzyjmy się przykładowi, w którym z tablicy [16,11] wybieramy 5 elementów o kształcie [8,6]. Położenie wycinka w tablicy [16,11] można przedstawić jako wektor indeksowy kształtu S64[2], więc zestaw 5 pozycji może być przedstawiony jako macierz S64[5,2].

Działanie operacji zbierania można przedstawić jako przekształcenie indeksu, które przyjmuje argumenty [G,O0,O1], czyli indeks w kształcie wyjściowym, i przypisuje je do elementu w tablicy wejściowej w ten sposób:

Najpierw wybieramy wektor (X,Y) z tablicy indeksów zbiorczego za pomocą funkcji G. Element w tablicy wyjściowej o indeksie [G,O0,O1] jest wtedy elementem w tablicy wejściowej o indeksie [X+O0,Y+O1].

slice_sizes to [8,6], który określa zakres O0 i O1, a to z kolei określa granice sekcji.

Ta operacja zbierania działa jako dynamiczny wycinek zbiorczy z użyciem wymiaru zbiorczego G.

Indeksy zbierania mogą być wielowymiarowe. Na przykład bardziej ogólna wersja powyższego przykładu z wykorzystaniem tablicy „gather indices” (indeksy zbierania danych) o kształcie [4,5,2] przełożyłaby indeksy w następujący sposób:

Ponownie działa on jako dynamiczny wycinek zbiorczy G0G1 jako wymiary zbiorczego. Rozmiar wycinka to nadal [8,6].

Operacja zbierania w XLA upraszcza nieformalną semantykę w następujący sposób:

  1. Możemy skonfigurować, które wymiary w kształcie wyjściowym mają być przesuniętymi wymiarami (wymiary zawierające O0 lub O1 w ostatnim przykładzie). Wymiary wyjściowej partii danych (w ostatnim przykładzie G0, G1) są zdefiniowane jako wymiary wyjściowe, które nie są wymiarami przesunięcia.

  2. Liczba wymiarów przesunięcia danych wyjściowych bezpośrednio w kształcie danych wyjściowych może być mniejsza niż pozycja danych wejściowych. Te „brakujące” wymiary, które są wyraźnie określone jako collapsed_slice_dims, muszą mieć rozmiar wycinka równy 1. Ponieważ mają wycinek o rozmiarze 1, jedynym prawidłowym indeksem dla nich jest 0, a jego usunięcie nie wprowadza niejasności.

  3. Wycinek wyodrębniony z tablicy „Zbierz indeksy” (X, Y w ostatnim przykładzie) może mieć mniej elementów niż wymiar tablicy wejściowej, a jawne mapowanie określa, jak indeks powinien być rozszerzony, aby mieć ten sam wymiar co dane wejściowe.

W ostatnim przykładzie używamy elementów (2) i (3) do implementacji tf.gather_nd:

G0G1 służą do wyodrębniania indeksu początkowego z tablicy zbiorczych indeksów w zwykły sposób, z tą różnicą, że indeks początkowy ma tylko jeden element, X. I podobnie, istnieje tylko 1 indeks przesunięcia wyjściowego o wartości O0. Jednak zanim zostaną użyte jako indeksy tablicy wejściowej, są one rozszerzane zgodnie z „mapowaniem indeksu zbiorczego” (start_index_map w opisie formalnym) i „mapowaniem przesunięcia” (remapped_offset_dims w opisie formalnym) odpowiednio na [X,0] i [0,O0], co daje w sumie [X,O0]. Innymi słowy, indeks wyjściowy [G0,G1,O0] jest mapowany na indeks wejściowy [GatherIndices[G0,G1,0],O0], co daje nam semantykę dla tf.gather_nd.

slice_sizes w tym przypadku to [1,11]. Intuicyjnie oznacza to, że każdy indeks X w tablicy indeksów gromadzenia danych wybiera cały wiersz, w wyniku czego powstaje konkatenacja wszystkich tych wierszy.

GetDimensionSize

Zobacz też XlaBuilder::GetDimensionSize.

Zwraca rozmiar danego wymiaru operanda. Operand musi mieć postać tablicy.

GetDimensionSize(operand, dimension)

Argumenty Typ Semantyka
operand XlaOp tablica wejściowa o n wymiarach,
dimension int64 wartość z przedziału [0, n) określająca wymiar;

SetDimensionSize

Zobacz też XlaBuilder::SetDimensionSize.

Ustawia dynamiczny rozmiar danego wymiaru XlaOp. operand musi mieć kształt tablicy.

SetDimensionSize(operand, size, dimension)

Argumenty Typ Semantyka
operand XlaOp n wymiarowa tablica wejściowa.
size XlaOp int32 reprezentujący rozmiar dynamiczny w czasie wykonywania.
dimension int64 Wartość z przedziału [0, n), która określa wymiar.

W rezultacie przekaż operand z wymiarem dynamicznym śledzonym przez kompilator.

Wartości z dodatkiem zostaną zignorowane przez operacje redukcji w dół łańcucha.

let v: f32[10] = f32[10]{1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
let five: s32 = 5;
let six: s32 = 6;

// Setting dynamic dimension size doesn't change the upper bound of the static
// shape.
let padded_v_five: f32[10] = set_dimension_size(v, five, /*dimension=*/0);
let padded_v_six: f32[10] = set_dimension_size(v, six, /*dimension=*/0);

// sum == 1 + 2 + 3 + 4 + 5
let sum:f32[] = reduce_sum(padded_v_five);
// product == 1 * 2 * 3 * 4 * 5
let product:f32[] = reduce_product(padded_v_five);

// Changing padding size will yield different result.
// sum == 1 + 2 + 3 + 4 + 5 + 6
let sum:f32[] = reduce_sum(padded_v_six);

GetTupleElement

Zobacz też XlaBuilder::GetTupleElement.

Indeksuje tablicę z wartością stałą w czasie kompilacji.

Wartość musi być stałą w czasie kompilacji, aby wnioskowanie o kształt mogło określić typ wynikowej wartości.

Jest to analogiczne do std::get<int N>(t) w C++. Koncepcyjnie:

let v: f32[10] = f32[10]{0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
let s: s32 = 5;
let t: (f32[10], s32) = tuple(v, s);
let element_1: s32 = gettupleelement(t, 1);  // Inferred shape matches s32.

Zobacz też tf.tuple.

Infeed

Zobacz też XlaBuilder::Infeed.

Infeed(shape)

Argument Typ Semantyka
shape Shape Kształt danych odczytywanych z interfejsu In-Feed. Pole układu kształtu musi być ustawione tak, aby odpowiadać układowi danych wysyłanych na urządzenie. W przeciwnym razie zachowanie tego pola będzie nieokreślone.

Odczytuje pojedynczy element danych z ukrytego interfejsu przesyłania danych w ramach InFeed na urządzeniu, interpretując dane jako określony kształt i jego układ, a następnie zwracaXlaOp danych. W obliczeniach można używać wielu operacji na danych wejściowych, ale muszą one być uporządkowane. Na przykład 2 elementy danych wejściowych w poniżej zamieszczonym kodzie mają całkowite zamówienie, ponieważ występuje zależność między pętlami while.

result1 = while (condition, init = init_value) {
  Infeed(shape)
}

result2 = while (condition, init = result1) {
  Infeed(shape)
}

Zagnieżdżone kształty tuple nie są obsługiwane. W przypadku pustej tupla operacja na karcie Infeed jest operacją pustą i nie powoduje odczytu żadnych danych z karty Infeed urządzenia.

Iota

Zobacz też XlaBuilder::Iota.

Iota(shape, iota_dimension)

Tworzy stałą wartość dosłowną na urządzeniu, a nie potencjalnie duży transfer hosta. Tworzy tablicę o określonym kształcie, która zawiera wartości zaczynające się od 0 i wzrost o 1 w wybranym wymiarze. W przypadku typów zmiennoprzecinkowych utworzony tablica jest równoważna ConvertElementType(Iota(...)), gdzie Iota jest typu całkowitego, a konwersja jest typu zmiennoprzecinkowego.

Argumenty Typ Semantyka
shape Shape Kształt tablicy utworzonej przez Iota()
iota_dimension int64 Wymiar, który ma być zwiększany.

Na przykład Iota(s32[4, 8], 0) zwraca

  [[0, 0, 0, 0, 0, 0, 0, 0 ],
   [1, 1, 1, 1, 1, 1, 1, 1 ],
   [2, 2, 2, 2, 2, 2, 2, 2 ],
   [3, 3, 3, 3, 3, 3, 3, 3 ]]

Iota(s32[4, 8], 1) za możliwość zwrotu

  [[0, 1, 2, 3, 4, 5, 6, 7 ],
   [0, 1, 2, 3, 4, 5, 6, 7 ],
   [0, 1, 2, 3, 4, 5, 6, 7 ],
   [0, 1, 2, 3, 4, 5, 6, 7 ]]

Mapa

Zobacz też XlaBuilder::Map.

Map(operands..., computation)

Argumenty Typ Semantyka
operands sekwencja N XlaOp s N tablic typu T0..T{N-1}
computation XlaComputation obliczenia typu T_0, T_1, .., T_{N + M -1} -> S z N parametrami typu T i M o dowolnym typie
dimensions Tablica int64 tablica wymiarów mapy

Stosuje funkcję skalarną do podanych tablic operands, tworząc tablicę o tych samych wymiarach, w której każdy element jest wynikiem zmapowanej funkcji zastosowanej do odpowiednich elementów w tablicach wejściowych.

Funkcja mapowana to dowolne obliczenie z ograniczeniem, że ma N wejść typu skalarnego T i jeden wynik typu S. Wyjście ma te same wymiary co operandy, z tym że typ elementu T jest zastąpiony typem S.

Na przykład: Map(op1, op2, op3, computation, par1) mapuje elem_out <- computation(elem1, elem2, elem3, par1) w każdym (wielowymiarowym) indeksie w tablicach wejściowych, aby utworzyć tablicę wyjściową.

OptimizationBarrier

Blokuje przenoszenie obliczeń przez barierę między przejściami optymalizacyjnymi.

Zapewnia ocenę wszystkich danych wejściowych przed operatorami zależnymi od danych wyjściowych bariery.

Wkładka

Zobacz też XlaBuilder::Pad.

Pad(operand, padding_value, padding_config)

Argumenty Typ Semantyka
operand XlaOp tablica typu T
padding_value XlaOp skalarny typu T, aby wypełnić dodane dopełnienie
padding_config PaddingConfig ilość wypełnień po obu stronach (mała, duża) i między elementami każdego wymiaru;

Rozszerza podany tablicę operand, dodając wypełnienie wokół tablicy oraz między elementami tablicy za pomocą podanego argumentu padding_value. padding_configokreśla ilość wypełnień krawędzi i wypełnień wewnętrznych dla każdego wymiaru.

PaddingConfig to powtarzalne pole obiektu PaddingConfigDimension, który zawiera 3 pola dla każdego wymiaru: edge_padding_low, edge_padding_highinterior_padding.

Parametry edge_padding_lowedge_padding_high określają ilość wypełnień dodawanych na niskich wartościach (obok indeksu 0) i na wysokich wartościach (obok najwyższego indeksu) w każdym wymiarze. Ilość wypełnień krawędzi może być ujemna – bezwzględna wartość ujemnego wypełnienia wskazuje liczbę elementów do usunięcia z wybranego wymiaru.

interior_padding określa ilość dopełnienia między dowolnymi 2 elementami w każdym wymiarze. Wartość nie może być ujemna. Dopełnienie wewnętrzne następuje logicznie przed dopełnieniem krawędzi, więc w przypadku negatywnego dopełnienia krawędzi elementy są usuwane z operandu dopełnionego wewnętrznym.

Ta operacja jest nieaktywna, jeśli wszystkie pary wypełnień krawędzi mają wartość (0, 0), a wartości wypełnień wewnętrznych mają wartość 0. Rysunek poniżej przedstawia przykłady różnych wartości edge_paddinginterior_padding w przypadku tablicy dwuwymiarowej.

Recv

Zobacz też XlaBuilder::Recv.

Recv(shape, channel_handle)

Argumenty Typ Semantyka
shape Shape kształt danych, które mają zostać odebrane
channel_handle ChannelHandle unikalny identyfikator dla każdej pary wysyłania/odbierania;

Pobiera dane o określonym kształcie z instrukcji Send w innym obliczeniu, które korzysta z tego samego nicka kanału. Zwraca XlaOp dla otrzymanych danych.

Interfejs API klienta operacji Recv reprezentuje komunikację synchroniczną. Jednak wewnętrznie instrukcja jest rozkładana na 2 instrukcje HLO (RecvRecvDone), aby umożliwić asynchroniczne przesyłanie danych. Zobacz też HloInstruction::CreateRecvHloInstruction::CreateRecvDone.

Recv(const Shape& shape, int64 channel_id)

Przydziela zasoby wymagane do otrzymywania danych z instrukcji Send z tym samym identyfikatorem channel_id. Zwraca kontekst dla przypisanych zasobów, który jest używany przez instrukcję RecvDone do oczekiwania na zakończenie przenoszenia danych. Kontekst to tupla {bufor odbioru (shape), identyfikator żądania (U32)} i może być używana tylko przez instrukcję RecvDone.

RecvDone(HloInstruction context)

W kontekście utworzonym przez instrukcję Recv czeka na zakończenie przesyłania danych i zwraca otrzymane dane.

Ograniczamy

Zobacz też XlaBuilder::Reduce.

Stosuje funkcję redukcji do jednej lub większej liczby tablic równolegle.

Reduce(operands..., init_values..., computation, dimensions)

Argumenty Typ Semantyka
operands Sekwencja N XlaOp N tablic typu T_0, ..., T_{N-1}.
init_values Sekwencja N XlaOp N skalarów typu T_0, ..., T_{N-1}.
computation XlaComputation obliczenia typu T_0, ..., T_{N-1}, T_0, ..., T_{N-1} -> Collate(T_0, ..., T_{N-1}).
dimensions Tablica int64 Nieuporządkowana tablica wymiarów do zredukowania.

Gdzie:

  • Wartość N musi być większa lub równa 1.
  • Obliczenia muszą być „w przybliżeniu” asocjalne (patrz poniżej).
  • Wszystkie tablice wejściowe muszą mieć te same wymiary.
  • Wszystkie wartości początkowe muszą tworzyć tożsamość w ramach computation.
  • Jeśli N = 1, Collate(T) to T.
  • Jeśli N > 1, Collate(T_0, ..., T_{N-1}) jest tupla elementów N typu T.

Ta operacja redukuje co najmniej 1 wymiar każdej tablicy wejściowej do skalarów. Pozycja każdej zwróconej tablicy to rank(operand) - len(dimensions). Dane wyjściowe operacji to Collate(Q_0, ..., Q_N), gdzie Q_i to tablica typu T_i, których wymiary zostały opisane poniżej.

Inne backendy mogą ponownie powiązać obliczenia redukcji. Może to prowadzić do różnic liczbowych, ponieważ niektóre funkcje redukcji, takie jak dodawanie, nie tworzą powiązania dla liczb zmiennoprzecinkowych. Jeśli jednak zakres danych jest ograniczony, dodawanie zmiennoprzecinkowe jest wystarczająco zbliżone do skojarzonego w większości praktycznych zastosowań.

Przykłady

Gdy redukujesz wymiar w pojedynczej tablicy 1D z wartościami [10, 11, 12, 13], przy użyciu funkcji redukcji f (czyli computation), można to obliczyć jako

f(10, f(11, f(12, f(init_value, 13)))

ale istnieje też wiele innych możliwości, np.

f(init_value, f(f(10, f(init_value, 11)), f(f(init_value, 12), f(init_value, 13))))

Poniżej znajduje się przykładowy pseudokod, który pokazuje, jak można zaimplementować redukcję, używając dodawania jako obliczenia redukcji z wartością początkową 0.

result_shape <- remove all dims in dimensions from operand_shape

# Iterate over all elements in result_shape. The number of r's here is equal
# to the rank of the result
for r0 in range(result_shape[0]), r1 in range(result_shape[1]), ...:
  # Initialize this result element
  result[r0, r1...] <- 0

  # Iterate over all the reduction dimensions
  for d0 in range(dimensions[0]), d1 in range(dimensions[1]), ...:
    # Increment the result element with the value of the operand's element.
    # The index of the operand's element is constructed from all ri's and di's
    # in the right order (by construction ri's and di's together index over the
    # whole operand shape).
    result[r0, r1...] += operand[ri... di]

Oto przykład zmniejszania tablicy dwuwymiarowej (macierzy). Kształt ma pozycję 2, wymiar 0 dla rozmiaru 2 i wymiar 1 rozmiaru 3:

Wyniki zmniejszenia wymiarów 0 lub 1 za pomocą funkcji „add”:

Pamiętaj, że oba wyniki redukcji to tablice jednowymiarowe. Dla wygody wykres przedstawia jeden jako kolumnę, a drugi jako wiersz.

Oto bardziej złożony przykład tablicy 3D. Jego rangę 3, wymiar 0 o rozmiarze 4, wymiar 1 o rozmiarze 2 i wymiar 2 o rozmiarze 3. Dla uproszczenia wartości 1–6 są powielane w wymiarze 0.

Podobnie jak w przypadku obrazu 2D, możemy ograniczyć wymiar tylko o jeden. Jeśli zredukujemy wymiar 0, otrzymamy tablicę o wymiarach 2, w której wszystkie wartości w wymiarze 0 zostały złożone w element skalar:

|  4   8  12 |
| 16  20  24 |

Jeśli zredukujemy wymiar 2, otrzymamy tablicę o wymiarach 2, w której wszystkie wartości w wymiarze 2 zostały złożone w skalar:

| 6  15 |
| 6  15 |
| 6  15 |
| 6  15 |

Pamiętaj, że względna kolejność pozostałych wymiarów na wejściu jest zachowana na wyjściu, ale niektórym wymiarom mogą zostać przypisane nowe numery (ponieważ zmienia się ich pozycja).

Możemy też zmniejszyć liczbę wymiarów. Dodawanie wymiarów 0 i 1 powoduje utworzenie tablicy 1D [20, 28, 36].

Zmniejszenie tablicy 3D we wszystkich jej wymiarach daje wynik skalarny 84.

Variadic Reduce

W przypadku funkcji N > 1 stosowanie funkcji jest nieco bardziej złożone, ponieważ jest stosowane jednocześnie do wszystkich danych wejściowych. Operandy są podawane do obliczeń w tej kolejności:

  • Uruchomiono zredukowaną wartość dla pierwszego operandu
  • Wartość zredukowana dla N-tego operanda
  • Wartość wejściowa pierwszego operandu
  • Wartość wejściowa N-tego operandu

Rozważmy na przykład funkcję redukcji, która może służyć do równoległego obliczania wartości maksymalnej i argmax tablicy jednowymiarowej:

f: (Float, Int, Float, Int) -> Float, Int
f(max, argmax, value, index):
  if value >= max:
    return (value, index)
  else:
    return (max, argmax)

W przypadku tablic wejściowych 1-D V = Float[N], K = Int[N] i wartości inicjowanych I_V = Float, I_K = Int wynik zmniejszania wartości f_(N-1) w przypadku jedynego wymiaru wejściowego jest odpowiednikiem tej aplikacji rekurencyjnej:

f_0 = f(I_V, I_K, V_0, K_0)
f_1 = f(f_0.first, f_0.second, V_1, K_1)
...
f_(N-1) = f(f_(N-2).first, f_(N-2).second, V_(N-1), K_(N-1))

Zastosowanie tego zawężenia do tablicy wartości i tablicy sekwencyjnych indeksów (np. iota) spowoduje współiterację tablic i zwróci tuple zawierającą maksymalną wartość i odpowiadający jej indeks.

ReducePrecision

Zobacz też XlaBuilder::ReducePrecision.

Modeluje efekt konwersji wartości zmiennoprzecinkowych na format o niższej precyzji (np. IEEE-FP16) i z powrotem na format oryginalny. Liczbę bitów wykładnika i mantysy w formacie o niższej dokładności można określić losowo, jednak niektóre rozmiary bitów mogą nie być obsługiwane przez niektóre implementacje sprzętowe.

ReducePrecision(operand, mantissa_bits, exponent_bits)

Argumenty Typ Semantyka
operand XlaOp tablica typu zmiennoprzecinkowego T.
exponent_bits int32 liczba bitów wykładnika w formacie o niższej dokładności
mantissa_bits int32 liczba bitów mantisy w formacie o niższej precyzji

Wynikiem jest tablica typu T. Wartości wejściowe są zaokrąglane do najbliższej wartości, którą można przedstawić za pomocą określonej liczby bitów mantisy (zgodnie z semantyką „związków z parzystymi liczbami”). Wartości, które przekraczają zakres określony przez liczbę bitów wykładnika, są ograniczane do dodatniej lub ujemnej nieskończoności. Wartości NaN są zachowywane, ale mogą być konwertowane na kanoniczne wartości NaN.

Format o niższej dokładności musi mieć co najmniej 1 bit do wykładnika (w celu odróżnienia wartości zerowej od nieskończoności, ponieważ oba mają mantysę o zerowej wartości) i muszą mieć nieujemną liczbę bitów modliszki. Liczba bitów wykładnika lub mantisa może przekraczać odpowiednią wartość w przypadku typu T; odpowiednia część konwersji jest wtedy po prostu pomijana.

ReduceScatter

Zobacz też XlaBuilder::ReduceScatter.

ReduceScatter to operacja zbiorcza, która skutecznie wykonuje AllReduce, a następnie rozprasza wynik, dzieląc go na bloki shard_count wzdłuż scatter_dimension, a replika i w grupie replik otrzymuje fragment ith.

ReduceScatter(operand, computation, scatter_dim, shard_count, replica_group_ids, channel_id)

Argumenty Typ Semantyka
operand XlaOp Tablica lub niepusta krotka tablic do zredukowania w replikach.
computation XlaComputation Obliczanie redukcji
scatter_dimension int64 Wymiar do rozproszenia.
shard_count int64 Liczba bloków do podziału scatter_dimension
replica_groups wektor wektorów int64 Grupy, między którymi wykonywane są redukcje
channel_id opcjonalnie int64 Opcjonalny identyfikator kanału na potrzeby komunikacji między modułami
  • Jeśli operand to tablica tablic, operacja reduce-scatter jest wykonywana na każdym elemencie tablicy.
  • replica_groups to lista grup replik, między którymi wykonywane jest zmniejszanie (identyfikator repliki bieżącej repliki można pobrać za pomocą ReplicaId). Kolejność replik w każdej grupie określa kolejność, w jakiej wynik wszystkich zmniejszeń zostanie rozproszony. replica_groups musi być pusty (w tym przypadku wszystkie repliki należą do jednej grupy) lub zawierać taką samą liczbę elementów jak liczba replik. Jeśli masz więcej niż jedną grupę replik, wszystkie muszą mieć ten sam rozmiar. Na przykład replica_groups = {0, 2}, {1, 3} wykonuje redukcję między replikami 02 oraz 13, a potem rozprasza wynik.
  • shard_count to rozmiar każdej grupy replik. Jest on potrzebny, gdy pole replica_groups jest puste. Jeśli replica_groups nie jest pusty, shard_count musi być równy rozmiarowi każdej grupy replik.
  • Interfejs channel_id jest używany do komunikacji między modułami: ze sobą mogą komunikować się tylko operacje reduce-scatter z tym samym adresem channel_id.

Kształt wyjściowy jest scatter_dimension razy mniejszy od kształtu wejściowego. Jeśli np. są 2 repliki, a operand ma odpowiednio wartości [1.0, 2.25][3.0, 5.25], wartość wyjściowa z tej operacji, w której scatter_dim to 0, będzie wynosić [4.0] w przypadku pierwszej repliki i [7.5] w przypadku drugiej repliki.

ReduceWindow

Zobacz też XlaBuilder::ReduceWindow.

Funkcja ta stosuje funkcję redukcji do wszystkich elementów w każdym oknie sekwencji N wielowymiarowych tablic, zwracając pojedynczą tablicę wielowymiarową lub tuplę N wielowymiarowych tablic. Każda tablica wyjściowa ma taką samą liczbę elementów jak liczba prawidłowych pozycji okna. Warstwę z zbiorem można wyrazić jako ReduceWindow. Podobnie jak w przypadku Reduce, zastosowany computation jest zawsze przekazywany po lewej stronie init_values.

ReduceWindow(operands..., init_values..., computation, window_dimensions, window_strides, padding)

Argumenty Typ Semantyka
operands N XlaOps Sekwencja N wielowymiarowych tablic typu T_0,..., T_{N-1}, z których każda reprezentuje obszar podstawowy, na którym znajduje się okno.
init_values N XlaOps N wartości początkowych funkcji redukcji, po jednej dla każdego z N operandów. Więcej informacji znajdziesz w sekcji Zmniejszanie.
computation XlaComputation Funkcja redukcji typu T_0, ..., T_{N-1}, T_0, ..., T_{N-1} -> Collate(T_0, ..., T_{N-1}), która ma być stosowana do elementów w każdym oknie wszystkich danych wejściowych.
window_dimensions ArraySlice<int64> tablica liczb całkowitych dla wartości wymiaru okna
window_strides ArraySlice<int64> tablica liczb całkowitych dla wartości kroku okna
base_dilations ArraySlice<int64> tablica liczb całkowitych dla wartości rozszerzania podstawy
window_dilations ArraySlice<int64> tablica liczb całkowitych dla wartości rozszerzenia okna
padding Padding typ wypełnienia dla okna (Padding::kSame, który wypełnia w taki sposób, aby uzyskać taki sam kształt wyjściowy jak wejście, jeśli krok wynosi 1, lub Padding::kValid, który nie używa wypełnienia i „zatrzymuje” okno, gdy już się nie mieści).

Gdzie:

  • Wartość N musi być większa od lub równa 1.
  • Wszystkie tablice wejściowe muszą mieć te same wymiary.
  • Jeśli N = 1, Collate(T) to T.
  • Jeśli N > 1, Collate(T_0, ..., T_{N-1}) jest tupla elementów N typu (T0,...T{N-1}).

Poniżej znajduje się kod i rysunek pokazujący przykład użycia funkcji ReduceWindow. Dane wejściowe to tablica o wymiarach [4 x 6], a obie zmienne window_dimensions i window_stride_dimensions mają wymiary [2 x 3].

// Create a computation for the reduction (maximum).
XlaComputation max;
{
  XlaBuilder builder(client_, "max");
  auto y = builder.Parameter(0, ShapeUtil::MakeShape(F32, {}), "y");
  auto x = builder.Parameter(1, ShapeUtil::MakeShape(F32, {}), "x");
  builder.Max(y, x);
  max = builder.Build().value();
}

// Create a ReduceWindow computation with the max reduction computation.
XlaBuilder builder(client_, "reduce_window_2x3");
auto shape = ShapeUtil::MakeShape(F32, {4, 6});
auto input = builder.Parameter(0, shape, "input");
builder.ReduceWindow(
    input,
    /*init_val=*/builder.ConstantLiteral(LiteralUtil::MinValue(F32)),
    *max,
    /*window_dimensions=*/{2, 3},
    /*window_stride_dimensions=*/{2, 3},
    Padding::kValid);

Krok 1 w wymiarze określa, że pozycja okna w wymiarze jest oddalona o 1 element od sąsiedniego okna. Aby określić, że żadne okna się nie nakładają, parametr window_stride_dimensions powinien być równy parametrowi window_dimensions. Rysunek poniżej pokazuje użycie 2 różnych wartości kroku. Dodanie wypełnień jest stosowane do każdego wymiaru danych wejściowych, a obliczenia są takie same, jak gdyby dane wejściowe miały wymiary po dodaniu wypełnień.

W przypadku nieprostego dopełnienia rozważ obliczenie minimalnego okna (wartość początkowa to MAX_FLOAT) z wymiarem 3 i krokiem 2 na tablicy wejściowej [10000, 1000, 100, 10, 1]. Funkcja Padding kValid oblicza minimum z 2 ważnych okien: [10000, 1000, 100][100, 10, 1], co daje wynik [100, 1]. Dopełnienie kSame powoduje dopełnienie tablicy w taki sposób, aby kształt po ograniczeniu okna był taki sam jak dane wejściowe pierwszego kroku. W tym celu dodaj elementy początkowe po obu stronach, otrzymując [MAX_VALUE, 10000, 1000, 100, 10, 1, MAX_VALUE]. Wykonanie funkcji reduce-window na wypełnionym tablicy działa na 3 oknach: [MAX_VALUE, 10000, 1000], [1000, 100, 10], [10, 1, MAX_VALUE] i zwraca wartość [1000, 10, 1].

Kolejność obliczania funkcji redukcji jest dowolna i może być niedeterministyczna. Dlatego funkcja redukcji nie powinna być zbyt wrażliwa na usunięcie powiązania. Aby dowiedzieć się więcej, zapoznaj się z dyskusją na temat asocjacyjności w kontekście Reduce.

ReplicaId

Zobacz też XlaBuilder::ReplicaId.

Zwraca unikalny identyfikator (skalarna U32) repliki.

ReplicaId()

Unikalny identyfikator każdej repliki jest nieoznaczoną liczbą całkowitą z przedziału [0, N), gdzie N to liczba replik. Ponieważ wszystkie repliki korzystają z tego samego programu, wywołanie ReplicaId() w programie zwróci inną wartość w każdej replice.

Kształtowanie

Zapoznaj się też z tymi dokumentami dotyczącymi usługi : XlaBuilder::ReshapeCollapse.

Zmienia wymiary tablicy w nową konfigurację.

Reshape(operand, new_sizes) Reshape(operand, dimensions, new_sizes)

Argumenty Typ Semantyka
operand XlaOp tablica typu T
dimensions int64 wektor kolejność zwinięć wymiarów
new_sizes int64 wektor wektor rozmiarów nowych wymiarów

Zmiana kształtu polega najpierw na spłaszczeniu tablicy do jednowymiarowego wektora wartości danych, a potem na dopracowaniu tego wektora do nowego kształtu. Argumenty wejściowe to dowolny tablica typu T, wektor wymiarów będący stałą w czasie kompilacji oraz wektor wymiarów będący stałą w czasie kompilacji. Wartości wektora dimension (jeśli zostanie podany) muszą być permutacją wszystkich wymiarów T; domyślnie jest to {0, ..., rank - 1}. Kolejność wymiarów w funkcji dimensions jest od wymiaru o najwolniejszej zmienności (najważniejszego) do wymiaru o najszybszej zmienności (najmniej ważnego) w gnieździe pętli, które łączy tablicę wejściową w pojedynczy wymiar. Wektor new_sizes określa rozmiar tablicy wyjściowej. Wartość w indeksie 0 w tablicy new_sizes to rozmiar wymiaru 0, wartość w indeksie 1 to rozmiar wymiaru 1 itd. Iloczyn wymiarów new_size musi być równy iloczynowi rozmiarów wymiarów operandu. Gdy poszerzasz zwinięty tablicowy obiekt danych o wielowymiarową tablicę zdefiniowaną przez funkcję new_sizes, wymiary w tym tablicy są uporządkowane od najmniej zmiennego (najbardziej głównego) do najbardziej zmiennego (najmniej głównego).

Na przykład niech v będzie tablicą złożoną z 24 elementów:

let v = f32[4x2x3] { { {10, 11, 12}, {15, 16, 17} },
                    { {20, 21, 22}, {25, 26, 27} },
                    { {30, 31, 32}, {35, 36, 37} },
                    { {40, 41, 42}, {45, 46, 47} } };

In-order collapse:
let v012_24 = Reshape(v, {0,1,2}, {24});
then v012_24 == f32[24] {10, 11, 12, 15, 16, 17, 20, 21, 22, 25, 26, 27,
                         30, 31, 32, 35, 36, 37, 40, 41, 42, 45, 46, 47};

let v012_83 = Reshape(v, {0,1,2}, {8,3});
then v012_83 == f32[8x3] { {10, 11, 12}, {15, 16, 17},
                          {20, 21, 22}, {25, 26, 27},
                          {30, 31, 32}, {35, 36, 37},
                          {40, 41, 42}, {45, 46, 47} };

Out-of-order collapse:
let v021_24 = Reshape(v, {1,2,0}, {24});
then v012_24 == f32[24]  {10, 20, 30, 40, 11, 21, 31, 41, 12, 22, 32, 42,
                          15, 25, 35, 45, 16, 26, 36, 46, 17, 27, 37, 47};

let v021_83 = Reshape(v, {1,2,0}, {8,3});
then v021_83 == f32[8x3] { {10, 20, 30}, {40, 11, 21},
                          {31, 41, 12}, {22, 32, 42},
                          {15, 25, 35}, {45, 16, 26},
                          {36, 46, 17}, {27, 37, 47} };


let v021_262 = Reshape(v, {1,2,0}, {2,6,2});
then v021_262 == f32[2x6x2] { { {10, 20}, {30, 40},
                              {11, 21}, {31, 41},
                              {12, 22}, {32, 42} },
                             { {15, 25}, {35, 45},
                              {16, 26}, {36, 46},
                              {17, 27}, {37, 47} } };

W szczególnym przypadku funkcja reshape może przekształcić tablicę jednoelementową w skalar i odwrotnie. Na przykład

Reshape(f32[1x1] { {5} }, {0,1}, {}) == 5;
Reshape(5, {}, {1,1}) == f32[1x1] { {5} };

Przych. (odwrotne)

Zobacz też XlaBuilder::Rev.

Rev(operand, dimensions)

Argumenty Typ Semantyka
operand XlaOp tablica typu T
dimensions ArraySlice<int64> wymiary do odwrócenia

Odwraca kolejność elementów w tablicy operand wzdłuż określonej osi dimensions, generując tablicę wyjściową o tej samej strukturze. Każdy element tablicy operand w indeksie wielowymiarowym jest zapisywany w tablicy wyjściowej w indeksie przekształconym. Indeks wielowymiarowy jest przekształcany przez odwrócenie indeksu w każdym wymiarze, który ma zostać odwrócony (czyli jeśli wymiar o rozmiarze N jest jednym z wymiarów odwracanych, jego indeks i jest przekształcany w N – 1 – i).

Operacja Rev może służyć do odwracania tablicy wag konwekcji wzdłuż 2 wymiarów okna podczas obliczania gradientu w sieciach neuronowych.

RngNormal

Zobacz też XlaBuilder::RngNormal.

Tworzy dane wyjściowe o danym kształcie za pomocą liczb losowych wygenerowanych zgodnie z  \(N(\mu, \sigma)\) rozkładem normalnym. Parametry \(\mu\) i \(\sigma\)oraz kształt wyjściowy muszą mieć typ elementu zmiennoprzecinkowego. Parametry muszą mieć wartość skalarną.

RngNormal(mu, sigma, shape)

Argumenty Typ Semantyka
mu XlaOp Typ T skalarny określający średnią wygenerowanych liczb
sigma XlaOp Skalarar typu T określający odchylenie standardowe wygenerowanej wartości
shape Shape Dane wyjściowe w postaci kształtu T

RngUniform

Zobacz też XlaBuilder::RngUniform.

Tworzy dane wyjściowe o danym kształcie z losowymi liczbami generowanymi zgodnie z rozkładem jednorodzonym na przedziałach \([a,b)\). Parametry i typ wyjściowy muszą być typu logicznego, całkowitego lub zmiennoprzecinkowego. Typy muszą być spójne. Backendy CPU i GPU obsługują obecnie tylko F64, F32, F16, BF16, S64, U64, S32 i U32. Ponadto parametry muszą mieć wartości skalarne. Jeśli \(b <= a\) wynik jest zdefiniowany przez implementację.

RngUniform(a, b, shape)

Argumenty Typ Semantyka
a XlaOp Element typu T określający dolny limit przedziału
b XlaOp Element typu T określający górny limit interwału
shape Shape Dane wyjściowe w postaci kształtu T

RngBitGenerator

Generuje dane wyjściowe o danym kształcie wypełnionym jednolitymi losowymi bitami przy użyciu określonego algorytmu (lub domyślnego ustawienia backendu) i zwraca zaktualizowany stan (z takim samym kształtem co stan początkowy) i wygenerowane dane losowe.

Stan początkowy to stan początkowy bieżącego generowania liczb losowych. Jego kształt i wymagany format oraz prawidłowe wartości zależą od użytego algorytmu.

Wyjście jest z założenia funkcją deterministyczną stanu początkowego, ale nie jest deterministyczne między backendami i różnymi wersjami kompilatorów.

RngBitGenerator(algorithm, key, shape)

Argumenty Typ Semantyka
algorithm RandomAlgorithm Algorytm PRNG.
initial_state XlaOp Stan początkowy algorytmu PRNG.
shape Shape Kształt wyjściowy wygenerowanych danych.

Dostępne wartości dla parametru algorithm:

Punktowy

Operacja rozproszenia XLA generuje sekwencję wyników, które są wartościami tablicy wejściowej operands, z kilkoma wycinkami (w indeksach określonych przez scatter_indices) zaktualizowanymi o sekwencję wartości z tabeli updates przy użyciu update_computation.

Zobacz też XlaBuilder::Scatter.

scatter(operands..., scatter_indices, updates..., update_computation, index_vector_dim, update_window_dims, inserted_window_dims, scatter_dims_to_operand_dims)

Argumenty Typ Semantyka
operands Kolejność N XlaOp N tablic typu T_0, ..., T_N, do których mają być rozproszone dane.
scatter_indices XlaOp Tablica zawierająca początkowe indeksy przedziałów, do których należy wykonać rozproszenie.
updates Sekwencja N XlaOp N tablic typów T_0, ..., T_N. updates[i] zawiera wartości, których należy używać do rozpraszania operands[i].
update_computation XlaComputation Obliczenie służące do łączenia dotychczasowych wartości w tablicy wejściowej i aktualizacji podczas rozpraszania. Obliczenie tego typu powinno być typu T_0, ..., T_N, T_0, ..., T_N -> Collate(T_0, ..., T_N).
index_vector_dim int64 Wymiar w elementach scatter_indices, który zawiera indeksy początkowe.
update_window_dims ArraySlice<int64> Zbiór wymiarów w formie updates, które są wymiarami okna.
inserted_window_dims ArraySlice<int64> Zestaw wymiarów okna, które należy wstawić do kształtu updates.
scatter_dims_to_operand_dims ArraySlice<int64> Mapowanie wymiarów z indeksów rozproszonych na przestrzeń indeksu operandu. Ta tablica jest interpretowana jako mapowanie i na scatter_dims_to_operand_dims[i]. Musi być jeden do jednego i obejmuje wszystkich.
indices_are_sorted bool Określa, czy indeksy są sortowane przez wywołującego.
unique_indices bool Czy indeksy mają gwarantować, że element wywołujący jest unikalny.

Gdzie:

  • Wartość N musi być większa od lub równa 1.
  • operands[0], ..., operands[N-1] muszą mieć te same wymiary.
  • updates[0], ..., updates[N-1] muszą mieć te same wymiary.
  • Jeśli N = 1, Collate(T) to T.
  • Jeśli N > 1, Collate(T_0, ..., T_N) jest krotką elementów N typu T.

Jeśli index_vector_dim równa się scatter_indices.rank, domyślnie uznajemy, że scatter_indices ma wymiar 1 na końcu.

Definiujemy update_scatter_dims typu ArraySlice<int64> jako zbiór wymiarów w kształcie updates, które nie znajdują się w formacie update_window_dims, w kolejności rosnącej.

Argumenty funkcji rozrzutu powinny być zgodne z tymi ograniczeniami:

  • Każda tablica updates musi mieć rangę update_window_dims.size + scatter_indices.rank - 1.

  • Ograniczenia wymiaru i w każdej tablicy updates muszą spełniać te wymagania:

    • Jeśli i występuje w update_window_dims (tj. równa się update_window_dims[k] dla niektórych k), to granica wymiaru i w updates nie może przekraczać odpowiadającej mu granicy operand po uwzględnieniu inserted_window_dims (tzn. adjusted_window_bounds[k], gdzie adjusted_window_bounds zawiera granice wymiaru operand z usuniętymi granicami w indeksach inserted_window_dims).
    • Jeśli i występuje w update_scatter_dims (tj. równa się update_scatter_dims[k] dla niektórych k), to granica wymiaru i w updates musi być równa odpowiadającej mu wartości granicznej scatter_indices z pominięciem index_vector_dim (np. scatter_indices.shape.dims[k], jeśli k < index_vector_dim, scatter_indices.shape.dims[k+1] w innym przypadku).
  • update_window_dims musi być uporządkowana rosnąco, nie może zawierać powtarzających się numerów wymiarów i musi mieścić się w zakresie [0, updates.rank).

  • Kolumna inserted_window_dims musi być posortowana rosnąco, nie może zawierać powtarzających się numerów wymiarów i musi należeć do zakresu [0, operand.rank).

  • Wartość parametru operand.rank musi być równa sumie parametrów update_window_dims.size i inserted_window_dims.size.

  • scatter_dims_to_operand_dims.size musi być równa scatter_indices.shape.dims[index_vector_dim], a jego wartości muszą się mieścić w zakresie [0, operand.rank).

Dla danego indeksu U w każdej tablicy updates odpowiedni indeks I w odpowiedniej tablicy operands, do której należy zastosować tę zmianę, jest obliczany w ten sposób:

  1. Niech G = { U[k] dla funkcji k w update_scatter_dims. Użyj funkcji G, aby wyszukać wektor indeksu S w tablicy scatter_indices, taki jak S[i] = scatter_indices[Połącz(G, i)], gdzie Połącz(A, b) umieszcza w pozycji index_vector_dim w miejscu index_vector_dim.
  2. Utwórz indeks Sin w obszarze operand za pomocą funkcji S, rozkładając S na mapie scatter_dims_to_operand_dims. Bardziej formalnie:
    1. Sin[scatter_dims_to_operand_dims[k]] = S[k], jeśli k < scatter_dims_to_operand_dims.size.
    2. Sin[_] = 0 w innym przypadku.
  3. Utwórz indeks Win w każdej tablicy operands, rozpraszając indeksy update_window_dims w tablicy U zgodnie z wartością inserted_window_dims. Bardziej oficjalnie:
    1. Win[window_dims_to_operand_dims(k)] = U[k], jeśli k znajduje się w update_window_dims, gdzie window_dims_to_operand_dims to funkcja monograficzna z domeną [0, update_window_dims.size) i zakresem [0, operand.rank) \ inserted_window_dims. (Jeśli na przykład update_window_dims.size to 4, operand.rank to 6, a inserted_window_dims to {0, 2}, to window_dims_to_operand_dims to {01, 13, 24, 35}).
    2. Win[_] = 0 w innych przypadkach.
  4. I to Win + Sin, gdzie + oznacza dodawanie element po elemencie.

Operację rozproszenia można podsumować w ten sposób:

  • Inicjalizacja outputoperands, czyli dla wszystkich indeksów J, dla wszystkich indeksów O w tablicy operands[J]:
    output[J][O] = operands[J][O]
  • W przypadku każdego indeksu U w tablicy updates[J] i odpowiadającego mu indeksu O w tablicy operand[J], jeśli O jest prawidłowym indeksem dla output:
    (output[0][O], ..., output[N-1][O]) =update_computation(output[0][O], ..., ,output[N-1][O],updates[0][U], ...,updates[N-1][U])

Kolejność, w jakiej są one stosowane, nie jest określona. Dlatego, gdy wiele indeksów w updates odwołuje się do tego samego indeksu w operands, odpowiadająca mu wartość w output będzie niedeterministyczna.

Pamiętaj, że pierwszy parametr przekazywany do funkcji update_computation będzie zawsze bieżącą wartością z tablicy output, a drugi parametr będzie zawsze wartością z tablicy updates. Jest to ważne zwłaszcza w przypadku, gdy update_computation nie jest przemienna.

Jeśli parametr indices_are_sorted ma wartość Prawda, XLA może założyć, że elementy scatter_indices są posortowane (w kolejności rosnącej, po z rozproszeniem wartości zgodnie z scatter_dims_to_operand_dims) przez użytkownika. Jeśli nie, semantyka jest zdefiniowana przez implementację.

Jeśli parametr unique_indices ma wartość Prawda, XLA może założyć, że wszystkie elementy są unikalne. XLA może więc używać operacji nieatomowych. Jeśli parametr unique_indices ma wartość Prawda, a indeksy, do których jest wykonywane rozproszenie, nie są unikalne, semantyka jest zdefiniowana przez implementację.

Eksperyment punktowy można postrzegać nieformalnie jako odwrotność operacji zbierania, tzn. zmiana ta aktualizuje elementy w danych wejściowych, które są wyodrębniane przez odpowiednie opcje zbierania.

Szczegółowe nieformalne omówienie i przykłady znajdziesz w sekcji „Nieformalny opis” w sekcji Gather.

Wybierz

Zobacz też XlaBuilder::Select.

Tworzy tablicę wyjściową z elementów 2 tablic wejściowych na podstawie wartości tablicy z predykatem.

Select(pred, on_true, on_false)

Argumenty Typ Semantyka
pred XlaOp tablica typu PRED
on_true XlaOp tablica typu T
on_false XlaOp tablica typu T

Tablice on_true i on_false muszą mieć taki sam kształt. Jest to też kształt tablicy wyjściowej. Tablica pred musi mieć taką samą wielowymiarowość jak tablice on_true i on_false oraz typ elementu PRED.

W przypadku każdego elementu P z tablicy pred odpowiedni element tablicy wyjściowej jest pobierany z tablicy on_true, jeśli wartość atrybutu P to true, i z tablicy on_false, jeśli wartość atrybutu P to false. Jako ograniczona forma transmisji pred może być wartością skalarną typu PRED. W tym przypadku tablica wyjściowa jest pobierana w całości z on_true, jeśli pred ma wartość true, a od on_false, jeśli pred to false.

Przykład z wartością nieskalarną pred:

let pred: PRED[4] = {true, false, false, true};
let v1: s32[4] = {1, 2, 3, 4};
let v2: s32[4] = {100, 200, 300, 400};
==>
Select(pred, v1, v2) = s32[4]{1, 200, 300, 4};

Przykład z elementem skalarnym pred:

let pred: PRED = true;
let v1: s32[4] = {1, 2, 3, 4};
let v2: s32[4] = {100, 200, 300, 400};
==>
Select(pred, v1, v2) = s32[4]{1, 2, 3, 4};

Obsługiwane są zapytania dotyczące kolumn. W tym celu tuple są traktowane jako typy skalarne. Jeśli on_true i on_false są krotkami (które muszą mieć taki sam kształt), pred musi być skalarem typu PRED.

SelectAndScatter

Zobacz też XlaBuilder::SelectAndScatter.

Tę operację można uznać za operację złożoną, w której najpierw oblicza wartość ReduceWindow na tablicy operand, aby wybrać element z każdego okna, a następnie rozkłada tablicę source na indeksy wybranych elementów, tworząc tablicę wyjściową o takim samym kształcie jak tablica argumentów. Funkcja binarna select służy do wybierania elementu z każdego okna przez zastosowanie go w każdym oknie. Jest ona wywoływana z tą właściwością, zgodnie z którą wektor indeksu pierwszego parametru jest leksykograficznie mniejszy od wektora indeksu drugiego parametru. Funkcja select zwraca wartość true, jeśli wybrany jest pierwszy parametr, oraz false, jeśli wybrany jest drugi parametr. Funkcja musi być przechodnia (czyli jeśli select(a, b)select(b, c) mają wartość true, to select(a, c) też ma wartość true), aby wybrany element nie zależał od kolejności elementów przemierzanych w danym oknie.

Funkcja scatter jest stosowana w przypadku każdego wybranego indeksu w tablicy wyjściowej. Przyjmuje 2 parametry skalarne:

  1. Bieżąca wartość w wybranym indeksie w tablicy wyjściowej
  2. Wartość punktowa z pola source, która ma zastosowanie do wybranego indeksu

Łączy te 2 parametry i zwraca wartość skalarną, która służy do aktualizowania wartości w wybranym indeksie tablicy wyjściowej. Początkowo wszystkie indeksy tablicy wyjściowej są ustawione na init_value.

Tablica wyjściowa ma ten sam kształt co tablica operand, a tablica source musi mieć ten sam kształt co wynik zastosowania operacji ReduceWindow do tablicy operand. SelectAndScatter można użyć do propagacji wstecznej wartości gradientu dla warstwy zbiorczego przetwarzania w sieci neuronowej.

SelectAndScatter(operand, select, window_dimensions, window_strides, padding, source, init_value, scatter)

Argumenty Typ Semantyka
operand XlaOp tablica typu T, po której przesuwają się okna
select XlaComputation obliczenia binarne typu T, T -> PRED, które mają zostać zastosowane do wszystkich elementów w każdym oknie. Zwraca true, jeśli wybrano pierwszy parametr, i zwraca false, jeśli wybrano drugi parametr.
window_dimensions ArraySlice<int64> tablica liczb całkowitych dla wartości wymiarów okna
window_strides ArraySlice<int64> tablica liczb całkowitych dla wartości kroku okna
padding Padding typ wypełnienia okna (Padding::kSame lub Padding::kValid)
source XlaOp tablica typu T z wartościami do rozproszenia
init_value XlaOp wartość skalarna typu T dla wartości początkowej tablicy wyjściowej
scatter XlaComputation obliczenia binarne typu T, T -> T, aby zastosować każdy element źródłowy rozrzutu z elementem docelowym

Rysunek poniżej przedstawia przykłady użycia funkcji SelectAndScatter, w której funkcja select oblicza maksymalną wartość spośród swoich parametrów. Pamiętaj, że gdy okna się nakładają, jak na rysunku (2) poniżej, indeks tablicy operand może być wybierany kilka razy przez różne okna. Na ilustracji zarówno górne okna (niebieskie, jak i czerwone), a funkcja dodawania binarnego scatter zwraca element wyjściowy o wartości 8 (2 + 6).

Kolejność obliczania funkcji scatter jest dowolna i może być niedeterministyczna. Dlatego funkcja scatter nie powinna być zbyt wrażliwa na ponowne powiązanie. Aby dowiedzieć się więcej, zapoznaj się z dyskusją na temat asocjacyjności w kontekście Reduce.

Wyślij

Zobacz też XlaBuilder::Send.

Send(operand, channel_handle)

Argumenty Typ Semantyka
operand XlaOp dane do wysłania (tabelka typu T)
channel_handle ChannelHandle unikalny identyfikator dla każdej pary wysyłania/odbierania;

Przesyła dane podanego operandu do instrukcji Recv w innej operacji, która korzysta z tego samego identyfikatora kanału. Nie zwraca żadnych danych.

Podobnie jak operacja Recv, interfejs API klienta operacji Send reprezentuje komunikację asynchroniczną i jest wewnętrznie rozkładany na 2 instrukcje HLO (SendSendDone), aby umożliwić asynchroniczne przesyłanie danych. Zobacz też HloInstruction::CreateSend i HloInstruction::CreateSendDone.

Send(HloInstruction operand, int64 channel_id)

Inicjuje asynchroniczny transfer operandu do zasobów przydzielonych przez instrukcję Recv z tym samym identyfikatorem kanału. Zwraca kontekst, który jest używany przez instrukcję SendDone do oczekiwania na zakończenie transferu danych. Kontekst to krotka {operand (kształt), identyfikator żądania (U32)} i może być używany tylko w instrukcji SendDone.

SendDone(HloInstruction context)

Biorąc pod uwagę kontekst utworzony przez instrukcję Send, czeka na zakończenie przesyłania danych. Instrukcja nie zwraca żadnych danych.

Planowanie instrukcji dotyczących kanału

Kolejność wykonywania 4 instrukcji dla każdego kanału (Recv, RecvDone, Send, SendDone) jest następująca:

  • Recv następuje przed Send
  • Send następuje przed RecvDone
  • Recv ma miejsce przed RecvDone
  • Send ma miejsce przed SendDone

Gdy kompilatory backendu generują harmonogram liniowy dla każdego obliczenia, które komunikuje się za pomocą instrukcji kanału, obliczenia nie mogą zawierać cykli. Na przykład harmonogramy poniżej powodują blokady.

Wycinek

Zobacz też XlaBuilder::Slice.

Slice wyodrębnia podtablicę z tablicy wejściowej. Podtablica ma ten sam stopień, co tablica wejściowa, i zawiera wartości w ramce ograniczającej w tablicy wejściowej, gdzie wymiary i indeksy ramki ograniczającej są podawane jako argumenty operacji wycinania.

Slice(operand, start_indices, limit_indices, strides)

Argumenty Typ Semantyka
operand XlaOp N-wymiarowa tablica typu T
start_indices ArraySlice<int64> Lista N liczb całkowitych zawierających indeksy początkowe przekroju dla każdego wymiaru. Wartości muszą być równe zeru lub większe.
limit_indices ArraySlice<int64> Lista N liczb całkowitych zawierających indeksy końcowe (wyłącznie) dla wycinka każdego wymiaru. Każda wartość musi być większa lub równa odpowiedniej wartości start_indices wymiaru i mniejsza lub równa rozmiarowi wymiaru.
strides ArraySlice<int64> Lista N liczb całkowitych, która określa interwał wejściowy przekroju. Wycinka wybiera wszystkie elementy strides[d] w wymiarze d.

Przykład jednowymiarowy:

let a = {0.0, 1.0, 2.0, 3.0, 4.0}
Slice(a, {2}, {4}) produces:
  {2.0, 3.0}

Przykład dwuwymiarowy:

let b =
 { {0.0,  1.0,  2.0},
   {3.0,  4.0,  5.0},
   {6.0,  7.0,  8.0},
   {9.0, 10.0, 11.0} }

Slice(b, {2, 1}, {4, 3}) produces:
  { { 7.0,  8.0},
    {10.0, 11.0} }

Sortuj

Zobacz też XlaBuilder::Sort.

Sort(operands, comparator, dimension, is_stable)

Argumenty Typ Semantyka
operands ArraySlice<XlaOp> Operandy do posortowania.
comparator XlaComputation Obliczanie, które ma zostać użyte.
dimension int64 Wymiar, według którego chcesz sortować dane.
is_stable bool Określa, czy należy użyć stabilnego sortowania.

Jeśli podano tylko 1 operand:

  • Jeśli operand jest tensorem 1-wymiarowym (tablicą), wynik jest uporządkowaną tablicą. Jeśli chcesz posortować tablicę w kolejności rosnącej, porównywacz powinien wykonać porównanie mniejsze niż. Formalnie po posortowaniu tablicy zachowuje ona wszystkie pozycje indeksu i, j z wartością i < j, dla których jest to comparator(value[i], value[j]) = comparator(value[j], value[i]) = false lub comparator(value[i], value[j]) = true.

  • Jeśli operand ma wyższą pozycję w rankingu, jest posortowany według podanego wymiaru. Na przykład w przypadku tensora rangi 2 (macierzy) wartość wymiaru 0 posortuje niezależnie każdą kolumnę, a wartość wymiaru 1 – niezależnie od tego, co zostanie posortowane. Jeśli nie podasz numeru wymiaru, domyślnie zostanie wybrany ostatni wymiar. W przypadku posortowanych wymiarów obowiązuje ta sama kolejność sortowania, jak w przypadku wymiaru 1.

Jeśli podano operandy n > 1:

  • Wszystkie operandy n muszą być tensorami o tych samych wymiarach. Typy elementów tensorów mogą być różne.

  • Wszystkie operandy są sortowane razem, a nie pojedynczo. Pojęcie operandów jest traktowane jako krotka. Podczas sprawdzania, czy trzeba zamienić elementy każdego operandu na pozycjach indeksu i i j, komparator jest wywoływany za pomocą parametrów skalarnych 2 * n, gdzie parametr 2 * k odpowiada wartości na pozycji i z operandu k-th, a parametr 2 * k + 1 – wartości w pozycji j z operandu k-th. Zwykle porównywarka porównuje parametry 2 * k2 * k + 1 ze sobą oraz ewentualnie używa innych par parametrów jako pary rozstrzygającej.

  • Wynikiem jest krotka, która składa się z operandów w porządku posortowanym (w podanym wymiarze, jak powyżej). Operand i-th w tuplu odpowiada operandowi i-th w funkcji Sort.

Jeśli np. istnieją 3 operandy operand0 = [3, 1], operand1 = [42, 50], operand2 = [-3.0, 1.1], a pośrednik porównuje tylko wartości operand0 z operatorem „mniejsze niż”, wyjściem sortowania jest tupla ([1, 3], [50, 42], [1.1, -3.0]).

Jeśli parametr is_stable ma wartość „true”, sortowanie jest stabilne, co oznacza, że jeśli są elementy, które są uważane za równe przez porównywacz, względna kolejność tych wartości jest zachowana. Dwa elementy e1e2 są równe wtedy i tylko wtedy, gdy comparator(e1, e2) = comparator(e2, e1) = false. Domyślnie is_stable ma wartość false.

Transponuj

Zobacz też operację tf.reshape.

Transpose(operand)

Argumenty Typ Semantyka
operand XlaOp operand do transponowania.
permutation ArraySlice<int64> Jak zmieniać kolejność wymiarów.

Przestawia wymiary operandów zgodnie z daną permutacją, czyli∀ i . 0 ≤ i < rank ⇒ input_dimensions[permutation[i]] = output_dimensions[i].

Jest to to samo co Reshape(operand, permutation, Permute(permutation, operand.shape.dimensions)).

TriangularSolve

Zobacz też XlaBuilder::TriangularSolve.

Rozwiązuje układy równań liniowych z macierzą współczynników o dolnej lub górnej trójkątnej za pomocą bezpośredniego lub odwrotnego podstawiania. Ta procedura rozwiązuje jeden z systemów równań macierzowych op(a) * x = b lub x * op(a) = b dla zmiennej x, pod warunkiem że ab, gdzie op(a) to op(a) = a, op(a) = Transpose(a) lub op(a) = Conj(Transpose(a)).

TriangularSolve(a, b, left_side, lower, unit_diagonal, transpose_a)

Argumenty Typ Semantyka
a XlaOp a rank > 2 tablica typu złożonego lub zmiennoprzecinkowego o kształcie [..., M, M].
b XlaOp a rank > 2 tablice tego samego typu o postaci [..., M, K], jeśli left_side ma wartość prawda, a w przeciwnym razie [..., K, M].
left_side bool wskazuje, czy należy rozwiązać system o postaci op(a) * x = b (true) czy x * op(a) = b (false).
lower bool czy należy użyć górnego, czy dolnego trójkąta w a.
unit_diagonal bool Jeśli true, przyjmuje się, że elementy diagonalne w elementach a mają wartość 1 i nie są dostępne.
transpose_a Transpose czy użyć a w niezmienionej postaci, czy przetransponować go lub wziąć jego sprzężenie sprzężone.

Dane wejściowe są odczytywane tylko z dolnego/górnego trójkąta a, w zależności od wartości lower. Wartości z drugiego trójkąta są ignorowane. Dane wyjściowe są zwracane w tym samym trójkącie; wartości w drugim trójkącie są zdefiniowane przez implementację i mogą być dowolne.

Jeśli ranking a i b jest większy niż 2, są one traktowane jako partie macierzy, gdzie wszystkie poza wymiarami podrzędnymi 2 są wymiarami wsadowymi. a i b muszą mieć jednakowe wymiary wsadu.

Kropka

Zobacz też XlaBuilder::Tuple.

Tuple zawierający zmienną liczbę uchwytów danych, z których każdy ma swój kształt.

Jest to odpowiednik std::tuple w C++. Ogólnie rzecz biorąc:

let v: f32[10] = f32[10]{0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
let s: s32 = 5;
let t: (f32[10], s32) = tuple(v, s);

Tupli można używać (dostęp do nich) za pomocą operacji GetTupleElement.

Podczas

Zobacz też XlaBuilder::While.

While(condition, body, init)

Argumenty Typ Semantyka
condition XlaComputation XlaComputation typu T -> PRED, która określa warunek zakończenia pętli.
body XlaComputation XlaComputation typu T -> T, który określa treść pętli.
init T Wartość początkowa parametru conditionbody.

Sekwencyjnie wykonuje body, dopóki condition nie zakończy się niepowodzeniem. Jest to podobne do typowej pętli „podczas gdy” w wielu innych językach, z wyjątkiem różnic i ograniczeń wymienionych poniżej.

  • Węzeł While zwraca wartość typu T, która jest wynikiem ostatniego wykonania żądania body.
  • Kształt typu T jest statyczny i musi być taki sam we wszystkich iteracjach.

Parametry T obliczeń są inicjowane wartością init w pierwszej iteracji i automatycznie aktualizowane do nowego wyniku z funkcji body w każdej kolejnej iteracji.

Jednym z głównych zastosowań węzła While jest implementacja wielokrotnego wykonywania treningu w sieciach neuronowych. Poniżej przedstawiono uproszczony pseudokod z wykresem, który przedstawia obliczenia. Kod znajdziesz w while_test.cc. Typ T w tym przykładzie to Tuple, który składa się z int32 dla liczby powtórzeń i vector[10] dla zasobnika. Przez 1000 iteracji pętla stale dodaje wektor stały do akumulatora.

// Pseudocode for the computation.
init = {0, zero_vector[10]} // Tuple of int32 and float[10].
result = init;
while (result(0) < 1000) {
  iteration = result(0) + 1;
  new_vector = result(1) + constant_vector[10];
  result = {iteration, new_vector};
}