StableHLO, makinedeki üst düzey işlemler (HLO) için kullanılan bir işlemdir. öğrenme (ML) modelleridir. StableHLO, farklı öğeler ile videolar arasında taşınabilirlik katmanı görevi görür. Makine öğrenimi çerçeveleri ve makine öğrenimi derleyicileri: StableHLO programları üreten makine öğrenimi çerçeveleri StableHLO programlarını kullanan makine öğrenimi derleyicileriyle uyumludur.
Hedefimiz makine öğrenimi geliştirmeyi basitleştirmek ve hızlandırmak Farklı makine öğrenimi çerçeveleri (ör. TensorFlow, JAX ve PyTorch) ve makine öğrenimi derleyicileri (XLA ve IREE gibi). Bu hedefe doğru belgesinde StableHLO programlama dili için bir spesifikasyon sunulmaktadır.
Bu spesifikasyon üç ana bölüm içermektedir. İlk olarak, Programlar bölümünde StableHLO programlarının yapısı açıklanmaktadır. Bunlar, StableHLO işlemlerinden oluşan StableHLO işlevlerinden oluşur. Bu yapıdaki Ops bölümü ayrı ayrı bağlıdır. Yürütme bölümü, bu işlemlerin bir program içinde birlikte yürütülmesini sağlamaktır. Son olarak, Notasyon bölümünde, bakın.
StableHLO'nun önceki bir sürümünün teknik özelliklerini görüntülemek için şurada depoyu açın: etiketli yayın ekleyin. Örneğin, StableHLO v0.19.0 Spec. StableHLO'nun her alt sürüm yükseltmesinde gerçekleşen değişiklikleri görüntülemek için şuraya bakın: VhloDialect.td adresindeki sürüm günlüğü.
Programlar
Program ::= {Func}
StableHLO programları isteğe bağlı sayıda StableHLO işlevinden oluşur.
Aşağıda, 3 girişe sahip @main
fonksiyonuna sahip örnek bir program verilmiştir.
(%image
, %weights
ve %bias
) ve 1 çıkış. İşlevin gövdesi
6 operasyonu var.
func.func @main(
%image: tensor<28x28xf32>,
%weights: tensor<784x10xf32>,
%bias: tensor<1x10xf32>
) -> tensor<1x10xf32> {
%0 = "stablehlo.reshape"(%image) : (tensor<28x28xf32>) -> tensor<1x784xf32>
%1 = "stablehlo.dot"(%0, %weights) : (tensor<1x784xf32>, tensor<784x10xf32>) -> tensor<1x10xf32>
%2 = "stablehlo.add"(%1, %bias) : (tensor<1x10xf32>, tensor<1x10xf32>) -> tensor<1x10xf32>
%3 = "stablehlo.constant"() {value = dense<0.0> : tensor<1x10xf32>} : () -> tensor<1x10xf32>
%4 = "stablehlo.maximum"(%2, %3) : (tensor<1x10xf32>, tensor<1x10xf32>) -> tensor<1x10xf32>
"func.return"(%4): (tensor<1x10xf32>) -> ()
}
İşlevler
Func ::= 'func' '.' 'func' FuncId FuncInputs FuncOutputs '{' FuncBody '}'
FuncInputs ::= '(' [FuncInput {',' FuncInput}] `)`
FuncInput ::= ValueId ':' ValueType
FuncOutputs ::= ['->' FuncOutput, {',' FuncOutput}]
FuncOutput ::= ValueType
FuncBody ::= {Op}
StableHLO işlevleri (adlandırılmış işlevler olarak da adlandırılır) bir tanımlayıcı, girişler/çıkışlar ve bir gövde. Gelecekte, Daha iyi uyumluluk sağlamak amacıyla işlevler için ek meta veriler sunmak HLO ile (#425, 626, #740, #744) girin.
Tanımlayıcılar
FuncId ::= '@' letter {letter | digit}
ValueId ::= '%' digit {digit}
| '%' letter {letter | digit}
letter ::= 'a' | ... | 'z' | 'A' | ... | 'Z' | '_'
digit ::= '0' | ... | '9'
StableHLO tanımlayıcıları çoğu programlamada tanımlayıcılara benzer iki özelliği vardır: 1) tüm tanımlayıcıların birlikte Farklı tanımlayıcı türlerini ayırt etme, 2) değer tanımlayıcıları StableHLO programlarının oluşturulmasını basitleştirmek için tamamen sayısal değerler.
Türler
Type ::= ValueType | NonValueType
ValueType ::= TensorType | QuantizedTensorType | TokenType | TupleType
NonValueType ::= TensorElementType | QuantizedTensorElementType | FunctionType | StringType
StableHLO türleri, değer türleri (diğer adıyla birinci sınıf türleri) içeren, StableHLO değerlerini ve değer olmayan türleri temsil eder. bir şablon görevi görür. StableHLO türleri, ana özelliği StableHLO'nun alana özgü bir yapıya sahip olup bu durum bazı olağan dışı sonuçlara (ör. skaler türler) yol açar değildir).
TensorType ::= 'tensor' '<' Shape TensorElementType '>'
Shape ::= {DimensionSize 'x'}
DimensionSize ::= digit {digit} | '?'
Tensör türleri, tensörleri, yani çok boyutlu dizileri temsil eder. Bir
şekil ve öğe türü (burada şekil, negatif olmayan veya
bilinmeyen boyut boyutları,
0
ile R-1
arasında numaralandırılan boyutlar (bunlar eksen olarak da adlandırılır). İlgili içeriği oluşturmak için kullanılan
R
boyut sayısına sıralama denir. Örneğin, tensor<2x3xf32>
2x3
şekline ve f32
öğe türüne sahip bir tensör türü. İki boyutu vardır.
(veya başka bir deyişle, iki eksen) - 0. boyut ve 1. boyut; diğer bir deyişle
2 ve 3'tür. Sıralaması 2.
Şekiller kısmen veya tamamen bilinmez (dinamik) olabilir, ör. tensor<?x2xf64>
.
kısmen bilinmiyor ve tensor<?x?xf64>
tamamen bilinmiyor. Dinamik
boyut boyutları ?
kullanılarak gösterilir. Şekillerin sıralaması geri alınamaz.
Gelecekte, Google Analytics 4'teki tensör türlerini boyutları ve öğe türlerini (örneğin, yerleşimleri dahil etmek için) (#629) ve yetersizlik (#1078).
QuantizedTensorType ::= 'tensor' '<' Shape QuantizedTensorElementType '>'
QuantizedTensorElementType ::= '!quant.uniform' '<'
QuantizationStorageType
['<' QuantizationStorageMin ':' QuantizationStorageMax '>']
':' QuantizationExpressedType
[':' QuantizationDimension]
',' QuantizationParameters '>'
QuantizationStorageType ::= IntegerType
QuantizationStorageMin ::= IntegerConstant
QuantizationStorageMax ::= IntegerConstant
QuantizationExpressedType ::= FloatType
QuantizationDimension ::= IntegerConstant
QuantizationParameters ::= QuantizationParameter
| '{' QuantizationParameter {',' QuantizationParameter} '}'
QuantizationParameter ::= QuantizationScale ':' QuantizationZeroPoint
QuantizationScale ::= FloatConstant
QuantizationZeroPoint ::= IntegerConstant
Ad | Tür | Sınırlamalar |
---|---|---|
storage_type |
tam sayı türü | (C1-C3), (C8) |
storage_min |
tam sayı sabiti | (C1), (C3), (C7) |
storage_max |
tam sayı sabiti | (C2), (C3), (C7) |
expressed_type |
kayan nokta türü | (C4) |
quantization_dimension |
isteğe bağlı tam sayı sabiti | (C10-C12) |
scales |
değişken kayan nokta sabitlerinin sayısı | (C4-C6), (C9), (C10), (C13) |
zero_points |
tam sayı sabitlerinin değişken sayısı | (C7-C9) |
Nitelikli öğe türleri, depolama türünün tam sayı değerlerini
şuna karşılık gelen storage_min
- storage_max
(dahil) aralığı
ifade edilmiş bir türün kayan nokta değerleri. Belirli bir tam sayı değeri i
için
karşılık gelen kayan nokta değeri f
şu şekilde hesaplanabilir:
f = (i - zero_point) * scale
, burada scale
ve zero_point
olarak adlandırılır
nicelleştirme parametreleri. storage_min
ve storage_max
isteğe bağlıdır
dilbilgisinde mevcut ancak varsayılan değerleri min_value(storage_type)
ve
Sırasıyla max_value(storage_type)
. Nicelleştirilmiş öğe türleri
aşağıdaki sınırlamalara tabidir:
- (C1)
type(storage_min) = storage_type
. - (C2)
type(storage_max) = storage_type
. - (C3)
min_value(storage_type) <= storage_min < storage_max <= max_value(storage_type)
. - (C4)
type(scales...) = expressed_type
- (C5)
0 < scales
- (C6)
is_finite(scales...)
. - (C7)
storage_min <= zero_points <= storage_max
. - (C8)
type(zero_points...) = storage_type
- (C9)
size(scales) = size(zero_points)
. - (C10)
is_empty(quantization_dimension)
isesize(scales) = 1
. - (C11)
0 <= quantization_dimension
Şu anda QuantizationScale
bir kayan nokta sabitidir, ancak
çarpanları ve değerleri ile temsil edilen tamsayı tabanlı ölçeklere güçlü ilgi
olur. Bu konuyu yakın gelecekte araştırmayı planlıyoruz
(#1404).
QuantizationZeroPoint
kelimesinin anlamı konusunda devam eden bir tartışma var.
ve yalnızca bir veya daha fazla
nicelleştirilmiş bir tensör türünde potansiyel olarak birden çok sıfır noktasıdır. Referans olarak
Bu tartışmanın sonuçlarına göre, sıfır puan civarındaki spesifikasyonlar değişebilir.
ileride bahsedeceğim (#1405).
Devam eden bir diğer tartışma da QuantizationStorageMin
anlamıyla ilgili.
ve kısıtlanması gerekip gerekmediğini belirlemek için QuantizationStorageMax
bu değerlere ve nicelenmiş tensörlerin değerlerine
(#1406).
Son olarak, bilinmeyen ölçekleri ve sıfır ölçeğini temsil ederek hesaplamayı planlıyoruz. araştırmalarımızda olduğu gibi, bilinmeyen noktaları temsil etmeyi planladığımız gibi boyut boyutlarını (#1407) tıklayın.
Nicelleştirilmiş tensör türleri, miktarlandırılmış öğelere sahip tensörleri temsil eder. Bu tensörler, elemanları dışında normal tensörlerle tamamen aynıdır. yerine miktarlandırılmış öğe türlerine sahip olmalıdır.
Miktarlandırılmış tensörlerde miktar tansör başına olabilir. Diğer bir deyişle,
tensörün tamamı için bir scale
ve zero_point
olabilir veya eksen başına olabilir.
yani, birden fazla scales
ve zero_points
(her bir öğe dilimi başına bir çift)
belirli bir quantization_dimension
boyutunu seçin. Daha resmi olarak, bir tensörde t
eksen başına nicelemeyle, dim(t, quantization_dimension)
dilim
quantization_dimension
tarihindekiler: t[:, ..., 0, ..., :], t[:, ..., 1, ..., :]
,
vb. i
. dilimdeki tüm öğeler, scales[i]
ve zero_points[i]
öğelerini
ve niceleme parametrelerinden biridir. Nicel tensör türleri aşağıdaki gibidir
sınırlamalar:
- Tensör başına miktar belirleme için:
- Ek kısıtlama yok.
- Eksen başına nicelik için:
- (C12)
quantization_dimension < rank(self)
- (C13)
dim(self, quantization_dimension) = size(scales)
- (C12)
TokenType ::= 'token'
Jeton türleri jetonları, yani üretilen ve tüketilen opak değerleri temsil eder. neden olur. Jetonlar, işlemlere yürütme sırası uygulamak için kullanılır Yürütme bölümünde gösterildiği gibi.
TupleType ::= 'tuple' '<' TupleElementTypes '>'
TupleElementTypes ::= [ValueType {',' ValueType}]
Tuple türleri, grupları (heterojen listeler) temsil eder. Tuples bir miradır
Bu özellik yalnızca HLO ile uyumluluk için kullanılabilir. HLO'da, delikler
giriş ve çıkışları temsil etmek için kullanılır. StableHLO'da değişken girdiler ve
çıkışlar yerel olarak desteklenir ve StableHLO'da tuple'ların tek kullanımı
HLO ABI'ı (ör. T
, tuple<T>
ve
tuple<tuple<T>>
, belirli bir kullanım alanına bağlı olarak önemli ölçüde farklılık gösterebilir.
hakkında bilgi edindiniz. Gelecekte HLO ABI'de değişiklikler yapmayı planlıyoruz.
Bu işlem, StableHLO'dan öğe türlerini kaldırmamıza olanak tanır.
(#598).
TensorElementType ::= BooleanType | IntegerType | FloatType | ComplexType
BooleanType ::= 'i1'
IntegerType ::= SignedIntegerType | UnsignedIntegerType
SignedIntegerType ::= 'si2' | 'si4' | 'si8' | 'si16' | 'si32' | 'si64'
UnsignedIntegerType ::= 'ui2' | 'ui4' | 'ui8' | 'ui16' | 'ui32' | 'ui64'
FloatType ::= 'f8E4M3FN' | 'f8E5M2' | 'f8E4M3FNUZ' | 'f8E5M2FNUZ'
| 'f8E4M3B11FNUZ' | 'bf16' | 'f16' | 'f32' | 'f64'
TensorFloat32 ::= 'tf32'
ComplexType ::= 'complex' '<' ComplexElementType '>'
ComplexElementType ::= 'f32' | 'f64'
Öğe türleri, tensör türlerinin öğelerini temsil eder. Birçok programın aksine
bu türler StableHLO'da birinci sınıf değildir. Bunun anlamı,
StableHLO programları bu tür değerleri doğrudan temsil edemez (sonuç olarak
0 boyutlu tensörle T
türünde skaler değerleri göstermek deyimseldir
(tensor<T>
türündeki değerler) seçin.
- Boole türü,
true
vefalse
Boole değerlerini temsil eder. - Tam sayı türleri, imzalı (
si
) veya imzasız (ui
) olabilir ve desteklenen bit genişliklerinden biri (2
,4
,8
,16
,32
veya64
). İmzalısiN
türleri,-2^(N-1)
ile2^(N-1)-1
arasındaki tam sayı değerlerini temsil eder dahil ve imzasızuiN
türleri,0
-0
arasındaki tam sayı değerlerini temsil eder2^N-1
dahil. - Kayan nokta türleri aşağıdakilerden biri olabilir:
f8E4M3FN
vef8E5M2
sırasıyla FP8 biçimininE4M3
veE5M2
kodlamaları: Derin Öğrenme için FP8 Biçimleri.E4M3
veE5M2
özelliklerine karşılık gelenf8E4M3FNUZ
vef8E5M2FNUZ
türleri şu sayfada açıklandığı üzere FP8 biçimlerinin kodlamaları: Derin Sinir Ağları için 8 Bit Sayısal Biçimler.- FP8 biçimlerinin
E4M3
kodlamasına karşılık gelenf8E4M3B11FNUZ
türü şurada açıklandığı: Derin Sinir Ağları için Karma 8 Bit Kayan Nokta (HFP8) Eğitimi ve Çıkarım. - Şu sayfada açıklanan
bfloat16
biçimine karşılık gelenbf16
türü: Bfloat16: Cloud TPU'larda yüksek performansın sırrı - Sırasıyla
f16
,f32
vef64
türleribinary16
("yarı hassasiyet"),binary32
("tek hassasiyet") vebinary64
("çift hassasiyet") biçimleri aşağıda açıklanmıştır: IEEE 754 standardı. tf32
türü, TensorKaydırma32 biçimine karşılık gelir ve StableHLO'da sınırlı destek sunulur.
- Karmaşık türler, gerçek bir bölümü olan karmaşık değerleri temsil eder
ve aynı öğe türünün sanal bir kısmını içerir. Desteklenen kompleks
türler,
complex<f32>
(her iki bölüm def32
türündedir) vecomplex<f64>
şeklindedir (her iki bölüm def64
türündedir).
FunctionType ::= '(' InputTypes ')' '->' '(' OutputTypes ')'
InputTypes ::= [ValueType {',' ValueType}]
OutputTypes ::= [ValueType {',' ValueType}]
İşlev türleri, hem adlandırılmış hem de anonim işlevleri temsil eder. Bunlar
giriş türleri (->
öğesinin sol tarafındaki türler listesi) ve çıkış türleri
(->
öğesinin sağındaki türler listesi). Birçok programlamada
dil, işlev türleri birinci sınıftır ancak StableHLO'da yoktur.
StringType ::= 'string'
Dize türü, bayt dizilerini temsil eder. Birçok programın aksine dize türü StableHLO'da birinci sınıf değildir ve yalnızca program öğeleri için statik meta verileri belirtir.
İşlemler
StableHLO işlemleri (operasyon olarak da adlandırılır) kapalı bir kümeyi temsil eder üst düzey operasyonlar. Yukarıda açıklandığı gibi, StableHLO söz dizimi, büyük ölçüde MLIR’den esinlenilerek geliştirilmiştir. Ancak bu, ergonomik bir alternatif ancak muhtemelen StableHLO'nun makine öğrenimi çerçeveleri ile makine öğrenimi derleyicileri arasında daha fazla birlikte çalışabilirlik sağlar.
Op ::= [OpOutputs] OpName OpInputs ':' OpSignature
OpName ::= '"' 'stablehlo' '.' OpMnemonic '"'
OpMnemonic ::= 'abs' | 'add' | ...
StableHLO işlemlerinin (işlem olarak da adlandırılır) bir adı vardır.
giriş/çıkış ve bir imzadır. Ad, stablehlo.
ön ekinden ve
Desteklenen işlemlerden birini benzersiz şekilde tanımlayan bir hatırlatıcı. Aşağıdaki bilgilere göz atın
desteklenen tüm operasyonların kapsamlı bir listesini içerir.
OpInputs ::= OpInputValues OpInputFuncs OpInputAttrs
OpInputValues ::= '(' [OpInputValue {',' OpInputValue}] ')'
OpInputValue ::= ValueId
OpInputFuncs ::= ['(' OpInputFunc {',' OpInputFunc} ')']
OpInputAttrs ::= ['{' OpInputAttr {',' OpInputAttr} '}']
OpOutputs ::= [OpOutput {',' OpOutput} '=']
OpOutput ::= ValueId
İşlemler girişleri tüketir ve çıkışlar üretir. Girişler şu kategorilere ayrılır:
giriş değerleri (yürütme sırasında hesaplanır), giriş işlevleri (sağlanan
statiktir, çünkü StableHLO'da işlevler birinci sınıf değerler değildir) ve
giriş özellikleri (statik olarak da sağlanır). Giriş ve çıkış türü
işlem gücüne bağlıdır. Örneğin, add
op, 2 giriş değeri tüketir ve 1 çıkış değeri üretir. Buna kıyasla,
select_and_scatter
işlemi 3 giriş değeri, 2 giriş işlevi tüketir ve
3 giriş özelliği.
OpInputFunc ::= '{' Unused FuncInputs ':' FuncBody '}'
Unused ::= '^' digit {digit}
| '^' letter {letter | digit}
Giriş işlevleri (anonim işlevler olarak da adlandırılır)
Adlandırılmış işlevlere benzerdir. Tek fark: 1) bir tanımlayıcıları yoktur (dolayısıyla
"anonim" olması gerekir, 2) çıkış türlerini bildirmezler (çıktı türleri
işlevin içindeki return
işleminden türetilir).
Giriş işlevlerinin söz dizimi, kullanılmayan bir bölümü içeriyor (bkz.
Unused
üretimi) gerekir. MLIR'de,
"bölgeler" daha genel bir kavramdır birden fazla "engelleme" olabilen
atlama operasyonlarıyla birbirine bağlanmış operasyonlar. Bu blokların, ilgili bloklara karşılık gelen
birbirlerinden ayırt edilebilmeleri için Unused
üretime atanır.
StableHLO'da atlama işlemleri yoktur. Bu nedenle, MLIR söz diziminin karşılık gelen kısmı
(ancak hâlâ oradadır).
OpInputAttr ::= OpInputAttrName '=' OpInputAttrValue
OpInputAttrName ::= letter {letter | digit}
OpInputAttrValue ::= Constant
Giriş özelliklerinin bir adı ve desteklenen bir değeri vardır
sabitler. Bunlar, program için statik meta verileri belirtmenin birincil yoludur
öğeler. Örneğin, concatenate
operasyonu şunun için dimension
özelliğini kullanır:
giriş değerlerinin birleştirileceği boyutu belirtin. Aynı şekilde,
slice
işlemi, start_indices
ve limit_indices
gibi birden çok özellik kullanıyor.
ifadesini girin.
Şu anda, doğadaki StableHLO programları bazen Bunlar bu dokümanda açıklanmamıştır. Gelecekte, ya bu özellikleri StableHLO işletim sistemine alır veya bunları StableHLO programlarında görünüyor. Bu arada sırada bu müzakerelerin özellikler:
layout
(#629).mhlo.frontend_attributes
. (#628).mhlo.sharding
(#619).output_operand_aliases
. (#740).- Konum meta verileri (#594).
OpSignature ::= '(' [ValueType {',' ValueType}] ')' '->' '(' [ValueType {',' ValueType}] ')'
İşlem imzası, tüm giriş değeri türlerinden (
->
işaretinin sol tarafındaki) ve tüm çıkış değerlerinin türlerini (liste,
türleri ->
öğesinin sağ tarafında gösterilir). Özetle, giriş türleri
ve çıkış türleri de neredeyse her zaman gereksizdir (çünkü
en fazla StableHLO işlemi için, çıkış türleri girişlerden çıkarılabilir. Yine de operasyon
imza, kasıtlı olarak MLIR ile uyumluluk için StableHLO söz diziminin bir parçasıdır.
Aşağıda, anımsatıcı select_and_scatter
olan bir örnek işlem verilmiştir. 3 veri tüketir
giriş değerleri (%operand
, %source
ve %init_value
), 2 giriş işlevi
ve 3 giriş özelliği (window_dimensions
, window_strides
ve padding
).
Operatörün imzasının yalnızca giriş değeri türlerini içerdiğini unutmayın
(satır içi sağlanan giriş işlevlerinin ve özniteliklerinin türleri değil).
%result = "stablehlo.select_and_scatter"(%operand, %source, %init_value) ({
^bb0(%arg0: tensor<i32>, %arg1: tensor<i32>):
%0 = "stablehlo.compare"(%arg0, %arg1) {
comparison_direction = #stablehlo<comparison_direction GE>
} : (tensor<i32>, tensor<i32>) -> tensor<i1>
"stablehlo.return"(%0) : (tensor<i1>) -> ()
}, {
^bb0(%arg0: tensor<i32>, %arg1: tensor<i32>):
%0 = "stablehlo.add"(%arg0, %arg1) : (tensor<i32>, tensor<i32>) -> tensor<i32>
"stablehlo.return"(%0) : (tensor<i32>) -> ()
}) {
window_dimensions = dense<[3, 1]> : tensor<2xi64>,
window_strides = dense<[2, 1]> : tensor<2xi64>,
padding = dense<[[0, 1], [0, 0]]> : tensor<2x2xi64>
} : (tensor<4x2xi32>, tensor<2x2xi32>, tensor<i32>) -> tensor<4x2xi32>
Sabitler
Constant ::= BooleanConstant
| IntegerConstant
| FloatConstant
| ComplexConstant
| TensorConstant
| QuantizedTensorConstant
| StringConstant
| EnumConstant
StableHLO sabitleri bir değişmez değere ve birlikte şu değeri temsil eden bir türe sahiptir:
StableHLO değerine sahip. Genellikle, tür sabit söz diziminin bir parçasıdır,
belirsiz olduğunda (ör. bir boole sabiti açık bir şekilde i1
türündeyse,
Buna karşın, tam sayı sabitinin birden fazla olası türü olabilir).
BooleanConstant ::= BooleanLiteral
BooleanLiteral ::= 'true' | 'false'
Boole sabitleri, true
ve false
boole değerlerini temsil eder. Boole
sabitler i1
türündedir.
IntegerConstant ::= IntegerLiteral ':' IntegerType
IntegerLiteral ::= ['-' | '+'] DecimalDigits
| ['-' | '+'] '0x' HexadecimalDigits
DecimalDigits ::= decimalDigit {decimalDigit}
HexadecimalDigits ::= hexadecimalDigit {hexadecimalDigit}
decimalDigit ::= '0' | ... | '9'
hexadecimalDigit ::= decimalDigit | 'a' | ... | 'f' | 'A' | ... | 'F'
Tam sayı sabitleri, ondalık veya onaltılık gösterim. Diğer tabanlar, ör. ikili veya sekizlik desteklenmez. Tam sayı sabitlerinin kısıtlamaları aşağıdaki gibidir:
- (C1)
is_wellformed(integer_literal, integer_type)
.
FloatConstant ::= FloatLiteral ':' FloatType
FloatLiteral ::= SignPart IntegerPart FractionalPart ScientificPart
| '0x' [HexadecimalDigits]
SignPart ::= ['-' | '+']
IntegerPart ::= DecimalDigits
FractionalPart ::= ['.' [DecimalDigits]]
ScientificPart ::= [('e' | 'E') ['-' | '+'] DecimalDigits]
Kayan nokta sabitleri, kayan nokta değerlerini Ondalık veya bilimsel gösterim kullanabilirsiniz. Buna ek olarak, onaltılı gösterim temel bitleri kayan nokta biçiminde doğrudan belirtmek için kullanılır seçin. Kayan nokta sabitleri aşağıdaki kısıtlamalara sahiptir:
- (C1) Onaltılı olmayan gösterim kullanılırsa
is_wellformed(float_literal, float_type)
- (C2) Onaltılı gösterim kullanılırsa
size(hexadecimal_digits) = num_bits(float_type) / 4
ComplexConstant ::= ComplexLiteral ':' ComplexType
ComplexLiteral ::= '(' RealPart ',' ImaginaryPart ')'
RealPart ::= FloatLiteral
ImaginaryPart ::= FloatLiteral
Karmaşık sabitler, gerçek bölümün listelerini kullanarak karmaşık değerleri temsil eder
(önce gelir) ve hayali bir bölüm (ikinci sırada gelir) yer alır. Örneğin,
(1.0, 0.0) : complex<f32>
, 1.0 + 0.0i
değerini ve
(0.0, 1.0) : complex<f32>
, 0.0 + 1.0i
değerini temsil eder. Bu öğelerin
daha sonra uygulama tarafından
tanımlanmış şekilde saklanır. Karmaşık sabitler
aşağıdaki sınırlamalara sahiptir:
- (C1)
is_wellformed(real_part, complex_element_type(complex_type))
. - (C2)
is_wellformed(imaginary_part, complex_element_type(complex_type))
.
TensorConstant ::= TensorLiteral ':' TensorType
TensorLiteral ::= 'dense' '<' (DenseLiteral | ElementLiteral) '>'
DenseLiteral ::= DenseDimension | DenseElements
DenseDimension ::= '[' [DenseLiteral {',' DenseLiteral}] ']'
DenseElements ::= [ElementLiteral {',' ElementLiteral}]
ElementLiteral ::= BooleanLiteral | IntegerLiteral | FloatLiteral | ComplexLiteral
Tensor sabitleri,
NumPy gösterimi. Örneğin, dense<[[1, 2, 3], [4, 5, 6]]> : tensor<2x3xi32>
dizinlerden öğelere aşağıdaki eşlemeyle birlikte bir tensör değerini temsil eder:
{0, 0} => 1
, {0, 1} => 2
, {0, 2} => 3
, {1, 0} => 4
, {1, 1} => 5
,
{1, 2} => 6
. Bu öğelerin bellekte depolanma sırası
tanımlanmıştır. Tensor sabitleri için aşağıdaki kısıtlamalar bulunur:
- (C1)
has_syntax(tensor_literal, element_type(tensor_type))
, burada:has_syntax(element_literal: Syntax, element_type: Type) = is_wellformed(element_literal, type)
.has_syntax(tensor_literal: List, element_type: Type) = has_syntax(tensor_literal..., element_type)
.
- (C2)
has_shape(tensor_literal, shape(tensor_type))
, burada:has_shape(element_literal: Syntax, []) = true
.has_shape(tensor_literal: List, shape: List) = size(tensor_literal) = shape[0] and has_shape(tensor_literal..., shape[1:])
.- aksi takdirde
false
.
QuantizedTensorConstant ::= QuantizedTensorLiteral ':' QuantizedTensorType
QuantizedTensorLiteral ::= 'dense' '<' (DenseLiteral | ElementLiteral) '>'
Nicelleştirilmiş tensör sabitleri, aynı tensör sabitleri olarak gösterim; elemanlar kendi sabit değerleri olarak belirtilir depolama alanı türü. Nicel tensör sabitleri aşağıdaki kısıtlamalara sahiptir:
- (C1)
has_syntax(quantized_tensor_literal, storage_type(quantized_tensor_type))
. - (C2)
has_shape(quantized_tensor_literal, shape(quantized_tensor_type))
.
StringConstant ::= StringLiteral
StringLiteral ::= '"' {stringCharacter | escapeSequence} '"'
stringCharacter ::= all ASCII characters except '\00', '\01', ... '\1f' and '"'
escapeSequence ::= '\' ('"' | '\' | 'n' | 't' | (hexadecimalDigit hexadecimalDigit))
Dize sabit değerleri, ASCII karakterleri kullanılarak belirtilen baytlardan oluşur.
kaçış dizileridir. Kodlamadan bağımsız oldukları için bu kodların yorumlanması
bayt, uygulama tanımlıdır. Dize değişmez değerleri string
türündedir.
İşlemler
abs
Anlam
operand
tensörü üzerinde öğe düzeyinde abs işlemi gerçekleştirir ve result
üretir
tensördür. Öğe türüne bağlı olarak aşağıdakiler gerçekleşir:
- İşaretli tam sayılar için: tam sayı modülü.
- Kayan reklamlar için: IEEE-754'ten
abs
. - Karmaşık sayılar için: karmaşık modül.
- Miktarlanmış türler için:
dequantize_op_quantize(abs, operand, type(result))
.
Girişler
Şirket | Ad | Tür | Sınırlamalar |
---|---|---|---|
(I1) | operand |
işaretli tam sayı, kayan nokta veya karmaşık tür ya da tensör başına miktarlandırılmış tensörün tensörü | (C1-C2) |
Çıkışlar
Ad | Tür | Sınırlamalar |
---|---|---|
result |
işaretli tam sayı veya kayan nokta türü ya da tensör başına miktarlandırılmış tensörün tensörü | (C1-C2) |
Sınırlamalar
- (C1)
shape(result) = shape(operand)
. - (C2)
baseline_element_type(result)
şu şekilde tanımlanır:is_complex(operand)
isecomplex_element_type(element_type(operand))
.- Aksi takdirde
baseline_element_type(operand)
.
Örnekler
// %operand: [-2, 0, 2]
%result = "stablehlo.abs"(%operand) : (tensor<3xi32>) -> tensor<3xi32>
// %result: [2, 0, 2]
add
Anlam
İki tensoru (lhs
ve rhs
) eleman olarak ekler ve bir üretir
result
tensörü. Öğe türüne bağlı olarak aşağıdakiler gerçekleşir:
- Boolelar için: mantıksal VEYA.
- Tam sayılar için: tamsayı toplama.
- Kayan reklamlar için: IEEE-754'ten
addition
. - Karmaşık sayılar için: karmaşık toplama.
- Miktarlanmış türler için:
dequantize_op_quantize(add, lhs, rhs, type(result))
.
Girişler
Şirket | Ad | Tür | Sınırlamalar |
---|---|---|---|
(I1) | lhs |
tensör veya nicel tensör | (C1-C6) |
(I2) | rhs |
tensör veya nicel tensör | (C1-C5), (C7) |
Çıkışlar
Ad | Tür | Sınırlamalar |
---|---|---|
result |
tensör veya nicel tensör | (C1-C7) |
Sınırlamalar
- İşlemde miktarlandırılmamış tensörler kullanılıyorsa:
- (C1)
type(lhs) = type(rhs) = type(result)
.
- (C1)
- İşlemde nicel tensörler kullanılıyorsa:
- (C2)
is_quantized(lhs) and is_quantized(rhs) and is_quantized(result)
. - (C3)
storage_type(lhs) = storage_type(rhs) = storage_type(result)
. - (C4)
expressed_type(lhs) = expressed_type(rhs) = expressed_type(result)
- (C5)
(is_per_axis_quantized(lhs) or is_per_axis_quantized(rhs)) = is_per_axis_quantized(result)
- (C6)
is_per_axis_quantized(lhs)
isequantization_dimension(lhs) = quantization_dimension(result)
. - (C7)
is_per_axis_quantized(rhs)
isequantization_dimension(rhs) = quantization_dimension(result)
.
- (C2)
Örnekler
// %lhs: [[1, 2], [3, 4]]
// %rhs: [[5, 6], [7, 8]]
%result = "stablehlo.add"(%lhs, %rhs) : (tensor<2x2xi32>, tensor<2x2xi32>) -> tensor<2x2xi32>
// %result: [[6, 8], [10, 12]]
after_all
Anlam
inputs
öğesini üreten işlemlerin herhangi bir tarihten önce yürütülmesini sağlar
ve result
türüne bağlı olan işlemler. Bu işlemi gerçekleştirmek hiçbir şey yapmaz,
yalnızca result
ile inputs
arasındaki veri bağımlılıklarını oluşturmak için kullanılabilir.
Girişler
Şirket | Ad | Tür |
---|---|---|
(I1) | inputs |
token değişken sayısı |
Çıkışlar
Ad | Tür |
---|---|
result |
token |
Örnekler
// %input0: !stablehlo.token
// %input1: !stablehlo.token
%result = "stablehlo.after_all"(%input0, %input1) : (!stablehlo.token, !stablehlo.token) -> !stablehlo.token
all_gather
Anlam
StableHLO süreç ızgarasındaki her işlem grubu içinde, değerleri birleştirir.
all_gather_dim
boyunca her süreçten operands
tensöründen
results
tensörü.
İşlem, StableHLO süreç ızgarasını process_groups
olarak ayırır.
şu şekilde tanımlanır:
cross_replica(replica_groups)
. (channel_id <= 0 and use_global_device_ids = false
ise)cross_replica_and_partition(replica_groups)
. (channel_id > 0 and use_global_device_ids = false
ise)flattened_ids(replica_groups)
. (channel_id > 0 and use_global_device_ids = true
ise)
Daha sonra, her process_group
içinde:
- Tümü için
operands...@receiver = [operand@sender for sender in process_group]
process_group
içindereceiver
. - Tümü için
results...@process = concatenate(operands...@process, all_gather_dim)
process_group
içindeprocess
.
Girişler
Şirket | Ad | Tür | Sınırlamalar |
---|---|---|---|
(I1) | operands |
değişken sayıda tensör veya tensör başına miktarlandırılmış tensör | (C1), (C6) |
(I2) | all_gather_dim |
si64 türündeki sabit |
(C1), (C6) |
(I3) | replica_groups |
si64 türünde 2 boyutlu tensör sabiti |
(C2-C4) |
(I4) | channel_id |
si64 türündeki sabit |
(C5) |
(I5) | use_global_device_ids |
i1 türündeki sabit |
(C5) |
Çıkışlar
Ad | Tür | Sınırlamalar |
---|---|---|
results |
değişken sayıda tensör veya tensör başına miktarlandırılmış tensör | (C6) |
Sınırlamalar
- (C1)
0 <= all_gather_dim < rank(operands...)
. - (C2)
is_unique(replica_groups)
. - (C3)
size(replica_groups)
şu şekilde tanımlanır:cross_replica
kullanılıyorsanum_replicas
.cross_replica_and_partition
kullanılıyorsanum_replicas
.flattened_ids
kullanılıyorsanum_processes
.
- (C4)
0 <= replica_groups < size(replica_groups)
- (C5)
use_global_device_ids = true
isechannel_id > 0
. - (C6)
type(results...) = type(operands...)
hariç:dim(results..., all_gather_dim) = dim(operands..., all_gather_dim) * dim(process_groups, 1)
.
Örnekler
// num_replicas: 2
// num_partitions: 1
// %operand0@(0, 0): [[1, 2], [3, 4]]
// %operand0@(1, 0): [[5, 6], [7, 8]]
// %operand1@(0, 0): [[11, 12], [13, 14]]
// %operand1@(1, 0): [[15, 16], [17, 18]]
%result:2 = "stablehlo.all_gather"(%operand0, %operand1) {
all_gather_dim = 1 : i64,
replica_groups = dense<[[0, 1]]> : tensor<1x2xi64>,
// channel_id = 0
channel_handle = #stablehlo.channel_handle<handle = 0, type = 0>
// use_global_device_ids = false
} : (tensor<2x2xi64>, tensor<2x2xi64>) -> (tensor<2x4xi64>, tensor<2x4xi64>)
// %result0@(0, 0): [[1, 2, 5, 6], [3, 4, 7, 8]]
// %result0@(1, 0): [[1, 2, 5, 6], [3, 4, 7, 8]]
// %result1@(0, 0): [[11, 12, 15, 16], [13, 14, 17, 18]]
// %result1@(1, 0): [[11, 12, 15, 16], [13, 14, 17, 18]]
all_reduce
Anlam
StableHLO süreç ızgarasındaki her süreç grubuna bir azaltma uygular
her işlemdeki operands
tensörlerinin değerlerine computation
işlevi
ve results
tensör üretir.
İşlem, StableHLO süreç ızgarasını process_groups
olarak ayırır.
şu şekilde tanımlanır:
cross_replica(replica_groups)
. (channel_id <= 0 and use_global_device_ids = false
ise)cross_replica_and_partition(replica_groups)
. (channel_id > 0 and use_global_device_ids = false
ise)flattened_ids(replica_groups)
. (channel_id > 0 and use_global_device_ids = true
ise)
Daha sonra, her process_group
içinde:
- Bazı ikili ağaçlar için
results...@process[result_index] = exec(schedule)
schedule
burada:exec(node)
=computation(exec(node.left), exec(node.right))
.exec(leaf)
=leaf.value
.
schedule
, sırasıyla geçişto_destination_type(operands...@process_group...[result_index], type(func_inputs(computation)[0]))
.
Girişler
Şirket | Ad | Tür | Sınırlamalar |
---|---|---|---|
(I1) | operands |
değişken sayıda tensör veya tensör başına miktarlandırılmış tensör | (C5) (C6) |
(I2) | replica_groups |
si64 türündeki 1 boyutlu tensör sabitlerinin değişken sayısı |
(C1-C3) |
(I3) | channel_id |
si64 türündeki sabit |
(C4) |
(I4) | use_global_device_ids |
i1 türündeki sabit |
(C4) |
(I5) | computation |
işlev | (C5) |
Çıkışlar
Ad | Tür | Sınırlamalar |
---|---|---|
results |
değişken sayıda tensör veya tensör başına miktarlandırılmış tensör | (C6-C7) |
Sınırlamalar
- (C1)
is_unique(replica_groups)
. - (C2)
size(replica_groups)
şu şekilde tanımlanır:cross_replica
kullanılıyorsanum_replicas
.cross_replica_and_partition
kullanılıyorsanum_replicas
.flattened_ids
kullanılıyorsanum_processes
.
- (C3)
0 <= replica_groups < size(replica_groups)
. - (C4)
use_global_device_ids = true
isechannel_id > 0
. - (C5)
computation
,(tensor<E>, tensor<E>) -> (tensor<E>)
türünde olup buradais_promotable(element_type(operand), E)
. - (C6)
shape(results...) = shape(operands...)
. - (C7)
element_type(results...) = E
.
Örnekler
// num_replicas: 2
// num_partitions: 1
// %operand0@(0, 0): [1, 2, 3, 4]
// %operand0@(1, 0): [5, 6, 7, 8]
// %operand1@(0, 0): [9, 10, 11, 12]
// %operand1@(1, 0): [13, 14, 15, 16]
%result:2 = "stablehlo.all_reduce"(%operand0, %operand0) ({
^bb0(%arg0: tensor<i64>, %arg1: tensor<i64>):
%0 = "stablehlo.add"(%arg0, %arg1) : (tensor<i64>, tensor<i64>) -> tensor<i64>
"stablehlo.return"(%0) : (tensor<i64>) -> ()
}) {
replica_groups = dense<[[0, 1]]> : tensor<1x2xi64>,
// channel_id = 0
channel_handle = #stablehlo.channel_handle<handle = 0, type = 0>
// use_global_device_ids = false
} : (tensor<4xi64>, tensor<4xi64>) -> (tensor<4xi64>, tensor<4xi64>)
// %result0@(0, 0): [6, 8, 10, 12]
// %result0@(1, 0): [6, 8, 10, 12]
// %result1@(0, 0): [22, 24, 26, 28]
// %result1@(1, 0): [22, 24, 26, 28]
all_to_all
Anlam
StableHLO süreç ızgarasındaki her süreç grubu içinde,
split_dimension
boyunca uzanan operands
tensörleri parçalara ayırarak bölünmeyi dağıtır
parçaları, sürekli olarak dağılmış parçaları birleştirerek
concat_dimension
ve results
tensör üretir.
İşlem, StableHLO süreç ızgarasını process_groups
olarak ayırır.
şu şekilde tanımlanır:
channel_id <= 0
isecross_replica(replica_groups)
.channel_id > 0
isecross_partition(replica_groups)
.
Daha sonra, her process_group
içinde:
split_parts...@sender = split(operands...@sender, split_count, split_dimension)
.process_group
içindeki tümsender
için.scattered_parts...@receiver = [split_parts...@sender[receiver_index] for sender in process_group]
burada:receiver_index = process_group.index(receiver)
.results...@process = concatenate(scattered_parts...@process, concat_dimension)
.
Girişler
Şirket | Ad | Tür | Sınırlamalar |
---|---|---|---|
(I1) | operands |
değişken sayıda tensör veya tensör başına miktarlandırılmış tensör | (C1-C3), (C9) |
(I2) | split_dimension |
si64 türündeki sabit |
(C1), (C2), (C9) |
(I3) | concat_dimension |
si64 türündeki sabit |
(C3) (C9) |
(I4) | split_count |
si64 türündeki sabit |
(C2), (C4), (C8), (C9) |
(I5) | replica_groups |
si64 türünde 2 boyutlu tensör sabiti |
(C5-C8) |
(I6) | channel_id |
si64 türündeki sabit |
Çıkışlar
Ad | Tür | Sınırlamalar |
---|---|---|
results |
değişken sayıda tensör veya tensör başına miktarlandırılmış tensör | (C9) |
Sınırlamalar
- (C1)
0 <= split_dimension < rank(operands...)
. - (C2)
dim(operands..., split_dimension) % split_count = 0
. - (C3)
0 <= concat_dimension < rank(operands...)
. - (C4)
0 < split_count
- (C5)
is_unique(replica_groups)
- (C6)
size(replica_groups)
şu şekilde tanımlanır:cross_replica
kullanılıyorsanum_replicas
.cross_partition
kullanılıyorsanum_partitions
.
- (C7)
0 <= replica_groups < size(replica_groups)
. - (C8)
dim(replica_groups, 1) = split_count
- (C9)
type(results...) = type(operands...)
, şu durumlar dışında:split_dimension != concat_dimension
:dim(results..., split_dimension) = dim(operands..., split_dimension) / split_count
.dim(results..., concat_dimension) = dim(operands..., concat_dimension) * split_count
.
Örnekler
// num_replicas: 2
// num_partitions: 1
// %operand1@(0, 0): [[1, 2, 3, 4],
// [5, 6, 7, 8]]
// %operand1@(1, 0): [[9, 10, 11, 12],
// [13, 14, 15, 16]]
// %operand2@(0, 0): [[17, 18, 19, 20],
// [21, 22, 23, 24]]
// %operand2@(1, 0): [[25, 26, 27, 28],
// [29, 30, 31, 32]]
%result:2 = "stablehlo.all_to_all"(%operand1, %operand2) {
split_dimension = 1 : i64,
concat_dimension = 0 : i64,
split_count = 2 : i64,
replica_groups = dense<[[0, 1]]> : tensor<1x2xi64>
// channel_id = 0
} : (tensor<2x4xi64>, tensor<2x4xi64>) -> (tensor<4x2xi64>, tensor<4x2xi64>)
// %result#0@(0, 0): [[1, 2], [5, 6], [9, 10], [13, 14]]
// %result#0@(1, 0): [[3, 4], [7, 8], [11, 12], [15, 16]]
// %result#1@(0, 0): [[17, 18], [21, 22], [25, 26], [29, 30]]
// %result#1@(1, 0): [[19, 20], [23, 24], [27, 28], [31, 32]]
ve
Anlam
lhs
ve rhs
olmak üzere iki tensör için öğe düzeyinde VE işlemini gerçekleştirir ve bir result
üretir
tensördür. Öğe türüne bağlı olarak aşağıdakiler gerçekleşir:
- Boolelar için: mantıksal VE.
- Tam sayılar için: bit tabanlı VE.
Girişler
Şirket | Ad | Tür | Sınırlamalar |
---|---|---|---|
(I1) | lhs |
boole veya tam sayı türündeki tensor | (C1) |
(I2) | rhs |
boole veya tam sayı türündeki tensor | (C1) |
Çıkışlar
Ad | Tür | Sınırlamalar |
---|---|---|
result |
boole veya tam sayı türündeki tensor | (C1) |
Sınırlamalar
- (C1)
type(lhs) = type(rhs) = type(result)
.
Örnekler
// %lhs: [[1, 2], [3, 4]]
// %rhs: [[5, 6], [7, 8]]
%result = "stablehlo.and"(%lhs, %rhs) : (tensor<2x2xi32>, tensor<2x2xi32>) -> tensor<2x2xi32>
// %result: [[1, 2], [3, 0]]
atan2
Anlam
lhs
ve rhs
tensörü üzerinde öğe tabanlı atan2 işlemi gerçekleştirir ve
result
tensörü. Öğe türüne bağlı olarak aşağıdakiler gerçekleşir:
- Kayan reklamlar için: IEEE-754'ten
atan2
. - Karmaşık sayılar için: karmaşık atan2.
- Miktarlanmış türler için:
dequantize_op_quantize(atan2, lhs, rhs, type(result))
.
Girişler
Şirket | Ad | Tür | Sınırlamalar |
---|---|---|---|
(I1) | lhs |
kayan nokta veya karmaşık tür ya da tensör başına miktarlandırılmış tensör tensörü | (C1) |
(I2) | rhs |
kayan nokta veya karmaşık tür ya da tensör başına miktarlandırılmış tensör tensörü | (C1) |
Çıkışlar
Ad | Tür | Sınırlamalar |
---|---|---|
result |
kayan nokta veya karmaşık tür ya da tensör başına miktarlandırılmış tensör tensörü | (C1) |
Sınırlamalar
- (C1)
baseline_type(lhs) = baseline_type(rhs) = baseline_type(result)
.
Örnekler
// %lhs: [0.0, 1.0, -1.0]
// %rhs: [0.0, 0.0, 0.0]
%result = "stablehlo.atan2"(%lhs, %rhs) : (tensor<3xf64>, tensor<3xf64>) -> tensor<3xf64>
// %result: [0.0, 1.57079637, -1.57079637] // [0.0, pi/2, -pi/2]
batch_norm_grad
Anlam
Geri çoğaltan çeşitli batch_norm_training
girişlerinin gradyanlarını hesaplar
grad_output
üretir ve grad_operand
, grad_scale
ve grad_offset
üretir
tensörler. Daha resmi ifade etmek gerekirse bu işlem,
aşağıdaki gibi Python söz dizimini kullanan mevcut StableHLO işlemlerini içerir:
def compute_sum(operand, feature_index):
(sum,) = reduce(
inputs=[operand],
init_values=[constant(0, element_type(operand))],
dimensions=[i for i in range(rank(operand)) if i != feature_index],
body=lambda x, y: add(x, y))
return sum
def compute_mean(operand, feature_index):
sum = compute_sum(operand, feature_index)
divisor = constant(size(operand) / dim(operand, feature_index),
element_type(operand))
divisor_bcast = broadcast_in_dim(divisor, [], type(sum))
return divide(sum, divisor_bcast)
def batch_norm_grad(operand, scale, mean, variance, grad_output, epsilon, feature_index):
# Broadcast inputs to type(operand)
scale_bcast = broadcast_in_dim(scale, [feature_index], type(operand))
mean_bcast = broadcast_in_dim(mean, [feature_index], type(operand))
variance_bcast = broadcast_in_dim(variance, [feature_index], type(operand))
epsilon_bcast = broadcast_in_dim(constant(epsilon, element_type(operand)), [],
type(operand))
# Perform normalization using the provided `mean` and `variance`
# Intermediate values will be useful for computing gradients
centered_operand = subtract(operand, mean_bcast)
stddev = sqrt(add(variance_bcast, epsilon_bcast))
normalized_operand = divide(centered_operand, stddev)
# Use the implementation from batchnorm_expander.cc in XLA
# Temporary variables have exactly the same names as in the C++ code
elements_per_feature = broadcast_in_dim(
constant(divide(size(operand), dim(operand, feature_index)),
element_type(grad_output)),
[], type(operand))
i1 = multiply(grad_output, elements_per_feature)
i2 = broadcast_in_dim(
compute_sum(grad_output, feature_index), [feature_index], type(operand))
i3 = broadcast_in_dim(
compute_sum(multiply(grad_output, centered_operand), feature_index),
[feature_index], type(operand))
i4 = multiply(i3, centered_operand)
i5 = divide(i4, add(variance_bcast, epsilon_bcast))
i6 = subtract(subtract(i1, i2), i5)
grad_operand =
multiply(divide(divide(scale_bcast, stddev), elements_per_feature), i6)
grad_scale =
compute_sum(multiply(grad_output, normalized_operand), feature_index)
grad_offset = compute_sum(grad_output, feature_index)
return grad_operand, grad_scale, grad_offset
Miktarı kullanılan türlerde,
dequantize_batch_norm_grad_or_training_quantize(lambda operand, scale, mean,
variance, grad_output: batch_norm_grad(operand, scale, mean, variance,
grad_output, epsilon, feature_index), operand, scale, mean, variance,
grad_output, type(grad_operand), type(grad_scale), type(feature_index))
Girişler
Şirket | Ad | Tür | Sınırlamalar |
---|---|---|---|
(I1) | operand |
kayan nokta tipi veya tensör başına miktarlandırılmış tensör tensörü | (C1-C3), (C5) |
(I2) | scale |
Kayan nokta veya tensör başına miktarlandırılmış türde 1 boyutlu tensör | (C2), (C4), (C5) |
(I3) | mean |
Kayan nokta veya tensör başına miktarlandırılmış türde 1 boyutlu tensör | (C2), (C4) |
(I4) | variance |
Kayan nokta veya tensör başına miktarlandırılmış türde 1 boyutlu tensör | (C2), (C4) |
(I5) | grad_output |
kayan nokta tipi veya tensör başına miktarlandırılmış tensör tensörü | (C2), (C3) |
(I6) | epsilon |
f32 türündeki sabit |
|
(I7) | feature_index |
si64 türündeki sabit |
(C1), (C5) |
Çıkışlar
Ad | Tür | Sınırlamalar |
---|---|---|
grad_operand |
kayan nokta tipi veya tensör başına miktarlandırılmış tensör tensörü | (C2), (C3) |
grad_scale |
Kayan nokta veya tensör başına miktarlandırılmış türde 1 boyutlu tensör | (C2), (C4) |
grad_offset |
Kayan nokta veya tensör başına miktarlandırılmış türde 1 boyutlu tensör | (C2), (C4) |
Sınırlamalar
- (C1)
0 <= feature_index < rank(operand)
. - (C2)
operand
,scale
,mean
,variance
,grad_output
,grad_operand
,grad_scale
vegrad_offset
aynıbaseline_element_type
değerine sahip. - (C3)
operand
,grad_output
vegrad_operand
aynı şekle sahip. - (C4)
scale
,mean
,variance
,grad_scale
vegrad_offset
sahip anlamına gelir. - (C5)
size(scale) = dim(operand, feature_index)
Örnekler
// %operand: [
// [[1.0, 2.0], [3.0, 4.0]],
// [[3.0, 4.0], [1.0, 2.0]]
// ]
// %scale: [1.0, 1.0]
// %mean: [2.0, 3.0]
// %variance: [1.0, 1.0]
// %grad_output: [
// [[0.1, 0.1], [0.1, 0.1]],
// [[0.1, 0.1], [0.1, 0.1]]
// ]
%grad_operand, %grad_scale, %grad_offset =
"stablehlo.batch_norm_grad"(%operand, %scale, %mean, %variance, %grad_output) {
epsilon = 0.0 : f32,
feature_index = 2 : i64
} : (tensor<2x2x2xf64>, tensor<2xf64>, tensor<2xf64>, tensor<2xf64>,
tensor<2x2x2xf64>) -> (tensor<2x2x2xf64>, tensor<2xf64>, tensor<2xf64>)
// %grad_operand: [
// [[0.0, 0.0], [0.0, 0.0]],
// [[0.0, 0.0], [0.0, 0.0]]
// ]
// %grad_scale: [0.0, 0.0]
// %grad_offset: [0.4, 0.4]
batch_norm_inference
Anlam
operand
tensörünü şu boyut hariç tüm boyutlarda normalleştirir:
feature_index
boyutunu belirler ve bir result
tensörü oluşturur. Daha resmi ifade etmek gerekirse
işlem, mevcut StableHLO işlemlerine ayrışma olarak ifade edilebilir
aşağıdaki gibi bir Python söz dizimi kullanarak:
def batch_norm_inference(operand, scale, offset, mean, variance, epsilon, feature_index):
# Broadcast inputs to shape(operand)
scale_bcast = broadcast_in_dim(scale, [feature_index], type(operand))
offset_bcast = broadcast_in_dim(offset, [feature_index], type(operand))
mean_bcast = broadcast_in_dim(mean, [feature_index], type(operand))
variance_bcast = broadcast_in_dim(variance, [feature_index], type(operand))
epsilon_bcast = broadcast_in_dim(constant(epsilon, element_type(operand)), [],
type(operand))
# Perform normalization using the provided `mean` and `variance` instead of
# computing them like `batch_norm_training` does.
centered_operand = subtract(operand, mean_bcast)
stddev = sqrt(add(variance_bcast, epsilon_bcast))
normalized_operand = divide(centered_operand, stddev)
return add(multiply(scale_bcast, normalized_operand), offset_bcast)
Miktarı kullanılan türlerde,
dequantize_op_quantize(lambda operand, scale, offset, mean, variance:
batch_norm_inference(operand, scale, offset, mean, variance, epsilon,
feature_index), operand, scale, offset, mean, variance, type(result))
Girişler
Şirket | Ad | Tür | Sınırlamalar |
---|---|---|---|
(I1) | operand |
kayan nokta tipi veya tensör başına miktarlandırılmış tensör tensörü | (C1-C7) |
(I2) | scale |
Kayan nokta veya tensör başına miktarlandırılmış türde 1 boyutlu tensör | (C2), (C3) |
(I3) | offset |
Kayan nokta veya tensör başına miktarlandırılmış türde 1 boyutlu tensör | (C2), (C4) |
(I4) | mean |
Kayan nokta veya tensör başına miktarlandırılmış türde 1 boyutlu tensör | (C5) |
(I5) | variance |
Kayan nokta veya tensör başına miktarlandırılmış türde 1 boyutlu tensör | (C2), (C6) |
(I6) | epsilon |
f32 türündeki sabit |
|
(I7) | feature_index |
si64 türündeki sabit |
(C1), (C3-C6) |
Çıkışlar
Ad | Tür | Sınırlamalar |
---|---|---|
result |
kayan nokta tipi veya tensör başına miktarlandırılmış tensör tensörü | (C2), (C7) |
Sınırlamalar
- (C1)
0 <= feature_index < rank(operand)
. - (C2)
operand
,scale
,offset
,mean
,variance
veresult
sahip aynıbaseline_element_type
. - (C3)
size(scale) = dim(operand, feature_index)
. - (C4)
size(offset) = dim(operand, feature_index)
- (C5)
size(mean) = dim(operand, feature_index)
- (C6)
size(variance) = dim(operand, feature_index)
. - (C7)
baseline_type(operand) = baseline_type(result)
.
Örnekler
// %operand: [
// [[1.0, 2.0], [3.0, 4.0]],
// [[3.0, 4.0], [1.0, 2.0]]
// ]
// %scale: [1.0, 1.0]
// %offset: [1.0, 1.0]
// %mean: [2.0, 3.0]
// %variance: [1.0, 1.0]
%result = "stablehlo.batch_norm_inference"(%operand, %scale, %offset, %mean, %variance) {
epsilon = 0.0 : f32,
feature_index = 2 : i64
} : (tensor<2x2x2xf64>, tensor<2xf64>, tensor<2xf64>, tensor<2xf64>, tensor<2xf64>) -> tensor<2x2x2xf64>
// %result: [
// [[0.0, 0.0], [2.0, 2.0]],
// [[2.0, 2.0], [0.0, 0.0]]
// ]
batch_norm_training
Anlam
feature_index
hariç tüm boyutlardaki ortalamayı ve varyansı hesaplar
boyut ve output
, batch_mean
üreten operand
tensörü normalleştirir
ve batch_var
tensör. Daha resmi ifade etmek gerekirse bu işlem
mevcut StableHLO işlemlerine ayrıştırmak için Python sözdizimini
şöyle olur:
def compute_mean(operand, feature_index):
(sum,) = reduce(
inputs=[operand],
init_values=[constant(0, element_type(operand))],
dimensions=[i for i in range(rank(operand)) if i != feature_index],
body=lambda x, y: add(x, y))
divisor = constant(size(operand) / dim(operand, feature_index),
element_type(operand))
divisor_bcast = broadcast_in_dim(divisor, [], type(sum))
return divide(sum, divisor_bcast)
def compute_variance(operand, feature_index):
mean = compute_mean(operand, feature_index)
mean_bcast = broadcast_in_dim(mean, [feature_index], type(operand))
centered_operand = subtract(operand, mean_bcast)
return compute_mean(mul(centered_operand, centered_operand), feature_index)
def batch_norm_training(operand, scale, offset, epsilon, feature_index):
mean = compute_mean(operand, feature_index)
variance = compute_variance(operand, feature_index)
return batch_norm_inference(operand, scale, offset, mean, variance, epsilon,
feature_index),
mean, variance
Miktarı kullanılan türlerde,
dequantize_batch_norm_grad_or_training_quantize(lambda operand, scale, offset:
batch_norm_training(operand, scale, offset, epsilon, feature_index), operand,
scale, offset, type(output), type(batch_mean), type(batch_var))
Girişler
Şirket | Ad | Tür | Sınırlamalar |
---|---|---|---|
(I1) | operand |
kayan nokta tipi veya tensör başına miktarlandırılmış tensör tensörü | (C1) |
(I2) | scale |
Kayan nokta veya tensör başına miktarlandırılmış 1 boyutlu tensör | (C2), (C3) |
(I3) | offset |
Kayan nokta veya tensör başına miktarlandırılmış 1 boyutlu tensör | (C2), (C4) |
(I4) | epsilon |
f32 türündeki sabit |
(C1), (C3-C6) |
(I5) | feature_index |
si64 türündeki sabit |
(C1), (C3-C6) |
Çıkışlar
Ad | Tür | Sınırlamalar |
---|---|---|
output |
kayan nokta tipi veya tensör başına miktarlandırılmış tensör tensörü | (C7) |
batch_mean |
Kayan nokta veya tensör başına miktarlandırılmış 1 boyutlu tensör | (C2), (C5) |
batch_var |
Kayan nokta veya tensör başına miktarlandırılmış 1 boyutlu tensör | (C2), (C6) |
Sınırlamalar
- (C1)
0 <= feature_index < rank(operand)
. - (C2)
operand
,scale
,offset
,batch_mean
,batch_var
veoutput
var aynıbaseline_element_type
. - (C3)
size(scale) = dim(operand, feature_index)
. - (C4)
size(offset) = dim(operand, feature_index)
- (C5)
size(batch_mean) = dim(operand, feature_index)
- (C6)
size(batch_var) = dim(operand, feature_index)
. - (C7)
baseline_type(output) = baseline_type(operand)
.
Örnekler
// %operand: [
// [[1.0, 2.0], [3.0, 4.0]],
// [[3.0, 4.0], [1.0, 2.0]]
// ]
// %scale: [1.0, 1.0]
// %offset: [1.0, 1.0]
%output, %batch_mean, %batch_var = "stablehlo.batch_norm_training"(%operand, %scale, %offset) {
epsilon = 0.0 : f32,
feature_index = 2 : i64
} : (tensor<2x2x2xf64>, tensor<2xf64>, tensor<2xf64>) ->
(tensor<2x2x2xf64>, tensor<2xf64>, tensor<2xf64>)
// %output: [
// [[0.0, 0.0], [2.0, 2.0]],
// [[2.0, 2.0], [0.0, 0.0]]
// ]
// %batch_mean: [2.0, 3.0]
// %batch_var: [1.0, 1.0]
bitcast_convert
Anlam
operand
tensörü üzerinde bir bitcast işlemi gerçekleştirir ve result
tensörü üretir
Bu örnekte, operand
tensörünün tamamının bitleri
result
tensör türü.
Daha resmî bir şekilde ifade etmek gerekirse E = element_type(operand)
, E' = element_type(result)
,
ve R = rank(operand)
:
num_bits(E') < num_bits(E)
isebits(result[i0, ..., iR-1, :]) = bits(operand[i0, ..., iR-1])
.num_bits(E') > num_bits(E)
isebits(result[i0, ..., iR-2]) = bits(operand[i0, ..., iR-2, :])
.num_bits(E') = num_bits(E)
isebits(result[i0, ..., iR-1]) = bits(operand[i0, ..., iR-1])
.
bits
, belirli bir değerin ve davranışının bellekteki gösterimini döndürür
uygulama tanımlıdır çünkü tensörlerin tam gösterimi
öğe türlerinin tam gösterimi şöyledir:
tanımlanabilir.
Girişler
Şirket | Ad | Tür | Sınırlamalar |
---|---|---|---|
(I1) | operand |
tensör veya nicel tensör | (C1-C2) |
Çıkışlar
Ad | Tür | Sınırlamalar |
---|---|---|
result |
tensör veya nicel tensör | (C1-C2) |
Sınırlamalar
- (C1)
E = is_quantized(operand) ? storage_type(operand) : element_type(operand)
,E' = is_quantized(result) ? storage_type(result) : element_type(result)
veR = rank(operand)
dikkate alınarak:num_bits(E') = num_bits(E)
iseshape(result) = shape(operand)
.- Eğer
num_bits(E') < num_bits(E)
: rank(result) = R + 1
.- Tüm
0 <= i < R
içindim(result, i) = dim(operand, i)
. dim(result, R) * num_bits(E') = num_bits(E)
.- Eğer
num_bits(E') > num_bits(E)
: rank(result) = R - 1
.- Tüm
0 <= i < R
içindim(result, i) = dim(operand, i)
. dim(operand, R - 1) * num_bits(E) = num_bits(E')
.
- (C2)
is_complex(operand) or is_complex(result)
ise,is_complex(operand) and is_complex(result)
.
Örnekler
// %operand: 0x0123456789ABCDEF
%result = "stablehlo.bitcast_convert"(%operand) : (tensor<f64>) -> tensor<4xf16>
// %result: [0xCDEF, 0x89AB, 0x4567, 0x0123] // little-endian representation
broadcast_in_dim
Anlam
Verileri çoğaltarak bir giriş tensörünün boyutlarını ve/veya sıralamasını genişletir
operand
tensöründe çalışır ve bir result
tensörü üretir. Daha resmi ifade etmek gerekirse
result[result_index] = operand[operand_index]
burada tüm d
için
axes(operand)
:
dim(operand, d) = 1
iseoperand_index[d] = 0
.- Aksi takdirde
operand_index[d] = result_index[broadcast_dimensions[d]]
.
Girişler
Şirket | Ad | Tür | Sınırlamalar |
---|---|---|---|
(I1) | operand |
tensör veya nicel tensör | (C1-C2), (C5-C6) |
(I2) | broadcast_dimensions |
si64 türünde 1 boyutlu tensör sabiti |
(C2-C6) |
Çıkışlar
Ad | Tür | Sınırlamalar |
---|---|---|
result |
tensör veya nicel tensör | (C1), (C3), (C5-C6) |
Sınırlamalar
- (C1)
element_type(result)
değerini sağlayan:!is_per_axis_quantized(operand)
iseelement_type(operand)
.element_type(operand)
(buquantization_dimension(operand)
hariç)scales(operand)
vezero_points(operand)
şundan farklı olabilir:quantization_dimension(result)
,scales(result)
vezero_points(result)
resp., aksi takdirde.
- (C2)
size(broadcast_dimensions) = rank(operand)
. - (C3)
0 <= broadcast_dimensions < rank(result)
. - (C4)
is_unique(broadcast_dimensions)
- (C5)
axes(operand)
bünyesindeki tümd
için:dim(operand, d) = 1
veyadim(operand, d) = dim(result, broadcast_dimensions[d])
.
- (C6)
is_per_axis_quantized(result)
ise:quantization_dimension(result) = broadcast_dimensions[quantization_dimension(operand)]
.dim(operand, quantization_dimension(operand)) = 1
ise,scales(result)[i] = scales(operand)[0] and zero_points(result)[i] = zero_points(operand)[0] for i in range(dim(result, quantization_dimension(result)))
.
Örnekler
// %operand: [
// [1, 2, 3]
// ]
%result = "stablehlo.broadcast_in_dim"(%operand) {
broadcast_dimensions = array<i64: 2, 1>
} : (tensor<1x3xi32>) -> tensor<2x3x2xi32>
// %result: [
// [
// [1, 1],
// [2, 2],
// [3, 3]
// ],
// [
// [1, 1],
// [2, 2],
// [3, 3]
// ]
// ]
kılıf
Anlam
branches
kaynağındaki tam olarak bir işlevin yürütülmesiyle elde edilen çıktıyı oluşturur
(index
değerine bağlıdır). Daha resmi dilde: result = selected_branch()
burada:
0 <= index < size(branches)
iseselected_branch = branches[index]
.- Aksi takdirde
selected_branch = branches[-1]
.
Girişler
Şirket | Ad | Tür | Sınırlamalar |
---|---|---|---|
(I1) | index |
si32 türünde 0 boyutlu tensör |
|
(I2) | branches |
değişken fonksiyon sayısı | (C1-C4) |
Çıkışlar
Ad | Tür | Sınırlamalar |
---|---|---|
results |
değişken tensör, nicel tensör veya jeton sayısı | (C4) |
Sınırlamalar
- (C1)
0 < size(branches)
. - (C2)
input_types(branches...) = []
. - (C3)
same(output_types(branches...))
. - (C4)
type(results...) = output_types(branches[0])
Örnekler
// %index: -1
// %result_branch0: [0, 0]
// %result_branch1: [1, 1]
%result0, %result1 = "stablehlo.case"(%index) ({
"stablehlo.return"(%result_branch0, %result_branch0) : (tensor<2xi64>, tensor<2xi64>) -> ()
}, {
"stablehlo.return"(%result_branch1, %result_branch1) : (tensor<2xi64>, tensor<2xi64>) -> ()
}) : (tensor<i32>) -> (tensor<2xi64>, tensor<2xi64>)
// %result0: [1, 1]
// %result1: [1, 1]
CBrt
Anlam
operand
tensörü üzerinde öğe tabanlı kübik kök işlemi gerçekleştirir ve
result
tensörü. Öğe türüne bağlı olarak aşağıdakiler gerçekleşir:
- Kayan reklamlar için: IEEE-754'ten
rootn(x, 3)
. - Karmaşık sayılar için: karmaşık küpik kök.
- Miktarı ölçülmüş türler için:
dequantize_op_quantize(cbrt, operand, type(result))
Girişler
Şirket | Ad | Tür | Sınırlamalar |
---|---|---|---|
(I1) | operand |
kayan nokta veya karmaşık tür ya da tensör başına miktarlandırılmış tensör tensörü | (C1) |
Çıkışlar
Ad | Tür | Sınırlamalar |
---|---|---|
result |
kayan nokta veya karmaşık tür ya da tensör başına miktarlandırılmış tensör tensörü | (C1) |
Sınırlamalar
- (C1)
baseline_type(operand) = baseline_type(result)
.
Örnekler
// %operand: [0.0, 1.0, 8.0, 27.0]
%result = "stablehlo.cbrt"(%operand) : (tensor<4xf64>) -> tensor<4xf64>
// %result: [0.0, 1.0, 2.0, 3.0]
ceil
Anlam
Element tabanlı operand
tensörü gerçekleştirir ve bir result
tensörü üretir.
IEEE-754'teki roundToIntegralTowardPositive
işlemini uygular
bakın. Miktarı kullanılan türlerde,
dequantize_op_quantize(ceil, operand, type(result))
Girişler
Şirket | Ad | Tür | Sınırlamalar |
---|---|---|---|
(I1) | operand |
kayan nokta tipi veya tensör başına miktarlandırılmış tensör tensörü | (C1) |
Çıkışlar
Ad | Tür | Sınırlamalar |
---|---|---|
result |
kayan nokta tipi veya tensör başına miktarlandırılmış tensör tensörü | (C1) |
Sınırlamalar
- (C1)
baseline_type(operand) = baseline_type(result)
.
Örnekler
// %operand: [-0.8166, -0.2530, 0.2530, 0.8166, 2.0]
%result = "stablehlo.ceil"(%operand) : (tensor<5xf32>) -> tensor<5xf32>
// %result: [-0.0, -0.0, 1.0, 1.0, 2.0]
Cholesky
Anlam
Bir dizi matrisin Cholesky ayrışmasını hesaplar.
Daha resmî bir şekilde ifade etmek gerekirse index_space(result)
bölgesindeki tüm i
için
result[i0, ..., iR-3, :, :]
, aşağıdaki değerin bir Cholesky ayrışmasıdır
a[i0, ..., iR-3, :, :]
, alt üçgenden biri biçiminde
(lower
true
ise) veya üst üçgen (lower
false
ise) matrisi.
Karşıt üçgende gösterilen çıkış değerleri (ör. katı üst üçgen veya
katı alt üçgenler ise uygulama tanımlıdır.
Girdi matrisinin Hermitian pozitif tanımlı olmadığı i
varsa
söz konusu olduğunda, davranış tanımsızdır.
Miktarı kullanılan türlerde,
dequantize_op_quantize(lambda operand: cholesky(operand, lower), a, type(result))
Girişler
Şirket | Ad | Tür | Sınırlamalar |
---|---|---|---|
(I1) | a |
kayan nokta veya karmaşık tür ya da tensör başına miktarlandırılmış tensör tensörü | (C1-C3) |
(I2) | lower |
i1 türünde 0 boyutlu tensör sabiti |
Çıkışlar
Ad | Tür | Sınırlamalar |
---|---|---|
result |
kayan nokta veya karmaşık tür ya da tensör başına miktarlandırılmış tensör tensörü | (C1) |
Sınırlamalar
- (C1)
baseline_type(a) = baseline_type(result)
. - (C2)
2 <= rank(a)
. - (C3)
dim(a, -2) = dim(a, -1)
.
Örnekler
// %a: [
// [1.0, 2.0, 3.0],
// [2.0, 20.0, 26.0],
// [3.0, 26.0, 70.0]
// ]
%result = "stablehlo.cholesky"(%a) {
lower = true
} : (tensor<3x3xf32>) -> tensor<3x3xf64>
// %result: [
// [1.0, 0.0, 0.0],
// [2.0, 4.0, 0.0],
// [3.0, 5.0, 6.0]
// ]
kenetleme
Anlam
operand
tensörünün her öğesini minimum ile maksimum arasında sabitler
değerini döndürür ve bir result
tensörü üretir. Daha resmi dilde: result[result_index] =
minimum(maximum(operand[result_index], min_element), max_element)
,
burada min_element = rank(min) = 0 ? min[] : min[result_index]
,
max_element = rank(max) = 0 ? max[] : max[result_index]
. Miktarı kullanılan türlerde
dequantize_op_quantize(clamp, min, operand, max, type(result))
gerçekleştiriyor.
Karmaşık sayılarda sıralama yaratmak, şaşırtıcı anlamlar ya da Bu nedenle gelecekte karmaşık sayılar için desteği kaldırmayı planlıyoruz. (#560).
Girişler
Şirket | Ad | Tür | Sınırlamalar |
---|---|---|---|
(I1) | min |
tensör veya tensör başına miktarlandırılmış tensör | (C1), (C3) |
(I2) | operand |
tensör veya tensör başına miktarlandırılmış tensör | (C1-C4) |
(I3) | max |
tensör veya tensör başına miktarlandırılmış tensör | (C2), (C3) |
Çıkışlar
Ad | Tür | Sınırlamalar |
---|---|---|
result |
tensör veya tensör başına miktarlandırılmış tensör | (C4) |
Sınırlamalar
- (C1)
rank(min) = 0 or shape(min) = shape(operand)
. - (C2)
rank(max) = 0 or shape(max) = shape(operand)
. - (C3)
baseline_element_type(min) = baseline_element_type(operand) = baseline_element_type(max)
. - (C4)
baseline_type(operand) = baseline_type(result)
Örnekler
// %min: [5, 10, 15]
// %operand: [3, 13, 23]
// %max: [10, 15, 20]
%result = "stablehlo.clamp"(%min, %operand, %max) : (tensor<3xi32>, tensor<3xi32>, tensor<3xi32>) -> tensor<3xi32>
// %result: [5, 13, 20]
collective_broadcast
Anlam
StableHLO süreç tablosundaki her süreç grubunda,
operand
tensörü kaynak süreçten hedef süreçlere aktarır ve
result
tensörü.
İşlem, StableHLO süreç ızgarasını process_groups
olarak ayırır.
şu şekilde tanımlanır:
channel_id <= 0
isecross_replica(replica_groups)
.channel_id > 0
isecross_partition(replica_groups)
.
Daha sonra, result@process
sağlayan:
- Sürecin geçerli olması için gereken
i
varsaoperand@process_groups[i, 0]
process_groups[i]
içinde. broadcast_in_dim(constant(is_quantized(result) ? quantize(0, element_type(result)) : 0, element_type(result)), [], type(result))
. aksi takdirde.
Girişler
Şirket | Ad | Tür | Sınırlamalar |
---|---|---|---|
(I1) | operand |
tensör veya tensör başına miktarlandırılmış tensör | (C3) |
(I2) | replica_groups |
si64 türündeki 1 boyutlu tensör sabitlerinin değişken sayısı |
(C1), (C2) |
(I3) | channel_id |
si64 türündeki sabit |
Çıkışlar
Ad | Tür | Sınırlamalar |
---|---|---|
result |
tensör veya tensör başına miktarlandırılmış tensör | (C3) |
Sınırlamalar
- (C1)
is_unique(replica_groups)
. - (C2)
0 <= replica_groups < N
buradaN
şu şekilde tanımlanır:cross_replica
kullanılıyorsanum_replicas
.cross_partition
kullanılıyorsanum_partitions
.
- (C3)
type(result) = type(operand)
.
Örnekler
// num_replicas: 4
// num_partitions: 1
// %operand@(0, 0): [[1, 2]]
// %operand@(1, 0): [[3, 4]]
// %operand@(2, 0): [[5, 6]]
// %operand@(3, 0): [[7, 8]]
%result = "stablehlo.collective_broadcast"(%operand) {
replica_groups = dense<[[2, 1]]> : tensor<1x2xi64>,
channel_handle = #stablehlo.channel_handle<handle = 0, type = 0>
} : (tensor1x2xi64>) -> tensor<1x2xi64>
// %result@(0, 0): [[0, 0]]
// %result@(1, 0): [[5, 6]]
// %result@(2, 0): [[5, 6]]
// %result@(3, 0): [[0, 0]]
collective_permute
Anlam
StableHLO süreç ızgarasındaki her işlem grubu içinde,
operand
tensörü kaynak süreçten hedef sürece çıkar ve
result
tensörü.
İşlem, StableHLO süreç ızgarasını process_groups
olarak ayırır.
şu şekilde tanımlanır:
channel_id <= 0
isecross_replica(source_target_pairs)
.channel_id > 0
isecross_partition(source_target_pairs)
.
Daha sonra, result@process
sağlayan:
operand@process_groups[i, 0]
gibi biri
varsaprocess_groups[i, 1] = process
.broadcast_in_dim(constant(is_quantized(result) ? quantize(0, element_type(result)) : 0, element_type(result)), [], type(result))
. aksi takdirde.
Girişler
Şirket | Ad | Tür | Sınırlamalar |
---|---|---|---|
(I1) | operand |
tensör veya tensör başına miktarlandırılmış tensör | (C5) |
(I2) | source_target_pairs |
si64 türünde 2 boyutlu tensör sabiti |
(C1-C4) |
(I3) | channel_id |
si64 türündeki sabit |
Çıkışlar
Ad | Tür | Sınırlamalar |
---|---|---|
result |
tensör veya tensör başına miktarlandırılmış tensör | (C1) |
Sınırlamalar
- (C1)
dim(source_target_pairs, 1) = 2
. - (C2)
is_unique(source_target_pairs[:, 0])
. - (C3)
is_unique(source_target_pairs[:, 1])
. - (C4)
0 <= source_target_pairs < N
; buradaN
şu şekilde tanımlanır:cross_replica
kullanılıyorsanum_replicas
.cross_partition
kullanılıyorsanum_partitions
.
- (C5)
type(result) = type(operand)
Örnekler
// num_replicas: 3
// num_partitions: 1
// %operand@(0, 0): [[1, 2], [3, 4]]
// %operand@(1, 0): [[5, 6], [7, 8]]
// %operand@(2, 0): [[9, 10], [11, 12]]
%result = "stablehlo.collective_permute"(%operand) {
source_target_pairs = dense<[[0, 1], [1, 2]]> : tensor<2x2xi64>,
channel_handle = #stablehlo.channel_handle<handle = 0, type = 0>
} : (tensor<2x2xi64>) -> tensor<2x2xi64>
//
// %result@(0, 0): [[0, 0], [0, 0]]
// %result@(1, 0): [[1, 2], [3, 4]]
// %result@(2, 0): [[5, 6], [7, 8]]
karşılaştır
Anlam
Şuna göre lhs
ve rhs
tensörlerinin öğe bazında karşılaştırmasını yapar:
comparison_direction
ve compare_type
ile aynı ve bir result
tensörü üretir.
comparison_direction
ve compare_type
değerleri şuna sahiptir:
anlambilim:
Boole ve tam sayı öğe türleri için:
EQ
:lhs = rhs
.NE
:lhs != rhs
.GE
:lhs >= rhs
.GT
:lhs > rhs
.LE
:lhs <= rhs
.LT
:lhs < rhs
.
op, compare_type = FLOAT
içeren kayan nokta öğe türlerinde
aşağıdaki IEEE-754 işlemleri için geçerlidir:
EQ
:compareQuietEqual
.NE
:compareQuietNotEqual
.GE
:compareQuietGreaterEqual
.GT
:compareQuietGreater
.LE
:compareQuietLessEqual
.LT
:compareQuietLess
.
compare_type = TOTALORDER
içeren kayan nokta öğe türlerinde op
şuna ait totalOrder
ve compareQuietEqual
işlemlerinin birleşimini kullanır:
IEEE-754.
Karmaşık öğe türleri için (real, imag)
çiftlerinin sözlüksel karşılaştırması
sağlanan comparison_direction
ve compare_type
kullanılarak gerçekleştirildi.
Karmaşık sayılarda sıralama yaratmak, şaşırtıcı anlamlar ya da
Bu nedenle gelecekte karmaşık sayılar için desteği kaldırmayı planlıyoruz.
comparison_direction
GE
, GT
, LE
veya LT
olduğunda
(#560).
Miktarı ölçülmüş türler için. dequantize_compare(lhs, rhs,
comparison_direction)
gerçekleştiriyor.
Girişler
Şirket | Ad | Tür | Sınırlamalar |
---|---|---|---|
(I1) | lhs |
tensör veya tensör başına miktarlandırılmış tensör | (C1-C3) |
(I2) | rhs |
tensör veya tensör başına miktarlandırılmış tensör | (C1-C2) |
(I3) | comparison_direction |
EQ , NE , GE , GT , LE ve LT sıralaması |
|
(I4) | compare_type |
FLOAT , TOTALORDER , SIGNED ve UNSIGNED sıralaması |
(C3) |
Çıkışlar
Ad | Tür | Sınırlamalar |
---|---|---|
result |
boole türündeki tensor | (C2) |
Sınırlamalar
- (C1)
baseline_element_type(lhs) = baseline_element_type(rhs)
. - (C2)
shape(lhs) = shape(rhs) = shape(result)
. - (C3)
compare_type
şu şekilde tanımlanır:is_signed_integer(element_type(lhs))
iseSIGNED
.is_unsigned_integer(element_type(lhs)) or is_boolean(element_type(lhs))
iseUNSIGNED
.is_float(element_type(lhs))
iseFLOAT
veyaTOTALORDER
.is_complex(element_type(lhs))
iseFLOAT
.
Örnekler
// %lhs: [1.0, 3.0]
// %rhs: [1.1, 2.9]
%result = "stablehlo.compare"(%lhs, %rhs) {
comparison_direction = #stablehlo<comparison_direction LT>,
compare_type = #stablehlo<comparison_type FLOAT>
} : (tensor<2xf32>, tensor<2xf32>) -> tensor<2xi1>
// %result: [true, false]
karmaşık
Anlam
Gerçek ve eşleştirilmiş değer çiftinden karmaşık bir değere element tabanlı dönüşüm gerçekleştirir.
lhs
ve rhs
ile sanal değerler arasında bir olarak belirleyip bir result
tensörü üretir.
Girişler
Şirket | Ad | Tür | Sınırlamalar |
---|---|---|---|
(I1) | lhs |
f32 veya f64 türündeki tensör |
(C1-C3) |
(I2) | rhs |
f32 veya f64 türündeki tensör |
(C1) |
Çıkışlar
Ad | Tür | Sınırlamalar |
---|---|---|
result |
karmaşık türde tensor | (C2), (C3) |
Sınırlamalar
- (C1)
type(lhs) = type(rhs)
. - (C2)
shape(result) = shape(lhs)
. - (C3)
element_type(result)
,complex<E>
türünde olup buradaE = element_type(lhs)
.
Örnekler
// %lhs: [1.0, 3.0]
// %rhs: [2.0, 4.0]
%result = "stablehlo.complex"(%lhs, %rhs) : (tensor<2xf64>, tensor<2xf64>) -> tensor<2xcomplex<f64>>
// %result: [(1.0, 2.0), (3.0, 4.0)]
birleşik
Anlam
Diğer StableHLO işlemlerinden oluşan (oluşturulan) bir işlemi içerir.
inputs
ve composite_attributes
alıp results
üretiyoruz. İlgili içeriği oluşturmak için kullanılan
işlemin anlamı, decomposition
özelliği tarafından uygulanır. İlgili içeriği oluşturmak için kullanılan
composite
işlemi, program değiştirilmeden ayrıştırılmasıyla değiştirilebilir
anlambilim. Ayrıştırmayı satır içine almak aynı
işlem semantiği, custom_call
kullanmayı tercih edin.
version
alanı (varsayılan olarak 0
değerine ayarlanır), bir bileşenin
anlamsal değişikliği vardır.
Girişler
Şirket | Ad | Tür |
---|---|---|
(I1) | inputs |
değişken değer sayısı |
(I2) | name |
string türündeki sabit |
(I3) | composite_attributes |
özellik sözlüğü |
(I4) | decomposition |
string türündeki sabit |
(I5) | version |
si32 türündeki sabit |
Çıkışlar
Ad | Tür |
---|---|
results |
değişken değer sayısı |
Sınırlamalar
- (C1)
is_namespaced_op_name(name)
- (C2)
is_defined_in_parent_scope(decomposition)
- (C3)
types(inputs...) == input_types(decomposition)
- (C4)
types(results...) == output_types(decomposition)
Örnekler
%results = "stablehlo.composite"(%input0, %input1) {
name = "my_namespace.my_op",
composite_attributes = {
my_attribute = "my_value"
},
decomposition = @my_op,
version = 1 : i32
} : (tensor<f32>, tensor<f32>) -> tensor<f32>
birleştirmek
Anlam
inputs
değerini, verilen sırada dimension
boyutu boyunca birleştirir
bağımsız değişkenlerini kullanır ve bir result
tensörü üretir. Daha resmi ifade etmek gerekirse
result[i0, ..., id, ..., iR-1] = inputs[k][i0, ..., kd, ..., iR-1]
, burada:
id = d0 + ... + dk-1 + kd
.d
,dimension
değerine eşit,d0
, ... ised
. boyut boyutudur /inputs
.
Girişler
Şirket | Ad | Tür | Sınırlamalar |
---|---|---|---|
(I1) | inputs |
değişken sayıda tensör veya tensör başına miktarlandırılmış tensör | (C1-C6) |
(I2) | dimension |
si64 türündeki sabit |
(C2), (C4), (C6) |
Çıkışlar
Ad | Tür | Sınırlamalar |
---|---|---|
result |
tensör veya tensör başına miktarlandırılmış tensör | (C5-C6) |
Sınırlamalar
- (C1)
same(element_type(inputs...))
. - (C2)
dim(inputs..., dimension)
hariçsame(shape(inputs...))
. - (C3)
0 < size(inputs)
. - (C4)
0 <= dimension < rank(inputs[0])
- (C5)
element_type(result) = element_type(inputs[0])
- (C6)
shape(result) = shape(inputs[0])
hariç:dim(result, dimension) = dim(inputs[0], dimension) + ...
.
Örnekler
// %input0: [[1, 2], [3, 4], [5, 6]]
// %input1: [[7, 8]]
%result = "stablehlo.concatenate"(%input0, %input1) {
dimension = 0 : i64
} : (tensor<3x2xi64>, tensor<1x2xi64>) -> tensor<4x2xi64>
// %result: [[1, 2], [3, 4], [5, 6], [7, 8]]
sabit
Anlam
Sabit bir value
değerinden bir output
tensörü üretir.
Girişler
Şirket | Ad | Tür | Sınırlamalar |
---|---|---|---|
(I1) | value |
sabit | (C1) |
Çıkışlar
Ad | Tür | Sınırlamalar |
---|---|---|
output |
tensör veya nicel tensör | (C1) |
Sınırlamalar
- (C1)
type(value) = type(output)
.
Örnekler
%output = "stablehlo.constant"() {
value = dense<[[0.0, 1.0], [2.0, 3.0]]> : tensor<2x2xf32>
} : () -> tensor<2x2xf32>
// %output: [[0.0, 1.0], [2.0, 3.0]]
Dönüşüm gerçekleştirme
Anlam
Şu durumda bir öğe türünden diğerine öğe tabanlı dönüşüm gerçekleştirir:
operand
tensörü ve result
tensörü üretir.
boolean-to-any-supported-type dönüşümleri için false
değeri
sıfıra dönüştürülür ve true
değeri bire dönüştürülür. Örneğin,
any-supported-type-to-boolean dönüşümlerini içeren bir dönüşüm yoksa sıfır değeri şuna dönüştürülür:
false
ve sıfır olmayan değerler true
biçimine dönüştürülür. Bunun nasıl yapılacağını
karmaşık türler için geçerlidir.
Tamsayıdan tam sayıya, tamsayıdan kayan noktaya geçiş içeren dönüşümler için veya floating-point-to-floating-point (kayan-nokta-kayan-nokta) hedef türünde temsil edildiğinde, sonuç değeri, söz konusu temsil eder. Aksi takdirde, davranış henüz belli değil (#180).
floating-point-to-integer dönüşüm içeren dönüşümlerde kesirli kısım kısaltılır. Kısaltılmış değer hedef türünde temsil edilemiyorsa davranış TBD'dir (#180).
Karmaşıktan karmaşa içeren dönüşümlerde aynı davranışı izler. floating-point-to-floating-point dönüşümler, gerçek ve hayali parçalar içerir.
complex-to-any-other-type ve any-other-type-to-complex dönüşümleri için kaynak sanal değeri yok sayılır veya hedef sanal değeri sıfırdır. Gerçek parçanın dönüştürülmesinde, kayan nokta dönüşümleridir.
Prensipte, bu işlem, ayrışmayı (deneyim,
nicelenmiş tensörlerden normal tensörlere), nicelleştirme (normalden
tensörlerden miktarlandırılmış tensörlere ve yeniden niceleme (nicelleştirilmiş
tensörler), ancak şu anda bunun için özel
operasyonlarımız var.
İlk kullanım alanı için uniform_dequantize
veuniform_quantize
kullanım alanlarından bahsedeceğiz. Gelecekte bu iki operasyon birleştirilebilir
convert
(#1576) olarak değiştirin.
Girişler
Şirket | Ad | Tür | Sınırlamalar |
---|---|---|---|
(I1) | operand |
Tensor | (C1) |
Çıkışlar
Ad | Tür | Sınırlamalar |
---|---|---|
result |
Tensor | (C1) |
Sınırlamalar
- (C1)
shape(operand) = shape(result)
.
Örnekler
// %operand: [-1, 0, 1]
%result = "stablehlo.convert"(%operand) : (tensor<3xi64>) -> tensor<3xcomplex<f64>>
// %result: [(-1.0, 0.0), (0.0, 0.0), (1.0, 0.0)]
konvolüsyon
Anlam
lhs
pencereleri ile rhs
dilimleri arasındaki nokta ürünlerini hesaplar ve şunları üretir:
result
. Aşağıdaki şemada, result
içindeki öğelerin
Somut bir örnek kullanarak lhs
ve rhs
.
Daha resmî bir şekilde, girişlerin lhs
açısından aşağıdaki şekilde yeniden kavranmasını sağlayabilirsiniz.
lhs
pencerelerini ifade edebilmek için:
lhs_window_dimensions = lhs_shape(dim(lhs, input_batch_dimension), dim(rhs, kernel_spatial_dimensions), dim(lhs, input_feature_dimension))
.lhs_window_strides = lhs_shape(1, window_strides, 1)
.lhs_padding = lhs_shape([0, 0], padding, [0, 0])
.lhs_base_dilations = lhs_shape(1, lhs_dilation, 1)
.lhs_window_dilations = lhs_shape(1, rhs_dilation, 1)
.
Bu yeniden çerçeveleme aşağıdaki yardımcı işlevleri kullanır:
lhs_shape(n, hw, c) = permute([n] + hw + [c], [input_batch_dimension] + input_spatial_dimensions + [input_feature_dimension])
.result_shape(n1, hw, c1) = permute([n1] + hw + [c1], [output_batch_dimension] + output_spatial_dimensions + [output_feature_dimension])
.permute([j0, j1, ..., jR-1], permutation) = [i0, i1, ..., iR-1]
buradaj[d] = i[permutation[d]]
.
feature_group_count = 1
ve batch_group_count = 1
ise herkes için
index_space(dim(result, output_spatial_dimensions...))
konumunda output_spatial_index
,
result[result_shape(:, output_spatial_index, :)] = dot_product
burada:
padding_value = constant(0, element_type(lhs))
.padded_lhs = pad(lhs, padding_value, lhs_padding[:, 0], lhs_padding[:, 1], lhs_base_dilations - 1)
.lhs_window_start = lhs_shape(0, output_spatial_index, 0) * lhs_window_strides
.lhs_window = slice(padded_lhs, lhs_window_start, lhs_window_start + lhs_window_dimensions, lhs_window_dilations)
.reversed_lhs_window = reverse(lhs_window, [input_spatial_dimensions[dim] for dim in range(size(window_reversal)) if window_reversal[dim] = true])
Bu özellik kullanılmadığından ileride uygulamayı kaldırmayı planlıyoruz. bu (#1181).dot_product = dot_general(reversed_lhs_window, rhs, lhs_batching_dimensions=[], lhs_contracting_dimensions=input_spatial_dimensions + [input_feature_dimension], rhs_batching_dimensions=[], rhs_contracting_dimensions=kernel_spatial_dimensions + [kernel_input_feature_dimension])
.
Eğer feature_group_count > 1
:
lhses = split(lhs, feature_group_count, input_feature_dimension)
.rhses = split(rhs, feature_group_count, kernel_output_feature_dimension)
.results... = convolution(lhses..., rhses..., ..., feature_group_count=1, ...)
.result = concatenate(results, output_feature_dimension)
.
Eğer batch_group_count > 1
:
lhses = split(lhs, batch_group_count, input_batch_dimension)
.rhses = split(rhs, batch_group_count, kernel_output_feature_dimension)
.results... = convolution(lhses..., rhses..., ..., batch_group_count=1, ...)
.result = concatenate(results, output_feature_dimension)
Miktarı ölçülmüş türlerde, dequantize_op_quantize(
lambda lhs, rhs: convolution(lhs, rhs, window_strides, padding,
lhs_dilation, rhs_dilation, window_reversal, input_batch_dimension,
input_feature_dimension, input_spatial_dimensions,
kernel_input_feature_dimension, kernel_output_feature_dimension,
kernel_spatial_dimensions, output_batch_dimension,
output_feature_dimension, output_spatial_dimensions,
feature_group_count, batch_group_count, precision_config), lhs, rhs,
type(result))
gerçekleştirir.
Karma miktarlandırılmış türlerde hybrid_dequantize_then_op(
lambda lhs, rhs: convolution(lhs, rhs, window_strides, padding,
lhs_dilation, rhs_dilation, window_reversal, input_batch_dimension,
input_feature_dimension, input_spatial_dimensions,
kernel_input_feature_dimension, kernel_output_feature_dimension,
kernel_spatial_dimensions, output_batch_dimension,
output_feature_dimension, output_spatial_dimensions,
feature_group_count, batch_group_count, precision_config), lhs, rhs)
performans gösterir.
Girişler
Şirket | Ad | Tür | Sınırlamalar |
---|---|---|---|
(I1) | lhs |
tensör veya tensör başına miktarlandırılmış tensör | (C1), (C10-C11), (C14) (C25), (C27-C28), (C31-C32), (C34) |
(I2) | rhs |
tensör veya nicel tensör | (C1), (C14-C16), (C25), (C27-C29), (C31-C34) |
(I3) | window_strides |
si64 türünde 1 boyutlu tensör sabiti |
(C2-C3), (C25) |
(I4) | padding |
si64 türünde 2 boyutlu tensör sabiti |
(C4), (C25) |
(I5) | lhs_dilation |
si64 türünde 1 boyutlu tensör sabiti |
(C5-C6), (C25) |
(I6) | rhs_dilation |
si64 türünde 1 boyutlu tensör sabiti |
(C7-C8), (C25) |
(I7) | window_reversal |
i1 türünde 1 boyutlu tensör sabiti |
(C9) |
(I8) | input_batch_dimension |
si64 türündeki sabit |
(C10), (C13), (C25) |
(I9) | input_feature_dimension |
si64 türündeki sabit |
(C11), (C13-C14) |
(I10) | input_spatial_dimensions |
si64 türünde 1 boyutlu tensör sabiti |
(C12), (C13), (C25) |
(I11) | kernel_input_feature_dimension |
si64 türündeki sabit |
(C14), (C18) |
(I12) | kernel_output_feature_dimension |
si64 türündeki sabit |
(C15-C16), (C18), (C25), (C29) |
(I13) | kernel_spatial_dimensions |
si64 türünde 1 boyutlu tensör sabiti |
(C17-C18), (C25) |
(I14) | output_batch_dimension |
si64 türündeki sabit |
(C20), (C25) |
(I15) | output_feature_dimension |
si64 türündeki sabit |
(C20), (C25), (C30) |
(I16) | output_spatial_dimensions |
si64 türünde 1 boyutlu tensör sabiti |
(C19-C20), (C25) |
(I17) | feature_group_count |
si64 türündeki sabit |
(C11), (C14), (C16), (C21), (C23) |
(I18) | batch_group_count |
si64 türündeki sabit |
(C10), (C15), (C22), (C23), (C25) |
(I19) | precision_config |
DEFAULT , HIGH ve HIGHEST sıralamalarının değişken sayısı |
(C24) |
Çıkışlar
Ad | Tür | Sınırlamalar |
---|---|---|
result |
tensör veya nicel tensör | (C25-C28), (C30), (C32-34) |
Sınırlamalar
- (C1)
N = rank(lhs) = rank(rhs)
. - (C2)
size(window_strides) = N - 2
. - (C3)
0 < window_strides
. - (C4)
shape(padding) = [N - 2, 2]
- (C5)
size(lhs_dilation) = N - 2
- (C6)
0 < lhs_dilation
. - (C7)
size(rhs_dilation) = N - 2
. - (C8)
0 < rhs_dilation
- (C9)
size(window_reversal) = N - 2
. - (C10)
dim(lhs, input_batch_dimension) % batch_group_count = 0
- (C11)
dim(lhs, input_feature_dimension) % feature_group_count = 0
- (C12)
size(input_spatial_dimensions) = N - 2
- (C13)
input_dimensions = [input_batch_dimension] + input_spatial_dimensions + [input_feature_dimension]
ile ilgili:is_unique(input_dimensions)
.0 <= input_dimensions < N
.
- (C14)
dim(rhs, kernel_input_feature_dimension) = dim(lhs, input_feature_dimension) / feature_group_count
- (C15)
dim(rhs, kernel_output_feature_dimension) % batch_group_count = 0
- (C16)
dim(rhs, kernel_output_feature_dimension) % feature_group_count = 0
- (C17)
size(kernel_spatial_dimensions) = N - 2
- (C18)
kernel_dimensions = kernel_spatial_dimensions + [kernel_input_feature_dimension] + [kernel_output_feature_dimension]
ile ilgili:is_unique(kernel_dimensions)
.0 <= kernel_dimensions < N
.
- (C19)
size(output_spatial_dimensions) = N - 2
- (C20)
output_dimensions = [output_batch_dimension] + output_spatial_dimensions + [output_feature_dimension]
ile ilgili:is_unique(output_dimensions)
.0 <= output_dimensions < N
.
- (C21)
0 < feature_group_count
- (C22)
0 < batch_group_count
- (C23)
feature_group_count = 1 or batch_group_count = 1
- (C24)
size(precision_config) = 2
- (C25)
dim(result, result_dim)
şu şekilde tanımlanır:result_dim = output_batch_dimension
isedim(lhs, input_batch_dimension) / batch_group_count
.result_dim = output_feature_dimension
isedim(rhs, kernel_output_feature_dimension)
.- Aksi takdirde, şu koşullarda
num_windows
: output_spatial_dimensions[spatial_dim] = result_dim
.lhs_dim = input_spatial_dimensions[spatial_dim]
.rhs_dim = kernel_spatial_dimensions[spatial_dim]
.dilated_input_shape[lhs_dim] = dim(lhs, lhs_dim) = 0 ? 0 : (dim(lhs, lhs_dim) - 1) * lhs_dilation[spatial_dim] + 1
.padded_input_shape[lhs_dim] = padding[spatial_dim, 0] + dilated_input_shape[lhs_dim] + padding[spatial_dim, 1]
.dilated_window_shape[lhs_dim] = dim(rhs, rhs_dim) = 0 ? 0 : (dim(rhs, rhs_dim) - 1) * rhs_dilation[spatial_dim] + 1
.is_empty_window[lhs_dim] = padded_input_shape[lhs_dim] = 0 || dilated_window_shape[lhs_dim] > padded_input_shape[lhs_dim]
.num_windows = is_empty_window[lhs_dim] ? 0 : floor((padded_input_shape[lhs_dim] - dilated_window_shape[lhs_dim]) / window_strides[spatial_dim]) + 1
.
- (C26)
rank(result) = N
- İşlemde miktarlandırılmamış tensörler kullanılıyorsa:
- (C27)
element_type(lhs) = element_type(rhs) = element_type(result)
- (C27)
- İşlemde nicel tensörler kullanılıyorsa:
- (C28)
is_quantized(lhs) = is_quantized(result) and is_quantized(rhs)
- (C29)
is_per_axis_quantized(rhs)
ise ardındanquantization_dimension(rhs) = kernel_output_feature_dimension
. - (C30)
is_per_axis_quantized(result)
isequantization_dimension(result) = output_feature_dimension
. - Eğer
is_quantized(lhs)
: - (C31)
storage_type(lhs) = storage_type(rhs)
- (C32)
expressed_type(lhs) = expressed_type(rhs) = expressed_type(result)
- (C33)
is_per_tensor_quantized(rhs)
iseis_per_tensor_quantized(result)
. - Eğer
!is_quantized(lhs)
: - (C34)
element_type(lhs) = expressed_type(rhs) = element_type(result)
.
- (C28)
Örnekler
// %lhs: [[
// [
// [1], [2], [5], [6]
// ],
// [
// [3], [4], [7], [8]
// ],
// [
// [10], [11], [14], [15]
// ],
// [
// [12], [13], [16], [17]
// ]
// ]]
//
// %rhs: [
// [[[1]], [[1]], [[1]]],
// [[[1]], [[1]], [[1]]],
// [[[1]], [[1]], [[1]]]
// ]
%result = "stablehlo.convolution"(%lhs, %rhs) {
window_strides = array<i64: 4, 4>,
padding = dense<0> : tensor<2x2xi64>,
lhs_dilation = array<i64: 2, 2>,
rhs_dilation = array<i64: 1, 1>,
window_reversal = array<i1: false, false>,
// In the StableHLO dialect, dimension numbers are encoded via:
// `[<input dimensions>]x[<kernel dimensions>]->[output dimensions]`.
// "b" is batch dimension, "f" is feature dimension,
// "i" is input feature dimension, "o" is output feature dimension,
// "0/1/etc" are spatial dimensions.
dimension_numbers = #stablehlo.conv<[b, 0, 1, f]x[0, 1, i, o]->[b, 0, 1, f]>,
batch_group_count = 1 : i64,
feature_group_count = 1 : i64,
precision_config = [#stablehlo<precision DEFAULT>, #stablehlo<precision DEFAULT>]
} : (tensor<1x4x4x1xi64>, tensor<3x3x1x1xi64>) -> tensor<1x2x2x1xi64>
// %result: [[
// [[10], [26]],
// [[46], [62]]
// ]]
kosinüs
Anlam
operand
tensörü üzerinde element düzeyinde kosinüs işlemi gerçekleştirir ve bir
result
tensörü. Öğe türüne bağlı olarak aşağıdakiler gerçekleşir:
- Kayan reklamlar için: IEEE-754'ten
cos
. - Karmaşık sayılar için: karmaşık kosinüs.
- Miktarlanmış türler için:
dequantize_op_quantize(cosine, operand, type(result))
.
Girişler
Şirket | Ad | Tür | Sınırlamalar |
---|---|---|---|
(I1) | operand |
kayan nokta veya karmaşık tür ya da tensör başına miktarlandırılmış tensör tensörü | (C1) |
Çıkışlar
Ad | Tür | Sınırlamalar |
---|---|---|
result |
kayan nokta veya karmaşık tür ya da tensör başına miktarlandırılmış tensör tensörü | (C1) |
Sınırlamalar
- (C1)
baseline_type(operand) = baseline_type(result)
.
Örnekler
// %operand: [
// [0.0, 1.57079632], // [0, pi/2]
// [3.14159265, 4.71238898] // [pi, 3pi/2]
// ]
%result = "stablehlo.cosine"(%operand) : (tensor<2x2xf32>) -> tensor<2x2xf32>
// %result: [[1.0, 0.0], [-1.0, 0.0]]
count_leading_zeros
Anlam
operand
hücresinin başındaki sıfır bit sayısını öğe bazında sayar
ve bir result
tensörü üretir.
Girişler
Şirket | Ad | Tür | Sınırlamalar |
---|---|---|---|
(I1) | operand |
tam sayı türündeki tensör | (C1) |
Çıkışlar
Ad | Tür | Sınırlamalar |
---|---|---|
result |
tam sayı türündeki tensör | (C1) |
Sınırlamalar
- (C1)
type(operand) = type(result)
.
Örnekler
// %operand: [[0, 1], [128, -1]]
%result = "stablehlo.count_leading_zeros"(%operand) : (tensor<2x2xi64>) -> tensor<2x2xi64>
// %result: [[64, 63], [56, 0]]
custom_call
Anlam
Aşağıdaki işlemler için gereken uygulama tanımlı call_target_name
işlemini içerir:
inputs
ve called_computations
ile results
üretir. has_side_effect
,
backend_config
ve api_version
, ek bilgi sağlamak için kullanılabilir.
meta verilerdir.
Şu anda bu işlem oldukça dağınık bir meta verileridir. Meta veriler XLA derleyicisi olur. Gelecekte bu meta verileri birleştirmeyi planlıyoruz. (#741).
Girişler
Şirket | Ad | Tür |
---|---|---|
(I1) | inputs |
değişken değer sayısı |
(I2) | call_target_name |
string türündeki sabit |
(I3) | has_side_effect |
i1 türündeki sabit |
(I4) | backend_config |
string türünün sabiti veya özellik sözlüğü |
(I5) | api_version |
si32 türündeki sabit |
(I6) | called_computations |
string türündeki değişken sabit sayı |
Çıkışlar
Ad | Tür |
---|---|
results |
değişken değer sayısı |
Örnekler
%results = "stablehlo.custom_call"(%input0) {
call_target_name = "foo",
has_side_effect = false,
backend_config = {bar = 42 : i32},
api_version = 4 : i32,
called_computations = [@foo]
} : (tensor<f64>) -> tensor<f64>
bölü
Anlam
lhs
bölünme ve bölünen rhs
tensörlerini element düzeyinde böler ve
bir result
tensörü üretir. Öğe türüne bağlı olarak aşağıdakiler gerçekleşir:
- Tam sayılar için: herhangi bir sayıdaki cebirsel bölümü oluşturan tam sayı bölme kısmen silindi.
- Kayan reklamlar için: IEEE-754'ten
division
. - Karmaşık sayılar için: karmaşık bölme.
- Ölçülen türler için:
dequantize_op_quantize(divide, lhs, rhs, type(result))
.
Girişler
Şirket | Ad | Tür | Sınırlamalar |
---|---|---|---|
(I1) | lhs |
tam sayı, kayan nokta veya karmaşık tür ya da tensör başına miktarlandırılmış tensör tensörü | (C1) |
(I2) | rhs |
tam sayı, kayan nokta veya karmaşık tür ya da tensör başına miktarlandırılmış tensör tensörü | (C1) |
Çıkışlar
Ad | Tür | Sınırlamalar |
---|---|---|
result |
tam sayı, kayan nokta veya karmaşık tür ya da tensör başına miktarlandırılmış tensör tensörü | (C1) |
Sınırlamalar
- (C1)
baseline_type(lhs) = baseline_type(rhs) = baseline_type(result)
.
Örnekler
// %lhs: [17.1, -17.1, 17.1, -17.1]
// %rhs: [3.0, 3.0, -3.0, -3.0]
%result = "stablehlo.divide"(%lhs, %rhs) : (tensor<4xf32>, tensor<4xf32>) -> tensor<4xf32>
// %result: [5.66666651, -5.66666651, -5.66666651, 5.66666651]
dot_general
Anlam
lhs
dilimleri ile rhs
dilimleri arasındaki nokta ürünlerini hesaplar ve
result
tensörü.
Daha resmi olarak, result[result_index] = dot_product
, burada:
lhs_result_dimensions = [d for d in axes(lhs) and d not in lhs_batching_dimensions and d not in lhs_contracting_dimensions]
.rhs_result_dimensions = [d for d in axes(rhs) and d not in rhs_batching_dimensions and d not in rhs_contracting_dimensions]
.result_batching_index + result_lhs_index + result_rhs_index = result_index
. buradasize(result_batching_index) = size(lhs_batching_dimensions)
,size(result_lhs_index) = size(lhs_result_dimensions)
vesize(result_rhs_index) = size(rhs_result_dimensions)
.transposed_lhs = transpose(lhs, lhs_batching_dimensions + lhs_result_dimensions + lhs_contracting_dimensions)
.transposed_lhs_slice = slice(transposed_lhs, result_batching_index + result_lhs_index + [:, ..., :])
.reshaped_lhs_slice = reshape(transposed_lhs_slice, dims(lhs, lhs_contracting_dimensions))
.transposed_rhs = transpose(rhs, rhs_batching_dimensions + rhs_result_dimensions + rhs_contracting_dimensions)
.transposed_rhs_slice = slice(transposed_rhs, result_batching_index + result_rhs_index + [:, ..., :])
.reshaped_rhs_slice = reshape(transposed_rhs_slice, dims(rhs, rhs_contracting_dimensions))
.dot_product = reduce( inputs=[multiply(reshaped_lhs_slice, reshaped_rhs_slice)], init_values=[constant(0, element_type(result))], dimensions=range(size(lhs_contracting_dimensions)), body=lambda x, y: add(x, y))
Miktarı ölçülmüş türlerde, dequantize_op_quantize(
lambda lhs, rhs: dot_general(lhs, rhs, lhs_batching_dimensions,
rhs_batching_dimensions, lhs_contracting_dimensions,
rhs_contracting_dimensions, precision_config), lhs, rhs, type(result))
gerçekleştirir.
Karma miktarlandırılmış türlerde hybrid_dequantize_then_op(
lambda lhs, rhs: dot_general(lhs, rhs, lhs_batching_dimensions,
rhs_batching_dimensions, lhs_contracting_dimensions,
rhs_contracting_dimensions, precision_config), lhs, rhs)
performans gösterir.
precision_config
, veriler için hız ile doğruluk arasındaki dengeyi kontrol eder
hesaplamalarına yardımcı olur. Bu, aşağıdakilerden biri olabilir (
bu sıralama değerlerinin anlamı eksik olsa da,
bu konuyu ele almayı
#755):
DEFAULT
: En hızlı hesaplama, ancak orijinal sayı.HIGH
: Hesaplama daha yavaştır ancak orijinal sayı.HIGHEST
: En yavaş hesaplama, ancak hedefe en doğru tahmin orijinal sayı.
DotAlgorithm
, aşağıdakileri uygulamak için kullanılan algoritmanın ana özelliklerini tanımlar:
nokta işlemidir. Bu işlem, hassasiyeti de tanımlar. Algoritma
alanları ayarlanırsa precision_config
, DEFAULT
olmalıdır. DotAlgorithms
.
varsayılan parametreler uygulandığından, varsayılan bir değere sahip değildir
tanımlanmıştır. Bu nedenle, tüm nokta algoritması alanları None
olarak ayarlanabilir
boş nokta algoritması bulunur. Bunun yerine, precision_config
değeri kullanılır.
DotAlgorithm
alanları şunları içerir:
lhs_precision_type
verhs_precision_type
, LHS ve LHS ile İşlemin sağ tarafı yuvarlanır. Hassasiyet türleri giriş ve çıkışların depolama türleri.accumulation_type
, toplama için kullanılan hassasiyet.lhs_component_count
,rhs_component_count
venum_primitive_operations
ve/veya RHS'yi ayıran bir algoritma yaptığımızda uygulanır. birden fazla bileşene sahip ve birden çok "temel" öğe bu satırlarda genellikle daha yüksek bir hassasiyet emülasyonu yapmak için (ör. Daha Yüksek Hassasiyetli Hesaplamalar İçin bfloat16 Yapay Zeka Veri Türünden Yararlanma: bf16_6x tf32_3x vb.) Ayrıştırılması olmayan algoritmalar için bu değerler1
olarak ayarlanmalıdır.- Toplama işleminin daha düşük kesinlikte olup olmadığını belirtmek için
allow_imprecise_accumulation
bazı adımlarda izin verilir (ör.CUBLASLT_MATMUL_DESC_FAST_ACCUM
).
Örnek DotAlgorithm
özellikleri:
// Inputs are casted to tf32, and then accumulated in f32:
{lhs_precision_type = tf32,
rhs_precision_type = tf32,
accumulation_type = f32,
lhs_component_count = 1,
rhs_component_count = 1,
num_primitive_operations = 1,
allow_imprecise_accumulation = false}
// bf16_6x: each input is decomposed to 3 bf16 components, then 6 dot operations are done on those components, and the result is accumulated in f32.
{lhs_precision_type = bf16,
rhs_precision_type = bf16,
accumulation_type = f32,
lhs_component_count = 3,
rhs_component_count = 3,
num_primitive_operations = 6,
allow_imprecise_accumulation = false}
// Inputs are (casted to) f8e5m2, and we accumulate in f32, but for some steps we may accumulate in lower precision.
{lhs_precision_type = f8e5m2,
rhs_precision_type = f8e5m2,
accumulation_type = f32,
lhs_component_count = 1,
rhs_component_count = 1,
num_primitive_operations = 1,
allow_imprecise_accumulation = true}
Hangi kombinasyonların desteklendiğine karar vermek uygulamalara bağlıdır. İçinde her algoritmanın tek bir algoritmada desteklendiği garanti edilmez. hızlandırıcı türünü ayarlayın. Belirli bir algoritma geri dönmek yerine bir hata alternatifidir. StableHLO doğrulaması mümkün olan en iyi doğrulamayı sağlar. herhangi bir donanımda desteklenmediği bilinen algoritmaları önleme amaçlıdır.
Bkz. xla_data.proto > Algorithm
. 2483 numaralı bilet, bir olası satış yaratma planını
algoritmalarla ilgili merkezi bir belge hazırladık.
Girişler
Şirket | Ad | Tür | Sınırlamalar |
---|---|---|---|
(I1) | lhs |
tensör veya tensör başına miktarlandırılmış tensör | (C5-C6), (C9-C10), (C12-C14), (C17-C18), (C20) |
(I2) | rhs |
tensör veya nicel tensör | (C7-C10), (C12-C20) |
(I3) | lhs_batching_dimensions |
si64 türünde 1 boyutlu tensör sabiti |
(C1), (C3), (C5), (C9), (C12) |
(I4) | rhs_batching_dimensions |
si64 türünde 1 boyutlu tensör sabiti |
(C1), (C4), (C7), (C9) |
(I5) | lhs_contracting_dimensions |
si64 türünde 1 boyutlu tensör sabiti |
(C2), (C3), (C6), (C10) |
(I6) | rhs_contracting_dimensions |
si64 türünde 1 boyutlu tensör sabiti |
(C2), (C4), (C8), (C10), (C16) |
(I7) | precision_config |
DEFAULT , HIGH ve HIGHEST sıralamalarının değişken sayısı |
(C11), (C21) |
(I8) | lhs_precision_type |
floatType veya Tensorfloat32 | (C21) |
(I9) | rhs_precision_type |
floatType veya Tensorfloat32 | (C21) |
(I10) | accumulation_type |
floatType veya Tensorfloat32 | (C21) |
(I11) | lhs_component_count |
si32 türündeki sabit |
(C21), (C22) |
(I12) | rhs_component_count |
si32 türündeki sabit |
(C21), (C23) |
(I13) | num_primitive_operations |
si32 türündeki sabit |
(C21), (C24) |
(I14) | allow_imprecise_accumulation |
bool türündeki sabit |
(C21) |
Çıkışlar
Ad | Tür | Sınırlamalar |
---|---|---|
result |
tensör veya nicel tensör | (C12), (C14), (C18-C20) |
Sınırlamalar
- (C1)
size(lhs_batching_dimensions) = size(rhs_batching_dimensions)
. - (C2)
size(lhs_contracting_dimensions) = size(rhs_contracting_dimensions)
. - (C3)
is_unique(lhs_batching_dimensions + lhs_contracting_dimensions)
. - (C4)
is_unique(rhs_batching_dimensions + rhs_contracting_dimensions)
- (C5)
0 <= lhs_batching_dimensions < rank(lhs)
- (C6)
0 <= lhs_contracting_dimensions < rank(lhs)
. - (C7)
0 <= rhs_batching_dimensions < rank(rhs)
. - (C8)
0 <= rhs_contracting_dimensions < rank(rhs)
- (C9)
dim(lhs, lhs_batching_dimensions...) = dim(rhs, rhs_batching_dimensions...)
. - (C10)
dim(lhs, lhs_contracting_dimensions...) = dim(rhs, rhs_contracting_dimensions...)
- (C11)
size(precision_config) = 2
- (C12)
shape(result) = dim(lhs, lhs_batching_dimensions) + dim(lhs, lhs_result_dimensions) + dim(rhs, rhs_result_dimensions)
- İşlemde miktarlandırılmamış tensörler kullanılıyorsa:
- (C13)
element_type(lhs) = element_type(rhs)
- (C13)
- İşlemde nicel tensörler kullanılıyorsa:
- (C14)
is_quantized(lhs) = is_quantized(result) and is_quantized(rhs)
- (C15)
zero_points(rhs) = 0
- (C16)
is_per_axis_quantized(rhs)
isequantization_dimension(rhs)
,rhs_contracting_dimensions
içinde yer almıyor. - Eğer
is_quantized(lhs)
: - (C17)
storage_type(lhs) = storage_type(rhs)
- (C18)
expressed_type(lhs) = expressed_type(rhs) = expressed_type(result)
- (C19)
is_per_tensor_quantized(rhs)
iseis_per_tensor_quantized(result)
. - Eğer
!is_quantized(lhs)
: - (C20)
element_type(lhs) = expressed_type(rhs) = element_type(result)
.
- (C14)
- Eğer
!is_empty_algorithm(lhs_precision_type, rhs_precision_type, accumulation_type, lhs_component_count, rhs_component_count, num_primitive_operations allow_imprecise_accumulation)
:- (C21)
precision_config... = DEFAULT
- (C22)
0 < lhs_component_count
- (C23)
0 < rhs_component_count
- (C24)
0 < num_primitive_operations
- (C21)
Örnekler
// %lhs: [
// [[1, 2],
// [3, 4]],
// [[5, 6],
// [7, 8]]
// ]
// %rhs: [
// [[1, 0],
// [0, 1]],
// [[1, 0],
// [0, 1]]
// ]
%result = "stablehlo.dot_general"(%lhs, %rhs) {
dot_dimension_numbers = #stablehlo.dot<
lhs_batching_dimensions = [0],
rhs_batching_dimensions = [0],
lhs_contracting_dimensions = [2],
rhs_contracting_dimensions = [1]
>,
precision_config = [#stablehlo<precision DEFAULT>, #stablehlo<precision DEFAULT>],
algorithm = #stablehlo.dot_algorithm<
lhs_precision_type = tf32,
rhs_precision_type = tf32,
accumulation_type = f32,
lhs_component_count = 1,
rhs_component_count = 1,
num_primitive_operations = 1,
allow_imprecise_accumulation = false
>
} : (tensor<2x2x2xi64>, tensor<2x2x2xi64>) -> tensor<2x2x2xi64>
// %result: [
// [[1, 2],
// [3, 4]],
// [[5, 6],
// [7, 8]]
// ]
dynamic_broadcast_in_dim
Anlam
Bu işlem işlevsel olarak
broadcast_in_dim
op, ancak sonuç şekli output_dimensions
aracılığıyla dinamik olarak belirtilir.
İşlemde isteğe bağlı known_expanding_dimensions
, known_non_expanding_dimensions
özellikleri de kabul edilir.
, boyutların genişleme davranışı hakkındaki statik bilgiyi ifade etmek için kullanılır.
Belirtilmezse tüm boyutların genişlemiş olabileceği varsayılır.
Girişler
Şirket | Ad | Tür | Sınırlamalar |
---|---|---|---|
(I1) | operand |
tensör veya nicel tensör | (C1-C2), (C5-C6), (C9) |
(I2) | output_dimensions |
Tam sayı türünde 1 boyutlu tensör | (C7) |
(I3) | broadcast_dimensions |
Tam sayı türünde 1 boyutlu sabit tensör | (C2-C6) |
(I4) | known_expanding_dimensions |
Tam sayı türünde 1 boyutlu sabit tensör | (C8-C9) |
(I5) | known_non_expanding_dimensions |
Tam sayı türünde 1 boyutlu sabit tensör | (C8-C9) |
Çıkışlar
Ad | Tür | Sınırlamalar |
---|---|---|
result |
tensör veya nicel tensör | (C1), (C3), (C5-C7) |
Sınırlamalar
- (C1)
element_type(result)
değerini sağlayan:!is_per_axis_quantized(operand)
iseelement_type(operand)
.element_type(operand)
(buquantization_dimension(operand)
hariç)scales(operand)
vezero_points(operand)
şundan farklı olabilir:quantization_dimension(result)
,scales(result)
vezero_points(result)
resp., aksi takdirde.
- (C2)
size(broadcast_dimensions) = rank(operand)
. - (C3)
0 <= broadcast_dimensions < rank(result)
. - (C4)
is_unique(broadcast_dimensions)
- (C5)
axes(operand)
bünyesindeki tümd
için:dim(operand, d) = 1
veyadim(operand, d) = dim(result, broadcast_dimensions[d])
.
- (C6)
is_per_axis_quantized(result)
ise:quantization_dimension(result) = broadcast_dimensions[quantization_dimension(operand)]
.dim(operand, quantization_dimension(operand)) = 1
ise,scales(result)[i] = scales(operand)[0] and zero_points(result)[i] = zero_points(operand)[0] for i in range(dim(result, quantization_dimension(result)))
.
- (C7)
size(output_dimensions) = rank(result)
. - (C8)
is_unique(known_expanding_dimensions + known_non_expanding_dimensions)
- (C9)
0 <= known_expanding_dimensions < rank(operand)
. - (C10)
0 <= known_non_expanding_dimensions < rank(operand)
Örnekler
// %operand: [
// [1, 2, 3]
// ]
%operand = stablehlo.constant dense<[[1, 2, 3]]> : tensor<1x3xi64>
%output_dimensions = stablehlo.constant dense<[2, 3, 2]> : tensor<3xi64>
%result = "stablehlo.dynamic_broadcast_in_dim"(%operand, %output_dimensions) {
broadcast_dimensions = array<i64: 2, 1>,
known_expanding_dimensions = array<i64: 0>,
known_non_expanding_dimensions = array<i64: 1>
} : (tensor<1x3xi64>, tensor<3xi64>) -> tensor<2x3x2xi64>
// %result: [
// [
// [1, 1],
// [2, 2],
// [3, 3]
// ],
// [
// [1, 1],
// [2, 2],
// [3, 3]
// ]
// ]
dynamic_conv
Anlam
Bu işlem işlevsel olarak
konvolüsyon
ancak dolgu padding
aracılığıyla dinamik olarak belirtilir.
Girişler
Şirket | Ad | Tür | Sınırlamalar |
---|---|---|---|
(I1) | lhs |
tensör veya tensör başına miktarlandırılmış tensör | (C1), (C10-C11), (C14) (C25), (C26-C27), (C30-C31), (C33) |
(I2) | rhs |
tensör veya nicel tensör | (C1), (C14-C16), (C26-C28), (C30-C33) |
(I3) | padding |
Tam sayı türünde 2 boyutlu tensör | (C4) |
(I4) | window_strides |
si64 türünde 1 boyutlu tensör sabiti |
(C2-C3) |
(I5) | lhs_dilation |
si64 türünde 1 boyutlu tensör sabiti |
(C5-C6) |
(I6) | rhs_dilation |
si64 türünde 1 boyutlu tensör sabiti |
(C7-C8) |
(I7) | window_reversal |
i1 türünde 1 boyutlu tensör sabiti |
(C9) |
(I8) | input_batch_dimension |
si64 türündeki sabit |
(C10), (C13) |
(I9) | input_feature_dimension |
si64 türündeki sabit |
(C11), (C13-C14) |
(I10) | input_spatial_dimensions |
si64 türünde 1 boyutlu tensör sabiti |
(C12), (C13) |
(I11) | kernel_input_feature_dimension |
si64 türündeki sabit |
(C14), (C18) |
(I12) | kernel_output_feature_dimension |
si64 türündeki sabit |
(C15-C16), (C18), (C28) |
(I13) | kernel_spatial_dimensions |
si64 türünde 1 boyutlu tensör sabiti |
(C17-C18) |
(I14) | output_batch_dimension |
si64 türündeki sabit |
(C20) |
(I15) | output_feature_dimension |
si64 türündeki sabit |
(C20), (C29) |
(I16) | output_spatial_dimensions |
si64 türünde 1 boyutlu tensör sabiti |
(C19-C20) |
(I17) | feature_group_count |
si64 türündeki sabit |
(C11), (C14), (C16), (C21), (C23) |
(I18) | batch_group_count |
si64 türündeki sabit |
(C10), (C15), (C22), (C23) |
(I19) | precision_config |
DEFAULT , HIGH ve HIGHEST sıralamalarının değişken sayısı |
(C24) |
Çıkışlar
Ad | Tür | Sınırlamalar |
---|---|---|
result |
tensör veya nicel tensör | (C25-C27), (C29), (C31-C33) |
Sınırlamalar
- (C1)
N = rank(lhs) = rank(rhs)
. - (C2)
size(window_strides) = N - 2
. - (C3)
0 < window_strides
. - (C4)
shape(padding) = [N - 2, 2]
- (C5)
size(lhs_dilation) = N - 2
- (C6)
0 < lhs_dilation
. - (C7)
size(rhs_dilation) = N - 2
. - (C8)
0 < rhs_dilation
- (C9)
size(window_reversal) = N - 2
. - (C10)
dim(lhs, input_batch_dimension) % batch_group_count = 0
- (C11)
dim(lhs, input_feature_dimension) % feature_group_count = 0
- (C12)
size(input_spatial_dimensions) = N - 2
- (C13)
input_dimensions = [input_batch_dimension] + input_spatial_dimensions + [input_feature_dimension]
ile ilgili:is_unique(input_dimensions)
.0 <= input_dimensions < N
.
- (C14)
dim(rhs, kernel_input_feature_dimension) = dim(lhs, input_feature_dimension) / feature_group_count
- (C15)
dim(rhs, kernel_output_feature_dimension) % batch_group_count = 0
- (C16)
dim(rhs, kernel_output_feature_dimension) % feature_group_count = 0
- (C17)
size(kernel_spatial_dimensions) = N - 2
- (C18)
kernel_dimensions = kernel_spatial_dimensions + [kernel_input_feature_dimension] + [kernel_output_feature_dimension]
ile ilgili:is_unique(kernel_dimensions)
.0 <= kernel_dimensions < N
.
- (C19)
size(output_spatial_dimensions) = N - 2
- (C20)
output_dimensions = [output_batch_dimension] + output_spatial_dimensions + [output_feature_dimension]
ile ilgili:is_unique(output_dimensions)
.0 <= output_dimensions < N
.
- (C21)
0 < feature_group_count
- (C22)
0 < batch_group_count
- (C23)
feature_group_count = 1 or batch_group_count = 1
- (C24)
size(precision_config) = 2
- (C25)
dim(result, result_dim)
şu şekilde tanımlanır:result_dim = output_batch_dimension
isedim(lhs, input_batch_dimension) / batch_group_count
.result_dim = output_feature_dimension
isedim(rhs, kernel_output_feature_dimension)
.- Aksi takdirde, şu koşullarda
num_windows
: output_spatial_dimensions[spatial_dim] = result_dim
.lhs_dim = input_spatial_dimensions[spatial_dim]
.rhs_dim = kernel_spatial_dimensions[spatial_dim]
.dilated_input_shape[lhs_dim] = dim(lhs, lhs_dim) = 0 ? 0 : (dim(lhs, lhs_dim) - 1) * lhs_dilation[spatial_dim] + 1
.padded_input_shape[lhs_dim] = padding[spatial_dim, 0] + dilated_input_shape[lhs_dim] + padding[spatial_dim, 1]
.dilated_window_shape[lhs_dim] = dim(rhs, rhs_dim) = 0 ? 0 : (dim(rhs, rhs_dim) - 1) * rhs_dilation[spatial_dim] + 1
.is_empty_window[lhs_dim] = padded_input_shape[lhs_dim] = 0 || dilated_window_shape[lhs_dim] > padded_input_shape[lhs_dim]
.num_windows = is_empty_window[lhs_dim] ? 0 : floor((padded_input_shape[lhs_dim] - dilated_window_shape[lhs_dim]) / window_strides[spatial_dim]) + 1
.
- (C26)
rank(result) = N
- İşlemde miktarlandırılmamış tensörler kullanılıyorsa:
- (C27)
element_type(lhs) = element_type(rhs) = element_type(result)
- (C27)
- İşlemde nicel tensörler kullanılıyorsa:
- (C28)
is_quantized(lhs) = is_quantized(result) and is_quantized(rhs)
- (C29)
is_per_axis_quantized(rhs)
ise ardındanquantization_dimension(rhs) = kernel_output_feature_dimension
. - (C30)
is_per_axis_quantized(result)
isequantization_dimension(result) = output_feature_dimension
. - Eğer
is_quantized(lhs)
: - (C31)
storage_type(lhs) = storage_type(rhs)
- (C32)
expressed_type(lhs) = expressed_type(rhs) = expressed_type(result)
- (C33)
is_per_tensor_quantized(rhs)
iseis_per_tensor_quantized(result)
. - Eğer
!is_quantized(lhs)
: - (C34)
element_type(lhs) = expressed_type(rhs) = element_type(result)
.
- (C28)
Örnekler
// %lhs: [[
// [[1], [2], [5], [6]],
// [[3], [4], [7], [8]],
// [[10], [11], [14], [15]],
// [[12], [13], [16], [17]]
// ]]
//
// %rhs: [
// [[[1]], [[1]], [[1]]],
// [[[1]], [[1]], [[1]]],
// [[[1]], [[1]], [[1]]]
// ]
// %padding: [[1, 1],
// [1, 1]]
%result = "stablehlo.dynamic_conv"(%lhs, %rhs, %padding) {
window_strides = array<i64: 4, 4>,
lhs_dilation = array<i64: 2, 2>,
rhs_dilation = array<i64: 1, 1>,
window_reversal = array<i1: false, false>,
dimension_numbers = #stablehlo.conv<raw
input_batch_dimension = 0,
input_feature_dimension = 3,
input_spatial_dimensions = [0, 1],
kernel_input_feature_dimension = 2,
kernel_output_feature_dimension = 3,
kernel_spatial_dimensions = [0, 1],
output_batch_dimension = 0,
output_feature_dimension = 3,
output_spatial_dimensions = [1, 2]
>,
feature_group_count = 1 : i64,
batch_group_count = 1 : i64,
precision_config = [#stablehlo<precision DEFAULT>, #stablehlo<precision DEFAULT>]
} : (tensor<1x4x4x1xi64>, tensor<3x3x1x1xi64>, tensor<2x2xi64>) -> tensor<1x2x2x1xi64>
// %result: [[
// [[1], [5]],
// [[10], [14]]
// ]]
dynamic_gather
Anlam
Bu işlem işlevsel olarak
topla
slice_sizes
ile dinamik bir şekilde değer olarak belirtilir.
Girişler
Şirket | Ad | Tür | Sınırlamalar |
---|---|---|---|
(I1) | operand |
tensör veya tensör başına miktarlandırılmış tensör | (C1), (C7), (C10-C12), (C14) |
(I2) | start_indices |
tam sayı türündeki tensör | (C2), (C3), (C13) |
(I3) | slice_sizes |
Tam sayı türünde 1 boyutlu tensör | (C8), (C11-C13) |
(I4) | offset_dims |
si64 türünde 1 boyutlu tensör sabiti |
(C1), (C4-C5), (C13) |
(I5) | collapsed_slice_dims |
si64 türünde 1 boyutlu tensör sabiti |
(C1), (C6-C8), (C13) |
(I6) | start_index_map |
si64 türünde 1 boyutlu tensör sabiti |
(C3), (C9), (C10) |
(I7) | index_vector_dim |
si64 türündeki sabit |
(C2), (C3), (C13) |
(I8) | indices_are_sorted |
i1 türündeki sabit |
Çıkışlar
Ad | Tür | Sınırlamalar |
---|---|---|
result |
tensör veya tensör başına miktarlandırılmış tensör | (C5), (C13-C14) |
Sınırlamalar
- (C1)
rank(operand) = size(offset_dims) + size(collapsed_slice_dims)
. - (C2)
0 <= index_vector_dim <= rank(start_indices)
. - (C3)
size(start_index_map) = index_vector_dim < rank(start_indices) ? dim(start_indices, index_vector_dim) : 1
. - (C4)
is_unique(offset_dims) and is_sorted(offset_dims)
- (C5)
0 <= offset_dims < rank(result)
- (C6)
is_unique(collapsed_slice_dims) and is_sorted(collapsed_slice_dims)
. - (C7)
0 <= collapsed_slice_dims < rank(operand)
. - (C8)
slice_sizes[collapsed_slice_dims...] <= 1
- (C9)
is_unique(start_index_map)
. - (C10)
0 <= start_index_map < rank(operand)
- (C11)
size(slice_sizes) = rank(operand)
- (C12)
0 <= slice_sizes <= shape(operand)
- (C13)
shape(result) = combine(batch_dim_sizes, offset_dim_sizes)
; burada:batch_dim_sizes = shape(start_indices)
(boyut boyutu hariç)index_vector_dim
öğesine karşılık gelenstart_indices
dahil edilmemiştir.offset_dim_sizes = shape(slice_sizes)
(boyut boyutları hariç) 'dekislice_sizes
dilindekicollapsed_slice_dims
dahil edilmemiştir.combine
,batch_dim_sizes
değerinibatch_dims
veoffset_dims
değerine karşılık gelen eksenlerdeoffset_dim_sizes
.
- (C14)
element_type(operand) = element_type(result)
Örnekler
// %operand: [
// [[1, 2], [3, 4], [5, 6], [7, 8]],
// [[9, 10],[11, 12], [13, 14], [15, 16]],
// [[17, 18], [19, 20], [21, 22], [23, 24]]
// ]
// %start_indices: [
// [[0, 0], [1, 0], [2, 1]],
// [[0, 1], [1, 1], [0, 2]]
// ]
// %slize_sizes: [1, 2, 2]
%result = "stablehlo.dynamic_gather"(%operand, %start_indices, %slize_sizes) {
dimension_numbers = #stablehlo.gather<
offset_dims = [2, 3],
collapsed_slice_dims = [0],
start_index_map = [1, 0],
index_vector_dim = 2>,
indices_are_sorted = false
} : (tensor<3x4x2xi64>, tensor<2x3x2xi64>, tensor<3xi64>) -> tensor<2x3x2x2xi64>
// %result: [
// [
// [[1, 2], [3, 4]],
// [[3, 4], [5, 6]],
// [[13, 14], [15, 16]]
// ],
// [
// [[9, 10], [11, 12]],
// [[11, 12], [13, 14]],
// [[17, 18], [19, 20]]
// ]
// ]
dynamic_iota
Anlam
Bu işlem işlevsel olarak
iota
op, ancak sonuç şekli output_shape
aracılığıyla dinamik olarak belirtilir.
Girişler
Şirket | Ad | Tür | Sınırlamalar |
---|---|---|---|
(I1) | output_shape |
Tam sayı türünde 1 boyutlu tensör | (C1), (C2) |
(I2) | iota_dimension |
si64 |
(C1) |
Çıkışlar
Ad | Tür | Sınırlamalar |
---|---|---|
result |
tam sayı, kayan nokta veya karmaşık tür ya da tensör başına miktarlandırılmış tensör tensörü | (C2) |
Sınırlamalar
- (C1)
0 <= iota_dimension < size(output_shape)
. - (C2)
rank(result) = size(output_shape)
.
Örnekler
%output_shape = stablehlo.constant dense<[4, 5]> : tensor<2xi64>
%result = "stablehlo.dynamic_iota"(%output_shape) {
iota_dimension = 0 : i64
} : (tensor<2xi64>) -> tensor<4x5xi64>
// %result: [
// [0, 0, 0, 0, 0],
// [1, 1, 1, 1, 1],
// [2, 2, 2, 2, 2],
// [3, 3, 3, 3, 3]
// ]
dynamic_pad
Anlam
Bu işlem işlevsel olarak
pad
işlem, ancak edge_padding_low
, edge_padding_high
ve interior_padding
ile
şeklinde dinamik bir şekilde değer olarak belirtilir.
Girişler
Şirket | Ad | Tür | Sınırlamalar |
---|---|---|---|
(I1) | operand |
tensör veya tensör başına miktarlandırılmış tensör | (C1), (C2), (C4) |
(I2) | padding_value |
0 boyutlu tensör veya tensör başına miktarlandırılmış tensör | (C1) |
(I3) | edge_padding_low |
Tam sayı türünde 1 boyutlu tensör | (C1), (C4) |
(I4) | edge_padding_high |
Tam sayı türünde 1 boyutlu tensör | (C1), (C4) |
(I5) | interior_padding |
Tam sayı türünde 1 boyutlu tensör | (C2-C4) |
Çıkışlar
Ad | Tür | Sınırlamalar |
---|---|---|
result |
tensör veya tensör başına miktarlandırılmış tensör | (C3-C6) |
Sınırlamalar
- (C1)
element_type(operand) = element_type(padding_value) = element_type(result)
. - (C2)
size(edge_padding_low) = size(edge_padding_high) = size(interior_padding) = rank(operand)
. - (C3)
0 <= interior_padding
. - (C4)
shape(result) = shape(operand) + edge_padding_low + max(shape(operand) - 1, 0) * interior_padding + edge_padding_high
Örnekler
// %operand: [
// [1, 2, 3],
// [4, 5, 6]
// ]
// %padding_value: 0
// %edge_padding_low: [0, 1]
// %edge_padding_high: [2, 1]
// %interior_padding: [1, 2]
%result = "stablehlo.dynamic_pad"(%operand, %padding_value,
%edge_padding_low, %edge_padding_high, %interior_padding
) : (tensor<2x3xi64>, tensor<i64>, tensor<2xi64>, tensor<2xi64>, tensor<2xi64>) -> tensor<5x9xi64>
// %result: [
// [0, 1, 0, 0, 2, 0, 0, 3, 0],
// [0, 0, 0, 0, 0, 0, 0, 0, 0],
// [0, 4, 0, 0, 5, 0, 0, 6, 0],
// [0, 0, 0, 0, 0, 0, 0, 0, 0],
// [0, 0, 0, 0, 0, 0, 0, 0, 0]
// ]
dynamic_reshape
Anlam
Bu işlem işlevsel olarak
yeniden şekillendirme
op, ancak sonuç şekli output_shape
aracılığıyla dinamik olarak belirtilir.
Girişler
Şirket | Ad | Tür | Sınırlamalar |
---|---|---|---|
(I1) | operand |
tensör veya nicel tensör | (C1-C3) |
(I2) | output_shape |
Tam sayı türünde 1 boyutlu tensör | (C4) |
Çıkışlar
Ad | Tür | Sınırlamalar |
---|---|---|
result |
tensör veya nicel tensör | (C1-C4) |
Sınırlamalar
- (C1)
element_type(result)
değerini sağlayan:!is_per_axis_quantized(operand)
iseelement_type(operand)
.element_type(operand)
yalnızcaquantization_dimension(operand)
ve Aksi takdirdequantization_dimension(result)
farklı olabilir.
- (C2)
size(operand) = size(result)
. - (C3)
is_per_axis_quantized(operand)
ise:reduce(dims(operand, [0, 1, ..., quantization_dimension(operand) - 1]), init_values=1, dimensions=[0], body=lambda x, y: x * y) = reduce(dims(result, [0, 1, ..., quantization_dimension(result) - 1]), init_values=1, dimensions=[0], body=lambda x, y: x * y)
.dim(operand, quantization_dimension(operand)) = dim(result, quantization_dimension(result))
.reduce(dims(operand, [quantization_dimension(operand) + 1, ..., rank(operand) - 1]), init_values=1, dimensions=[0], body=lambda x, y: x * y) = reduce(dims(result, [quantization_dimension(result) + 1, ..., rank(result) - 1]), init_values=1, dimensions=[0], body=lambda x, y: x * y)
.
- (C4)
size(output_shape) = rank(result)
Örnekler
// %operand: [[1, 2, 3], [4, 5, 6]]
// %output_shape: [3, 2]
%result = "stablehlo.dynamic_reshape"(%operand, %output_shape) : (tensor<2x3xi64>, tensor<2xi64>) -> tensor<3x2xi64>
// %result: [[1, 2], [3, 4], [5, 6]]
dynamic_slice
Anlam
Dinamik olarak hesaplanan başlangıç dizinlerini kullanarak operand
öğesinden bir dilim çıkarır
ve bir result
tensörü üretir. start_indices
, şunun başlangıç dizinlerini içeriyor:
olası düzenlemeye tabi her bir boyuta ait dilim ve slice_sizes
her boyut için dilimin boyutlarını içermelidir. Daha resmi ifade etmek gerekirse
result[result_index] = operand[operand_index]
; burada:
adjusted_start_indices = clamp(0, start_indices, shape(operand) - slice_sizes)
.operand_index = adjusted_start_indices + result_index
.
Girişler
Şirket | Ad | Tür | Sınırlamalar |
---|---|---|---|
(I1) | operand |
tensör veya tensör başına miktarlandırılmış tensör | (C1), (C2), (C4) |
(I2) | start_indices |
tam sayı türündeki 0 boyutlu tensörlerin değişken sayısı | (C2), (C3) |
(I3) | slice_sizes |
si64 türünde 1 boyutlu tensör sabiti |
(C2), (C4), (C5) |
Çıkışlar
Ad | Tür | Sınırlamalar |
---|---|---|
result |
tensör veya tensör başına miktarlandırılmış tensör | (C1), (C5) |
Sınırlamalar
- (C1)
element_type(operand) = element_type(result)
. - (C2)
size(start_indices) = size(slice_sizes) = rank(operand)
. - (C3)
same(type(start_indices...))
. - (C4)
0 <= slice_sizes <= shape(operand)
- (C5)
shape(result) = slice_sizes
Örnekler
// %operand: [
// [0, 0, 1, 1],
// [0, 0, 1, 1],
// [0, 0, 0, 0],
// [0, 0, 0, 0]
// ]
// %start_indices0: -1
// %start_indices1: 3
%result = "stablehlo.dynamic_slice"(%operand, %start_indices0, %start_indices1) {
slice_sizes = array<i64: 2, 2>
} : (tensor<4x4xi32>, tensor<i64>, tensor<i64>) -> tensor<2x2xi32>
// %result: [
// [1, 1],
// [1, 1]
// ]
dynamic_update_slice
Anlam
Şu hariç operand
tensörüne eşit bir result
tensörü üretir:
start_indices
ile başlayan dilim, update
içindeki değerlerle güncellenir.
Daha resmi olarak, result[result_index]
şu şekilde tanımlanır:
0 <= update_index < shape(update)
iseupdate[update_index]
:adjusted_start_indices = clamp(0, start_indices, shape(operand) - shape(update))
.update_index = result_index - adjusted_start_indices
.
- Aksi takdirde
operand[result_index]
.
Girişler
Şirket | Ad | Tür | Sınırlamalar |
---|---|---|---|
(I1) | operand |
tensör veya tensör başına miktarlandırılmış tensör | (C1-C4), (C6) |
(I2) | update |
tensör veya tensör başına miktarlandırılmış tensör | (C2), (C3), (C6) |
(I3) | start_indices |
tam sayı türündeki 0 boyutlu tensörlerin değişken sayısı | (C4), (C5) |
Çıkışlar
Ad | Tür | Sınırlamalar |
---|---|---|
result |
tensör veya tensör başına miktarlandırılmış tensör | (C1) |
Sınırlamalar
- (C1)
type(operand) = type(result)
. - (C2)
element_type(update) = element_type(operand)
. - (C3)
rank(update) = rank(operand)
. - (C4)
size(start_indices) = rank(operand)
- (C5)
same(type(start_indices...))
- (C6)
0 <= shape(update) <= shape(operand)
.
Örnekler
// %operand: [
// [1, 1, 0, 0],
// [1, 1, 0, 0],
// [1, 1, 1, 1],
// [1, 1, 1, 1]
// ]
// %update: [
// [1, 1],
// [1, 1]
// ]
// %start_indices0: -1
// %start_indices1: 3
%result = "stablehlo.dynamic_update_slice"(%operand, %update, %start_indices0, %start_indices1)
: (tensor<4x4xi32>, tensor<2x2xi32>, tensor<i64>, tensor<i64>) -> tensor<4x4xi32>
// %result: [
// [1, 1, 1, 1],
// [1, 1, 1, 1],
// [1, 1, 1, 1],
// [1, 1, 1, 1]
// ]
üstel
Anlam
operand
tensörü üzerinde öğe düzeyinde üstel işlem gerçekleştirir ve bir
result
tensörü. Öğe türüne bağlı olarak aşağıdakiler gerçekleşir:
- Kayan reklamlar için: IEEE-754'ten
exp
. - Karmaşık sayılar için: karmaşık üstel.
- Ölçülen türler için:
dequantize_op_quantize(exponential, operand, type(result))
Girişler
Şirket | Ad | Tür | Sınırlamalar |
---|---|---|---|
(I1) | operand |
kayan nokta veya karmaşık tür ya da tensör başına miktarlandırılmış tensör tensörü | (C1) |
Çıkışlar
Ad | Tür | Sınırlamalar |
---|---|---|
result |
kayan nokta veya karmaşık tür ya da tensör başına miktarlandırılmış tensör tensörü | (C1) |
Sınırlamalar
- (C1)
baseline_type(operand) = baseline_type(result)
.
Örnekler
// %operand: [[0.0, 1.0], [2.0, 3.0]]
%result = "stablehlo.exponential"(%operand) : (tensor<2x2xf64>) -> tensor<2x2xf64>
// %result: [[1.0, 2.7182818284590451], [7.3890560989306504, 20.085536923187668]]
exponential_minus_one
Anlam
operand
tensörü üzerinde öğe tabanlı üslü eksi bir işlem gerçekleştirir ve
bir result
tensörü üretir. Öğe türüne bağlı olarak aşağıdakiler gerçekleşir:
- Kayan reklamlar için: IEEE-754'ten
expm1
. - Karmaşık sayılar için: karmaşık üslü sayı eksi bir.
- Ölçülen türler için:
dequantize_op_quantize(exponential_minus_one, operand, type(result))
Girişler
Şirket | Ad | Tür | Sınırlamalar |
---|---|---|---|
(I1) | operand |
kayan nokta veya karmaşık tür ya da tensör başına miktarlandırılmış tensör tensörü | (C1) |
Çıkışlar
Ad | Tür | Sınırlamalar |
---|---|---|
result |
kayan nokta veya karmaşık tür ya da tensör başına miktarlandırılmış tensör tensörü | (C1) |
Sınırlamalar
- (C1)
baseline_type(operand) = baseline_type(result)
.
Örnekler
// %operand: [0.0, 1.0]
%result = "stablehlo.exponential_minus_one"(%operand) : (tensor<2xf64>) -> tensor<2xf64>
// %result: [0.0, 1.71828187]
fft
Anlam
Gerçek ve karmaşık süreçler için ileri ve ters Fourier dönüşümlerini gerçekleştirir giriş/çıkışları kontrol edin.
fft_type
şunlardan biridir:
FFT
: Karmaşıkdan karmaşık FFT'ye yönlendir.IFFT
: Ters karmaşıktan karmaşıka FFT.RFFT
: Gerçekten karmaşık FFT'yi yönlendir.IRFFT
: Ters gerçeğe dayalı FFT (ör. karmaşık alır, gerçek sonucu döndürür).
Daha resmi ifade etmek gerekirse, 1 boyutlu tensörleri alan fft
fonksiyonu
iki boyutlu tensörler üreterek aynı türde 1 boyutlu tensörler
çıktısını verir ve ayrı Fourier dönüşümünü hesaplar:
fft_type = FFT
için result
, bir L dizisinin nihai sonucu olarak tanımlanır
hesaplamalar için L = size(fft_length)
. Örneğin, L = 3
için:
result1[i0, ..., :] = fft(operand[i0, ..., :])
.result2[i0, ..., :, iR-1] = fft(result1[i0, ..., :, iR-1])
.result[i0, ..., :, iR-2, iR-1] = fft(result2[i0, ..., :, iR-2, iR-1])
.
Ayrıca, aynı tür imzaya veifft
fft
değerinin tersini hesaplar:
fft_type = IFFT
için result
, hesaplamaların tersi olarak tanımlanır
fft_type = FFT
için. Örneğin, L = 3
için:
result1[i0, ..., :, iR-2, iR-1] = ifft(operand[i0, ..., :, iR-2, iR-1])
.result2[i0, ..., :, iR-1] = ifft(result1[i0, ..., :, iR-1])
.result[i0, ..., :] = ifft(result2[i0, ..., :])
.
Ayrıca, 1 boyutlu tensörleri alan rfft
fonksiyonu
kayan nokta türleri, bir dizi karmaşık öğenin 1 boyutlu tensörlerini
aynı kayan nokta semantiğiyle çalışır ve aşağıdaki gibi çalışır:
rfft(real_operand) = truncated_result
burada:complex_operand... = (real_operand..., 0.0)
.complex_result = fft(complex_operand)
.truncated_result = complex_result[:(rank(complex_result) / 2 + 1)]
.
(Gerçek işlenenler için ayrık Fourier dönüşümü hesaplandığında,
Sonucun N/2 + 1
öğeleri, sonucun geri kalanını açık bir şekilde tanımlar.
bu nedenle, gereksiz öğelerin hesaplamasını önlemek için rfft
işlevinin sonucu kısaltılır.
fft_type = RFFT
için result
, bir L dizisinin nihai sonucu olarak tanımlanır
hesaplamalar için L = size(fft_length)
. Örneğin, L = 3
için:
result1[i0, ..., :] = rfft(operand[i0, ..., :])
.result2[i0, ..., :, iR-1] = fft(result1[i0, ..., :, iR-1])
.result[i0, ..., :, iR-2, iR-1] = fft(result2[i0, ..., :, iR-2, iR-1])
.
Son olarak, aynı tür imzaya veirfft
rfft
değerinin tersini hesaplar:
fft_type = IRFFT
için result
, hesaplamaların tersi olarak tanımlanır
fft_type = RFFT
için. Örneğin, L = 3
için:
result1[i0, ..., :, iR-2, iR-1] = ifft(operand[i0, ..., :, iR-2, iR-1])
.result2[i0, ..., :, iR-1] = ifft(result1[i0, ..., :, iR-1])
.result[i0, ..., :] = irfft(result2[i0, ..., :])
.
Girişler
Şirket | Ad | Tür | Sınırlamalar |
---|---|---|---|
(I1) | operand |
kayan nokta veya karmaşık türde tensor | (C1), (C2), (C4), (C5) |
(I2) | fft_type |
FFT , IFFT , RFFT ve IRFFT sıralaması |
(C2), (C5) |
(I3) | fft_length |
si64 türünde 1 boyutlu tensör sabiti |
(C1), (C3), (C4) |
Çıkışlar
Ad | Tür | Sınırlamalar |
---|---|---|
result |
kayan nokta veya karmaşık türde tensor | (C2), (C4), (C5) |
Sınırlamalar
- (C1)
size(fft_length) <= rank(operand)
. - (C2)
operand
ileresult
öğe türleri arasındaki ilişki değişiklik gösterir:- Eğer
fft_type = FFT
,element_type(operand)
veelement_type(result)
aynı karmaşık türdedir. - Eğer
fft_type = IFFT
,element_type(operand)
veelement_type(result)
aynı karmaşık türdedir. fft_type = RFFT
iseelement_type(operand)
kayan nokta türüdür veelement_type(result)
, aynı kayan noktanın karmaşık bir türüdür anlambilim.fft_type = IRFFT
iseelement_type(operand)
karmaşık bir türdür veelement_type(result)
, aynı kayan noktanın bir kayan nokta türüdür anlambilim.
- Eğer
- (C3)
1 <= size(fft_length) <= 3
. - (C4)
operand
veresult
arasındaysa tensorreal
var ardındanshape(real)[-size(fft_length):] = fft_length
'e gidin. - (C5)
shape(result) = shape(operand)
hariç:fft_type = RFFT
isedim(result, -1) = dim(operand, -1) = 0 ? 0 : dim(operand, -1) / 2 + 1
.fft_type = IRFFT
isedim(operand, -1) = dim(result, -1) = 0 ? 0 : dim(result, -1) / 2 + 1
.
Örnekler
// %operand: [(1.0, 0.0), (0.0, 0.0), (0.0, 0.0), (0.0, 0.0)]
%result = "stablehlo.fft"(%operand) {
fft_type = #stablehlo<fft_type FFT>,
fft_length = array<i64: 4>
} : (tensor<4xcomplex<f32>>) -> tensor<4xcomplex<f32>>
// %result: [(1.0, 0.0), (1.0, 0.0), (1.0, 0.0), (1.0, 0.0)]
floor
Anlam
Element tabanlı tabanda operand
tensörü gerçekleştirir ve bir result
tensörü üretir.
IEEE-754'teki roundToIntegralTowardNegative
işlemini uygular
bakın. Miktarı kullanılan türlerde,
dequantize_op_quantize(floor, operand, type(result))
Girişler
Şirket | Ad | Tür | Sınırlamalar |
---|---|---|---|
(I1) | operand |
kayan nokta tipi veya tensör başına miktarlandırılmış tensör tensörü | (C1) |
Çıkışlar
Ad | Tür | Sınırlamalar |
---|---|---|
result |
kayan nokta tipi veya tensör başına miktarlandırılmış tensör tensörü | (C1) |
Sınırlamalar
- (C1)
baseline_type(operand) = baseline_type(result)
.
Örnekler
// %operand: [-0.8166, -0.2530, 0.2530, 0.8166, 2.0]
%result = "stablehlo.floor"(%operand) : (tensor<5xf32>) -> tensor<5xf32>
// %result: [-1.0, -1.0, 0.0, 0.0, 2.0]
toplamak
Anlam
start_indices
içinde belirtilen ofsetlerden operand
tensöründen dilimleri toplar
ve bir result
tensörü üretir.
Aşağıdaki şemada result
içindeki öğelerin,
Somut bir örnek kullanarak operand
. Diyagramda birkaç örnek result
.operand
Daha resmi dilde, result[result_index] = operand[operand_index]
burada:
batch_dims = [d for d in axes(result) and d not in offset_dims]
.batch_index = result_index[batch_dims...]
.start_index
şu şekilde tanımlanır:bi
öğesinin bağımsız öğeler olduğustart_indices[bi0, ..., :, ..., biN]
Aşağıdaki koşul karşılandığındaindex_vector_dim
dizininebatch_index
ve:
eklenirindex_vector_dim
<rank(start_indices)
.- Aksi takdirde
[start_indices[batch_index]]
.
axes(operand)
içindekid_operand
için,full_start_index[d_operand] = clamp(start_index[d_start], 0, dim(operand, d_operand) - slice_sizes[d_operand])
. (d_operand = start_index_map[d_start]
ise)- Aksi takdirde
full_start_index[d_operand] = 0
.
axes(operand)
içindekid_operand
için,full_batching_index[d_operand] = batch_index[d_start - (d_start < index_vector_dim ? 0 : 1)]
. eğerd_operand = operand_batching_dims[i_batching]
ved_start = start_indices_batching_dims[i_batching]
.- Aksi takdirde
full_batching_index[d_operand] = 0
.
offset_index = result_index[offset_dims...]
.oi
bireysel olduğufull_offset_index = [oi0, ..., 0, ..., oiN]
öğelerioffset_index
içindeki dizinlere eklenir ve0
,collapsed_slice_dims
veoperand_batching_dims
.operand_index = full_start_index + full_batching_index + full_offset_index
indices_are_sorted
değeri true
ise uygulama,
start_indices
, start_index_map
ölçütüne göre sıralanır, aksi takdirde
tanımlanmamıştır. Daha resmî bir şekilde ifade etmek gerekirse indices(result)
kaynaklı tüm i1 < i2
için
full_start_index(i1) <= full_start_index(i2)
.
Girişler
Şirket | Ad | Tür | Sınırlamalar |
---|---|---|---|
(I1) | operand |
tensör veya tensör başına miktarlandırılmış tensör | (C1), (C8), (C11), (C17), (C19-C21), (C23) |
(I2) | start_indices |
tam sayı türündeki tensör | (C2-C3), (C14), (C17), (C22) |
(I3) | offset_dims |
si64 türünde 1 boyutlu tensör sabiti |
(C1), (C4-C5), (C22) |
(I4) | collapsed_slice_dims |
si64 türünde 1 boyutlu tensör sabiti |
(C1), (C6-C9), (C22) |
(I5) | operand_batching_dims |
si64 türünde 1 boyutlu tensör sabiti |
(C1), (C6), (C10-C12), (C16-C18), (C22) |
(I6) | start_indices_batching_dims |
si64 türünde 1 boyutlu tensör sabiti |
(C13-C17) |
(I7) | start_index_map |
si64 türünde 1 boyutlu tensör sabiti |
(C3), (C18-C19) |
(I8) | index_vector_dim |
si64 türündeki sabit |
(C2-C3), (C15), (C22) |
(I9) | slice_sizes |
si64 türünde 1 boyutlu tensör sabiti |
(C9), (C12), (C20-C22) |
(I10) | indices_are_sorted |
i1 türündeki sabit |
Çıkışlar
Ad | Tür | Sınırlamalar |
---|---|---|
result |
tensör veya tensör başına miktarlandırılmış tensör | (C5), (C22-C23) |
Sınırlamalar
- (C1)
rank(operand) = size(offset_dims) + size(collapsed_slice_dims) + size(operand_batching_dims)
. - (C2)
0 <= index_vector_dim <= rank(start_indices)
. - (C3)
size(start_index_map) = index_vector_dim < rank(start_indices) ? dim(start_indices, index_vector_dim) : 1
. - (C4)
is_unique(offset_dims) and is_sorted(offset_dims)
- (C5)
0 <= offset_dims < rank(result)
- (C6)
is_unique(concatenate(collapsed_slice_dims, operand_batching_dims))
- (C7)
is_sorted(collapsed_slice_dims)
. - (C8)
0 <= collapsed_slice_dims < rank(operand)
- (C9)
slice_sizes[collapsed_slice_dims...] <= 1
. - (C10)
is_sorted(operand_batching_dims)
- (C11)
0 <= operand_batching_dims < rank(operand)
- (C12)
slice_sizes[operand_batching_dims...] <= 1
- (C13)
is_unique(start_indices_batching_dims)
- (C14)
0 <= start_indices_batching_dims < rank(start_indices)
- (C15)
index_vector_dim not in start_indices_batching_dims
- (C16)
size(operand_batching_dims) == size(start_indices_batching_dims)
- (C17)
dim(operand, operand_batching_dims...) = dim(start_indices, start_indices_batching_dims...)
- (C18)
is_unique(concatenate(start_index_map, operand_batching_dims))
- (C19)
0 <= start_index_map < rank(operand)
- (C20)
size(slice_sizes) = rank(operand)
. - (C21)
0 <= slice_sizes <= shape(operand)
- (C22)
shape(result) = combine(batch_dim_sizes, offset_dim_sizes)
; burada:batch_dim_sizes = shape(start_indices)
(boyut boyutu hariç)index_vector_dim
öğesine karşılık gelenstart_indices
dahil edilmemiştir.offset_dim_sizes = slice_sizes
dışında, şu boyuttaki boyutlarslice_sizes
collapsed_slice_dims
veoperand_batching_dims
dahil edilmedi.combine
,batch_dim_sizes
değerinibatch_dims
veoffset_dims
değerine karşılık gelen eksenlerdeoffset_dim_sizes
.
- (C23)
element_type(operand) = element_type(result)
Örnekler
// %operand: [
// [
// [[1, 2], [3, 4], [5, 6], [7, 8]],
// [[9, 10],[11, 12], [13, 14], [15, 16]],
// [[17, 18], [19, 20], [21, 22], [23, 24]]
// ],
// [
// [[25, 26], [27, 28], [29, 30], [31, 32]],
// [[33, 34], [35, 36], [37, 38], [39, 40]],
// [[41, 42], [43, 44], [45, 46], [47, 48]]
// ]
// ]
// %start_indices: [
// [
// [[0, 0], [1, 0], [2, 1]],
// [[0, 1], [1, 1], [0, 9]]
// ],
// [
// [[0, 0], [2, 1], [2, 2]],
// [[1, 2], [0, 1], [1, 0]]
// ]
// ]
%result = "stablehlo.gather"(%operand, %start_indices) {
dimension_numbers = #stablehlo.gather<
offset_dims = [3, 4],
collapsed_slice_dims = [1],
operand_batching_dims = [0],
start_indices_batching_dims = [1],
start_index_map = [2, 1],
index_vector_dim = 3>,
slice_sizes = array<i64: 1, 1, 2, 2>,
indices_are_sorted = false
} : (tensor<2x3x4x2xi32>, tensor<2x2x3x2xi64>) -> tensor<2x2x3x2x2xi32>
// %result: [
// [
// [
// [[1, 2], [3, 4]],
// [[3, 4], [5, 6]],
// [[13, 14], [15, 16]]
// ],
// [
// [[33, 34], [35, 36]],
// [[35, 36], [37, 38]],
// [[41, 42], [43, 44]]
// ]
// ],
// [
// [
// [[1, 2], [3, 4]],
// [[13, 14], [15, 16]],
// [[21, 22], [23, 24]]
// ],
// [
// [[43, 44], [45, 46]],
// [[33, 34], [35, 36]],
// [[27, 28], [29, 30]]
// ]
// ]
// ]
get_dimension_size
Anlam
operand
için belirtilen dimension
öğesinin boyutunu oluşturur. Daha resmi ifade etmek gerekirse
result = dim(operand, dimension)
Anlamsal açıdan yalnızca şekille ilgilidir.
türünün bileşenidir. Öğe türü herhangi bir şey olabilir.
Girişler
Şirket | Ad | Tür | Sınırlamalar |
---|---|---|---|
(I1) | operand |
tensör veya nicel tensör | (C1) |
(I2) | dimension |
si64 türündeki sabit |
(C1) |
Çıkışlar
Ad | Tür |
---|---|
result |
si32 türünde 0 boyutlu tensör |
Sınırlamalar
- (C1)
0 <= dimension < rank(operand)
.
Örnekler
// %operand: [[1, 2, 3], [4, 5, 6]]
%result = "stablehlo.get_dimension_size"(%operand) {
dimension = 1 : i64
} : (tensor<2x3xi64>) -> tensor<i32>
// %result: 3
get_tuple_element
Anlam
operand
unsurunun index
konumundaki öğeyi çıkarır ve bir
result
. Daha resmi olarak, result = operand[index]
.
Girişler
Şirket | Ad | Tür | Sınırlamalar |
---|---|---|---|
(I1) | operand |
tuple | (C1), (C2) |
(I2) | index |
si32 türündeki sabit |
(C1), (C2) |
Çıkışlar
Ad | Tür | Sınırlamalar |
---|---|---|
result |
desteklenen tüm türler | (C2) |
Sınırlamalar
- (C1)
0 <= index < size(operand)
. - (C2)
type(result) = tuple_element_types(operand)[index]
.
Örnekler
// %operand: ([1.0, 2.0], (3))
index = 0 : i32
} : (tuple<tensor<2xf32>, tuple<tensor<i32>>>) -> tensor<2xf32>
// %result: [1.0, 2.0]
koşul:
Anlam
true_branch
veya
pred
değerine bağlı olarak false_branch
. Daha resmi olarak, result =
pred ? true_branch() : false_branch()
.
Girişler
Şirket | Ad | Tür | Sınırlamalar |
---|---|---|---|
(I1) | pred |
i1 türünde 0 boyutlu tensör |
|
(I2) | true_branch |
işlev | (C1-C3) |
(I3) | false_branch |
işlev | (C1), (C2) |
Çıkışlar
Ad | Tür | Sınırlamalar |
---|---|---|
results |
değişken tensör, nicel tensör veya jeton sayısı | (C3) |
Sınırlamalar
- (C1)
input_types(true_branch) = input_types(false_branch) = []
. - (C2)
output_types(true_branch) = output_types(false_branch)
. - (C3)
type(results...) = output_types(true_branch)
.
Örnekler
// %result_true_branch: 10
// %result_false_branch: 11
// %pred: true
%result = "stablehlo.if"(%pred) ({
"stablehlo.return"(%result_true_branch) : (tensor<i32>) -> ()
}, {
"stablehlo.return"(%result_false_branch) : (tensor<i32>) -> ()
}) : (tensor<i1>) -> tensor<i32>
// %result: 10
hayal etmek
Anlam
Öğe tabanlı sanal bölümü operand
öğesinden çıkarır ve bir
result
tensörü. Daha resmi olarak, her öğe için x
:
imag(x) = is_complex(x) ? imaginary_part(x) :
constant(0, element_type(result))
.
Girişler
Şirket | Ad | Tür | Sınırlamalar |
---|---|---|---|
(I1) | operand |
kayan nokta veya karmaşık türde tensor | (C1), (C2) |
Çıkışlar
Ad | Tür | Sınırlamalar |
---|---|---|
result |
kayan nokta türünün tensörü | (C1), (C2) |
Sınırlamalar
- (C1)
shape(result) = shape(operand)
. - (C2)
element_type(result)
şu şekilde tanımlanır:is_complex(operand)
isecomplex_element_type(element_type(operand))
.- Aksi takdirde
element_type(operand)
.
Örnekler
// %operand: [(1.0, 2.0), (3.0, 4.0)]
%result = "stablehlo.imag"(%operand) : (tensor<2xcomplex<f32>>) -> tensor<2xf32>
// %result: [2.0, 4.0]
feed içi
Anlam
Feed içinden verileri okur ve results
üretir.
infeed_config
anlamı, uygulama tanımlıdır.
results
, başta gelen yük değerlerinden ve
bakın. Gelecekte yükü ve jetonu ikiye bölmeyi planlıyoruz.
Netliği artırmak için ayrı çıktılar
(#670).
Girişler
Şirket | Ad | Tür |
---|---|---|
(I1) | token |
token |
(I2) | infeed_config |
string türündeki sabit |
Çıkışlar
Ad | Tür | Sınırlamalar |
---|---|---|
results |
değişken tensör, nicel tensör veya jeton sayısı | (C1-C3) |
Sınırlamalar
- (C1)
0 < size(results)
. - (C2)
is_empty(result[:-1])
veyais_tensor(type(results[:-1]))
. - (C3)
is_token(type(results[-1]))
.
Örnekler
// %token: !stablehlo.token
// infeed_queue[0]: [[1, 2], [3, 4]]
// infeed_queue[1]: [[5, 6], [7, 8]]
%results0:2 = "stablehlo.infeed"(%token) {
infeed_config = ""
} : (!stablehlo.token) -> (tensor<2x2xi64>, !stablehlo.token)
// results0#0: [[1, 2], [3, 4]]
%results1:2 = "stablehlo.infeed"(%token) {
infeed_config = ""
} : (!stablehlo.token) -> (tensor<2x2xi64>, !stablehlo.token)
// results1#0: [[5, 6], [7, 8]]
Iota
Anlam
Bir output
tensörünü sıfırdan başlayarak artan sırayla değerlerle doldurur
iota_dimension
boyutu boyunca görüntülenir. Daha resmi ifade etmek gerekirse
output[output_index] = constant(is_quantized(output) ?
quantize(output_index[iota_dimension], element_type(output)) :
output_index[iota_dimension], element_type(output))
.
Girişler
Şirket | Ad | Tür | Sınırlamalar |
---|---|---|---|
(I1) | iota_dimension |
si64 |
(C1) |
Çıkışlar
Ad | Tür | Sınırlamalar |
---|---|---|
output |
tam sayı, kayan nokta veya karmaşık tür ya da tensör başına miktarlandırılmış tensör tensörü | (C1) |
Sınırlamalar
- (C1)
0 <= iota_dimension < rank(output)
.
Örnekler
%output = "stablehlo.iota"() {
iota_dimension = 0 : i64
} : () -> tensor<4x5xi32>
// %output: [
// [0, 0, 0, 0, 0],
// [1, 1, 1, 1, 1],
// [2, 2, 2, 2, 2],
// [3, 3, 3, 3, 3]
// ]
%output = "stablehlo.iota"() {
iota_dimension = 1 : i64
} : () -> tensor<4x5xi32>
// %output: [
// [0, 1, 2, 3, 4],
// [0, 1, 2, 3, 4],
// [0, 1, 2, 3, 4],
// [0, 1, 2, 3, 4]
// ]
is_finite
Anlam
x
öğesindeki değerin sonlu olup olmadığını (yani
+Inf, -Inf, veya NaN) çevirir ve bir y
tensörü üretir. isFinite
öğesini uygular
IEEE-754 spesifikasyonundan bu işlemi yapma. Miktarlandırılmış türlerde sonuç,
her zaman true
.
Girişler
Şirket | Ad | Tür | Sınırlamalar |
---|---|---|---|
(I1) | x |
kayan nokta tipi veya tensör başına miktarlandırılmış tensör tensörü | (C1) |
Çıkışlar
Ad | Tür | Sınırlamalar |
---|---|---|
y |
boole türündeki tensor | (C1) |
Sınırlamalar
- (C1)
shape(x) = shape(y)
.
Örnekler
// Logical values: -Inf, +Inf, NaN, ...
// %x: [0xFFF0000000000000, 0x7FF0000000000000, 0x7FF8000000000000, -10.0, -0.0, 0.0, 10.0]
%y = "stablehlo.is_finite"(%x) : (tensor<7xf64) -> tensor<7xi1>
// %y: [false, false, false, true, true, true, true]
log
Anlam
operand
tensörü üzerinde öğe tabanlı logaritma işlemi gerçekleştirir ve
result
tensörü. Öğe türüne bağlı olarak aşağıdakiler gerçekleşir:
- Kayan reklamlar için: IEEE-754'ten
log
. - Karmaşık sayılar için: karmaşık logaritma.
- Miktarlanmış türler için:
dequantize_op_quantize(log, operand, type(result))
.
Girişler
Şirket | Ad | Tür | Sınırlamalar |
---|---|---|---|
(I1) | operand |
kayan nokta veya karmaşık tür ya da tensör başına miktarlandırılmış tensör tensörü | (C1) |
Çıkışlar
Ad | Tür | Sınırlamalar |
---|---|---|
result |
kayan nokta veya karmaşık tür ya da tensör başına miktarlandırılmış tensör tensörü | (C1) |
Sınırlamalar
- (C1)
baseline_type(operand) = baseline_type(result)
.
Örnekler
// %operand: [[1.0, 2.0], [3.0, 4.0]]
%result = "stablehlo.log"(%operand) : (tensor<2x2xf64>) -> tensor<2x2xf64>
// %result: [[0.0, 0.69314718055994529], [1.0986122886681098, 1.3862943611198906]]
log_plus_one
Anlam
operand
tensörü üzerinde eleman tabanlı logaritma artı bir işlem gerçekleştirir ve
bir result
tensörü üretir. Öğe türüne bağlı olarak aşağıdakiler gerçekleşir:
- Kayan reklamlar için: IEEE-754'ten
logp1
. - Karmaşık sayılar için: karmaşık logaritma artı bir.
- Ölçülen türler için:
dequantize_op_quantize(log_plus_one, operand, type(result))
Girişler
Şirket | Ad | Tür | Sınırlamalar |
---|---|---|---|
(I1) | operand |
kayan nokta veya karmaşık tür ya da tensör başına miktarlandırılmış tensör tensörü | (C1) |
Çıkışlar
Ad | Tür | Sınırlamalar |
---|---|---|
result |
kayan nokta veya karmaşık tür ya da tensör başına miktarlandırılmış tensör tensörü | (C1) |
Sınırlamalar
- (C1)
baseline_type(operand) = baseline_type(result)
.
Örnekler
// %operand: [0.0, -0.999, 7.0, 6.38905621, 15.0]
%result = "stablehlo.log_plus_one"(%operand) : (tensor<5xf64>) -> tensor<5xf64>
// %result: [0.0, -6.90776825, 2.07944155, 2.0, 2.77258873]
lojistik
Anlam
operand
tensörü üzerinde öğe tabanlı lojistik işlem gerçekleştirir ve
result
tensörü. Öğe türüne bağlı olarak aşağıdakiler gerçekleşir:
- Kayan reklamlar için: IEEE-754'ten
division(1, addition(1, exp(-x)))
. - Karmaşık sayılar için: karmaşık lojistik.
- Ölçülen türler için:
dequantize_op_quantize(logistic, operand, type(result))
Girişler
Şirket | Ad | Tür | Sınırlamalar |
---|---|---|---|
(I1) | operand |
kayan nokta veya karmaşık tür ya da tensör başına miktarlandırılmış tensör tensörü | (C1) |
Çıkışlar
Ad | Tür | Sınırlamalar |
---|---|---|
result |
kayan nokta veya karmaşık tür ya da tensör başına miktarlandırılmış tensör tensörü | (C1) |
Sınırlamalar
- (C1)
baseline_type(operand) = baseline_type(result)
.
Örnekler
// %operand: [[0.0, 1.0], [2.0, 3.0]]
%result = "stablehlo.logistic"(%operand) : (tensor<2x2xf64>) -> tensor<2x2xf64>
// %result: [[0.5, 0.73105858], [0.88079708, 0.95257413]]
harita
Anlam
dimensions
boyunca inputs
konumuna computation
harita işlevini uygular ve
bir result
tensörü üretir.
Daha resmi olarak, result[result_index] = computation(inputs...[result_index])
.
Girişler
Şirket | Ad | Tür | Sınırlamalar |
---|---|---|---|
(I1) | inputs |
değişken sayıda tensör veya tensör başına miktarlandırılmış tensör | (C1-C4) |
(I2) | dimensions |
si64 türünde 1 boyutlu tensör sabiti |
(C3) |
(I3) | computation |
işlev | (C4) |
Çıkışlar
Ad | Tür | Sınırlamalar |
---|---|---|
result |
tensör veya tensör başına miktarlandırılmış tensör | (C1), (C4) |
Sınırlamalar
- (C1)
shape(inputs...) = shape(result)
. - (C2)
0 < size(inputs) = N
. - (C3)
dimensions = range(rank(inputs[0]))
. - (C4)
computation
,(tensor<E0>, ..., tensor<EN-1>) -> tensor<E'>
türünde buradaEi = element_type(inputs[i])
veE' = element_type(result)
.
Örnekler
// %input0: [[0, 1], [2, 3]]
// %input1: [[4, 5], [6, 7]]
%result = "stablehlo.map"(%input0, %input1) ({
^bb0(%arg0: tensor<i64>, %arg1: tensor<i64>):
%0 = stablehlo.multiply %arg0, %arg1 : tensor<i64>
stablehlo.return %0 : tensor<i64>
}) {
dimensions = array<i64: 0, 1>
} : (tensor<2x2xi64>, tensor<2x2xi64>) -> tensor<2x2xi64>
// %result: [[0, 5], [12, 21]]
maksimum
Anlam
lhs
ve rhs
tensörleri üzerinde öğe bazında maksimum işlemi gerçekleştirir ve bir
result
tensörü. Öğe türüne bağlı olarak aşağıdakiler gerçekleşir:
- Booleler için: mantıksal VEYA.
- Tam sayılar için: Maksimum tam sayı.
- Kayan reklamlar için: IEEE-754'ten
maximum
. - Karmaşık sayılar için:
(real, imaginary)
çifti için sözlüksel maksimum değer. Karmaşık sayılarda sıralama yaratmak, şaşırtıcı anlamlar ya da Bu nedenle gelecekte karmaşık sayılar için desteği kaldırmayı planlıyoruz. (#560). - Ölçülen türler için:
dequantize_op_quantize(maximum, lhs, rhs, type(result))
.
Girişler
Şirket | Ad | Tür | Sınırlamalar |
---|---|---|---|
(I1) | lhs |
tensör veya tensör başına miktarlandırılmış tensör | (C1) |
(I2) | rhs |
tensör veya tensör başına miktarlandırılmış tensör | (C1) |
Çıkışlar
Ad | Tür | Sınırlamalar |
---|---|---|
result |
tensör veya tensör başına miktarlandırılmış tensör | (C1) |
Sınırlamalar
- (C1)
baseline_type(lhs) = baseline_type(rhs) = baseline_type(result)
.
Örnekler
// %lhs: [[1, 2], [7, 8]]
// %rhs: [[5, 6], [3, 4]]
%result = "stablehlo.maximum"(%lhs, %rhs) : (tensor<2x2xi32>, tensor<2x2xi32>) -> tensor<2x2xi32>
// %result: [[5, 6], [7, 8]]
minimum
Anlam
lhs
ve rhs
tensörleri üzerinde öğe bazında minimum işlem gerçekleştirir ve
result
tensörü. Öğe türüne bağlı olarak aşağıdakiler gerçekleşir:
- Boolelar için: mantıksal VE.
- Tam sayılar için: Minimum tam sayı.
- Kayan reklamlar için: IEEE-754'ten
minimum
. - Karmaşık sayılar için:
(real, imaginary)
çifti için sözlüksel minimum. Karmaşık sayılarda sıralama yaratmak, şaşırtıcı anlamlar ya da Bu nedenle gelecekte karmaşık sayılar için desteği kaldırmayı planlıyoruz. (#560). - Ölçülen türler için:
dequantize_op_quantize(minimum, lhs, rhs, type(result))
.
Girişler
Şirket | Ad | Tür | Sınırlamalar |
---|---|---|---|
(I1) | lhs |
tensör veya tensör başına miktarlandırılmış tensör | (C1) |
(I2) | rhs |
tensör veya tensör başına miktarlandırılmış tensör | (C1) |
Çıkışlar
Ad | Tür | Sınırlamalar |
---|---|---|
result |
tensör veya tensör başına miktarlandırılmış tensör | (C1) |
Sınırlamalar
- (C1)
baseline_type(lhs) = baseline_type(rhs) = baseline_type(result)
.
Örnekler
// %lhs: [[1, 2], [7, 8]]
// %rhs: [[5, 6], [3, 4]]
%result = "stablehlo.minimum"(%lhs, %rhs) : (tensor<2x2xi32>, tensor<2x2xi32>) -> tensor<2x2xi32>
// %result: [[1, 2], [3, 4]]
Çarpma
Anlam
İki lhs
ve rhs
tensöründen element düzeyinde ürün gerçekleştirir ve bir üretir
result
tensörü. Öğe türüne bağlı olarak aşağıdakiler gerçekleşir:
- Boolelar için: mantıksal VE.
- Tam sayılar için: tamsayıları çarpma.
- Kayan reklamlar için: IEEE-754'ten
multiplication
. - Karmaşık sayılar için: karmaşık çarpma.
- Ölçülen türler için:
dequantize_op_quantize(multiply, lhs, rhs, type(result))
.
Girişler
Şirket | Ad | Tür | Sınırlamalar |
---|---|---|---|
(I1) | lhs |
tensör veya tensör başına miktarlandırılmış tensör | (C1) |
(I2) | rhs |
tensör veya tensör başına miktarlandırılmış tensör | (C1) |
Çıkışlar
Ad | Tür | Sınırlamalar |
---|---|---|
result |
tensör veya tensör başına miktarlandırılmış tensör | (C1) |
Sınırlamalar
- (C1)
baseline_type(operand) = baseline_type(result)
.
Örnekler
// %lhs: [[1, 2], [3, 4]]
// %rhs: [[5, 6], [7, 8]]
%result = "stablehlo.multiply"(%lhs, %rhs) : (tensor<2x2xi32>, tensor<2x2xi32>) -> tensor<2x2xi32>
// %result: [[5, 12], [21, 32]]
işareti değiştir
Anlam
operand
tensörü için öğe tabanlı olumsuzlama gerçekleştirir ve bir result
üretir
tensördür. Öğe türüne bağlı olarak aşağıdakiler gerçekleşir:
- İşaretli tam sayılar için: Tam sayı olumsuzlama.
- İmzasız tam sayılar için: bitcast'ten işaretli tam sayıya, tamsayı olumsuzlama, bitcast imzasız tam sayıya geri döner.
- Kayan reklamlar için: IEEE-754'ten
negate
. - Karmaşık sayılar için: karmaşık olumsuzlama.
- Ölçülen türler için:
dequantize_op_quantize(negate, operand, type(result))
Girişler
Şirket | Ad | Tür | Sınırlamalar |
---|---|---|---|
(I1) | operand |
tam sayı, kayan nokta veya karmaşık tür ya da tensör başına miktarlandırılmış tensör tensörü | (C1) |
Çıkışlar
Ad | Tür | Sınırlamalar |
---|---|---|
result |
tam sayı, kayan nokta veya karmaşık tür ya da tensör başına miktarlandırılmış tensör tensörü | (C1) |
Sınırlamalar
- (C1)
baseline_type(operand) = baseline_type(result)
.
Örnekler
// Negation operation with integer Tensors
// %operand: [0, -2]
%result = "stablehlo.negate"(%operand) : (tensor<2xi32>) -> tensor<2xi32>
// %result: [0, 2]
// Negation operation with with complex tensors
// %operand: (2.5, 0.0)
%result = "stablehlo.negate"(%operand) : (tensor<1xcomplex<f32>>) -> tensor<1xcomplex<f32>>
// %result: [-2.5, -0.0]
değil
Anlam
operand
tensörü için öğe düzeyinde NOT gerçekleştirir ve bir result
tensörü üretir.
Öğe türüne bağlı olarak aşağıdakiler gerçekleşir:
- Boolelar için: mantıksal DEĞİL.
- Tam sayılar için: bit tabanlı DEĞİL.
Bağımsız değişkenler
Ad | Tür | Sınırlamalar |
---|---|---|
operand |
boole veya tam sayı türündeki tensor | (C1) |
Çıkışlar
Ad | Tür | Sınırlamalar |
---|---|---|
result |
boole veya tam sayı türündeki tensor | (C1) |
Sınırlamalar
- (C1)
type(operand) = type(result)
.
Örnekler
// Bitwise operation with with integer tensors
// %operand: [[1, 2], [3, 4]]
%result = "stablehlo.not"(%operand) : (tensor<2x2xi32>) -> tensor<2x2xi32>
// %result: [[-2, -3], [-4, -5]]
// Bitwise operation with with boolean tensors
// %operand: [true, false]
%result = "stablehlo.not"(%operand) : (tensor<2xi1>) -> tensor<2xi1>
// %result: [false, true]
optimization_barrier
Anlam
operand
öğesini oluşturan işlemlerin,
result
öğesine bağlı olan ve derleyici dönüşümlerini engelleyen işlemler
engelleri aşmanızı sağlar. Bunun dışında, işlem
bir kimlik (ör. result = operand
).
Bağımsız değişkenler
Ad | Tür | Sınırlamalar |
---|---|---|
operand |
değişken tensör, tensör başına miktarlandırılmış tensör veya jeton sayısı | (C1) |
Çıkışlar
Ad | Tür | Sınırlamalar |
---|---|---|
result |
değişken tensör, tensör başına miktarlandırılmış tensör veya jeton sayısı | (C1) |
Sınırlamalar
- (C1)
type(operand...) = type(result...)
.
Örnekler
// %operand0: 0.0
// %operand1: 1.0
%result0, %result1 = "stablehlo.optimization_barrier"(%operand0, %operand1) : (tensor<f32>, tensor<f32>) -> (tensor<f32>, tensor<f32>)
// %result0: 0.0
// %result1: 1.0
veya
Anlam
lhs
ve rhs
iki tensörü için öğe düzeyinde VEYA gerçekleştirir ve bir result
üretir
tensördür. Öğe türüne bağlı olarak aşağıdakiler gerçekleşir:
- Boolelar için: mantıksal VEYA.
- Tam sayılar için: bit tabanlı VEYA.
Girişler
Şirket | Ad | Tür | Sınırlamalar |
---|---|---|---|
(I1) | lhs |
tam sayı veya boole türündeki tensör | (C1) |
(I2) | rhs |
tam sayı veya boole türündeki tensör | (C1) |
Çıkışlar
Ad | Tür | Sınırlamalar |
---|---|---|
result |
tam sayı veya boole türündeki tensör | (C1) |
Sınırlamalar
- (C1)
type(lhs) = type(rhs) = type(result)
.
Örnekler
// Bitwise operation with with integer tensors
// %lhs: [[1, 2], [3, 4]]
// %rhs: [[5, 6], [7, 8]]
%result = "stablehlo.or"(%lhs, %rhs) : (tensor<2x2xi32>, tensor<2x2xi32>) -> tensor<2x2xi32>
// %result: [[5, 6], [7, 12]]
// Logical operation with with boolean tensors
// %lhs: [[false, false], [true, true]]
// %rhs: [[false, true], [false, true]]
%result = "stablehlo.or"(%lhs, %rhs) : (tensor<2x2xi1>, tensor<2x2xi1>) -> tensor<2x2xi1>
// %result: [[false, true], [true, true]]
feed dışı
Anlam
Out feed'e inputs
yazar ve result
jetonu oluşturur.
outfeed_config
anlamı, uygulama tanımlıdır.
Girişler
Şirket | Ad | Tür |
---|---|---|
(I1) | inputs |
değişken sayıda tensör veya nicel tensör |
(I2) | token |
token |
(I3) | outfeed_config |
string türündeki sabit |
Çıkışlar
Ad | Tür |
---|---|
result |
token |
Örnekler
%result = "stablehlo.outfeed"(%input0, %token) {
outfeed_config = ""
} : (tensor<2x2x2xi64>, !stablehlo.token) -> !stablehlo.token
dolgu
Anlam
operand
öğesini, tensörün çevresindeki ve öğeler arasında dolgu yaparak genişletir
değeri verilen padding_value
ile tensörün değeri.
edge_padding_low
ve edge_padding_high
, eklenen dolgu miktarını belirtir
düşük uçta (endeks 0'ın yanında) ve üst uçta (en yüksek endeks yanında)
tıklayın. Dolgu miktarı negatif olabilir. Burada,
negatif dolgunun mutlak değeri, kaldırılacak öğe sayısını gösterir
belirtilen boyuttan çıkarılacak.
interior_padding
, herhangi bir ikisi arasına eklenen dolgu miktarını belirtir
öğeler eklemekten çekinmeyin. İç dolgu meydana geliyor
negatif kenar dolgusu, öğeleri kenar dolgusundan kaldıracak şekilde
iç dolgulu işlenene göre.
Daha resmi olarak, result[result_index]
şu şekilde tanımlanır:
- Şu durumda
operand[operand_index]
result_index = edge_padding_low + operand_index * (interior_padding + 1)
. - Aksi takdirde
padding_value
.
Girişler
Şirket | Ad | Tür | Sınırlamalar |
---|---|---|---|
(I1) | operand |
tensör veya tensör başına miktarlandırılmış tensör | (C1), (C2), (C4) |
(I2) | padding_value |
0 boyutlu tensör veya tensör başına miktarlandırılmış tensör | (C1) |
(I3) | edge_padding_low |
si64 türünde 1 boyutlu tensör sabiti |
(C1), (C4) |
(I4) | edge_padding_high |
si64 türünde 1 boyutlu tensör sabiti |
(C1), (C4) |
(I5) | interior_padding |
si64 türünde 1 boyutlu tensör sabiti |
(C2-C4) |
Çıkışlar
Ad | Tür | Sınırlamalar |
---|---|---|
result |
tensör veya tensör başına miktarlandırılmış tensör | (C3-C6) |
Sınırlamalar
- (C1)
element_type(operand) = element_type(padding_value) = element_type(result)
. - (C2)
size(edge_padding_low) = size(edge_padding_high) = size(interior_padding) = rank(operand)
. - (C3)
0 <= interior_padding
. - (C4)
shape(result) = shape(operand) + edge_padding_low + max(shape(operand) - 1, 0) * interior_padding + edge_padding_high
Örnekler
// %operand: [
// [1, 2, 3],
// [4, 5, 6]
// ]
// %padding_value: 0
%result = "stablehlo.pad"(%operand, %padding_value) {
edge_padding_low = array<i64: 0, 1>,
edge_padding_high = array<i64: 2, 1>,
interior_padding = array<i64: 1, 2>
} : (tensor<2x3xi32>, tensor<i32>) -> tensor<5x9xi32>
// %result: [
// [0, 1, 0, 0, 2, 0, 0, 3, 0],
// [0, 0, 0, 0, 0, 0, 0, 0, 0],
// [0, 4, 0, 0, 5, 0, 0, 6, 0],
// [0, 0, 0, 0, 0, 0, 0, 0, 0],
// [0, 0, 0, 0, 0, 0, 0, 0, 0]
// ]
partition_id
Anlam
Mevcut işlemin partition_id
kadarını oluşturur.
Çıkışlar
Ad | Tür |
---|---|
result |
ui32 türünde 0 boyutlu tensör |
Örnekler
%result = "stablehlo.partition_id"() : () -> tensor<ui32>
patlatma
Anlam
operand
tensöründe ayarlanan bit sayısının öğe bazında sayımını yapar
ve bir result
tensörü üretir.
Girişler
Şirket | Ad | Tür | Sınırlamalar |
---|---|---|---|
(I1) | operand |
tam sayı türündeki tensör | (C1) |
Çıkışlar
Ad | Tür | Sınırlamalar |
---|---|---|
result |
tam sayı türündeki tensör | (C1) |
Sınırlamalar
- (C1)
type(operand) = type(result)
.
Örnekler
// %operand: [0, 1, 2, 127]
%result = "stablehlo.popcnt"(%operand) : (tensor<4xi64>) -> tensor<4xi64>
// %result: [0, 1, 1, 7]
güç
Anlam
rhs
tensörü ile lhs
tensörü için öğe düzeyinde üsleme gerçekleştirir ve
bir result
tensörü üretir. Öğe türüne bağlı olarak aşağıdakiler gerçekleşir:
- Tam sayılar için: tam sayı üssü.
- Kayan reklamlar için: IEEE-754'ten
pow
. - Karmaşık sayılar için: karmaşık üsleme.
- Miktarlanmış türler için:
dequantize_op_quantize(power, lhs, rhs, type(result))
.
Girişler
Şirket | Ad | Tür | Sınırlamalar |
---|---|---|---|
(I1) | lhs |
tam sayı, kayan nokta veya karmaşık tür ya da tensör başına miktarlandırılmış tensör tensörü | (C1) |
(I2) | rhs |
tam sayı, kayan nokta veya karmaşık tür ya da tensör başına miktarlandırılmış tensör tensörü | (C1) |
Çıkışlar
Ad | Tür | Sınırlamalar |
---|---|---|
result |
tam sayı, kayan nokta veya karmaşık tür ya da tensör başına miktarlandırılmış tensör tensörü | (C1) |
Sınırlamalar
- (C1)
baseline_type(operand) = baseline_type(result)
.
Örnekler
// %lhs: [-2.0, -0.0, -36.0, 5.0, 3.0, 10000.0]
// %rhs: [2.0, 2.0, 1.1, 2.0, -1.0, 10.0]
%result = "stablehlo.power"(%lhs, %rhs) : (tensor<6xf64>, tensor<6xf64>) -> tensor<6xf64>
// %result: [4.0, 0.0, -nan, 25.0, 0.333333343, inf]
gerçek
Anlam
operand
öğesinden gerçek kısmı eleman olarak çıkarır ve bir result
üretir
tensördür. Daha resmi olarak, her öğe için x
:
real(x) = is_complex(x) ? real_part(x) : x
.
Girişler
Şirket | Ad | Tür | Sınırlamalar |
---|---|---|---|
(I1) | operand |
kayan nokta veya karmaşık türde tensor | (C1), (C2) |
Çıkışlar
Ad | Tür | Sınırlamalar |
---|---|---|
result |
kayan nokta türünün tensörü | (C1), (C2) |
Sınırlamalar
- (C1)
shape(result) = shape(operand)
. - (C2)
element_type(result)
şu şekilde tanımlanır:is_complex(operand)
isecomplex_element_type(element_type(operand))
.- Aksi takdirde
element_type(operand)
.
Örnekler
// %operand: [(1.0, 2.0), (3.0, 4.0)]
%result = "stablehlo.real"(%operand) : (tensor<2xcomplex<f32>>) -> tensor<2xf32>
// %result: [1.0, 3.0]
gelen
Anlam
channel_id
ile bir kanaldan veri alır ve results
üretir.
is_host_transfer
değeri true
ise işlem,
ana bilgisayar. Aksi takdirde, verileri başka bir cihazdan aktarır. Bu,
tanımlanmıştır. Bu işaret,
channel_type
, gelecekte bunlardan yalnızca birini tutmayı planlıyoruz
(#666).
results
, başta gelen yük değerlerinden ve
bakın. Gelecekte yükü ve jetonu ikiye bölmeyi planlıyoruz.
Netliği artırmak için ayrı çıktılar
(#670).
Girişler
Şirket | Ad | Tür | Sınırlamalar |
---|---|---|---|
(I1) | token |
token |
(C4) |
(I2) | channel_id |
si64 türündeki sabit |
|
(I3) | channel_type |
DEVICE_TO_DEVICE ve HOST_TO_DEVICE sıralaması |
(C1) |
(I4) | is_host_transfer |
i1 türündeki sabit |
(C1) |
Çıkışlar
Ad | Tür | Sınırlamalar |
---|---|---|
results |
değişken tensör, nicel tensör veya jeton sayısı | (C2-C4) |
Sınırlamalar
- (C1)
channel_type
şu şekilde tanımlanır:is_host_transfer = true
iseHOST_TO_DEVICE
,- Aksi takdirde
DEVICE_TO_DEVICE
.
- (C2)
0 < size(results)
. - (C3)
is_empty(result[:-1])
veyais_tensor(type(results[:-1]))
. - (C4)
is_token(type(results[-1]))
Örnekler
%results0, %results1 = "stablehlo.recv"(%token) {
channel_handle = #stablehlo.channel_handle<handle = 1, type = 3>,
is_host_transfer = true
} : (!stablehlo.token) -> (tensor<2x2xi64>, !stablehlo.token)
reduce
Anlam
inputs
ve init_values
aralığına body
azaltma işlevi uygular
dimensions
olup results
tensör üretir.
İndirimlerin sırası uygulama tanımlıdır. Diğer bir deyişle body
ve
init_values
, işlemin şunu ürettiğini garanti etmek için bir monoid oluşturmalıdır:
tüm uygulamalarda aynı sonuçlar elde edilmesine
yardımcı olur. Ancak bu koşul
pek çok popüler indirim için geçerli değildir. Ör. kayan nokta eklemesi
init_values
için body
ve sıfır değerleri monoid oluşturmaz çünkü
kayan nokta eklemesi ilişkisel değildir.
Daha resmi dilde, results...[j0, ..., jR-1] = reduce(input_slices_converted)
burada:
input_slices = inputs...[j0, ..., :, ..., jR-1]
, burada:
eklenir saat:dimensions
.input_slices_converted = to_destination_type(input_slices..., type(func_inputs(body)[:len(func_inputs(body))//2])...)
.init_values_converted = to_destination_type(init_values..., type(func_inputs(body)[len(func_inputs(body))//2:])...)
.- Bazı ikili ağaçlar için
reduce(input_slices_converted) = exec(schedule)
schedule
burada:exec(node) = body(exec(node.left), exec(node.right))
.exec(leaf) = leaf.value
.
schedule
, sırasıyla şunları içerir:- Şu kampanyadaki tüm
index
içininput_slices_converted...[index]
değerleri:index_space(input_slices_converted)
, artan sözlük sıralamasında /index
. - Uygulamanın tanımlı bir
Uygulama tanımlı konumlarda
init_values_converted
.
- Şu kampanyadaki tüm
Girişler
Şirket | Ad | Tür | Sınırlamalar |
---|---|---|---|
(I1) | inputs |
değişken sayıda tensör veya tensör başına miktarlandırılmış tensör | (C1-C4), (C6), (C7) |
(I2) | init_values |
0 boyutlu tensörlerin veya tensör başına miktarlandırılmış tensörlerin değişken sayısı | (C2), (C3) |
(I3) | dimensions |
si64 türünde 1 boyutlu tensör sabiti |
(C4), (C5), (C7) |
(I4) | body |
işlev | (C6) |
Çıkışlar
Ad | Tür | Sınırlamalar |
---|---|---|
results |
değişken sayıda tensör veya tensör başına miktarlandırılmış tensör | (C3), (C7), (C8) |
Sınırlamalar
- (C1)
same(shape(inputs...))
. - (C2)
element_type(inputs...) = element_type(init_values...)
. - (C3)
0 < size(inputs) = size(init_values) = size(results) = N
. - (C4)
0 <= dimensions < rank(inputs[0])
- (C5)
is_unique(dimensions)
- (C6)
body
,(tensor<E0>, ..., tensor<EN-1>, tensor<E0>, ...,
türündetensor<EN-1>) -> (tensor<E0>, ..., tensor<EN-1>)
burada:is_promotable(element_type(inputs[i]), Ei)
. - (C7)
shape(results...) = shape(inputs...)
dışında, boyutdimensions
değerine karşılık geleninputs...
boyutları dahil edilmemiştir. - (C8)
[0,N)
kapsamındaki tümi
içinelement_type(results[i]) = Ei
.
Örnekler
// %input = [[0, 1, 2, 3, 4, 5]]
// %init_value = 0
%result = "stablehlo.reduce"(%input, %init_value) ({
^bb0(%arg0: tensor<i64>, %arg1: tensor<i64>):
%0 = "stablehlo.add"(%arg0, %arg1) : (tensor<i64>, tensor<i64>) -> tensor<i64>
"stablehlo.return"(%0) : (tensor<i64>) -> ()
}) {
dimensions = array<i64: 1>
} : (tensor<1x6xi64>, tensor<i64>) -> tensor<1xi64>
// %result = [15]
reduce_precision
Anlam
operand
değerini başka bir kayan nokta türüne öğe bazında dönüştürür
exponent_bits
ve mantissa_bits
kullanan ve orijinal haline döndüren bir sürüm
kayan nokta türünü ifade eder ve bir output
tensörü oluşturur.
Daha resmi dilde:
- Orijinal değerin mantissa bitleri orijinal değeri yuvarlayacak şekilde güncellenir
değeri,
mantissa_bits
ile temsil edilebilecek en yakın değereroundToIntegralTiesToEven
semantiği. - Bu durumda
mantissa_bits
, şu mantissa bitlerinden küçükse, orijinal değer ise mantissa bitlerimantissa_bits
olacak şekilde kısaltılır. - Bu durumda, ara sonucun üs bitleri
exponent_bits
tarafından sağlanan aralık: Ara sonuç sonsuza kadar gider veya orijinal imza. - Miktarı ölçülmüş türlerde,
dequantize_op_quantize( lambda operand: reduce_precision(operand, exponent_bits, mantissa_bits), operand, type(result))
gerçekleştirir.
Girişler
Şirket | Ad | Tür | Sınırlamalar |
---|---|---|---|
(I1) | operand |
kayan nokta tipi veya tensör başına miktarlandırılmış tensör tensörü | (C1) |
(I2) | exponent_bits |
si32 türündeki sabit |
(C2) |
(I3) | mantissa_bits |
si32 türündeki sabit |
(C3) |
Çıkışlar
Ad | Tür | Sınırlamalar |
---|---|---|
output |
kayan nokta tipi veya tensör başına miktarlandırılmış tensör tensörü | (C1) |
Sınırlamalar
- (C1)
baseline_type(operand) = baseline_type(output)
. - (C2)
1 <= exponent_bits
. - (C3)
0 <= mantissa_bits
.
Örnekler
// Logical values: +Inf, NaN, +Denormal, 0.0, 65519.0, 65520.0
// %operand: [0x7FF0000000000000, 0x7FFFFFFFFFFFFFFF, 0x0000000000000001, 0.0, 65519.0, 65520.0]
%output = "stablehlo.reduce_precision"(%operand) {
exponent_bits = 5 : i32,
mantissa_bits = 10 : i32
} : (tensor<6xf64>) -> tensor<6xf64>
// Logical values: +Inf, NaN, 0.0, 0.0, 65504.0, +Inf
// %output: [0x7FF0000000000000, 0x7FFFFFFFFFFFFFFF, 0.0, 0.0, 65504.0, 0x7FF0000000000000]
reduce_scatter
Anlam
StableHLO süreç ızgarasındaki her süreç grubunda azaltma,
her işlemdeki operand
tensörü değerleri üzerinden computations
kullanılarak,
scatter_dimension
boyunca azaltma sonucunu parçalara ve parçalara böler
result
oluşturmak için işlemler arasındaki bölünen kısımları ayırın.
İşlem, StableHLO süreç ızgarasını process_groups
olarak ayırır.
şu şekilde tanımlanır:
cross_replica(replica_groups)
. (channel_id <= 0 and use_global_device_ids = false
ise)cross_replica_and_partition(replica_groups)
. (channel_id > 0 and use_global_device_ids = false
ise)flattened_ids(replica_groups)
. (channel_id > 0 and use_global_device_ids = true
ise)
Daha sonra, her process_group
içinde:
reduced_value = all_reduce(operand, replica_groups, channel_id, use_global_device_ids, computation)
.parts@sender = split(reduced_value@sender, dim(process_groups, 1), scatter_dimension)
.- Şu kapsamdaki tüm
sender
içinresult@receiver = parts@sender[receiver_index]
:process_group
(buradareceiver_index = process_group.index(receiver)
).
Girişler
Şirket | Ad | Tür | Sınırlamalar |
---|---|---|---|
(I1) | operand |
tensör veya tensör başına miktarlandırılmış tensör | (C1), (C2), (C7), (C8) |
(I2) | scatter_dimension |
si64 türündeki sabit |
(C1), (C2), (C8) |
(I3) | replica_groups |
si64 türünde 2 boyutlu tensör sabiti |
(C3-C5) |
(I4) | channel_id |
si64 türündeki sabit |
(C6) |
(I5) | use_global_device_ids |
i1 türündeki sabit |
(C6) |
(I6) | computation |
işlev | (C7) |
Çıkışlar
Ad | Tür | Sınırlamalar |
---|---|---|
result |
tensör veya tensör başına miktarlandırılmış tensör | (C8-C9) |
Sınırlamalar
- (C1)
dim(operand, scatter_dimension) % dim(process_groups, 1) = 0
. - (C2)
0 <= scatter_dimension < rank(operand)
. - (C3)
is_unique(replica_groups)
. - (C4)
size(replica_groups)
şu şekilde tanımlanır:cross_replica
kullanılıyorsanum_replicas
.cross_replica_and_partition
kullanılıyorsanum_replicas
.flattened_ids
kullanılıyorsanum_processes
.
- (C5)
0 <= replica_groups < size(replica_groups)
- (C6)
use_global_device_ids = true
isechannel_id > 0
. - (C7)
computation
,(tensor<E>, tensor<E>) -> (tensor<E>)
türünde olup buradais_promotable(element_type(operand), E)
. - (C8)
shape(result) = shape(operand)
hariç:dim(result, scatter_dimension) = dim(operand, scatter_dimension) / dim(process_groups, 1)
.
- (C9)
element_type(result) = E
.
Örnekler
// num_replicas: 2
// num_partitions: 1
// %operand@(0, 0): [[1, 2, 3, 4],
// [5, 6, 7, 8]]
// %operand@(1, 0): [[9, 10, 11, 12],
// [13, 14, 15, 16]]
%result = "stablehlo.reduce_scatter"(%operand) ({
^bb0(%arg0: tensor<i64>, %arg1: tensor<i64>):
%0 = "stablehlo.add"(%arg0, %arg1) : (tensor<i64>, tensor<i64>) -> tensor<i64>
"stablehlo.return"(%0) : (tensor<i64>) -> ()
}) {
scatter_dimension = 1 : i64,
replica_groups = dense<[[0, 1]]> : tensor<1x2xi64>,
channel_handle = #stablehlo.channel_handle<handle = 0, type = 0>
} : (tensor<2x4xi64>) -> tensor<2x2xi64>
//
// %result@(0, 0): [[10, 12],
// [18, 20]]
// %result@(1, 0): [[14, 16],
// [22, 24]]
reduce_window
Anlam
inputs
ve init_values
aralıklarına body
azaltma işlevi uygular
ve results
üretir.
Aşağıdaki şemada, results...
içindeki öğelerin
Somut bir örnek kullanarak inputs...
.
Daha resmi ifade etmek gerekirse
results...[result_index] = reduce(windows, init_values, axes(inputs...), body)
.
(bkz. azaltma) burada:
padded_inputs = pad(inputs..., init_values..., padding[:, 0], padding[:, 1], base_dilations - 1)
.window_start = result_index * window_strides
.window_end = window_start + (window_dimensions - 1) * window_dilations + 1
.windows = slice(padded_inputs..., window_start, window_end, window_dilations)
.
Girişler
Şirket | Ad | Tür | Sınırlamalar |
---|---|---|---|
(I1) | inputs |
değişken sayıda tensör veya tensör başına miktarlandırılmış tensör | (C1-C4), (C6), (C8), (C10), (C12), (C13), (C15) |
(I2) | init_values |
0 boyutlu tensörlerin veya tensör başına miktarlandırılmış tensörlerin değişken sayısı | (C1), (C13) |
(I3) | window_dimensions |
si64 türünde 1 boyutlu tensör sabiti |
(C4), (C5), (C15) |
(I4) | window_strides |
si64 türünde 1 boyutlu tensör sabiti |
(C6), (C7), (C15) |
(I5) | base_dilations |
si64 türünde 1 boyutlu tensör sabiti |
(C8), (C9), (C15) |
(I6) | window_dilations |
si64 türünde 1 boyutlu tensör sabiti |
(C10), (C11), (C15) |
(I7) | padding |
si64 türünde 2 boyutlu tensör sabiti |
(C12), (C15) |
(I8) | body |
işlev | (C13) |
Çıkışlar
Ad | Tür | Sınırlamalar |
---|---|---|
results |
değişken sayıda tensör veya tensör başına miktarlandırılmış tensör | (C1), (C14-C16) |
Sınırlamalar
- (C1)
0 < size(inputs) = size(init_values) = size(results) = N
. - (C2)
same(shape(inputs...))
. - (C3)
element_type(inputs...) = element_type(init_values...)
. - (C4)
size(window_dimensions) = rank(inputs[0])
- (C5)
0 < window_dimensions
- (C6)
size(window_strides) = rank(inputs[0])
. - (C7)
0 < window_strides
. - (C8)
size(base_dilations) = rank(inputs[0])
- (C9)
0 < base_dilations
. - (C10)
size(window_dilations) = rank(inputs[0])
- (C11)
0 < window_dilations
- (C12)
shape(padding) = [rank(inputs[0]), 2]
- (C13)
body
,(tensor<E0>, ..., tensor<EN-1>, tensor<E0>, ...,
türündetensor<EN-1>) -> (tensor<E0>, ..., tensor<EN-1>)
burada:is_promotable(element_type(inputs[i]), Ei)
. - (C14)
same(shape(results...))
- (C15)
shape(results[0]) = num_windows
; burada:dilated_input_shape = shape(inputs[0]) = 0 ? 0 : (shape(inputs[0]) - 1) * base_dilations + 1
.padded_input_shape = padding[:, 0] + dilated_input_shape + padding[:, 1]
.dilated_window_shape = (window_dimensions - 1) * window_dilations + 1
.is_empty_window = padded_input_shape = 0 || dilated_window_shape > padded_input_shape
.num_windows = is_empty_window ? 0 : floor((padded_input_shape - dilated_window_shape) / window_strides) + 1
.
- (C16)
[0,N)
kapsamındaki tümi
içinelement_type(results[i]) = Ei
.
Örnekler
// %input = [[1, 2], [3, 4], [5, 6]]
// %init_value = 0
%result = "stablehlo.reduce_window"(%input, %init_value) ({
^bb0(%arg0: tensor<i64>, %arg1: tensor<i64>):
%0 = "stablehlo.add"(%arg0, %arg1) : (tensor<i64>, tensor<i64>) -> tensor<i64>
"stablehlo.return"(%0) : (tensor<i64>) -> ()
}) {
window_dimensions = array<i64: 2, 1>,
window_strides = array<i64: 4, 1>,
base_dilations = array<i64: 2, 1>,
window_dilations = array<i64: 3, 1>,
padding = dense<[[2, 1], [0, 0]]> : tensor<2x2xi64>
} : (tensor<3x2xi64>, tensor<i64>) -> tensor<2x2xi64>
// %result = [[0, 0], [3, 4]]
kalan
Anlam
lhs
bölünme ve bölen rhs
tensörlerinin öğe bazında kalanlarını gerçekleştirir ve
bir result
tensörü üretir.
Daha resmi ifade etmek gerekirse, sonucun işareti bölmeden alınır ve
sonucun mutlak değeri, her zaman bölenin mutlak değerinden küçüktür.
Kalan değer lhs - d * rhs
olarak hesaplanır. Burada d
değeri şu şekilde bulunur:
- Tam sayılar için:
stablehlo.divide(lhs, rhs)
. - Kayan reklamlar için: IEEE-754'ten yuvarlama özellikli
division(lhs, rhs)
roundTowardZero
. - Karmaşık sayılar için: TBD (#997).
- Ölçülen türler için:
dequantize_op_quantize(remainder, lhs, rhs, type(result))
.
Kayan nokta öğe türlerinde bu işlem,
IEEE-754 spesifikasyonundan d
integral bir değer olduğu remainder
işlemi
çift değerine eşit olan lhs/rhs
tam değerine en yakın.
Girişler
Şirket | Ad | Tür | Sınırlamalar |
---|---|---|---|
(I1) | lhs |
tam sayı, kayan nokta veya karmaşık tür ya da tensör başına miktarlandırılmış tensör tensörü | (C1) |
(I2) | rhs |
tam sayı, kayan nokta veya karmaşık tür ya da tensör başına miktarlandırılmış tensör tensörü | (C1) |
Çıkışlar
Ad | Tür | Sınırlamalar |
---|---|---|
result |
tam sayı, kayan nokta veya karmaşık tür ya da tensör başına miktarlandırılmış tensör tensörü | (C1) |
Sınırlamalar
- (C1)
baseline_type(operand) = baseline_type(result)
.
Örnekler
// %lhs: [17, -17, 17, -17]
// %rhs: [3, 3, -3, -3]
%result = "stablehlo.remainder"(%lhs, %rhs) : (tensor<4xi64>, tensor<4xi64>) -> tensor<4xi64>
// %result: [2, -2, 2, -2]
replica_id
Anlam
Mevcut işlemin replica_id
kadarını oluşturur.
Çıkışlar
Ad | Tür |
---|---|
result |
ui32 türünde 0 boyutlu tensör |
Örnekler
%result = "stablehlo.replica_id"() : () -> tensor<ui32>
yeniden şekillendirme
Anlam
operand
tensörünü bir result
tensörüne yeniden şekillendirir. Kavramsal olarak
aynı standart gösterime sahip olmaya devam eder ancak
potansiyel olarak değişir.
şekil, ör. tensor<2x3xf32>
- tensor<3x2xf32>
veya tensor<6xf32>
.
Daha resmi dilde, result[result_index] = operand[operand_index]
;
result_index
ve operand_index
, sözlükte aynı konuma sahip
index_space(result)
ve index_space(operand)
siparişi.
Girişler
Şirket | Ad | Tür | Sınırlamalar |
---|---|---|---|
(I1) | operand |
tensör veya nicel tensör | (C1-C3) |
Çıkışlar
Ad | Tür | Sınırlamalar |
---|---|---|
result |
tensör veya nicel tensör | (C1-C3) |
Sınırlamalar
- (C1)
element_type(result)
değerini sağlayan:!is_per_axis_quantized(operand)
iseelement_type(operand)
.element_type(operand)
yalnızcaquantization_dimension(operand)
ve Aksi takdirdequantization_dimension(result)
farklı olabilir.
- (C2)
size(operand) = size(result)
. - (C3)
is_per_axis_quantized(operand)
ise:reduce(dims(operand, [0, 1, ..., quantization_dimension(operand) - 1]), init_values=1, dimensions=[0], body=lambda x, y: x * y) = reduce(dims(result, [0, 1, ..., quantization_dimension(result) - 1]), init_values=1, dimensions=[0], body=lambda x, y: x * y)
.dim(operand, quantization_dimension(operand)) = dim(result, quantization_dimension(result))
.reduce(dims(operand, [quantization_dimension(operand) + 1, ..., rank(operand) - 1]), init_values=1, dimensions=[0], body=lambda x, y: x * y) = reduce(dims(result, [quantization_dimension(result) + 1, ..., rank(result) - 1]), init_values=1, dimensions=[0], body=lambda x, y: x * y)
.
Örnekler
// %operand: [[1, 2, 3], [4, 5, 6]]
%result = "stablehlo.reshape"(%operand) : (tensor<2x3xi32>) -> tensor<3x2xi32>
// %result: [[1, 2], [3, 4], [5, 6]]
geri al
Anlam
Belirtilen dimensions
boyunca operand
içindeki öğelerin sırasını tersine çevirir
ve bir result
tensörü üretir. Daha resmi ifade etmek gerekirse
result[result_index] = operand[operand_index]
; burada:
operand_index[d] = dim(result, d) - result_index[d] - 1
.dimensions
içinded
ise.- Aksi takdirde
operand_index[d] = result_index[d]
.
Girişler
Şirket | Ad | Tür | Sınırlamalar |
---|---|---|---|
(I1) | operand |
tensör veya tensör başına miktarlandırılmış tensör | (C1), (C3) |
(I2) | dimensions |
si64 türünde 1 boyutlu tensör sabiti |
(C2), (C3) |
Çıkışlar
Ad | Tür | Sınırlamalar |
---|---|---|
result |
tensör veya tensör başına miktarlandırılmış tensör | (C1), (C3) |
Sınırlamalar
- (C1)
type(operand) = type(result)
. - (C2)
is_unique(dimensions)
. - (C3)
0 <= dimensions < rank(result)
.
Örnekler
// %operand = [[1, 2], [3, 4], [5, 6]]
%result = "stablehlo.reverse"(%operand) {
dimensions = array<i64: 1>
} : (tensor<3x2xi32>) -> tensor<3x2xi32>
// %result: [[2, 1], [4, 3], [6, 5]]
ng
Anlam
rng_distribution
algoritmasını kullanarak rastgele sayılar üretir ve şu sonucu verir:
Belirli bir shape
şeklinin result
tensörü.
rng_distribution = UNIFORM
ise rastgele sayılar oluşturulur
[a, b)
aralığı üzerinde tek tip dağılım uygulanarak. a >= b
ise
davranış tanımsızdır.
rng_distribution = NORMAL
ise rastgele sayılar oluşturulur
ortalama = a
ve standart sapma = b
ile normal dağılımdan sonra.
b < 0
ise davranış tanımsızdır.
Rastgele sayıların tam olarak nasıl oluşturulduğu, uygulama tarafından tanımlanır. Örneğin, deterministik olabilir ya da olmayabilir ve farklı gizli durum:
Birçok paydaşla yapılan görüşmelerde bu fırsat, desteği sonlandırıldı. Bu nedenle gelecekte bu özelliği kaldırmayı planlıyoruz. (#597).
Girişler
Şirket | Ad | Tür | Sınırlamalar |
---|---|---|---|
(I1) | a |
Tam sayı, boole veya kayan nokta türünün 0 boyutlu tensörü | (C1), (C2) |
(I2) | b |
Tam sayı, boole veya kayan nokta türünün 0 boyutlu tensörü | (C1), (C2) |
(I3) | shape |
si64 türünde 1 boyutlu tensör sabiti |
(C3) |
(I4) | rng_distribution |
UNIFORM ve NORMAL sıralaması |
(C2) |
Çıkışlar
Ad | Tür | Sınırlamalar |
---|---|---|
result |
tam sayı, boole veya kayan nokta türünde tensör | (C1-C3) |
Sınırlamalar
- (C1)
element_type(a) = element_type(b) = element_type(result)
. - (C2)
rng_distribution = NORMAL
iseis_float(a)
. - (C3)
shape(result) = shape
.
Örnekler
// %a = 0
// %b = 2
// %shape = [3, 3]
%result = "stablehlo.rng"(%a, %b, %shape) {
rng_distribution = #stablehlo<rng_distribution UNIFORM>
} : (tensor<i32>, tensor<i32>, tensor<2xi64>) -> tensor<3x3xi32>
// %result: [
// [1, 0, 1],
// [1, 1, 1],
// [0, 0, 0]
// ]
rng_bit_generator
Anlam
Tek tip rastgele bitlerle ve güncellenmiş bir çıkış durumuyla doldurulmuş bir output
döndürür
Rastgele sayı oluşturma aracı rng_algorithm
kullanılarak output_state
ilk durumu initial_state
olarak belirler. Çıkışın
deterministik initial_state
işlevi vardır, ancak
belirleyecek olan kişidir.
rng_algorithm
şunlardan biridir:
DEFAULT
: Uygulama tanımlı algoritma.THREE_FRY
: Threefry algoritmasının uygulama tanımlı varyantı.*PHILOX
: Philox algoritmasının uygulama tanımlı varyantı.*
* Bkz. Salmon ve diğerleri. SC 2011 Paralel rastgele sayılar: 1, 2, 3 kadar kolay. ziyaret edin.
Girişler
Şirket | Ad | Tür | Sınırlamalar |
---|---|---|---|
(I1) | rng_algorithm |
DEFAULT , THREE_FRY ve PHILOX sıralaması |
(C2) |
(I2) | initial_state |
ui64 türünde 1 boyutlu tensör |
(C1), (C2) |
Çıkışlar
Ad | Tür | Sınırlamalar |
---|---|---|
output_state |
ui64 türünde 1 boyutlu tensör |
(C1) |
output |
tam sayı veya kayan nokta türünde tensör |
Sınırlamalar
- (C1)
type(initial_state) = type(output_state)
. - (C2)
size(initial_state)
şu şekilde tanımlanır:rng_algorithm = DEFAULT
durumunda uygulama tanımlanır.rng_algorithm = THREE_FRY
ise2
.rng_algorithm = PHILOX
ise2
veya3
.
Örnekler
// %initial_state: [1, 2]
%output_state, %output = "stablehlo.rng_bit_generator"(%initial_state) {
rng_algorithm = #stablehlo<rng_algorithm THREE_FRY>
} : (tensor<2xui64>) -> (tensor<2xui64>, tensor<2x2xui64>)
// %output_state: [1, 6]
// %output: [
// [9236835810183407956, 16087790271692313299],
// [18212823393184779219, 2658481902456610144]
// ]
round_nearest_afz
Anlam
En yakın tam sayıya eleman tabanlı yuvarlama yaparak bağları kopararak
operand
tensöründe sıfırdan başlayarak result
tensörü üretir. Uygulama
IEEE-754 spesifikasyonundan roundToIntegralTiesToAway
işlemini. Örneğin,
nicelikselleştirilmiş türler,
dequantize_op_quantize(round_nearest_afz, operand, type(result))
Girişler
Şirket | Ad | Tür | Sınırlamalar |
---|---|---|---|
(I1) | operand |
kayan nokta tipi veya tensör başına miktarlandırılmış tensör tensörü | (C1) |
Çıkışlar
Ad | Tür | Sınırlamalar |
---|---|---|
result |
kayan nokta tipi veya tensör başına miktarlandırılmış tensör tensörü | (C1) |
Sınırlamalar
- (C1)
baseline_type(operand) = baseline_type(result)
.
Örnekler
// %operand = [-2.5, 0.4, 0.5, 0.6, 2.5]
%result = "stablehlo.round_nearest_afz"(%operand) : (tensor<5xf64>) -> tensor<5xf64>
// %result: [-3.0, 0.0, 1.0, 1.0, 3.0]
round_nearest_even
Anlam
En yakın tam sayıya eleman tabanlı yuvarlama yaparak bağları bozar
operand
tensörü üzerinde çift tam sayıya eşittir ve bir result
üretir
tensördür. IEEE-754'teki roundToIntegralTiesToEven
işlemini uygular
bakın. Miktarı kullanılan türlerde,
dequantize_op_quantize(round_nearest_even, operand, type(result))
Girişler
Şirket | Ad | Tür | Sınırlamalar |
---|---|---|---|
(I1) | operand |
kayan nokta tipi veya tensör başına miktarlandırılmış tensör tensörü | (C1) |
Çıkışlar
Ad | Tür | Sınırlamalar |
---|---|---|
result |
kayan nokta tipi veya tensör başına miktarlandırılmış tensör tensörü | (C1) |
Sınırlamalar
- (C1)
baseline_type(operand) = baseline_type(result)
.
Örnekler
// %operand = [-2.5, 0.4, 0.5, 0.6, 2.5]
%result = "stablehlo.round_nearest_even"(%operand) : (tensor<5xf64>) -> tensor<5xf64>
// %result: [-2.0, 0.0, 0.0, 1.0, 2.0]
rsqrt
Anlam
operand
tensörü üzerinde öğe tabanlı ters karekök işlemi gerçekleştirir.
bir result
tensörü üretir. Öğe türüne bağlı olarak aşağıdakiler gerçekleşir:
- Kayan reklamlar için: IEEE-754'ten
rSqrt
. - Karmaşık sayılar için: karmaşık ters karekök.
- Miktarlanmış türler için:
dequantize_op_quantize(rsqrt, operand, type(result))
.
Girişler
Şirket | Ad | Tür | Sınırlamalar |
---|---|---|---|
(I1) | operand |
kayan nokta veya karmaşık tür ya da tensör başına miktarlandırılmış tensör tensörü | (C1) |
Çıkışlar
Ad | Tür | Sınırlamalar |
---|---|---|
result |
kayan nokta veya karmaşık tür ya da tensör başına miktarlandırılmış tensör tensörü | (C1) |
Sınırlamalar
- (C1)
baseline_type(operand) = baseline_type(result)
.
Örnekler
// %operand: [[1.0, 4.0], [9.0, 25.0]]
%result = "stablehlo.rsqrt"(%operand) : (tensor<2x2xf32>) -> tensor<2x2xf32>
// %result: [[1.0, 0.5], [0.33333343, 0.2]]
dağılım
Anlam
Şu hariç inputs
tensöre eşit results
tensör üretir:
scatter_indices
tarafından belirtilen bazı dilimler ilgili değerlerle güncellenir
updates
, update_computation
kullanılıyor.
Aşağıdaki şemada updates...
içindeki öğelerin,
Somut bir örnek kullanarak results...
. Diyagramda birkaç örnek
updates...
, hangi results...
indekslerinin
anlamına gelir.
Daha resmi dilde, index_space(updates[0])
içindeki tüm update_index
için:
update_scatter_dims = [d for d in axes(updates[0]) and d not in update_window_dims]
.update_scatter_index = update_index[update_scatter_dims...]
.start_index
şu şekilde tanımlanır:si
bireysel olduğuscatter_indices[si0, ..., :, ..., siN]
update_scatter_index
ve:
içine eklenen öğelerindex_vector_dim
< iseindex_vector_dim
dizinirank(scatter_indices)
.- Aksi takdirde
[scatter_indices[update_scatter_index]]
.
axes(inputs[0])
içindekid_input
için,- Şu durumda
full_start_index[d_input] = start_index[d_start]
d_input = scatter_dims_to_operand_dims[d_start]
. - Aksi takdirde
full_start_index[d_input] = 0
.
- Şu durumda
axes(inputs[0])
içindekid_input
için,full_batching_index[d_input] = update_scatter_index[d_start - (d_start < index_vector_dim ? 0 : 1)]
. eğerd_input = input_batching_dims[i_batching]
ved_start = scatter_indices_batching_dims[i_batching]
.- Aksi takdirde
full_batching_index[d_input] = 0
.
update_window_index = update_index[update_window_dims...]
.wi
bireysel olduğufull_window_index = [wi0, ..., 0, ..., wiN]
öğeleriupdate_window_index
içindeki dizinlere eklenir ve0
,inserted_window_dims
veinput_batching_dims
.result_index = full_start_index + full_batching_index + full_window_index
.
Buna göre results = exec(schedule, inputs)
, şu şekilde:
schedule
, şunun uygulama tanımlı permütasyonudur:index_space(updates[0])
.exec([update_index, ...], results) = exec([...], updated_results)
; burada:result_index
,shape(results...)
için sınırların içindeyseupdates_converted = to_destination_type( updates...[update_index], type(func_inputs(update_computation) [len(func_inputs(update_computation))//2:])... )
updated_values = update_computation(results...[result_index], updates_converted)
updated_results
,results...[result_index]
içerenresults
öğesinin bir kopyasıupdated_values...
olarak ayarlandı.- Aksi halde
updated_results = results
.
exec([], results) = results
.
indices_are_sorted
değeri true
ise uygulama,
scatter_indices
, scatter_dims_to_operand_dims
ölçütüne göre sıralanır,
Aksi takdirde davranış tanımsızdır. Daha resmi dilde, şu ülkeden gelen tüm i1 < i2
için:
indices(result)
, full_start_index(i1)
<= full_start_index(i2)
.
unique_indices
değeri true
ise uygulama, tüm öğelerin
Dağılım yapılan result_index
dizin benzersizdir. unique_indices
ise
true
ancak dağılımların dağılımındaki dizinler benzersiz değil, o zaman davranış
tanımlanmadı.
Girişler
Şirket | Ad | Tür | Sınırlamalar |
---|---|---|---|
(I1) | inputs |
değişken sayıda tensör veya tensör başına miktarlandırılmış tensör | (C1), (C2), (C4-C6), (C11), (C13), (C18), (C21), (C23-C24) |
(I2) | scatter_indices |
tam sayı türündeki tensör | (C4), (C15), (C19), (C22) |
(I3) | updates |
değişken sayıda tensör veya tensör başına miktarlandırılmış tensör | (C3-C6), (C8) |
(I4) | update_window_dims |
si64 türünde 1 boyutlu tensör sabiti |
(C2), (C4), (C7-C8) |
(I5) | inserted_window_dims |
si64 türünde 1 boyutlu tensör sabiti |
(C2), (C4), (C9-C11) |
(I6) | input_batching_dims |
si64 türünde 1 boyutlu tensör sabiti |
(C2), (C4), (C9), (C12-13), (C17-18), (C20) |
(I7) | scatter_indices_batching_dims |
si64 türünde 1 boyutlu tensör sabiti |
(C14-C18) |
(I8) | scatter_dims_to_operand_dims |
si64 türünde 1 boyutlu tensör sabiti |
(C19-C21) |
(I9) | index_vector_dim |
si64 türündeki sabit |
(C4), (C16), (C19), (C22) |
(I10) | indices_are_sorted |
i1 türündeki sabit |
|
(I11) | unique_indices |
i1 türündeki sabit |
|
(I12) | update_computation |
işlev | (C23) |
Çıkışlar
Ad | Tür | Sınırlamalar |
---|---|---|
results |
değişken sayıda tensör veya tensör başına miktarlandırılmış tensör | (C24-C25) |
Sınırlamalar
- (C1)
same(shape(inputs...))
. - (C2) `rank(inputs[0]) = boyut(update_window_dims) + boyut(inserted_window_dims)
- size(input_batching_dims)`.
- (C3)
same(shape(updates...))
. - (C4)
shape(updates[0]) = combine(update_scatter_dim_sizes, update_window_dim_sizes)
burada:- Bunun dışında
update_scatter_dim_sizes = shape(scatter_indices)
şuna karşılık gelenscatter_indices
boyut boyutu:index_vector_dim
dahil edilmedi. - Bunun dışında
update_window_dim_sizes <= shape(inputs[0])
inserted_window_dims
değerine karşılık geleninputs[0]
içindeki boyut boyutları veinput_batching_dims
dahil edilmedi. combine
,update_scatter_dim_sizes
değerini İlgili eksenlerdeupdate_scatter_dims
veupdate_window_dim_sizes
kime:update_window_dims
.
- Bunun dışında
- (C5)
0 < size(inputs) = size(updates) = N
- (C6)
element_type(updates...) = element_type(inputs...)
. - (C7)
is_unique(update_window_dims) and is_sorted(update_window_dims)
. - (C8)
0 <= update_window_dims < rank(updates[0])
- (C9)
is_unique(concatenate(inserted_window_dims, input_batching_dims))
- (C10)
is_sorted(inserted_window_dims)
- (C11)
0 <= inserted_window_dims < rank(inputs[0])
- (C12)
is_sorted(input_batching_dims)
- (C13)
0 <= input_batching_dims < rank(inputs[0]))
- (C14)
is_unique(scatter_indices_batching_dims)
- (C15)
0 <= scatter_indices_batching_dims < rank(scatter_indices)
- (C16)
index_vector_dim not in scatter_indices_batching_dims
- (C17)
size(input_batching_dims) == size(scatter_indices_batching_dims)
- (C18)
dim(inputs[0], input_batching_dims...) = dim(scatter_indices, scatter_indices_batching_dims...)
- (C19)
size(scatter_dims_to_operand_dims) = index_vector_dim < rank(scatter_indices) ? dim(scatter_indices, index_vector_dim) : 1
- (C20)
is_unique(concatenate(scatter_dims_to_operand_dims, input_batching_dims))
. - (C21)
0 <= scatter_dims_to_operand_dims < rank(inputs[0])
- (C22)
0 <= index_vector_dim <= rank(scatter_indices)
- (C23)
update_computation
,(tensor<E0>, ..., tensor<EN-1>, tensor<E0>, ..., tensor<EN-1>) -> (tensor<E0>, ..., tensor<EN-1>)
türünde, buradais_promotable(element_type(inputs[i]), Ei)
. - (C24)
shape(inputs...) = shape(results...)
- (C25)
[0,N)
kapsamındaki tümi
içinelement_type(results[i]) = Ei
.
Örnekler
// %input: [
// [
// [[1, 2], [3, 4], [5, 6], [7, 8]],
// [[9, 10],[11, 12], [13, 14], [15, 16]],
// [[17, 18], [19, 20], [21, 22], [23, 24]]
// ],
// [
// [[25, 26], [27, 28], [29, 30], [31, 32]],
// [[33, 34], [35, 36], [37, 38], [39, 40]],
// [[41, 42], [43, 44], [45, 46], [47, 48]]
// ]
// ]
// %scatter_indices: [
// [
// [[0, 0], [1, 0], [2, 1]],
// [[0, 1], [1, 1], [0, 9]]
// ],
// [
// [[0, 0], [2, 1], [2, 2]],
// [[1, 2], [0, 1], [1, 0]]
// ]
// ]
// %update: [
// [
// [[1, 1], [1, 1], [1, 1]],
// [[1, 1], [1, 1], [1, 1]]
// ],
// [
// [[1, 1], [1, 1], [1, 1]],
// [[1, 1], [1, 1], [1, 1]]
// ]
// ]
%result = "stablehlo.scatter"(%input, %scatter_indices, %update) ({
^bb0(%arg0: tensor<i64>, %arg1: tensor<i64>):
%0 = "stablehlo.add"(%arg0, %arg1) : (tensor<i64>, tensor<i64>) -> tensor<i64>
"stablehlo.return"(%0) : (tensor<i64>) -> ()
}) {
scatter_dimension_numbers = #stablehlo.scatter<
update_window_dims = [3, 4],
inserted_window_dims = [1],
input_batching_dims = [0],
scatter_indices_batching_dims = [1],
scatter_dims_to_operand_dims = [2, 1],
index_vector_dim = 3>,
indices_are_sorted = false,
unique_indices = false
} : (tensor<2x3x4x2xi64>, tensor<2x2x3x2xi64>, tensor<2x2x3x2x2xi64>) -> tensor<2x3x4x2xi64>
// %result: [
// [
// [[3, 4], [6, 7], [6, 7], [7, 8]],
// [[9, 10],[11, 12], [15, 16], [17, 18]],
// [[17, 18], [19, 20], [22, 23], [24, 25]]
// ],
// [
// [[25, 26], [28, 29], [30, 31], [31, 32]],
// [[35, 36], [38, 39], [38, 39], [39, 40]],
// [[41, 42], [44, 45], [46, 47], [47, 48]]
// ]
// ]
seç
Anlam
Her öğenin on_true
veyaresult
Karşılık gelen pred
öğesinin değerine göre on_false
tensörü.
Daha resmi olarak, result[result_index] = pred_element ? on_true[result_index] :
on_false[result_index]
(pred_element = rank(pred) = 0 ? pred[] :
pred[result_index]
). Miktarı kullanılan türlerde,
dequantize_select_quantize(pred, on_true, on_false, type(result))
Girişler
Şirket | Ad | Tür | Sınırlamalar |
---|---|---|---|
(I1) | pred |
i1 türündeki tensör |
(C1) |
(I2) | on_true |
tensör veya tensör başına miktarlandırılmış tensör | (C1-C2) |
(I3) | on_false |
tensör veya tensör başına miktarlandırılmış tensör | (C2) |
Çıkışlar
Ad | Tür | Sınırlamalar |
---|---|---|
result |
tensör veya tensör başına miktarlandırılmış tensör | (C2) |
Sınırlamalar
- (C1)
rank(pred) = 0 or shape(pred) = shape(on_true)
. - (C2)
baseline_type(on_true) = baseline_type(on_false) = baseline_type(result)
.
Örnekler
// %pred: [[false, true], [true, false]]
// %on_true: [[1, 2], [3, 4]]
// %on_false: [[5, 6], [7, 8]]
%result = "stablehlo.select"(%pred, %on_true, %on_false) : (tensor<2x2xi1>, tensor<2x2xi32>, tensor<2x2xi32>) -> tensor<2x2xi32>
// %result: [[5, 2], [3, 8]]
select_and_scatter
Anlam
Şu özelliğe göre scatter
kullanarak source
tensöründen gelen değerleri dağıtır:
input
tensöründen reduce_window
sonucun select
kullanılıp şu şekilde üretilir:
bir result
tensör.
Aşağıdaki şemada, result
içindeki öğelerin
Somut bir örnek kullanarak operand
ve source
.
Daha resmi dilde:
Aşağıdaki girişlerle
selected_values = reduce_window_without_init(...)
:inputs = [operand].
window_dimensions
,window_strides
vepadding
olduğu gibi kullanılır.base_dilations = windows_dilations = 1
.body
şu şekilde tanımlanır:
def body(arg0: tensor<E>, arg1: tensor<E>) -> tensor<E>: return select(arg0, arg1) ? arg0 : arg1;
Burada
E = element_type(operand)
vereduce_window_without_init
çalışır aynenreduce_window
gibidir, ancak temelde kullanılanschedule
reduce
(azaltma bölümüne bakın) başlangıç değerlerini içermez. Şu anda ilgili pencerede değer bulunmazsa ne olacağı belirtilmedi (#731).result[result_index] = reduce([source_values], [init_value], [0], scatter)
. burada:source_values = [source[source_index] for source_index in source_indices]
.- Şu durumda
selected_index(source_index) = operand_index
selected_values[source_index]
,operand
öğesine sahipoperand_index
başlangıç fiyatıyla. source_indices = [source_index for source_index in indices(source) if selected_index(source_index) = result_index]
.
Girişler
Şirket | Ad | Tür | Sınırlamalar |
---|---|---|---|
(I1) | operand |
tensör veya tensör başına miktarlandırılmış tensör | (C1-C4), (C6), (C8-C11) |
(I2) | source |
tensör veya tensör başına miktarlandırılmış tensör | (C1), (C2) |
(I3) | init_value |
0 boyutlu tensör veya tensör başına miktarlandırılmış tensör | (C3) |
(I4) | window_dimensions |
si64 türünde 1 boyutlu tensör sabiti |
(C2), (C4), (C5) |
(I5) | window_strides |
si64 türünde 1 boyutlu tensör sabiti |
(C2), (C6), (C7) |
(I6) | padding |
si64 türünde 2 boyutlu tensör sabiti |
(C2), (C8) |
(I7) | select |
işlev | (C9) |
(I8) | scatter |
işlev | (C10) |
Çıkışlar
Ad | Tür | Sınırlamalar |
---|---|---|
result |
tensör veya tensör başına miktarlandırılmış tensör | (C11-C12) |
Sınırlamalar
- (C1)
element_type(operand) = element_type(source)
. - (C2)
shape(source) = num_windows
burada:padded_operand_shape = padding[:, 0] + shape(operand) + padding[:, 1]
.is_empty_window = padded_operand_shape = 0 || window_dimensions > padded_operand_shape
.num_windows = is_empty_window ? 0 : floor((padded_operand_shape - window_dimensions) / window_strides) + 1
.
- (C3)
element_type(init_value) = element_type(operand)
. - (C4)
size(window_dimensions) = rank(operand)
- (C5)
0 < window_dimensions
- (C6)
size(window_strides) = rank(operand)
. - (C7)
0 < window_strides
. - (C8)
shape(padding) = [rank(operand), 2]
- (C9)
select
,(tensor<E>, tensor<E>) -> tensor<i1>
türünde olup buradaE = element_type(operand)
. - (C10)
scatter
,(tensor<E>, tensor<E>) -> tensor<E>
türünde olup buradais_promotable(element_type(operand), E)
. - (C11)
shape(operand) = shape(result)
- (C12)
element_type(result) = E
Örnekler
// %operand: [[1, 5], [2, 5], [3, 6], [4, 4]]
// %source: [[5, 6], [7, 8]]
// %init_value: 0
%result = "stablehlo.select_and_scatter"(%operand, %source, %init_value) ({
^bb0(%arg0: tensor<i64>, %arg1: tensor<i64>):
%0 = "stablehlo.compare"(%arg0, %arg1) {
comparison_direction = #stablehlo<comparison_direction GE>
} : (tensor<i64>, tensor<i64>) -> tensor<i1>
"stablehlo.return"(%0) : (tensor<i1>) -> ()
}, {
^bb0(%arg0: tensor<i64>, %arg1: tensor<i64>):
%0 = "stablehlo.add"(%arg0, %arg1) : (tensor<i64>, tensor<i64>) -> tensor<i64>
"stablehlo.return"(%0) : (tensor<i64>) -> ()
}) {
window_dimensions = array<i64: 3, 1>,
window_strides = array<i64: 2, 1>,
padding = dense<[[0, 1], [0, 0]]> : tensor<2x2xi64>
} : (tensor<4x2xi64>, tensor<2x2xi64>, tensor<i64>) -> tensor<4x2xi64>
// %result: [[0, 0], [0, 0], [5, 14], [7, 0]]
gönder
Anlam
channel_id
kanalına inputs
gönderir ve result
jetonu oluşturur.
is_host_transfer
değeri true
ise işlem, verileri
ana bilgisayar. Aksi takdirde veriler başka bir cihaza aktarılır. Bu,
tanımlanmıştır. Bu işaret,
channel_type
, gelecekte bunlardan yalnızca birini tutmayı planlıyoruz
(#666).
Girişler
Şirket | Ad | Tür | Sınırlamalar |
---|---|---|---|
(I1) | inputs |
değişken sayıda tensör veya nicel tensör | |
(I2) | token |
token |
|
(I3) | channel_id |
si64 türündeki sabit |
|
(I4) | channel_type |
DEVICE_TO_DEVICE ve DEVICE_TO_HOST sıralaması |
(C1) |
(I5) | is_host_transfer |
i1 türündeki sabit |
(C1) |
Çıkışlar
Ad | Tür |
---|---|
result |
token |
Sınırlamalar
- (C1)
channel_type
şu şekilde tanımlanır:is_host_transfer = true
iseDEVICE_TO_HOST
,- Aksi takdirde
DEVICE_TO_DEVICE
.
Örnekler
%result = "stablehlo.send"(%operand, %token) {
channel_handle = #stablehlo.channel_handle<handle = 1, type = 2>,
is_host_transfer = true
} : (tensor<2x2xi64>, !stablehlo.token) -> !stablehlo.token
shift_left
Anlam
lhs
tensörü üzerinde rhs
sayısına kadar öğe düzeyinde sola kaydırma işlemi gerçekleştirir
ve bir result
tensörü üretir.
Girişler
Şirket | Ad | Tür | Sınırlamalar |
---|---|---|---|
(I1) | lhs |
tam sayı türündeki tensör | (C1) |
(I2) | rhs |
tam sayı türündeki tensör | (C1) |
Çıkışlar
Ad | Tür | Sınırlamalar |
---|---|---|
result |
tam sayı türündeki tensör | (C1) |
Sınırlamalar
- (C1)
type(lhs) = type(rhs) = type(result)
.
Örnekler
// %lhs: [-1, 0, 1]
// %rhs: [1, 2, 3]
%result = "stablehlo.shift_left"(%lhs, %rhs): (tensor<3xi64>, tensor<3xi64>) -> tensor<3xi64>
// %result: [-2, 0, 8]
shift_right_arithmetic
Anlam
lhs
tensörü üzerinde element tabanlı aritmetik sağ kaydırma işlemi şu şekilde gerçekleştirir:
rhs
bit sayısını verir ve result
tensörü üretir.
Girişler
Şirket | Ad | Tür | Sınırlamalar |
---|---|---|---|
(I1) | lhs |
tam sayı türündeki tensör | (C1) |
(I2) | rhs |
tam sayı türündeki tensör | (C1) |
Çıkışlar
Ad | Tür | Sınırlamalar |
---|---|---|
result |
tam sayı türündeki tensör | (C1) |
Sınırlamalar
- (C1)
type(lhs) = type(rhs) = type(result)
.
Örnekler
// %lhs: [-1, 0, 8]
// %rhs: [1, 2, 3]
%result = "stablehlo.shift_right_arithmetic"(%lhs, %rhs): (tensor<3xi64>, tensor<3xi64>) -> tensor<3xi64>
// %result: [-1, 0, 1]
shift_right_logical
Anlam
rhs
ile lhs
tensörü üzerinde öğe bazında mantıksal sağ kaydırma işlemi gerçekleştirir
bit sayısı ile bir result
tensörü üretir.
Girişler
Şirket | Ad | Tür | Sınırlamalar |
---|---|---|---|
(I1) | lhs |
tam sayı türündeki tensör | (C1) |
(I2) | rhs |
tam sayı türündeki tensör | (C1) |
Çıkışlar
Ad | Tür | Sınırlamalar |
---|---|---|
result |
tam sayı türündeki tensör | (C1) |
Sınırlamalar
- (C1)
type(lhs) = type(rhs) = type(result)
.
Örnekler
// %lhs: [-1, 0, 8]
// %rhs: [1, 2, 3]
%result = "stablehlo.shift_right_logical"(%lhs, %rhs): (tensor<3xi64>, tensor<3xi64>) -> tensor<3xi64>
// %result: [9223372036854775807, 0, 1]
işaret
Anlam
Öğe tabanlı operand
işaretini döndürür ve bir result
tensörü üretir.
Daha resmi bir ifadeyle, her bir öğe (x
) için anlam şu şekilde ifade edilebilir:
Python söz dizimi şöyledir:
def sign(x):
if is_integer(x):
if compare(x, 0, LT, SIGNED): return -1
if compare(x, 0, EQ, SIGNED): return 0
return 1
elif is_float(x):
if is_nan(x): return NaN
if compare(x, -0.0, EQ, FLOAT): return -0.0
if compare(x, +0.0, EQ, FLOAT): return +0.0
if compare(x, 0.0, LT, FLOAT): return -1.0
return 1.0
elif is_complex(x):
if is_nan(real(x)) or is_nan(imag(x)): return (NaN, NaN)
if compare(x, (0.0, 0.0), EQ, FLOAT): return (0.0, 0.0)
return divide(x, convert(abs(x), type(x)))
Miktarı kullanılan türlerde,
dequantize_op_quantize(sign, operand, type(result))
Girişler
Şirket | Ad | Tür | Sınırlamalar |
---|---|---|---|
(I1) | operand |
işaretli tam sayı, kayan nokta veya karmaşık tür ya da tensör başına miktarlandırılmış tensörün tensörü | (C1) |
Çıkışlar
Ad | Tür | Sınırlamalar |
---|---|---|
result |
işaretli tam sayı, kayan nokta veya karmaşık tür ya da tensör başına miktarlandırılmış tensörün tensörü | (C1) |
Sınırlamalar
- (C1)
baseline_type(operand) = baseline_type(result)
.
Örnekler
// Logical values: +NaN, -1.0, -0.0, +0.0, 1.0
// operand: [0x7FFFFFFFFFFFFFFF, -1.0, -0.0, 0.0, 1.0]
%result = "stablehlo.sign"(%operand) : (tensor<5xf64>) -> tensor<5xf64>
// Logical values: +NaN, -1.0, -0.0, +0.0, 1.0
// %result: [0x7FFFFFFFFFFFFFFF, -1.0, -0.0, 0.0, 1.0]
sinüs
Anlam
operand
tensörü üzerinde element düzeyinde sinüs işlemi gerçekleştirir ve result
üretir
tensördür. Öğe türüne bağlı olarak aşağıdakiler gerçekleşir:
- Kayan reklamlar için: IEEE-754'ten
sin
. - Karmaşık sayılar için: karmaşık sinüs.
- Miktarlanmış türler için:
dequantize_op_quantize(sine, operand, type(result))
.
Girişler
Şirket | Ad | Tür | Sınırlamalar |
---|---|---|---|
(I1) | operand |
kayan nokta veya karmaşık tür ya da tensör başına miktarlandırılmış tensör tensörü | (C1) |
Çıkışlar
Ad | Tür | Sınırlamalar |
---|---|---|
result |
kayan nokta veya karmaşık tür ya da tensör başına miktarlandırılmış tensör tensörü | (C1) |
Sınırlamalar
- (C1)
baseline_type(operand) = baseline_type(result)
.
Örnekler
// %operand: [
// [0.0, 1.57079632], // [0, pi/2]
// [3.14159265, 4.71238898] // [pi, 3pi/2]
// ]
%result = "stablehlo.sine"(%operand) : (tensor<2x2xf32>) -> tensor<2x2xf32>
// %result: [[0.0, 1.0], [0.0, -1.0]]
slice
Anlam
Statik olarak hesaplanmış başlangıç dizinlerini kullanarak operand
öğesinden bir dilim çıkarır
ve bir result
tensörü üretir. start_indices
, şunun başlangıç dizinlerini içeriyor:
her boyuta ait dilimi, limit_indices
bitiş dizinlerini içerir
(hariç) ve strides
, adımları içeriyor
tıklayın.
Daha resmi dilde, result[result_index] = operand[operand_index]
;
operand_index = start_indices + result_index * strides
.
Girişler
Şirket | Ad | Tür | Sınırlamalar |
---|---|---|---|
(I1) | operand |
tensör veya tensör başına miktarlandırılmış tensör | (C1-C3), (C5) |
(I2) | start_indices |
si64 türünde 1 boyutlu tensör sabiti |
(C2), (C3), (C5) |
(I3) | limit_indices |
si64 türünde 1 boyutlu tensör sabiti |
(C2), (C3), (C5) |
(I4) | strides |
si64 türünde 1 boyutlu tensör sabiti |
(C2), (C4) |
Çıkışlar
Ad | Tür | Sınırlamalar |
---|---|---|
result |
tensör veya tensör başına miktarlandırılmış tensör | (C1), (C5) |
Sınırlamalar
- (C1)
element_type(operand) = element_type(result)
. - (C2)
size(start_indices) = size(limit_indices) = size(strides) = rank(operand)
. - (C3)
0 <= start_indices <= limit_indices <= shape(operand)
. - (C4)
0 < strides
- (C5)
shape(result) = ceil((limit_indices - start_indices) / strides)
Örnekler
// %operand: [
// [0, 0, 0, 0],
// [0, 0, 1, 1],
// [0, 0, 1, 1]
// ]
%result = "stablehlo.slice"(%operand) {
start_indices = array<i64: 1, 2>,
limit_indices = array<i64: 3, 4>,
strides = array<i64: 1, 1>
} : (tensor<3x4xi64>) -> tensor<2x2xi64>
// % result: [
// [1, 1],
// [1, 1]
// ]
sıralama
Anlam
dimension
boyutu boyunca 1 boyutlu inputs
dilimlerini birlikte sıralar.
bir comparator
parametresine göre ve results
üretir.
Diğer işlemlerdeki benzer girişlerin aksine dimension
, negatif değerlere izin verir.
aşağıdaki anlamlara gelir. Gelecekte, buna izin verilmeyebilir
(ör. tutarlılık nedeniyle)
(#1377).
is_stable
doğru değerine ayarlanırsa sıralama sabittir, yani
karşılaştırıcının eşit olduğu kabul edilen öğeler korunur. Kılıf için
tek bir giriş olduğunda e1
ve e2
adlı iki öğe şu şekilde kabul edilir:
ancak ve yalnızca, karşılaştırıcıya eşittir
comparator(e1, e2) = comparator(e2, e1) = false
. Aşağıdaki biçimi inceleyin
birden fazla girişe genelleştiğini göreceksiniz.
Daha resmi dilde, index_space(results[0])
içindeki tüm result_index
için:
adjusted_dimension = dimension >= 0 ? dimension : rank(inputs[0]) + dimension
.riN
bireysel olduğuresult_slice = [ri0, ..., :, ..., riR-1]
öğelerresult_index
içinde ve:
,adjusted_dimension
konumuna eklenir.inputs_together = (inputs[0]..., ..., inputs[N-1]...)
.results_together[result_slice] = sort(inputs_together[result_slice], comparator_together)
.- Burada
sort
, 1 boyutlu bir dilimi azalan düzende sıralar ve beklenen şekilde sol taraftaki bağımsız değişken şöyle isecomparator_together
,true
değerini döndürür: daha az olabilir. def comparator_together(lhs_together, rhs_together): args = [] for (lhs_el, rhs_el) in zip(lhs_together, rhs_together): args.append(lhs_el) args.append(rhs_el) return comparator(*args)
(results[0]..., ..., results[N-1]...) = results_together
.
Girişler
Şirket | Ad | Tür | Sınırlamalar |
---|---|---|---|
(I1) | inputs |
değişken sayıda tensör veya tensör başına miktarlandırılmış tensör | (C1-C5) |
(I2) | dimension |
si64 türündeki sabit |
(C4) |
(I3) | is_stable |
i1 türündeki sabit |
|
(I4) | comparator |
işlev | (C5) |
Çıkışlar
Ad | Tür | Sınırlamalar |
---|---|---|
results |
değişken sayıda tensör veya tensör başına miktarlandırılmış tensör | (C2), (C3) |
Sınırlamalar
- (C1)
0 < size(inputs)
. - (C2)
type(inputs...) = type(results...)
. - (C3)
same(shape(inputs...) + shape(results...))
. - (C4)
-R <= dimension < R
, buradaR = rank(inputs[0])
. - (C5)
comparator
şu türe sahip:(tensor<E1>, tensor<E1>, ..., tensor<EN-1>, tensor<EN-1>) -> tensor<i1>
, buradaEi = element_type(inputs[i])
.
Örnekler
// %input0 = [[1, 2, 3], [3, 2, 1]]
// %input1 = [[3, 2, 1], [1, 2, 3]]
%result0, %result1 = "stablehlo.sort"(%input0, %input1) ({
^bb0(%arg0: tensor<i64>, %arg1: tensor<i64>, %arg2: tensor<i64>, %arg3: tensor<i64>):
%predicate = "stablehlo.compare"(%arg0, %arg1) {
comparison_direction = #stablehlo<comparison_direction GT>
} : (tensor<i64>, tensor<i64>) -> tensor<i1>
"stablehlo.return"(%predicate) : (tensor<i1>) -> ()
}) {
dimension = 0 : i64,
is_stable = true
} : (tensor<2x3xi64>, tensor<2x3xi64>) -> (tensor<2x3xi64>, tensor<2x3xi64>)
// %result0 = [[3, 2, 3], [1, 2, 1]]
// %result1 = [[1, 2, 1], [3, 2, 3]]
sqrt
Anlam
operand
tensörü üzerinde öğe tabanlı karekök işlemi gerçekleştirir ve
result
tensörü. Öğe türüne bağlı olarak aşağıdakiler gerçekleşir:
- Kayan reklamlar için: IEEE-754'ten
squareRoot
. - Karmaşık sayılar için: karmaşık karekök.
- Miktarlanmış türler için:
dequantize_op_quantize(sqrt, operand, type(result))
.
Girişler
Şirket | Ad | Tür | Sınırlamalar |
---|---|---|---|
(I1) | operand |
kayan nokta veya karmaşık tür ya da tensör başına miktarlandırılmış tensör tensörü | (C1) |
Çıkışlar
Ad | Tür | Sınırlamalar |
---|---|---|
result |
kayan nokta veya karmaşık tür ya da tensör başına miktarlandırılmış tensör tensörü | (C1) |
Sınırlamalar
- (C1)
baseline_type(operand) = baseline_type(result)
.
Örnekler
// %operand: [[0.0, 1.0], [4.0, 9.0]]
%result = "stablehlo.sqrt"(%operand) : (tensor<2x2xf32>) -> tensor<2x2xf32>
// %result: [[0.0, 1.0], [2.0, 3.0]]
çıkarma
Anlam
İki lhs
ve rhs
tensöründen öğe tabanlı çıkarma işlemi gerçekleştirir ve bir üretir
result
tensörü. Öğe türüne bağlı olarak aşağıdakiler gerçekleşir:
- Tam sayılar için: tam sayı çıkarma.
- Kayan reklamlar için: IEEE-754'ten
subtraction
. - Karmaşık sayılar için: karmaşık çıkarma işlemi.
- Ölçülen türler için:
dequantize_op_quantize(subtract, lhs, rhs, type(result))
.
Girişler
Şirket | Ad | Tür | Sınırlamalar |
---|---|---|---|
(I1) | lhs |
tam sayı, kayan nokta veya karmaşık tür ya da tensör başına miktarlandırılmış tensör tensörü | (C1) |
(I2) | rhs |
tam sayı, kayan nokta veya karmaşık tür ya da tensör başına miktarlandırılmış tensör tensörü | (C1) |
Çıkışlar
Ad | Tür | Sınırlamalar |
---|---|---|
result |
tam sayı, kayan nokta veya karmaşık tür ya da tensör başına miktarlandırılmış tensör tensörü | (C1) |
Sınırlamalar
- (C1)
baseline_type(lhs) = baseline_type(rhs) = baseline_type(result)
.
Örnekler
// %lhs: [[6, 8], [10, 12]]
// %rhs: [[5, 6], [7, 8]]
%result = "stablehlo.subtract"(%lhs, %rhs) : (tensor<2x2xf32>, tensor<2x2xf32>) -> (tensor<2x2xf32>)
// %result: [[1, 2], [3, 4]]
tan
Anlam
operand
tensörü üzerinde öğe tabanlı teğet işlemi gerçekleştirir ve
result
tensörü. Öğe türüne bağlı olarak aşağıdakiler gerçekleşir:
- Kayan reklamlar için: IEEE-754'ten
tan
. - Karmaşık sayılar için: karmaşık tanjant.
- Miktarlanmış türler için:
dequantize_op_quantize(tan, operand, type(result))
.
Girişler
Şirket | Ad | Tür | Sınırlamalar |
---|---|---|---|
(I1) | operand |
kayan nokta veya karmaşık tür ya da tensör başına miktarlandırılmış tensör tensörü | (C1) |
Çıkışlar
Ad | Tür | Sınırlamalar |
---|---|---|
result |
kayan nokta veya karmaşık tür ya da tensör başına miktarlandırılmış tensör tensörü | (C1) |
Sınırlamalar
- (C1)
baseline_type(operand) = baseline_type(result)
.
Örnekler
// %operand: [
// [0.0, 1.57079632], // [0, pi/2]
// [3.14159265, 4.71238898] // [pi, 3pi/2]
// ]
%result = "stablehlo.tan"(%operand) : (tensor<2x2xf64>) -> tensor<2x2xf64>
// %result: [
// [0.0, 1.63312e+16],
// [0.0, 5.44375e+15]
// ]
tanh
Anlam
operand
tensörü üzerinde element tabanlı hiperbolik tanjant işlemi gerçekleştirir ve
bir result
tensörü üretir. Öğe türüne bağlı olarak aşağıdakiler gerçekleşir:
- Kayan reklamlar için: IEEE-754'ten
tanh
. - Karmaşık sayılar için: karmaşık hiperbolik tanjant.
- Ölçülen türler için:
dequantize_op_quantize(tanh, operand, type(result))
.
Girişler
Şirket | Ad | Tür | Sınırlamalar |
---|---|---|---|
(I1) | operand |
kayan nokta veya karmaşık tür ya da tensör başına miktarlandırılmış tensör tensörü | (C1) |
Çıkışlar
Ad | Tür | Sınırlamalar |
---|---|---|
result |
kayan nokta veya karmaşık tür ya da tensör başına miktarlandırılmış tensör tensörü | (C1) |
Sınırlamalar
- (C1)
baseline_type(operand) = baseline_type(result)
.
Örnekler
// %operand: [-1.0, 0.0, 1.0]
%result = "stablehlo.tanh"(%operand) : (tensor<3xf32>) -> tensor<3xf32>
// %result: [-0.76159416, 0.0, 0.76159416]
ters çevir
Anlam
permutation
kullanarak operand
tensörünün boyutlarını ayarlar ve
result
tensörü. Daha resmi dilde: result[result_index] = operand[operand_index]
burada result_index[d] = operand_index[permutation[d]]
.
Girişler
Şirket | Ad | Tür | Sınırlamalar |
---|---|---|---|
(I1) | operand |
tensör veya nicel tensör | (C1-C4) |
(I2) | permutation |
si64 türünde 1 boyutlu tensör sabiti |
(C2-C4) |
Çıkışlar
Ad | Tür | Sınırlamalar |
---|---|---|
result |
tensör veya nicel tensör | (C1), (C3-C4) |
Sınırlamalar
- (C1)
element_type(result)
değerini sağlayan:!is_per_axis_quantized(operand)
iseelement_type(operand)
.element_type(operand)
yalnızcaquantization_dimension(operand)
ve Aksi takdirdequantization_dimension(result)
farklı olabilir.
- (C2)
permutation
,range(rank(operand))
permütasyonudur. - (C3)
shape(result) = dim(operand, permutation...)
. - (C4)
is_per_axis_quantized(result)
isequantization_dimension(operand) = permutation(quantization_dimension(result))
.
Örnekler
// %operand: [
// [[1,2], [3,4], [5,6]],
// [[7,8], [9,10], [11,12]]
// ]
%result = "stablehlo.transpose"(%operand) {
permutation = array<i64: 2, 1, 0>
} : (tensor<2x3x2xi32>) -> tensor<2x3x2xi32>
// %result: [
// [[1,7], [3,9], [5,11]],
// [[2,8], [4,10], [6,12]]
// ]
triangular_solve
Anlam
Küçük veya üst üçgenlere sahip doğrusal denklem sistemlerini toplu çözebilme katsayı matrislerini kullanır.
Daha resmî bir şekilde ifade etmek gerekirse a
ve b
için çözüm result[i0, ..., iR-3, :, :]
left_side
şu durumda op(a[i0, ..., iR-3, :, :]) * x = b[i0, ..., iR-3, :, :]
adresine:
Şu durumda true
veya x * op(a[i0, ..., iR-3, :, :]) = b[i0, ..., iR-3, :, :]
:
left_side
, false
. Burada, op(a)
değerine sahip x
değişkeni çözülür
transpose_a
tarihine kadar. Bu, aşağıdakilerden biri olabilir:
NO_TRANSPOSE
:a
öğesini olduğu gibi kullanarak işlemi gerçekleştirin.TRANSPOSE
:a
ifadesinin ters çevirme işlemini gerçekleştirin.ADJOINT
:a
hücresinin eşlenik ters çevirme işlemini gerçekleştirin.
lower
değeri true
ise giriş verileri yalnızca a
öğesinin alt üçgeninden okunur
a
üst üçgeni, aksi takdirde. Çıkış verileri aynı üçgen içinde döndürülür;
diğer üçgendeki değerler uygulama tanımlıdır.
unit_diagonal
doğru ise uygulama, köşegenin
a
elemanları 1'e eşittir, aksi takdirde davranış tanımsızdır.
Miktarı kullanılan türlerde,
dequantize_op_quantize(lambda x, y: triangular_solve(x, y, left_side, lower,
unit_diagonal, transpose_a), a, b, type(result))
Girişler
Şirket | Ad | Tür | Sınırlamalar |
---|---|---|---|
(I1) | a |
kayan nokta veya karmaşık tür ya da tensör başına miktarlandırılmış tensör tensörü | (C1-C3) |
(I2) | b |
kayan nokta veya karmaşık tür ya da tensör başına miktarlandırılmış tensör tensörü | (C1-C4) |
(I3) | left_side |
i1 türündeki sabit |
(C3) |
(I4) | lower |
i1 türündeki sabit |
|
(I5) | unit_diagonal |
i1 türündeki sabit |
|
(I6) | transpose_a |
NO_TRANSPOSE , TRANSPOSE ve ADJOINT sıralaması |
Çıkışlar
Ad | Tür | Sınırlamalar |
---|---|---|
result |
kayan nokta veya karmaşık tür ya da tensör başına miktarlandırılmış tensör tensörü | (C1) |
Sınırlamalar
- (C1)
baseline_element_type(a) = baseline_element_type(b)
. - (C2)
2 <= rank(a) = rank(b) = R
. - (C3)
shape(a)
ileshape(b)
arasındaki ilişki aşağıdaki gibi tanımlanır:shape(a)[:-3] = shape(b)[:-3]
.dim(a, -2) = dim(a, -1) = dim(b, left_side ? -2 : -1)
.
- (C4)
baseline_type(b) = baseline_type(result)
Örnekler
// %a = [
// [1.0, 0.0, 0.0],
// [2.0, 4.0, 0.0],
// [3.0, 5.0, 6.0]
// ]
// %b = [
// [2.0, 0.0, 0.0],
// [4.0, 8.0, 0.0],
// [6.0, 10.0, 12.0]
// ]
%result = "stablehlo.triangular_solve"(%a, %b) {
left_side = true,
lower = true,
unit_diagonal = false,
transpose_a = #stablehlo<transpose NO_TRANSPOSE>
} : (tensor<3x3xf32>, tensor<3x3xf32>) -> tensor<3x3xf32>
// %result: [
// [2.0, 0.0, 0.0],
// [0.0, 2.0, 0.0],
// [0.0, 0.0, 2.0]
// ]
tuple
Anlam
val
değerlerinden bir result
delmesi oluşturur.
Girişler
Şirket | Ad | Tür | Sınırlamalar |
---|---|---|---|
(I1) | val |
değişken değer sayısı | (C1) |
Çıkışlar
Ad | Tür | Sınırlamalar |
---|---|---|
result |
tuple | (C1) |
Sınırlamalar
- (C1)
result
,Ei = type(val[i])
olduğundatuple<E0, ..., EN-1>
türünde.
Örnekler
// %val0: [1.0, 2.0]
// %val1: (3)
%result = "stablehlo.tuple"(%val0, %val1) : (tensor<2xf32>, tuple<tensor<i32>>) -> tuple<tensor<2xf32>, tuple<tensor<i32>>>
// %result: ([1.0, 2.0], (3))
uniform_dequantize
Anlam
Ölçülen operand
tensörünü öğe bazında bir
Tanımlanan miktar belirleme parametrelerine göre result
kayan nokta tensörü
operand
türüne göre.
Daha resmi olarak, result = dequantize(operand)
.
Girişler
Şirket | Ad | Tür | Sınırlamalar |
---|---|---|---|
(I1) | operand |
nicel tensör | (C1), (C2) |
Çıkışlar
Ad | Tür | Sınırlamalar |
---|---|---|
result |
kayan nokta türünün tensörü | (C1), (C2) |
Sınırlamalar
- (C1)
shape(operand) = shape(result)
. - (C2)
element_type(result) = expressed_type(operand)
.
Örnekler
// %operand: [10, 10]
%result = "stablehlo.uniform_dequantize"(%operand) : (tensor<2x!quant.uniform<i8:f32:0, {0.1:-30,0.5:-20}>>) -> tensor<2xf32>
// %result: [4.0, 15.0]
uniform_quantize
Anlam
Kayan nokta tensörünün veya nicelenmiş tensörün öğe tabanlı dönüşümünü gerçekleştirir
Miktara göre, result
nicelleştirilmiş bir tensöre operand
result
türü tarafından tanımlanan parametreler.
Daha resmi ifade etmek gerekirse
- Eğer
is_float(operand)
:result = quantize(operand, type(result))
.
- Eğer
is_quantized(operand)
:float_result = dequantize(operand)
.result = quantize(float_result, type(result))
.
Girişler
Şirket | Ad | Tür | Sınırlamalar |
---|---|---|---|
(I1) | operand |
kayan nokta veya nicelenmiş türde tensor | (C1), (C2) |
Çıkışlar
Ad | Tür | Sınırlamalar |
---|---|---|
result |
nicel tensör | (C1), (C2) |
Sınırlamalar
- (C1)
shape(operand) = shape(result)
. - (C2)
expressed_type(result) = is_float(operand) ? element_type(operand) : expressed_type(operand)
.
Örnekler
// %operand: [4.0, 15.0]
%result = "stablehlo.uniform_quantize"(%operand) : (tensor<2xf32>) -> tensor<2x!quant.uniform<i8:f32:0, {0.1:-30,0.5:-20}>>
// %result: [10, 10]
// %operand: [10, 10]
%result = "stablehlo.uniform_quantize"(%operand) : (tensor<2x!quant.uniform<i8:f32:0, {0.1:-30,0.5:-20}>>) -> tensor<2x!quant.uniform<i8:f32:0, {0.1:-20,0.2:-30}>>
// %result: [20, 45]
ancak
Anlam
body
işlevinin yürütülmesinden elde edilen çıktıyı 0 veya daha fazla kez üretir.
cond
işlevi, true
çıktısını verir. Daha resmi bir ifadeyle, anlamlar
aşağıdaki gibi bir Python söz dizimi kullanarak:
internal_state = operand
while cond(*internal_state):
internal_state = body(*internal_state)
results = internal_state
Sonsuz döngünün davranışı henüz belli değil (#383).
Girişler
Şirket | Ad | Tür | Sınırlamalar |
---|---|---|---|
(I1) | operand |
değişken tensör, nicel tensör veya jeton sayısı | (C1-C3) |
(I2) | cond |
işlev | (C1) |
(I3) | body |
işlev | (C2) |
Çıkışlar
Ad | Tür | Sınırlamalar |
---|---|---|
results |
değişken tensör, nicel tensör veya jeton sayısı | (C3) |
Sınırlamalar
- (C1)
cond
,(T0, ..., TN-1) -> tensor<i1>
türünde olup buradaTi = type(operand[i])
. - (C2)
body
,(T0, ..., TN-1) -> (T0, ..., TN-1)
türünde olup buradaTi = type(operand[i])
. - (C3)
type(results...) = type(operand...)
.
Örnekler
// %init_i: 1
// %init_sum: 0
// %one: 1
// %ten: 10
%results0, %results1 = "stablehlo.while"(%init_i, %init_sum) ({
^bb0(%arg0: tensor<i64>, %arg1: tensor<i64>):
%cond = "stablehlo.compare"(%arg0, %ten) {
comparison_direction = #stablehlo<comparison_direction LT>
} : (tensor<i64>, tensor<i64>) -> tensor<i1>
stablehlo.return %cond : tensor<i1>
}, {
^bb0(%arg0: tensor<i64>, %arg1: tensor<i64>):
%new_sum = stablehlo.add %arg1, %one : tensor<i64>
%new_i = stablehlo.add %arg0, %one : tensor<i64>
stablehlo.return %new_i, %new_sum : tensor<i64>, tensor<i64>
}) : (tensor<i64>, tensor<i64>) -> (tensor<i64>, tensor<i64>)
// %results0: 10
// %results1: 10
Xor
Anlam
lhs
ve rhs
iki tensörü için öğe tabanlı XOR gerçekleştirir ve bir result
üretir
tensördür. Öğe türüne bağlı olarak aşağıdakiler gerçekleşir:
- Boolelar için: mantıksal XOR.
- Tam sayılar için: bit tabanlı XOR.
Girişler
Şirket | Ad | Tür | Sınırlamalar |
---|---|---|---|
(I1) | lhs |
boole veya tam sayı türündeki tensor | (C1) |
(I2) | rhs |
boole veya tam sayı türündeki tensor | (C1) |
Çıkışlar
Ad | Tür | Sınırlamalar |
---|---|---|
result |
boole veya tam sayı türündeki tensor | (C1) |
Sınırlamalar
- (C1)
type(lhs) = type(rhs) = type(result)
.
Örnekler
// Bitwise operation with with integer tensors
// %lhs: [[1, 2], [3, 4]]
// %rhs: [[5, 6], [7, 8]]
%result = "stablehlo.xor"(%lhs, %rhs) : (tensor<2x2xi32>, tensor<2x2xi32>) -> tensor<2x2xi32>
// %result: [[4, 4], [4, 12]]
// Logical operation with with boolean tensors
// %lhs: [[false, false], [true, true]]
// %rhs: [[false, true], [false, true]]
%result = "stablehlo.xor"(%lhs, %rhs) : (tensor<2x2xi1>, tensor<2x2xi1>) -> tensor<2x2xi1>
// %result: [[false, true], [true, false]]
Dialkt Birlikte Çalışabilirlik
Şu anda, doğadaki StableHLO programları bazen StableHLO tarafından tanımlanmaz.
Modül, İşlev, Arama ve İade
StableHLO; ModuleOp, FuncOp, CallOp ve için yukarı akış MLIR işlemlerini kullanır ReturnOp. Bu, mevcut MLIR makineleriyle daha iyi bir faydalı kartlar, FuncOp ile ModuleOp'u hedefleyen yazılı belgeler ve birçok derleme ardışık düzenler bu işlemlerin mevcut olmasını bekler. Tam uyumluluk garantileri bu işlemlere uygulandı. Bu işlemlerde herhangi bir değişiklik olursa uyumlu olmayan bir yöntemle (ör. kaldırma işlemi), StableHLO eşdeğerleri uyumluluk.
CHLO
CHLO işlem kümesi, StableHLO'ya ayrıştırılan üst düzey işlemler içerir. Şu anda CHLO için uyumluluk garantisi yoktur. Uyumluluk için chlo-legalize-to-stablehlo kartı serileştirmeden önce kullanılmalıdır.
Şekil İşlemleri
Temelden belirli işlemlerin kullanılması toplulukta yaygın bir kullanım örneğidir.
Dinamik StableHLO programlarında MLIR, şekil hesaplamaları yapmak için diyalekt kullanır.
Bunlar en yaygın olarak shape
lehçesini içerir.
shape_of
veya num_elements
gibi işlemler, tensor
diyalekt
dim
veya from_elements
gibi işlemler ve yerleşik index
türü.
Dynamism RFC > O2
bunları kapsam dışı olarak belirtir, ancak index
türleri için bazı destek
birlikte çalışabilirlik amacıyla kullanılabilir. Bunlar için uyumluluk garantisi yoktur
olanak sağlar. shape-legalize-to-stablehlo
bu işlemleri tam olarak desteklenen StableHLO operasyonlarına dönüştürmek için kullanılabilir.
Kullanımdan Kaldırılan İşlemler
Devralınan birkaç StableHLO işlemi var: MHLO ve artık StableHLO'dan çıkacaklar. Bu konularla ilgili tüm ayrıntılar kaldırma işlemlerini StableHLO v1.0 Temizleme #2283 içinde bulabilirsiniz. Bu kullanımdan kaldırmalarla ilgili takip sorunu #2340'tır.
Bu işlemler birkaç kategoriye ayrılır:
- "HLO yok" Bunlar, StableHLO operasyonları kategorisiydi. Bunlar başlangıçta
StableHLO işletim sistemini, ancak daha sonra uygun olmadığına karar verildi:
broadcast
,create_token
,cross-replica-sum
,dot
,einsum
,torch_index_select
,unary_einsum
(#3). - Kullanılmayan işlemler: Bu işlemler bir noktada yararlı olabilir, ancak
ya da bu işlemleri kullanan ardışık düzenler
gereklilikleri ortadan kaldıracak şekilde yeniden düzenlendi. Bunlar arasında
map
,tuple
(#598),get_tuple_element
,rng
,complex
karşılaştırma #560, ve evrişimwindow_reversal
(#1181).
Bu işlemlerden bazıları
mevcut işlemler (broadcast
, create_token
, cross-replica-sum
, dot
,
unary_einsum
) ve mevcut uyumluluk penceresinden sonra kaldırılacak.
kullanım hakkı (6 ay). Diğerleri kaldırılmak üzere araştırılıyor (einsum
,
get_tuple_element
, map
, rng
torch_index_select
, tuple
, complex
karşılaştırmalar, window_reversal
). Topluluk geri bildirimi bekliyorum,
bu işlemler kaldırılacak veya tam destekle spesifikasyona eklenecektir. Bitiş
bu işlem gelecekleri biliniyor, yalnızca 6 ay uyumluluğu garanti edilir.
Yürütme
Sıralı yürütme
Bir StableHLO programı, main
işlevine giriş değerleri sağlanarak yürütülür
ve çıkış değerlerini hesaplayabilirsiniz. Bir fonksiyonun çıkış değerleri şöyle hesaplanır:
karşılık gelen return
işlemindeki kök işlemleri grafiğini yürütme
Yürütme siparişi,
veri akışı (ör. işlemler kullanımlarından önce yürütülürse). StableHLO'daki tüm
Operasyonel bir jeton tüketip bir jeton üretir (birden fazla jeton
after_all
aracılığıyla tek bir jetonda çoğulalan) olması gerekir; bu nedenle,
ve efektler de veri akışıyla uyumludur. Örneğin, bu programda
Olası iki yürütme siparişi vardır: %0
→ %1
→ %2
→ return
ve
%1
→ %0
→ %2
→ return
.
func.func @main() -> tensor<f64> {
%0 = stablehlo.constant dense<1.0> : tensor<f64>
%1 = stablehlo.constant dense<2.0> : tensor<f64>
%2 = stablehlo.add %0, %1 : tensor<f64>
return %2 : tensor<f64>
}
Daha resmi bir ifadeyle, StableHLO süreci şunların birleşiminden oluşur:
1) StableHLO programı, 2) çalışma durumları (henüz yürütülmemiştir,
zaten yürütülmüş olması) ve 3) sürecin üzerinde çalıştığı ara değerler.
İşlem, main
işlevine giriş değerleriyle başlar ve süreç boyunca
işlem durumlarını ve ara değerleri güncelleyen işlemlerin grafiği
bitiş değerleriyle bitirir. Daha resmi açıklama henüz belli değil
(#484).
Paralel yürütme
StableHLO programları, 2D süreç ızgarası şeklinde düzenlenmiş, paralel olarak yürütülebilir
(her ikisi de ui32
türünde olan) num_partitions
bazında num_replicas
.
StableHLO süreç ızgarasında, StableHLO'nun num_replicas * num_partitions
aynı anda yürütüldüğünden
emin olmanız gerekir. Her sürecin kendine özgü bir
process_id = (replica_id, partition_id)
, burada:
replica_ids = range(num_replicas)
içinde replica_id
ve
partition_ids = range(num_partitions)
içinde her ikisi de olan partition_id
ui32
yazın.
Süreç çizelgesinin boyutu her program için statik olarak bilinir (
gelecekte bunu StableHLO programlarının bir parçası yapmayı planlıyoruz.
#650) ve konumun
her süreç için statik olarak bilinir. Her süreç
ve onun süreç tablosundaki konumuna replica_id
ve
partition_id
işlem
Süreç çizelgesinde programların tümü aynı olabilir ("Tek Program, Çoklu Veri" stili) tümü farklı olabilir ("Birden Çok Program'da, Çoklu Veri" veya bunların arasında başka bir şey vardır. Gelecekte, paralel StableHLO programları tanımlamaya yönelik diğer deyimler için destek sağlamak GSPMD (#619) dahil.
Süreç çizelgesinde süreçler büyük ölçüde birbirinden bağımsızdır. ayrı işlem durumları, ayrı giriş/ara/çıkış değerleri vardır İşlemlerin çoğu süreçler arasında ayrı ayrı yürütülür, (aşağıda açıklanan az sayıda ortak işlem hariçtir.)
Çoğu işlemin yürütülmesi sırasında yalnızca aynı
bu değerlere adlarıyla atıfta bulunmak genellikle belirsizdir.
Ancak toplu işlemlerin anlamını açıklarken bu yeterli değildir ve
name
değerini ifade etmek için name@process_id
gösterimini oluşturan
belirli bir süreç içinde yürütülür. (Bu açıdan bakıldığında, uygun olmayan name
(name@(replica_id(), partition_id())
için kısaltma olarak görüntülendi).
Süreçlerdeki yürütme sırası, Noktadan noktaya iletişim ve toplu işlemlerle sağlanan senkronizasyon gerekir.
Bire bir iletişim
StableHLO süreçleri
StableHLO kanalları. Kanal, pozitif bir kimlik türü ile temsil edilir
si64
Çeşitli operasyonlar yoluyla, kanallara ve değerlerine,
anlayabiliyoruz.
Daha resmi hale getirme, ör. ve bu kanal kimliklerinin nereden geldiğini farkında olmasını sağlayan işlemler ve bu süreçlerin tarafından başlatılmış, henüz belli değil (#484).
Akış iletişimi
Her StableHLO işleminin iki akış arayüzüne erişimi vardır:
- Okunabilen feed içi öğeler.
- Yazılabilecek özet feed'i.
Süreçler arasında iletişim kurmak için kullanılan kanalların aksine, Her iki ucunda da süreçlere sahip olmakla birlikte, feed içi ve çıkışların tanımlanmıştır.
Daha resmi hale getirme, ör. Akışlı iletişimin yürütmeyi nasıl etkilediği bu işlemin ne tür bir senkronizasyona yol açtığına dair (#484).
Ortak operasyonlar
StableHLO'da altı ortak operasyon vardır: all_gather
, all_reduce
,
all_to_all
, collective_broadcast
, collective_permute
ve
reduce_scatter
. Tüm bu işlemler, StableHLO sürecindeki süreçleri böler
StableHLO süreç gruplarına ayırır ve
diğer süreç gruplarından bağımsız olarak
her işlem grubuna atanır.
Her işlem grubu içinde toplu işlemler bir senkronizasyona neden olabilir. engel oluşturabilirsiniz. Daha resmi hale getirme, ör. tam olarak bunun ne zaman süreçlerin bu engele tam olarak nasıl ulaştığını, yoksa ne olacağı ise henüz belli değil. (#484).
Süreç grubunda bölümler arası iletişim varsa (diğer bir deyişle,
işlem grubunda, bölüm kimlikleri farklı olan işlemler ve ardından yürütme
kolektif operasyonun bir kanala ihtiyacı var; kolektif operasyonun ise
si64
türünde pozitif channel_id
. Çapraz kopya iletişimde
kanallar.
Toplu işlemler tarafından gerçekleştirilen hesaplamalar, bağımsız operasyonlara özgüdür ve yukarıdaki bağımsız operasyon bölümlerinde açıklanmaktadır. Ancak proje yöneticilerinin Kılavuz, süreç gruplarına ayrılır ve bu operasyonlar arasında paylaşılır. ve bu bölümde açıklanmıştır. Daha resmi bir ifadeyle, StableHLO dört strateji uygulayarak.
cross_replica
Her işlem grubu içinde yalnızca çapraz replikalı iletişimler gerçekleşir. Bu
stratejisi, replica_groups
(replika kimlikleri listesi) ve hesaplamalar listesi alır
partition_ids
tarafından replica_groups
ürününe ait bir Kartezyen ürün. replica_groups
.
benzersiz öğelere sahip olmalı ve tüm replica_ids
öğelerini kapsamalıdır. Daha resmi ifade etmek gerekirse
Python söz dizimi:
def cross_replica(replica_groups: List[List[ReplicaId]]) -> List[List[ProcessId]]:
for replica_group in replica_groups:
for partition_id in partition_ids:
process_group = []
for replica_id in replica_group:
process_group.append((replica_id, partition_id))
yield process_group
Örneğin, replica_groups = [[0, 1], [2, 3]]
ve num_partitions = 2
için
cross_replica
şunu üretecek:
[[(0, 0), (1, 0)], [(0, 1), (1, 1)], [(2, 0), (3, 0)], [(2, 1), (3, 1)]]
.
cross_partition
Her süreç grubu içinde yalnızca bölümler arası iletişimler gerçekleşir. Bu
stratejisi partition_groups
(bölüm kimlik listesi listesi) ve
replica_ids
tarafından partition_groups
değerindeki bir Kartezyen ürünü hesaplar.
partition_groups
benzersiz öğelere sahip olmalı ve tüm partition_ids
öğelerini kapsamalıdır.
Daha resmi bir ifadeyle, Python söz dizimini kullanarak:
def cross_partition(partition_groups: List[List[PartitionId]]) -> List[List[ProcessId]]:
for partition_group in partition_groups:
for replica_id in replica_ids:
process_group = []
for partition_id in partition_group:
process_group.append((replica_id, partition_id))
yield process_group
Örneğin, partition_groups = [[0, 1]]
ve num_replicas = 4
için
cross_partition
şunu üretecek:
[[(0, 0), (0, 1)], [(1, 0), (1, 1)], [(2, 0), (2, 1)], [(3, 0), (3, 1)]]
.
cross_replica_and_partition
Her ikisinde de hem çapraz hem de bölümler arası iletişimler gerçekleşebilir
işlem grubudur. Bu strateji replica_groups
-
replika kimlikleri - ve her bir replica_group
öğesinin Kartezyen ürünlerini
partition_ids
. replica_groups
benzersiz öğelere sahip olmalı ve tüm öğeleri kapsamalıdır
replica_ids
. Daha resmi bir ifadeyle, Python söz dizimini kullanarak:
def cross_replica_and_partition(replica_groups: List[List[ReplicaId]]) -> List[List[ProcessId]]:
for replica_group in replica_groups:
process_group = []
for partition_id in partition_ids:
for replica_id in replica_group:
process_group.append((replica_id, partition_id))
yield process_group
Örneğin, replica_groups = [[0, 1], [2, 3]]
ve num_partitions = 2
için
cross_replica_and_partition
şunu üretecek:
[[(0, 0), (1, 0), (0, 1), (1, 1)], [(2, 0), (3, 0), (2, 1), (3, 1)]]
.
flattened_ids
Bu strateji flattened_id_groups
("birleştirilmiş" listelerden oluşan bir liste) alıyor
replica_id * num_partitions + partition_id
biçiminde işlem kimlikleri - ve
bunları işlem kimliklerine dönüştürür. flattened_id_groups
benzersiz öğelere sahip olmalıdır
ve tüm process_ids
öğelerini kapsamalıdır. Daha resmi bir ifadeyle, Python söz dizimini kullanarak:
def flattened_ids(flattened_id_groups: List[List[ui32]]) -> List[List[ProcessId]]:
for flattened_id_group in flattened_id_groups:
process_group = []
for flattened_id in flattened_id_group:
replica_id = flattened_id // num_partitions
partition_id = flattened_id % num_partitions
process_group.append((replica_id, partition_id))
yield process_group
Örneğin, flattened_id_groups = [[0, 1, 2, 3], [4, 5, 6, 7]]
için
num_replicas = 4
ve num_partitions = 2
, flattened_ids
şunları üretecek:
[[(0, 0), (0, 1), (1, 0), (1, 1)], [(2, 0), (2, 1), (3, 0), (3, 1)]]
.
Doğruluk
Şu anda StableHLO, sayısal doğruluk ve ancak bu durum ileride değişebilir (#1156).
Ölçülen işlemin yürütme anlamı
Ölçülen StableHLO işlemlerinin yorumlanması donanım gereksinimleri ve özellikleri. Örneğin, bazı donanımlar "dequantize, gerçekleştirme kayan nokta ve son olarak da nicel olarak üzerine konuşacağız. Bazıları ise tüm etkinliği tamsayı aritmetiği ile hesaplama. Sonuç olarak, miktarlandırılmış StableHLO işlemleri, hakkında bilgi edindiniz. Karma niceliğin yorumlanması (#1575) değeri, teknik özellikleri belirtildiği gibi ( 1792).
Hatalar
StableHLO programları, ayrı ayrı işlem yapılmasını sağlar. Bu yöntem, çalışma zamanından önce birçok hata sınıfını ortadan kaldırır. Ancak hata koşulları yine de mümkündür, ör. tamsayı taşmaları sayesinde sınır dışı erişimler vb. olabilir. Açıkça belirtilmediği sürece tüm bu hatalar tanımlı davranışla sonuçlanır, ancak bu durum (#1157).
Kayan nokta istisnaları
Bu kurala bir istisna olarak, StableHLO programlarındaki kayan nokta istisnaları
iyi tanımlanmış davranışlara sahiptir.
IEEE-754 standardı (geçersiz işlem, sıfıra bölme, taşma, yetersiz veya
kesin olmayan istisnalar) üretmesi (standartta tanımlandığı şekilde) ve
karşılık gelen durum işaretini kaldırmadan yürütmeye devam etme; şunlara benzer:
Standarttan raiseNoFlag
istisna işleme. Standart dışı durumlar için istisnalar
işlemler (ör. karmaşık aritmetik ve belirli yüksek sayıdaki fonksiyonlar)
tanımlanmıştır.
Şekil uyuşmazlıkları
StableHLO, dinamik olarak şekilli tensörleri destekler. Ancak şekillerin hemfikir olması hem de aksi takdirde davranış tanımsızdır. StableHLO, bir tensörün çalışma zamanında belirli bir şekle sahip olduğunu gösterebilecek bir işlem sağlar. Doğru kodun oluşturulması yapımcının sorumluluğundadır.
Somut bir örnek vermek gerekirse aşağıdaki programın geçerliliği vardır. Ancak çalışma zamanında
%arg0
ve %arg1
tam şekillerinin aynı olması gerekir, aksi halde
programın davranışı tanımsızdır:
func.func @foo(%arg0: tensor<?xi32>, %arg1: tensor<?xi32>) -> tensor<?xi32> {
%0 = stablehlo.add %arg0, %arg1 : tensor<?xi32>
return %0 : tensor<?xi32>
}
Notasyon
Bu dokümanda, söz diziminin açıklanması için EBNF'nin değiştirilmiş ISO biçimi kullanılmaktadır
söz dizimine (ISO/IEC 14977:1996,
Vikipedi),
iki değişiklikle birlikte: 1) kurallar =
yerine ::=
kullanılarak tanımlanır,
2) birleştirme, ,
yerine yan yana konum kullanılarak ifade edilir.
Anlamları açıklamak için (ör. "Türler", "Sabitler" ve "İşlemler" bölümlerinde) Python söz dizimine dayalı formüller kullanıyoruz. dizi işlemlerini aşağıda açıklandığı gibi kısa bir şekilde ifade etmek için kullanılır. Bu, işe yarıyor küçük kod snippet'leri için, ancak nadiren de olsa daha büyük kod snippet'leri her zaman açıkça ortaya konulan vanilla Python söz dizimini kullanırız.
Formüller
dot_general
bakın. Bu işlemin kısıtlamalarından biri şu şekilde görünür:
dim(lhs, lhs_batching_dimensions...) = dim(rhs, rhs_batching_dimensions...)
Bu formülde kullanılan adlar iki kaynaktan gelir: 1) genel işlevler,
Ör. dim
, 2) ilgili program öğesinin üye tanımları, ör.
lhs
, lhs_batching_dimensions
, rhs
ve rhs_batching_dimensions
girişleri
"Girişler" bölümünde bölümünde (dot_general
) görebilirsiniz.
Yukarıda belirtildiği gibi, bu formülün söz dizimi Python tabanlıdır ve uzantılarınızın kısa ve öz olmasını sağlayın. Formülü anlamak için, dönüşüm izlemeyi vanil Python söz dizimine dönüştürmenizi sağlar.
A) Bu formüllerde eşitliği temsil etmek için =
kullanıyoruz, bu nedenle ilk adım
=
değerini ==
ile değiştirmek, Python söz dizimini elde etmek için aşağıdaki gibidir:
dim(lhs, lhs_batching_dimensions...) == dim(rhs, rhs_batching_dimensions...)
.
B) Ayrıca, bu formüller skaler ifadeleri dönüştüren elipsleri (...
) destekler
tensör ifadelerine dönüştürebilirsiniz. Özetle, f(xs...)
kabaca "her biri için
xs
tensöründeki skaler x
, bir skaler f(x)
hesaplayın ve ardından hepsini döndürün
bu skaler sonuçları bir tensör sonucu olarak birleştiriyoruz". Vanilla Python söz diziminde,
örnek formülümüz şuna dönüşür:
[dim(lhs, dim1) for dim1 in lhs_batching_dimensions] ==
[dim(rhs, dim2) for dim2 in rhs_batching_dimensions]
Elipsler sayesinde genelde sabit bir seviyede çalışmak
kullanabilirsiniz. Ancak bazı yanıltıcı örneklerde, daha düşük düzeyde
söz dizimi, start_indices[bi0, ..., :, ..., biN]
formülündeki gibi kullanılabilir
gather
spesifikasyonundan. Kısa ve öz yazım sağlamak amacıyla
bu tür söz dizimini vanilla Python'a çevirmek için kesin bir biçimsellik sağlamak
her örnek için sezgisel olarak anlaşılır olmasını umuyor.
Bazı formüller opak görünüyorsa lütfen bize bildirin. Bu durumda,
yardımcı olabilir.
Ayrıca, formüllerin her tür listeyi genişletmek için elipsler kullandığını fark edeceksiniz. tensörler ve tensör listeleri de dahil olmak üzere (örneğin, tensör sayısı) veriyorum. Bu, kesin bir veri sağlamadığımız bir başka alandır. biçimsellik (örneğin, listeler StableHLO türü sistemin bir parçası bile değildir) ve sezgisel anlaşılabilirliğe dayanır.
C) Kullandığımız son önemli notasyon aracı, üstü kapalıdır yayınlama. StableHLO işletim sistemi örtülü yayını desteklemese de aynı zamanda kısa ve öz yazın. Özetle, skaler bir veri bir tensörün beklendiği durumlarda kullanıldığında, skaler sağlayabilir.
dot_general
örneğine devam etmek için başka bir kısıtlama şu şekildedir:
0 <= lhs_batching_dimensions < rank(lhs)
. dot_general
içinde tanımlandığı şekilde
spesifikasyonlarında, lhs_batching_dimensions
bir tensördür, ancak hem 0
hem de
rank(lhs)
skaler değerlerdir. Dolaylı yayın uygulandıktan sonra, formül
[0, ..., 0] <= lhs_batching_dimensions < [rank(lhs), ..., rank(lhs)]
olur.
Bu formül belirli bir dot_general
işlemine uygulandığında
boole tensörüne dönüştürün. Formüller kısıtlama olarak kullanıldığında,
kısıt, formül true
veya sonuç veren bir tensör olarak değerlendirilirse
yalnızca true
öğeleri içeriyor.
Adlar
Formüllerde sözlüksel kapsam şunları içerir: 1) genel işlevler, 2) üye tanımları,
3) yerel tanımlar. Genel işlevlerin listesi aşağıda verilmiştir. Liste öğe tanımları, gösterimin temsil edildiği program öğesine bağlıdır uygulandı:
- İşlemler için üye tanımları, "Girişler"de sunulan adları da içerir. ve "Çıkışlar" bölümlerini kontrol edin.
- Diğer her şey için de üye tanımları,
program öğesi. Çoğu
Bu yapısal parçaların adları, zaman içinde
yılan şeklinde büyük/küçük harfe duyarlı olmayan terminallerin adları (ör.
IntegerLiteral
=>integer_literal
), ancak bazen adlar işlem sırasında kısaltılır (ör.QuantizationStorageType
=>storage_type
) olmalıdır; bu durumda adlar "Girdiler"e açıkça benzer şekilde tanıtıldı / "Çıkışlar" faaliyetteki bölümler özellikler. - Ayrıca, üye tanımlarında
self
ilgili program öğesine dokunun.
Değerler
Formüller değerlendirilirken aşağıdaki değer türleriyle çalışır:
1) Value
(gerçek değerler, ör. dense<[[1, 2], [3, 4]]> : tensor<2x2xi32>
;
türlerini daima bilirler.)
2) Placeholder
(gelecekteki değerler, ör. lhs
, rhs
veya result
; asıl değerleri
değerler henüz bilinmiyor, yalnızca türleri bilinmektedir).
3) Type
("Türler" bölümünde tanımlandığı şekilde türler),
4) Function
("İşlevler" bölümünde tanımlandığı şekliyle genel işlevler).
Bağlama göre adlar farklı değerleri ifade ediyor olabilir. Daha fazla
“Anlambilim” işlemler (ve diğer programın eşdeğerleri) bölümü
öğeleri) çalışma zamanı mantığını tanımlar. Bu nedenle, tüm girişler Value
olarak kullanılabilir.
Öte yandan "Sınırlamalar" bölümünde, DMAIC ve Yalın Altı Sigma yaklaşımının
"derleme-süresi" mantıksal, yani genellikle çalışma zamanından önce yürütülen bir işlem,
Bu nedenle, Value
olarak sadece sabit girişler kullanılabilir ve diğer girişler
yalnızca Placeholder
olarak kullanılabilir.
Adlar | "Anlambilim" bölümünde | "Kısıtlamalar" bölümünde |
---|---|---|
Genel işlevler | Function |
Function |
Sabit girişler | Value |
Value |
Sabit olmayan girişler | Value |
Placeholder |
Çıkışlar | Value |
Placeholder |
Yerel tanımlar | Tanıma bağlıdır. | Tanıma bağlıdır. |
Örnek bir transpose
işlemini inceleyelim:
%result = "stablehlo.transpose"(%operand) {
permutation = dense<[2, 1, 0]> : tensor<3xi64>
} : (tensor<2x3x2xi32>) -> tensor<2x3x2xi32>
Bu işlem için permutation
sabit olduğundan Value
olarak kullanılabilir
ve kısıtları yoktur. Öte yandan operand
ve result
,
anlamsal olarak bir Value
olarak, ancak kısıtlamalarda yalnızca Placeholder
olarak kullanılabilir.
İşlevler
Tür oluşturma
Türleri oluşturmak için kullanılabilecek işlev yoktur. Bunun yerine
genelde daha kısa ve öz olduğundan tür söz dizimini kullanın. Ör.
function_type(
[tensor_type([], E), tensor_type([], E)], [tensor_type([], E)])
yerine (tensor<E>, tensor<E>) -> (tensor<E>)
.
Türlerdeki işlevler
element_type
, tensör türlerinde ve nicelenmiş tensör türlerinde tanımlanır ve sırasıylaTensorElementType
veyaQuantizedTensorElementType
değerini döndürür (ilgiliTensorType
veyaQuantizedTensorType
)
def element_type(x: Value | Placeholder | Type):
if type(x) == TensorType:
return tensor_element_type(x)
if type(x) == QuantizedTensorType:
return quantized_tensor_element_type(x)
if type(x) is not Type:
return element_type(type(x))
is_per_axis_quantized(x: Value | Placeholder | Type) -> Value
bir kısayoldur (is_quantized(x) and quantization_dimension(x) is not None
için).is_per_tensor_quantized(x: Value | Placeholder | Type) -> Value
biris_quantized(x) and quantization_dimension(x) is None
kısayolu.is_promotable(x: Type, y: Type) -> bool
,x
türünün tanıtılıp tanıtılamayacağını kontrol edery
yazın.x
vey
QuantizedTensorElementType
olduğunda promosyon yalnızcastorage_type
öğesine uygulanır. Promosyonun bu versiyonu şu anda indirgenme hesaplaması bağlamında kullanılmaktadır (bkz. RFC'de bulabilirsiniz).
def is_promotable(x: Type, y: Type) -> Value:
is_same_type = (is_bool(x) and is_bool(y)) or
(is_integer(x) and is_integer(y)) or (is_float(x) and is_float(y)) or
(is_complex(x) and is_complex(y)) or
(is_quantized(x) and is_quantized(y) and expressed_type(x) = expressed_type(y))
if is_same_type == False:
return False
if is_integer(x) or is_float(x):
return bitwidth(x) <= bitwidth(y)
if is_complex(x):
return bitwidth(element_type(x)) <= bitwidth(element_type(y))
if is_quantized(x):
return bitwidth(storage_type(x)) <= bitwidth(storage_type(y))
return false
is_quantized(x: Value | Placeholder | Type) -> Value
şunun kısayoludur:is_quantized_tensor_element_type(x)
.is_type_name(x: Value | Placeholder | Type) -> Value
Herkes için kullanılabilir bulunur. Örneğin,x
birFloatType
iseis_float(x)
,true
değerini döndürür.x
bir değer veya yer tutucuysa bu işlevis_type_name(type(x))
.max_value(x: Type) -> Value
,TensorElementType
.x
birTensorElementType
değilseNone
değerini döndürür.min_value(x: Type) -> Value
, birTensorElementType
.x
birTensorElementType
değilseNone
değerini döndürür.member_name(x: Value | Placeholder | Type) -> Any
Tüm üyeler tarafından kullanılabilir her türdenmember_name
tanımlar. Örneğin,tensor_element_type(x)
karşılık gelenTensorType
öğesininTensorElementType
bölümünü döndürür.x
bir değer veya yer tutucuysa bu işlevmember_name(type(x))
.x
, uygun üyeye sahip bir tür değilse veya bir değer veya böyle bir tür yer tutucusuNone
değerini döndürür.is_empty_algorithm(*args: Type)
, tüm nokta algoritması alanlarının ayarlanıp ayarlanmadığını kontrol eder Hedef:None
. Nokta algoritmalarında uygulama tanımı yapıldığından bu gereklidir bu nedenle değer belirtmek yanlış olur.
Değerlerin oluşturulması
operation_name(*xs: Value | Type) -> Value
Tüm işlemler için kullanılabilir. Örneğin,add(lhs, rhs)
,lhs
verhs
olmak üzere iki tensör değeri alır veadd
işlemini bu girişlerle değerlendirmenin sonucunu döndürür. Bazı işlemler için, ör.broadcast_in_dim
, çıkış türleri "yük taşıyan", yani bir işlemi değerlendirmek için gereklidir. Bu durumda, bunları bağımsız değişken olarak kabul eder.
Değerlere dayalı işlevler
Python'un tüm operatörleri ve işlevleri kullanılabilir. Ör. her ikisi abonelik ve dilimlere ayırma Python'daki gösterimler, tensörlere, miktarlandırılmış tensörlere dizine eklemek için kullanılabilir ve demetler.
to_destination_type(x: Value, destination_type: Type) -> Value
şurada tanımlandı: tensörler iletype(x)
ve özelliklerine göre dönüştürülmüşx
değerini döndürürdestination_type
şu şekildedir:
def to_destination_type(x: Value, destination_type: Type) -> Value:
if type(x) == destination_type:
return x
if is_quantized(destination_type):
if is_quantized(type(x)):
return quantize(x, destination_type)
assert is_float(type(x))
return quantize(x, destination_type)
if is_quantized(type(x)):
assert destination_type = expressed_type(type(x))
return dequantize(type(x))
return convert(x, destination_type)
convert
, uniform_quantize
ve
uniform_dequantize
işlemleri (#1576).
Birleştirmeden sonra yukarıdaki işleve gerek duymayız ve işlem adını kullanabiliriz.
Bunun yerine convert
için.
is_nan(x: Value) -> Value
, tensörlerde tanımlanır ve şu durumlardatrue
değerini döndürür:x
öğesinin tüm öğeleriNaN
veyafalse
öğesidir.x
bir tensör değilseNone
değerini döndürür.is_sorted(x: Value) -> Value
, tensörlerde tanımlanır ve şu durumlardatrue
değerini döndürür:x
öğeleri artan düzende, artan düzende sıralanır veyafalse
kullanılması şart değildir.x
bir tensor,None
değerini döndürür.is_unique(x: Value) -> Value
, tensörlerde tanımlanır vex
isetrue
değerini döndürür yinelenen öğeler veyafalse
içermiyor.x
bir tensör değilseNone
değerini döndürür.Tüm üye tanımları için
member_name(x: Value) -> Any
tanımlandı Tüm değerlerinmember_name
kadarı. Örneğin,real_part(x)
,RealPart
değerini döndürür. bir bölümü için ödeme yaparsınız.ComplexConstant
x
, uygun üye,None
değerini döndürür.same(x: Value) -> Value
, tensörlerde tanımlanır ve şu durumlardatrue
değerini döndürür:x
öğelerinin tümü birbirine eşit veya aksi takdirdefalse
. Tensör "hepsi birbirine eşit" olarak kabul edilen, yani işlevitrue
değerini döndürür.x
bir tensör değilseNone
değerini döndürür.split(x: Value, num_results: Value, axis: Value) -> Value
şurada tanımlandı: tensörler veaxis
ekseni üzerindenum_results
x
dilimleri döndürür.x
bir tensör veyadim(x, axis) % num_results != 0
değilseNone
değerini döndürür.is_defined_in_parent_scope(x: Value) -> Value
dizelerde tanımlı vex
aynı kapsamda tanımlanan bir işlevin adıysatrue
değerini döndürür ilgili işlemin ana işlevi olarak kullanılır.is_namespaced_op_name(x: Value) -> Value
, dizelerde ve iadelerde tanımlanırx
geçerli bir işlem adıysatrue
ifade:[a-zA-Z][a-zA-Z0-9_]*([.][a-zA-Z0-9_$]+)+
Şekil hesaplamaları
axes(x: Value | Placeholder | Type) -> Value
şunun kısayoludur:range(rank(x))
.dim(x: Value | Placeholder | Type, axis: Value) -> Value
şunun kısayoludur:shape(x)[axis]
.dims(x: Value | Placeholder | Type, axes: List) -> List
şunun kısayoludur:list(map(lambda axis: dim(x, axis), axes))
.index_space(x: Value | Placeholder | Type) -> Value
, tensörlerde tanımlandı ve aşağıdaki dizinde sıralanmış karşılık gelenTensorType
içinsize(x)
dizin döndürür artan sözlük sıralaması, ör.[0, ..., 0]
,[0, ..., 1]
, ...,shape(x) - 1
.x
bir tensör türü, nicelenmiş tensör türü veya bir değer değilse veya bu türlerden birinin yer tutucusuNone
değerini döndürür.rank(x: Value | Placeholder | Type) -> Value
şunun kısayoludur:size(shape(x))
.shape(x: Value | Placeholder | Type) -> Value
, "İşlevler" içinde tanımlanmış türlerde" bölümünemember_name
üzerinden ulaşabilirsiniz.size(x: Value | Placeholder | Type) -> Value
şunun kısayoludur:reduce(lambda x, y: x * y, shape(x))
.
Nicelendirme hesaplamaları
def baseline_element_type(x: Value | Placeholder | Type) -> Type
birelement_type(baseline_type(x))
kısayolu.baseline_type
, tensör türlerinde ve nicelenmiş tensör türlerinde tanımlanır ve bunları "referans çizgisine" (yani aynı şekle sahip ancak öğe türünün niceleme parametreleri varsayılan değerlere sıfırlanır. Bu tensör ve nicel tensör türlerini karşılaştırmak için kullanışlı bir yöntem olarak kullanılmıştır eşit şekilde çalışıyor. Bu da oldukça sık ihtiyaç duyuyor. Bu, miktarlandırılmış türlerde yok sayarak türlerin karşılaştırılması (shape
,storage_type
,expressed_type
,storage_min
,storage_max
vequantization_dimension
(eksen başına miktarlandırılmış tür için) değerinin tümü eşleşmelidir, ancakscales
ilezero points
farklı olabilir.
def baseline_type(x: Value | Placeholder | Type) -> Type:
if type(x) == TensorType:
return x
if type(x) == QuantizedTensorType:
element_type = quantized_tensor_element_type(x)
baseline_element_type = QuantizedTensorElementType(
storage_type = storage_type(element_type),
storage_min = storage_min(element_type),
storage_max = storage_max(element_type),
expressed_type = expressed_type(element_type),
quantization_dimension = quantization_dimension(element_type),
scales = [constant(1.0, expressed_type(element_type))] * dim(x, quantization_dimension(element_type)),
zero_points = [constant(0, storage_type(element_type))] * dim(x, quantization_dimension(element_type)))
return QuantizedTensorType(shape(x), baseline_element_type)
if type(x) is not Type:
return baseline_element_type(type(x))
dequantize
, nicel tensör türlerinde tanımlanır ve bunları şuna dönüştürür: kayan nokta tensörü türlerine örnek verilebilir. Bu, nicelenmiş öğelerin dönüştürülmesiyle gerçekleşir depolama türünün tam sayı değerlerini karşılık gelen sıfır noktası ve ölçeği kullanılarak ifade edilen türün kayan nokta değerleri ölçülebilir öğe türüyle ilişkilidir.
def compute_zero_points(quantized_type, result_type):
if is_per_tensor_quantized(quantized_type):
return broadcast_in_dim(constant(zero_point(quantized_type), storage_type(quantized_type)), [], result_type)
if is_per_axis_quantized(quantized_type):
for i in index_space(result_type):
d = quantization_dimension(quantized_type)
zero_points[i] = zero_points(quantized_type)[i[d]]
return zero_points
def compute_scales(quantized_type, result_type):
if is_per_tensor_quantized(quantized_type):
return broadcast_in_dim(constant(scale(quantized_type), expressed_type(quantized_type)), [],
type(result_type))
if is_per_axis_quantized(quantized_type):
for i in index_space(result_type):
d = quantization_dimension(quantized_type)
scales[i] = scales(quantized_type)[i[d]]
return scales
def dequantize(x: Value) -> Value:
assert is_quantized(x)
x_storage = bitcast_convert(x, storage_type(x))
x_storage_sub = x_storage - compute_zero_points(type(x), type(x_storage))
x_expressed_sub = convert(x_storage_sub, expressed_type(x))
return x_expressed_sub * compute_scales(type(x), type(x_expressed_sub))
quantize
, kayan nokta tensör türlerinde tanımlanır ve bunları şuna dönüştürür: nicel tensör türlerine bakalım. Bu, kayan nokta değerlerini dönüştürerek gerçekleşir depolama türünün karşılık gelen tam sayı değerlerine ifade edilen türün kullanılan öğe türüyle ilişkili sıfır noktası ve ölçeğin kullanılmasıdır.
def quantize(x: Value, result_type: Type) -> Value:
assert is_float(x) and is_quantized(result_type)
zero_points = compute_zero_points(result_type, TensorType(shape(x), storage_type(result_type)))
converted_zero_points = convert(zero_points, expressed_type(result_type))
converted_min = convert(storage_min(result_type), expressed_type(result_type))
converted_max = convert(storage_max(result_type), expressed_type(result_type))
x_scaled = x / compute_scales(result_type, type(x))
x_scaled_add_zp = x_scaled + converted_zero_points
x_clamped = clamp(converted_min, x_scaled_add_zp, converted_max)
x_rounded = round_nearest_even(x_clamped)
return convert(x_rounded, result_type)
dequantize_op_quantize
, nicelleştirilmiş tensörler. Miktarı belirler, yani nicelleştirilmiş öğeleri ardından bir işlem gerçekleştirir ve ardından nicelik olarak ifade eder. Diğer bir deyişle, depolama türüne geri döner. Şu anda bu işlev yalnızca tensör başına miktar belirleme için kullanılır. Eksen başına miktar belirleme işlemi devam ediyor (#1574).
def dequantize_op_quantize(op, *inputs_and_output_type):
inputs = inputs_and_output_type[:-1]
output_type = inputs_and_output_type[-1]
float_inputs = map(dequantize, inputs)
float_result = op(*float_inputs)
return quantize(float_result, output_type)
def dequantize_batch_norm_grad_or_training_quantize(op, *inputs_and_output_types):
inputs = inputs_and_output_type[:-3]
float_inputs = map(dequantize, inputs)
float_results = op(*float_inputs)
return map(quantize, float_results, inputs_and_output_type[-3:])
def dequantize_compare(lhs, rhs, comparison_direction):
float_lhs = dequantize(lhs)
float_rhs = dequantize(rhs)
return compare(float_lhs, float_rhs, comparison_direction, FLOAT)
def dequantize_select_quantize(pred, on_true, on_false, output_type):
float_on_true = dequantize(on_true)
float_on_false = dequantize(on_false)
float_result = select(pred, float_on_true, float_on_false)
return quantize(float_result, output_type)
hybrid_dequantize_then_op
, şunlar için yalnızca ağırlık miktarını belirtmek için kullanılır: Kayan noktalı türlerde lh ve rhs kabul eden karma işlem. Google nicel girdileri ifade edilen türlerine göre ayırır ve hesaplama yapar kullanabilirsiniz. Kayan lhs tensörünün öğe türü ve ölçülen rh'lerin ifade edilen türü tensör aynı olmalıdır.
def hybrid_dequantize_then_op(op, lhs, rhs):
assert(is_float(lhs) and is_quantized(rhs) and element_type(lhs) == expressed_type(rhs))
return op(lhs, dequantize(rhs))
Izgara hesaplamaları
cross_partition(replica_groups: Value) -> Value
"cross_replica" ifadesini inceleyin. bölümüne bakın.cross_replica(replica_groups: Value) -> Value
"cross_replica" ifadesini inceleyin. bölümüne bakın.cross_replica_and_partition(replica_groups: Value) -> Value
Bkz. "cross_replica_and_partition" bölümüne bakın.flattened_ids(replica_groups: Value) -> Value
"flattened_ids" değerini inceleyin bölümüne bakın.
Dinamik
StableHLO değerlerinin dinamik boyut boyutları olabilir (ör. tensor<?xi64>
Ancak StableHLO değerleri dinamik sayıda boyuta (sıralanmamış) sahip olamaz.
dinamik, ör. tensor<*xi64>
) bilgileri gösterilir. İşlem görenler ve sonuçların dinamik
boyut kısıtlamaları mevcut olsa bile bu boyuta izin verilmez. Kısıtlamalar
mümkünse statik olarak doğrulanır, aksi takdirde çalışma zamanına
belirsiz davranışa neden olur. Örnekler için aşağıya bakın.
Tekli öğe bazlı işlemler için şekil uyuşmazlıkları
Şu oyuncak programını kullanabilirsiniz:
func.func @foo(%arg0: tensor<?xf64>) {
%0 = stablehlo.abs %arg0 : (tensor<?xf64>) -> tensor<2xf64>
return
}
Bu tür bir program olağan dışıdır, çünkü
girdinin şeklini belirtmez. Yine de bu, geçerli bir StableHLO
çok önemli. Bu öğede abs
işlemini statik olarak doğrulamak mümkün değildir
programda bulunabilir. Bunun nedeni, işlenenin tam şekli bilinmemektedir. Ancak şekiller
kesinlikle uyumludur ve bu durum statik olarak kontrol edilebilir: ?
2
olacak ve hiç sorun olmayacak. Ancak ?
ortaya çıkan başka bir tam sayı olacaktır. Bu durumda, davranış tanımlanmamış olur.
Sonuçta dinamik boyut boyutu varsa olabilir. Gerçekten de, hiç "beklenen" büyüklükte olduğundan uyuşmazlığı.
İkili öğe tabanlı işlemler için şekil uyuşmazlıkları
Şu oyuncak programını kullanabilirsiniz:
func.func @foo(%arg0: tensor<?xf64>, %arg1: tensor<?xf64>) {
%0 = stablehlo.add %arg0, %arg0 : (tensor<?xf64>, tensor<?xf64>) -> tensor<?xf64>
return
}
İkili element tabanlı işlemler söz konusu olduğunda, girişlerin ve girdilerin şekilleri sonucu çalışma zamanında aynı olmalıdır. Derleme sırasında statik boyutlar, Aksi takdirde, tek yapmaları gereken uyumlu olmaları gerekir. Girişlerde herhangi bir boyut dinamikse tanımlanmamış olabilir genellikle çalışma zamanında istenen davranışa işaret etmesidir, çünkü dinamik boyut diğer işlenendeki boyut (statik veya dinamik) olmalıdır. Tüm girişler sonucun dinamik olup olmaması önemli değildir: statik olarak bilinen boyutlar statik olarak kontrol edilir. Dinamik boyutlar ise ve kısıtları yoktur.
Çıktı şeklini işlenen olarak alan işlemler için şekil uyuşmazlıkları
Şu oyuncak programını kullanabilirsiniz:
func.func @foo(%arg0: tensor<2xi32>) {
%0 = stablehlo.dynamic_iota %arg0, dim = 0 : (tensor<2xi32>) -> tensor<3x4xi64>
return
}
Çalışma zamanında şekil işlenenindeki değerler sonucun şekliyle eşleşmelidir.
Aksi takdirde davranış tanımsızdır. Yani, çalışma zamanında %arg0
için
dense<[3, 4]> : tensor<2xi32>
değerine ayarlanır. Şekil işleneni sabitse
statik olarak doğrulanabilir. Sonuç şekli tamamen dinamikse
uyuşmuyor olabilir.