StableHLO की खास बातें

StableHLO, मशीन में हाई-लेवल ऑपरेशन (HLO) के लिए इस्तेमाल होने वाला एक ऑपरेशन सेट है लर्निंग (एमएल) मॉडल. StableHLO, अलग-अलग प्लैटफ़ॉर्म के बीच पोर्टेबिलिटी लेयर के तौर पर काम करता है एमएल फ़्रेमवर्क और एमएल कंपाइलर: एमएल फ़्रेमवर्क जो StableHLO प्रोग्राम बनाते हैं एमएल कंपाइलर के साथ काम करते हैं, जो StableHLO प्रोग्राम का इस्तेमाल करते हैं.

हमारा मकसद, मशीन लर्निंग को आसान बनाने के साथ-साथ मशीन लर्निंग को बेहतर बनाने के लिए, मशीन लर्निंग सिस्टम को अलग-अलग एमएल फ़्रेमवर्क के बीच इंटरऑपरेबिलिटी (दूसरे सिस्टम के साथ काम करना), जैसे कि TensorFlow, JAX, और PyTorch) और ML कंपाइलर (जैसे कि XLA और IREE). उस ओर, यह इस दस्तावेज़ में StableHLO प्रोग्रामिंग भाषा की जानकारी दी गई है.

इस स्पेसिफ़िकेशन में तीन मुख्य सेक्शन शामिल हैं. सबसे पहले, प्रोग्राम सेक्शन में, StableHLO प्रोग्राम की बनावट के बारे में जानकारी दी जाती है इनमें StableHLO फ़ंक्शन शामिल होते हैं, जिनमें StableHLO ops शामिल होता है. उस स्ट्रक्चर में, Ops सेक्शन, व्यक्तिगत ऑपरेशन एक्ज़िक्यूशन सेक्शन सभी के लिए सिमेंटिक उपलब्ध कराता है ये Ops, किसी प्रोग्राम में एक साथ एक्ज़ीक्यूट किए जाते हैं. आख़िर में, नोटेशन सेक्शन में स्पेसिफ़िकेशन.

StableHLO की पिछली रिलीज़ की खास जानकारी देखने के लिए, रेपो खोलें पसंद की टैग की गई रिलीज़. उदाहरण के लिए, StableHLO v0.19.0 स्पेसिफ़िकेशन. StableHLO के हर छोटे वर्शन बंप पर होने वाले बदलावों को देखने के लिए, इसे देखें VhloDialect.td वर्शन में लॉग इन करें.

प्रोग्राम

Program ::= {Func}

StableHLO प्रोग्राम में आर्बिट्रेरी संख्या में StableHLO फ़ंक्शन होते हैं. यहां @main फ़ंक्शन वाले प्रोग्राम का उदाहरण दिया गया है, जिसमें तीन इनपुट हैं (%image, %weights और %bias) और 1 आउटपुट. फ़ंक्शन का मुख्य हिस्सा में 6 ऑपरेशन हैं.

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>) -> ()
}

फ़ंक्शन

Func        ::= 'func' '.' 'func' FuncId FuncInputs FuncOutputs '{' FuncBody '}'
FuncInputs  ::= '(' [FuncInput {',' FuncInput}] `)`
FuncInput   ::= ValueId ':' ValueType
FuncOutputs ::= ['->' FuncOutput, {',' FuncOutput}]
FuncOutput  ::= ValueType
FuncBody    ::= {Op}

StableHLO फ़ंक्शन (जिन्हें नाम वाले फ़ंक्शन भी कहा जाता है) में एक आइडेंटिफ़ायर, इनपुट/आउटपुट, और एक बॉडी. आने वाले समय में, हम फ़ंक्शन के लिए अतिरिक्त मेटाडेटा की जानकारी दें, ताकि वे बेहतर तरीके से काम कर सकें HLO (#425, #626, #740, #744).

आइडेंटिफ़ायर

FuncId  ::= '@' letter {letter | digit}
ValueId ::= '%' digit {digit}
          | '%' letter {letter | digit}
letter  ::= 'a' | ... | 'z' | 'A' | ... | 'Z' | '_'
digit   ::= '0' | ... | '9'

StableHLO आइडेंटिफ़ायर, कई प्रोग्राम में मौजूद आइडेंटिफ़ायर से मिलते-जुलते होते हैं होती है, जिसकी दो विशेषताएं होती हैं: 1) सभी आइडेंटिफ़ायर अलग-अलग तरह के आइडेंटिफ़ायर में अंतर करें, 2) वैल्यू आइडेंटिफ़ायर StableHLO प्रोग्राम की जनरेशन को आसान बनाने के लिए पूरी तरह से न्यूमेरिक.

टाइप

Type         ::= ValueType | NonValueType
ValueType    ::= TensorType | QuantizedTensorType | TokenType | TupleType
NonValueType ::= TensorElementType | QuantizedTensorElementType | FunctionType | StringType

StableHLO टाइप को वैल्यू टाइप में रखा जाता है (इन्हें फ़र्स्ट-क्लास टाइप) जो StableHLO वैल्यू और नॉन-वैल्यू टाइप दिखाते हैं जो प्रोग्राम से जुड़े अन्य एलिमेंट के बारे में बताती हैं. StableHLO के टाइप, कई प्रोग्रामिंग भाषाओं में से एक है, जिसकी मुख्य विशेषता StableHLO एक खास डोमेन के लिए तैयार किया गया है, जिसकी वजह से कुछ असामान्य नतीजे मिलते हैं (उदाहरण के लिए, स्केलर टाइप वैल्यू टाइप नहीं हैं).

TensorType ::= 'tensor' '<' Shape TensorElementType '>'
Shape ::= {DimensionSize 'x'}
DimensionSize ::= digit {digit} | '?'

टेन्सर के टाइप टेंसर यानी कई डाइमेंशन वाले सरणियों को दिखाते हैं. उनके पास आकार और एलिमेंट का टाइप, जिसमें आकार गैर-ऋणात्मक या संबंधित डाइमेंशन साइज़ के बढ़ते क्रम में डाइमेंशन (जिन्हें ऐक्सिस भी कहा जाता है) को 0 से R-1 तक के नंबर के साथ लिखा जाता है. कॉन्टेंट बनाने डाइमेंशन की संख्या R को रैंक कहा जाता है. उदाहरण के लिए, tensor<2x3xf32> 2x3 आकार और f32 एलिमेंट वाला टेंसर टाइप. इसमें दो डाइमेंशन हैं (या, दूसरे शब्दों में, दो ऐक्सिस) - पहला डाइमेंशन और पहला डाइमेंशन - जिसके साइज़ नंबर 2 और 3 हैं. इसकी रैंक दो है.

आकार आंशिक या पूरी तरह से अज्ञात (डाइनैमिक) हो सकता है, जैसे tensor<?x2xf64> अभी तक किसी भी व्यक्ति ने चेक इन नहीं किया है आंशिक रूप से अज्ञात है और tensor<?x?xf64> पूरी तरह अज्ञात है. डाइनैमिक डाइमेंशन के साइज़ को ? का इस्तेमाल करके दिखाया जाता है. आकारों को अनरैंक नहीं किया जा सकता.

आने वाले समय में, हम ऐसे अन्य टेंसर टाइप एक्सप्लोर करने की योजना बना रहे हैं जो डाइमेंशन साइज़ और एलिमेंट टाइप. उदाहरण के लिए, लेआउट शामिल करने के लिए (#629) और विरलता (#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
नाम टाइप कंस्ट्रेंट
storage_type पूर्णांक का टाइप (C1-C3), (C8)
storage_min पूर्णांक कॉन्सटेंट (C1), (C3), (C7)
storage_max पूर्णांक कॉन्सटेंट (C2), (C3), (C7)
expressed_type फ़्लोटिंग-पॉइंट टाइप (सी4)
quantization_dimension वैकल्पिक पूर्णांक कॉन्सटेंट (C10-C12)
scales फ़्लोटिंग-पॉइंट कॉन्सटेंट की वैरायडिक संख्या (C4-C6), (C9), (C10), (C13)
zero_points पूर्णांक कॉन्सटेंट की वैरायडिक संख्या (C7-C9)

क्वांटाइज़ किए गए एलिमेंट टाइप, स्टोरेज टाइप के पूर्णांक वैल्यू को दिखाते हैं storage_min से storage_max तक की श्रेणी (शामिल) जो इससे संबंधित है दिखाए गए टाइप के फ़्लोटिंग-पॉइंट वैल्यू. दी गई पूर्णांक वैल्यू i के लिए, संबंधित फ़्लोटिंग-पॉइंट मान f का हिसाब इस तरह से लगाया जा सकता है f = (i - zero_point) * scale, जहां scale और zero_point को कॉल किया जाता है क्वांटाइज़ेशन पैरामीटर. storage_min और storage_max ज़रूरी नहीं हैं व्याकरण में है, लेकिन डिफ़ॉल्ट तौर पर min_value(storage_type) और max_value(storage_type). क्वांटाइज़्ड एलिमेंट टाइप में शर्तों को पूरा करना होगा:

  • (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) है, तो size(scales) = 1.
  • (C11) 0 <= quantization_dimension.

इस समय, QuantizationScale एक फ़्लोटिंग-पॉइंट कॉन्सटेंट है, लेकिन वहां पूर्णांक-आधारित स्केल में ज़्यादा दिलचस्पी होना, जिसे मल्टीप्लायर से दिखाया गया हो और शिफ़्ट. हम आने वाले समय में इस पर काम करने के बारे में सोच रहे हैं (#1404).

QuantizationZeroPoint के सिमैंटिक पर एक बातचीत चल रही है, इसमें वे टाइप और वैल्यू शामिल होती हैं. साथ ही, यह भी जानकारी होती है कि क्या सिर्फ़ एक या क्वांटाइज़्ड टेंसर टाइप में, कई शून्य पॉइंट हो सकते हैं. इसके आधार पर इस चर्चा के परिणाम, शून्य बिंदु के लिए निर्देश बदल सकते हैं आने वाले समय में (#1405).

एक अन्य चर्चा में QuantizationStorageMin के सिमेंटिक्स शामिल हैं और QuantizationStorageMax तय करते हैं कि किसी कंस्ट्रेंट को इन वैल्यू और क्वांटाइज़्ड टेंसर की वैल्यू पर लगाया गया (#1406).

आखिर में, हम अज्ञात स्केल और शून्य को दर्शाने वाले तरीके के बारे में जानने की योजना बना रहे हैं जैसे हम अनजान लोगों को दिखाने के लिए डाइमेंशन का साइज़ (#1407).

क्वांटाइज़्ड टेंसर टाइप, क्वांटाइज़्ड एलिमेंट वाले टेंसर दिखाते हैं. ये टेंसर, सामान्य टेंसर की तरह ही होते हैं, अंतर सिर्फ़ इतना होता है कि उनके एलिमेंट इसमें सामान्य एलिमेंट के बजाय क्वांटाइज़्ड एलिमेंट टाइप होते हैं.

क्वांटाइज़्ड टेंसर में, क्वांटाइज़ेशन हर टेंसर के हिसाब से हो सकता है. इसका मतलब है कि पूरे टेंसर के लिए एक scale और zero_point या हर ऐक्सिस पर एक वैल्यू हो सकती है, मतलब कई scales और zero_points होने का मतलब है, इमेज के हर स्लाइस के लिए एक जोड़ा कोई विशेष आयाम quantization_dimension. औपचारिक तौर पर, टेंसर में t हर एक्सिस पर संख्या के हिसाब से, dim(t, quantization_dimension) स्लाइस हैं quantization_dimension में से: t[:, ..., 0, ..., :], t[:, ..., 1, ..., :], वगैरह. iवें स्लाइस के सभी एलिमेंट में scales[i] और zero_points[i] का इस्तेमाल इस तौर पर किया जाएगा में अपने क्वांटाइज़ेशन पैरामीटर को जोड़ दिया जाता है. क्वांटाइज़्ड टेंसर के टाइप में ये शामिल हैं सीमाएं:

  • हर टेन्सर की क्वांटाइज़ेशन के लिए:
    • कोई अतिरिक्त शर्त नहीं.
  • हर ऐक्सिस पर प्रॉडक्ट की संख्या बढ़ाने के लिए:
    • (C12) quantization_dimension < rank(self).
    • (C13) dim(self, quantization_dimension) = size(scales).
TokenType ::= 'token'

टोकन के टाइप, टोकन दिखाते हैं. जैसे, बनी और इस्तेमाल की गई ओपेक वैल्यू कुछ कार्रवाइयों से किया जा सकता है. टोकन का इस्तेमाल कार्रवाइयों को लागू करने का ऑर्डर देने के लिए किया जाता है जैसा कि इस्तेमाल करना सेक्शन में बताया गया है.

TupleType ::= 'tuple' '<' TupleElementTypes '>'
TupleElementTypes ::= [ValueType {',' ValueType}]

ट्यूपल टाइप, ट्यूपल को दिखाते हैं. जैसे, विषमांगी सूचियां. टपल्स एक लेगसी हैं ऐसी सुविधा है जो सिर्फ़ HLO के साथ काम करने के लिए मौजूद है. HLO में, टपल्स इसका इस्तेमाल वैरिडिक इनपुट और आउटपुट को दिखाने के लिए किया जाता है. StableHLO में, वैरायडिक इनपुट और आउटपुट, नेटिव तौर पर काम करते हैं. साथ ही, StableHLO में टुपल का सिर्फ़ यह इस्तेमाल किया जाता है कि HLO ABI को अच्छी तरह से दिखाता है, जहां उदाहरण के लिए, T, tuple<T>, और tuple<tuple<T>> किसी खास डेटा टाइप के आधार पर असल में अलग हो सकता है लागू करना. आने वाले समय में, हम एचएलओ एबीआई में बदलाव करने की योजना बना रहे हैं जिसकी मदद से हम StableHLO से ट्यूपल टाइप हटा सकते हैं (#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'

एलिमेंट टाइप, टेंसर टाइप के एलिमेंट दिखाते हैं. कई तरह के कॉन्टेंट से अलग नहीं हैं, तो ये प्रकार StableHLO में प्रथम श्रेणी के नहीं हैं. इसका मतलब है कि StableHLO प्रोग्राम, सीधे तौर पर इस तरह की वैल्यू नहीं दिखा सकते. इसकी वजह से, T टाइप की अदिश वैल्यू को 0-डाइमेंशन वाले टेंसर के साथ दिखाना मुहावरेदार होता है tensor<T> टाइप की वैल्यू).

  • बूलियन टाइप, बूलियन वैल्यू true और false को दिखाता है.
  • इंटिजर टाइप साइन (si) या अनसाइन किए गए (ui) हो सकते हैं. साथ ही, काम करने वाली बिट की चौड़ाई (2, 4, 8, 16, 32 या 64) में से कोई एक. साइन किए गए siN टाइप, -2^(N-1) से 2^(N-1)-1 तक की पूर्णांक वैल्यू दिखाते हैं शामिल हैं, और अनसाइन किए गए uiN टाइप, 0 से लेकर इंटिजर वैल्यू को दिखाते हैं 2^N-1 के साथ.
  • फ़्लोटिंग-पॉइंट के टाइप इनमें से कोई एक हो सकते हैं:
  • जटिल प्रकार ऐसे जटिल मान दिखाते हैं जिनका वास्तविक भाग होता है और उसी एलिमेंट टाइप का कोई काल्पनिक हिस्सा. इस्तेमाल किया जा सकने वाला कॉम्प्लेक्स टाइप complex<f32> हैं (दोनों हिस्से f32 टाइप के हैं) और complex<f64> (दोनों हिस्से f64 टाइप के हैं).
FunctionType ::= '(' InputTypes ')' '->' '(' OutputTypes ')'
InputTypes ::= [ValueType {',' ValueType}]
OutputTypes ::= [ValueType {',' ValueType}]

फ़ंक्शन टाइप नाम वाले और पहचान छिपाने वाले, दोनों तरह के फ़ंक्शन दिखाते हैं. उनके पास इनपुट टाइप (-> की बाईं ओर मौजूद टाइप की सूची) और आउटपुट टाइप (-> की दाईं ओर टाइप की सूची). कई प्रोग्रामिंग में भाषाओं के आधार पर, फ़ंक्शन टाइप फ़र्स्ट क्लास हैं, लेकिन StableHLO में नहीं.

StringType ::= 'string'

स्ट्रिंग टाइप, बाइट के क्रम को दिखाता है. कई तरह के कॉन्टेंट से अलग भाषाओं के साथ-साथ, StableHLO में स्ट्रिंग टाइप फ़र्स्ट क्लास नहीं होता है. इसका इस्तेमाल सिर्फ़ इन कामों के लिए किया जाता है प्रोग्राम के एलिमेंट के लिए स्टैटिक मेटाडेटा की जानकारी दें.

ऑपरेशंस

StableHLO ऑपरेशन (जिन्हें ops भी कहा जाता है) एक बंद सेट का प्रतिनिधित्व करते हैं में हाई-लेवल ऑपरेशन के बारे में बताया गया है. जैसा कि ऊपर बताया गया है, StableHLO सिंटैक्स काफ़ी हद तक MLIR से प्रभावित होता है. यह ज़रूरी नहीं है कि एर्गोनॉमिक विकल्प है, लेकिन निश्चित रूप से यह StableHLO के एमएल फ़्रेमवर्क और एमएल कंपाइलर के बीच ज़्यादा इंटरऑपरेबिलिटी (दूसरे सिस्टम के साथ काम करना) बनाना.

Op            ::= [OpOutputs] OpName OpInputs ':' OpSignature
OpName        ::= '"' 'stablehlo' '.' OpMnemonic '"'
OpMnemonic    ::= 'abs' | 'add' | ...

StableHLO ऑपरेशंस (जिन्हें ops भी कहा जाता है) का एक नाम है, इनपुट/आउटपुट और एक हस्ताक्षर. नाम में stablehlo. प्रीफ़िक्स शामिल है और स्मृति एक ऐसी सुविधा है जो काम करने वाली कार्रवाइयों में से किसी एक की खास तौर पर पहचान करती है. इनके लिए नीचे देखें उन सभी ऑपरेशन की पूरी सूची होगी जिनका इस्तेमाल किया जा सकता है.

OpInputs        ::= OpInputValues OpInputFuncs OpInputAttrs
OpInputValues   ::= '(' [OpInputValue {',' OpInputValue}] ')'
OpInputValue    ::= ValueId
OpInputFuncs    ::= ['(' OpInputFunc {',' OpInputFunc} ')']
OpInputAttrs    ::= ['{' OpInputAttr {',' OpInputAttr} '}']
OpOutputs       ::= [OpOutput {',' OpOutput} '=']
OpOutput        ::= ValueId

ऑपरेशन इनपुट का इस्तेमाल करते हैं और आउटपुट बनाते हैं. इनपुट को इसमें कैटगरी में बांटा गया है इनपुट वैल्यू (एक्ज़िक्यूशन के दौरान कैलकुलेट की गई), इनपुट फ़ंक्शन (दिया गए स्थिर रूप से, क्योंकि StableHLO में फ़ंक्शन फ़र्स्ट-क्लास वैल्यू नहीं होते हैं) और एट्रिब्यूट की वैल्यू डालें (स्टैटिक तरीके से भी दी गई). इनपुट और आउटपुट किस तरह के हैं यह ऑपर्च्यूनिटी की वजह से बनाया जाता है और इसका इस्तेमाल किया जाता है. उदाहरण के लिए, add op, दो इनपुट वैल्यू का इस्तेमाल करता है और एक आउटपुट वैल्यू देता है. इसके मुकाबले, select_and_scatter op, तीन इनपुट वैल्यू, दो इनपुट फ़ंक्शन, और तीन इनपुट एट्रिब्यूट.

OpInputFunc ::= '{' Unused FuncInputs ':' FuncBody '}'
Unused      ::= '^' digit {digit}
              | '^' letter {letter | digit}

इनपुट फ़ंक्शन (जिन्हें अनाम फ़ंक्शन भी कहा जाता है) वे नाम वाले फ़ंक्शन से मिलते-जुलते हैं, लेकिन शामिल हैं: 1) इनमें कोई आइडेंटिफ़ायर नहीं है (इसलिए) नाम "अनाम"), 2) आउटपुट टाइप का एलान नहीं करते. फ़ंक्शन के अंदर return ऑप से अनुमान लगाया जाता है).

इनपुट फ़ंक्शन के सिंटैक्स में अभी इस्तेमाल न किया गया एक हिस्सा शामिल है (देखें Unused प्रोडक्शन, जो कि एमएलआईआर के साथ काम करने के लिए उपलब्ध है. MLIR में, "क्षेत्र" एक सामान्य कॉन्सेप्ट है, जिसे जिसमें एक से ज़्यादा "ब्लॉक" हो सकते हैं जंप ऑपरेशन के ज़रिए एक साथ जुड़े ऑपरेटर हैं. इन ब्लॉक में ऐसे आईडी हैं जो इससे जुड़े हैं Unused प्रोडक्शन में ऐसा किया गया हो, ताकि वे एक-दूसरे से अलग दिखें. StableHLO में जंप ops नहीं है, इसलिए MLIR सिंटैक्स का संबंधित हिस्सा यह है इस्तेमाल नहीं किया गया है (लेकिन अब भी मौजूद है).

OpInputAttr      ::= OpInputAttrName '=' OpInputAttrValue
OpInputAttrName  ::= letter {letter | digit}
OpInputAttrValue ::= Constant

इनपुट एट्रिब्यूट का एक नाम और एक वैल्यू होती है, जो इस्तेमाल की जा सकने वाली एट्रिब्यूट में से एक है स्थिरांक. ये प्रोग्राम के लिए स्टैटिक मेटाडेटा तय करने का मुख्य तरीका हैं एलिमेंट. उदाहरण के लिए, concatenate op, dimension एट्रिब्यूट का इस्तेमाल इन कामों के लिए करता है वह डाइमेंशन तय करना जिसके ज़रिए इसकी इनपुट वैल्यू जोड़ी गई हैं. इसी तरह, slice सेशन, start_indices और limit_indices जैसे कई एट्रिब्यूट का इस्तेमाल करता है का इस्तेमाल करें.

इस समय, जंगल में स्थित StableHLO प्रोग्राम में कभी-कभी एट्रिब्युट शामिल होते हैं जिनकी जानकारी इस दस्तावेज़ में नहीं दी गई है. आने वाले समय में, हम या तो इन एट्रिब्यूट को StableHLO ऑपसेट में सोख लें या उन्हें ऐसा करने से रोकें जो StableHLO प्रोग्राम में दिखते हैं. तब तक, यहां इन विज्ञापनों की सूची दी गई है विशेषताएं:

  • layout (#629).
  • mhlo.frontend_attributes अभी तक किसी भी व्यक्ति ने चेक इन नहीं किया है (#628).
  • mhlo.sharding (#619).
  • output_operand_aliases अभी तक किसी भी व्यक्ति ने चेक इन नहीं किया है (#740).
  • जगह की जानकारी का मेटाडेटा (#594).
OpSignature ::= '(' [ValueType {',' ValueType}] ')' '->' '(' [ValueType {',' ValueType}] ')'

ऑप हस्ताक्षर में सभी इनपुट वैल्यू के टाइप शामिल होते हैं. जैसे, -> की बाईं ओर) और सभी आउटपुट वैल्यू के टाइप (सूची प्रकार -> के दाईं ओर). सच में, इनपुट के टाइप अनावश्यक और आउटपुट प्रकार लगभग हमेशा अनावश्यक होते हैं (क्योंकि ज़्यादातर StableHLO ऑपरेशन, आउटपुट टाइप का अनुमान इनपुट से लगाया जा सकता है). फिर भी, ऑप हस्ताक्षर जान-बूझकर StableHLO सिंटैक्स का हिस्सा है, ताकि MLIR के साथ काम किया जा सके.

नीचे एक ऑप का उदाहरण दिया गया है जिसका स्मरणिक select_and_scatter है. यह तीन की खपत करता है इनपुट वैल्यू (%operand, %source, और %init_value), दो इनपुट फ़ंक्शन और तीन इनपुट एट्रिब्यूट (window_dimensions, window_strides, और padding). ध्यान दें कि ऑपरेशन के सिग्नेचर में, इनपुट वैल्यू के टाइप ही कैसे शामिल होते हैं (इसमें इनलाइन दिए जाने वाले इनपुट फ़ंक्शन और एट्रिब्यूट के टाइप नहीं होते).

%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>

स्थिरांक

Constant ::= BooleanConstant
           | IntegerConstant
           | FloatConstant
           | ComplexConstant
           | TensorConstant
           | QuantizedTensorConstant
           | StringConstant
           | EnumConstant

StableHLO कॉन्सटेंट में, लिटरल और एक टाइप होता है, जो एक साथ एक StableHLO वैल्यू. आम तौर पर, टाइप कॉन्सटैंट सिंटैक्स का हिस्सा होता है. हालांकि, इसमें शामिल नहीं यह साफ़ तौर पर बताया जाता है (उदाहरण के लिए, किसी बूलियन कॉन्सटेंट में टाइप i1 होता है, जबकि पूर्णांक कॉन्सटेंट के कई संभावित टाइप हो सकते हैं).

BooleanConstant ::= BooleanLiteral
BooleanLiteral  ::= 'true' | 'false'

बूलियन कॉन्सटेंट, बूलियन वैल्यू true और false को दिखाते हैं. बूलियन कॉन्सटेंट का टाइप i1 होता है.

IntegerConstant   ::= IntegerLiteral ':' IntegerType
IntegerLiteral    ::= ['-' | '+'] DecimalDigits
                    | ['-' | '+'] '0x' HexadecimalDigits
DecimalDigits     ::= decimalDigit {decimalDigit}
HexadecimalDigits ::= hexadecimalDigit {hexadecimalDigit}
decimalDigit      ::= '0' | ... | '9'
hexadecimalDigit  ::= decimalDigit | 'a' | ... | 'f' | 'A' | ... | 'F'

इंटिजर कॉन्सटेंट, पूर्णांक वैल्यू को उन स्ट्रिंग के ज़रिए दिखाते हैं जिनमें दशमलव या हेक्साडेसिमल नोटेशन. अन्य आधार, जैसे कि बाइनरी या ऑक्टल का इस्तेमाल नहीं किया जा सकता. पूर्णांक कॉन्सटेंट में ये कंस्ट्रेंट होते हैं:

  • (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]

फ़्लोटिंग-पॉइंट कॉन्सटेंट ऐसी स्ट्रिंग के ज़रिए फ़्लोटिंग-पॉइंट वैल्यू दिखाते हैं दशमलव या वैज्ञानिक संकेतन का इस्तेमाल करें. इसके अलावा, हेक्साडेसिमल नोटेशन इसका इस्तेमाल फ़्लोटिंग-पॉइंट फ़ॉर्मैट में सीधे तौर पर बिट को तय करने के लिए किया जाता है संबंधित प्रकार. फ़्लोटिंग-पॉइंट कॉन्सटेंट में ये कंस्ट्रेंट होते हैं:

  • (C1) अगर नॉन-हेक्साडेसिमल नोटेशन का इस्तेमाल किया जाता है, is_wellformed(float_literal, float_type).
  • (C2) अगर हेक्साडेसिमल नोटेशन का इस्तेमाल किया जाता है, size(hexadecimal_digits) = num_bits(float_type) / 4.
ComplexConstant ::= ComplexLiteral ':' ComplexType
ComplexLiteral  ::= '(' RealPart ',' ImaginaryPart ')'
RealPart        ::= FloatLiteral
ImaginaryPart   ::= FloatLiteral

जटिल स्थिरांक वास्तविक भाग की सूचियों का इस्तेमाल करके जटिल मान दिखाते हैं (पहले आता है) और एक काल्पनिक हिस्सा (दूसरा आता है). उदाहरण के लिए, (1.0, 0.0) : complex<f32>, 1.0 + 0.0i का प्रतिनिधित्व करता है और (0.0, 1.0) : complex<f32>, 0.0 + 1.0i का प्रतिनिधित्व करता है. जिस क्रम में ये हिस्सों को मेमोरी में स्टोर किया जाता है. इसे लागू करने के लिए तय किया जाता है. कॉम्प्लेक्स कॉन्सटेंट कॉन्टेंट पर ये सीमाएं लागू होती हैं:

  • (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

टेन्सर कॉन्सटेंट, नेस्ट की गई सूचियों का इस्तेमाल करके टेंसर वैल्यू दिखाते हैं NumPy नोटेशन. उदाहरण के लिए, dense<[[1, 2, 3], [4, 5, 6]]> : tensor<2x3xi32> इंडेक्स से एलिमेंट तक इस तरह की मैपिंग की मदद से, टेंसर वैल्यू दिखाता है: {0, 0} => 1, {0, 1} => 2, {0, 2} => 3, {1, 0} => 4, {1, 1} => 5, {1, 2} => 6. इसके बाद, इन एलिमेंट को मेमोरी में सेव करने का क्रम यह होता है लागू किया जाना चाहिए. टेन्सर कॉन्सटेंट में ये कंस्ट्रेंट होते हैं:

  • (C1) has_syntax(tensor_literal, element_type(tensor_type)), जहां:
    • 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)), जहां:
    • 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:]).
    • अगर ऐसा नहीं है, तो false.
QuantizedTensorConstant ::= QuantizedTensorLiteral ':' QuantizedTensorType
QuantizedTensorLiteral  ::= 'dense' '<' (DenseLiteral | ElementLiteral) '>'

क्वांटाइज़्ड टेंसर कॉन्सटेंट क्वांटाइज़्ड टेंसर वैल्यू को दिखाता है. इसके लिए, नोटेशन, टेंसर कॉन्सटेंट के तौर पर होता है. इसमें एलिमेंट के कॉन्सटेंट के तौर पर स्टोरेज टाइप. क्वांटाइज़्ड टेंसर कॉन्सटेंट में ये कंस्ट्रेंट होते हैं:

  • (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))

स्ट्रिंग की लिटरल वैल्यू में ऐसे बाइट होते हैं जिन्हें ASCII वर्णों का इस्तेमाल करके तय किया जाता है और एस्केप सीक्वेंस. ये कोड में बदलने के तरीके (एन्कोडिंग-एग्नोस्टिक) हैं. इसलिए, इन बाइट लागू करने के लिए तय की जाती है. स्ट्रिंग की लिटरल वैल्यू का टाइप string है.

ऑपरेशन

कुल

सिमैंटिक

operand टेंसर पर एलिमेंट के हिसाब से abs ऑपरेशन करता है और result जनरेट करता है टेंसर. एलिमेंट टाइप के आधार पर, ये काम किए जाते हैं:

  • हस्ताक्षर किए गए पूर्णांकों के लिए: पूर्णांक मॉड्यूल.
  • फ़्लोट के लिए: IEEE-754 से abs.
  • सम्मिश्र संख्याओं के लिए: जटिल मापांक.
  • क्वांटाइज़्ड टाइप के लिए: dequantize_op_quantize(abs, operand, type(result)).

इनपुट

लेबल नाम टाइप कंस्ट्रेंट
(I1) operand साइन किए हुए पूर्णांक, फ़्लोटिंग-पॉइंट या कॉम्प्लेक्स टाइप या हर टेंसर क्वांटाइज़्ड टेंसर का टेंसर (सी1-सी2)

आउटपुट

नाम टाइप कंस्ट्रेंट
result साइन किए गए पूर्णांक या फ़्लोटिंग-पॉइंट टाइप या हर टेंसर क्वांटाइज़्ड टेंसर का टेंसर (सी1-सी2)

कंस्ट्रेंट

  • (C1) shape(result) = shape(operand).
  • (C2) baseline_element_type(result) को इस तरह परिभाषित किया गया है:
    • अगर is_complex(operand) है, तो complex_element_type(element_type(operand)).
    • अगर ऐसा नहीं है, तो baseline_element_type(operand).

उदाहरण

// %operand: [-2, 0, 2]
%result = "stablehlo.abs"(%operand) : (tensor<3xi32>) -> tensor<3xi32>
// %result: [2, 0, 2]

ज़्यादा उदाहरण

जोड़ें

सिमैंटिक

दो टेंसर lhs और rhs को एलिमेंट के हिसाब से जोड़ता है और इससे result टेंसर. एलिमेंट टाइप के आधार पर, ये काम किए जाते हैं:

  • बूलियन के लिए: लॉजिकल OR.
  • पूर्णांकों के लिए: पूर्णांक को जोड़ना.
  • फ़्लोट के लिए: IEEE-754 से addition.
  • सम्मिश्र संख्याओं के लिए: सम्मिश्र जोड़.
  • क्वांटाइज़्ड टाइप के लिए: dequantize_op_quantize(add, lhs, rhs, type(result)).

इनपुट

लेबल नाम टाइप कंस्ट्रेंट
(I1) lhs टेंसर या क्वांटाइज़्ड टेंसर (सी1-सी6)
(I2) rhs टेंसर या क्वांटाइज़्ड टेंसर (C1-C5), (C7)

आउटपुट

नाम टाइप कंस्ट्रेंट
result टेंसर या क्वांटाइज़्ड टेंसर (C1-C7)

कंस्ट्रेंट

  • अगर इस संक्रिया में गैर-संख्यात्मक टेंसर का इस्तेमाल किया गया है, तो:
    • (C1) type(lhs) = type(rhs) = type(result).
  • अगर इस संक्रिया में क्वांटाइज़्ड टेंसर का इस्तेमाल किया जाता है:
    • (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) है, तो quantization_dimension(lhs) = quantization_dimension(result).
    • (C7) अगर is_per_axis_quantized(rhs) है, तो quantization_dimension(rhs) = quantization_dimension(result).

उदाहरण

// %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

सिमैंटिक

यह पक्का करता है कि inputs को बनाने वाली कार्रवाइयां, किसी भी जो result पर निर्भर करती हैं. इस कार्रवाई को चलाने से कुछ नहीं होता है, यह सिर्फ़ result से inputs तक के डेटा पर निर्भरता सेट करने के लिए मौजूद है.

इनपुट

लेबल नाम टाइप
(I1) inputs token की वैरायडिक संख्या

आउटपुट

नाम टाइप
result token

उदाहरण

// %input0: !stablehlo.token
// %input1: !stablehlo.token
%result = "stablehlo.after_all"(%input0, %input1) : (!stablehlo.token, !stablehlo.token) -> !stablehlo.token

ज़्यादा उदाहरण

all_gather

सिमैंटिक

StableHLO प्रोसेस ग्रिड में हर प्रोसेस ग्रुप के अंदर, वैल्यू को जोड़ता है all_gather_dim की हर प्रोसेस से, operands टेंसर का बनाया जाता है और इस तरह से बनाया जाता है results टेंसर.

ऑपरेशन, StableHLO प्रोसेस ग्रिड को process_groups में बांट देता है जो कि इस तरह परिभाषित किया गया है:

  • cross_replica(replica_groups) अभी तक किसी भी व्यक्ति ने चेक इन नहीं किया है अगर channel_id <= 0 and use_global_device_ids = false है.
  • cross_replica_and_partition(replica_groups) अभी तक किसी भी व्यक्ति ने चेक इन नहीं किया है अगर channel_id > 0 and use_global_device_ids = false है.
  • flattened_ids(replica_groups) अभी तक किसी भी व्यक्ति ने चेक इन नहीं किया है अगर channel_id > 0 and use_global_device_ids = true है.

इसके बाद, हर process_group में:

  • सभी के लिए operands...@receiver = [operand@sender for sender in process_group] process_group में receiver.
  • सभी के लिए results...@process = concatenate(operands...@process, all_gather_dim) process_group में process.

इनपुट

लेबल नाम टाइप कंस्ट्रेंट
(I1) operands टेंसर की वैरायडिक संख्या या हर टेंसर की क्वांटाइज़्ड टेंसर की संख्या (C1), (C6)
(I2) all_gather_dim si64 टाइप का कॉन्स्टेंट (C1), (C6)
(I3) replica_groups si64 टाइप का 2-डाइमेंशन टेंसर कॉन्सटेंट (सी2-सी4)
(आई4) channel_id si64 टाइप का कॉन्स्टेंट (सी5)
(I5) use_global_device_ids i1 टाइप का कॉन्स्टेंट (सी5)

आउटपुट

नाम टाइप कंस्ट्रेंट
results टेंसर की वैरायडिक संख्या या हर टेंसर की क्वांटाइज़्ड टेंसर की संख्या (सी6)

कंस्ट्रेंट

  • (C1) 0 <= all_gather_dim < rank(operands...).
  • (C2) is_unique(replica_groups).
  • (C3) size(replica_groups) को इस तरह परिभाषित किया गया है:
    • अगर cross_replica का इस्तेमाल किया जाता है, तो num_replicas.
    • अगर cross_replica_and_partition का इस्तेमाल किया जाता है, तो num_replicas.
    • अगर flattened_ids का इस्तेमाल किया जाता है, तो num_processes.
  • (C4) 0 <= replica_groups < size(replica_groups).
  • (C5) अगर use_global_device_ids = true है, तो channel_id > 0.
  • (C6) type(results...) = type(operands...) को छोड़कर:
    • dim(results..., all_gather_dim) = dim(operands..., all_gather_dim) * dim(process_groups, 1).

उदाहरण

// 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

सिमैंटिक

StableHLO प्रोसेस ग्रिड में हर प्रोसेस ग्रुप के अंदर, एक रिडक्शन लागू होता है हर प्रोसेस के लिए, operands टेंसर की वैल्यू के लिए computation फ़ंक्शन और results टेंसर बनाता है.

ऑपरेशन, StableHLO प्रोसेस ग्रिड को process_groups में बांट देता है जो कि इस तरह परिभाषित किया गया है:

  • cross_replica(replica_groups) अभी तक किसी भी व्यक्ति ने चेक इन नहीं किया है अगर channel_id <= 0 and use_global_device_ids = false है.
  • cross_replica_and_partition(replica_groups) अभी तक किसी भी व्यक्ति ने चेक इन नहीं किया है अगर channel_id > 0 and use_global_device_ids = false है.
  • flattened_ids(replica_groups) अभी तक किसी भी व्यक्ति ने चेक इन नहीं किया है अगर channel_id > 0 and use_global_device_ids = true है.

इसके बाद, हर process_group में:

  • कुछ बाइनरी ट्री के लिए results...@process[result_index] = exec(schedule) schedule कहां:
    • exec(node) = computation(exec(node.left), exec(node.right)).
    • exec(leaf) = leaf.value.
  • schedule लागू करने के बारे में तय किया गया बाइनरी ट्री है, जिसका क्रम में है ट्रैवर्सल to_destination_type(operands...@process_group...[result_index], type(func_inputs(computation)[0])) है.

इनपुट

लेबल नाम टाइप कंस्ट्रेंट
(I1) operands टेंसर की वैरायडिक संख्या या हर टेंसर की क्वांटाइज़्ड टेंसर की संख्या (C5), (C6)
(I2) replica_groups si64 टाइप के 1-डाइमेंशन वाले टेंसर कॉन्सटेंट की वैरायडिक संख्या (सी1-सी3)
(I3) channel_id si64 टाइप का कॉन्स्टेंट (सी4)
(आई4) use_global_device_ids i1 टाइप का कॉन्स्टेंट (सी4)
(I5) computation फ़ंक्शन (सी5)

आउटपुट

नाम टाइप कंस्ट्रेंट
results टेंसर की वैरायडिक संख्या या हर टेंसर की क्वांटाइज़्ड टेंसर की संख्या (C6-C7)

कंस्ट्रेंट

  • (C1) is_unique(replica_groups).
  • (C2) size(replica_groups) को इस तरह परिभाषित किया गया है:
    • अगर cross_replica का इस्तेमाल किया जाता है, तो num_replicas.
    • अगर cross_replica_and_partition का इस्तेमाल किया जाता है, तो num_replicas.
    • अगर flattened_ids का इस्तेमाल किया जाता है, तो num_processes.
  • (C3) 0 <= replica_groups < size(replica_groups).
  • (C4) अगर use_global_device_ids = true है, तो channel_id > 0.
  • (C5) computation का टाइप (tensor<E>, tensor<E>) -> (tensor<E>) है, जहां is_promotable(element_type(operand), E).
  • (C6) shape(results...) = shape(operands...).
  • (C7) element_type(results...) = E.

उदाहरण

// 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

सिमैंटिक

all_to_all

StableHLO प्रोसेस ग्रिड में मौजूद प्रोसेस ग्रुप के हर एक प्रोसेस ग्रुप में, split_dimension के साथ-साथ operands टेंसर को अलग-अलग हिस्सों में बांटता है प्रक्रियाओं के बीच के हिस्से, बिखरे हुए हिस्सों को साथ-साथ जोड़ता है concat_dimension और results टेंसर बनाता है. ऑपरेशन, StableHLO प्रोसेस ग्रिड को process_groups में बांट देता है जो कि इस तरह परिभाषित किया गया है:

  • अगर channel_id <= 0 है, तो cross_replica(replica_groups).
  • अगर channel_id > 0 है, तो cross_partition(replica_groups).

इसके बाद, हर process_group में:

  • split_parts...@sender = split(operands...@sender, split_count, split_dimension) अभी तक किसी भी व्यक्ति ने चेक इन नहीं किया है process_group के सभी sender के लिए.
  • scattered_parts...@receiver = [split_parts...@sender[receiver_index] for sender in process_group] जहां receiver_index = process_group.index(receiver).
  • results...@process = concatenate(scattered_parts...@process, concat_dimension).

इनपुट

लेबल नाम टाइप कंस्ट्रेंट
(I1) operands टेंसर की वैरायडिक संख्या या हर टेंसर की क्वांटाइज़्ड टेंसर की संख्या (C1-C3), (C9)
(I2) split_dimension si64 टाइप का कॉन्स्टेंट (C1), (C2), (C9)
(I3) concat_dimension si64 टाइप का कॉन्स्टेंट (C3), (C9)
(आई4) split_count si64 टाइप का कॉन्स्टेंट (C2), (C4), (C8), (C9)
(I5) replica_groups si64 टाइप का 2-डाइमेंशन टेंसर कॉन्सटेंट (C5-C8)
(I6) channel_id si64 टाइप का कॉन्स्टेंट

आउटपुट

नाम टाइप कंस्ट्रेंट
results टेंसर की वैरायडिक संख्या या हर टेंसर की क्वांटाइज़्ड टेंसर की संख्या (सी9)

कंस्ट्रेंट

  • (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) को इस तरह परिभाषित किया गया है:
    • अगर cross_replica का इस्तेमाल किया जाता है, तो num_replicas.
    • अगर cross_partition का इस्तेमाल किया जाता है, तो num_partitions.
  • (C7) 0 <= replica_groups < size(replica_groups).
  • (C8) dim(replica_groups, 1) = split_count.
  • (C9) type(results...) = type(operands...), अगर split_dimension != concat_dimension:
    • dim(results..., split_dimension) = dim(operands..., split_dimension) / split_count.
    • dim(results..., concat_dimension) = dim(operands..., concat_dimension) * split_count.

उदाहरण

// 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]]

ज़्यादा उदाहरण

और

सिमैंटिक

दो टेंसर lhs और rhs के एलिमेंट के हिसाब से AND फ़ंक्शन करता है और result देता है टेंसर. एलिमेंट टाइप के आधार पर, ये काम किए जाते हैं:

  • बूलियन के लिए: लॉजिकल AND.
  • पूर्णांकों के लिए: बिट के अनुसार AND.

इनपुट

लेबल नाम टाइप कंस्ट्रेंट
(I1) lhs बूलियन या पूर्णांक टाइप का टेंसर (सी1)
(I2) rhs बूलियन या पूर्णांक टाइप का टेंसर (सी1)

आउटपुट

नाम टाइप कंस्ट्रेंट
result बूलियन या पूर्णांक टाइप का टेंसर (सी1)

कंस्ट्रेंट

  • (C1) type(lhs) = type(rhs) = type(result).

उदाहरण

// %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

सिमैंटिक

lhs और rhs टेंसर पर एलिमेंट के हिसाब से atan2 ऑपरेशन करता है और इससे result टेंसर. एलिमेंट टाइप के आधार पर, ये काम किए जाते हैं:

  • फ़्लोट के लिए: IEEE-754 से atan2.
  • कॉम्प्लेक्स नंबर के लिए: कॉम्प्लेक्स atan2.
  • क्वांटाइज़्ड टाइप के लिए: dequantize_op_quantize(atan2, lhs, rhs, type(result)).

इनपुट

लेबल नाम टाइप कंस्ट्रेंट
(I1) lhs फ़्लोटिंग-पॉइंट या कॉम्प्लेक्स टाइप या हर टेंसर क्वांटाइज़्ड टेंसर का टेंसर (सी1)
(I2) rhs फ़्लोटिंग-पॉइंट या कॉम्प्लेक्स टाइप या हर टेंसर क्वांटाइज़्ड टेंसर का टेंसर (सी1)

आउटपुट

नाम टाइप कंस्ट्रेंट
result फ़्लोटिंग-पॉइंट या कॉम्प्लेक्स टाइप या हर टेंसर क्वांटाइज़्ड टेंसर का टेंसर (सी1)

कंस्ट्रेंट

  • (C1) baseline_type(lhs) = baseline_type(rhs) = baseline_type(result).

उदाहरण

// %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

सिमैंटिक

batch_norm_training बैकप्रोपागेटिंग के कई इनपुट के ग्रेडिएंट को कैलकुलेट करता है grad_output से, grad_operand, grad_scale, और grad_offset का प्रोडक्शन होता है टेंसर. ज़्यादा औपचारिक रूप से, इस ऑपरेशन को अपघटन के रूप में दिखाया जा सकता है Python सिंटैक्स का इस्तेमाल करने वाले मौजूदा StableHLO ऑपरेशन का उदाहरण नीचे दिया गया है:

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

क्वांटाइज़्ड टाइप के लिए, 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)).

इनपुट

लेबल नाम टाइप कंस्ट्रेंट
(I1) operand फ़्लोटिंग-पॉइंट टाइप या हर टेंसर क्वांटाइज़्ड टेंसर का टेंसर (C1-C3), (C5)
(I2) scale फ़्लोटिंग-पॉइंट या हर टेंसर की क्वांटाइज़्ड टाइप का 1-डाइमेंशन टेंसर (C2), (C4), (C5)
(I3) mean फ़्लोटिंग-पॉइंट या हर टेंसर की क्वांटाइज़्ड टाइप का 1-डाइमेंशन टेंसर (C2), (C4)
(आई4) variance फ़्लोटिंग-पॉइंट या हर टेंसर की क्वांटाइज़्ड टाइप का 1-डाइमेंशन टेंसर (C2), (C4)
(I5) grad_output फ़्लोटिंग-पॉइंट टाइप या हर टेंसर क्वांटाइज़्ड टेंसर का टेंसर (C2), (C3)
(I6) epsilon f32 टाइप का कॉन्स्टेंट
(I7) feature_index si64 टाइप का कॉन्स्टेंट (C1), (C5)

आउटपुट

नाम टाइप कंस्ट्रेंट
grad_operand फ़्लोटिंग-पॉइंट टाइप या हर टेंसर क्वांटाइज़्ड टेंसर का टेंसर (C2), (C3)
grad_scale फ़्लोटिंग-पॉइंट या हर टेंसर की क्वांटाइज़्ड टाइप का 1-डाइमेंशन टेंसर (C2), (C4)
grad_offset फ़्लोटिंग-पॉइंट या हर टेंसर की क्वांटाइज़्ड टाइप का 1-डाइमेंशन टेंसर (C2), (C4)

कंस्ट्रेंट

  • (C1) 0 <= feature_index < rank(operand).
  • (C2) operand, scale, mean, variance, grad_output, grad_operand, grad_scale और grad_offset का baseline_element_type एक जैसा है.
  • (C3) operand, grad_output, और grad_operand का आकार एक जैसा है.
  • (C4) scale, mean, variance, grad_scale, और grad_offset के पास एक ही आकार में.
  • (C5) size(scale) = dim(operand, feature_index).

उदाहरण

// %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

सिमैंटिक

इसे छोड़कर सभी डाइमेंशन में operand टेंसर को नॉर्मलाइज़ करता है feature_index डाइमेंशन बनाता है और result टेंसर बनाता है. औपचारिक तौर पर, यह ऑपरेशन को मौजूदा StableHLO ऑपरेशन के डिकंपोज़िशन के तौर पर दिखाया जा सकता है Python सिंटैक्स का इस्तेमाल इस तरह से करता है:

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)

क्वांटाइज़्ड टाइप के लिए, 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)).

इनपुट

लेबल नाम टाइप कंस्ट्रेंट
(I1) operand फ़्लोटिंग-पॉइंट टाइप या हर टेंसर क्वांटाइज़्ड टेंसर का टेंसर (C1-C7)
(I2) scale फ़्लोटिंग-पॉइंट या हर टेंसर की क्वांटाइज़्ड टाइप का 1-डाइमेंशन टेंसर (C2), (C3)
(I3) offset फ़्लोटिंग-पॉइंट या हर टेंसर की क्वांटाइज़्ड टाइप का 1-डाइमेंशन टेंसर (C2), (C4)
(आई4) mean फ़्लोटिंग-पॉइंट या हर टेंसर की क्वांटाइज़्ड टाइप का 1-डाइमेंशन टेंसर (सी5)
(I5) variance फ़्लोटिंग-पॉइंट या हर टेंसर की क्वांटाइज़्ड टाइप का 1-डाइमेंशन टेंसर (C2), (C6)
(I6) epsilon f32 टाइप का कॉन्स्टेंट
(I7) feature_index si64 टाइप का कॉन्स्टेंट (C1), (C3-C6)

आउटपुट

नाम टाइप कंस्ट्रेंट
result फ़्लोटिंग-पॉइंट टाइप या हर टेंसर क्वांटाइज़्ड टेंसर का टेंसर (C2), (C7)

कंस्ट्रेंट

  • (C1) 0 <= feature_index < rank(operand).
  • (C2) operand, scale, offset, mean, variance, और result के पास वही 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).

उदाहरण

// %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

सिमैंटिक

feature_index को छोड़कर सभी डाइमेंशन में मीन और वैरियंस कैलकुलेट करता है डाइमेंशन और operand टेंसर को नॉर्मलाइज़ करता है, जिससे output, batch_mean बनता है और batch_var टेंसर. ज़्यादा औपचारिक रूप से, इस ऑपरेशन को Python सिंटैक्स का इस्तेमाल करके, मौजूदा StableHLO ऑपरेशन को डीकंपोज़ करना अनुसरण करता है:

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

क्वांटाइज़्ड टाइप के लिए, 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)).

इनपुट

लेबल नाम टाइप कंस्ट्रेंट
(I1) operand फ़्लोटिंग-पॉइंट टाइप या हर टेंसर क्वांटाइज़्ड टेंसर का टेंसर (सी1)
(I2) scale फ़्लोटिंग-पॉइंट या हर टेंसर की क्वांटाइज़्ड का 1-डाइमेंशन टेंसर (C2), (C3)
(I3) offset फ़्लोटिंग-पॉइंट या हर टेंसर की क्वांटाइज़्ड का 1-डाइमेंशन टेंसर (C2), (C4)
(आई4) epsilon f32 टाइप का कॉन्स्टेंट (C1), (C3-C6)
(I5) feature_index si64 टाइप का कॉन्स्टेंट (C1), (C3-C6)

आउटपुट

नाम टाइप कंस्ट्रेंट
output फ़्लोटिंग-पॉइंट टाइप या हर टेंसर क्वांटाइज़्ड टेंसर का टेंसर (सी7)
batch_mean फ़्लोटिंग-पॉइंट या हर टेंसर की क्वांटाइज़्ड का 1-डाइमेंशन टेंसर (C2), (C5)
batch_var फ़्लोटिंग-पॉइंट या हर टेंसर की क्वांटाइज़्ड का 1-डाइमेंशन टेंसर (C2), (C6)

कंस्ट्रेंट

  • (C1) 0 <= feature_index < rank(operand).
  • (C2) operand, scale, offset, batch_mean, batch_var, और output के पास वही 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).

उदाहरण

// %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

सिमैंटिक

operand टेंसर पर बिटकास्ट कार्रवाई करता है और result टेंसर बनाता है जहां पूरे operand टेंसर के बिट को result टेंसर का टाइप.

इन देशों में E = element_type(operand), E' = element_type(result), और R = rank(operand):

  • अगर num_bits(E') < num_bits(E), bits(result[i0, ..., iR-1, :]) = bits(operand[i0, ..., iR-1]).
  • अगर num_bits(E') > num_bits(E), bits(result[i0, ..., iR-2]) = bits(operand[i0, ..., iR-2, :]).
  • अगर num_bits(E') = num_bits(E), bits(result[i0, ..., iR-1]) = bits(operand[i0, ..., iR-1]).

bits, दी गई वैल्यू को मेमोरी में दिखाने के साथ-साथ उसके व्यवहार की जानकारी देता है को लागू करना तय होता है, क्योंकि टेंसर का सटीक निरूपण होता है लागू है, और एलिमेंट टाइप की सटीक जानकारी दी गई है तय करें.

इनपुट

लेबल नाम टाइप कंस्ट्रेंट
(I1) operand टेंसर या क्वांटाइज़्ड टेंसर (सी1-सी2)

आउटपुट

नाम टाइप कंस्ट्रेंट
result टेंसर या क्वांटाइज़्ड टेंसर (सी1-सी2)

कंस्ट्रेंट

  • (C1) E = is_quantized(operand) ? storage_type(operand) : element_type(operand), E' = is_quantized(result) ? storage_type(result) : element_type(result), और R = rank(operand) दिए गए:
    • अगर num_bits(E') = num_bits(E), तो shape(result) = shape(operand).
    • अगर num_bits(E') < num_bits(E):
    • rank(result) = R + 1.
    • सभी 0 <= i < R के लिए dim(result, i) = dim(operand, i).
    • dim(result, R) * num_bits(E') = num_bits(E).
    • अगर num_bits(E') > num_bits(E):
    • rank(result) = R - 1.
    • सभी 0 <= i < R के लिए dim(result, i) = dim(operand, i).
    • dim(operand, R - 1) * num_bits(E) = num_bits(E').
  • (C2) अगर is_complex(operand) or is_complex(result) है, तो is_complex(operand) and is_complex(result).

उदाहरण

// %operand: 0x0123456789ABCDEF
%result = "stablehlo.bitcast_convert"(%operand) : (tensor<f64>) -> tensor<4xf16>
// %result: [0xCDEF, 0x89AB, 0x4567, 0x0123] // little-endian representation

ज़्यादा उदाहरण

broadcast_in_dim

सिमैंटिक

डेटा की डुप्लीकेट कॉपी बनाकर, इनपुट टेंसर के डाइमेंशन और/या रैंक को बढ़ाता है यह operand टेंसर में होता है और result टेंसर बनाता है. औपचारिक तौर पर, result[result_index] = operand[operand_index] में सभी d कहां देखें axes(operand):

  • अगर dim(operand, d) = 1 है, तो operand_index[d] = 0.
  • अगर ऐसा नहीं है, तो operand_index[d] = result_index[broadcast_dimensions[d]].

इनपुट

लेबल नाम टाइप कंस्ट्रेंट
(I1) operand टेंसर या क्वांटाइज़्ड टेंसर (C1-C2), (C5-C6)
(I2) broadcast_dimensions si64 टाइप का 1-डाइमेंशन टेंसर कॉन्सटेंट (सी2-सी6)

आउटपुट

नाम टाइप कंस्ट्रेंट
result टेंसर या क्वांटाइज़्ड टेंसर (C1), (C3), (C5-C6)

कंस्ट्रेंट

  • (C1) element_type(result) देने वाली कंपनी:
    • अगर !is_per_axis_quantized(operand) है, तो element_type(operand).
    • quantization_dimension(operand) को छोड़कर, element_type(operand), scales(operand) और zero_points(operand) इनसे अलग हो सकती हैं quantization_dimension(result), scales(result), और zero_points(result) नहीं करना होगा.
  • (C2) size(broadcast_dimensions) = rank(operand).
  • (C3) 0 <= broadcast_dimensions < rank(result).
  • (C4) is_unique(broadcast_dimensions).
  • (C5) axes(operand) में सभी d के लिए:
    • dim(operand, d) = 1 या
    • dim(operand, d) = dim(result, broadcast_dimensions[d]).
  • (C6) अगर is_per_axis_quantized(result):
    • quantization_dimension(result) = broadcast_dimensions[quantization_dimension(operand)].
    • अगर dim(operand, quantization_dimension(operand)) = 1, तो scales(result)[i] = scales(operand)[0] and zero_points(result)[i] = zero_points(operand)[0] for i in range(dim(result, quantization_dimension(result))).

उदाहरण

// %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]
//            ]
//          ]

ज़्यादा उदाहरण

केस

सिमैंटिक

branches से सिर्फ़ एक फ़ंक्शन चलाने पर आउटपुट मिलता है यह index की वैल्यू के हिसाब से तय होता है. औपचारिक तौर पर, result = selected_branch() कहां:

  • अगर 0 <= index < size(branches) है, तो selected_branch = branches[index].
  • अगर ऐसा नहीं है, तो selected_branch = branches[-1].

इनपुट

लेबल नाम टाइप कंस्ट्रेंट
(I1) index si32 टाइप का 0-डाइमेंशन वाला टेंसर
(I2) branches फ़ंक्शन की वैरायडिक नंबर (सी1-सी4)

आउटपुट

नाम टाइप कंस्ट्रेंट
results टेंसर की वैरायडिक संख्या, क्वांटाइज़ किए गए टेंसर या टोकन (सी4)

कंस्ट्रेंट

  • (C1) 0 < size(branches).
  • (C2) input_types(branches...) = [].
  • (C3) same(output_types(branches...)).
  • (C4) type(results...) = output_types(branches[0]).

उदाहरण

// %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]

ज़्यादा उदाहरण

सीबीआरटी

सिमैंटिक

operand टेंसर पर एलिमेंट के मुताबिक घन मूल की कार्रवाई करता है और इससे result टेंसर. एलिमेंट टाइप के आधार पर, ये काम किए जाते हैं:

  • फ़्लोट के लिए: IEEE-754 से rootn(x, 3).
  • सम्मिश्र संख्याओं के लिए: सम्मिश्र घन मूल.
  • क्वांटिफ़ाइड टाइप के लिए: dequantize_op_quantize(cbrt, operand, type(result))

इनपुट

लेबल नाम टाइप कंस्ट्रेंट
(I1) operand फ़्लोटिंग-पॉइंट या कॉम्प्लेक्स टाइप या हर टेंसर क्वांटाइज़्ड टेंसर का टेंसर (सी1)

आउटपुट

नाम टाइप कंस्ट्रेंट
result फ़्लोटिंग-पॉइंट या कॉम्प्लेक्स टाइप या हर टेंसर क्वांटाइज़्ड टेंसर का टेंसर (सी1)

कंस्ट्रेंट

  • (C1) baseline_type(operand) = baseline_type(result).

उदाहरण

// %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]

ज़्यादा उदाहरण

सील

सिमैंटिक

operand टेंसर की एलिमेंट के हिसाब से सेल करता है और result टेंसर बनाता है. आईईईई-754 से roundToIntegralTowardPositive ऑपरेशन लागू करता है स्पेसिफ़िकेशन. क्वांटाइज़्ड टाइप के लिए, dequantize_op_quantize(ceil, operand, type(result)).

इनपुट

लेबल नाम टाइप कंस्ट्रेंट
(I1) operand फ़्लोटिंग-पॉइंट टाइप या हर टेंसर क्वांटाइज़्ड टेंसर का टेंसर (सी1)

आउटपुट

नाम टाइप कंस्ट्रेंट
result फ़्लोटिंग-पॉइंट टाइप या हर टेंसर क्वांटाइज़्ड टेंसर का टेंसर (सी1)

कंस्ट्रेंट

  • (C1) baseline_type(operand) = baseline_type(result).

उदाहरण

// %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]

ज़्यादा उदाहरण

चोलस्की

सिमैंटिक

मैट्रिक्स के बैच के कोलेस्की अपघटन की गणना करता है.

ज़्यादा औपचारिक तौर पर, index_space(result) में सभी i के लिए, result[i0, ..., iR-3, :, :] इसका कोलेस्की अपघटन है a[i0, ..., iR-3, :, :], निचले त्रिभुज के फ़ॉर्मैट में (अगर lower true है) या ऊपरी त्रिभुज वाला (अगर lower false है) मैट्रिक्स. सामने वाले त्रिभुज में आउटपुट वैल्यू, जैसे कि सख्त ऊपरी त्रिभुज या इसके अनुसार सख्त निचले त्रिभुज, लागू करने के तरीके बनाए गए हैं.

अगर i मौजूद है, जहां इनपुट मैट्रिक्स हर्मिटियन सकारात्मक-निश्चित नहीं है मैट्रिक्स, तो व्यवहार तय नहीं होता है.

क्वांटाइज़्ड टाइप के लिए, dequantize_op_quantize(lambda operand: cholesky(operand, lower), a, type(result)).

इनपुट

लेबल नाम टाइप कंस्ट्रेंट
(I1) a फ़्लोटिंग-पॉइंट या कॉम्प्लेक्स टाइप या हर टेंसर क्वांटाइज़्ड टेंसर का टेंसर (सी1-सी3)
(I2) lower i1 टाइप का 0-डाइमेंशन टेंसर कॉन्सटेंट

आउटपुट

नाम टाइप कंस्ट्रेंट
result फ़्लोटिंग-पॉइंट या कॉम्प्लेक्स टाइप या हर टेंसर क्वांटाइज़्ड टेंसर का टेंसर (सी1)

कंस्ट्रेंट

  • (C1) baseline_type(a) = baseline_type(result).
  • (C2) 2 <= rank(a).
  • (C3) dim(a, -2) = dim(a, -1).

उदाहरण

// %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]
//          ]

क्लैंप

सिमैंटिक

operand टेंसर के हर एलिमेंट को कम से कम और ज़्यादा से ज़्यादा के बीच जोड़ता है वैल्यू और result टेंसर बनाता है. औपचारिक तौर पर, result[result_index] = minimum(maximum(operand[result_index], min_element), max_element), जहां min_element = rank(min) = 0 ? min[] : min[result_index], max_element = rank(max) = 0 ? max[] : max[result_index]. क्वांटाइज़्ड टाइप के लिए, dequantize_op_quantize(clamp, min, operand, max, type(result)) करता है.

जटिल संख्याओं को क्रम से लगाने में हैरान करने वाले सिमैंटिक, इसलिए, आने वाले समय में हम कॉम्प्लेक्स नंबर की सुविधा को बंद करने की योजना बना रहे हैं. इस कार्रवाई के लिए (#560).

इनपुट

लेबल नाम टाइप कंस्ट्रेंट
(I1) min टेंसर या हर टेन्सर क्वांटाइज़्ड टेंसर (C1), (C3)
(I2) operand टेंसर या हर टेन्सर क्वांटाइज़्ड टेंसर (सी1-सी4)
(I3) max टेंसर या हर टेन्सर क्वांटाइज़्ड टेंसर (C2), (C3)

आउटपुट

नाम टाइप कंस्ट्रेंट
result टेंसर या हर टेन्सर क्वांटाइज़्ड टेंसर (सी4)

कंस्ट्रेंट

  • (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).

उदाहरण

// %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

सिमैंटिक

StableHLO प्रोसेस ग्रिड में हर प्रोसेस ग्रुप के अंदर, सोर्स प्रोसेस से टारगेट प्रोसेस तक, operand टेंसर का इस्तेमाल करें और result टेंसर.

ऑपरेशन, StableHLO प्रोसेस ग्रिड को process_groups में बांट देता है जो कि इस तरह परिभाषित किया गया है:

  • अगर channel_id <= 0 है, तो cross_replica(replica_groups).
  • अगर channel_id > 0 है, तो cross_partition(replica_groups).

इसके बाद, result@process देने वाली कंपनी:

  • operand@process_groups[i, 0], अगर कोई i मौजूद हो और प्रोसेस इस तरह की हो process_groups[i] में.
  • broadcast_in_dim(constant(is_quantized(result) ? quantize(0, element_type(result)) : 0, element_type(result)), [], type(result)) अभी तक किसी भी व्यक्ति ने चेक इन नहीं किया है नहीं तो.

इनपुट

लेबल नाम टाइप कंस्ट्रेंट
(I1) operand टेंसर या हर टेन्सर क्वांटाइज़्ड टेंसर (सी3)
(I2) replica_groups si64 टाइप के 1-डाइमेंशन वाले टेंसर कॉन्सटेंट की वैरायडिक संख्या (C1), (C2)
(I3) channel_id si64 टाइप का कॉन्स्टेंट

आउटपुट

नाम टाइप कंस्ट्रेंट
result टेंसर या हर टेन्सर क्वांटाइज़्ड टेंसर (सी3)

कंस्ट्रेंट

  • (C1) is_unique(replica_groups).
  • (C2) 0 <= replica_groups < N जहां N को इस तरह परिभाषित किया गया है:
    • अगर cross_replica का इस्तेमाल किया जाता है, तो num_replicas.
    • अगर cross_partition का इस्तेमाल किया जाता है, तो num_partitions.
  • (C3) type(result) = type(operand).

उदाहरण

// 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

सिमैंटिक

StableHLO प्रोसेस ग्रिड में मौजूद हर प्रोसेस ग्रुप के तहत, सोर्स प्रोसेस से टारगेट प्रोसेस तक, operand टेंसर बनाता है और नतीजे के तौर पर result टेंसर.

ऑपरेशन, StableHLO प्रोसेस ग्रिड को process_groups में बांट देता है जो कि इस तरह परिभाषित किया गया है:

  • अगर channel_id <= 0 है, तो cross_replica(source_target_pairs).
  • अगर channel_id > 0 है, तो cross_partition(source_target_pairs).

इसके बाद, result@process देने वाली कंपनी:

  • operand@process_groups[i, 0], अगर कोई i मौजूद हो, तो process_groups[i, 1] = process.
  • broadcast_in_dim(constant(is_quantized(result) ? quantize(0, element_type(result)) : 0, element_type(result)), [], type(result)) अभी तक किसी भी व्यक्ति ने चेक इन नहीं किया है नहीं तो.

इनपुट

लेबल नाम टाइप कंस्ट्रेंट
(I1) operand टेंसर या हर टेन्सर क्वांटाइज़्ड टेंसर (सी5)
(I2) source_target_pairs si64 टाइप का 2-डाइमेंशन टेंसर कॉन्सटेंट (सी1-सी4)
(I3) channel_id si64 टाइप का कॉन्स्टेंट

आउटपुट

नाम टाइप कंस्ट्रेंट
result टेंसर या हर टेन्सर क्वांटाइज़्ड टेंसर (सी1)

कंस्ट्रेंट

  • (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, जहां N का मतलब इस तरह है:
    • अगर cross_replica का इस्तेमाल किया जाता है, तो num_replicas.
    • अगर cross_partition का इस्तेमाल किया जाता है, तो num_partitions.
  • (C5) type(result) = type(operand).

उदाहरण

// 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]]

ज़्यादा उदाहरण

तुलना करें

सिमैंटिक

lhs और rhs टेंसर की एलिमेंट के हिसाब से तुलना करता है comparison_direction और compare_type से, result टेंसर बनाता है.

comparison_direction और compare_type की वैल्यू ये हैं सिमेंटिक्स:

बूलियन और इंटीजर टाइप के एलिमेंट के लिए:

  • EQ: lhs = rhs.
  • NE: lhs != rhs.
  • GE: lhs >= rhs.
  • GT: lhs > rhs.
  • LE: lhs <= rhs.
  • LT: lhs < rhs.

compare_type = FLOAT के साथ फ़्लोटिंग-पॉइंट एलिमेंट टाइप के लिए, op- मान लागू करता है आईईईई-754 के ये ऑपरेशन:

  • EQ: compareQuietEqual.
  • NE: compareQuietNotEqual.
  • GE: compareQuietGreaterEqual.
  • GT: compareQuietGreater.
  • LE: compareQuietLessEqual.
  • LT: compareQuietLess.

compare_type = TOTALORDER वाले फ़्लोटिंग-पॉइंट एलिमेंट के लिए, op इससे totalOrder और compareQuietEqual कार्रवाइयों का कॉम्बिनेशन इस्तेमाल करता है आईईईई-754.

जटिल एलिमेंट टाइप के लिए, (real, imag) पेयर की लेक्सिकोग्राफ़िक तुलना इस तरह है दिए गए comparison_direction और compare_type का इस्तेमाल करके परफ़ॉर्म किया. जटिल संख्याओं को क्रम से लगाने में हैरान करने वाले सिमैंटिक, इसलिए, आने वाले समय में हम कॉम्प्लेक्स नंबर की सुविधा को बंद करने की योजना बना रहे हैं. जब comparison_direction, GE, GT, LE या LT हो (#560).

क्वांटाइज़्ड टाइप के लिए. dequantize_compare(lhs, rhs, comparison_direction) करता है.

इनपुट

लेबल नाम टाइप कंस्ट्रेंट
(I1) lhs टेंसर या हर टेन्सर क्वांटाइज़्ड टेंसर (सी1-सी3)
(I2) rhs टेंसर या हर टेन्सर क्वांटाइज़्ड टेंसर (सी1-सी2)
(I3) comparison_direction EQ, NE, GE, GT, LE, और LT का कुल डेटा
(आई4) compare_type FLOAT, TOTALORDER, SIGNED, और UNSIGNED का कुल डेटा (सी3)

आउटपुट

नाम टाइप कंस्ट्रेंट
result बूलियन टाइप का टेंसर (सी2)

कंस्ट्रेंट

  • (C1) baseline_element_type(lhs) = baseline_element_type(rhs).
  • (C2) shape(lhs) = shape(rhs) = shape(result).
  • (C3) compare_type को इस तरह परिभाषित किया गया है:
    • अगर is_signed_integer(element_type(lhs)) है, तो SIGNED.
    • अगर is_unsigned_integer(element_type(lhs)) or is_boolean(element_type(lhs)) है, तो UNSIGNED.
    • अगर is_float(element_type(lhs)) है, तो FLOAT या TOTALORDER.
    • अगर is_complex(element_type(lhs)) है, तो FLOAT.

उदाहरण

// %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]

ज़्यादा उदाहरण

जटिल

सिमैंटिक

वास्तविक और के पेयर से एक कॉम्प्लेक्स वैल्यू पर एलिमेंट के हिसाब से कन्वर्ज़न करता है काल्पनिक मान, lhs और rhs, और एक result टेंसर बनाता है.

इनपुट

लेबल नाम टाइप कंस्ट्रेंट
(I1) lhs f32 या f64 टाइप का टेंसर (सी1-सी3)
(I2) rhs f32 या f64 टाइप का टेंसर (सी1)

आउटपुट

नाम टाइप कंस्ट्रेंट
result कॉम्प्लेक्स टाइप का टेंसर (C2), (C3)

कंस्ट्रेंट

  • (C1) type(lhs) = type(rhs).
  • (C2) shape(result) = shape(lhs).
  • (C3) element_type(result) का टाइप complex<E> है, जहां E = element_type(lhs).

उदाहरण

// %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)]

ज़्यादा उदाहरण

मिश्रित

सिमैंटिक

अन्य StableHLO ऑपरेशन से बने ऑपरेशन को इनकैप्सुलेट करता है, इस वीडियो में, inputs और composite_attributes को लिया जा रहा है और results वीडियो बनाया जा रहा है. कॉन्टेंट बनाने ऑपरेशन के सिमैंटिक को decomposition एट्रिब्यूट की मदद से लागू किया जाता है. कॉन्टेंट बनाने प्रोग्राम में बदलाव किए बिना, composite ऑप को इसके डिकपोज़िशन से बदला जा सकता है सिमेंटिक्स. ऐसे मामलों में जहां अपघटन को इनलाइन करने से नतीजे नहीं मिलते ऑप सिमैंटिक्स, custom_call का इस्तेमाल करना पसंद है.

version फ़ील्ड (डिफ़ॉल्ट रूप से 0 पर सेट होती है) का इस्तेमाल किसी कंपोज़िट की वैल्यू को दिखाने के लिए किया जाता है सिमेंटिक्स बदल गया है.

इनपुट

लेबल नाम टाइप
(I1) inputs वैल्यू की वैरायडिक संख्या
(I2) name string टाइप का कॉन्स्टेंट
(I3) composite_attributes एट्रिब्यूट डिक्शनरी
(आई4) decomposition string टाइप का कॉन्स्टेंट
(I5) version si32 टाइप का कॉन्स्टेंट

आउटपुट

नाम टाइप
results वैल्यू की वैरायडिक संख्या

कंस्ट्रेंट

  • (C1) is_namespaced_op_name(name)
  • (सी2) is_defined_in_parent_scope(decomposition)
  • (C3) types(inputs...) == input_types(decomposition)
  • (C4) types(results...) == output_types(decomposition)

उदाहरण

%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>

ज़्यादा उदाहरण

जोड़ें

सिमैंटिक

inputs को dimension डाइमेंशन के साथ उसी क्रम में जोड़ता है जिस क्रम में दिया गया है आर्ग्युमेंट और result टेंसर बनाता है. औपचारिक तौर पर, result[i0, ..., id, ..., iR-1] = inputs[k][i0, ..., kd, ..., iR-1], जहां:

  1. id = d0 + ... + dk-1 + kd.
  2. d, dimension के बराबर है और d0, ... डाइमेंशन का dवां साइज़ है inputs का.

इनपुट

लेबल नाम टाइप कंस्ट्रेंट
(I1) inputs टेंसर की वैरायडिक संख्या या हर टेंसर की क्वांटाइज़्ड टेंसर की संख्या (सी1-सी6)
(I2) dimension si64 टाइप का कॉन्स्टेंट (C2), (C4), (C6)

आउटपुट

नाम टाइप कंस्ट्रेंट
result टेंसर या हर टेन्सर क्वांटाइज़्ड टेंसर (सी5-सी6)

कंस्ट्रेंट

  • (C1) same(element_type(inputs...)).
  • (C2) dim(inputs..., dimension) को छोड़कर, 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]), इन्हें छोड़कर:
    • dim(result, dimension) = dim(inputs[0], dimension) + ....

उदाहरण

// %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]]

ज़्यादा उदाहरण

कॉन्सटेंट

सिमैंटिक

कॉन्स्टेंट value से, output टेंसर बनाता है.

इनपुट

लेबल नाम टाइप कंस्ट्रेंट
(I1) value कॉन्सटेंट (सी1)

आउटपुट

नाम टाइप कंस्ट्रेंट
output टेंसर या क्वांटाइज़्ड टेंसर (सी1)

कंस्ट्रेंट

  • (C1) type(value) = type(output).

उदाहरण

%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]]

ज़्यादा उदाहरण

ग्राहक में बदलने वाले

सिमैंटिक

एक एलिमेंट से दूसरे टाइप में एलिमेंट के हिसाब से कन्वर्ज़न करता है operand टेंसर और result टेंसर बनाता है.

boolean-to-any-supported-type के लिए, वैल्यू false है शून्य में बदल जाता है और true मान एक में बदल जाता है. इसके लिए any-supported-type-to-boolean रूपांतरण, शून्य मान को false और शून्य के अलावा किसी अन्य वैल्यू को true में बदल दिया जाता है. इसे देखने का तरीका नीचे दिया गया है और जटिल प्रकारों के लिए काम करते हैं.

integer-टू-इंटीजर, integer-टू-फ़्लोटिंग-पॉइंट वाले कन्वर्ज़न के लिए या floating-point-to-floating-point, अगर सोर्स वैल्यू ठीक को डेस्टिनेशन टाइप में दिखाया जाता है, तो नतीजे के तौर पर मिलने वाली वैल्यू प्रतिनिधित्व. नहीं तो, व्यवहार अभी तय नहीं किया जा सकता (#180).

floating-point-to-integer वाले कन्वर्ज़न के लिए, फ़्रैक्शनल हिस्सा काट-छांट की गई है. अगर काट-छांट की गई वैल्यू को डेस्टिनेशन टाइप में नहीं दिखाया जा सकता, तो व्यवहार अभी तय नहीं है (#180).

कॉम्प्लेक्स-टू-कॉम्प्लेक्स वाले कन्वर्ज़न का तरीका कन्वर्ज़न के लिए, floating-point-to-floating-point कन्वर्ज़न काल्पनिक हिस्से.

complex-to-any-other-type और any-other-type-to-complex कन्वर्ज़न के लिए. सोर्स काल्पनिक मान को नज़रअंदाज़ कर दिया जाता है या डेस्टिनेशन काल्पनिक मान यह होता है शून्य है. वास्तविक भाग का रूपांतरण फ़्लोटिंग-पॉइंट कन्वर्ज़न.

सिद्धांत के तौर पर, इस ऑपरेशन में डिक्वांटाइज़ेशन की सुविधा इस्तेमाल की जा सकती है (कन्वर्ज़न से क्वांटाइज़्ड टेंसर से रेगुलर टेंसर तक), क्वांटाइज़ेशन (रेगुलर से कन्वर्ज़न टेंसर से क्वांटाइज़्ड टेंसर) और रीक्वांटाइज़ेशन (संख्या में बदलने वाले टेंसर के बीच कन्वर्ज़न) टेंसर), लेकिन फ़िलहाल हमारे पास उसके लिए खास तौर पर काम करने वाले ऑपरेशन हैं - पहले इस्तेमाल के उदाहरण के लिए uniform_dequantize और पहली बार इस्तेमाल के लिए uniform_quantize इस्तेमाल के दूसरे और तीसरे उदाहरण. आने वाले समय में, ये दोनों ऑपरेशन मर्ज किए जा सकते हैं convert (#1576) में.

इनपुट

लेबल नाम टाइप कंस्ट्रेंट
(I1) operand टेनसॉर (सी1)

आउटपुट

नाम टाइप कंस्ट्रेंट
result टेनसॉर (सी1)

कंस्ट्रेंट

  • (C1) shape(operand) = shape(result).

उदाहरण

// %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)]

ज़्यादा उदाहरण

कन्वर्ज़न

सिमैंटिक

lhs की विंडो और rhs के स्लाइस के बीच, प्रॉडक्ट की गणना करता है और नतीजे देता है result. यहां दिए गए डायग्राम में दिखाया गया है कि result में एलिमेंट का हिसाब कैसे लगाया जाता है lhs और rhs को बेहतर तरीके से समझने के लिए, एक अच्छा उदाहरण दिया गया है.

कन्वर्ज़न

ज़्यादा औपचारिक तौर पर, lhs के हिसाब से इनपुट की इन रीफ़्रेमिंग पर विचार करें lhs की विंडो को दिखाने के लिए:

  • 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).

इस रीफ़्रेमिंग में ये हेल्पर फ़ंक्शन इस्तेमाल किए जाते हैं:

  • 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] जहां j[d] = i[permutation[d]].

अगर feature_group_count = 1 और batch_group_count = 1 है, तो सभी के लिए index_space(dim(result, output_spatial_dimensions...)) में output_spatial_index, result[result_shape(:, output_spatial_index, :)] = dot_product जहां:

  • 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]). ऐसा लगता है कि इस सुविधा का इस्तेमाल नहीं किया गया है, इसलिए आने वाले समय में हम इसे हटाने की योजना बना रहे हैं (#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]).

अगर 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).

अगर 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).

क्वांटाइज़्ड टाइप के लिए, 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)) परफ़ॉर्म करता है.

हाइब्रिड क्वांटाइज़्ड टाइप के लिए 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) परफ़ॉर्म करता है.

इनपुट

लेबल नाम टाइप कंस्ट्रेंट
(I1) lhs टेंसर या हर टेन्सर क्वांटाइज़्ड टेंसर (C1), (C10-C11), (C14) (C25), (C27-C28), (C31-C32), (C34)
(I2) rhs टेंसर या क्वांटाइज़्ड टेंसर (C1), (C14-C16), (C25), (C27-C29), (C31-C34)
(I3) window_strides si64 टाइप का 1-डाइमेंशन टेंसर कॉन्सटेंट (C2-C3), (C25)
(आई4) padding si64 टाइप का 2-डाइमेंशन टेंसर कॉन्सटेंट (C4), (C25)
(I5) lhs_dilation si64 टाइप का 1-डाइमेंशन टेंसर कॉन्सटेंट (C5-C6), (C25)
(I6) rhs_dilation si64 टाइप का 1-डाइमेंशन टेंसर कॉन्सटेंट (C7-C8), (C25)
(I7) window_reversal i1 टाइप का 1-डाइमेंशन टेंसर कॉन्सटेंट (सी9)
(I8) input_batch_dimension si64 टाइप का कॉन्स्टेंट (C10), (C13), (C25)
(I9) input_feature_dimension si64 टाइप का कॉन्स्टेंट (C11), (C13-C14)
(I10) input_spatial_dimensions si64 टाइप का 1-डाइमेंशन टेंसर कॉन्सटेंट (C12), (C13), (C25)
(I11) kernel_input_feature_dimension si64 टाइप का कॉन्स्टेंट (C14), (C18)
(I12) kernel_output_feature_dimension si64 टाइप का कॉन्स्टेंट (C15-C16), (C18), (C25), (C29)
(I13) kernel_spatial_dimensions si64 टाइप का 1-डाइमेंशन टेंसर कॉन्सटेंट (C17-C18), (C25)
(I14) output_batch_dimension si64 टाइप का कॉन्स्टेंट (C20), (C25)
(I15) output_feature_dimension si64 टाइप का कॉन्स्टेंट (C20), (C25), (C30)
(I16) output_spatial_dimensions si64 टाइप का 1-डाइमेंशन टेंसर कॉन्सटेंट (C19-C20), (C25)
(I17) feature_group_count si64 टाइप का कॉन्स्टेंट (C11), (C14), (C16), (C21), (C23)
(I18) batch_group_count si64 टाइप का कॉन्स्टेंट (C10), (C15), (C22), (C23), (C25)
(I19) precision_config DEFAULT, HIGH, और HIGHEST के ईनम की अलग-अलग संख्या (सी24)

आउटपुट

नाम टाइप कंस्ट्रेंट
result टेंसर या क्वांटाइज़्ड टेंसर (C25-C28), (C30), (C32-34)

कंस्ट्रेंट

  • (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] दिया गया:
    • 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] दिया गया:
    • 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] दिया गया:
    • 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) को इस तरह परिभाषित किया गया है:
    • अगर result_dim = output_batch_dimension है, तो dim(lhs, input_batch_dimension) / batch_group_count.
    • अगर result_dim = output_feature_dimension है, तो dim(rhs, kernel_output_feature_dimension).
    • 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.
  • अगर इस संक्रिया में गैर-संख्यात्मक टेंसर का इस्तेमाल किया गया है, तो:
    • (C27) element_type(lhs) = element_type(rhs) = element_type(result).
  • अगर इस संक्रिया में क्वांटाइज़्ड टेंसर का इस्तेमाल किया जाता है:
    • (C28) is_quantized(lhs) = is_quantized(result) and is_quantized(rhs).
    • (C29) अगर is_per_axis_quantized(rhs), फिर quantization_dimension(rhs) = kernel_output_feature_dimension.
    • (C30) अगर is_per_axis_quantized(result) है, तो quantization_dimension(result) = output_feature_dimension.
    • अगर 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) है, तो is_per_tensor_quantized(result).
    • अगर !is_quantized(lhs):
    • (C34) element_type(lhs) = expressed_type(rhs) = element_type(result).

उदाहरण

// %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]]
//          ]]

ज़्यादा उदाहरण

कोज्या

सिमैंटिक

operand टेंसर पर एलिमेंट के हिसाब से कोसाइन करता है और इससे result टेंसर. एलिमेंट टाइप के आधार पर, ये काम किए जाते हैं:

  • फ़्लोट के लिए: IEEE-754 से cos.
  • सम्मिश्र संख्याओं के लिए: सम्मिश्र कोसाइन.
  • क्वांटाइज़्ड टाइप के लिए: dequantize_op_quantize(cosine, operand, type(result)).

इनपुट

लेबल नाम टाइप कंस्ट्रेंट
(I1) operand फ़्लोटिंग-पॉइंट या कॉम्प्लेक्स टाइप या हर टेंसर क्वांटाइज़्ड टेंसर का टेंसर (सी1)

आउटपुट

नाम टाइप कंस्ट्रेंट
result फ़्लोटिंग-पॉइंट या कॉम्प्लेक्स टाइप या हर टेंसर क्वांटाइज़्ड टेंसर का टेंसर (सी1)

कंस्ट्रेंट

  • (C1) baseline_type(operand) = baseline_type(result).

उदाहरण

// %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

सिमैंटिक

operand में शुरुआत में शून्य बिट की संख्या एलिमेंट के हिसाब से गिनती करता है टेंसर बनाता है और result टेंसर बनाता है.

इनपुट

लेबल नाम टाइप कंस्ट्रेंट
(I1) operand पूर्णांक टाइप का टेंसर (सी1)

आउटपुट

नाम टाइप कंस्ट्रेंट
result पूर्णांक टाइप का टेंसर (सी1)

कंस्ट्रेंट

  • (C1) type(operand) = type(result).

उदाहरण

// %operand: [[0, 1], [128, -1]]
%result = "stablehlo.count_leading_zeros"(%operand) : (tensor<2x2xi64>) -> tensor<2x2xi64>
// %result: [[64, 63], [56, 0]]

ज़्यादा उदाहरण

custom_call

सिमैंटिक

लागू करने के बारे में तय की गई कार्रवाई call_target_name को इनकैप्सुलेट करता है, जो inputs और called_computations के साथ मिलकर results बनाती हैं. has_side_effect, backend_config और api_version का इस्तेमाल, जानकारी देने के लिए किया जा सकता है लागू करने से जुड़ा मेटाडेटा.

फ़िलहाल, इस कार्रवाई में काफ़ी अव्यवस्थित कलेक्शन है ऐसा मेटाडेटा जो सर्च इंजन की तरह काम करने वाली कंपनी की परफ़ॉर्मेंस में हुए बदलाव को दिखाता है XLA कंपाइलर का इस्तेमाल किया. आने वाले समय में, हम इस मेटाडेटा को एक जगह पर लाने की योजना बना रहे हैं (#741).

इनपुट

लेबल नाम टाइप
(I1) inputs वैल्यू की वैरायडिक संख्या
(I2) call_target_name string टाइप का कॉन्स्टेंट
(I3) has_side_effect i1 टाइप का कॉन्स्टेंट
(आई4) backend_config string टाइप का कॉन्स्टेंट या एट्रिब्यूट डिक्शनरी
(I5) api_version si32 टाइप का कॉन्स्टेंट
(I6) called_computations string टाइप के कॉन्सटेंट की वैरायडिक संख्या

आउटपुट

नाम टाइप
results वैल्यू की वैरायडिक संख्या

उदाहरण

%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>

विभाजन

सिमैंटिक

भाज्य lhs और भाजक rhs टेंसर और एलिमेंट के आधार पर भाग करता है result टेंसर बनाता है. एलिमेंट टाइप के आधार पर, ये काम किए जाते हैं:

  • पूर्णांकों के लिए: पूर्णांक विभाजन जो किसी भी वैल्यू के साथ बीजगणितीय भागफल बनाता है आंशिक भाग खारिज किया गया.
  • फ़्लोट के लिए: IEEE-754 से division.
  • सम्मिश्र संख्याओं के लिए: जटिल विभाजन.
  • क्वांटाइज़्ड टाइप के लिए:
    • dequantize_op_quantize(divide, lhs, rhs, type(result)).

इनपुट

लेबल नाम टाइप कंस्ट्रेंट
(I1) lhs इंटीजर, फ़्लोटिंग-पॉइंट या कॉम्प्लेक्स टाइप या हर टेंसर क्वांटाइज़्ड टेंसर का टेंसर (सी1)
(I2) rhs इंटीजर, फ़्लोटिंग-पॉइंट या कॉम्प्लेक्स टाइप या हर टेंसर क्वांटाइज़्ड टेंसर का टेंसर (सी1)

आउटपुट

नाम टाइप कंस्ट्रेंट
result इंटीजर, फ़्लोटिंग-पॉइंट या कॉम्प्लेक्स टाइप या हर टेंसर क्वांटाइज़्ड टेंसर का टेंसर (सी1)

कंस्ट्रेंट

  • (C1) baseline_type(lhs) = baseline_type(rhs) = baseline_type(result).

उदाहरण

// %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

सिमैंटिक

lhs के स्लाइस और rhs के स्लाइस के बीच, प्रॉडक्ट की गणना डॉट करता है और result टेंसर.

औपचारिक तौर पर, result[result_index] = dot_product, जहां:

  • 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 अभी तक किसी भी व्यक्ति ने चेक इन नहीं किया है जहां size(result_batching_index) = size(lhs_batching_dimensions), size(result_lhs_index) = size(lhs_result_dimensions) और size(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)).

क्वांटाइज़्ड टाइप के लिए, 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)) परफ़ॉर्म करता है.

हाइब्रिड क्वांटाइज़्ड टाइप के लिए 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) परफ़ॉर्म करता है.

precision_config, स्पीड और सटीक होने के बीच के अंतर को कंट्रोल करता है कंप्यूटेशन (अक्सेलरेटर बैकएंड पर). यह इनमें से कोई एक हो सकता है ( मोमेंट, इन ईनम वैल्यू के सिमेंटिक्स तय नहीं किए गए हैं, लेकिन हम इस समस्या को हल करने के लिए #755):

  • DEFAULT: सबसे तेज़ कैलकुलेशन, लेकिन इसका सबसे कम सटीक अनुमान मूल नंबर.
  • HIGH: धीमी कैलकुलेशन, लेकिन मूल नंबर.
  • HIGHEST: सबसे धीमी कैलकुलेशन, लेकिन मूल नंबर.

DotAlgorithm, लागू करने के लिए इस्तेमाल किए जाने वाले एल्गोरिदम की मुख्य प्रॉपर्टी के बारे में बताता है डॉट ऑपरेशन, जो प्रिसिज़न भी परिभाषित करता है. अगर एल्गोरिदम एट्रिब्यूट फ़ील्ड सेट हैं, तो precision_config DEFAULT होनी चाहिए. DotAlgorithms अभी तक किसी भी व्यक्ति ने चेक इन नहीं किया है इसके लिए कोई डिफ़ॉल्ट वैल्यू न हो, क्योंकि डिफ़ॉल्ट पैरामीटर को लागू किया जाता है तय किया गया है. इसलिए, सभी डॉट एल्गोरिदम फ़ील्ड को None पर सेट किया जा सकता है, ताकि खाली डॉट एल्गोरिदम, जो इसके बजाय precision_config वैल्यू का इस्तेमाल करेगा.

DotAlgorithm फ़ील्ड में शामिल हैं:

  • lhs_precision_type और rhs_precision_type, वह सटीक जानकारी जो LHS और ऑपरेशन की दाईं ओर मौजूद वैल्यू में बदल दिया जाता है. प्रिसिज़न टाइप, और आउटपुट के स्टोरेज टाइप को अलग-अलग कर सकते हैं.
  • accumulation_type इकट्ठा करने के लिए इस्तेमाल की गई सटीक वैल्यू.
  • lhs_component_count, rhs_component_count, और num_primitive_operations तब लागू होती है, जब हम एक ऐसा एल्गोरिदम बनाते हैं जो LHS और/या RHS को कई कॉम्पोनेंट और कई सारे "प्रीमिटिव" होते हैं उन पर डॉट ऑपरेशन वैल्यू - आम तौर पर ज़्यादा सटीक जानकारी देने के लिए (उदाहरण के लिए, ज़्यादा सटीक गणना के लिए bfloat16 आर्टिफ़िशियल इंटेलिजेंस डेटाटाइप का इस्तेमाल करना: bf16_6x tf32_3x वगैरह). जिन एल्गोरिदम के लिए डिकंपोज़िशन नहीं हुआ है उनके लिए, ये वैल्यू 1 पर सेट होना चाहिए.
  • कम सटीक तरीके से इकट्ठा होने की जानकारी देने के लिए allow_imprecise_accumulation को कुछ चरणों के लिए इस्तेमाल करने की अनुमति है (जैसे, CUBLASLT_MATMUL_DESC_FAST_ACCUM).

DotAlgorithm एट्रिब्यूट के उदाहरण:

// 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}

यह लागू करने पर निर्भर करता है कि किन कॉम्बिनेशन का इस्तेमाल किया जा सकता है. तय सीमा में आम तौर पर, इस बात की गारंटी नहीं है कि हर एल्गोरिदम StableHLO के उपभोक्ता के हिसाब से एक्सेलरेटर टाइप. अगर दिया गया एल्गोरिदम, नहीं दिखाई देता है, तो कोई गड़बड़ी वैकल्पिक है. StableHLO से पुष्टि करने की सुविधा से, पुष्टि करने में आसानी होगी. उन एल्गोरिदम को रोक रहा है जो किसी भी हार्डवेयर पर काम नहीं करते हैं.

xla_data.proto > Algorithm देखें का इस्तेमाल किया जा सकता है. टिकट #2483 का इस्तेमाल करके, बैकएंड की मदद से काम करने वाले एल्गोरिदम पर, एक ही जगह पर दस्तावेज़ बनाने की सुविधा.

इनपुट

लेबल नाम टाइप कंस्ट्रेंट
(I1) lhs टेंसर या हर टेन्सर क्वांटाइज़्ड टेंसर (C5-C6), (C9-C10), (C12-C14), (C17-C18), (C20)
(I2) rhs टेंसर या क्वांटाइज़्ड टेंसर (C7-C10), (C12-C20)
(I3) lhs_batching_dimensions si64 टाइप का 1-डाइमेंशन टेंसर कॉन्सटेंट (C1), (C3), (C5), (C9), (C12)
(आई4) rhs_batching_dimensions si64 टाइप का 1-डाइमेंशन टेंसर कॉन्सटेंट (C1), (C4), (C7), (C9)
(I5) lhs_contracting_dimensions si64 टाइप का 1-डाइमेंशन टेंसर कॉन्सटेंट (C2), (C3), (C6), (C10)
(I6) rhs_contracting_dimensions si64 टाइप का 1-डाइमेंशन टेंसर कॉन्सटेंट (C2), (C4), (C8), (C10), (C16)
(I7) precision_config DEFAULT, HIGH, और HIGHEST के ईनम की अलग-अलग संख्या (C11), (C21)
(I8) lhs_precision_type FloodType या TensorFloat32 (सी21)
(I9) rhs_precision_type FloodType या TensorFloat32 (सी21)
(I10) accumulation_type FloodType या TensorFloat32 (सी21)
(I11) lhs_component_count si32 टाइप का कॉन्स्टेंट (C21), (C22)
(I12) rhs_component_count si32 टाइप का कॉन्स्टेंट (C21), (C23)
(I13) num_primitive_operations si32 टाइप का कॉन्स्टेंट (C21), (C24)
(I14) allow_imprecise_accumulation bool टाइप का कॉन्स्टेंट (सी21)

आउटपुट

नाम टाइप कंस्ट्रेंट
result टेंसर या क्वांटाइज़्ड टेंसर (C12), (C14), (C18-C20)

कंस्ट्रेंट

  • (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).
  • अगर इस संक्रिया में गैर-संख्यात्मक टेंसर का इस्तेमाल किया गया है, तो:
    • (C13) element_type(lhs) = element_type(rhs).
  • अगर इस संक्रिया में क्वांटाइज़्ड टेंसर का इस्तेमाल किया जाता है:
    • (C14) is_quantized(lhs) = is_quantized(result) and is_quantized(rhs).
    • (C15) zero_points(rhs) = 0.
    • (C16) अगर is_per_axis_quantized(rhs) है, तो quantization_dimension(rhs), rhs_contracting_dimensions में नहीं है.
    • अगर 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) है, तो is_per_tensor_quantized(result).
    • अगर !is_quantized(lhs):
    • (C20) element_type(lhs) = expressed_type(rhs) = element_type(result).
  • अगर !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.

उदाहरण

// %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

सिमैंटिक

यह ऑपरेशन इसके फ़ंक्शनल रूप से एक जैसा है broadcast_in_dim ऑप, लेकिन output_dimensions के ज़रिए नतीजे का आकार डायनैमिक तौर पर बताया जाता है.

इस ऑपरेशन में वैकल्पिक एट्रिब्यूट known_expanding_dimensions, known_non_expanding_dimensions भी स्वीकार किए जाते हैं डाइमेंशन के बढ़ते व्यवहार के बारे में अपनी अहम जानकारी ज़ाहिर करने के लिए. अगर जानकारी नहीं दी गई है, तो माना गया है कि सभी डाइमेंशन बड़े हो सकते हैं.

इनपुट

लेबल नाम टाइप कंस्ट्रेंट
(I1) operand टेंसर या क्वांटाइज़्ड टेंसर (C1-C2), (C5-C6), (C9)
(I2) output_dimensions पूर्णांक प्रकार का 1-विमीय टेंसर (सी7)
(I3) broadcast_dimensions पूर्णांक टाइप का 1-डाइमेंशन कॉन्सटेंट टेंसर (सी2-सी6)
(आई4) known_expanding_dimensions पूर्णांक टाइप का 1-डाइमेंशन कॉन्सटेंट टेंसर (सी8-सी9)
(I5) known_non_expanding_dimensions पूर्णांक टाइप का 1-डाइमेंशन कॉन्सटेंट टेंसर (सी8-सी9)

आउटपुट

नाम टाइप कंस्ट्रेंट
result टेंसर या क्वांटाइज़्ड टेंसर (C1), (C3), (C5-C7)

कंस्ट्रेंट

  • (C1) element_type(result) देने वाली कंपनी:
    • अगर !is_per_axis_quantized(operand) है, तो element_type(operand).
    • quantization_dimension(operand) को छोड़कर, element_type(operand), scales(operand) और zero_points(operand) इनसे अलग हो सकती हैं quantization_dimension(result), scales(result), और zero_points(result) नहीं करना होगा.
  • (C2) size(broadcast_dimensions) = rank(operand).
  • (C3) 0 <= broadcast_dimensions < rank(result).
  • (C4) is_unique(broadcast_dimensions).
  • (C5) axes(operand) में सभी d के लिए:
    • dim(operand, d) = 1 या
    • dim(operand, d) = dim(result, broadcast_dimensions[d]).
  • (C6) अगर is_per_axis_quantized(result):
    • quantization_dimension(result) = broadcast_dimensions[quantization_dimension(operand)].
    • अगर dim(operand, quantization_dimension(operand)) = 1, तो 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).

उदाहरण

// %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

सिमैंटिक

यह ऑपरेशन इसके फ़ंक्शनल रूप से एक जैसा है बातचीत ऑप, लेकिन padding के ज़रिए पैडिंग (जगह) को डाइनैमिक तौर पर बताया गया है.

इनपुट

लेबल नाम टाइप कंस्ट्रेंट
(I1) lhs टेंसर या हर टेन्सर क्वांटाइज़्ड टेंसर (C1), (C10-C11), (C14) (C25), (C26-C27), (C30-C31), (C33)
(I2) rhs टेंसर या क्वांटाइज़्ड टेंसर (C1), (C14-C16), (C26-C28), (C30-C33)
(I3) padding पूर्णांक टाइप का 2-डाइमेंशन वाला टेंसर (सी4)
(आई4) window_strides si64 टाइप का 1-डाइमेंशन टेंसर कॉन्सटेंट (सी2-सी3)
(I5) lhs_dilation si64 टाइप का 1-डाइमेंशन टेंसर कॉन्सटेंट (सी5-सी6)
(I6) rhs_dilation si64 टाइप का 1-डाइमेंशन टेंसर कॉन्सटेंट (C7-C8)
(I7) window_reversal i1 टाइप का 1-डाइमेंशन टेंसर कॉन्सटेंट (सी9)
(I8) input_batch_dimension si64 टाइप का कॉन्स्टेंट (C10), (C13)
(I9) input_feature_dimension si64 टाइप का कॉन्स्टेंट (C11), (C13-C14)
(I10) input_spatial_dimensions si64 टाइप का 1-डाइमेंशन टेंसर कॉन्सटेंट (C12), (C13)
(I11) kernel_input_feature_dimension si64 टाइप का कॉन्स्टेंट (C14), (C18)
(I12) kernel_output_feature_dimension si64 टाइप का कॉन्स्टेंट (C15-C16), (C18), (C28)
(I13) kernel_spatial_dimensions si64 टाइप का 1-डाइमेंशन टेंसर कॉन्सटेंट (C17-C18)
(I14) output_batch_dimension si64 टाइप का कॉन्स्टेंट (C20)
(I15) output_feature_dimension si64 टाइप का कॉन्स्टेंट (C20), (C29)
(I16) output_spatial_dimensions si64 टाइप का 1-डाइमेंशन टेंसर कॉन्सटेंट (C19-C20)
(I17) feature_group_count si64 टाइप का कॉन्स्टेंट (C11), (C14), (C16), (C21), (C23)
(I18) batch_group_count si64 टाइप का कॉन्स्टेंट (C10), (C15), (C22), (C23)
(I19) precision_config DEFAULT, HIGH, और HIGHEST के ईनम की अलग-अलग संख्या (सी24)

आउटपुट

नाम टाइप कंस्ट्रेंट
result टेंसर या क्वांटाइज़्ड टेंसर (C25-C27), (C29), (C31-C33)

कंस्ट्रेंट

  • (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] दिया गया:
    • 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] दिया गया:
    • 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] दिया गया:
    • 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) को इस तरह परिभाषित किया गया है:
    • अगर result_dim = output_batch_dimension है, तो dim(lhs, input_batch_dimension) / batch_group_count.
    • अगर result_dim = output_feature_dimension है, तो dim(rhs, kernel_output_feature_dimension).
    • 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.
  • अगर इस संक्रिया में गैर-संख्यात्मक टेंसर का इस्तेमाल किया गया है, तो:
    • (C27) element_type(lhs) = element_type(rhs) = element_type(result).
  • अगर इस संक्रिया में क्वांटाइज़्ड टेंसर का इस्तेमाल किया जाता है:
    • (C28) is_quantized(lhs) = is_quantized(result) and is_quantized(rhs).
    • (C29) अगर is_per_axis_quantized(rhs), फिर quantization_dimension(rhs) = kernel_output_feature_dimension.
    • (C30) अगर is_per_axis_quantized(result) है, तो quantization_dimension(result) = output_feature_dimension.
    • अगर 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) है, तो is_per_tensor_quantized(result).
    • अगर !is_quantized(lhs):
    • (C34) element_type(lhs) = expressed_type(rhs) = element_type(result).

उदाहरण

// %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

सिमैंटिक

यह ऑपरेशन इसके फ़ंक्शनल रूप से एक जैसा है इकट्ठा करना op, slice_sizes को मान के रूप में डायनैमिक तौर पर बताया गया है.

इनपुट

लेबल नाम टाइप कंस्ट्रेंट
(I1) operand टेंसर या हर टेन्सर क्वांटाइज़्ड टेंसर (C1), (C7), (C10-C12), (C14)
(I2) start_indices पूर्णांक टाइप का टेंसर (C2), (C3), (C13)
(I3) slice_sizes पूर्णांक प्रकार का 1-विमीय टेंसर (C8), (C11-C13)
(आई4) offset_dims si64 टाइप का 1-डाइमेंशन टेंसर कॉन्सटेंट (C1), (C4-C5), (C13)
(I5) collapsed_slice_dims si64 टाइप का 1-डाइमेंशन टेंसर कॉन्सटेंट (C1), (C6-C8), (C13)
(I6) start_index_map si64 टाइप का 1-डाइमेंशन टेंसर कॉन्सटेंट (C3), (C9), (C10)
(I7) index_vector_dim si64 टाइप का कॉन्स्टेंट (C2), (C3), (C13)
(I8) indices_are_sorted i1 टाइप का कॉन्स्टेंट

आउटपुट

नाम टाइप कंस्ट्रेंट
result टेंसर या हर टेन्सर क्वांटाइज़्ड टेंसर (C5), (C13-C14)

कंस्ट्रेंट

  • (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) जहां:
    • batch_dim_sizes = shape(start_indices), सिर्फ़ डाइमेंशन का साइज़ index_vector_dim से संबंधित start_indices को शामिल नहीं किया गया है.
    • offset_dim_sizes = shape(slice_sizes), सिर्फ़ डाइमेंशन के साइज़ collapsed_slice_dims से संबंधित slice_sizes में शामिल नहीं किए गए हैं.
    • combine, batch_dim_sizes को batch_dims के हिसाब से ऐक्सिस पर लगाता है और offset_dims के हिसाब से, ऐक्सिस पर offset_dim_sizes.
  • (C14) element_type(operand) = element_type(result).

उदाहरण

// %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

सिमैंटिक

यह ऑपरेशन इसके फ़ंक्शनल रूप से एक जैसा है आईओटा ऑप, लेकिन output_shape के ज़रिए नतीजे का आकार डायनैमिक तौर पर बताया जाता है.

इनपुट

लेबल नाम टाइप कंस्ट्रेंट
(I1) output_shape पूर्णांक प्रकार का 1-विमीय टेंसर (C1), (C2)
(I2) iota_dimension si64 (सी1)

आउटपुट

नाम टाइप कंस्ट्रेंट
result इंटीजर, फ़्लोटिंग-पॉइंट या कॉम्प्लेक्स टाइप या हर टेंसर क्वांटाइज़्ड टेंसर का टेंसर (सी2)

कंस्ट्रेंट

  • (C1) 0 <= iota_dimension < size(output_shape).
  • (C2) rank(result) = size(output_shape).

उदाहरण

%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

सिमैंटिक

यह ऑपरेशन इसके फ़ंक्शनल रूप से एक जैसा है पैड ठीक है, लेकिन edge_padding_low, edge_padding_high, और interior_padding के साथ को डाइनैमिक रूप से वैल्यू के तौर पर बताया जाता है.

इनपुट

लेबल नाम टाइप कंस्ट्रेंट
(I1) operand टेंसर या हर टेन्सर क्वांटाइज़्ड टेंसर (C1), (C2), (C4)
(I2) padding_value 0-डाइमेंशन वाला टेंसर या हर टेंसर क्वांटाइज़्ड टेंसर (सी1)
(I3) edge_padding_low पूर्णांक प्रकार का 1-विमीय टेंसर (C1), (C4)
(आई4) edge_padding_high पूर्णांक प्रकार का 1-विमीय टेंसर (C1), (C4)
(I5) interior_padding पूर्णांक प्रकार का 1-विमीय टेंसर (सी2-सी4)

आउटपुट

नाम टाइप कंस्ट्रेंट
result टेंसर या हर टेन्सर क्वांटाइज़्ड टेंसर (सी3-सी6)

कंस्ट्रेंट

  • (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.

उदाहरण

// %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

सिमैंटिक

यह ऑपरेशन इसके फ़ंक्शनल रूप से एक जैसा है आकार बदलना ऑप, लेकिन output_shape के ज़रिए नतीजे का आकार डायनैमिक तौर पर बताया जाता है.

इनपुट

लेबल नाम टाइप कंस्ट्रेंट
(I1) operand टेंसर या क्वांटाइज़्ड टेंसर (सी1-सी3)
(I2) output_shape पूर्णांक प्रकार का 1-विमीय टेंसर (सी4)

आउटपुट

नाम टाइप कंस्ट्रेंट
result टेंसर या क्वांटाइज़्ड टेंसर (सी1-सी4)

कंस्ट्रेंट

  • (C1) element_type(result) देने वाली कंपनी:
    • अगर !is_per_axis_quantized(operand) है, तो element_type(operand).
    • element_type(operand), लेकिन quantization_dimension(operand) और ऐसा न होने पर quantization_dimension(result) अलग हो सकती है.
  • (C2) size(operand) = size(result).
  • (C3) अगर is_per_axis_quantized(operand):
    • 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).

उदाहरण

// %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

सिमैंटिक

डाइनैमिक तौर पर गिने गए शुरुआती इंडेक्स का इस्तेमाल करके, operand से स्लाइस एक्सट्रैक्ट करता है और result टेंसर बनाता है. start_indices में इसके शुरुआती इंडेक्स शामिल हैं हर डाइमेंशन के लिए स्लाइस, जिस पर संभावित बदलाव हो सकता है और slice_sizes इसमें हर डाइमेंशन के स्लाइस के साइज़ शामिल होने चाहिए. औपचारिक तौर पर, result[result_index] = operand[operand_index] कहां:

  • adjusted_start_indices = clamp(0, start_indices, shape(operand) - slice_sizes).
  • operand_index = adjusted_start_indices + result_index.

इनपुट

लेबल नाम टाइप कंस्ट्रेंट
(I1) operand टेंसर या हर टेन्सर क्वांटाइज़्ड टेंसर (C1), (C2), (C4)
(I2) start_indices पूर्णांक टाइप के 0-डाइमेंशन वाले टेंसर की वैरायडिक संख्या (C2), (C3)
(I3) slice_sizes si64 टाइप का 1-डाइमेंशन टेंसर कॉन्सटेंट (C2), (C4), (C5)

आउटपुट

नाम टाइप कंस्ट्रेंट
result टेंसर या हर टेन्सर क्वांटाइज़्ड टेंसर (C1), (C5)

कंस्ट्रेंट

  • (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.

उदाहरण

// %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

सिमैंटिक

result टेंसर बनाता है, जो इसे छोड़कर operand टेंसर के बराबर होता है start_indices से शुरू होने वाला स्लाइस, update की वैल्यू के साथ अपडेट होता है. औपचारिक तौर पर, result[result_index] को इस तरह परिभाषित किया गया है:

  • update[update_index], अगर 0 <= update_index < shape(update) कहां:
    • adjusted_start_indices = clamp(0, start_indices, shape(operand) - shape(update)).
    • update_index = result_index - adjusted_start_indices.
  • अगर ऐसा नहीं है, तो operand[result_index].

इनपुट

लेबल नाम टाइप कंस्ट्रेंट
(I1) operand टेंसर या हर टेन्सर क्वांटाइज़्ड टेंसर (C1-C4), (C6)
(I2) update टेंसर या हर टेन्सर क्वांटाइज़्ड टेंसर (C2), (C3), (C6)
(I3) start_indices पूर्णांक टाइप के 0-डाइमेंशन वाले टेंसर की वैरायडिक संख्या (C4), (C5)

आउटपुट

नाम टाइप कंस्ट्रेंट
result टेंसर या हर टेन्सर क्वांटाइज़्ड टेंसर (सी1)

कंस्ट्रेंट

  • (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).

उदाहरण

// %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]
//          ]

ज़्यादा उदाहरण

घातांकी

सिमैंटिक

operand टेंसर पर एलिमेंट के हिसाब से चरघातांकीय संक्रिया करता है और इससे result टेंसर. एलिमेंट टाइप के आधार पर, ये काम किए जाते हैं:

  • फ़्लोट के लिए: IEEE-754 से exp.
  • सम्मिश्र संख्याओं के लिए: सम्मिश्र घातांक.
  • क्वांटाइज़्ड टाइप के लिए: dequantize_op_quantize(exponential, operand, type(result)).

इनपुट

लेबल नाम टाइप कंस्ट्रेंट
(I1) operand फ़्लोटिंग-पॉइंट या कॉम्प्लेक्स टाइप या हर टेंसर क्वांटाइज़्ड टेंसर का टेंसर (सी1)

आउटपुट

नाम टाइप कंस्ट्रेंट
result फ़्लोटिंग-पॉइंट या कॉम्प्लेक्स टाइप या हर टेंसर क्वांटाइज़्ड टेंसर का टेंसर (सी1)

कंस्ट्रेंट

  • (C1) baseline_type(operand) = baseline_type(result).

उदाहरण

// %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

सिमैंटिक

operand टेंसर पर एलिमेंट के हिसाब से एक्सपोनेन्शियल माइनस एक संक्रिया करता है और result टेंसर बनाता है. एलिमेंट टाइप के आधार पर, ये काम किए जाते हैं:

  • फ़्लोट के लिए: IEEE-754 से expm1.
  • सम्मिश्र संख्याओं के लिए: सम्मिश्र घातांक से एक घटाएं.
  • क्वांटाइज़्ड टाइप के लिए: dequantize_op_quantize(exponential_minus_one, operand, type(result)).

इनपुट

लेबल नाम टाइप कंस्ट्रेंट
(I1) operand फ़्लोटिंग-पॉइंट या कॉम्प्लेक्स टाइप या हर टेंसर क्वांटाइज़्ड टेंसर का टेंसर (सी1)

आउटपुट

नाम टाइप कंस्ट्रेंट
result फ़्लोटिंग-पॉइंट या कॉम्प्लेक्स टाइप या हर टेंसर क्वांटाइज़्ड टेंसर का टेंसर (सी1)

कंस्ट्रेंट

  • (C1) baseline_type(operand) = baseline_type(result).

उदाहरण

// %operand: [0.0, 1.0]
%result = "stablehlo.exponential_minus_one"(%operand) : (tensor<2xf64>) -> tensor<2xf64>
// %result: [0.0, 1.71828187]

ज़्यादा उदाहरण

एफ़एफ़टी

सिमैंटिक

रियल और कॉम्प्लेक्स के लिए फ़ॉरवर्ड और इन्वर्स फ़ूरियर रूपांतरण करता है इनपुट/आउटपुट.

fft_type इनमें से एक है:

  • FFT: कॉम्प्लेक्स से मुश्किल एफ़एफ़टी फ़ॉरवर्ड करें.
  • IFFT: इनवर्स कॉम्प्लेक्स से कॉम्प्लेक्स एफ़एफ़टी.
  • RFFT: रीयल-टू-कॉम्प्लेक्स एफ़एफ़टी फ़ॉरवर्ड करें.
  • IRFFT: रियल-टू-कॉम्प्लेक्स FFT (यानी जटिल लेता है, वास्तविक देता है).

औपचारिक रूप से, fft फ़ंक्शन दिया गया है, जो इनपुट के रूप में जटिल प्रकार, जो आउटपुट और असंतत फूरिये रूपांतरण की गणना करता है:

fft_type = FFT के लिए, result को L की सीरीज़ के आखिरी नतीजे के तौर पर तय किया जाता है कैलकुलेशन जहां L = size(fft_length). उदाहरण के लिए, L = 3 के लिए:

  • 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]).

इसके अलावा, ifft फ़ंक्शन दिया गया है, जिसमें एक ही तरह का हस्ताक्षर है और fft के व्युत्क्रम की गणना करता है:

fft_type = IFFT के लिए, result को कंप्यूटेशन (कंप्यूटेशन) के व्युत्क्रम के तौर पर परिभाषित किया जाता है fft_type = FFT के लिए. उदाहरण के लिए, L = 3 के लिए:

  • 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, ..., :]).

इसके अलावा, rfft फ़ंक्शन दिया गया है, जो फ़्लोटिंग-पॉइंट टाइप, मुश्किल टाइप के 1-डाइमेंशन वाले टेंसर पैदा करता है और इस तरह से काम करता है:

  • rfft(real_operand) = truncated_result जहां
  • complex_operand... = (real_operand..., 0.0).
  • complex_result = fft(complex_operand).
  • truncated_result = complex_result[:(rank(complex_result) / 2 + 1)].

(जब वास्तविक ऑपरेंड के लिए अलग फूरिये रूपांतरण की गणना की जाती है, तो पहले नतीजे के N/2 + 1 एलिमेंट, बाकी के नतीजे के बारे में साफ़ तौर पर जानकारी देते हैं, इसलिए गैर-ज़रूरी एलिमेंट की गिनती करने से बचने के लिए, rfft के नतीजे को छोटा कर दिया जाता है).

fft_type = RFFT के लिए, result को L की सीरीज़ के आखिरी नतीजे के तौर पर तय किया जाता है कैलकुलेशन जहां L = size(fft_length). उदाहरण के लिए, L = 3 के लिए:

  • 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]).

आखिर में, irfft फ़ंक्शन दिया गया, जिसमें एक ही तरह का हस्ताक्षर है और rfft के व्युत्क्रम की गणना करता है:

fft_type = IRFFT के लिए, result को कंप्यूटेशन (कंप्यूटेशन) के व्युत्क्रम के तौर पर परिभाषित किया जाता है fft_type = RFFT के लिए. उदाहरण के लिए, L = 3 के लिए:

  • 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, ..., :]).

इनपुट

लेबल नाम टाइप कंस्ट्रेंट
(I1) operand फ़्लोटिंग-पॉइंट या कॉम्प्लेक्स टाइप का टेंसर (C1), (C2), (C4), (C5)
(I2) fft_type FFT, IFFT, RFFT, और IRFFT का कुल डेटा (C2), (C5)
(I3) fft_length si64 टाइप का 1-डाइमेंशन टेंसर कॉन्सटेंट (C1), (C3), (C4)

आउटपुट

नाम टाइप कंस्ट्रेंट
result फ़्लोटिंग-पॉइंट या कॉम्प्लेक्स टाइप का टेंसर (C2), (C4), (C5)

कंस्ट्रेंट

  • (C1) size(fft_length) <= rank(operand).
  • (C2) operand और result एलिमेंट के बीच का संबंध अलग-अलग होता है:
    • अगर fft_type = FFT, element_type(operand) और element_type(result) उनका कॉम्प्लेक्स टाइप एक ही है.
    • अगर fft_type = IFFT, element_type(operand) और element_type(result) उनका कॉम्प्लेक्स टाइप एक ही है.
    • अगर fft_type = RFFT, element_type(operand) एक फ़्लोटिंग-पॉइंट टाइप है और element_type(result), एक ही फ़्लोटिंग-पॉइंट का जटिल टाइप है सिमेंटिक्स.
    • अगर fft_type = IRFFT, तो element_type(operand) एक जटिल टाइप है और element_type(result) एक ही फ़्लोटिंग-पॉइंट का प्रकार फ़्लोटिंग-पॉइंट है सिमेंटिक्स.
  • (C3) 1 <= size(fft_length) <= 3.
  • (C4) अगर operand और result के बीच में, तोreal फ़्लोटिंग-पॉइंट टाइप को चुनें. इसके बाद, shape(real)[-size(fft_length):] = fft_length.
  • (C5) shape(result) = shape(operand), इन्हें छोड़कर:
    • अगर fft_type = RFFT, dim(result, -1) = dim(operand, -1) = 0 ? 0 : dim(operand, -1) / 2 + 1.
    • अगर fft_type = IRFFT, dim(operand, -1) = dim(result, -1) = 0 ? 0 : dim(result, -1) / 2 + 1.

उदाहरण

// %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)]

फ़्लोर

सिमैंटिक

operand टेंसर के एलिमेंट के हिसाब से फ़्लोर बनाता है और result टेंसर बनाता है. आईईईई-754 से roundToIntegralTowardNegative ऑपरेशन लागू करता है स्पेसिफ़िकेशन. क्वांटाइज़्ड टाइप के लिए, dequantize_op_quantize(floor, operand, type(result)).

इनपुट

लेबल नाम टाइप कंस्ट्रेंट
(I1) operand फ़्लोटिंग-पॉइंट टाइप या हर टेंसर क्वांटाइज़्ड टेंसर का टेंसर (सी1)

आउटपुट

नाम टाइप कंस्ट्रेंट
result फ़्लोटिंग-पॉइंट टाइप या हर टेंसर क्वांटाइज़्ड टेंसर का टेंसर (सी1)

कंस्ट्रेंट

  • (C1) baseline_type(operand) = baseline_type(result).

उदाहरण

// %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]

ज़्यादा उदाहरण

इकट्ठा करें

सिमैंटिक

start_indices में दिए गए ऑफ़सेट से operand टेंसर से स्लाइस इकट्ठा करता है और result टेंसर बनाता है.

नीचे दिया गया डायग्राम दिखाता है कि result में एलिमेंट, operand पर जाकर, एक अच्छे उदाहरण का इस्तेमाल करें. इस डायग्राम में, result के कुछ उदाहरण चुने गए हैं और विस्तार से बताता है कि वे किन operand इंडेक्स से जुड़े हैं.

इकट्ठा करें

ज़्यादा औपचारिक तौर पर, result[result_index] = operand[operand_index] जहां:

  • batch_dims = [d for d in axes(result) and d not in offset_dims].
  • batch_index = result_index[batch_dims...].
  • start_index को इस तरह से परिभाषित किया गया है:
    • start_indices[bi0, ..., :, ..., biN] जहां bi अलग-अलग एलिमेंट होते हैं batch_index और : को index_vector_dim इंडेक्स में डाला जाता है, अगर index_vector_dim rank(start_indices).
    • अगर ऐसा नहीं है, तो [start_indices[batch_index]].
  • axes(operand) में d_operand के लिए,
    • 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] है.
    • अगर ऐसा नहीं है, तो full_start_index[d_operand] = 0.
  • axes(operand) में d_operand के लिए,
    • full_batching_index[d_operand] = batch_index[d_start - (d_start < index_vector_dim ? 0 : 1)] अभी तक किसी भी व्यक्ति ने चेक इन नहीं किया है अगर d_operand = operand_batching_dims[i_batching] और d_start = start_indices_batching_dims[i_batching].
    • अगर ऐसा नहीं है, तो full_batching_index[d_operand] = 0.
  • offset_index = result_index[offset_dims...].
  • full_offset_index = [oi0, ..., 0, ..., oiN], जहां oi व्यक्तिगत हैं offset_index के एलिमेंट का इस्तेमाल किया जाता है और 0 को इंडेक्स में शामिल किया जाता है collapsed_slice_dims और operand_batching_dims.
  • operand_index = full_start_index + full_batching_index + full_offset_index.

अगर indices_are_sorted, true है, तो लागू करने पर यह मान लिया जा सकता है कि start_indices को start_index_map के हिसाब से क्रम में लगाया जाता है, नहीं तो व्यवहार के बारे में नहीं बताया गया है. आम तौर पर, indices(result) के सभी i1 < i2 के लिए, full_start_index(i1) <= full_start_index(i2).

इनपुट

लेबल नाम टाइप कंस्ट्रेंट
(I1) operand टेंसर या हर टेन्सर क्वांटाइज़्ड टेंसर (C1), (C8), (C11), (C17), (C19-C21), (C23)
(I2) start_indices पूर्णांक टाइप का टेंसर (C2-C3), (C14), (C17), (C22)
(I3) offset_dims si64 टाइप का 1-डाइमेंशन टेंसर कॉन्सटेंट (C1), (C4-C5), (C22)
(आई4) collapsed_slice_dims si64 टाइप का 1-डाइमेंशन टेंसर कॉन्सटेंट (C1), (C6-C9), (C22)
(I5) operand_batching_dims si64 टाइप का 1-डाइमेंशन टेंसर कॉन्सटेंट (C1), (C6), (C10-C12), (C16-C18), (C22)
(I6) start_indices_batching_dims si64 टाइप का 1-डाइमेंशन टेंसर कॉन्सटेंट (C13-C17)
(I7) start_index_map si64 टाइप का 1-डाइमेंशन टेंसर कॉन्सटेंट (C3), (C18-C19)
(I8) index_vector_dim si64 टाइप का कॉन्स्टेंट (C2-C3), (C15), (C22)
(I9) slice_sizes si64 टाइप का 1-डाइमेंशन टेंसर कॉन्सटेंट (C9), (C12), (C20-C22)
(I10) indices_are_sorted i1 टाइप का कॉन्स्टेंट

आउटपुट

नाम टाइप कंस्ट्रेंट
result टेंसर या हर टेन्सर क्वांटाइज़्ड टेंसर (C5), (C22-C23)

कंस्ट्रेंट

  • (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) जहां:
    • batch_dim_sizes = shape(start_indices), सिर्फ़ डाइमेंशन का साइज़ index_vector_dim से संबंधित start_indices को शामिल नहीं किया गया है.
    • offset_dim_sizes = slice_sizes, लेकिन इसमें डाइमेंशन का साइज़ collapsed_slice_dims और के संगत slice_sizes operand_batching_dims शामिल नहीं हैं.
    • combine, batch_dim_sizes को batch_dims के हिसाब से ऐक्सिस पर लगाता है और offset_dims के हिसाब से, ऐक्सिस पर offset_dim_sizes.
  • (C23) element_type(operand) = element_type(result).

उदाहरण

// %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

सिमैंटिक

operand के दिए गए dimension का साइज़ बनाता है. औपचारिक तौर पर, result = dim(operand, dimension). सीमेंटिक का संबंध सिर्फ़ आकार से संबंधित है का एक हिस्सा है. एलिमेंट का टाइप कुछ भी हो सकता है.

इनपुट

लेबल नाम टाइप कंस्ट्रेंट
(I1) operand टेंसर या क्वांटाइज़्ड टेंसर (सी1)
(I2) dimension si64 टाइप का कॉन्स्टेंट (सी1)

आउटपुट

नाम टाइप
result si32 टाइप का 0-डाइमेंशन वाला टेंसर

कंस्ट्रेंट

  • (C1) 0 <= dimension < rank(operand).

उदाहरण

// %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

सिमैंटिक

operand टपल की index स्थिति पर एलिमेंट निकालता है और नतीजे के रूप में result. औपचारिक तौर पर, result = operand[index].

इनपुट

लेबल नाम टाइप कंस्ट्रेंट
(I1) operand टपल (C1), (C2)
(I2) index si32 टाइप का कॉन्स्टेंट (C1), (C2)

आउटपुट

नाम टाइप कंस्ट्रेंट
result काम करने वाला कोई भी टाइप (सी2)

कंस्ट्रेंट

  • (C1) 0 <= index < size(operand).
  • (C2) type(result) = tuple_element_types(operand)[index].

उदाहरण

// %operand: ([1.0, 2.0], (3))
  index = 0 : i32
} : (tuple<tensor<2xf32>, tuple<tensor<i32>>>) -> tensor<2xf32>
// %result: [1.0, 2.0]

ज़्यादा उदाहरण

अगर

सिमैंटिक

true_branch से सिर्फ़ एक फ़ंक्शन चलाने पर आउटपुट मिलता है या pred की वैल्यू के आधार पर false_branch. औपचारिक तौर पर, result = pred ? true_branch() : false_branch().

इनपुट

लेबल नाम टाइप कंस्ट्रेंट
(I1) pred i1 टाइप का 0-डाइमेंशन वाला टेंसर
(I2) true_branch फ़ंक्शन (सी1-सी3)
(I3) false_branch फ़ंक्शन (C1), (C2)

आउटपुट

नाम टाइप कंस्ट्रेंट
results टेंसर की वैरायडिक संख्या, क्वांटाइज़ किए गए टेंसर या टोकन (सी3)

कंस्ट्रेंट

  • (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).

उदाहरण

// %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

ज़्यादा उदाहरण

Imag

सिमैंटिक

एलिमेंट के हिसाब से, operand से काल्पनिक हिस्से को एक्सट्रैक्ट करता है और नतीजे के तौर पर result टेंसर. औपचारिक तौर पर, हर एलिमेंट x के लिए: imag(x) = is_complex(x) ? imaginary_part(x) : constant(0, element_type(result)).

इनपुट

लेबल नाम टाइप कंस्ट्रेंट
(I1) operand फ़्लोटिंग-पॉइंट या कॉम्प्लेक्स टाइप का टेंसर (C1), (C2)

आउटपुट

नाम टाइप कंस्ट्रेंट
result फ़्लोटिंग-पॉइंट टाइप का टेंसर (C1), (C2)

कंस्ट्रेंट

  • (C1) shape(result) = shape(operand).
  • (C2) element_type(result) को इस तरह परिभाषित किया गया है:
    • अगर is_complex(operand) है, तो complex_element_type(element_type(operand)).
    • अगर ऐसा नहीं है, तो element_type(operand).

उदाहरण

// %operand: [(1.0, 2.0), (3.0, 4.0)]
%result = "stablehlo.imag"(%operand) : (tensor<2xcomplex<f32>>) -> tensor<2xf32>
// %result: [2.0, 4.0]

ज़्यादा उदाहरण

इनफ़ीड

सिमैंटिक

इनफ़ीड के डेटा को पढ़ता है और results जनरेट करता है.

infeed_config के सीमैंटिक को लागू किया जाता है.

results में पेलोड मान पहले आने वाले पेलोड मान और आने वाले टोकन होते हैं अंतिम. आने वाले समय में, हमारी योजना पेलोड और टोकन को दो हिस्सों में बांटने की है साफ़ तौर पर जानकारी देने के लिए, अलग-अलग आउटपुट (#670).

इनपुट

लेबल नाम टाइप
(I1) token token
(I2) infeed_config string टाइप का कॉन्स्टेंट

आउटपुट

नाम टाइप कंस्ट्रेंट
results टेंसर की वैरायडिक संख्या, क्वांटाइज़ किए गए टेंसर या टोकन (सी1-सी3)

कंस्ट्रेंट

  • (C1) 0 < size(results).
  • (C2) is_empty(result[:-1]) या is_tensor(type(results[:-1])).
  • (C3) is_token(type(results[-1])).

उदाहरण

// %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]]

ज़्यादा उदाहरण

आईओटा

सिमैंटिक

output टेंसर को शून्य से शुरू होने वाले बढ़ते क्रम में वैल्यू से भरता है iota_dimension डाइमेंशन के साथ. औपचारिक तौर पर,

output[output_index] = constant(is_quantized(output) ? quantize(output_index[iota_dimension], element_type(output)) : output_index[iota_dimension], element_type(output)).

इनपुट

लेबल नाम टाइप कंस्ट्रेंट
(I1) iota_dimension si64 (सी1)

आउटपुट

नाम टाइप कंस्ट्रेंट
output इंटीजर, फ़्लोटिंग-पॉइंट या कॉम्प्लेक्स टाइप या हर टेंसर क्वांटाइज़्ड टेंसर का टेंसर (सी1)

कंस्ट्रेंट

  • (C1) 0 <= iota_dimension < rank(output).

उदाहरण

%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

सिमैंटिक

एलिमेंट के हिसाब से जांच करता है कि x की वैल्यू सीमित है या नहीं (यानी दोनों में से कोई भी वैल्यू नहीं है) +Inf, -Inf, या NaN) और y टेंसर नहीं बनाता है. isFinite लागू करता है आईईईई-754 स्पेसिफ़िकेशन के मुताबिक काम करती है. क्वांटिफ़ाइड टाइप के लिए नतीजा यह होता है हमेशा true.

इनपुट

लेबल नाम टाइप कंस्ट्रेंट
(I1) x फ़्लोटिंग-पॉइंट टाइप या हर टेंसर क्वांटाइज़्ड टेंसर का टेंसर (सी1)

आउटपुट

नाम टाइप कंस्ट्रेंट
y बूलियन टाइप का टेंसर (सी1)

कंस्ट्रेंट

  • (C1) shape(x) = shape(y).

उदाहरण

// 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

सिमैंटिक

operand टेंसर पर एलिमेंट के हिसाब से लॉगारिद्म (लघुगणक) की कार्रवाई करता है और इससे result टेंसर. एलिमेंट टाइप के आधार पर, ये काम किए जाते हैं:

  • फ़्लोट के लिए: IEEE-754 से log.
  • सम्मिश्र संख्याओं के लिए: सम्मिश्र लॉगारिद्म.
  • क्वांटाइज़्ड टाइप के लिए: dequantize_op_quantize(log, operand, type(result)).

इनपुट

लेबल नाम टाइप कंस्ट्रेंट
(I1) operand फ़्लोटिंग-पॉइंट या कॉम्प्लेक्स टाइप या हर टेंसर क्वांटाइज़्ड टेंसर का टेंसर (सी1)

आउटपुट

नाम टाइप कंस्ट्रेंट
result फ़्लोटिंग-पॉइंट या कॉम्प्लेक्स टाइप या हर टेंसर क्वांटाइज़्ड टेंसर का टेंसर (सी1)

कंस्ट्रेंट

  • (C1) baseline_type(operand) = baseline_type(result).

उदाहरण

// %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

सिमैंटिक

operand टेंसर और एलिमेंट के हिसाब से लॉगारिद्म (लघुगणक) और एक संक्रिया करता है result टेंसर बनाता है. एलिमेंट टाइप के आधार पर, ये काम किए जाते हैं:

  • फ़्लोट के लिए: IEEE-754 से logp1.
  • सम्मिश्र संख्याओं के लिए: सम्मिश्र लॉगारिद्म प्लस वन.
  • क्वांटाइज़्ड टाइप के लिए: dequantize_op_quantize(log_plus_one, operand, type(result)).

इनपुट

लेबल नाम टाइप कंस्ट्रेंट
(I1) operand फ़्लोटिंग-पॉइंट या कॉम्प्लेक्स टाइप या हर टेंसर क्वांटाइज़्ड टेंसर का टेंसर (सी1)

आउटपुट

नाम टाइप कंस्ट्रेंट
result फ़्लोटिंग-पॉइंट या कॉम्प्लेक्स टाइप या हर टेंसर क्वांटाइज़्ड टेंसर का टेंसर (सी1)

कंस्ट्रेंट

  • (C1) baseline_type(operand) = baseline_type(result).

उदाहरण

// %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]

ज़्यादा उदाहरण

लॉजिस्टिक

सिमैंटिक

operand टेंसर पर एलिमेंट के हिसाब से लॉजिस्टिक ऑपरेशन करता है और result टेंसर. एलिमेंट टाइप के आधार पर, ये काम किए जाते हैं:

  • फ़्लोट के लिए: IEEE-754 से division(1, addition(1, exp(-x))).
  • कॉम्प्लेक्स लॉजिस्टिक के लिए: कॉम्प्लेक्स लॉजिस्टिक.
  • क्वांटाइज़्ड टाइप के लिए: dequantize_op_quantize(logistic, operand, type(result)).

इनपुट

लेबल नाम टाइप कंस्ट्रेंट
(I1) operand फ़्लोटिंग-पॉइंट या कॉम्प्लेक्स टाइप या हर टेंसर क्वांटाइज़्ड टेंसर का टेंसर (सी1)

आउटपुट

नाम टाइप कंस्ट्रेंट
result फ़्लोटिंग-पॉइंट या कॉम्प्लेक्स टाइप या हर टेंसर क्वांटाइज़्ड टेंसर का टेंसर (सी1)

कंस्ट्रेंट

  • (C1) baseline_type(operand) = baseline_type(result).

उदाहरण

// %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]]

ज़्यादा उदाहरण

मैप

सिमैंटिक

dimensions और के साथ-साथ inputs पर मैप फ़ंक्शन computation लागू करता है result टेंसर बनाता है.

औपचारिक तौर पर, result[result_index] = computation(inputs...[result_index]).

इनपुट

लेबल नाम टाइप कंस्ट्रेंट
(I1) inputs टेंसर की वैरायडिक संख्या या हर टेंसर की क्वांटाइज़्ड टेंसर की संख्या (सी1-सी4)
(I2) dimensions si64 टाइप का 1-डाइमेंशन टेंसर कॉन्सटेंट (सी3)
(I3) computation फ़ंक्शन (सी4)

आउटपुट

नाम टाइप कंस्ट्रेंट
result टेंसर या हर टेन्सर क्वांटाइज़्ड टेंसर (C1), (C4)

कंस्ट्रेंट

  • (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'> है जहां Ei = element_type(inputs[i]) और E' = element_type(result) हैं.

उदाहरण

// %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]]

ज़्यादा उदाहरण

ज़्यादा से ज़्यादा

सिमैंटिक

टेंसर lhs और rhs पर एलिमेंट के हिसाब से सबसे बड़ी कार्रवाई करता है और नतीजे के तौर पर result टेंसर. एलिमेंट टाइप के आधार पर, ये काम किए जाते हैं:

  • बूलियन के लिए: लॉजिकल OR.
  • पूर्णांकों के लिए: ज़्यादा से ज़्यादा पूर्णांक.
  • फ़्लोट के लिए: IEEE-754 से maximum.
  • सम्मिश्र संख्याओं के लिए: (real, imaginary) पेयर के लिए लेक्सिकोग्राफ़िक ज़्यादा से ज़्यादा. जटिल संख्याओं को क्रम से लगाने में हैरान करने वाले सिमैंटिक, इसलिए, आने वाले समय में हम कॉम्प्लेक्स नंबर की सुविधा को बंद करने की योजना बना रहे हैं. इस कार्रवाई के लिए (#560).
  • क्वांटाइज़्ड टाइप के लिए:
    • dequantize_op_quantize(maximum, lhs, rhs, type(result)).

इनपुट

लेबल नाम टाइप कंस्ट्रेंट
(I1) lhs टेंसर या हर टेन्सर क्वांटाइज़्ड टेंसर (सी1)
(I2) rhs टेंसर या हर टेन्सर क्वांटाइज़्ड टेंसर (सी1)

आउटपुट

नाम टाइप कंस्ट्रेंट
result टेंसर या हर टेन्सर क्वांटाइज़्ड टेंसर (सी1)

कंस्ट्रेंट

  • (C1) baseline_type(lhs) = baseline_type(rhs) = baseline_type(result).

उदाहरण

// %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]]

ज़्यादा उदाहरण

कम से कम

सिमैंटिक

टेंसर lhs और rhs पर एलिमेंट के हिसाब से कम से कम संक्रिया करता है और इससे result टेंसर. एलिमेंट टाइप के आधार पर, ये काम किए जाते हैं:

  • बूलियन के लिए: लॉजिकल AND.
  • पूर्णांकों के लिए: कम से कम पूर्णांक.
  • फ़्लोट के लिए: IEEE-754 से minimum.
  • कॉम्प्लेक्स नंबर के लिए: (real, imaginary) पेयर के लिए कम से कम लेक्सिकोग्राफ़िक. जटिल संख्याओं को क्रम से लगाने में हैरान करने वाले सिमैंटिक, इसलिए, आने वाले समय में हम कॉम्प्लेक्स नंबर की सुविधा को बंद करने की योजना बना रहे हैं. इस कार्रवाई के लिए (#560).
  • क्वांटाइज़्ड टाइप के लिए:
    • dequantize_op_quantize(minimum, lhs, rhs, type(result)).

इनपुट

लेबल नाम टाइप कंस्ट्रेंट
(I1) lhs टेंसर या हर टेन्सर क्वांटाइज़्ड टेंसर (सी1)
(I2) rhs टेंसर या हर टेन्सर क्वांटाइज़्ड टेंसर (सी1)

आउटपुट

नाम टाइप कंस्ट्रेंट
result टेंसर या हर टेन्सर क्वांटाइज़्ड टेंसर (सी1)

कंस्ट्रेंट

  • (C1) baseline_type(lhs) = baseline_type(rhs) = baseline_type(result).

उदाहरण

// %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]]

ज़्यादा उदाहरण

गुणा

सिमैंटिक

दो टेंसर lhs और rhs के एलिमेंट के हिसाब से गुणनफल करता है और result टेंसर. एलिमेंट टाइप के आधार पर, ये काम किए जाते हैं:

  • बूलियन के लिए: लॉजिकल AND.
  • पूर्णांकों के लिए: पूर्णांक का गुणा करना.
  • फ़्लोट के लिए: IEEE-754 से multiplication.
  • सम्मिश्र संख्याओं के लिए: जटिल गुणा करना.
  • क्वांटाइज़्ड टाइप के लिए:
    • dequantize_op_quantize(multiply, lhs, rhs, type(result)).

इनपुट

लेबल नाम टाइप कंस्ट्रेंट
(I1) lhs टेंसर या हर टेन्सर क्वांटाइज़्ड टेंसर (सी1)
(I2) rhs टेंसर या हर टेन्सर क्वांटाइज़्ड टेंसर (सी1)

आउटपुट

नाम टाइप कंस्ट्रेंट
result टेंसर या हर टेन्सर क्वांटाइज़्ड टेंसर (सी1)

कंस्ट्रेंट

  • (C1) baseline_type(operand) = baseline_type(result).

उदाहरण

// %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]]

ज़्यादा उदाहरण

निगेट

सिमैंटिक

operand टेंसर के एलिमेंट के हिसाब से निगेशन करता है और result बनाता है टेंसर. एलिमेंट टाइप के आधार पर, ये काम किए जाते हैं:

  • साइन किए गए पूर्णांकों के लिए: पूर्णांक निगेशन.
  • साइन नहीं किए गए पूर्णांकों के लिए: बिटकास्ट से हस्ताक्षर किए गए पूर्णांक, पूर्णांक निगेशन, बिटकास्ट साइन नहीं किए गए पूर्णांक पर वापस जाएं.
  • फ़्लोट के लिए: IEEE-754 से negate.
  • कॉम्प्लेक्स निगेशन के लिए: कॉम्प्लेक्स निगेशन.
  • क्वांटाइज़्ड टाइप के लिए: dequantize_op_quantize(negate, operand, type(result)).

इनपुट

लेबल नाम टाइप कंस्ट्रेंट
(I1) operand इंटीजर, फ़्लोटिंग-पॉइंट या कॉम्प्लेक्स टाइप या हर टेंसर क्वांटाइज़्ड टेंसर का टेंसर (सी1)

आउटपुट

नाम टाइप कंस्ट्रेंट
result इंटीजर, फ़्लोटिंग-पॉइंट या कॉम्प्लेक्स टाइप या हर टेंसर क्वांटाइज़्ड टेंसर का टेंसर (सी1)

कंस्ट्रेंट

  • (C1) baseline_type(operand) = baseline_type(result).

उदाहरण

// 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]

ज़्यादा उदाहरण

नहीं

सिमैंटिक

टेंसर operand के एलिमेंट के हिसाब से परफ़ॉर्म करता है और result टेंसर बनाता है. एलिमेंट टाइप के आधार पर, ये काम किए जाते हैं:

  • बूलियन के लिए: लॉजिकल NOT.
  • पूर्णांक के लिए: बिट के अनुसार NOT.

तर्क

नाम टाइप कंस्ट्रेंट
operand बूलियन या पूर्णांक टाइप का टेंसर (सी1)

आउटपुट

नाम टाइप कंस्ट्रेंट
result बूलियन या पूर्णांक टाइप का टेंसर (सी1)

कंस्ट्रेंट

  • (C1) type(operand) = type(result).

उदाहरण

// 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

सिमैंटिक

यह पक्का करता है कि operand बनाने वाले ऑपरेशन, ऐसी कार्रवाइयां जो result पर निर्भर होती हैं और कंपाइलर के ट्रांसफ़ॉर्मेशन को रोकती हैं एक जगह से दूसरी जगह पर जाने से रोका जा सकता है. इसके अलावा, यह ऑपरेशन है कोई पहचान, उदाहरण result = operand.

तर्क

नाम टाइप कंस्ट्रेंट
operand टेंसर की वैरायडिक संख्या, हर टेंसर की क्वांटाइज़ किए गए टेंसर या टोकन (सी1)

आउटपुट

नाम टाइप कंस्ट्रेंट
result टेंसर की वैरायडिक संख्या, हर टेंसर की क्वांटाइज़ किए गए टेंसर या टोकन (सी1)

कंस्ट्रेंट

  • (C1) type(operand...) = type(result...).

उदाहरण

// %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

ज़्यादा उदाहरण

या

सिमैंटिक

दो टेंसर lhs और rhs के एलिमेंट के हिसाब से OR करता है और result जनरेट करता है टेंसर. एलिमेंट टाइप के आधार पर, ये काम किए जाते हैं:

  • बूलियन के लिए: लॉजिकल OR.
  • पूर्णांक के लिए: बिट के अनुसार OR.

इनपुट

लेबल नाम टाइप कंस्ट्रेंट
(I1) lhs पूर्णांक या बूलियन टाइप का टेंसर (सी1)
(I2) rhs पूर्णांक या बूलियन टाइप का टेंसर (सी1)

आउटपुट

नाम टाइप कंस्ट्रेंट
result पूर्णांक या बूलियन टाइप का टेंसर (सी1)

कंस्ट्रेंट

  • (C1) type(lhs) = type(rhs) = type(result).

उदाहरण

// 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]]

ज़्यादा उदाहरण

आउटफ़ीड

सिमैंटिक

आउटफ़ीड में inputs लिखता है और result टोकन बनाता है.

outfeed_config के सीमैंटिक को लागू किया जाता है.

इनपुट

लेबल नाम टाइप
(I1) inputs टेंसर या क्वांटाइज़्ड टेंसर की वैरायड संख्या
(I2) token token
(I3) outfeed_config string टाइप का कॉन्स्टेंट

आउटपुट

नाम टाइप
result token

उदाहरण

%result = "stablehlo.outfeed"(%input0, %token) {
  outfeed_config = ""
} : (tensor<2x2x2xi64>, !stablehlo.token) -> !stablehlo.token

ज़्यादा उदाहरण

पैड

सिमैंटिक

टेंसर के आस-पास पैडिंग के साथ-साथ एलिमेंट के बीच में, operand को बड़ा करता है दिए गए padding_value के साथ टेंसर का मान.

edge_padding_low और edge_padding_high से जोड़ी गई पैडिंग (जगह) की जानकारी मिलती है सबसे कम वैल्यू पर (इंडेक्स 0 के बगल में) और हाई-एंड (सबसे ज़्यादा इंडेक्स के बगल में) पर हर डाइमेंशन का इस्तेमाल करती हैं. पैडिंग (जगह) की मात्रा नेगेटिव हो सकती है, जहां नेगेटिव पैडिंग की कुल वैल्यू से पता चलता है कि कितने एलिमेंट हटाए जाने हैं डाइमेंशन से बाहर रखा गया है.

interior_padding से, इन दोनों के बीच जोड़ी जाने वाली पैडिंग (जगह) की जानकारी मिलती है एलिमेंट शामिल करना है जो नेगेटिव नहीं हो सकते. अंदर की पैडिंग होती है किनारे की पैडिंग के पहले इस तरह से रखें कि नेगेटिव एज पैडिंग, टारगेटिंग से एलिमेंट को हटा देगी एक ही पैरामीटर के तौर पर जोड़ा जाता है.

औपचारिक तौर पर, result[result_index] को इस तरह परिभाषित किया गया है:

  • operand[operand_index] अगर result_index = edge_padding_low + operand_index * (interior_padding + 1).
  • अगर ऐसा नहीं है, तो padding_value.

इनपुट

लेबल नाम टाइप कंस्ट्रेंट
(I1) operand टेंसर या हर टेन्सर क्वांटाइज़्ड टेंसर (C1), (C2), (C4)
(I2) padding_value 0-डाइमेंशन वाला टेंसर या हर टेंसर क्वांटाइज़्ड टेंसर (सी1)
(I3) edge_padding_low si64 टाइप का 1-डाइमेंशन टेंसर कॉन्सटेंट (C1), (C4)
(आई4) edge_padding_high si64 टाइप का 1-डाइमेंशन टेंसर कॉन्सटेंट (C1), (C4)
(I5) interior_padding si64 टाइप का 1-डाइमेंशन टेंसर कॉन्सटेंट (सी2-सी4)

आउटपुट

नाम टाइप कंस्ट्रेंट
result टेंसर या हर टेन्सर क्वांटाइज़्ड टेंसर (सी3-सी6)

कंस्ट्रेंट

  • (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.

उदाहरण

// %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

सिमैंटिक

इससे मौजूदा प्रोसेस का partition_id बनता है.

आउटपुट

नाम टाइप
result ui32 टाइप का 0-डाइमेंशन वाला टेंसर

उदाहरण

%result = "stablehlo.partition_id"() : () -> tensor<ui32>

ज़्यादा उदाहरण

पॉप सीएनटी

सिमैंटिक

operand टेंसर में सेट किए गए बिट की संख्या की एलिमेंट के हिसाब से गिनती करता है और result टेंसर बनाता है.

इनपुट

लेबल नाम टाइप कंस्ट्रेंट
(I1) operand पूर्णांक टाइप का टेंसर (सी1)

आउटपुट

नाम टाइप कंस्ट्रेंट
result पूर्णांक टाइप का टेंसर (सी1)

कंस्ट्रेंट

  • (C1) type(operand) = type(result).

उदाहरण

// %operand: [0, 1, 2, 127]
%result = "stablehlo.popcnt"(%operand) : (tensor<4xi64>) -> tensor<4xi64>
// %result: [0, 1, 1, 7]

ज़्यादा उदाहरण

पावर

सिमैंटिक

lhs टेंसर से rhs टेंसर और एलिमेंट के हिसाब से एक्सपोनेंशिएट करता है result टेंसर बनाता है. एलिमेंट टाइप के आधार पर, ये काम किए जाते हैं:

  • पूर्णांकों के लिए: पूर्णांक घातांक.
  • फ़्लोट के लिए: IEEE-754 से pow.
  • सम्मिश्र संख्याओं के लिए: सम्मिश्र घातांक.
  • क्वांटाइज़्ड टाइप के लिए: dequantize_op_quantize(power, lhs, rhs, type(result)).

इनपुट

लेबल नाम टाइप कंस्ट्रेंट
(I1) lhs इंटीजर, फ़्लोटिंग-पॉइंट या कॉम्प्लेक्स टाइप या हर टेंसर क्वांटाइज़्ड टेंसर का टेंसर (सी1)
(I2) rhs इंटीजर, फ़्लोटिंग-पॉइंट या कॉम्प्लेक्स टाइप या हर टेंसर क्वांटाइज़्ड टेंसर का टेंसर (सी1)

आउटपुट

नाम टाइप कंस्ट्रेंट
result इंटीजर, फ़्लोटिंग-पॉइंट या कॉम्प्लेक्स टाइप या हर टेंसर क्वांटाइज़्ड टेंसर का टेंसर (सी1)

कंस्ट्रेंट

  • (C1) baseline_type(operand) = baseline_type(result).

उदाहरण

// %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]

ज़्यादा उदाहरण

रीयल

सिमैंटिक

operand से एलिमेंट के हिसाब से, रीयल पार्ट निकालता है और result बनाता है टेंसर. औपचारिक तौर पर, हर एलिमेंट x के लिए: real(x) = is_complex(x) ? real_part(x) : x.

इनपुट

लेबल नाम टाइप कंस्ट्रेंट
(I1) operand फ़्लोटिंग-पॉइंट या कॉम्प्लेक्स टाइप का टेंसर (C1), (C2)

आउटपुट

नाम टाइप कंस्ट्रेंट
result फ़्लोटिंग-पॉइंट टाइप का टेंसर (C1), (C2)

कंस्ट्रेंट

  • (C1) shape(result) = shape(operand).
  • (C2) element_type(result) को इस तरह परिभाषित किया गया है:
    • अगर is_complex(operand) है, तो complex_element_type(element_type(operand)).
    • अगर ऐसा नहीं है, तो element_type(operand).

उदाहरण

// %operand: [(1.0, 2.0), (3.0, 4.0)]
%result = "stablehlo.real"(%operand) : (tensor<2xcomplex<f32>>) -> tensor<2xf32>
// %result: [1.0, 3.0]

ज़्यादा उदाहरण

रेवेन्यू

सिमैंटिक

channel_id वाले चैनल से डेटा हासिल करता है और results जनरेट करता है.

अगर is_host_transfer true है, तो कार्रवाई होस्ट. ऐसा न होने पर, यह दूसरे डिवाइस से डेटा ट्रांसफ़र करता है. इसका क्या मतलब है लागू किया जाना चाहिए. यह फ़्लैग इसमें दी गई जानकारी का डुप्लीकेट बनाता है channel_type, इसलिए भविष्य में हम उनमें से केवल एक को रखने की योजना बना रहे हैं (#666).

results में पेलोड मान पहले आने वाले पेलोड मान और आने वाले टोकन होते हैं अंतिम. आने वाले समय में, हमारी योजना पेलोड और टोकन को दो हिस्सों में बांटने की है साफ़ तौर पर जानकारी देने के लिए, अलग-अलग आउटपुट (#670).

इनपुट

लेबल नाम टाइप कंस्ट्रेंट
(I1) token token (सी4)
(I2) channel_id si64 टाइप का कॉन्स्टेंट
(I3) channel_type DEVICE_TO_DEVICE और HOST_TO_DEVICE का enum (सी1)
(आई4) is_host_transfer i1 टाइप का कॉन्स्टेंट (सी1)

आउटपुट

नाम टाइप कंस्ट्रेंट
results टेंसर की वैरायडिक संख्या, क्वांटाइज़ किए गए टेंसर या टोकन (सी2-सी4)

कंस्ट्रेंट

  • (C1) channel_type को इस तरह परिभाषित किया गया है:
    • अगर is_host_transfer = true है, तो HOST_TO_DEVICE,
    • अगर ऐसा नहीं है, तो DEVICE_TO_DEVICE.
  • (C2) 0 < size(results).
  • (C3) is_empty(result[:-1]) या is_tensor(type(results[:-1])).
  • (C4) is_token(type(results[-1])).

उदाहरण

%results0, %results1 = "stablehlo.recv"(%token) {
  channel_handle = #stablehlo.channel_handle<handle = 1, type = 3>,
  is_host_transfer = true
} : (!stablehlo.token) -> (tensor<2x2xi64>, !stablehlo.token)

ज़्यादा उदाहरण

कम करें

सिमैंटिक

लघुकरण फ़ंक्शन body को inputs और init_values पर लागू करता है dimensions और results टेंसर बनाता है.

कमी का क्रम लागू करने का तरीका तय होता है. इसका मतलब है कि body और init_values को एक मोनोइड बनाना चाहिए, ताकि यह पक्का किया जा सके कि ऑपरेशन से सभी इनपुट के लिए एक जैसे नतीजे मिलेंगे. हालांकि, यह शर्त कई लोकप्रिय गिरावटों के लिए उपलब्ध नहीं होता है. उदाहरण के लिए, फ़्लोटिंग-पॉइंट जोड़ init_values के लिए body और शून्य वास्तव में मोनोइड नहीं बनाते, क्योंकि फ़्लोटिंग-पॉइंट को जोड़ना असोसिएशन से जुड़ा नहीं है.

ज़्यादा औपचारिक तौर पर, results...[j0, ..., jR-1] = reduce(input_slices_converted) जहां:

  • input_slices = inputs...[j0, ..., :, ..., jR-1], जहां : डाले गए हैं 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:])...).
  • कुछ बाइनरी ट्री के लिए reduce(input_slices_converted) = exec(schedule) schedule कहां:
    • exec(node) = body(exec(node.left), exec(node.right)).
    • exec(leaf) = leaf.value.
  • schedule, लागू करने के हिसाब से तय किया गया पूरा बाइनरी ट्री है, जिसका ऑर्डर में होता है ट्रैवर्सल में शामिल हैं:
    • input_slices_converted...[index] मान, इसमें सभी index के लिए index_space(input_slices_converted) के बढ़ते क्रम में लेक्सिकोग्राफ़िक क्रम में कुल index.
    • यह एक लागू की जाने वाली रकम के साथ इंटरफ़ेस में है init_values_converted, लागू करने के तय की गई जगहों पर.

इनपुट

लेबल नाम टाइप कंस्ट्रेंट
(I1) inputs टेंसर की वैरायडिक संख्या या हर टेंसर की क्वांटाइज़्ड टेंसर की संख्या (C1-C4), (C6), (C7)
(I2) init_values 0-डाइमेंशन वाले टेंसर या हर टेंसर की क्वांटाइज़्ड टेंसर की वैरायडिक संख्या (C2), (C3)
(I3) dimensions si64 टाइप का 1-डाइमेंशन टेंसर कॉन्सटेंट (C4), (C5), (C7)
(आई4) body फ़ंक्शन (सी6)

आउटपुट

नाम टाइप कंस्ट्रेंट
results टेंसर की वैरायडिक संख्या या हर टेंसर की क्वांटाइज़्ड टेंसर की संख्या (C3), (C7), (C8)

कंस्ट्रेंट

  • (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>, ..., है tensor<EN-1>) -> (tensor<E0>, ..., tensor<EN-1>) कहां is_promotable(element_type(inputs[i]), Ei).
  • (C7) shape(results...) = shape(inputs...) सिर्फ़ डाइमेंशन dimensions से जुड़े inputs... के साइज़ शामिल नहीं किए गए हैं.
  • [0,N) में सभी i के लिए (C8) element_type(results[i]) = Ei.

उदाहरण

// %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

सिमैंटिक

operand के एलिमेंट के हिसाब से कन्वर्ज़न को किसी अन्य फ़्लोटिंग-पॉइंट टाइप में करता है जो exponent_bits और mantissa_bits का इस्तेमाल करता है और मूल फ़ोटो पर वापस जाता है फ़्लोटिंग-पॉइंट टाइप और output टेंसर बनाता है.

ज़्यादा औपचारिक तौर पर:

  • ओरिजनल वैल्यू के मैंटिसा बिट को अपडेट करके, ओरिजनल वैल्यू को राउंड ऑफ़ किया जाता है मान को निकटतम मान का ऐसा मान दें जिसे mantissa_bits के साथ दिखाया जा सकता है. roundToIntegralTiesToEven सिमेंटिक्स.
  • फिर, अगर mantissa_bits, इसके मैंटिसा बिट की संख्या से कम है ओरिजनल वैल्यू है, तो मैंटिसा बिट को mantissa_bits तक छोटा करके रखा जाता है.
  • फिर, अगर मध्यवर्ती परिणाम के एक्सपोनेंट बिट exponent_bits द्वारा दी गई श्रेणी, मध्यवर्ती परिणाम से ओवरफ़्लो होता है इसके लिए, मूल चिह्न का इस्तेमाल करके इनफ़िनिटी या अंडरफ़्लो का इस्तेमाल करके शून्य पर जाएं मूल चिह्न.
  • क्वांटाइज़्ड टाइप के लिए, dequantize_op_quantize( lambda operand: reduce_precision(operand, exponent_bits, mantissa_bits), operand, type(result)) परफ़ॉर्म करता है.

इनपुट

लेबल नाम टाइप कंस्ट्रेंट
(I1) operand फ़्लोटिंग-पॉइंट टाइप या हर टेंसर क्वांटाइज़्ड टेंसर का टेंसर (सी1)
(I2) exponent_bits si32 टाइप का कॉन्स्टेंट (सी2)
(I3) mantissa_bits si32 टाइप का कॉन्स्टेंट (सी3)

आउटपुट

नाम टाइप कंस्ट्रेंट
output फ़्लोटिंग-पॉइंट टाइप या हर टेंसर क्वांटाइज़्ड टेंसर का टेंसर (सी1)

कंस्ट्रेंट

  • (C1) baseline_type(operand) = baseline_type(output).
  • (C2) 1 <= exponent_bits.
  • (C3) 0 <= mantissa_bits.

उदाहरण

// 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

सिमैंटिक

reduce_scatter

StableHLO प्रोसेस ग्रिड में हर प्रोसेस ग्रुप के अंदर, रिडक्शन करता है, हर प्रोसेस के operand टेंसर की वैल्यू पर, computations का इस्तेमाल करके scatter_dimension के साथ कमी के परिणाम को भागों में और स्कैटर में विभाजित करता है result बनाने के लिए अलग-अलग प्रोसेस के बीच के हिस्से.

ऑपरेशन, StableHLO प्रोसेस ग्रिड को process_groups में बांट देता है जो कि इस तरह परिभाषित किया गया है:

  • cross_replica(replica_groups) अभी तक किसी भी व्यक्ति ने चेक इन नहीं किया है अगर channel_id <= 0 and use_global_device_ids = false है.
  • cross_replica_and_partition(replica_groups) अभी तक किसी भी व्यक्ति ने चेक इन नहीं किया है अगर channel_id > 0 and use_global_device_ids = false है.
  • flattened_ids(replica_groups) अभी तक किसी भी व्यक्ति ने चेक इन नहीं किया है अगर channel_id > 0 and use_global_device_ids = true है.

इसके बाद, हर process_group में:

  • 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).
  • result@receiver = parts@sender[receiver_index] में सभी sender process_group पर जहां receiver_index = process_group.index(receiver) है.

इनपुट

लेबल नाम टाइप कंस्ट्रेंट
(I1) operand टेंसर या हर टेन्सर क्वांटाइज़्ड टेंसर (C1), (C2), (C7), (C8)
(I2) scatter_dimension si64 टाइप का कॉन्स्टेंट (C1), (C2), (C8)
(I3) replica_groups si64 टाइप का 2-डाइमेंशन टेंसर कॉन्सटेंट (सी3-सी5)
(आई4) channel_id si64 टाइप का कॉन्स्टेंट (सी6)
(I5) use_global_device_ids i1 टाइप का कॉन्स्टेंट (सी6)
(I6) computation फ़ंक्शन (सी7)

आउटपुट

नाम टाइप कंस्ट्रेंट
result टेंसर या हर टेन्सर क्वांटाइज़्ड टेंसर (सी8-सी9)

कंस्ट्रेंट

  • (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) को इस तरह परिभाषित किया गया है:
    • अगर cross_replica का इस्तेमाल किया जाता है, तो num_replicas.
    • अगर cross_replica_and_partition का इस्तेमाल किया जाता है, तो num_replicas.
    • अगर flattened_ids का इस्तेमाल किया जाता है, तो num_processes.
  • (C5) 0 <= replica_groups < size(replica_groups).
  • (C6) अगर use_global_device_ids = true है, तो channel_id > 0.
  • (C7) computation का टाइप (tensor<E>, tensor<E>) -> (tensor<E>) है, जहां is_promotable(element_type(operand), E).
  • (C8) shape(result) = shape(operand) को छोड़कर:
    • dim(result, scatter_dimension) = dim(operand, scatter_dimension) / dim(process_groups, 1).
  • (C9) element_type(result) = E.

उदाहरण

// 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

सिमैंटिक

inputs और init_values की विंडो पर रिडक्शन फ़ंक्शन body लागू करता है और results प्रोडक्शन करता है.

यहां दिए गए डायग्राम में दिखाया गया है कि results... में एलिमेंट का हिसाब कैसे लगाया जाता है inputs... पर जाकर, एक अच्छे उदाहरण का इस्तेमाल करें.

reduce_window

औपचारिक तौर पर, results...[result_index] = reduce(windows, init_values, axes(inputs...), body) अभी तक किसी भी व्यक्ति ने चेक इन नहीं किया है (कम करें देखें) कहां:

  • 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).

इनपुट

लेबल नाम टाइप कंस्ट्रेंट
(I1) inputs टेंसर की वैरायडिक संख्या या हर टेंसर की क्वांटाइज़्ड टेंसर की संख्या (C1-C4), (C6), (C8), (C10), (C12), (C13), (C15)
(I2) init_values 0-डाइमेंशन वाले टेंसर या हर टेंसर की क्वांटाइज़्ड टेंसर की वैरायडिक संख्या (C1), (C13)
(I3) window_dimensions si64 टाइप का 1-डाइमेंशन टेंसर कॉन्सटेंट (C4), (C5), (C15)
(आई4) window_strides si64 टाइप का 1-डाइमेंशन टेंसर कॉन्सटेंट (C6), (C7), (C15)
(I5) base_dilations si64 टाइप का 1-डाइमेंशन टेंसर कॉन्सटेंट (C8), (C9), (C15)
(I6) window_dilations si64 टाइप का 1-डाइमेंशन टेंसर कॉन्सटेंट (C10), (C11), (C15)
(I7) padding si64 टाइप का 2-डाइमेंशन टेंसर कॉन्सटेंट (C12), (C15)
(I8) body फ़ंक्शन (सी13)

आउटपुट

नाम टाइप कंस्ट्रेंट
results टेंसर की वैरायडिक संख्या या हर टेंसर की क्वांटाइज़्ड टेंसर की संख्या (C1), (C14-C16)

कंस्ट्रेंट

  • (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>, ..., है tensor<EN-1>) -> (tensor<E0>, ..., tensor<EN-1>) कहां is_promotable(element_type(inputs[i]), Ei).
  • (C14) same(shape(results...)).
  • (C15) shape(results[0]) = num_windows जहां:
    • 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) में सभी i के लिए element_type(results[i]) = Ei.

उदाहरण

// %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]]

ज़्यादा उदाहरण

शेष

सिमैंटिक

भाज्य lhs और भाजक rhs के टेन्सर और भाजक के एलिमेंट के अनुसार शेषफल के आधार पर फ़ंक्शन करता है result टेंसर बनाता है.

औपचारिक रूप से, परिणाम का चिह्न भाज्यों से लिया जाता है और नतीजे का निरपेक्ष मान हमेशा भाजक के निरपेक्ष मान से कम होता है. बाकी बचे पैसों की गिनती lhs - d * rhs के रूप में की जाती है, जहां d इससे दी जाती है:

  • पूर्णांकों के लिए: stablehlo.divide(lhs, rhs).
  • फ़्लोट के लिए: राउंडिंग एट्रिब्यूट के साथ IEEE-754 से division(lhs, rhs) roundTowardZero.
  • सम्मिश्र संख्याओं के लिए: TBD (#997).
  • क्वांटाइज़्ड टाइप के लिए:
    • dequantize_op_quantize(remainder, lhs, rhs, type(result)).

फ़्लोटिंग-पॉइंट एलिमेंट टाइप के लिए, यह ऑपरेशन, IEEE-754 स्पेसिफ़िकेशन से remainder ऑपरेशन, जिसमें d एक इंटिग्रल वैल्यू है सम संख्या के साथ lhs/rhs की सटीक वैल्यू के सबसे करीब.

इनपुट

लेबल नाम टाइप कंस्ट्रेंट
(I1) lhs इंटीजर, फ़्लोटिंग-पॉइंट या कॉम्प्लेक्स टाइप या हर टेंसर क्वांटाइज़्ड टेंसर का टेंसर (सी1)
(I2) rhs इंटीजर, फ़्लोटिंग-पॉइंट या कॉम्प्लेक्स टाइप या हर टेंसर क्वांटाइज़्ड टेंसर का टेंसर (सी1)

आउटपुट

नाम टाइप कंस्ट्रेंट
result इंटीजर, फ़्लोटिंग-पॉइंट या कॉम्प्लेक्स टाइप या हर टेंसर क्वांटाइज़्ड टेंसर का टेंसर (सी1)

कंस्ट्रेंट

  • (C1) baseline_type(operand) = baseline_type(result).

उदाहरण

// %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

सिमैंटिक

इससे मौजूदा प्रोसेस का replica_id बनता है.

आउटपुट

नाम टाइप
result ui32 टाइप का 0-डाइमेंशन वाला टेंसर

उदाहरण

%result = "stablehlo.replica_id"() : () -> tensor<ui32>

ज़्यादा उदाहरण

आकार बदलना

सिमैंटिक

operand टेंसर को result टेंसर के आकार देता है. सैद्धांतिक तौर पर, यह कैननिकल निरूपण को एक जैसा बनाए रखता है, लेकिन हो सकता है कि इसमें बदलाव हो सकता है आकार, जैसे tensor<2x3xf32> से tensor<3x2xf32> या tensor<6xf32> तक.

ज़्यादा औपचारिक तौर पर, result[result_index] = operand[operand_index] जहां लेक्सिकोग्राफ़िक में result_index और operand_index की रैंक एक जैसी है index_space(result) और index_space(operand) का ऑर्डर.

इनपुट

लेबल नाम टाइप कंस्ट्रेंट
(I1) operand टेंसर या क्वांटाइज़्ड टेंसर (सी1-सी3)

आउटपुट

नाम टाइप कंस्ट्रेंट
result टेंसर या क्वांटाइज़्ड टेंसर (सी1-सी3)

कंस्ट्रेंट

  • (C1) element_type(result) देने वाली कंपनी:
    • अगर !is_per_axis_quantized(operand) है, तो element_type(operand).
    • element_type(operand), लेकिन quantization_dimension(operand) और ऐसा न होने पर quantization_dimension(result) अलग हो सकती है.
  • (C2) size(operand) = size(result).
  • (C3) अगर is_per_axis_quantized(operand):
    • 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).

उदाहरण

// %operand: [[1, 2, 3], [4, 5, 6]]
%result = "stablehlo.reshape"(%operand) : (tensor<2x3xi32>) -> tensor<3x2xi32>
// %result: [[1, 2], [3, 4], [5, 6]]

ज़्यादा उदाहरण

विपरीत करें

सिमैंटिक

यह तय किए गए dimensions के साथ-साथ, operand में एलिमेंट के क्रम को उलटता है और result टेंसर बनाता है. औपचारिक तौर पर, result[result_index] = operand[operand_index] कहां:

  • operand_index[d] = dim(result, d) - result_index[d] - 1 अभी तक किसी भी व्यक्ति ने चेक इन नहीं किया है अगर dimensions में d है.
  • अगर ऐसा नहीं है, तो operand_index[d] = result_index[d].

इनपुट

लेबल नाम टाइप कंस्ट्रेंट
(I1) operand टेंसर या हर टेन्सर क्वांटाइज़्ड टेंसर (C1), (C3)
(I2) dimensions si64 टाइप का 1-डाइमेंशन टेंसर कॉन्सटेंट (C2), (C3)

आउटपुट

नाम टाइप कंस्ट्रेंट
result टेंसर या हर टेन्सर क्वांटाइज़्ड टेंसर (C1), (C3)

कंस्ट्रेंट

  • (C1) type(operand) = type(result).
  • (C2) is_unique(dimensions).
  • (C3) 0 <= dimensions < rank(result).

उदाहरण

// %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]]

ज़्यादा उदाहरण

आरएनजी

सिमैंटिक

rng_distribution एल्गोरिदम का इस्तेमाल करके, रैंडम नंबर जनरेट करता है और दिए गए आकार shape का result टेंसर.

अगर rng_distribution = UNIFORM है, तो कोई भी नंबर जनरेट होता है [a, b) इंटरवल में यूनिफ़ॉर्म डिस्ट्रिब्यूशन के बाद. अगर a >= b, व्यवहार के बारे में नहीं बताया गया है.

अगर rng_distribution = NORMAL है, तो कोई भी नंबर जनरेट होता है माध्य = a और मानक विचलन = b के साथ सामान्य वितरण के बाद. अगर b < 0, व्यवहार तय नहीं है.

रैंडम नंबर जनरेट करने का सही तरीका, इसे लागू करने के तरीके से तय होता है. इसके लिए उदाहरण के लिए, वे शायद सारणिक हों और नहीं भी, और छिपी हुई स्थिति के लिए.

कई हिस्सेदारों के साथ बातचीत करते समय, यह सेशन असरदार तरीके से की सुविधा उपलब्ध नहीं है. इसलिए, हम आने वाले समय में इसे हटाने की योजना बना रहे हैं (#597).

इनपुट

लेबल नाम टाइप कंस्ट्रेंट
(I1) a पूर्णांक, बूलियन या फ़्लोटिंग-पॉइंट टाइप का 0-डाइमेंशन वाला टेंसर (C1), (C2)
(I2) b पूर्णांक, बूलियन या फ़्लोटिंग-पॉइंट टाइप का 0-डाइमेंशन वाला टेंसर (C1), (C2)
(I3) shape si64 टाइप का 1-डाइमेंशन टेंसर कॉन्सटेंट (सी3)
(आई4) rng_distribution UNIFORM और NORMAL का enum (सी2)

आउटपुट

नाम टाइप कंस्ट्रेंट
result पूर्णांक, बूलियन या फ़्लोटिंग-पॉइंट टाइप का टेंसर (सी1-सी3)

कंस्ट्रेंट

  • (C1) element_type(a) = element_type(b) = element_type(result).
  • (C2) अगर rng_distribution = NORMAL है, तो is_float(a).
  • (C3) shape(result) = shape.

उदाहरण

// %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

सिमैंटिक

यह फ़ंक्शन एक जैसे रैंडम बिट से भरा गया output दिखाता है और आउटपुट की अपडेट की गई स्थिति दिखाता है स्यूडोरैंडम नंबर जनरेटर एल्गोरिदम rng_algorithm का इस्तेमाल करके output_state initial_state को शुरुआती स्थिति दी गई है. आउटपुट की गारंटी दी जाती है initial_state का डिटरमिनिस्टिक फ़ंक्शन, लेकिन इसके होने की गारंटी नहीं है दो अलग-अलग तरीकों से तय किया जा सकता है.

rng_algorithm इनमें से एक है:

  • DEFAULT: लागू करने के लिए तय किया गया एल्गोरिदम.
  • THREE_FRY: Fivefry एल्गोरिदम का लागू करने के बारे में तय किया गया वैरिएंट.*
  • PHILOX: Pilox एल्गोरिदम को लागू करने के लिए तय किया गया वैरिएंट.*

* देखें: सैलमन और अन्य एससी 2011. समानांतर यादृच्छिक संख्याएं: 1, 2, 3 जितनी आसान होती हैं.

इनपुट

लेबल नाम टाइप कंस्ट्रेंट
(I1) rng_algorithm DEFAULT, THREE_FRY, और PHILOX का कुल डेटा (सी2)
(I2) initial_state ui64 टाइप का 1-डाइमेंशन टेंसर (C1), (C2)

आउटपुट

नाम टाइप कंस्ट्रेंट
output_state ui64 टाइप का 1-डाइमेंशन टेंसर (सी1)
output इंटीजर या फ़्लोटिंग-पॉइंट टाइप का टेंसर

कंस्ट्रेंट

  • (C1) type(initial_state) = type(output_state).
  • (C2) size(initial_state) को इस तरह परिभाषित किया गया है:
    • अगर rng_algorithm = DEFAULT है, तो लागू करने के बारे में तय किया जाता है.
    • अगर rng_algorithm = THREE_FRY है, तो 2.
    • अगर rng_algorithm = PHILOX है, तो 2 या 3.

उदाहरण

// %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

सिमैंटिक

निकटतम पूर्णांक की ओर तत्व के अनुसार पूर्णांकन करता है, जिससे संबंध टूट जाते हैं शून्य से, operand टेंसर पर, result टेंसर बनाता है. लागू करता है आईईईई-754 स्पेसिफ़िकेशन से मिली roundToIntegralTiesToAway कार्रवाई. इसके लिए क्वांटाइज़्ड टाइप, परफ़ॉर्मेंस dequantize_op_quantize(round_nearest_afz, operand, type(result)).

इनपुट

लेबल नाम टाइप कंस्ट्रेंट
(I1) operand फ़्लोटिंग-पॉइंट टाइप या हर टेंसर क्वांटाइज़्ड टेंसर का टेंसर (सी1)

आउटपुट

नाम टाइप कंस्ट्रेंट
result फ़्लोटिंग-पॉइंट टाइप या हर टेंसर क्वांटाइज़्ड टेंसर का टेंसर (सी1)

कंस्ट्रेंट

  • (C1) baseline_type(operand) = baseline_type(result).

उदाहरण

// %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

सिमैंटिक

निकटतम पूर्णांक की ओर तत्व के अनुसार पूर्णांकन करता है, जिससे संबंध टूट जाते हैं operand टेंसर पर, सम पूर्णांक की दिशा में result बनाता है टेंसर. आईईईई-754 से roundToIntegralTiesToEven ऑपरेशन लागू करता है स्पेसिफ़िकेशन. क्वांटाइज़्ड टाइप के लिए, dequantize_op_quantize(round_nearest_even, operand, type(result)).

इनपुट

लेबल नाम टाइप कंस्ट्रेंट
(I1) operand फ़्लोटिंग-पॉइंट टाइप या हर टेंसर क्वांटाइज़्ड टेंसर का टेंसर (सी1)

आउटपुट

नाम टाइप कंस्ट्रेंट
result फ़्लोटिंग-पॉइंट टाइप या हर टेंसर क्वांटाइज़्ड टेंसर का टेंसर (सी1)

कंस्ट्रेंट

  • (C1) baseline_type(operand) = baseline_type(result).

उदाहरण

// %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

सिमैंटिक

operand टेंसर पर एलिमेंट के हिसाब से व्युत्क्रम (रिसिप्रोकल स्क्वेयर रूट) कार्रवाई करता है और result टेंसर बनाता है. एलिमेंट टाइप के आधार पर, ये काम किए जाते हैं:

  • फ़्लोट के लिए: IEEE-754 से rSqrt.
  • सम्मिश्र संख्याओं के लिए: सम्मिश्र व्युत्क्रम वर्ग मूल.
  • क्वांटाइज़्ड टाइप के लिए: dequantize_op_quantize(rsqrt, operand, type(result)).

इनपुट

लेबल नाम टाइप कंस्ट्रेंट
(I1) operand फ़्लोटिंग-पॉइंट या कॉम्प्लेक्स टाइप या हर टेंसर क्वांटाइज़्ड टेंसर का टेंसर (सी1)

आउटपुट

नाम टाइप कंस्ट्रेंट
result फ़्लोटिंग-पॉइंट या कॉम्प्लेक्स टाइप या हर टेंसर क्वांटाइज़्ड टेंसर का टेंसर (सी1)

कंस्ट्रेंट

  • (C1) baseline_type(operand) = baseline_type(result).

उदाहरण

// %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]]

ज़्यादा उदाहरण

स्कैटर

सिमैंटिक

results टेंसर बनाता है, जो कि इसे छोड़कर inputs टेंसर के बराबर होते हैं scatter_indices के तय किए गए कई स्लाइस, उनकी वैल्यू के साथ अपडेट किए गए हैं update_computation का इस्तेमाल करके updates.

नीचे दिया गया डायग्राम दिखाता है कि updates... में एलिमेंट, results... पर जाकर, एक अच्छे उदाहरण का इस्तेमाल करें. इस डायग्राम में कुछ उदाहरण दिए गए हैं updates... इंडेक्स और विस्तार से बताता है कि वे कौनसे results... इंडेक्स करते हैं के मुताबिक हैं.

स्कैटर

index_space(updates[0]) में सभी update_index के लिए, औपचारिक तौर पर:

  • 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 को इस तरह से परिभाषित किया गया है:
    • scatter_indices[si0, ..., :, ..., siN], जहां si व्यक्तिगत हैं update_scatter_index और : के तत्वों को index_vector_dim इंडेक्स, अगर index_vector_dim < rank(scatter_indices).
    • अगर ऐसा नहीं है, तो [scatter_indices[update_scatter_index]].
  • axes(inputs[0]) में d_input के लिए,
    • full_start_index[d_input] = start_index[d_start] अगर d_input = scatter_dims_to_operand_dims[d_start].
    • अगर ऐसा नहीं है, तो full_start_index[d_input] = 0.
  • axes(inputs[0]) में d_input के लिए,
    • full_batching_index[d_input] = update_scatter_index[d_start - (d_start < index_vector_dim ? 0 : 1)] अभी तक किसी भी व्यक्ति ने चेक इन नहीं किया है अगर d_input = input_batching_dims[i_batching] और d_start = scatter_indices_batching_dims[i_batching].
    • अगर ऐसा नहीं है, तो full_batching_index[d_input] = 0.
  • update_window_index = update_index[update_window_dims...].
  • full_window_index = [wi0, ..., 0, ..., wiN], जहां wi व्यक्तिगत हैं update_window_index के एलिमेंट का इस्तेमाल किया जाता है और 0 को इंडेक्स में शामिल किया जाता है inserted_window_dims और input_batching_dims.
  • result_index = full_start_index + full_batching_index + full_window_index.

यह देखते हुए, results = exec(schedule, inputs), जहां:

  • schedule, इसका लागू करने के हिसाब से क्रमचय है index_space(updates[0]).
  • exec([update_index, ...], results) = exec([...], updated_results) कहां:
    • अगर result_index, shape(results...) के लिए सीमा के अंदर है
    • updates_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] वाले results की कॉपी है updated_values... पर सेट किया गया.
    • या फिर
    • updated_results = results.
  • exec([], results) = results.

अगर indices_are_sorted, true है, तो लागू करने पर यह मान लिया जा सकता है कि scatter_indices, scatter_dims_to_operand_dims के हिसाब से क्रम से लगाए गए हैं, ऐसा नहीं होता है, तो व्यवहार तय नहीं होता है. ज़्यादा औपचारिक तौर पर, इस तारीख से सभी i1 < i2 indices(result), full_start_index(i1) <= full_start_index(i2).

अगर unique_indices, true है, तो लागू करने पर यह मान लिया जा सकता है कि सभी result_index इंडेक्स का डेटा यूनीक है. अगर unique_indices है true लेकिन बिखरने वाले इंडेक्स अलग-अलग नहीं हैं, तो व्यवहार ऐसा है तय नहीं है.

इनपुट

लेबल नाम टाइप कंस्ट्रेंट
(I1) inputs टेंसर की वैरायडिक संख्या या हर टेंसर की क्वांटाइज़्ड टेंसर की संख्या (C1), (C2), (C4-C6), (C11), (C13), (C18), (C21), (C23-C24)
(I2) scatter_indices पूर्णांक टाइप का टेंसर (C4), (C15), (C19), (C22)
(I3) updates टेंसर की वैरायडिक संख्या या हर टेंसर की क्वांटाइज़्ड टेंसर की संख्या (C3-C6), (C8)
(आई4) update_window_dims si64 टाइप का 1-डाइमेंशन टेंसर कॉन्सटेंट (C2), (C4), (C7-C8)
(I5) inserted_window_dims si64 टाइप का 1-डाइमेंशन टेंसर कॉन्सटेंट (C2), (C4), (C9-C11)
(I6) input_batching_dims si64 टाइप का 1-डाइमेंशन टेंसर कॉन्सटेंट (C2), (C4), (C9), (C12-13), (C17-18), (C20)
(I7) scatter_indices_batching_dims si64 टाइप का 1-डाइमेंशन टेंसर कॉन्सटेंट (C14-C18)
(I8) scatter_dims_to_operand_dims si64 टाइप का 1-डाइमेंशन टेंसर कॉन्सटेंट (C19-C21)
(I9) index_vector_dim si64 टाइप का कॉन्स्टेंट (C4), (C16), (C19), (C22)
(I10) indices_are_sorted i1 टाइप का कॉन्स्टेंट
(I11) unique_indices i1 टाइप का कॉन्स्टेंट
(I12) update_computation फ़ंक्शन (सी23)

आउटपुट

नाम टाइप कंस्ट्रेंट
results टेंसर की वैरायडिक संख्या या हर टेंसर की क्वांटाइज़्ड टेंसर की संख्या (C24-C25)

कंस्ट्रेंट

  • (C1) same(shape(inputs...)).
  • (C2) `रैंक(इनपुट[0]) = साइज़(update_window_dims) + साइज़(inserted_window_dims)
    • size(input_batching_dims)`.
  • (C3) same(shape(updates...)).
  • (C4) shape(updates[0]) = combine(update_scatter_dim_sizes, update_window_dim_sizes) जहां:
    • उसे छोड़कर update_scatter_dim_sizes = shape(scatter_indices) इसके मुताबिक scatter_indices का डाइमेंशन साइज़ index_vector_dim शामिल नहीं है.
    • उसे छोड़कर update_window_dim_sizes <= shape(inputs[0]) inserted_window_dims के अनुरूप inputs[0] में डाइमेंशन आकार और input_batching_dims शामिल नहीं हैं.
    • combine, update_scatter_dim_sizes को इससे जुड़े ऐक्सिस पर लगाता है update_scatter_dims और update_window_dim_sizes से जुड़े ऐक्सिस update_window_dims तक.
  • (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>) है, जहां is_promotable(element_type(inputs[i]), Ei) है.
  • (C24) shape(inputs...) = shape(results...).
  • [0,N) में सभी i के लिए (C25) element_type(results[i]) = Ei.

उदाहरण

// %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]]
//           ]
//          ]

ज़्यादा उदाहरण

चुनें

सिमैंटिक

जहां से हर एलिमेंट on_true से चुना जाता है वहां से result टेंसर बनता है या pred के संबंधित एलिमेंट की वैल्यू पर आधारित on_false टेंसर. ज़्यादा औपचारिक तौर पर, result[result_index] = pred_element ? on_true[result_index] : on_false[result_index], जहां pred_element = rank(pred) = 0 ? pred[] : pred[result_index]. क्वांटाइज़्ड टाइप के लिए, dequantize_select_quantize(pred, on_true, on_false, type(result)).

इनपुट

लेबल नाम टाइप कंस्ट्रेंट
(I1) pred i1 टाइप का टेंसर (सी1)
(I2) on_true टेंसर या हर टेन्सर क्वांटाइज़्ड टेंसर (सी1-सी2)
(I3) on_false टेंसर या हर टेन्सर क्वांटाइज़्ड टेंसर (सी2)

आउटपुट

नाम टाइप कंस्ट्रेंट
result टेंसर या हर टेन्सर क्वांटाइज़्ड टेंसर (सी2)

कंस्ट्रेंट

  • (C1) rank(pred) = 0 or shape(pred) = shape(on_true).
  • (C2) baseline_type(on_true) = baseline_type(on_false) = baseline_type(result).

उदाहरण

// %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

सिमैंटिक

scatter का इस्तेमाल करके, source टेंसर से वैल्यू दिखाता है. ये वैल्यू select का इस्तेमाल करके input टेंसर के reduce_window का नतीजा और इससे मिले नतीजे result टेंसर.

यहां दिए गए डायग्राम में दिखाया गया है कि result में एलिमेंट का हिसाब कैसे लगाया जाता है operand और source को बेहतर तरीके से समझने के लिए, एक अच्छा उदाहरण दिया गया है.

select_and_scatter

ज़्यादा औपचारिक तौर पर:

  • selected_values = reduce_window_without_init(...) में ये इनपुट शामिल हैं:

    • inputs = [operand].
    • window_dimensions, window_strides, और padding का इस्तेमाल पहले किया जा रहा है.
    • base_dilations = windows_dilations = 1.
    • body को इस तरह से परिभाषित किया गया है:
    def body(arg0: tensor<E>, arg1: tensor<E>) -> tensor<E>:
      return select(arg0, arg1) ? arg0 : arg1;
    

    जहां E = element_type(operand) और reduce_window_without_init काम करते हैं बिलकुल reduce_window की तरह, इसमें मौजूदा चीज़ों का schedule शामिल नहीं है reduce (कम करें देखें) में, init वैल्यू शामिल नहीं हैं. फ़िलहाल, ऐसा है यह नहीं बताया गया कि क्या होगा अगर इससे जुड़ी विंडो में वैल्यू नहीं हैं (#731).

  • result[result_index] = reduce([source_values], [init_value], [0], scatter) अभी तक किसी भी व्यक्ति ने चेक इन नहीं किया है कहां:

    • source_values = [source[source_index] for source_index in source_indices].
    • selected_index(source_index) = operand_index अगर selected_values[source_index] में operand एलिमेंट है operand_index से.
    • source_indices = [source_index for source_index in indices(source) if selected_index(source_index) = result_index].

इनपुट

लेबल नाम टाइप कंस्ट्रेंट
(I1) operand टेंसर या हर टेन्सर क्वांटाइज़्ड टेंसर (C1-C4), (C6), (C8-C11)
(I2) source टेंसर या हर टेन्सर क्वांटाइज़्ड टेंसर (C1), (C2)
(I3) init_value 0-डाइमेंशन वाला टेंसर या हर टेंसर क्वांटाइज़्ड टेंसर (सी3)
(आई4) window_dimensions si64 टाइप का 1-डाइमेंशन टेंसर कॉन्सटेंट (C2), (C4), (C5)
(I5) window_strides si64 टाइप का 1-डाइमेंशन टेंसर कॉन्सटेंट (C2), (C6), (C7)
(I6) padding si64 टाइप का 2-डाइमेंशन टेंसर कॉन्सटेंट (C2), (C8)
(I7) select फ़ंक्शन (सी9)
(I8) scatter फ़ंक्शन (C10)

आउटपुट

नाम टाइप कंस्ट्रेंट
result टेंसर या हर टेन्सर क्वांटाइज़्ड टेंसर (C11-C12)

कंस्ट्रेंट

  • (C1) element_type(operand) = element_type(source).
  • (C2) shape(source) = num_windows जहां:
    • 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> है, जहां E = element_type(operand).
  • (C10) scatter का टाइप (tensor<E>, tensor<E>) -> tensor<E> है, जहां is_promotable(element_type(operand), E).
  • (C11) shape(operand) = shape(result).
  • (C12) element_type(result) = E.

उदाहरण

// %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]]

ज़्यादा उदाहरण

भेजें

सिमैंटिक

यह inputs को channel_id चैनल पर भेजता है और result टोकन जनरेट करता है.

अगर is_host_transfer true है, तो ऑपरेशन डेटा को होस्ट. ऐसा न होने पर, यह डेटा को दूसरे डिवाइस पर ट्रांसफ़र कर देता है. इसका क्या मतलब है लागू किया जाना चाहिए. यह फ़्लैग इसमें दी गई जानकारी का डुप्लीकेट बनाता है channel_type, इसलिए भविष्य में हम उनमें से केवल एक को रखने की योजना बना रहे हैं (#666).

इनपुट

लेबल नाम टाइप कंस्ट्रेंट
(I1) inputs टेंसर या क्वांटाइज़्ड टेंसर की वैरायड संख्या
(I2) token token
(I3) channel_id si64 टाइप का कॉन्स्टेंट
(आई4) channel_type DEVICE_TO_DEVICE और DEVICE_TO_HOST का enum (सी1)
(I5) is_host_transfer i1 टाइप का कॉन्स्टेंट (सी1)

आउटपुट

नाम टाइप
result token

कंस्ट्रेंट

  • (C1) channel_type को इस तरह परिभाषित किया गया है:
    • अगर is_host_transfer = true है, तो DEVICE_TO_HOST,
    • अगर ऐसा नहीं है, तो DEVICE_TO_DEVICE.

उदाहरण

%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

सिमैंटिक

lhs टेंसर पर rhs संख्या से एलिमेंट के हिसाब से लेफ़्ट-शिफ़्ट ऑपरेशन करता है बिट का इस्तेमाल करता है और result टेंसर बनाता है.

इनपुट

लेबल नाम टाइप कंस्ट्रेंट
(I1) lhs पूर्णांक टाइप का टेंसर (सी1)
(I2) rhs पूर्णांक टाइप का टेंसर (सी1)

आउटपुट

नाम टाइप कंस्ट्रेंट
result पूर्णांक टाइप का टेंसर (सी1)

कंस्ट्रेंट

  • (C1) type(lhs) = type(rhs) = type(result).

उदाहरण

// %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

सिमैंटिक

lhs टेंसर पर एलिमेंट के हिसाब से अंकगणित के राइट शिफ़्ट ऑपरेशन को ऐसा करता है rhs बिट की संख्या और result टेंसर बनाना.

इनपुट

लेबल नाम टाइप कंस्ट्रेंट
(I1) lhs पूर्णांक टाइप का टेंसर (सी1)
(I2) rhs पूर्णांक टाइप का टेंसर (सी1)

आउटपुट

नाम टाइप कंस्ट्रेंट
result पूर्णांक टाइप का टेंसर (सी1)

कंस्ट्रेंट

  • (C1) type(lhs) = type(rhs) = type(result).

उदाहरण

// %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

सिमैंटिक

lhs टेंसर पर rhs के हिसाब से एलिमेंट के हिसाब से लॉजिकल राइट शिफ़्ट ऑपरेशन करता है बिट की संख्या और result टेंसर बनाता है.

इनपुट

लेबल नाम टाइप कंस्ट्रेंट
(I1) lhs पूर्णांक टाइप का टेंसर (सी1)
(I2) rhs पूर्णांक टाइप का टेंसर (सी1)

आउटपुट

नाम टाइप कंस्ट्रेंट
result पूर्णांक टाइप का टेंसर (सी1)

कंस्ट्रेंट

  • (C1) type(lhs) = type(rhs) = type(result).

उदाहरण

// %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]

ज़्यादा उदाहरण

हस्ताक्षर

सिमैंटिक

एलिमेंट के हिसाब से operand का निशान दिखाता है और result टेंसर बनाता है. औपचारिक तौर पर, हर एलिमेंट x के लिए सिमेंटिक्स को इसका इस्तेमाल करके बताया जा सकता है Python सिंटैक्स इस तरह से है:

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)))

क्वांटाइज़्ड टाइप के लिए, dequantize_op_quantize(sign, operand, type(result)).

इनपुट

लेबल नाम टाइप कंस्ट्रेंट
(I1) operand साइन किए हुए पूर्णांक, फ़्लोटिंग-पॉइंट या कॉम्प्लेक्स टाइप या हर टेंसर क्वांटाइज़्ड टेंसर का टेंसर (सी1)

आउटपुट

नाम टाइप कंस्ट्रेंट
result साइन किए हुए पूर्णांक, फ़्लोटिंग-पॉइंट या कॉम्प्लेक्स टाइप या हर टेंसर क्वांटाइज़्ड टेंसर का टेंसर (सी1)

कंस्ट्रेंट

  • (C1) baseline_type(operand) = baseline_type(result).

उदाहरण

// 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]

ज़्यादा उदाहरण

ज्या

सिमैंटिक

operand टेंसर पर एलिमेंट के हिसाब से साइन (sin) करता है और result बनाता है टेंसर. एलिमेंट टाइप के आधार पर, ये काम किए जाते हैं:

  • फ़्लोट के लिए: IEEE-754 से sin.
  • सम्मिश्र संख्याओं के लिए: सम्मिश्र ज्या.
  • क्वांटाइज़्ड टाइप के लिए: dequantize_op_quantize(sine, operand, type(result)).

इनपुट

लेबल नाम टाइप कंस्ट्रेंट
(I1) operand फ़्लोटिंग-पॉइंट या कॉम्प्लेक्स टाइप या हर टेंसर क्वांटाइज़्ड टेंसर का टेंसर (सी1)

आउटपुट

नाम टाइप कंस्ट्रेंट
result फ़्लोटिंग-पॉइंट या कॉम्प्लेक्स टाइप या हर टेंसर क्वांटाइज़्ड टेंसर का टेंसर (सी1)

कंस्ट्रेंट

  • (C1) baseline_type(operand) = baseline_type(result).

उदाहरण

// %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]]

ज़्यादा उदाहरण

स्‍लाइस

सिमैंटिक

स्टैटिक तरीके से कंप्यूट किए गए शुरुआती इंडेक्स का इस्तेमाल करके, operand से स्लाइस एक्सट्रैक्ट करता है और result टेंसर बनाता है. start_indices में इसके शुरुआती इंडेक्स शामिल हैं स्लाइस, limit_indices में आखिरी इंडेक्स शामिल हैं (खास तौर पर) हर डाइमेंशन के स्लाइस के लिए, और strides में स्ट्राइड होते हैं पैरामीटर का इस्तेमाल करें.

ज़्यादा औपचारिक तौर पर, result[result_index] = operand[operand_index] जहां operand_index = start_indices + result_index * strides.

इनपुट

लेबल नाम टाइप कंस्ट्रेंट
(I1) operand टेंसर या हर टेन्सर क्वांटाइज़्ड टेंसर (C1-C3), (C5)
(I2) start_indices si64 टाइप का 1-डाइमेंशन टेंसर कॉन्सटेंट (C2), (C3), (C5)
(I3) limit_indices si64 टाइप का 1-डाइमेंशन टेंसर कॉन्सटेंट (C2), (C3), (C5)
(आई4) strides si64 टाइप का 1-डाइमेंशन टेंसर कॉन्सटेंट (C2), (C4)

आउटपुट

नाम टाइप कंस्ट्रेंट
result टेंसर या हर टेन्सर क्वांटाइज़्ड टेंसर (C1), (C5)

कंस्ट्रेंट

  • (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).

उदाहरण

// %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]
//           ]

ज़्यादा उदाहरण

क्रम से लगाएं

सिमैंटिक

inputs के 1-डाइमेंशन वाले स्लाइस को, डाइमेंशन dimension के साथ एक साथ क्रम में लगाता है, comparator के हिसाब से और results का प्रोडक्शन होता है.

अन्य कार्रवाइयों में मिलते-जुलते इनपुट के उलट, dimension नेगेटिव वैल्यू की अनुमति देता है, इस्तेमाल करें. आने वाले समय में इसकी अनुमति नहीं दी जाएगी नियमित तौर पर किए जाने की वजह (#1377).

अगर is_stable सही है, तो क्रम स्थिर है, यानी ऐसे एलिमेंट को सुरक्षित रखा जाता है जिन्हें तुलना करने वाले की ज़रूरत होती है. इस मामले के लिए जहां एक ही इनपुट होता है, वहां दो एलिमेंट e1 और e2 माने जाते हैं तुलना करने वाले के बराबर होना चाहिए, अगर comparator(e1, e2) = comparator(e2, e1) = false. फ़ॉर्मलाइज़ेशन यहां देखें के लिए भी इसका इस्तेमाल किया जा सकता है.

index_space(results[0]) में सभी result_index के लिए, औपचारिक तौर पर:

  • adjusted_dimension = dimension >= 0 ? dimension : rank(inputs[0]) + dimension.
  • result_slice = [ri0, ..., :, ..., riR-1], जहां riN व्यक्तिगत हैं result_index के एलिमेंट और : को adjusted_dimension पर डाला गया.
  • inputs_together = (inputs[0]..., ..., inputs[N-1]...).
  • results_together[result_slice] = sort(inputs_together[result_slice], comparator_together).
  • जहां sort 1-डायमेंशनल स्लाइस को गैर-घटते क्रम में क्रम में लगाता है कि comparator_together, true लौटाता है अगर बाईं ओर का तर्क यह है दाईं ओर मौजूद दूसरे तर्क से कम.
  • 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.

इनपुट

लेबल नाम टाइप कंस्ट्रेंट
(I1) inputs टेंसर की वैरायडिक संख्या या हर टेंसर की क्वांटाइज़्ड टेंसर की संख्या (सी1-सी5)
(I2) dimension si64 टाइप का कॉन्स्टेंट (सी4)
(I3) is_stable i1 टाइप का कॉन्स्टेंट
(आई4) comparator फ़ंक्शन (सी5)

आउटपुट

नाम टाइप कंस्ट्रेंट
results टेंसर की वैरायडिक संख्या या हर टेंसर की क्वांटाइज़्ड टेंसर की संख्या (C2), (C3)

कंस्ट्रेंट

  • (C1) 0 < size(inputs).
  • (C2) type(inputs...) = type(results...).
  • (C3) same(shape(inputs...) + shape(results...)).
  • (C4) -R <= dimension < R, जहां R = rank(inputs[0]).
  • (C5) comparator का टाइप (tensor<E1>, tensor<E1>, ..., tensor<EN-1>, tensor<EN-1>) -> tensor<i1>, जहां Ei = element_type(inputs[i]) है.

उदाहरण

// %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]]

ज़्यादा उदाहरण

स्क्वेयर

सिमैंटिक

operand टेंसर पर एलिमेंट के हिसाब से स्क्वेयर रूट ऑपरेशन करता है और इससे result टेंसर. एलिमेंट टाइप के आधार पर, ये काम किए जाते हैं:

  • फ़्लोट के लिए: IEEE-754 से squareRoot.
  • सम्मिश्र संख्याओं के लिए: सम्मिश्र वर्गमूल.
  • क्वांटाइज़्ड टाइप के लिए: dequantize_op_quantize(sqrt, operand, type(result)).

इनपुट

लेबल नाम टाइप कंस्ट्रेंट
(I1) operand फ़्लोटिंग-पॉइंट या कॉम्प्लेक्स टाइप या हर टेंसर क्वांटाइज़्ड टेंसर का टेंसर (सी1)

आउटपुट

नाम टाइप कंस्ट्रेंट
result फ़्लोटिंग-पॉइंट या कॉम्प्लेक्स टाइप या हर टेंसर क्वांटाइज़्ड टेंसर का टेंसर (सी1)

कंस्ट्रेंट

  • (C1) baseline_type(operand) = baseline_type(result).

उदाहरण

// %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]]

ज़्यादा उदाहरण

घटाएं

सिमैंटिक

दो टेंसर lhs और rhs के एलिमेंट के हिसाब से घटाव करता है और इससे result टेंसर. एलिमेंट टाइप के आधार पर, ये काम किए जाते हैं:

  • पूर्णांकों के लिए: पूर्णांक घटाव.
  • फ़्लोट के लिए: IEEE-754 से subtraction.
  • सम्मिश्र संख्याओं के लिए: जटिल घटाव.
  • क्वांटाइज़्ड टाइप के लिए:
    • dequantize_op_quantize(subtract, lhs, rhs, type(result)).

इनपुट

लेबल नाम टाइप कंस्ट्रेंट
(I1) lhs इंटीजर, फ़्लोटिंग-पॉइंट या कॉम्प्लेक्स टाइप या हर टेंसर क्वांटाइज़्ड टेंसर का टेंसर (सी1)
(I2) rhs इंटीजर, फ़्लोटिंग-पॉइंट या कॉम्प्लेक्स टाइप या हर टेंसर क्वांटाइज़्ड टेंसर का टेंसर (सी1)

आउटपुट

नाम टाइप कंस्ट्रेंट
result इंटीजर, फ़्लोटिंग-पॉइंट या कॉम्प्लेक्स टाइप या हर टेंसर क्वांटाइज़्ड टेंसर का टेंसर (सी1)

कंस्ट्रेंट

  • (C1) baseline_type(lhs) = baseline_type(rhs) = baseline_type(result).

उदाहरण

// %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

सिमैंटिक

operand टेंसर पर एलिमेंट के हिसाब से टैंजेंट (tan) की संक्रिया करता है और इससे result टेंसर. एलिमेंट टाइप के आधार पर, ये काम किए जाते हैं:

  • फ़्लोट के लिए: IEEE-754 से tan.
  • सम्मिश्र संख्याओं के लिए: सम्मिश्र टैंजेंट.
  • क्वांटाइज़्ड टाइप के लिए: dequantize_op_quantize(tan, operand, type(result)).

इनपुट

लेबल नाम टाइप कंस्ट्रेंट
(I1) operand फ़्लोटिंग-पॉइंट या कॉम्प्लेक्स टाइप या हर टेंसर क्वांटाइज़्ड टेंसर का टेंसर (सी1)

आउटपुट

नाम टाइप कंस्ट्रेंट
result फ़्लोटिंग-पॉइंट या कॉम्प्लेक्स टाइप या हर टेंसर क्वांटाइज़्ड टेंसर का टेंसर (सी1)

कंस्ट्रेंट

  • (C1) baseline_type(operand) = baseline_type(result).

उदाहरण

// %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]
//          ]

ज़्यादा उदाहरण

तान

सिमैंटिक

operand टेंसर और पर एलिमेंट के हिसाब से हाइपरबोलिक टैंजेंट ऑपरेशन करता है result टेंसर बनाता है. एलिमेंट टाइप के आधार पर, ये काम किए जाते हैं:

  • फ़्लोट के लिए: IEEE-754 से tanh.
  • कॉम्प्लेक्स नंबर के लिए: कॉम्प्लेक्स हाइपरबोलिक टैंजेंट.
  • क्वांटाइज़्ड टाइप के लिए:
    • dequantize_op_quantize(tanh, operand, type(result)).

इनपुट

लेबल नाम टाइप कंस्ट्रेंट
(I1) operand फ़्लोटिंग-पॉइंट या कॉम्प्लेक्स टाइप या हर टेंसर क्वांटाइज़्ड टेंसर का टेंसर (सी1)

आउटपुट

नाम टाइप कंस्ट्रेंट
result फ़्लोटिंग-पॉइंट या कॉम्प्लेक्स टाइप या हर टेंसर क्वांटाइज़्ड टेंसर का टेंसर (सी1)

कंस्ट्रेंट

  • (C1) baseline_type(operand) = baseline_type(result).

उदाहरण

// %operand: [-1.0, 0.0, 1.0]
%result = "stablehlo.tanh"(%operand) : (tensor<3xf32>) -> tensor<3xf32>
// %result: [-0.76159416, 0.0, 0.76159416]

ज़्यादा उदाहरण

ट्रांसपोज़

सिमैंटिक

permutation का इस्तेमाल करके operand टेंसर के डाइमेंशन को अनुमति देता है और result टेंसर. औपचारिक तौर पर, result[result_index] = operand[operand_index] जहां result_index[d] = operand_index[permutation[d]].

इनपुट

लेबल नाम टाइप कंस्ट्रेंट
(I1) operand टेंसर या क्वांटाइज़्ड टेंसर (सी1-सी4)
(I2) permutation si64 टाइप का 1-डाइमेंशन टेंसर कॉन्सटेंट (सी2-सी4)

आउटपुट

नाम टाइप कंस्ट्रेंट
result टेंसर या क्वांटाइज़्ड टेंसर (C1), (C3-C4)

कंस्ट्रेंट

  • (C1) element_type(result) देने वाली कंपनी:
    • अगर !is_per_axis_quantized(operand) है, तो element_type(operand).
    • element_type(operand), लेकिन quantization_dimension(operand) और ऐसा न होने पर quantization_dimension(result) अलग हो सकती है.
  • (C2) permutation, range(rank(operand)) का क्रमचय (परम्यूटेशन) है.
  • (C3) shape(result) = dim(operand, permutation...).
  • (C4) अगर is_per_axis_quantized(result) है, तो quantization_dimension(operand) = permutation(quantization_dimension(result)).

उदाहरण

// %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

सिमैंटिक

निचले या ऊपरी त्रिकोणीय वाले रैखिक समीकरणों की प्रणालियों के बैच हल करता है गुणांक वाले मैट्रिक्स से अलग-अलग वैल्यू हो.

औपचारिक तौर पर, a और b को दिए जाने पर, result[i0, ..., iR-3, :, :] समाधान है op(a[i0, ..., iR-3, :, :]) * x = b[i0, ..., iR-3, :, :] तक जब left_side हो true या x * op(a[i0, ..., iR-3, :, :]) = b[i0, ..., iR-3, :, :], जब left_side, false है. वैरिएबल x के लिए हल किया जा रहा है, जहां op(a) तय किया जाता है transpose_a से मिला, जो इनमें से एक हो सकता है:

  • NO_TRANSPOSE: a को उसी रूप में इस्तेमाल करके कार्रवाई करें.
  • TRANSPOSE: a को ट्रांसपोज़ करने पर कार्रवाई करें.
  • ADJOINT: a के संयुग्मी ट्रांसपोज़ पर कार्रवाई करें.

अगर lower true है, तो इनपुट डेटा को a के निचले त्रिभुज से ही पढ़ा जाएगा या a का ऊपर वाला त्रिकोण मानें, नहीं तो. आउटपुट डेटा उसी त्रिकोण में दिखाया जाता है; दूसरे त्रिभुज की वैल्यू लागू करने के तरीके तय की गई हैं.

अगर unit_diagonal सही है, तो लागू करने पर यह मान लिया जा सकता है कि डायगनल a के एलिमेंट 1 के बराबर होते हैं, वरना व्यवहार तय नहीं होता है.

क्वांटाइज़्ड टाइप के लिए, dequantize_op_quantize(lambda x, y: triangular_solve(x, y, left_side, lower, unit_diagonal, transpose_a), a, b, type(result)).

इनपुट

लेबल नाम टाइप कंस्ट्रेंट
(I1) a फ़्लोटिंग-पॉइंट या कॉम्प्लेक्स टाइप या हर टेंसर क्वांटाइज़्ड टेंसर का टेंसर (सी1-सी3)
(I2) b फ़्लोटिंग-पॉइंट या कॉम्प्लेक्स टाइप या हर टेंसर क्वांटाइज़्ड टेंसर का टेंसर (सी1-सी4)
(I3) left_side i1 टाइप का कॉन्स्टेंट (सी3)
(आई4) lower i1 टाइप का कॉन्स्टेंट
(I5) unit_diagonal i1 टाइप का कॉन्स्टेंट
(I6) transpose_a NO_TRANSPOSE, TRANSPOSE, और ADJOINT का कुल डेटा

आउटपुट

नाम टाइप कंस्ट्रेंट
result फ़्लोटिंग-पॉइंट या कॉम्प्लेक्स टाइप या हर टेंसर क्वांटाइज़्ड टेंसर का टेंसर (सी1)

कंस्ट्रेंट

  • (C1) baseline_element_type(a) = baseline_element_type(b).
  • (C2) 2 <= rank(a) = rank(b) = R.
  • (C3) shape(a) और shape(b) के बीच का संबंध इस तरह से परिभाषित किया गया है:
    • 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).

उदाहरण

// %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]
//          ]

टपल

सिमैंटिक

val वैल्यू से result टपल बनाता है.

इनपुट

लेबल नाम टाइप कंस्ट्रेंट
(I1) val वैल्यू की वैरायडिक संख्या (सी1)

आउटपुट

नाम टाइप कंस्ट्रेंट
result टपल (सी1)

कंस्ट्रेंट

  • (C1) result का टाइप tuple<E0, ..., EN-1> है, जहां Ei = type(val[i]) है.

उदाहरण

// %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

सिमैंटिक

यह फ़ंक्शन, क्वांटाइज़्ड टेंसर operand को एलिमेंट के हिसाब से कन्वर्ट करता है तय किए गए क्वांटाइज़ेशन पैरामीटर के मुताबिक, फ़्लोटिंग-पॉइंट टेंसर result operand टाइप के हिसाब से.

औपचारिक तौर पर, result = dequantize(operand).

इनपुट

लेबल नाम टाइप कंस्ट्रेंट
(I1) operand क्वांटाइज़्ड टेंसर (C1), (C2)

आउटपुट

नाम टाइप कंस्ट्रेंट
result फ़्लोटिंग-पॉइंट टाइप का टेंसर (C1), (C2)

कंस्ट्रेंट

  • (C1) shape(operand) = shape(result).
  • (C2) element_type(result) = expressed_type(operand).

उदाहरण

// %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

सिमैंटिक

फ़्लोटिंग-पॉइंट टेंसर या क्वांटाइज़्ड टेंसर का एलिमेंट के हिसाब से कन्वर्ज़न करता है क्वांटाइज़ेशन के हिसाब से, operand को क्वांटाइज़्ड टेंसर result पर सेट करें result टाइप के ज़रिए तय किए गए पैरामीटर.

औपचारिक तौर पर,

  • अगर is_float(operand):
    • result = quantize(operand, type(result)).
  • अगर is_quantized(operand):
    • float_result = dequantize(operand).
    • result = quantize(float_result, type(result)).

इनपुट

लेबल नाम टाइप कंस्ट्रेंट
(I1) operand फ़्लोटिंग-पॉइंट या क्वांटाइज़्ड टाइप का टेंसर (C1), (C2)

आउटपुट

नाम टाइप कंस्ट्रेंट
result क्वांटाइज़्ड टेंसर (C1), (C2)

कंस्ट्रेंट

  • (C1) shape(operand) = shape(result).
  • (C2) expressed_type(result) = is_float(operand) ? element_type(operand) : expressed_type(operand).

उदाहरण

// %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]

जबकि

सिमैंटिक

body फ़ंक्शन को 0 या उससे ज़्यादा बार चलाने पर आउटपुट देता है, जबकि cond फ़ंक्शन का आउटपुट true है. औपचारिक तौर पर, सिमेंटिक्स को व्यक्त किया जा सकता है Python सिंटैक्स का इस्तेमाल इस तरह से करता है:

internal_state = operand
while cond(*internal_state):
  internal_state = body(*internal_state)
results = internal_state

अनंत लूप का व्यवहार अभी तय नहीं है (#383).

इनपुट

लेबल नाम टाइप कंस्ट्रेंट
(I1) operand टेंसर की वैरायडिक संख्या, क्वांटाइज़ किए गए टेंसर या टोकन (सी1-सी3)
(I2) cond फ़ंक्शन (सी1)
(I3) body फ़ंक्शन (सी2)

आउटपुट

नाम टाइप कंस्ट्रेंट
results टेंसर की वैरायडिक संख्या, क्वांटाइज़ किए गए टेंसर या टोकन (सी3)

कंस्ट्रेंट

  • (C1) cond का टाइप (T0, ..., TN-1) -> tensor<i1> है, जहां Ti = type(operand[i]).
  • (C2) body का टाइप (T0, ..., TN-1) -> (T0, ..., TN-1) है, जहां Ti = type(operand[i]).
  • (C3) type(results...) = type(operand...).

उदाहरण

// %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

ज़्यादा उदाहरण

एक्सओआर

सिमैंटिक

दो टेंसर lhs और rhs के एलिमेंट के हिसाब से XOR करता है और result बनाता है टेंसर. एलिमेंट टाइप के आधार पर, ये काम किए जाते हैं:

  • बूलियन के लिए: लॉजिकल XOR.
  • पूर्णांक के लिए: बिट के अनुसार XOR.

इनपुट

लेबल नाम टाइप कंस्ट्रेंट
(I1) lhs बूलियन या पूर्णांक टाइप का टेंसर (सी1)
(I2) rhs बूलियन या पूर्णांक टाइप का टेंसर (सी1)

आउटपुट

नाम टाइप कंस्ट्रेंट
result बूलियन या पूर्णांक टाइप का टेंसर (सी1)

कंस्ट्रेंट

  • (C1) type(lhs) = type(rhs) = type(result).

उदाहरण

// 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]]

ज़्यादा उदाहरण

भाषा सिंक करने की सुविधा

इस समय, जंगल में StableHLO प्रोग्राम कभी-कभी ऐसे ऑपरेशन होते हैं जो StableHLO की ओर से तय नहीं किए जाते हैं.

मॉड्यूल, फ़ंक्शन, कॉल, और रिटर्न

StableHLO, ModuleOp, FuncOp, CallOp, और रिटर्नOp. ऐसा करने से, मौजूदा एमएलआईआर मशीनरी के साथ बेहतर इंटरऑप की सुविधा इस्तेमाल की गई. काम के पास को लिखित तौर पर, FuncOp और ModuleOp, और कई सारे कंपाइलेशन को टारगेट करके तैयार किया जाता है पाइपलाइन में ये ऑपरेशन मौजूद होने की उम्मीद होती है. साथ काम करने से जुड़ी गारंटी इन ऑपरेशन पर लागू किया गया. अगर इन ऑपरेशन में कभी भी कुछ बदलता है असंगत तरीके से (यानी निकालना), सुरक्षित रखने के लिए StableHLO से मिलते-जुलते तरीके साथ काम करता है.

CHLO

CHLO ऑपसेट में उच्च स्तर की कार्रवाइयां होती हैं, जो StableHLO में डीकंपोज़ होती हैं. फ़िलहाल, इस बात की कोई गारंटी नहीं है कि सीएचएलओ के साथ यह काम करेगा या नहीं. साथ काम करने के लिए गारंटी के साथ, chlo-legalize-to-stablehlo पास क्रम से लगाने से पहले इस्तेमाल किया जाना चाहिए.

आकार से जुड़ी कार्रवाइयां

समुदाय में बुनियादी चीज़ों का इस्तेमाल करने के लिए, यह आम तौर पर इस्तेमाल किया जाता है आकार की गणना करने के लिए, डाइनैमिक StableHLO प्रोग्राम में एमएलआईआर बोलियां इस्तेमाल की जाती हैं. आम तौर पर, इनमें shape भाषा शामिल है shape_of या num_elements जैसे विकल्प, tensor बोली वर्शन, जैसे कि dim या from_elements और पहले से मौजूद index टाइप.

डायनेमिज़म आरएफ़सी > O2 यह दिखाता है कि ये दायरे से बाहर हैं. हालांकि, कुछ तरह के index के लिए भी कुछ काम किया जा सकता है इसे इंटरऑप के लिए इस्तेमाल किया जाता है. इस बात की कोई गारंटी नहीं है कि इनके साथ काम करेगा या नहीं ऑपरेशन या प्रकार. shape-legalize-to-stablehlo पास का इस्तेमाल इन ऑपरेशन को पूरी तरह से काम करने वाले StableHLO ऑपरेशन में बदलने के लिए किया जा सकता है.

ऐसी कार्रवाइयां जो अब रोक दी गई हैं

ऐसे कई StableHLO ऑपरेशन हैं जो इनसे इनहेरिट किए गए थे MHLO जो अब सेवा में नहीं हैं और StableHLO से बाहर निकलने वाले हैं. इन विज्ञापनों में पूरा विवरण StableHLO v1.0 क्लीनअप #2283 में, ऐप्लिकेशन हटाए जाने की जानकारी मौजूद होती है. इस सुविधा के बंद होने से जुड़ी ट्रैकर से जुड़ी समस्या #2340 है.

ये कार्रवाइयां कुछ कैटगरी में आती हैं:

  • "HLO में नहीं" StableHLO ऑपरेशन की एक कैटगरी होती है - जो शुरुआत में StableHLO ओपसेट का इस्तेमाल किया जाता है, लेकिन बाद में यह माना गया कि यह ठीक से फ़िट नहीं हुआ: broadcast, create_token, cross-replica-sum, dot, einsum, torch_index_select, unary_einsum (#3).
  • इस्तेमाल नहीं किए गए ऑपरेशन - ये कार्रवाइयां शायद किसी भी समय उपयोगी रही हों, लेकिन ऑपरेशन या तो पूरी तरह से विकसित नहीं हुआ था या इन ऑपरेशन का इस्तेमाल करने वाली पाइपलाइन जवाब की ज़रूरत नहीं होगी, इसके लिए जवाब दिया गया. इसमें map, tuple (#598), get_tuple_element, rng, complex तुलनाएं #560, और कन्वर्ज़न window_reversal (#1181).

इनमें से कुछ ऑपरेशन को आसानी से हटाया जा सकता है, क्योंकि उन्हें इसका इस्तेमाल करके दिखाया जा सकता है मौजूदा ऑपरेशन (broadcast, create_token, cross-replica-sum, dot, unary_einsum) को एक्सपोर्ट किया जाएगा और मौजूदा कंपैटबिलिटी विंडो के बाद इसे हटा दिया जाएगा पास (छह महीने). अन्य यूआरएल की जांच अब भी जारी है, ताकि उन्हें हटाया जा सके (einsum, get_tuple_element, map, rng torch_index_select, tuple, complex तुलनाएं, window_reversal). लंबित समुदाय सुझाव, ये ऑपरेशन या तो हटा दिए जाएंगे या पूरे सपोर्ट के साथ इन्हें स्पेसिफ़िकेशन में जोड़ दिए जाएंगे. पूरा होने तक ये ऑपरेशन फ़्यूचर्स के बारे में पता है, लेकिन ये सिर्फ़ 6 महीनों के साथ काम करने की गारंटी देते हैं.

प्लान लागू करना

क्रम से लागू करना

main फ़ंक्शन में इनपुट वैल्यू देकर, StableHLO प्रोग्राम चलाया जाता है और आउटपुट वैल्यू की गणना की जा सकती है. फ़ंक्शन की आउटपुट वैल्यू का हिसाब लगाने के तरीके इससे जुड़े return ऑपरेशन में रूट किए गए ऑपरेशन के ग्राफ़ को एक्ज़ीक्यूट किया जा रहा है.

लागू होने का क्रम तब तक तय होता है, जब तक यह dataflow, इसका मतलब है कि अगर ऑपरेशन को इस्तेमाल करने से पहले एक्ज़ीक्यूट किया जाता है. StableHLO में, सभी साइड-इफ़ेक्टिंग ऑपरेशन, एक टोकन का इस्तेमाल करते हैं और एक टोकन बनाते हैं. हालांकि, एक से ज़्यादा टोकन after_all के ज़रिए एक टोकन में मल्टीप्लेक्स किया जाएगा), इसलिए साइड का एक्ज़ीक्यूशन ऑर्डर इफ़ेक्ट भी डेटाफ़्लो के साथ अलाइन होते हैं. उदाहरण के लिए, नीचे दिए गए प्रोग्राम में प्रोग्राम चलाने के दो संभावित ऑर्डर हैं: %0%1%2return और %1%0%2return.

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>
}

औपचारिक रूप से, StableHLO प्रोसेस, इनमें से एक है: 1) StableHLO प्रोग्राम, 2) ऑपरेशन की स्थितियां (अभी तक एक्ज़ीक्यूट नहीं किया गया है, ) और 3) इंटरमीडिएट वैल्यू, जिन पर प्रोसेस काम कर रही है. प्रोसेस, main फ़ंक्शन के लिए इनपुट वैल्यू से शुरू होती है और आगे बढ़ती है ऑपरेशन की स्थितियों और इंटरमीडिएट वैल्यू को अपडेट करने वाले ऑपरेशन का ग्राफ़ और आउटपुट वैल्यू के साथ खत्म होती है. सुविधाओं को और औपचारिक तौर पर अभी तय नहीं किया गया है (#484).

साथ-साथ एक्ज़ीक्यूशन

StableHLO प्रोग्राम, साथ-साथ चलाए जा सकते हैं और 2D प्रोसेस ग्रिड में व्यवस्थित किए जा सकते हैं num_partitions गुणा num_replicas का, जो दोनों प्रकार ui32 है.

StableHLO प्रोसेस ग्रिड में, StableHLO का num_replicas * num_partitions एक ही समय पर प्रोसेस होती हैं. हर प्रोसेस की अपनी एक खास बात होती है process_id = (replica_id, partition_id), जहां replica_ids = range(num_replicas) में replica_id और partition_ids = range(num_partitions) में partition_id, जिसमें दोनों के पास ui32 लिखें.

प्रोसेस ग्रिड के साइज़ को स्टैटिक रूप से हर प्रोग्राम के लिए जाना जाता है ( आने वाले समय में, हम इसे StableHLO प्रोग्राम का एक अहम हिस्सा बनाने की योजना बना रहे हैं #650) और पोज़िशन के अंदर प्रोसेस ग्रिड को हर प्रोसेस के लिए स्टैटिक तरीके से जाना जाता है. हर प्रोसेस में replica_id और partition_id ऑपरेशन

प्रोसेस ग्रिड में, प्रोग्राम एक जैसे हो सकते हैं. ऐसा "सिंगल प्रोग्राम, एक से ज़्यादा डेटा" शैली), सभी अलग-अलग हो सकते हैं ("एक से ज़्यादा प्रोग्राम, एक से ज़्यादा डेटा" स्टाइल) या बीच की कोई दूसरी चीज़ भी हो सकती है. आने वाले समय में, हम समानांतर StableHLO प्रोग्राम को तय करने से जुड़े दूसरे मुहावरों का समर्थन करने के लिए इसमें GSPMD (#619) भी शामिल है.

प्रोसेस ग्रिड में, प्रोसेस एक-दूसरे से अलग होती हैं - उनकी कार्रवाई की अलग-अलग स्थितियां होती हैं. उनके इनपुट/इंटरमीडिएट/आउटपुट वैल्यू अलग-अलग होती हैं और ज़्यादातर ऑपरेशन, प्रक्रियाओं के बीच अलग-अलग तरीके से चलाए जाते हैं और उनमें अपवाद के तौर पर कुछ जोड़ सकते हैं.

यह देखते हुए कि ज़्यादातर ऑपरेशन को चलाने के लिए सिर्फ़ उसी प्रक्रिया के दौरान, इन वैल्यू को उनके नाम से साफ़ तौर पर देखा जा सकता है. हालांकि, सामूहिक ऑपरेशन के सिमेंटिक्स की व्याख्या करते समय, यह पर्याप्त नहीं है और जो name मान को बताने के लिए नोटेशन name@process_id को जनरेट करता है एक खास प्रोसेस में शामिल किया जाता है. (इस नज़रिए से, बिना अनुमति वाले name ऐसे हो सकते हैं को name@(replica_id(), partition_id()) के लिए शॉर्टहैंड के तौर पर देखा गया).

सभी प्रोसेस के लिए एक्ज़ीक्यूशन का क्रम तय होता है. हालांकि, इसमें पॉइंट-टू-पॉइंट कम्यूनिकेशन और कलेक्टिव ऑपरेशन की मदद से सिंक करने की सुविधा जैसा कि नीचे बताया गया है.

पॉइंट-टू-पॉइंट कम्यूनिकेशन

StableHLO प्रोसेस, StableHLO चैनल. चैनल को एक पॉज़िटिव आईडी से दिखाया जाता है si64. कई ऑपरेशन के ज़रिए, चैनल और उन्हें चैनलों से न ले सकें.

ज़्यादा औपचारिकता, जैसे कि ये चैनल आईडी कहां से आते हैं, कैसे इससे उन्हें प्रोसेस के बारे में जानकारी मिलती है. साथ ही, उन्हें यह भी पता चलता है कि किस तरह का सिंक्रोनाइज़ेशन होता है उन्होंने टेक्नोलॉजी का इस्तेमाल शुरू किया है. यह अभी तय नहीं है (#484).

स्ट्रीमिंग कम्यूनिकेशन

StableHLO की हर प्रोसेस के पास दो स्ट्रीमिंग इंटरफ़ेस का ऐक्सेस होता है:

  • इनफ़ीड, जिससे टेक्स्ट को पढ़ा जा सकता है.
  • आउटफ़ीड, जिसे लिखा जा सकता है.

चैनलों के उलट, जिनका इस्तेमाल अलग-अलग प्रोसेस के बीच बातचीत करने के लिए किया जाता है. इनफ़ीड और आउटफ़ीड के लिए एक-दूसरे से जुड़ी अलग-अलग प्रक्रियाएं होती हैं. लागू करना-तय करना बंद करें.

ज़्यादा औपचारिकता, जैसे कि स्ट्रीमिंग कम्यूनिकेशन, कैसे एक्ज़ीक्यूट करता है यह अभी तय नहीं है कि ऑर्डर में किस तरह का सिंक किया जाएगा. (#484).

कलेक्टिव ऑपरेशन

StableHLO में छह कलेक्टिव ऑपरेशन हैं: all_gather, all_reduce, all_to_all, collective_broadcast, collective_permute, और reduce_scatter. ये सभी ऑपरेशन StableHLO प्रोसेस में, प्रोसेस को अलग-अलग करते हैं StableHLO प्रोसेस ग्रुप में ग्रिड जोड़ें और अन्य प्रोसेस ग्रुप से अलग, हर प्रोसेस ग्रुप.

हर प्रोसेस ग्रुप में, कलेक्टिव ऑपरेशन एक सिंक की सुविधा दे सकते हैं समस्या को हल करने में मदद मिलती है. ज़्यादा औपचारिकता, जैसे कि जिसमें यह बताया गया है कि सिंक होता है, प्रोसेस इस रुकावट तक कैसे पहुंचती हैं, यह अभी तय नहीं है कि ऐसा न होने पर क्या होगा (#484).

अगर प्रोसेस ग्रुप में क्रॉस-पार्टिशन कम्यूनिकेशन शामिल है, तो इसका मतलब है कि प्रक्रिया समूह की ऐसी प्रक्रियाएं जिनके विभाजन आईडी अलग-अलग हैं, फिर निष्पादन कलेक्टिव ऑपरेशन को एक चैनल की ज़रूरत होती है और कलेक्टिव ऑपरेशन को si64 प्रकार का सकारात्मक channel_id. क्रॉस-रेप्लिका कम्यूनिकेशन की ज़रूरत नहीं है चैनल.

कलेक्टिव ऑपरेशन की रिपोर्ट, हर ऑपरेशन के लिए अलग होती है इनके बारे में ऊपर दिए गए अलग-अलग सेशन के सेक्शन में बताया गया है. हालांकि, रणनीति बनाकर इसमें प्रोसेस ग्रिड को प्रोसेस ग्रुप में बांटा जाता है. इन्हें इन ऑपरेशन के बीच शेयर किया जाता है और इस सेक्शन में इनके बारे में बताया गया है. औपचारिक रूप से, StableHLO ये चार रणनीतियां शामिल हैं.

cross_replica

हर प्रोसेस ग्रुप में सिर्फ़ क्रॉस-रेप्लिका कम्यूनिकेशन होते हैं. यह कार्यनीति replica_groups - प्रतिरूप आईडी की सूचियों की सूची - और कंप्यूट का इस्तेमाल करती है partition_ids के replica_groups का एक कार्टीज़न प्रॉडक्ट. replica_groups अभी तक किसी भी व्यक्ति ने चेक इन नहीं किया है यूनीक एलिमेंट होने चाहिए और सभी replica_ids कवर किए जाने चाहिए. ज़्यादा औपचारिक तौर पर, Python सिंटैक्स:

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

उदाहरण के लिए, replica_groups = [[0, 1], [2, 3]] और num_partitions = 2 के लिए, cross_replica प्रोडक्शन होगी [[(0, 0), (1, 0)], [(0, 1), (1, 1)], [(2, 0), (3, 0)], [(2, 1), (3, 1)]].

cross_partition

हर प्रोसेस ग्रुप में सिर्फ़ क्रॉस-पार्टिशन कम्यूनिकेशन होते हैं. यह रणनीति, सेगमेंट आईडी की सूचियों की सूची - और partition_groups का इस्तेमाल करती है replica_ids गुणा partition_groups के कार्टीज़न गुणनफल की गणना करता है. partition_groups में यूनीक एलिमेंट होने चाहिए और इनमें सभी partition_ids शामिल होने चाहिए. Python सिंटैक्स का इस्तेमाल करके, औपचारिक रूप से:

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

उदाहरण के लिए, partition_groups = [[0, 1]] और num_replicas = 4 के लिए, cross_partition प्रोडक्शन होगी [[(0, 0), (0, 1)], [(1, 0), (1, 1)], [(2, 0), (2, 1)], [(3, 0), (3, 1)]].

cross_replica_and_partition

क्रॉस-रेप्लिका और क्रॉस-पार्टिशन कम्यूनिकेशन, दोनों प्रोसेस ग्रुप. इस रणनीति के लिए replica_groups की ज़रूरत होती है - यह सूचियों की सूची है प्रतिरूप आईडी - और इसके हिसाब से हर replica_group के कार्टीज़न प्रॉडक्ट की गणना करता है partition_ids. replica_groups में यूनीक एलिमेंट होने चाहिए और इनमें सभी एलिमेंट शामिल होने चाहिए replica_ids. Python सिंटैक्स का इस्तेमाल करके, औपचारिक रूप से:

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

उदाहरण के लिए, replica_groups = [[0, 1], [2, 3]] और num_partitions = 2 के लिए, cross_replica_and_partition प्रोडक्शन होगी [[(0, 0), (1, 0), (0, 1), (1, 1)], [(2, 0), (3, 0), (2, 1), (3, 1)]].

flattened_ids

इस रणनीति के लिए, flattened_id_groups की ज़रूरत है - यह "फ़्लैट की गई" सूचियों की सूची है replica_id * num_partitions + partition_id - और उन्हें प्रोसेस आईडी में बदल देता है. flattened_id_groups में यूनीक एलिमेंट होने चाहिए और सभी process_ids कवर करती हैं. Python सिंटैक्स का इस्तेमाल करके, औपचारिक रूप से:

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

उदाहरण के लिए, flattened_id_groups = [[0, 1, 2, 3], [4, 5, 6, 7]] के लिए, num_replicas = 4 और num_partitions = 2, flattened_ids के साथ मिलकर काम करेंगे [[(0, 0), (0, 1), (1, 0), (1, 1)], [(2, 0), (2, 1), (3, 0), (3, 1)]].

सटीक जानकारी

फ़िलहाल, StableHLO, अंकों में सटीक होने की गारंटी नहीं देता है. हालांकि, आने वाले समय में इसकी स्थिति बदल सकती है (#1156).

क्वांटाइज़्ड ऑपरेशन का एक्ज़ीक्यूशन सिमेंटिक्स

क्वांटाइज़्ड StableHLO ऑपरेशन की परिभाषा, इस बात पर निर्भर करती है कि हार्डवेयर की ज़रूरतों और क्षमताओं को पूरा किया जाता है. उदाहरण के लिए, कुछ हार्डवेयर क्वांटाइज़्ड ऑपरेशन की व्याख्या करने के लिए और आखिर में आकलन करें" रणनीति. अन्य लोग पूरा परफ़ॉर्म कर सकते हैं पूर्णांक अंकगणित के साथ गणना. इस वजह से, क्वांटाइज़्ड StableHLO ऑपरेशन खास तौर पर, लागू करना. हाइब्रिड क्वांटाइज़ेशन की परिभाषा (#1575) इस पर आधारित होना चाहिए: यह स्पेसिफ़िकेशन में बताए गए अनुसार सिमेंटिक्स है ( 1792).

गड़बड़ियां

StableHLO प्रोग्राम की पुष्टि, कई तरह की पाबंदियों के ज़रिए की जाती है इसकी मदद से, रन टाइम से पहले कई तरह की गड़बड़ियों को रोका जा सकता है. हालांकि, गड़बड़ी की स्थितियां अब भी हो सकती हैं, जैसे कि पूर्णांक से होकर, आउट-ऑफ़-बाउंड ऐक्सेस वगैरह. जब तक साफ़ तौर पर इस बारे में न बताया गया हो, तब तक ये सभी गड़बड़ियां के नतीजे के तौर पर हम तय करते हैं कि यह ज़रूरी है या नहीं, लेकिन इसकी वजह से आने वाले समय में (#1157).

फ़्लोटिंग-पॉइंट अपवाद

इस नियम के अपवाद के तौर पर, StableHLO प्रोग्राम में फ़्लोटिंग-पॉइंट के अपवाद अच्छे ढंग से तय किए गए व्यवहार होते हैं. ऐसी कार्रवाइयां जिनके नतीजे में आईईईई-754 स्टैंडर्ड (अमान्य ऑपरेशन, हर सेगमेंट की संख्या, ओवरफ़्लो, अंडरफ़्लो या सटीक अपवाद) डिफ़ॉल्ट नतीजे देते हैं (जैसा कि स्टैंडर्ड में बताया गया है) और स्टेटस बताने वाले फ़्लैग को उठाए बिना, एक्ज़ीक्यूशन जारी रखना; इसके समान स्टैंडर्ड से raiseNoFlag अपवाद मैनेज करना. गैर-मानकों के लिए अपवाद संक्रियाएं (उदाहरण के लिए, जटिल अंकगणित और कुछ ट्रांसेंडेंटल फ़ंक्शन) लागू किया जाना चाहिए.

आकार मेल नहीं खाता

StableHLO, डाइनैमिक आकार के टेंसर के साथ काम करता है. हालांकि, आकृतियों का सहमत होना ज़रूरी है रनटाइम है, तो व्यवहार तय नहीं होता है. StableHLO, साफ़ तौर पर एक ऐसी ऑप उपलब्ध कराएं, जो दावा कर सके कि रनटाइम के समय टेंसर का एक आकार होता है. सही कोड जनरेट करने की ज़िम्मेदारी मैन्युफ़ैक्चरर की है.

खास उदाहरण के तौर पर, यह प्रोग्राम मान्य है. हालांकि, रनटाइम के दौरान, %arg0 और %arg1 का सटीक आकार एक जैसा होना चाहिए. अगर ऐसा नहीं है, तो प्रोग्राम के व्यवहार के बारे में नहीं बताया गया है:

func.func @foo(%arg0: tensor<?xi32>, %arg1: tensor<?xi32>) -> tensor<?xi32> {
    %0 = stablehlo.add %arg0, %arg1 : tensor<?xi32>
    return %0 : tensor<?xi32>
}

नोटेशन

सिंटैक्स की जानकारी देने के लिए, इस दस्तावेज़ में EBNF के बदले गए आईएसओ फ़्लेवर का इस्तेमाल किया गया है सिंटैक्स (ISO/IEC 14977:1996, Wikipedia), दो बदलावों के साथ: 1) नियम = के बजाय ::= का इस्तेमाल करके तय किए जाते हैं,

2) स्ट्रिंग जोड़ने की प्रोसेस को , के बजाय, सीधे तौर पर जोड़ने की सुविधा का इस्तेमाल करके दिखाया जाता है.

सिमैंटिक के बारे में बताने के लिए (जैसे, "टाइप", "कॉन्सटेंट", और "ऑपरेशन" सेक्शन) में, हम ऐसे फ़ॉर्मूले इस्तेमाल कर रहे हैं जो सहायता के साथ बढ़ाए गए Python सिंटैक्स पर आधारित होते हैं का इस्तेमाल करें. यह काफ़ी कारगर है के लिए छोटे स्निपेट के लिए होता है, लेकिन बहुत कम मामलों में जब कोड के बड़े स्निपेट ज़रूरी है, तो हम वैनिला Python सिंटैक्स का इस्तेमाल करते हैं. यह सिंटैक्स हमेशा साफ़ तौर पर पेश किया जाता है.

फ़ॉर्मूला

आइए, देखते हैं कि dot_general के उदाहरण के आधार पर फ़ॉर्मूला कैसे काम करते हैं स्पेसिफ़िकेशन. इस कार्रवाई की एक सीमा यहां दी गई है: dim(lhs, lhs_batching_dimensions...) = dim(rhs, rhs_batching_dimensions...).

इस फ़ॉर्मूला में इस्तेमाल किए गए नाम दो सोर्स से आते हैं: 1) ग्लोबल फ़ंक्शन, उदाहरण के लिए, dim, 2) प्रोग्राम के एलिमेंट से जुड़ी सदस्यों की परिभाषाएं, जैसे कि lhs, lhs_batching_dimensions, rhs, और rhs_batching_dimensions इनपुट "इनपुट" में परिभाषित किया गया है सेक्शन dot_general का है.

जैसा कि ऊपर बताया गया है, इस फ़ॉर्मूला का सिंटैक्स Python पर आधारित है. इसमें कम समय में इस्तेमाल किए जा सकने वाले एक्सटेंशन. फ़ॉर्मूला को समझने के लिए, आइए पूरी तरह बदलें इसे वनिला Python सिंटैक्स में बदल देते हैं.

A) इन फ़ॉर्मूले में, हम समानता को दिखाने के लिए = का इस्तेमाल कर रहे हैं. इसलिए, पहला चरण यह तरीका अपनाकर, Python सिंटैक्स पाने के लिए, = को == से बदला जा रहा है: dim(lhs, lhs_batching_dimensions...) == dim(rhs, rhs_batching_dimensions...).

B) साथ ही, ये फ़ॉर्मूले, एलिप्स (...) का इस्तेमाल करते हैं, जो अदिश व्यंजकों को बदलते हैं टेंसर एक्सप्रेशन में बदल सकते हैं. कम शब्दों में कहें, तो f(xs...) का मतलब है "हर टेंसर xs में अदिश x, एक अदिश f(x) की गणना करें और फिर सभी का मान निकालें ये अदिश परिणाम एक साथ टेंसर परिणाम के रूप में होते हैं". वैनिला Python सिंटैक्स में, हमारा उदाहरण फ़ॉर्मूला यहां बदल जाता है: [dim(lhs, dim1) for dim1 in lhs_batching_dimensions] == [dim(rhs, dim2) for dim2 in rhs_batching_dimensions].

दीर्घवृत्त की वजह से अक्सर संभव है कि आप डैशबोर्ड पर अलग-अलग स्केलर. हालांकि, कुछ पेचीदा मामलों में, लोअर-लेवल सेमी-अनौपचारिक start_indices[bi0, ..., :, ..., biN] फ़ॉर्मूला की तरह ही सिंटैक्स का इस्तेमाल किया जा सकता है gather स्पेसिफ़िकेशन के मुताबिक. संक्षिप्तता की सेवा में, हम इस तरह के सिंटैक्स का अनुवाद वैनिला Python में करने के लिए, सटीक फ़ॉर्मलिज़्म उपलब्ध कराया जा सकता है. उम्मीद है कि अब भी अलग-अलग पहलुओं को आसानी से समझा जा सकेगा. अगर कुछ फ़ॉर्मूला साफ़ नहीं दिख रहे हैं, तो कृपया हमें बताएं. हम उन फ़ॉर्मूलों को उन्हें बेहतर बनाना.

साथ ही, आप देखेंगे कि फ़ॉर्मूला सभी तरह की सूचियों को बड़ा करने के लिए एलिप्स का इस्तेमाल करते हैं, इसमें टेंसर, टेंसर की सूचियां (उदाहरण के लिए, वैरायडिक टेंसर की संख्या वगैरह. यह एक अन्य एरिया है, जहां हम सटीक जानकारी नहीं देते औपचारिकता (उदाहरण के लिए, सूचियां StableHLO टाइप सिस्टम का हिस्सा भी नहीं हैं) और समझने की क्षमता पर भरोसा करते हैं.

C) ध्यान देने लायक आखिरी नोटेशनल वाहन ब्रॉडकास्ट कर रहा है. हालांकि StableHLO opset, इंप्लिसिट ब्रॉडकास्टिंग के साथ काम नहीं करता, फ़ॉर्मूले में, कम अवधि के लिए भी किया जा सकता है. संक्षेप में, अगर एक अदिश का इस्तेमाल ऐसे कॉन्टेक्स्ट में किया जाता है जहां टेंसर की उम्मीद की जाती है, और स्केलर को अनुमानित आकार.

dot_general उदाहरण को जारी रखने के लिए, यहां एक और कंस्ट्रेंट दिया गया है: 0 <= lhs_batching_dimensions < rank(lhs). जैसा कि dot_general में बताया गया है स्पेसिफ़िकेशन के हिसाब से, lhs_batching_dimensions एक टेंसर है. हालांकि, 0 और rank(lhs) स्केलर हैं. इंप्लिसिट ब्रॉडकास्टिंग को लागू करने के बाद, फ़ॉर्मूला [0, ..., 0] <= lhs_batching_dimensions < [rank(lhs), ..., rank(lhs)] बन जाएं.

किसी खास dot_general ऑपरेशन पर लागू होने पर, यह फ़ॉर्मूला बूलियन के टेंसर का आकलन करें. जब फ़ॉर्मूला को कंस्ट्रेंट के रूप में इस्तेमाल किया जाता है, तो कंस्ट्रेंट होल्ड करता है अगर फ़ॉर्मूला का आकलन या तो true या टेंसर पर होता है सिर्फ़ true एलिमेंट हैं.

नाम

फ़ॉर्मूला में, लेक्सिकल स्कोप में ये शामिल हैं: 1) ग्लोबल फ़ंक्शन, 2) सदस्य की परिभाषाएं,

3) स्थानीय परिभाषाएं. ग्लोबल फ़ंक्शन की सूची यहां दी गई है. सूची एलिमेंट की परिभाषाएं प्रोग्राम एलिमेंट पर निर्भर करती हैं कि नोटेशन इस पर लागू किया गया:

  • कार्रवाइयों के लिए, सदस्य की परिभाषाओं में "इनपुट" में बताए गए नाम शामिल होते हैं और "आउटपुट" सेक्शन.
  • बाकी सभी के लिए, सदस्य की परिभाषाओं में प्रोग्राम एलिमेंट, जिसका नाम संबंधित EBNF नॉन-टर्मिनल के नाम पर रखा गया है. ज़्यादातर समय, इन संरचनात्मक हिस्सों के नाम इस तरह से लिए गए हैं कि सांप के केस के लिए नॉन-टर्मिनल के नाम (उदाहरण के लिए IntegerLiteral => integer_literal), लेकिन कभी-कभी इस प्रोसेस में नामों को छोटा कर दिया जाता है (जैसे, QuantizationStorageType => storage_type) होता है, जिसमें नाम "इनपुट" के समान रूप से पेश किया गया / "आउटपुट" कारोबार के सेक्शन खास जानकारी.
  • इसके अलावा, सदस्य की परिभाषाओं में हमेशा self शामिल होता है, ताकि संबंधित प्रोग्राम एलिमेंट.

वैल्यू

फ़ॉर्मूला का आकलन करते समय, वे इस तरह की वैल्यू के साथ काम करते हैं: 1) Value (असल वैल्यू, जैसे कि dense<[[1, 2], [3, 4]]> : tensor<2x2xi32>; उन्हें हमेशा यह पता होता है कि उनका टाइप क्या है), 2) Placeholder (आने वाले समय की वैल्यू, जैसे कि lhs, rhs या result; उनकी असल वैल्यू फ़िलहाल, वैल्यू के बारे में कोई जानकारी नहीं है. सिर्फ़ उनके टाइप के बारे में पता है), 3) Type (टाइप" सेक्शन में बताए गए टाइप), 4) Function (ग्लोबल फ़ंक्शन, जैसा कि "फ़ंक्शन" सेक्शन में बताया गया है).

कॉन्टेक्स्ट के आधार पर, नाम अलग-अलग वैल्यू की जानकारी दे सकते हैं. ज़्यादा देखें खास तौर पर, "सेमैंटिक्स" ऑपरेशन के लिए सेक्शन (और अन्य प्रोग्राम के लिए इसी तरह का कोई सेक्शन एलिमेंट) रनटाइम लॉजिक के बारे में बताता है, इसलिए सभी इनपुट Value के तौर पर उपलब्ध होते हैं. इसके उलट, "कंस्ट्रेंट" ops (और समकक्ष) के लिए अनुभाग "कंपाइल-टाइम" लॉजिक, यानी कुछ ऐसा जिसे आम तौर पर रनटाइम से पहले लागू किया जाता है, Value की तरह कॉन्सटैंट इनपुट उपलब्ध होते हैं. साथ ही, अन्य इनपुट उपलब्ध होते हैं सिर्फ़ Placeholder के तौर पर उपलब्ध है.

नाम "Semantics" में "कंस्ट्रेंट" में
ग्लोबल फ़ंक्शन Function Function
कॉन्सटेंट इनपुट Value Value
नॉन-कॉन्सटेंट इनपुट Value Placeholder
आउटपुट Value Placeholder
स्थानीय परिभाषाएं यह परिभाषा पर निर्भर करता है यह परिभाषा पर निर्भर करता है

आइए, एक उदाहरण transpose कार्रवाई पर गौर करें:

%result = "stablehlo.transpose"(%operand) {
  permutation = dense<[2, 1, 0]> : tensor<3xi64>
} : (tensor<2x3x2xi32>) -> tensor<2x3x2xi32>

इस ऑपरेशन के लिए, permutation कॉन्स्टेंट है. इसलिए, यह Value के तौर पर उपलब्ध होता है दोनों में देखा जा सकता है. इसके उलट, operand और result सिमैंटिक में Value के तौर पर उपलब्ध है, लेकिन कंस्ट्रेंट में सिर्फ़ Placeholder के तौर पर उपलब्ध है.

फ़ंक्शन

अलग-अलग तरह के एलिमेंट बनाना

टाइप बनाने के लिए, ऐसा कोई फ़ंक्शन नहीं है. इसके बजाय, हम सीधे टाइप सिंटैक्स का इस्तेमाल करें, क्योंकि आम तौर पर यह ज़्यादा छोटा होता है. उदाहरण के लिए, function_type( [tensor_type([], E), tensor_type([], E)], [tensor_type([], E)]) के बजाय (tensor<E>, tensor<E>) -> (tensor<E>).

टाइप के फ़ंक्शन

  • element_type को टेंसर टाइप और क्वांटाइज़ किए गए टेंसर टाइप के हिसाब से तय किया गया है और TensorElementType या QuantizedTensorElementType के तौर पर रिटर्न करता है का हिस्सा है.TensorTypeQuantizedTensorType
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 एक शॉर्टकट है is_quantized(x) and quantization_dimension(x) is not None के लिए.

  • is_per_tensor_quantized(x: Value | Placeholder | Type) -> Value is_quantized(x) and quantization_dimension(x) is None के लिए शॉर्टकट.

  • is_promotable(x: Type, y: Type) -> bool यह जांच करता है कि x टाइप का प्रमोशन किया जा सकता है या नहीं y टाइप करने के लिए. जब x और y, QuantizedTensorElementType होते हैं, तो प्रमोशन सिर्फ़ storage_type पर लागू होता है. प्रमोशन का यह खास वर्शन वर्तमान में न्यूनीकरण अभिकलन के संदर्भ में उपयोग किया जाता है ( RFC देखें).

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 इनका शॉर्टकट है: is_quantized_tensor_element_type(x).

  • is_type_name(x: Value | Placeholder | Type) -> Value. सभी के लिए उपलब्ध प्रकार. उदाहरण के लिए, अगर x एक FloatType है, तो is_float(x) true वैल्यू दिखाता है. अगर x कोई वैल्यू या प्लेसहोल्डर है, तो यह फ़ंक्शन इनके लिए शॉर्टकट के तौर पर काम करता है is_type_name(type(x)).

  • max_value(x: Type) -> Value किसी TensorElementType. अगर x, TensorElementType नहीं है, तो None दिखाता है.

  • min_value(x: Type) -> Value सबसे कम संभावित वैल्यू दिखाता है TensorElementType. अगर x, TensorElementType नहीं है, तो None दिखाता है.

  • member_name(x: Value | Placeholder | Type) -> Any. सभी सदस्यों के लिए उपलब्ध सभी तरह की member_name परिभाषाएं. उदाहरण के लिए, tensor_element_type(x) इससे जुड़े TensorType का TensorElementType वाला हिस्सा दिखाता है. अगर x कोई वैल्यू या प्लेसहोल्डर है, तो यह फ़ंक्शन इनके लिए शॉर्टकट के तौर पर काम करता है member_name(type(x)). अगर x ऐसा टाइप नहीं है जिसका कोई सदस्य सही है, या इस तरह के टाइप की वैल्यू या प्लेसहोल्डर, None दिखाता है.

  • is_empty_algorithm(*args: Type) जांचता है कि सभी डॉट एल्गोरिदम फ़ील्ड सेट हैं या नहीं None तक. यह ज़रूरी है, क्योंकि डॉट एल्गोरिदम को लागू किया गया है डिफ़ॉल्ट व्यवहार है, इसलिए डिफ़ॉल्ट मान बताना गलत होगा.

वैल्यू बनाना

  • operation_name(*xs: Value | Type) -> Value. सभी कार्रवाइयों के लिए उपलब्ध. उदाहरण के लिए, add(lhs, rhs) दो टेंसर वैल्यू lhs और rhs लेता है और इन इनपुट के साथ add ऑपरेशन के मूल्यांकन का आउटपुट देता है. कुछ कामों के लिए, जैसे broadcast_in_dim, उनके आउटपुट टाइप ये हैं "लोड-बेयरिंग", यानी किसी कार्रवाई का मूल्यांकन करने के लिए ज़रूरी है. इस मामले में, फ़ंक्शन इन टाइप को आर्ग्युमेंट के तौर पर लेता है.

वैल्यू पर फ़ंक्शन

  • Python के सभी ऑपरेटर और फ़ंक्शन उपलब्ध हैं. उदाहरण के लिए, दोनों सदस्यता और स्लाइसिंग Python के नोटेशन, टेंसर और क्वांटाइज़ किए गए टेंसर में इंडेक्स करने के लिए उपलब्ध हैं और ट्यूपल्स.

  • to_destination_type(x: Value, destination_type: Type) -> Value के बारे में जानकारी दी गई है टेंसर और type(x) के आधार पर x का रूपांतरित मान देता है और destination_type इस तरह से पाएं:

def to_destination_type(x: Value, destination_type: Ty