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ą funkcjiReplicaId
). Kolejność replik w każdej grupie określa kolejność, w jakiej ich dane wejściowe znajdują się w wyniku.replica_groups
musi być pusty (w tym przypadku wszystkie repliki należą do jednej grupy, uporządkowanej od0
doN - 1
) lub zawierać taką samą liczbę elementów jak liczba replik. Na przykładreplica_groups = {0, 2}, {1, 3}
wykonuje konkatenację replik0
i2
oraz1
i3
.shard_count
to rozmiar każdej grupy replik. Potrzebujemy tego w przypadku pustych wartościreplica_groups
.channel_id
jest używany do komunikacji między modułami: tylko operacjeall-gather
z tym samymchannel_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ładreplica_groups = {0, 2}, {1, 3}
wykonuje redukcję między replikami0
i2
oraz1
i3
.- Interfejs
channel_id
jest używany do komunikacji między modułami: ze sobą mogą komunikować się tylko operacjeall-reduce
z tym samym elementemchannel_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]
i [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:
- 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. - 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ą parametruReplicaId
). Operacja AllToAll zostanie zastosowana w podgrupach w określonej kolejności. Na przykładreplica_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ślireplica_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 przezsplit_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::BatchNormGrad
i pierwotnym 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 mean
i variance
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::BatchNormTraining
i the 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 m
elementów o wymiarach przestrzennych w
i h
(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_mean
i batch_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::Collapse
i tf.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 przestrzennen
, 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
: wymiarz
danych wyjściowych.input-z
: rozmiar tego wymiaru pomnożony przezfeature_group_count
powinien być równy rozmiarowiz
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_dilation
i rhs_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 przezbatch_group_count
powinien być równy rozmiarowi wymiarubatch
po lewej stronie.z
: ten sam rozmiar cooutput-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 lhs
i rhs
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 lhs
i rhs
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), ShiftRightLogical
Atan2
Complex
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:
Jeśli w polu
batch_dims
występuje parametri
(tzn. w przypadku niektórychk
ma ono wartość równabatch_dims[k]
), wybieramy odpowiednie granice wymiaru z wymiarustart_indices.shape
, pomijającindex_vector_dim
(czyli wybieramystart_indices.shape.dims
[k
], jeślik
<index_vector_dim
, a w przeciwnym razie:start_indices.shape.dims
[k
+1
]).Jeśli w polu
offset_dims
występuje elementi
(tzn. równa wartościoffset_dims
[k
] w przypadku niektórych danych typuk
), po uwzględnieniucollapsed_slice_dims
wybieramy odpowiednią granicę zslice_sizes
(tzn. wybieramyadjusted_slice_sizes
[k
], gdzieadjusted_slice_sizes
jestslice_sizes
z usuniętymi granicami indeksówcollapsed_slice_dims
).
Formalnie indeks operanda In
odpowiadający danemu indeksowi wyjściowemu Out
jest obliczany w ten sposób:
Niech
G
= {Out
[k
] dla funkcjik
wbatch_dims
. Użyj funkcjiG
, by wyciąć wektorS
w taki sposób, abyS
[i
] =start_indices
[Połącz(G
,i
)], gdzie Połącz(A; b) wstawia b w pozycjiindex_vector_dim
w A. Pamiętaj, że ten parametr jest dobrze zdefiniowany nawet wtedy, gdy poleG
jest puste. Jeśli poleG
jest puste, wtedyS
=start_indices
.Utwórz indeks początkowy
S
in
w obszarzeoperand
za pomocą funkcjiS
, rozkładającS
na elementstart_index_map
. Więcej szczegółów:S
in
[start_index_map
[k
]] =S
[k
] ifk
<start_index_map.size
.S
in
[_
] =0
w innych przypadkach.
Utwórz indeks
O
in
w tabelioperand
, rozpraszając indeksy w wymiarach offsetowych w tabeliOut
zgodnie z zbioremcollapsed_slice_dims
. Więcej szczegółów:O
in
[remapped_offset_dims
(k
)] =Out
[offset_dims
[k
]] jeślik
<offset_dims.size
(remapped_offset_dims
jest zdefiniowany poniżej).O
in
[_
] =0
w innym przypadku.
In
toO
in
+S
in
, 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 {0
→1
,
1
→3
, 2
→4
, 3
→5
}.
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 elementustart_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 woperand
.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ściowemuOut
.
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
,O
0
,O
1
], 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
,O
0
,O
1
] jest wtedy elementem w tablicy wejściowej o indeksie [X
+O
0
,Y
+O
1
].
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 G
0
i G
1
jako wymiary zbiorczego. Rozmiar wycinka to nadal [8,6]
.
Operacja zbierania w XLA upraszcza nieformalną semantykę w następujący sposób:
Możemy skonfigurować, które wymiary w kształcie wyjściowym mają być przesuniętymi wymiarami (wymiary zawierające
O
0
lubO
1
w ostatnim przykładzie). Wymiary wyjściowej partii danych (w ostatnim przykładzieG
0
,G
1
) są zdefiniowane jako wymiary wyjściowe, które nie są wymiarami przesunięcia.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ówny1
. Ponieważ mają wycinek o rozmiarze1
, jedynym prawidłowym indeksem dla nich jest0
, a jego usunięcie nie wprowadza niejasności.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
:
G
0
i G
1
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 O
0
. 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
,O
0
], co daje w sumie [X
,O
0
]. Innymi słowy, indeks wyjściowy [G
0
,G
1
,O
0
] jest mapowany na indeks wejściowy [GatherIndices
[G
0
,G
1
,0
],O
0
], 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_config
okreś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_high
i interior_padding
.
Parametry edge_padding_low
i edge_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_padding
i interior_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 (Recv
i RecvDone
), aby umożliwić asynchroniczne przesyłanie danych. Zobacz też HloInstruction::CreateRecv
i HloInstruction::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)
toT
. - Jeśli
N > 1
,Collate(T_0, ..., T_{N-1})
jest tupla elementówN
typuT
.
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ładreplica_groups = {0, 2}, {1, 3}
wykonuje redukcję między replikami0
i2
oraz1
i3
, a potem rozprasza wynik.shard_count
to rozmiar każdej grupy replik. Jest on potrzebny, gdy polereplica_groups
jest puste. Jeślireplica_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 operacjereduce-scatter
z tym samym adresemchannel_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]
i [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)
toT
. - Jeśli
N > 1
,Collate(T_0, ..., T_{N-1})
jest tupla elementówN
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]
i [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::Reshape
i Collapse
.
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
:
rng_default
: algorytm specyficzny dla backendu z wymaganiami dotyczącymi kształtu.rng_three_fry
: algorytm PRNG oparty na liczniku ThreeFry. Kształtinitial_state
jestu64[2]
z dowolnymi wartościami. Salmon i in., SC 2011. Równoległe liczby losowe to proste – jak 1, 2, 3.rng_philox
: algorytm Philox do równoległego generowania liczb losowych. Kształtinitial_state
tou64[3]
z dowolnymi wartościami. Salmon i in. SC 2011. Losowe liczby równoległe: to bardzo proste
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)
toT
. - Jeśli
N > 1
,Collate(T_0, ..., T_N)
jest krotką elementówN
typuT
.
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 tablicyupdates
muszą spełniać te wymagania:- Jeśli
i
występuje wupdate_window_dims
(tj. równa sięupdate_window_dims
[k
] dla niektórychk
), to granica wymiarui
wupdates
nie może przekraczać odpowiadającej mu granicyoperand
po uwzględnieniuinserted_window_dims
(tzn.adjusted_window_bounds
[k
], gdzieadjusted_window_bounds
zawiera granice wymiaruoperand
z usuniętymi granicami w indeksachinserted_window_dims
). - Jeśli
i
występuje wupdate_scatter_dims
(tj. równa sięupdate_scatter_dims
[k
] dla niektórychk
), to granica wymiarui
wupdates
musi być równa odpowiadającej mu wartości granicznejscatter_indices
z pominięciemindex_vector_dim
(np.scatter_indices.shape.dims
[k
], jeślik
<index_vector_dim
,scatter_indices.shape.dims
[k+1
] w innym przypadku).
- Jeśli
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ówupdate_window_dims.size
iinserted_window_dims.size
.scatter_dims_to_operand_dims.size
musi być równascatter_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:
- Niech
G
= {U
[k
] dla funkcjik
wupdate_scatter_dims
. Użyj funkcjiG
, aby wyszukać wektor indeksuS
w tablicyscatter_indices
, taki jakS
[i
] =scatter_indices
[Połącz(G
,i
)], gdzie Połącz(A, b) umieszcza w pozycjiindex_vector_dim
w miejscuindex_vector_dim
. - Utwórz indeks
S
in
w obszarzeoperand
za pomocą funkcjiS
, rozkładającS
na mapiescatter_dims_to_operand_dims
. Bardziej formalnie:S
in
[scatter_dims_to_operand_dims
[k
]] =S
[k
], jeślik
<scatter_dims_to_operand_dims.size
.S
in
[_
] =0
w innym przypadku.
- Utwórz indeks
W
in
w każdej tablicyoperands
, rozpraszając indeksyupdate_window_dims
w tablicyU
zgodnie z wartościąinserted_window_dims
. Bardziej oficjalnie:W
in
[window_dims_to_operand_dims
(k
)] =U
[k
], jeślik
znajduje się wupdate_window_dims
, gdziewindow_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ładupdate_window_dims.size
to4
,operand.rank
to6
, ainserted_window_dims
to {0
,2
}, towindow_dims_to_operand_dims
to {0
→1
,1
→3
,2
→4
,3
→5
}).W
in
[_
] =0
w innych przypadkach.
I
toW
in
+S
in
, gdzie + oznacza dodawanie element po elemencie.
Operację rozproszenia można podsumować w ten sposób:
- Inicjalizacja
output
zoperands
, czyli dla wszystkich indeksówJ
, dla wszystkich indeksówO
w tablicyoperands
[J
]:output
[J
][O
] =operands
[J
][O
] - W przypadku każdego indeksu
U
w tablicyupdates
[J
] i odpowiadającego mu indeksuO
w tablicyoperand
[J
], jeśliO
jest prawidłowym indeksem dlaoutput
:
(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)
i 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:
- Bieżąca wartość w wybranym indeksie w tablicy wyjściowej
- 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 (Send
i SendDone
), 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 przedSend
Send
następuje przedRecvDone
Recv
ma miejsce przedRecvDone
Send
ma miejsce przedSendDone
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 tocomparator(value[i], value[j]) = comparator(value[j], value[i]) = false
lubcomparator(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ść wymiaru1
– 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
ij
, komparator jest wywoływany za pomocą parametrów skalarnych2 * n
, gdzie parametr2 * k
odpowiada wartości na pozycjii
z operanduk-th
, a parametr2 * k + 1
– wartości w pozycjij
z operanduk-th
. Zwykle porównywarka porównuje parametry2 * k
i2 * 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 operandowii-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 e1
i e2
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 a
i b
, 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 condition i body . |
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ść typuT
, która jest wynikiem ostatniego wykonania żądaniabody
. - 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};
}