ข้อกำหนดของ StableHLO

StableHLO คือชุดการดำเนินการสำหรับการดำเนินการระดับสูง (HLO) ในโมเดลแมชชีนเลิร์นนิง (ML) StableHLO ทำงานเป็นเลเยอร์การถ่ายโอนได้ระหว่างเฟรมเวิร์ก ML กับคอมไพเลอร์ ML เฟรมเวิร์ก ML ที่สร้างโปรแกรม StableHLO ใช้ได้กับคอมไพเลอร์ ML ที่ใช้โปรแกรม StableHLO

เป้าหมายของเราคือการลดความซับซ้อนและเร่งการพัฒนา ML ด้วยการสร้างความสามารถในการทำงานร่วมกันระหว่างเฟรมเวิร์ก ML ที่หลากหลาย (เช่น TensorFlow, JAX และ PyTorch) และคอมไพเลอร์ ML (เช่น XLA และ IREE) ในส่วนดังกล่าว เอกสารนี้จะระบุข้อกำหนดสำหรับภาษาโปรแกรมของ StableHLO

ข้อกำหนดนี้ประกอบด้วยส่วนหลัก 3 ส่วน ประการแรก ส่วนโปรแกรมจะอธิบายโครงสร้างของโปรแกรม StableHLO ซึ่งประกอบด้วยฟังก์ชัน StableHLO ที่ประกอบด้วย Ops ของ StableHLO ภายในโครงสร้างนั้น ส่วน Ops จะระบุความหมายของการดำเนินการแต่ละรายการ ส่วนการดำเนินการจะให้ข้อมูลความหมายสำหรับการดำเนินการทั้งหมดเหล่านี้ที่ดำเนินการร่วมกันภายในโปรแกรม สุดท้าย ส่วนหมายเหตุจะพูดถึงสัญกรณ์ที่ใช้ตลอดทั้งข้อกำหนด

โปรแกรม

Program ::= {Func}

โปรแกรม StableHLO ประกอบด้วยฟังก์ชัน StableHLO กี่ฟังก์ชันก็ได้ ด้านล่างนี้เป็นโปรแกรมตัวอย่างที่มีฟังก์ชัน @main ซึ่งมีอินพุต 3 รายการ (%image, %weights และ %bias) และเอาต์พุต 1 รายการ ส่วนเนื้อหาของฟังก์ชัน มี 6 Ops

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}

ฟังก์ชัน SttableHLO (หรือที่เรียกว่าฟังก์ชันที่มีชื่อ) มีตัวระบุ อินพุต/เอาต์พุต และเนื้อหา ในอนาคต เราวางแผนที่จะเปิดตัวข้อมูลเมตาเพิ่มเติมสำหรับฟังก์ชันต่างๆ เพื่อให้เข้ากันได้กับ HLO (#425, #626, #740, #744) ได้ดียิ่งขึ้น

ตัวระบุ

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

ตัวระบุ StableHLO คล้ายกับตัวระบุในภาษาโปรแกรมต่างๆ โดยมีลักษณะเฉพาะ 2 ประการ ได้แก่ 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}

ประเภท Tensor แสดงถึง tensors ซึ่งก็คืออาร์เรย์หลายมิติ ซึ่งประกอบด้วยรูปร่างและประเภทองค์ประกอบ โดยที่รูปร่างแสดงถึงขนาดที่ไม่เป็นลบ โดยเรียงตามลำดับจากน้อยไปมากของมิติข้อมูลที่เกี่ยวข้อง (หรือที่เรียกว่าแกน) โดยมีตัวเลขตั้งแต่ 0 ถึง R-1 จำนวนของมิติข้อมูลRเรียกว่าอันดับ ตัวอย่างเช่น tensor<2x3xf32> เป็นประเภท Tensor ที่มีรูปร่าง 2x3 และประเภทองค์ประกอบ f32 ซึ่งประกอบด้วย 2 มิติ (หรือ 2 แกน) ได้แก่ มิติที่ 0 และมิติข้อมูลที่ 1 ซึ่งมีขนาด 2 และ 3 อันดับที่ 2

แอตทริบิวต์นี้ระบุการรองรับรูปร่างคงที่ในตำแหน่งที่ขนาดของมิติข้อมูลเป็นที่รู้จักแบบคงที่ ในอนาคต เราวางแผนที่จะเพิ่มการรองรับรูปร่างแบบไดนามิกที่ไม่ทราบขนาดของมิติข้อมูลบางส่วนหรือทั้งหมด (#8) นอกจากนี้ เรายังมีแผนที่จะสำรวจการขยายประเภท tensor นอกเหนือจากขนาดมิติข้อมูลและประเภทองค์ประกอบ ยกตัวอย่างเช่น เพื่อรวมเลย์เอาต์ (#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-C4) (C9)
storage_min ค่าคงที่จำนวนเต็ม (C2), (C4), (C8)
storage_max ค่าคงที่จำนวนเต็ม (C3), (C4), (C8)
expressed_type ประเภทจุดลอยตัว (C1), (C5)
quantization_dimension ค่าคงที่จำนวนเต็มที่ไม่บังคับ (C11-C13)
scales จำนวนตัวแปรของค่าคงที่จุดลอยตัว (C5-C7), (C10), (C11), (C13)
zero_points จำนวนคงที่จำนวนเต็มสำหรับตัวแปร (C8-C10)

ประเภทองค์ประกอบที่เล็กลงแสดงค่าที่เป็นจำนวนเต็มของประเภทพื้นที่เก็บข้อมูลในช่วงตั้งแต่ 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) num_bits(storage_type) < num_bits(expressed_type)
  • (C2) type(storage_min) = storage_type
  • (C3) type(storage_max) = storage_type
  • (C4) min_value(storage_type) <= storage_min < storage_max <= max_value(storage_type)
  • (C5) type(scales...) = expressed_type
  • (C6) 0 < scales
  • (C7) is_finite(scales...)
  • (C8) storage_min <= zero_points <= storage_max
  • (C9) type(zero_points...) = storage_type
  • (C10) size(scales) = size(zero_points)
  • (C11) หากเป็น is_empty(quantization_dimension) ให้ size(scales) = 1
  • (C12) 0 <= quantization_dimension

ตอนนี้ QuantizationScale เป็นค่าคงที่ของจุดลอยตัว แต่มีความสนใจอย่างมากในสเกลที่อิงตามจำนวนเต็มซึ่งแสดงตัวคูณและ Shift เรามีแผนที่จะสำรวจสิ่งนี้ในอนาคตอันใกล้ (#1404)

เรายังมีการพูดคุยเรื่องความหมายของ QuantizationZeroPoint อยู่อย่างต่อเนื่อง ซึ่งรวมถึงประเภท ค่า และขึ้นอยู่กับว่าในประเภท tensor เชิงปริมาณมีจุด 1 จุดหรือหลายจุดหรือไม่ จากผลการพูดคุยครั้งนี้ ข้อกำหนดเกี่ยวกับคะแนน 0 อาจมีการเปลี่ยนแปลงในอนาคต (#1405)

การพูดคุยที่ดำเนินอยู่อีกรายการเกี่ยวข้องกับความหมายของ QuantizationStorageMin และ QuantizationStorageMax เพื่อระบุว่าควรกำหนดข้อจำกัดใดกับค่าเหล่านี้และสำหรับค่าของ tensors เชิงปริมาณ (#1406)

สุดท้ายนี้ เราวางแผนที่จะสำรวจโดยใช้ค่าจากขนาดที่ไม่รู้จักและจุด 0 จุด ซึ่งคล้ายกับที่เราวางแผนจะหาค่าแทนขนาดมิติข้อมูลที่ไม่รู้จัก (#1407)

ประเภท tensor ที่เล็กลงแสดง tensors ที่มีองค์ประกอบที่เล็กลง Tensor เหล่านี้เหมือนกับ Tensor ปกติทุกประการ ยกเว้นว่าองค์ประกอบมีประเภทองค์ประกอบในเชิงปริมาณ ไม่ใช่ประเภทองค์ประกอบปกติ

ใน tensor ที่วัดปริมาณได้ การหาปริมาณอาจเท่ากับ per-tensor ซึ่งหมายความว่ามี scale 1 ค่าและ zero_point สำหรับ tensor ทั้งหมด หรืออาจเป็นต่อแกนก็ได้ ซึ่งหมายความว่ามี scales และ zero_points หลายรายการ 1 คู่ต่อสไลซ์ของมิติข้อมูลหนึ่งๆ quantization_dimension อย่างเป็นทางการใน tensor t ที่มีการคำนวณเชิงปริมาณตามแกนจะมี dim(t, quantization_dimension) ส่วนของ quantization_dimension: t[:, ..., 0, ..., :], t[:, ..., 1, ..., :] ฯลฯ องค์ประกอบทั้งหมดใน i ส่วนจะใช้ scales[i] และ zero_points[i] เป็นพารามิเตอร์การหาปริมาณ ประเภท tensor ที่แบ่งทศนิยมมีข้อจํากัดดังต่อไปนี้

  • สําหรับการกําหนดจํานวนตาม tensor
    • ไม่มีข้อจำกัดเพิ่มเติม
  • สําหรับการหาปริมาณตามแกน:
    • (C12) quantization_dimension < rank(self)
    • (C13) dim(self, quantization_dimension) = size(scales)
TokenType ::= 'token'

ประเภทโทเค็นแสดงถึงโทเค็น ซึ่งก็คือค่าทึบแสงที่ผลิตและใช้โดยการดําเนินการบางอย่าง โทเค็นใช้สำหรับกำหนดคำสั่งปฏิบัติการของการดำเนินการตามที่อธิบายไว้ในส่วนการดำเนินการ

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

ประเภท Tuple คือ tuple ในรายการที่แตกต่างกัน Tuple เป็นฟีเจอร์เดิมที่จะใช้ได้เฉพาะกับ HLO เท่านั้น ใน HLO จะใช้ Tuples เพื่อแสดงถึงอินพุตและเอาต์พุตจากตัวแปร ใน StableHLO ระบบจะรองรับอินพุตและเอาต์พุตแบบแปรผันโดยค่าเริ่มต้น และการใช้ tuples เพียงอย่างเดียวใน StableHLO ก็คือการแสดง HLO ABI อย่างครอบคลุม เช่น T, tuple<T> และ tuple<tuple<T>> อาจแตกต่างกันไปตามการใช้งานจริง เราวางแผนที่จะทําการเปลี่ยนแปลง HLO ABI ในอนาคตซึ่งอาจนําประเภท tuple ออกจาก StableHLO (#598)

TensorElementType ::= BooleanType | IntegerType | FloatType | ComplexType
BooleanType ::= 'i1'
IntegerType ::= SignedIntegerType | UnsignedIntegerType
SignedIntegerType ::= 'si4' | 'si8' | 'si16' | 'si32' | 'si64'
UnsignedIntegerType ::= 'ui4' | 'ui8' | 'ui16' | 'ui32' | 'ui64'
FloatType ::= 'f8E4M3FN' | 'f8E5M2' | 'f8E4M3FNUZ' | 'f8E5M2FNUZ'
            | 'f8E4M3B11FNUZ' | 'bf16' | 'f16' | 'f32' | 'f64'
ComplexType ::= 'complex' '<' ComplexElementType '>'
ComplexElementType ::= 'f32' | 'f64'

ประเภทองค์ประกอบแสดงถึงองค์ประกอบของประเภท Tensor ประเภทเหล่านี้ไม่ใช่คลาสแรกใน StableHLO ซึ่งต่างจากภาษาโปรแกรมหลายๆ ภาษา ซึ่งหมายความว่าโปรแกรม StableHLO จะแสดงค่าประเภทเหล่านี้โดยตรงไม่ได้ (ดังนั้น ระบบจึงแสดงค่าสเกลาร์ของประเภท T ที่มีค่า tensor แบบ 0 มิติของประเภท tensor<T>)

  • ประเภทบูลีน แสดงค่าบูลีน true และ false
  • ประเภทจำนวนเต็มอาจมีเครื่องหมาย (si) หรือไม่มีเครื่องหมาย (ui) และมี ความกว้างบิตที่รองรับอย่างใดอย่างหนึ่ง (4, 8, 16, 32 หรือ 64) ประเภท siN ที่ลงนามจะแสดงค่าจำนวนเต็มตั้งแต่ -2^(N-1) ถึง 2^(N-1)-1 โดยรวม ประเภท uiN ที่ไม่มีเครื่องหมายจะแสดงค่าจำนวนเต็มตั้งแต่ 0 ถึง 2^N-1
  • ประเภทจุดทศนิยมอาจเป็นประเภทใดประเภทหนึ่งต่อไปนี้
  • ประเภทที่ซับซ้อนแสดงถึงค่าเชิงซ้อนที่มีส่วนจริงและส่วนจินตภาพเป็นประเภทองค์ประกอบเดียวกัน ประเภทที่ซับซ้อนที่รองรับคือ complex<f32> (ทั้ง 2 ส่วนเป็นประเภท f32) และ complex<f64> (ทั้ง 2 ส่วนเป็นประเภท f64)
FunctionType ::= '(' InputTypes ')' '->' '(' OutputTypes ')'
InputTypes ::= [ValueType {',' ValueType}]
OutputTypes ::= [ValueType {',' ValueType}]

ประเภทฟังก์ชันจะแสดงทั้งฟังก์ชันที่มีชื่อและไม่ระบุตัวตน โดยมีประเภทอินพุต (รายการประเภททางด้านซ้ายของ ->) และประเภทเอาต์พุต (รายการประเภททางด้านขวามือของ ->) สำหรับภาษาโปรแกรมหลายๆ ภาษา ประเภทฟังก์ชันจะเป็นคลาสแรก แต่ไม่อยู่ใน StableHLO

StringType ::= 'string'

ประเภทสตริงแสดงลำดับของไบต์ ประเภทสตริงไม่ใช่คลาสแรกใน StableHLO ซึ่งต่างจากภาษาโปรแกรมหลายๆ ภาษา ซึ่งใช้เพื่อระบุข้อมูลเมตาแบบคงที่สำหรับองค์ประกอบของโปรแกรมเท่านั้น

การทำงาน

การดำเนินการของ SttableHLO (หรือที่เรียกว่า ops) แสดงถึงชุดการดำเนินการระดับสูงแบบปิดในโมเดลแมชชีนเลิร์นนิง ดังที่กล่าวไว้ข้างต้น ไวยากรณ์ StableHLO ได้รับแรงบันดาลใจอย่างมากจาก MLIR ซึ่งไม่จำเป็นต้องเป็นทางเลือกที่เหมาะกับสรีรศาสตร์มากที่สุด แต่เห็นได้ชัดว่าเหมาะสมที่สุดสำหรับเป้าหมาย StableHLO ในการสร้างความสามารถในการทำงานร่วมกันระหว่างเฟรมเวิร์ก ML และคอมไพเลอร์ ML

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

การดำเนินการของ SttableHLO (หรือที่เรียกว่า ops) จะมีชื่อ อินพุต/เอาต์พุต และลายเซ็น ชื่อมีคำนำหน้า stablehlo. และช่วยจำซึ่งระบุการดำเนินการที่รองรับโดยไม่ซ้ำกัน ดูรายการที่ครอบคลุมของการดำเนินการทั้งหมดที่รองรับด้านล่าง

ในขณะนี้ โปรแกรม StableHLO ในระบบทรัพยากรธรรมชาติมีการดำเนินการที่ไม่ได้อธิบายไว้ในเอกสารนี้ ในอนาคต เราวางแผนที่จะดูดกลืนการดำเนินการเหล่านี้ลงในตัวเลือกของ StableHLO หรือห้ามไม่ให้การดำเนินการเหล่านี้ปรากฏในโปรแกรม StableHLO ในระหว่างนี้ โปรดดูรายการการดำเนินงานต่อไปนี้

  • builtin.module, func.func, func.call และ func.return (#425)
  • chlo การดำเนินการ (#602)
  • หมวดหมู่ "ไม่อยู่ใน HLO" ของการดำเนินการของ StableHLO ซึ่งตอนแรกเป็นส่วนหนึ่งของ ตัวเลือกของ StableHLO แต่ภายหลังได้รับการพิจารณาว่าไม่เหมาะกับการใช้งาน: broadcast, create_token, cross-replica-sum, dot, einsum, torch_index_select, unary_einsum (#3)
  • หมวดหมู่ "Dynamism" ของปฏิบัติการ StableHLO ถูกลงทุนจาก MHLO แต่เรายังไม่กำหนด: compute_reshape_shape, cstr_reshapable, dynamic_broadcast_in_dim, dynamic_conv, dynamic_gather, dynamic_iota, dynamic_pad, dynamic_reshape, real_dynamic_slice, set_dimension_size (#8)
  • การคำนวณรูปร่าง รวมถึงการดำเนินการ arith, shape และ tensor (#8)
OpInputs        ::= OpInputValues OpInputFuncs OpInputAttrs
OpInputValues   ::= '(' [OpInputValue {',' OpInputValue}] ')'
OpInputValue    ::= ValueId
OpInputFuncs    ::= ['(' OpInputFunc {',' OpInputFunc} ')']
OpInputAttrs    ::= ['{' OpInputAttr {',' OpInputAttr} '}']
OpOutputs       ::= [OpOutput {',' OpOutput} '=']
OpOutput        ::= ValueId

การดำเนินการจะใช้อินพุตและสร้างเอาต์พุต อินพุตจะได้รับการจัดหมวดหมู่เป็นค่าอินพุต (คํานวณระหว่างการดําเนินการ) ฟังก์ชันอินพุต (มีแบบคงที่เนื่องจากในฟังก์ชัน StableHLO ไม่ใช่ค่าระดับเฟิร์ส) และแอตทริบิวต์อินพุต (ระบุแบบคงที่) ชนิดของอินพุตและเอาต์พุตที่ใช้และผลิตโดยการทดสอบจะขึ้นอยู่กับการช่วยจำ เช่น add op ใช้ค่าอินพุต 2 ค่าและสร้างค่าเอาต์พุต 1 ค่า เมื่อเปรียบเทียบกันแล้ว การดำเนินการ select_and_scatter จะใช้ค่าอินพุต 3 ค่า ฟังก์ชันอินพุต 2 ฟังก์ชัน และแอตทริบิวต์อินพุต 3 รายการ

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

ฟังก์ชันอินพุต (หรือเรียกว่าฟังก์ชันที่ไม่ระบุตัวตน) คล้ายกับฟังก์ชันที่มีชื่ออย่างมาก ยกเว้นว่า 1) ไม่มีตัวระบุ (จึงชื่อ "ไม่ระบุชื่อ") 2) ไม่ประกาศประเภทเอาต์พุต (ประเภทเอาต์พุตจะอนุมานจาก op return ภายในฟังก์ชัน)

ไวยากรณ์สำหรับฟังก์ชันอินพุตประกอบด้วยส่วนที่ไม่มีการใช้งานในปัจจุบัน (ดูเวอร์ชันที่ใช้งานจริงของ Unused ด้านบน) ซึ่งมีไว้สำหรับ MLIR ใน MLIR มีแนวคิดกว้างๆ เกี่ยวกับ "ภูมิภาค" ซึ่งอาจมี "การบล็อก" ของ Ops หลาย "บล็อก" ที่เชื่อมต่อเข้าด้วยกันผ่านการข้าม บล็อกเหล่านี้มีรหัสที่สอดคล้องกับเวอร์ชันที่ใช้งานจริงของ Unused จึงแยกความแตกต่างจากกันได้ StableHLO ไม่มีการข้ามการดำเนินการ ดังนั้นจึงไม่มีการใช้ส่วนที่เกี่ยวข้องของไวยากรณ์ MLIR (แต่ยังคงอยู่)

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

แอตทริบิวต์อินพุตมีชื่อและค่าซึ่งเป็นหนึ่งในค่าคงที่ที่รองรับ ซึ่งเป็นวิธีหลักในการระบุข้อมูลเมตาแบบคงที่สำหรับองค์ประกอบของโปรแกรม ตัวอย่างเช่น concatenate op ใช้แอตทริบิวต์ dimension เพื่อระบุมิติข้อมูลที่จะใช้ค่าอินพุตต่อกัน ในทำนองเดียวกัน slice op จะใช้แอตทริบิวต์หลายรายการ เช่น 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}] ')'

ลายเซ็น Op ประกอบด้วยประเภทของค่าอินพุตทั้งหมด (รายการประเภททางด้านซ้ายของ ->) และประเภทค่าเอาต์พุตทั้งหมด (รายการประเภททางด้านขวามือของ ->) กล่าวโดยละเอียดคือประเภทอินพุตมีความซ้ำซ้อนและประเภทเอาต์พุตเกือบตลอดเวลาเช่นกัน (เนื่องจากการทำงานของ StableHLO ส่วนใหญ่อาจมีการอนุมานประเภทเอาต์พุตจากอินพุต) อย่างไรก็ตาม สัญลักษณ์ op เป็นส่วนหนึ่งของไวยากรณ์ StableHLO โดยเฉพาะเพื่อให้เข้ากันได้กับ MLIR

ด้านล่างคือตัวอย่างการทดสอบที่มีฟังก์ชันช่วยจำคือ select_and_scatter โดยใช้ค่าอินพุต 3 รายการ (%operand, %source และ %init_value), ฟังก์ชันอินพุต 2 รายการ และแอตทริบิวต์อินพุต 3 รายการ (window_dimensions, window_strides และ padding) โปรดทราบว่าลายเซ็นของ op มีเฉพาะประเภทของค่าอินพุตเท่านั้น (แต่ไม่รวมประเภทของฟังก์ชันและแอตทริบิวต์ที่ป้อนในหน้า)

%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

ค่าคงที่เชิงซ้อนแสดงค่าเชิงซ้อนโดยใช้รายการของส่วนจริง (มาก่อน) และส่วนจินตภาพ (เกิดเป็นลำดับที่ 2) ตัวอย่างเช่น (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

ค่าคงที่ Tensor แสดงถึงค่า tensor โดยใช้รายการแบบซ้อนที่ระบุผ่านรูปแบบ NumPy ตัวอย่างเช่น dense<[[1, 2, 3], [4, 5, 6]]> : tensor<2x3xi32> แสดงค่า tensor ที่มีการแมปต่อไปนี้จากดัชนีถึงองค์ประกอบ {0, 0} => 1, {0, 1} => 2, {0, 2} => 3, {1, 0} => 4, {1, 1} => 5, {1, 2} => 6 ลำดับที่เก็บองค์ประกอบเหล่านี้ไว้ในหน่วยความจำจะได้รับการกำหนดการใช้งาน ค่าคงที่ของ Tensor มีข้อจำกัดต่อไปนี้

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

ค่าคงที่ tensor ที่เล็กลงแสดงค่า tensor เชิงปริมาณโดยใช้เครื่องหมายเดียวกับค่าคงที่ tensor ที่มีองค์ประกอบที่ระบุเป็นค่าคงที่ของประเภทพื้นที่เก็บข้อมูล ค่าคงที่ tensor ที่หาค่าเป็นตัวเลขมีข้อจำกัดต่อไปนี้

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

การดำเนินการ

abs

อรรถศาสตร์

ดำเนินการ abs ตามองค์ประกอบบน tensor ใน operand และสร้าง tensor result ระบบจะดำเนินการดังต่อไปนี้โดยขึ้นอยู่กับประเภทองค์ประกอบ

  • สำหรับจำนวนเต็มแบบมีเครื่องหมาย: จำนวนเต็มโมดูลัส
  • สำหรับเลขทศนิยม: abs จาก IEEE-754
  • สำหรับจำนวนเชิงซ้อน: โมดูลัสเชิงซ้อน
  • สำหรับประเภทที่เล็กลง: dequantize_op_quantize(abs, operand, type(result))

อินพุต

ป้ายกำกับ ชื่อ ประเภท ข้อจำกัด
(1) operand Tensor ของจำนวนเต็มแบบมีเครื่องหมาย ประเภทจุดลอยตัว หรือประเภทเชิงซ้อน หรือ tensor ที่เล็กลงแบบต่อ tensor (C1-C2)

เอาต์พุต

ชื่อ ประเภท ข้อจำกัด
result tensor ของจำนวนเต็มแบบมีเครื่องหมายหรือประเภทจุดลอยตัวหรือ tensor ที่เล็กลงแบบต่อ tensor (C1-C2)

ข้อจำกัด

  • (C1) shape(result) = shape(operand)
  • (C2) baseline_element_type(result) ให้คำจำกัดความไว้ดังนี้
    • complex_element_type(element_type(operand)) หาก is_complex(operand)
    • หากไม่ใช่ baseline_element_type(operand)

ตัวอย่าง

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

ตัวอย่างอื่นๆ

เพิ่ม

อรรถศาสตร์

เพิ่ม Tensor จำนวน 2 รายการ ได้แก่ lhs และ rhs ตามองค์ประกอบ แล้วสร้าง result Tensor ระบบจะดำเนินการดังต่อไปนี้โดยขึ้นอยู่กับประเภทองค์ประกอบ

  • สำหรับบูลีน: logical OR
  • สำหรับจำนวนเต็ม: การเพิ่มจำนวนเต็ม
  • สำหรับเลขทศนิยม: addition จาก IEEE-754
  • สำหรับจำนวนเชิงซ้อน: การบวกเชิงซ้อน
  • สำหรับประเภทที่เล็กลง: dequantize_op_quantize(add, lhs, rhs, type(result))

อินพุต

ป้ายกำกับ ชื่อ ประเภท ข้อจำกัด
(1) lhs tensor หรือต่อ tensor ที่วัดปริมาณด้วย tensor (C1)
(I2) rhs tensor หรือต่อ tensor ที่วัดปริมาณด้วย tensor (C1)

เอาต์พุต

ชื่อ ประเภท ข้อจำกัด
result tensor หรือต่อ tensor ที่วัดปริมาณด้วย tensor (C1)

ข้อจำกัด

  • (C1) baseline_type(lhs) = baseline_type(rhs) = baseline_type(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 การดำเนินการของการดำเนินการนี้จะไม่มีผลใดๆ จะมีเพียงการสร้างทรัพยากร Dependency จาก result ไปยัง inputs เท่านั้น

อินพุต

ป้ายกำกับ ชื่อ ประเภท
(1) 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 จะเชื่อมโยงค่าของ Tensor operand จากแต่ละกระบวนการตาม all_gather_dim แล้วสร้าง Tensor 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:

  • operands@receiver = [operand@sender for sender in process_group] สำหรับ receiver ทั้งหมดใน process_group
  • result@process = concatenate(operands@process, all_gather_dim) สำหรับ process ทั้งหมดใน process_group

อินพุต

ป้ายกำกับ ชื่อ ประเภท ข้อจำกัด
(1) operand tensor หรือต่อ tensor ที่วัดปริมาณด้วย tensor (C1), (C6)
(I2) all_gather_dim ค่าคงที่ของประเภท si64 (C1), (C6)
(1) replica_groups ค่าคงที่ tensor 2 มิติของประเภท si64 (C2-C4)
(I4) channel_id ค่าคงที่ของประเภท si64 (C5)
(1) use_global_device_ids ค่าคงที่ของประเภท i1 (C5)

เอาต์พุต

ชื่อ ประเภท ข้อจำกัด
result tensor หรือต่อ tensor ที่วัดปริมาณด้วย tensor (C6)

ข้อจำกัด

  • (C1) 0 <= all_gather_dim < rank(operand)
  • (C2) is_unique(replica_groups)
  • (C3) size(replica_groups) ให้คำจำกัดความไว้ดังนี้
    • num_replicas หากใช้ cross_replica
    • num_replicas หากใช้ cross_replica_and_partition
    • num_processes หากใช้ flattened_ids
  • (C4) 0 <= replica_groups < size(replica_groups)
  • (C5) หากเป็น use_global_device_ids = true ให้จ่าย channel_id > 0
  • (C6) type(result) = type(operand) ยกเว้นสิ่งต่อไปนี้
    • dim(result, all_gather_dim) = dim(operand, all_gather_dim) * dim(process_groups, 1).

ตัวอย่าง

// num_replicas: 2
// num_partitions: 1
// %operand@(0, 0): [[1, 2], [3, 4]]
// %operand@(1, 0): [[5, 6], [7, 8]]
%result = "stablehlo.all_gather"(%operand) {
  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<2x4xi64>
// %result@(0, 0): [[1, 2, 5, 6], [3, 4, 7, 8]]
// %result@(1, 0): [[1, 2, 5, 6], [3, 4, 7, 8]]

ตัวอย่างอื่นๆ

all_reduce

อรรถศาสตร์

ภายในแต่ละกลุ่มกระบวนการในตารางกระบวนการของ StableHLO ให้ใช้ฟังก์ชันการลด computation กับค่าของ operand Tensor จากแต่ละกระบวนการและสร้าง Tensor 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:

  • result@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]))

อินพุต

ป้ายกำกับ ชื่อ ประเภท ข้อจำกัด
(1) operand tensor หรือต่อ tensor ที่วัดปริมาณด้วย tensor (C5) (C6)
(I2) replica_groups จำนวนแปรผันของค่าคงที่ tensor 1 มิติของประเภท si64 (C1-C3)
(1) channel_id ค่าคงที่ของประเภท si64 (C4)
(I4) use_global_device_ids ค่าคงที่ของประเภท i1 (C4)
(1) computation ฟังก์ชัน (C5)

เอาต์พุต

ชื่อ ประเภท ข้อจำกัด
result tensor หรือต่อ tensor ที่วัดปริมาณด้วย tensor (C6-C7)

ข้อจำกัด

  • (C1) is_unique(replica_groups)
  • (C2) size(replica_groups) ให้คำจำกัดความไว้ดังนี้
    • num_replicas หากใช้ cross_replica
    • num_replicas หากใช้ cross_replica_and_partition
    • num_processes หากใช้ flattened_ids
  • (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(result) = shape(operand)
  • (C7) element_type(result) = E

ตัวอย่าง

// num_replicas: 2
// num_partitions: 1
// %operand@(0, 0): [1, 2, 3, 4]
// %operand@(1, 0): [5, 6, 7, 8]
%result = "stablehlo.all_reduce"(%operand) ({
  ^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_handle = #stablehlo.channel_handle<handle = 0, type = 0>
} : (tensor<i64>) -> tensor<i64>
// %result@(0, 0): [6, 8, 10, 12]
// %result@(1, 0): [6, 8, 10, 12]

ตัวอย่างอื่นๆ

all_to_all

อรรถศาสตร์

ภายในแต่ละกลุ่มกระบวนการในตารางกระบวนการของ StableHLO จะแบ่งค่า Tensor operand ตาม split_dimension ออกเป็นส่วนต่างๆ กระจายส่วนที่แยกระหว่างกระบวนการ เชื่อมต่อส่วนที่กระจัดกระจายไปตาม concat_dimension และสร้าง result Tensor

การดำเนินการจะแยกตารางกริดกระบวนการของ StableHLO เป็น process_groups ซึ่งมีคำจำกัดความดังนี้

  • cross_replica(replica_groups) หาก channel_id <= 0
  • cross_partition(replica_groups) หาก channel_id > 0

หลังจากนั้น ภายในแต่ละ process_group:

  • split_parts@sender = split(operand@sender, split_count, split_dimension) สำหรับ sender ทั้งหมดใน process_group
  • scattered_parts@receiver = [split_parts@sender[receiver_index] for sender in process_group] โดยที่ receiver_index = process_group.index(receiver)
  • result@process = concatenate(scattered_parts@process, concat_dimension).

อินพุต

ป้ายกำกับ ชื่อ ประเภท ข้อจำกัด
(1) operand tensor หรือต่อ tensor ที่วัดปริมาณด้วย tensor (C1-C3), (C9)
(I2) split_dimension ค่าคงที่ของประเภท si64 (C1), (C2), (C9)
(1) concat_dimension ค่าคงที่ของประเภท si64 (C3), (C9)
(I4) split_count ค่าคงที่ของประเภท si64 (C2), (C4), (C8), (C9)
(1) replica_groups ค่าคงที่ tensor 2 มิติของประเภท si64 (C5-C8)
(1) channel_id ค่าคงที่ของประเภท si64

เอาต์พุต

ชื่อ ประเภท ข้อจำกัด
result tensor หรือต่อ tensor ที่วัดปริมาณด้วย tensor (C9)

ข้อจำกัด

  • (C1) 0 <= split_dimension < rank(operand)
  • (C2) dim(operand, split_dimension) % split_count = 0
  • (C3) 0 <= concat_dimension < rank(operand)
  • (C4) 0 < split_count
  • (C5) is_unique(replica_groups)
  • (C6) size(replica_groups) ให้คำจำกัดความไว้ดังนี้
    • num_replicas หากใช้ cross_replica
    • num_partitions หากใช้ cross_partition
  • (C7) 0 <= replica_groups < size(replica_groups)
  • (C8) dim(replica_groups, 1) = split_count
  • (C9) type(result) = type(operand) ยกเว้นสิ่งต่อไปนี้
    • dim(result, split_dimension) = dim(operand, split_dimension) / split_count.
    • dim(result, concat_dimension) = dim(operand, concat_dimension) * split_count.

ตัวอย่าง

// 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.all_to_all"(%operand) {
  split_dimension = 1 : i64,
  concat_dimension = 0 : i64,
  split_count = 2 : i64,
  replica_groups = dense<[[0, 1]]> : tensor<1x2xi64>
} : (tensor<2x4xi64>) -> tensor<4x2xi64>
// %result@(0, 0): [[1, 2],
//                  [5, 6],
//                  [9, 10],
//                  [13, 14]]
// %result@(1, 0): [[3, 4],
//                  [7, 8],
//                  [11, 12],
//                  [15, 16]]

ตัวอย่างอื่นๆ

และ

อรรถศาสตร์

ดำเนินการ AND ตามองค์ประกอบตาม tensor จำนวน 2 รายการ lhs และ rhs แล้วสร้าง result tensor ระบบจะดำเนินการดังต่อไปนี้โดยขึ้นอยู่กับประเภทองค์ประกอบ

  • สำหรับบูลีน: ตรรกะ AND
  • สำหรับจำนวนเต็ม: บิตไวส์ AND

อินพุต

ป้ายกำกับ ชื่อ ประเภท ข้อจำกัด
(1) lhs Tensor ของประเภทบูลีนหรือจำนวนเต็ม (C1)
(I2) rhs Tensor ของประเภทบูลีนหรือจำนวนเต็ม (C1)

เอาต์พุต

ชื่อ ประเภท ข้อจำกัด
result Tensor ของประเภทบูลีนหรือจำนวนเต็ม (C1)

ข้อจำกัด

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

อรรถศาสตร์

ดำเนินการดำเนินการ atan2 ตามองค์ประกอบใน lhs และ rhs Tensor และสร้าง Tensor result ระบบจะดำเนินการดังต่อไปนี้โดยขึ้นอยู่กับประเภทองค์ประกอบ

  • สำหรับเลขทศนิยม: atan2 จาก IEEE-754
  • สำหรับจำนวนเชิงซ้อน: จำนวนเชิงซ้อน atan2
  • สำหรับประเภทที่เล็กลง: dequantize_op_quantize(atan2, lhs, rhs, type(result))

อินพุต

ป้ายกำกับ ชื่อ ประเภท ข้อจำกัด
(1) lhs tensor ของชนิดจุดลอยตัวหรือชนิดเชิงซ้อนหรือต่อ tensor ที่วัดปริมาณด้วย tensor (C1)
(I2) rhs tensor ของชนิดจุดลอยตัวหรือชนิดเชิงซ้อนหรือต่อ tensor ที่วัดปริมาณด้วย tensor (C1)

เอาต์พุต

ชื่อ ประเภท ข้อจำกัด
result tensor ของชนิดจุดลอยตัวหรือชนิดเชิงซ้อนหรือต่อ tensor ที่วัดปริมาณด้วย tensor (C1)

ข้อจำกัด

  • (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 และสร้าง Tensor grad_operand, grad_scale และ grad_offset อย่างเป็นทางการ การดำเนินการนี้อาจแสดงเป็นการแยกย่อยการดำเนินการ StableHLO ที่มีอยู่โดยใช้ไวยากรณ์ Python ดังนี้

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

อินพุต

ป้ายกำกับ ชื่อ ประเภท ข้อจำกัด
(1) operand tensor ของชนิดจุดลอยตัวหรือต่อ tensor ที่วัดปริมาณแล้ว (C1-C3), (C5)
(I2) scale tensor 1 มิติของชนิดจุดลอยตัวหรือต่อ tensor ที่เล็กลง (C2), (C4), (C5)
(1) mean tensor 1 มิติของชนิดจุดลอยตัวหรือต่อ tensor ที่เล็กลง (C2), (C4)
(I4) variance tensor 1 มิติของชนิดจุดลอยตัวหรือต่อ tensor ที่เล็กลง (C2), (C4)
(1) grad_output tensor ของชนิดจุดลอยตัวหรือต่อ tensor ที่วัดปริมาณแล้ว (C2), (C3)
(1) epsilon ค่าคงที่ของประเภท f32
(1) feature_index ค่าคงที่ของประเภท si64 (C1), (C5)

เอาต์พุต

ชื่อ ประเภท ข้อจำกัด
grad_operand tensor ของชนิดจุดลอยตัวหรือต่อ tensor ที่วัดปริมาณแล้ว (C2), (C3)
grad_scale tensor 1 มิติของชนิดจุดลอยตัวหรือต่อ tensor ที่เล็กลง (C2), (C4)
grad_offset tensor 1 มิติของชนิดจุดลอยตัวหรือต่อ tensor ที่เล็กลง (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

อรรถศาสตร์

ทำให้ Tensor operand เป็นมาตรฐานในทุกมิติข้อมูลยกเว้นมิติข้อมูล feature_index และสร้าง Tensor 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))

อินพุต

ป้ายกำกับ ชื่อ ประเภท ข้อจำกัด
(1) operand tensor ของชนิดจุดลอยตัวหรือต่อ tensor ที่วัดปริมาณแล้ว (C1-C7)
(I2) scale tensor 1 มิติของชนิดจุดลอยตัวหรือต่อ tensor ที่เล็กลง (C2), (C3)
(1) offset tensor 1 มิติของชนิดจุดลอยตัวหรือต่อ tensor ที่เล็กลง (C2), (C4)
(I4) mean tensor 1 มิติของชนิดจุดลอยตัวหรือต่อ tensor ที่เล็กลง (C5)
(1) variance tensor 1 มิติของชนิดจุดลอยตัวหรือต่อ tensor ที่เล็กลง (C2) (C6)
(1) epsilon ค่าคงที่ของประเภท f32
(1) feature_index ค่าคงที่ของประเภท si64 (C1), (C3-C6)

เอาต์พุต

ชื่อ ประเภท ข้อจำกัด
result tensor ของชนิดจุดลอยตัวหรือต่อ tensor ที่วัดปริมาณแล้ว (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 และปรับ tensor ของ operand ที่ทำให้เกิด output, batch_mean และ batch_var เป็นมาตรฐาน อย่างเป็นทางการ การดำเนินการนี้อาจแสดงเป็นการแยกย่อยการดำเนินการ StableHLO ที่มีอยู่โดยใช้ไวยากรณ์ Python ดังนี้

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

อินพุต

ป้ายกำกับ ชื่อ ประเภท ข้อจำกัด
(1) operand tensor ของชนิดจุดลอยตัวหรือต่อ tensor ที่วัดปริมาณแล้ว (C1)
(I2) scale tensor 1 มิติของจุดลอยตัวหรือต่อ tensor ที่เล็กลง (C2), (C3)
(1) offset tensor 1 มิติของจุดลอยตัวหรือต่อ tensor ที่เล็กลง (C2), (C4)
(I4) epsilon ค่าคงที่ของประเภท f32 (C1), (C3-C6)
(1) feature_index ค่าคงที่ของประเภท si64 (C1), (C3-C6)

เอาต์พุต

ชื่อ ประเภท ข้อจำกัด
output tensor ของชนิดจุดลอยตัวหรือต่อ tensor ที่วัดปริมาณแล้ว (C7)
batch_mean tensor 1 มิติของจุดลอยตัวหรือต่อ tensor ที่เล็กลง (C2), (C5)
batch_var tensor 1 มิติของจุดลอยตัวหรือต่อ tensor ที่เล็กลง (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

อรรถศาสตร์

ดำเนินการบิตแคสต์บน Tensor operand และสร้าง result Tensor ซึ่งมีการตีความบิตของ Tensor ทั้งหมด operand อีกครั้งโดยใช้ประเภทของ Tensor ของ 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 จะแสดงผลค่าที่กำหนดในหน่วยความจำ และลักษณะการทำงานของค่าดังกล่าวเป็นการกำหนดการติดตั้งใช้งาน เนื่องจากการแสดง tensors ที่แท้จริงนั้นเป็นตัวกำหนดการติดตั้งใช้งาน และการนำเสนอประเภทองค์ประกอบที่แน่นอนนั้นมีการกำหนดการติดตั้งใช้งานด้วยเช่นกัน

อินพุต

ป้ายกำกับ ชื่อ ประเภท ข้อจำกัด
(1) operand tensor หรือ tensor ที่วัดปริมาณแล้ว (C1-C2)

เอาต์พุต

ชื่อ ประเภท ข้อจำกัด
result tensor หรือ tensor ที่วัดปริมาณแล้ว (C1-C2)

ข้อจำกัด

  • (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.
    • dim(result, i) = dim(operand, i) สำหรับ 0 <= i < R ทั้งหมด
    • dim(result, R) * num_bits(E') = num_bits(E).
    • หาก num_bits(E') > num_bits(E):
    • rank(result) = R - 1.
    • dim(result, i) = dim(operand, i) สำหรับ 0 <= i < R ทั้งหมด
    • 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

อรรถศาสตร์

ขยายมิติข้อมูลและ/หรืออันดับของ Tensor อินพุตโดยการทำซ้ำข้อมูลใน Tensor operand และสร้าง Tensor result เป็นทางการมากขึ้นแล้ว result[result_index] = operand[operand_index] สถานที่สำหรับ d ทั้งหมดใน axes(operand):

  • operand_index[d] = 0 หาก dim(operand, d) = 1
  • หากไม่ใช่ operand_index[d] = result_index[broadcast_dimensions[d]]

อินพุต

ป้ายกำกับ ชื่อ ประเภท ข้อจำกัด
(1) operand tensor หรือ tensor ที่วัดปริมาณแล้ว (C1-C2), (C5-C6)
(I2) broadcast_dimensions ค่าคงที่ tensor แบบ 1 มิติของประเภท si64 (C2-C6)

เอาต์พุต

ชื่อ ประเภท ข้อจำกัด
result tensor หรือ tensor ที่วัดปริมาณแล้ว (C1), (C3), (C5-C6)

ข้อจำกัด

  • (C1) element_type(result) ให้บริการโดย
    • element_type(operand) หากเป็น !is_per_axis_quantized(operand)
    • element_type(operand) เว้นแต่ว่า quantization_dimension(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) สําหรับ d ทั้งหมดใน axes(operand) ให้ทําดังนี้
    • 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]
//            ]
//          ]

ตัวอย่างอื่นๆ

เคส

อรรถศาสตร์

สร้างเอาต์พุตจากการทำงานเพียง 1 ฟังก์ชันจาก branches โดยขึ้นอยู่กับค่าของ index อย่างเป็นทางการ result = selected_branch() ที่

  • selected_branch = branches[index] หาก 0 <= index < size(branches)
  • หากไม่ใช่ selected_branch = branches[-1]

อินพุต

ป้ายกำกับ ชื่อ ประเภท ข้อจำกัด
(1) index Tensor แบบ 0 มิติของประเภท si32
(I2) branches จำนวนฟังก์ชันต่างๆ (C1-C4)

เอาต์พุต

ชื่อ ประเภท ข้อจำกัด
results จำนวน tensors หลากหลายแบบ, tensors ในเชิงปริมาณ หรือโทเค็น (C4)

ข้อจำกัด

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

ตัวอย่างอื่นๆ

Cbrt

อรรถศาสตร์

ดำเนินการรากลูกบาศก์ตามองค์ประกอบตามองค์ประกอบใน Tensor operand และสร้าง Tensor result ระบบจะดำเนินการดังต่อไปนี้โดยขึ้นอยู่กับประเภทองค์ประกอบ

  • สำหรับเลขทศนิยม: rootn(x, 3) จาก IEEE-754
  • สําหรับจํานวนเชิงซ้อน: รากจํานวนเชิงซ้อน
  • สำหรับประเภทที่เล็กลง: dequantize_op_quantize(cbrt, operand, type(result))

อินพุต

ป้ายกำกับ ชื่อ ประเภท ข้อจำกัด
(1) operand tensor ของชนิดจุดลอยตัวหรือชนิดเชิงซ้อนหรือต่อ tensor ที่วัดปริมาณด้วย tensor (C1)

เอาต์พุต

ชื่อ ประเภท ข้อจำกัด
result tensor ของชนิดจุดลอยตัวหรือชนิดเชิงซ้อนหรือต่อ tensor ที่วัดปริมาณด้วย tensor (C1)

ข้อจำกัด

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

ตัวอย่างอื่นๆ

Ceil

อรรถศาสตร์

ดำเนินการ Tensor ตามองค์ประกอบตาม tensor ของ operand และสร้าง Tensor result ใช้การดำเนินการ roundToIntegralTowardPositive จากข้อกำหนด IEEE-754 สำหรับประเภทที่แบ่งปริมาณแล้ว จะแสดงผล dequantize_op_quantize(ceil, operand, type(result))

อินพุต

ป้ายกำกับ ชื่อ ประเภท ข้อจำกัด
(1) operand tensor ของชนิดจุดลอยตัวหรือต่อ tensor ที่วัดปริมาณแล้ว (C1)

เอาต์พุต

ชื่อ ประเภท ข้อจำกัด
result tensor ของชนิดจุดลอยตัวหรือต่อ tensor ที่วัดปริมาณแล้ว (C1)

ข้อจำกัด

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

ตัวอย่างอื่นๆ

Cholesky

อรรถศาสตร์

คำนวณการแยกตัวของชูเลสกี้ของเมทริกซ์กลุ่มหนึ่ง

อย่างเป็นทางการสำหรับ i ทั้งหมดใน index_space(result) result[i0, ..., iR-3, :, :] คือการแยกตัวแบบ Cholesky ของ a[i0, ..., iR-3, :, :] ในรูปแบบของสามเหลี่ยมล่าง (หาก lower เป็น true) หรือเมทริกซ์รูปสามเหลี่ยมบน (หาก lower เป็น false) ค่าเอาต์พุตในรูปสามเหลี่ยมตรงข้ามกัน เช่น รูปสามเหลี่ยมด้านบนที่เข้มงวดหรือสามเหลี่ยมล่างสุดแคบตามลำดับ จะได้รับการกำหนดการนำไปใช้งาน

หากมี i ที่เมทริกซ์อินพุตไม่ใช่เมทริกซ์บวกลบของเฮอร์มิเชียน จะไม่มีการระบุลักษณะการทำงาน

สำหรับประเภทที่แบ่งปริมาณแล้ว จะแสดงผล dequantize_op_quantize(lambda operand: cholesky(operand, lower), a, type(result))

อินพุต

ป้ายกำกับ ชื่อ ประเภท ข้อจำกัด
(1) a tensor ของชนิดจุดลอยตัวหรือชนิดเชิงซ้อนหรือต่อ tensor ที่วัดปริมาณด้วย tensor (C1-C3)
(I2) lower ค่าคงที่ tensor 0 มิติของประเภท i1

เอาต์พุต

ชื่อ ประเภท ข้อจำกัด
result tensor ของชนิดจุดลอยตัวหรือชนิดเชิงซ้อนหรือต่อ tensor ที่วัดปริมาณด้วย tensor (C1)

ข้อจำกัด

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

ที่ยึด

อรรถศาสตร์

ยึดทุกองค์ประกอบของ tensor operand ระหว่างค่าต่ำสุดและสูงสุด แล้วสร้าง tensor 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)

อินพุต

ป้ายกำกับ ชื่อ ประเภท ข้อจำกัด
(1) min tensor หรือต่อ tensor ที่วัดปริมาณด้วย tensor (C1), (C3)
(I2) operand tensor หรือต่อ tensor ที่วัดปริมาณด้วย tensor (C1-C4)
(1) max tensor หรือต่อ tensor ที่วัดปริมาณด้วย tensor (C2), (C3)

เอาต์พุต

ชื่อ ประเภท ข้อจำกัด
result tensor หรือต่อ tensor ที่วัดปริมาณด้วย tensor (C4)

ข้อจำกัด

  • (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 ให้ส่งค่า Tensor operand จากกระบวนการต้นทางไปยังกระบวนการเป้าหมายและสร้าง Tensor result

การดำเนินการจะแยกตารางกริดกระบวนการของ StableHLO เป็น process_groups ซึ่งมีคำจำกัดความดังนี้

  • cross_replica(replica_groups) หาก channel_id <= 0
  • cross_partition(replica_groups) หาก channel_id > 0

หลังจากนั้น result@process จะมอบให้โดย

  • operand@process_groups[i, 0] หากมี i เพื่อให้กระบวนการอยู่ใน process_groups[i]
  • broadcast_in_dim(constant(0, element_type(result)), [], type(result)) ไม่เช่นนั้น

อินพุต

ป้ายกำกับ ชื่อ ประเภท ข้อจำกัด
(1) operand Tensor (C3)
(I2) replica_groups จำนวนแปรผันของค่าคงที่ tensor 1 มิติของประเภท si64 (C1), (C2)
(1) channel_id ค่าคงที่ของประเภท si64

เอาต์พุต

ชื่อ ประเภท ข้อจำกัด
result Tensor (C3)

ข้อจำกัด

  • (C1) is_unique(replica_groups)
  • (C2) 0 <= replica_groups < N โดยให้นิยาม N ว่า
    • num_replicas หากใช้ cross_replica
    • num_partitions หากใช้ cross_partition
  • (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 ให้ส่งค่าของ Tensor operand จากกระบวนการต้นทางไปยังกระบวนการเป้าหมายและสร้าง Tensor result

การดำเนินการจะแยกตารางกริดกระบวนการของ StableHLO เป็น process_groups ซึ่งมีคำจำกัดความดังนี้

  • cross_replica(source_target_pairs) หาก channel_id <= 0
  • cross_partition(source_target_pairs) หาก channel_id > 0

หลังจากนั้น 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)) ไม่เช่นนั้น

อินพุต

ป้ายกำกับ ชื่อ ประเภท ข้อจำกัด
(1) operand tensor หรือต่อ tensor ที่วัดปริมาณด้วย tensor (C5)
(I2) source_target_pairs ค่าคงที่ tensor 2 มิติของประเภท si64 (C1-C4)
(1) channel_id ค่าคงที่ของประเภท si64

เอาต์พุต

ชื่อ ประเภท ข้อจำกัด
result tensor หรือต่อ tensor ที่วัดปริมาณด้วย tensor (C1)

ข้อจำกัด

  • (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 ว่า
    • num_replicas หากใช้ cross_replica
    • num_partitions หากใช้ cross_partition
  • (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]]

ตัวอย่างอื่นๆ

เปรียบเทียบ

อรรถศาสตร์

ทำการเปรียบเทียบ tensors lhs และ rhs ตามองค์ประกอบตาม comparison_direction และ compare_type แล้วสร้าง result Tensor

ค่าของ 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 การทดสอบจะใช้การดำเนินการ IEEE-754 ต่อไปนี้

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

สำหรับประเภทองค์ประกอบจุดลอยตัวที่มี compare_type = TOTALORDER การทดสอบจะใช้ชุดค่าผสมของการดำเนินการ totalOrder และ compareQuietEqual จาก IEEE-754 ดูเหมือนว่าจะไม่มีการใช้งานฟีเจอร์นี้ เราจึงมีแผนที่จะนำออกในอนาคต (#584)

สําหรับประเภทองค์ประกอบที่ซับซ้อน การเปรียบเทียบแบบพจนานุกรมของคู่ (real, imag) จะดําเนินการโดยใช้ comparison_direction และ compare_type ที่ให้ไว้ การตั้งอันดับด้วยจำนวนเชิงซ้อนเกี่ยวข้องกับความหมายที่น่าประหลาดใจ ดังนั้นในอนาคตเราจึงวางแผนที่จะยกเลิกการรองรับจำนวนเชิงซ้อนเมื่อ comparison_direction เท่ากับ GE, GT, LE หรือ LT (#560)

สำหรับประเภทที่แบ่งปริมาณแล้ว จะแสดงผล dequantize_compare(lhs, rhs, comparison_direction)

อินพุต

ป้ายกำกับ ชื่อ ประเภท ข้อจำกัด
(1) lhs tensor หรือต่อ tensor ที่วัดปริมาณด้วย tensor (C1-C3)
(I2) rhs tensor หรือต่อ tensor ที่วัดปริมาณด้วย tensor (C1-C2)
(1) comparison_direction enum ของ EQ, NE, GE, GT, LE และ LT
(I4) compare_type enum ของ FLOAT, TOTALORDER, SIGNED และ UNSIGNED (C3)

เอาต์พุต

ชื่อ ประเภท ข้อจำกัด
result Tensor ของประเภทบูลีน (C2)

ข้อจำกัด

  • (C1) baseline_element_type(lhs) = baseline_element_type(rhs)
  • (C2) shape(lhs) = shape(rhs) = shape(result)
  • (C3) compare_type ให้คำจำกัดความไว้ดังนี้
    • SIGNED หาก is_signed_integer(element_type(lhs))
    • UNSIGNED หาก is_unsigned_integer(element_type(lhs)) or is_boolean(element_type(lhs))
    • FLOAT หรือ TOTALORDER หากเป็น is_float(element_type(lhs))
    • FLOAT หาก is_complex(element_type(lhs))

ตัวอย่าง

// %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 และสร้าง Tensor result

อินพุต

ป้ายกำกับ ชื่อ ประเภท ข้อจำกัด
(1) lhs Tensor ประเภท f32 หรือ f64 (C1-C3)
(I2) rhs Tensor ประเภท f32 หรือ f64 (C1)

เอาต์พุต

ชื่อ ประเภท ข้อจำกัด
result Tensor ของประเภทที่ซับซ้อน (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)]

ตัวอย่างอื่นๆ

concatenate

อรรถศาสตร์

เชื่อมต่อ inputs ในมิติข้อมูล dimension ในลำดับเดียวกันกับอาร์กิวเมนต์ที่ระบุ และสร้าง result Tensor อย่างเป็นทางการคือ result[i0, ..., id, ..., iR-1] = inputs[k][i0, ..., kd, ..., iR-1] ซึ่ง

  1. id = d0 + ... + dk-1 + kd.
  2. d เท่ากับ dimension และ d0 ... เป็นขนาดมิติข้อมูลที่ d ของ inputs

อินพุต

ป้ายกำกับ ชื่อ ประเภท ข้อจำกัด
(1) inputs จำนวน tensors แบบแปรผันหรือต่อ tensor ที่วัดปริมาณด้วย tensor (C1-C6)
(I2) dimension ค่าคงที่ของประเภท si64 (C2), (C4), (C6)

เอาต์พุต

ชื่อ ประเภท ข้อจำกัด
result tensor หรือต่อ tensor ที่วัดปริมาณด้วย tensor (C5-C6)

ข้อจำกัด

  • (C1) same(element_type(inputs...))
  • (C2) same(shape(inputs...)) ยกเว้น dim(inputs..., dimension)
  • (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]]

ตัวอย่างอื่นๆ

ค่าคงที่

อรรถศาสตร์

สร้าง output Tensor จาก value คงที่

อินพุต

ป้ายกำกับ ชื่อ ประเภท ข้อจำกัด
(1) value ค่าคงที่ (C1)

เอาต์พุต

ชื่อ ประเภท ข้อจำกัด
output tensor หรือ tensor ที่วัดปริมาณแล้ว (C1)

ข้อจำกัด

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

ตัวอย่างอื่นๆ

ทำให้เกิด Conversion

อรรถศาสตร์

ทำ Conversion ตามองค์ประกอบจากประเภทองค์ประกอบหนึ่งไปเป็นอีกประเภทหนึ่งใน operand Tensor และสร้าง Tensor result

สำหรับ Conversion boolean-to-any-supported-type ค่า false จะแปลงไปเป็น 0 และแปลงค่า true เป็น 1 สำหรับ Conversion any-supported-type-to-boolean ระบบจะแปลงค่า 0 เป็น false และค่าที่ไม่ใช่ 0 จะถูกแปลงเป็น true ดูวิธีการทำงาน สำหรับประเภทที่ซับซ้อนได้ที่ด้านล่าง

สำหรับ Conversion ที่เกี่ยวข้องกับ integer-to-integer, integer-to-Floing-point หรือ Floating-point-to-Floing-point หากค่าแหล่งที่มาสามารถนำเสนอได้ในประเภทปลายทางทุกประการ ค่าผลลัพธ์จะเป็นการแทนค่าที่ตรงกับความเป็นจริง มิเช่นนั้น ลักษณะการทำงานจะเป็น TBD (#180)

สำหรับ Conversion ที่เกี่ยวข้องกับ floating-point-to-integer ระบบจะตัดส่วนที่เป็นเศษส่วนออก หากแสดงค่าที่ตัดในประเภทปลายทางไม่ได้ ลักษณะการทำงานจะเป็น TBD (#180)

Conversion ที่เกี่ยวข้องกับ complex-to-complex ใช้ลักษณะการทำงานเดียวกันกับ Conversion ของ floating-point-to-Floing-point สำหรับการแปลงส่วนจริงและส่วนจินตภาพ

สำหรับ Conversion แบบ complex-to-any-other-type และ complex-to-any-other-type ระบบจะไม่สนใจค่าจินตภาพของแหล่งที่มาหรือค่าจินตภาพปลายทางจะเป็น 0 ตามลำดับ การแปลงส่วนจริงจะเป็นไปตาม Conversion จุดลอยตัว

ตามหลักแล้ว การดําเนินการนี้อาจแสดงลําดับความสําคัญ (การแปลงจาก tensors ที่ทําให้เล็กลงเป็น tensors ปกติ) การทําให้ปริมาณ (การแปลงจาก tensors ปกติไปเป็น tensors เชิงปริมาณ) และการแปลงค่าซ้ำ (Conversion ระหว่าง tensors เชิงปริมาณ) แต่ในตอนนี้เราได้ทำการดำเนินการเฉพาะให้กับ tensor ดังกล่าว -uniform_dequantize สำหรับ Use Case แรกและ uniform_quantize สำหรับ Use Case ครั้งที่ 2 และ 3 ในอนาคต การดำเนินการทั้ง 2 อย่างนี้อาจผสานรวมเป็น convert (#1576)

อินพุต

ป้ายกำกับ ชื่อ ประเภท ข้อจำกัด
(1) operand Tensor (C1)

เอาต์พุต

ชื่อ ประเภท ข้อจำกัด
result Tensor (C1)

ข้อจำกัด

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

ตัวอย่างอื่นๆ

Convolution

อรรถศาสตร์

การประมวลผลจะจุดผลิตภัณฑ์ระหว่างหน้าต่างของ 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 สำหรับ output_spatial_index ทั้งหมดใน index_space(dim(result, output_spatial_dimensions...)) 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))

อินพุต

ป้ายกำกับ ชื่อ ประเภท ข้อจำกัด
(1) lhs tensor หรือต่อ tensor ที่วัดปริมาณด้วย tensor (C1), (C10-C11), (C14) (C25), (C27-C30)
(I2) rhs tensor หรือ tensor ที่วัดปริมาณแล้ว (C1), (C14-C16), (C25), (C27-C32)
(1) window_strides ค่าคงที่ tensor แบบ 1 มิติของประเภท si64 (C2-C3), (C25)
(I4) padding ค่าคงที่ tensor 2 มิติของประเภท si64 (C4) (C25)
(1) lhs_dilation ค่าคงที่ tensor แบบ 1 มิติของประเภท si64 (C5-C6), (C25)
(1) rhs_dilation ค่าคงที่ tensor แบบ 1 มิติของประเภท si64 (C7-C8), (C25)
(1) window_reversal ค่าคงที่ tensor แบบ 1 มิติของประเภท i1 (C9)
(i8) input_batch_dimension ค่าคงที่ของประเภท si64 (C10), (C13), (C25)
(I9) input_feature_dimension ค่าคงที่ของประเภท si64 (C11), (C13-C14)
(10) input_spatial_dimensions ค่าคงที่ tensor แบบ 1 มิติของประเภท si64 (C12), (C13), (C25)
(11) kernel_input_feature_dimension ค่าคงที่ของประเภท si64 (C14), (C18)
(12) kernel_output_feature_dimension ค่าคงที่ของประเภท si64 (C15-C16), (C18), (C25), (C32)
(13) kernel_spatial_dimensions ค่าคงที่ tensor แบบ 1 มิติของประเภท si64 (C17-C18), (C25)
(14) output_batch_dimension ค่าคงที่ของประเภท si64 (C20) (C25)
(15) output_feature_dimension ค่าคงที่ของประเภท si64 (C20), (C25), (C33)
(16) output_spatial_dimensions ค่าคงที่ tensor แบบ 1 มิติของประเภท si64 (C19-C20) (C25)
(17) feature_group_count ค่าคงที่ของประเภท si64 (C11), (C14), (C16), (C21), (C23)
(18) batch_group_count ค่าคงที่ของประเภท si64 (C10), (C15), (C22), (C23), (C25)
(19) precision_config จำนวน enum ของ DEFAULT, HIGH และ HIGHEST (C24)

เอาต์พุต

ชื่อ ประเภท ข้อจำกัด
result tensor หรือ tensor ที่วัดปริมาณแล้ว (C25-C28), (C30-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) ให้คำจำกัดความไว้ดังนี้
    • dim(lhs, input_batch_dimension) / batch_group_count หาก result_dim = output_batch_dimension
    • dim(rhs, kernel_output_feature_dimension) หาก result_dim = 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
  • หากการดำเนินการใช้ Tensor แบบไม่วัดปริมาณ:
    • (C27) element_type(lhs) = element_type(rhs) = element_type(result)
  • หากการดำเนินการใช้ tensors ที่วัดปริมาณแล้ว ให้ทำดังนี้
    • (C28) is_quantized_tensor(lhs) and is_quantized_tensor(rhs) and is_quantized_tensor(result)
    • (C29) storage_type(lhs) = storage_type(rhs)
    • (C30) expressed_type(lhs) = expressed_type(rhs) = expressed_type(result)
    • (C31) หากเป็น is_per_tensor_quantized(rhs) ให้ is_per_tensor_quantized(result)
    • (C32) หากเป็น is_per_axis_quantized(rhs) ให้ quantization_dimension(rhs) = kernel_output_feature_dimension
    • (C33) หากเป็น is_per_axis_quantized(result) ให้ quantization_dimension(result) = output_feature_dimension

ตัวอย่าง

// %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 = dense<4> : tensor<2xi64>,
  padding = dense<0> : tensor<2x2xi64>,
  lhs_dilation = dense<2> : tensor<2xi64>,
  rhs_dilation = dense<1> : tensor<2xi64>,
  window_reversal = dense<false> : tensor<2xi1>,
  // 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]>,
  feature_group_count = 1 : i64,
  batch_group_count = 1 : i64,
  precision_config = [#stablehlo<precision DEFAULT>, #stablehlo<precision DEFAULT>]
} : (tensor<1x4x4x1xi32>, tensor<3x3x1x1xi32>) -> tensor<1x2x2x1xi32>
// %result: [[
//            [[10], [26]],
//            [[46], [62]]
//          ]]

โคไซน์

อรรถศาสตร์

ดำเนินการดำเนินการโคไซน์ตามองค์ประกอบบน Tensor operand และสร้าง Tensor result ระบบจะดำเนินการดังต่อไปนี้โดยขึ้นอยู่กับประเภทองค์ประกอบ

  • สำหรับเลขทศนิยม: cos จาก IEEE-754
  • สำหรับจำนวนเชิงซ้อน: โคไซน์เชิงซ้อน
  • สำหรับประเภทที่เล็กลง: dequantize_op_quantize(cosine, operand, type(result))

อินพุต

ป้ายกำกับ ชื่อ ประเภท ข้อจำกัด
(1) operand tensor ของชนิดจุดลอยตัวหรือชนิดเชิงซ้อนหรือต่อ tensor ที่วัดปริมาณด้วย tensor (C1)

เอาต์พุต

ชื่อ ประเภท ข้อจำกัด
result tensor ของชนิดจุดลอยตัวหรือชนิดเชิงซ้อนหรือต่อ tensor ที่วัดปริมาณด้วย tensor (C1)

ข้อจำกัด

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

อรรถศาสตร์

ดำเนินการนับตามองค์ประกอบของจำนวนบิตนำ 0 บิตใน Tensor ใน operand และสร้าง tensor result

อินพุต

ป้ายกำกับ ชื่อ ประเภท ข้อจำกัด
(1) operand Tensor ของประเภทจำนวนเต็ม (C1)

เอาต์พุต

ชื่อ ประเภท ข้อจำกัด
result Tensor ของประเภทจำนวนเต็ม (C1)

ข้อจำกัด

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

อินพุต

ป้ายกำกับ ชื่อ ประเภท
(1) inputs จำนวนค่าที่แตกต่างกัน
(I2) call_target_name ค่าคงที่ของประเภท string
(1) has_side_effect ค่าคงที่ของประเภท i1
(I4) backend_config ค่าคงที่ของประเภท string
(1) api_version ค่าคงที่ของประเภท si32
(1) called_computations จำนวนคงที่ของชนิด string

เอาต์พุต

ชื่อ ประเภท
results จำนวนค่าที่แตกต่างกัน

ตัวอย่าง

%results = "stablehlo.custom_call"(%input0) {
  call_target_name = "foo",
  has_side_effect = false,
  backend_config = "bar",
  api_version = 1 : i32,
  called_computations = [@foo]
} : (tensor<f64>) -> tensor<f64>

หาร

อรรถศาสตร์

ทำการหาร Tensor หาร lhs และตัวหาร rhs ตามองค์ประกอบ แล้วสร้าง result Tensor ระบบจะดำเนินการดังต่อไปนี้โดยขึ้นอยู่กับประเภทองค์ประกอบ

  • สำหรับจำนวนเต็ม: การหารจำนวนเต็มที่สร้างผลหารพีชคณิตที่มีเศษส่วนใดๆ ที่ถูกทิ้ง
  • สำหรับเลขทศนิยม: division จาก IEEE-754
  • สำหรับจำนวนเชิงซ้อน: การหารเชิงซ้อน
  • สำหรับประเภทที่เล็กลง
    • dequantize_op_quantize(divide, lhs, rhs, type(result)).

อินพุต

ป้ายกำกับ ชื่อ ประเภท ข้อจำกัด
(1) lhs tensor ของจำนวนเต็ม ชนิดจุดลอยตัว หรือชนิดเชิงซ้อน หรือ tensor ที่วัดปริมาณด้วยต่อ tensor (C1)
(I2) rhs tensor ของจำนวนเต็ม ชนิดจุดลอยตัว หรือชนิดเชิงซ้อน หรือ tensor ที่วัดปริมาณด้วยต่อ tensor (C1)

เอาต์พุต

ชื่อ ประเภท ข้อจำกัด
result tensor ของจำนวนเต็ม จุดลอยตัว หรือชนิดเชิงซ้อน หรือ tensor ที่วัดปริมาณด้วยต่อ tensor (C1)

ข้อจำกัด

  • (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 จะสร้าง tensor จำนวน 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))

ซึ่งจะระบุเฉพาะความหมายสำหรับการหาปริมาณต่อ tensor เท่านั้น การคำนวณจำนวนตามแกนอยู่ระหว่างดำเนินการ (#1574) นอกจากนี้ ในอนาคตเราอาจพิจารณาเพิ่มการรองรับการระบุปริมาณแบบผสม (#1575)

precision_config จะควบคุมการทดแทนกันระหว่างความเร็วและความแม่นยำสำหรับการคำนวณแบ็กเอนด์ของ Accelerator ซึ่งอาจเป็นอย่างใดอย่างหนึ่งต่อไปนี้ (ในขณะนี้ ระบบไม่ได้กำหนดความหมายของค่า enum เหล่านี้ไว้ แต่เรามีแผนที่จะจัดการเรื่องนี้ใน #755)

  • DEFAULT: การคำนวณเร็วที่สุด แต่ใกล้เคียงตัวเลขเดิมน้อยที่สุด
  • HIGH: การคำนวณช้าลง แต่ใกล้เคียงตัวเลขเดิมมากกว่า
  • HIGHEST: การคำนวณแบบช้าที่สุด แต่เป็นการคาดประมาณที่แม่นยำที่สุดกับจำนวนเดิม

อินพุต

ป้ายกำกับ ชื่อ ประเภท ข้อจำกัด
(1) lhs tensor หรือต่อ tensor ที่วัดปริมาณด้วย tensor (C5-C6), (C9-C10), (C12-C16)
(I2) rhs tensor หรือต่อ tensor ที่วัดปริมาณด้วย tensor (C7-C10), (C12)
(1) lhs_batching_dimensions ค่าคงที่ tensor แบบ 1 มิติของประเภท si64 (C1), (C3), (C5), (C9), (C12)
(I4) rhs_batching_dimensions ค่าคงที่ tensor แบบ 1 มิติของประเภท si64 (C1), (C4), (C7), (C9)
(1) lhs_contracting_dimensions ค่าคงที่ tensor แบบ 1 มิติของประเภท si64 (C2), (C3), (C6), (C10)
(1) rhs_contracting_dimensions ค่าคงที่ tensor แบบ 1 มิติของประเภท si64 (C2), (C4), (C8), (C10)
(1) precision_config จำนวน enum ของ DEFAULT, HIGH และ HIGHEST (C11)

เอาต์พุต

ชื่อ ประเภท ข้อจำกัด
result tensor หรือต่อ tensor ที่วัดปริมาณด้วย tensor (C12), (C14), (C16)

ข้อจำกัด

  • (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)
  • หากการดำเนินการใช้ Tensor แบบไม่วัดปริมาณ:
    • (C13) element_type(lhs) = element_type(rhs)
  • หากการดำเนินการใช้ tensors ที่วัดปริมาณแล้ว ให้ทำดังนี้
    • (C14) is_quantized(lhs) and is_quantized(rhs) and is_quantized(result)
    • (C15) storage_type(lhs) = storage_type(rhs)
    • (C16) expressed_type(lhs) = expressed_type(rhs) = expressed_type(result)
    • (C17) zero_points(rhs) = 0

ตัวอย่าง

// %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>]
} : (tensor<2x2x2xi64>, tensor<2x2x2xi64>) -> tensor<2x2x2xi64>
// %result: [
//           [[1, 2],
//            [3, 4]],
//           [[5, 6],
//            [7, 8]]
//          ]

ตัวอย่างอื่นๆ

dynamic_slice

อรรถศาสตร์

แยกสไลซ์จาก operand โดยใช้ดัชนีเริ่มต้นที่คำนวณแบบไดนามิก และสร้าง Tensor 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.

อินพุต

ป้ายกำกับ ชื่อ ประเภท ข้อจำกัด
(1) operand tensor หรือต่อ tensor ที่วัดปริมาณด้วย tensor (C1), (C2), (C4)
(I2) start_indices จำนวนตัวแปรของ tensors 0 มิติของจำนวนเต็ม (C2), (C3)
(1) slice_sizes ค่าคงที่ tensor แบบ 1 มิติของประเภท si64 (C2), (C4), (C5)

เอาต์พุต

ชื่อ ประเภท ข้อจำกัด
result tensor หรือต่อ tensor ที่วัดปริมาณด้วย tensor (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 = dense<[2, 2]> : tensor<2xi64>
} : (tensor<4x4xi32>, tensor<i64>, tensor<i64>) -> tensor<2x2xi32>
// %result: [
//           [1, 1],
//           [1, 1]
//          ]

ตัวอย่างอื่นๆ

dynamic_update_slice

อรรถศาสตร์

สร้าง result tensor ซึ่งเท่ากับ operand tensor เว้นแต่สไลซ์ที่เริ่มต้นที่ 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]

อินพุต

ป้ายกำกับ ชื่อ ประเภท ข้อจำกัด
(1) operand tensor หรือต่อ tensor ที่วัดปริมาณด้วย tensor (C1-C4) (C6)
(I2) update tensor หรือต่อ tensor ที่วัดปริมาณด้วย tensor (C2), (C3), (C6)
(1) start_indices จำนวนตัวแปรของ tensors 0 มิติของจำนวนเต็ม (C4) (C5)

เอาต์พุต

ชื่อ ประเภท ข้อจำกัด
result tensor หรือต่อ tensor ที่วัดปริมาณด้วย tensor (C1)

ข้อจำกัด

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

ตัวอย่างอื่นๆ

เลขชี้กำลัง

อรรถศาสตร์

ดำเนินการเลขชี้กำลังตามองค์ประกอบใน Tensor operand และสร้าง Tensor result ระบบจะดำเนินการดังต่อไปนี้โดยขึ้นอยู่กับประเภทองค์ประกอบ

  • สำหรับเลขทศนิยม: exp จาก IEEE-754
  • สำหรับจำนวนเชิงซ้อน: เลขชี้กำลังเชิงซ้อน
  • สำหรับประเภทที่เล็กลง: dequantize_op_quantize(exponential, operand, type(result))

อินพุต

ป้ายกำกับ ชื่อ ประเภท ข้อจำกัด
(1) operand tensor ของชนิดจุดลอยตัวหรือชนิดเชิงซ้อนหรือต่อ tensor ที่วัดปริมาณด้วย tensor (C1)

เอาต์พุต

ชื่อ ประเภท ข้อจำกัด
result tensor ของชนิดจุดลอยตัวหรือชนิดเชิงซ้อนหรือต่อ tensor ที่วัดปริมาณด้วย tensor (C1)

ข้อจำกัด

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

อรรถศาสตร์

ดำเนินการเลขชี้กำลังตามเชิงองค์ประกอบลบ 1 การดำเนินการใน tensor operand และสร้าง tensor result ระบบจะดำเนินการดังต่อไปนี้โดยขึ้นอยู่กับประเภทองค์ประกอบ

  • สำหรับเลขทศนิยม: expm1 จาก IEEE-754
  • สำหรับจำนวนเชิงซ้อน: เลขชี้กำลังเชิงซ้อนลบ 1
  • สำหรับประเภทที่เล็กลง: dequantize_op_quantize(exponential_minus_one, operand, type(result))

อินพุต

ป้ายกำกับ ชื่อ ประเภท ข้อจำกัด
(1) operand tensor ของชนิดจุดลอยตัวหรือชนิดเชิงซ้อนหรือต่อ tensor ที่วัดปริมาณด้วย tensor (C1)

เอาต์พุต

ชื่อ ประเภท ข้อจำกัด
result tensor ของชนิดจุดลอยตัวหรือชนิดเชิงซ้อนหรือต่อ tensor ที่วัดปริมาณด้วย tensor (C1)

ข้อจำกัด

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

อรรถศาสตร์

ทำการแปลงฟูรีเยแบบไปข้างหน้าและผกผันสำหรับอินพุต/เอาต์พุตจริงและที่ซับซ้อน

fft_type เป็นหนึ่งในค่าต่อไปนี้

  • FFT: FFT แบบซับซ้อนสู่ซับซ้อน
  • IFFT: FFT เชิงซ้อนไปเชิงซ้อนแบบผกผัน
  • RFFT: ส่งต่อ FFT แบบจริงสู่ข้อมูลที่ซับซ้อน
  • IRFFT: FFT แบบผกผันจริงถึงซับซ้อน (นั่นคือ ใช้ค่าที่ซับซ้อน แสดงผลจริง)

อย่างเป็นทางการมากขึ้น จากฟังก์ชัน fft ซึ่งนำ tensors แบบ 1 มิติของประเภทที่ซับซ้อนมาเป็นอินพุต จะสร้าง tensor แบบ 1 มิติของประเภทเดียวกันกับเอาต์พุตแล้วคำนวณการแปลงฟูรีเยที่แยกจากกันโดยสิ้นเชิง ดังนี้

สำหรับ 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 ซึ่งจะใช้ tensors 1 มิติของประเภทจุดลอยตัว จะสร้าง tensor แบบ 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, ..., :]).

อินพุต

ป้ายกำกับ ชื่อ ประเภท ข้อจำกัด
(1) operand Tensor ของชนิดจุดลอยตัวหรือเชิงซ้อน (C1), (C2), (C4), (C5)
(I2) fft_type enum ของ FFT, IFFT, RFFT และ IRFFT (C2), (C5)
(1) fft_length ค่าคงที่ tensor แบบ 1 มิติของประเภท si64 (C1), (C3), (C4)

เอาต์พุต

ชื่อ ประเภท ข้อจำกัด
result Tensor ของชนิดจุดลอยตัวหรือเชิงซ้อน (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 มี tensor 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 = dense<4> : tensor<1xi64>
} : (tensor<4xcomplex<f32>>) -> tensor<4xcomplex<f32>>
// %result: [(1.0, 0.0), (1.0, 0.0), (1.0, 0.0), (1.0, 0.0)]

ชั้น

อรรถศาสตร์

ดำเนินการราคาพื้นตามองค์ประกอบของ tensor operand และสร้าง Tensor result ใช้การดำเนินการ roundToIntegralTowardNegative จากข้อกำหนด IEEE-754 สำหรับประเภทที่แบ่งปริมาณแล้ว จะแสดงผล dequantize_op_quantize(floor, operand, type(result))

อินพุต

ป้ายกำกับ ชื่อ ประเภท ข้อจำกัด
(1) operand tensor ของชนิดจุดลอยตัวหรือต่อ tensor ที่วัดปริมาณแล้ว (C1)

เอาต์พุต

ชื่อ ประเภท ข้อจำกัด
result tensor ของชนิดจุดลอยตัวหรือต่อ tensor ที่วัดปริมาณแล้ว (C1)

ข้อจำกัด

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

ตัวอย่างอื่นๆ

รวบรวม

อรรถศาสตร์

รวบรวมชิ้นส่วนจาก operand Tensor จากออฟเซ็ตที่ระบุใน start_indices และสร้าง result Tensor

แผนภาพต่อไปนี้แสดงลักษณะที่องค์ประกอบใน result จับคู่กับองค์ประกอบใน operand โดยใช้ตัวอย่างที่เป็นรูปธรรม แผนภาพนี้เลือกตัวอย่างดัชนี result 2-3 รายการและอธิบายรายละเอียดว่าดัชนี 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]]
  • สำหรับ d_operand ใน axes(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
  • offset_index = result_index[offset_dims...].
  • full_offset_index = [oi0, ..., 0, ..., oiN] โดยที่ oi เป็นองค์ประกอบเดี่ยวใน offset_index และแทรก 0 ที่ดัชนีจาก collapsed_slice_dims
  • operand_index = full_start_index + full_offset_index

หาก indices_are_sorted คือ true การติดตั้งใช้งานจะถือว่ามีการจัดเรียง start_indices ตาม start_index_map ไม่เช่นนั้นจะไม่มีการกำหนดลักษณะการทำงาน อย่างเป็นทางการ สำหรับ i1 < i2 ทั้งหมดจาก indices(result) full_start_index(i1) <= full_start_index(i2)

อินพุต

ป้ายกำกับ ชื่อ ประเภท ข้อจำกัด
(1) operand tensor หรือต่อ tensor ที่วัดปริมาณด้วย tensor (C1), (C7), (C10-C12), (C14)
(I2) start_indices Tensor ของประเภทจำนวนเต็ม (C2), (C3), (C13)
(1) offset_dims ค่าคงที่ tensor แบบ 1 มิติของประเภท si64 (C1), (C4-C5), (C13)
(I4) collapsed_slice_dims ค่าคงที่ tensor แบบ 1 มิติของประเภท si64 (C1), (C6-C8), (C13)
(1) start_index_map ค่าคงที่ tensor แบบ 1 มิติของประเภท si64 (C3), (C9), (C10)
(1) index_vector_dim ค่าคงที่ของประเภท si64 (C2), (C3), (C13)
(1) slice_sizes ค่าคงที่ tensor แบบ 1 มิติของประเภท si64 (C8), (C11-C13)
(i8) indices_are_sorted ค่าคงที่ของประเภท i1

เอาต์พุต

ชื่อ ประเภท ข้อจำกัด
result tensor หรือต่อ tensor ที่วัดปริมาณด้วย tensor (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) เว้นแต่ว่าจะไม่รวมขนาดมิติข้อมูล start_indices ที่สอดคล้องกับ index_vector_dim
    • offset_dim_sizes = shape(slice_sizes) เว้นแต่ว่าจะไม่มีการรวมขนาดของมิติข้อมูลใน slice_sizes ที่สอดคล้องกับ collapsed_slice_dims
    • combine วาง batch_dim_sizes ที่แกนที่สัมพันธ์กับ batch_dims และ offset_dim_sizes ในแกนที่สัมพันธ์กับ offset_dims
  • (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]]
//                 ]
%result = "stablehlo.gather"(%operand, %start_indices) {
  dimension_numbers = #stablehlo.gather<
    offset_dims = [2, 3],
    collapsed_slice_dims = [0],
    start_index_map = [1, 0],
    index_vector_dim = 2>,
  slice_sizes = dense<[1, 2, 2]> : tensor<3xi64>,
  indices_are_sorted = false
} : (tensor<3x4x2xi32>, tensor<2x3x2xi64>) -> tensor<2x3x2x2xi32>
// %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]]
//            ]
//          ]

ตัวอย่างอื่นๆ

get_dimension_size

อรรถศาสตร์

จะสร้างขนาดของ dimension ที่ระบุของ operand เป็นทางการมากขึ้นแล้ว result = dim(operand, dimension)

อินพุต

ป้ายกำกับ ชื่อ ประเภท ข้อจำกัด
(1) operand Tensor (C1)
(I2) dimension ค่าคงที่ของประเภท si64 (C1)

เอาต์พุต

ชื่อ ประเภท
result Tensor แบบ 0 มิติของประเภท si32

ข้อจำกัด

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

อรรถศาสตร์

แยกองค์ประกอบที่ตำแหน่ง index ของ Tuple operand และสร้าง result เป็นทางการมากขึ้นแล้วนะ result = operand[index]

อินพุต

ป้ายกำกับ ชื่อ ประเภท ข้อจำกัด
(1) operand tuple (C1), (C2)
(I2) index ค่าคงที่ของประเภท si32 (C1), (C2)

เอาต์พุต

ชื่อ ประเภท ข้อจำกัด
result ประเภทใดก็ได้ที่รองรับ (C2)

ข้อจำกัด

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

ตัวอย่าง

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

ตัวอย่างอื่นๆ

if

อรรถศาสตร์

สร้างเอาต์พุตจากการรันฟังก์ชันจาก true_branch หรือ false_branch เพียง 1 ฟังก์ชัน โดยขึ้นอยู่กับค่าของ pred เป็นทางการมากขึ้นแล้วนะ result = pred ? true_branch() : false_branch()

อินพุต

ป้ายกำกับ ชื่อ ประเภท ข้อจำกัด
(1) pred Tensor แบบ 0 มิติของประเภท i1
(I2) true_branch ฟังก์ชัน (C1-C3)
(1) false_branch ฟังก์ชัน (C1), (C2)

เอาต์พุต

ชื่อ ประเภท ข้อจำกัด
results จำนวน tensors หลากหลายแบบ, tensors ในเชิงปริมาณ หรือโทเค็น (C3)

ข้อจำกัด

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

ตัวอย่างอื่นๆ

ภาพ

อรรถศาสตร์

แยกส่วนจินตภาพจาก "องค์ประกอบ" ออกจาก operand และสร้าง Tensor result เป็นทางการมากขึ้นสำหรับองค์ประกอบ x แต่ละรายการ: imag(x) = is_complex(x) ? imaginary_part(x) : constant(0, element_type(result))

อินพุต

ป้ายกำกับ ชื่อ ประเภท ข้อจำกัด
(1) operand Tensor ของชนิดจุดลอยตัวหรือเชิงซ้อน (C1), (C2)

เอาต์พุต

ชื่อ ประเภท ข้อจำกัด
result Tensor ของประเภทจุดลอยตัว (C1), (C2)

ข้อจำกัด

  • (C1) shape(result) = shape(operand)
  • (C2) element_type(result) ให้คำจำกัดความไว้ดังนี้
    • complex_element_type(element_type(operand)) หาก is_complex(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 ประกอบด้วยค่าเพย์โหลดซึ่งมาก่อนและโทเค็นที่อยู่ท้ายสุด ในอนาคต เรามีแผนที่จะแยกเพย์โหลดและโทเค็นออกเป็นเอาต์พุต 2 แบบแยกกันเพื่อปรับปรุงความชัดเจน (#670)

อินพุต

ป้ายกำกับ ชื่อ ประเภท
(1) token token
(I2) infeed_config ค่าคงที่ของประเภท string

เอาต์พุต

ชื่อ ประเภท ข้อจำกัด
results จำนวน tensors หลากหลายแบบ, tensors ในเชิงปริมาณ หรือโทเค็น (C1-C3)

ข้อจำกัด

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

ตัวอย่างอื่นๆ

Iota

อรรถศาสตร์

เติม Tensor output ด้วยค่าตามลำดับที่เพิ่มขึ้นโดยเริ่มจาก 0 ตามมิติข้อมูล iota_dimension อย่างเป็นทางการ

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

อินพุต

ป้ายกำกับ ชื่อ ประเภท ข้อจำกัด
(1) iota_dimension si64 (C1)

เอาต์พุต

ชื่อ ประเภท ข้อจำกัด
output tensor ของจำนวนเต็ม ชนิดจุดลอยตัว หรือชนิดเชิงซ้อน หรือ tensor ที่วัดปริมาณด้วยต่อ tensor (C1)

ข้อจำกัด

  • (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) และสร้าง Tensor y ใช้การดำเนินการ isFinite จากข้อกำหนด IEEE-754 สำหรับประเภทที่เล็กลง ผลลัพธ์จะเป็น true เสมอ

อินพุต

ป้ายกำกับ ชื่อ ประเภท ข้อจำกัด
(1) x tensor ของชนิดจุดลอยตัวหรือต่อ tensor ที่วัดปริมาณแล้ว (C1)

เอาต์พุต

ชื่อ ประเภท ข้อจำกัด
y Tensor ของประเภทบูลีน (C1)

ข้อจำกัด

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

อรรถศาสตร์

ดำเนินการใช้ลอการิทึมตามองค์ประกอบใน tensor ใน operand และสร้าง tensor result ระบบจะดำเนินการดังต่อไปนี้โดยขึ้นอยู่กับประเภทองค์ประกอบ

  • สำหรับเลขทศนิยม: log จาก IEEE-754
  • สำหรับจำนวนเชิงซ้อน: ลอการิทึมเชิงซ้อน
  • สำหรับประเภทที่เล็กลง: dequantize_op_quantize(log, operand, type(result))

อินพุต

ป้ายกำกับ ชื่อ ประเภท ข้อจำกัด
(1) operand tensor ของชนิดจุดลอยตัวหรือชนิดเชิงซ้อนหรือต่อ tensor ที่วัดปริมาณด้วย tensor (C1)

เอาต์พุต

ชื่อ ประเภท ข้อจำกัด
result tensor ของชนิดจุดลอยตัวหรือชนิดเชิงซ้อนหรือต่อ tensor ที่วัดปริมาณด้วย tensor (C1)

ข้อจำกัด

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

อรรถศาสตร์

ดำเนินการลอการิทึมตามองค์ประกอบพร้อมการดำเนินการ 1 อย่างใน operand Tensor และสร้าง Tensor result ระบบจะดำเนินการดังต่อไปนี้โดยขึ้นอยู่กับประเภทองค์ประกอบ

  • สำหรับเลขทศนิยม: logp1 จาก IEEE-754
  • สำหรับจำนวนเชิงซ้อน: ลอการิทึมเชิงซ้อนบวก 1
  • สำหรับประเภทที่เล็กลง: dequantize_op_quantize(log_plus_one, operand, type(result))

อินพุต

ป้ายกำกับ ชื่อ ประเภท ข้อจำกัด
(1) operand tensor ของชนิดจุดลอยตัวหรือชนิดเชิงซ้อนหรือต่อ tensor ที่วัดปริมาณด้วย tensor (C1)

เอาต์พุต

ชื่อ ประเภท ข้อจำกัด
result tensor ของชนิดจุดลอยตัวหรือชนิดเชิงซ้อนหรือต่อ tensor ที่วัดปริมาณด้วย tensor (C1)

ข้อจำกัด

  • (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 Tensor และสร้าง Tensor result ระบบจะดำเนินการดังต่อไปนี้โดยขึ้นอยู่กับประเภทองค์ประกอบ

  • สำหรับเลขทศนิยม: division(1, addition(1, exp(-x))) จาก IEEE-754
  • สำหรับจำนวนเชิงซ้อน: โลจิสติกส์เชิงซ้อน
  • สำหรับประเภทที่เล็กลง: dequantize_op_quantize(logistic, operand, type(result))

อินพุต

ป้ายกำกับ ชื่อ ประเภท ข้อจำกัด
(1) operand tensor ของชนิดจุดลอยตัวหรือชนิดเชิงซ้อนหรือต่อ tensor ที่วัดปริมาณด้วย tensor (C1)

เอาต์พุต

ชื่อ ประเภท ข้อจำกัด
result tensor ของชนิดจุดลอยตัวหรือชนิดเชิงซ้อนหรือต่อ tensor ที่วัดปริมาณด้วย tensor (C1)

ข้อจำกัด

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

ตัวอย่างอื่นๆ

map

อรรถศาสตร์

ใช้ฟังก์ชันแผนที่ computation กับ inputs ตาม dimensions และสร้าง Tensor result

เป็นทางการมากขึ้นแล้วนะ result[result_index] = computation(inputs...[result_index]) โปรดทราบว่าขณะนี้ dimensions ไม่มีการใช้งานและมีแนวโน้มที่จะถูกนำออกในอนาคต (#487)

อินพุต

ป้ายกำกับ ชื่อ ประเภท ข้อจำกัด
(1) inputs จำนวน tensors แบบแปรผันหรือต่อ tensor ที่วัดปริมาณด้วย tensor (C1-C4)
(I2) dimensions ค่าคงที่ tensor แบบ 1 มิติของประเภท si64 (C3)
(1) computation ฟังก์ชัน (C4)

เอาต์พุต

ชื่อ ประเภท ข้อจำกัด
result tensor หรือต่อ tensor ที่วัดปริมาณด้วย tensor (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 = dense<[0, 1]> : tensor<2xi64>
} : (tensor<2x2xi64>, tensor<2x2xi64>) -> tensor<2x2xi64>
// %result: [[0, 5], [12, 21]]

ตัวอย่างอื่นๆ

สูงสุด

อรรถศาสตร์

ดำเนินการสูงสุดตามองค์ประกอบตามองค์ประกอบบน tensors lhs และ rhs และสร้าง Tensor result ระบบจะดำเนินการดังต่อไปนี้โดยขึ้นอยู่กับประเภทองค์ประกอบ

  • สำหรับบูลีน: logical OR
  • สำหรับจำนวนเต็ม: จำนวนเต็มสูงสุด
  • สำหรับเลขทศนิยม: maximum จาก IEEE-754
  • สำหรับจำนวนเชิงซ้อน: จำนวนสูงสุดแบบพจนานุกรมสำหรับคู่ (real, imaginary) การตั้งลำดับในจำนวนเชิงซ้อนเกี่ยวข้องกับความหมายที่น่าประหลาดใจ ดังนั้นในอนาคตเราจึงวางแผนที่จะยกเลิกการรองรับจำนวนเชิงซ้อนในการดำเนินการนี้ (#560)
  • สำหรับประเภทที่เล็กลง
    • dequantize_op_quantize(maximum, lhs, rhs, type(result)).

อินพุต

ป้ายกำกับ ชื่อ ประเภท ข้อจำกัด
(1) lhs tensor หรือต่อ tensor ที่วัดปริมาณด้วย tensor (C1)
(I2) rhs tensor หรือต่อ tensor ที่วัดปริมาณด้วย tensor (C1)

เอาต์พุต

ชื่อ ประเภท ข้อจำกัด
result tensor หรือต่อ tensor ที่วัดปริมาณด้วย tensor (C1)

ข้อจำกัด

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

ตัวอย่างอื่นๆ

ขั้นต่ำ

อรรถศาสตร์

ดำเนินการขั้นต่ำตามองค์ประกอบตามองค์ประกอบบน tensors lhs และ rhs และสร้าง tensor เพียง result ระบบจะดำเนินการดังต่อไปนี้โดยขึ้นอยู่กับประเภทองค์ประกอบ

  • สำหรับบูลีน: ตรรกะ AND
  • สำหรับจำนวนเต็ม: จำนวนเต็มขั้นต่ำ
  • สำหรับเลขทศนิยม: minimum จาก IEEE-754
  • สำหรับจำนวนเชิงซ้อน: จำนวนขั้นต่ำของพจนานุกรมสำหรับคู่ (real, imaginary) การตั้งลำดับในจำนวนเชิงซ้อนเกี่ยวข้องกับความหมายที่น่าประหลาดใจ ดังนั้นในอนาคตเราจึงวางแผนที่จะยกเลิกการรองรับจำนวนเชิงซ้อนในการดำเนินการนี้ (#560)
  • สำหรับประเภทที่เล็กลง
    • dequantize_op_quantize(minimum, lhs, rhs, type(result)).

อินพุต

ป้ายกำกับ ชื่อ ประเภท ข้อจำกัด
(1) lhs tensor หรือต่อ tensor ที่วัดปริมาณด้วย tensor (C1)
(I2) rhs tensor หรือต่อ tensor ที่วัดปริมาณด้วย tensor (C1)

เอาต์พุต

ชื่อ ประเภท ข้อจำกัด
result tensor หรือต่อ tensor ที่วัดปริมาณด้วย tensor (C1)

ข้อจำกัด

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

ตัวอย่างอื่นๆ

คูณ

อรรถศาสตร์

สร้างผลคูณตามองค์ประกอบของ tensors 2 ตัว lhs และ rhs แล้วสร้าง Tensor result ระบบจะดำเนินการดังต่อไปนี้โดยขึ้นอยู่กับประเภทองค์ประกอบ

  • สำหรับบูลีน: ตรรกะ AND
  • สำหรับจำนวนเต็ม: การคูณจำนวนเต็ม
  • สำหรับเลขทศนิยม: multiplication จาก IEEE-754
  • สำหรับจำนวนเชิงซ้อน: การคูณเชิงซ้อน
  • สำหรับประเภทที่เล็กลง
    • dequantize_op_quantize(multiply, lhs, rhs, type(result)).

อินพุต

ป้ายกำกับ ชื่อ ประเภท ข้อจำกัด
(1) lhs tensor หรือต่อ tensor ที่วัดปริมาณด้วย tensor (C1)
(I2) rhs tensor หรือต่อ tensor ที่วัดปริมาณด้วย tensor (C1)

เอาต์พุต

ชื่อ ประเภท ข้อจำกัด
result tensor หรือต่อ tensor ที่วัดปริมาณด้วย tensor (C1)

ข้อจำกัด

  • (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 Tensor และสร้าง result Tensor ระบบจะดำเนินการดังต่อไปนี้โดยขึ้นอยู่กับประเภทองค์ประกอบ

  • สําหรับจํานวนเต็มที่มีเครื่องหมาย: การปฏิเสธจํานวนเต็ม
  • สำหรับจำนวนเต็มที่ไม่มีเครื่องหมาย: บิตแคสต์ไปยังจำนวนเต็มแบบมีเครื่องหมาย นิเสธที่เป็นจำนวนเต็ม บิตแคสต์ย้อนกลับไปยังจำนวนเต็มที่ไม่มีเครื่องหมาย
  • สำหรับเลขทศนิยม: negate จาก IEEE-754
  • สำหรับจำนวนเชิงซ้อน: นิเสธเชิงซ้อน
  • สำหรับประเภทที่เล็กลง: dequantize_op_quantize(negate, operand, type(result))

อินพุต

ป้ายกำกับ ชื่อ ประเภท ข้อจำกัด
(1) operand tensor ของจำนวนเต็ม จุดลอยตัว หรือชนิดเชิงซ้อน หรือ tensor ที่วัดปริมาณด้วยต่อ tensor (C1)

เอาต์พุต

ชื่อ ประเภท ข้อจำกัด
result tensor ของจำนวนเต็ม จุดลอยตัว หรือชนิดเชิงซ้อน หรือ tensor ที่วัดปริมาณด้วยต่อ tensor (C1)

ข้อจำกัด

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

ตัวอย่างอื่นๆ

ไม่ใช่

อรรถศาสตร์

ดำเนินการ NOT แบบองค์ประกอบตาม tensor operand และสร้าง tensor result ระบบจะดำเนินการดังต่อไปนี้โดยขึ้นอยู่กับประเภทองค์ประกอบ

  • สำหรับบูลีน: ตรรกะ NOT
  • สำหรับจำนวนเต็ม: Bitwise ไม่ใช่

อาร์กิวเมนต์

ชื่อ ประเภท ข้อจำกัด
operand Tensor ของประเภทบูลีนหรือจำนวนเต็ม (C1)

เอาต์พุต

ชื่อ ประเภท ข้อจำกัด
result Tensor ของประเภทบูลีนหรือจำนวนเต็ม (C1)

ข้อจำกัด

  • (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 จำนวน tensors แบบแปรผัน, ต่อ tensor ที่วัดค่า Tensor หรือโทเค็น (C1)

เอาต์พุต

ชื่อ ประเภท ข้อจำกัด
result จำนวน tensors แบบแปรผัน, ต่อ tensor ที่วัดค่า Tensor หรือโทเค็น (C1)

ข้อจำกัด

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

ตัวอย่างอื่นๆ

หรือ

อรรถศาสตร์

ดำเนินการ OR ตามองค์ประกอบของ tensor จำนวน 2 รายการ lhs และ rhs แล้วสร้าง result Tensor ระบบจะดำเนินการดังต่อไปนี้โดยขึ้นอยู่กับประเภทองค์ประกอบ

  • สำหรับบูลีน: logical OR
  • สำหรับจำนวนเต็ม: บิตไวส์ OR

อินพุต

ป้ายกำกับ ชื่อ ประเภท ข้อจำกัด
(1) lhs Tensor ของจำนวนเต็มหรือประเภทบูลีน (C1)
(I2) rhs Tensor ของจำนวนเต็มหรือประเภทบูลีน (C1)

เอาต์พุต

ชื่อ ประเภท ข้อจำกัด
result Tensor ของจำนวนเต็มหรือประเภทบูลีน (C1)

ข้อจำกัด

  • (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 มีการกำหนดการนำไปใช้งาน

อินพุต

ป้ายกำกับ ชื่อ ประเภท
(1) inputs จำนวน tensors แบบแปรผันหรือ tensors เชิงปริมาณ
(I2) token token
(1) outfeed_config ค่าคงที่ของประเภท string

เอาต์พุต

ชื่อ ประเภท
result token

ตัวอย่าง

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

ตัวอย่างอื่นๆ

Pad

อรรถศาสตร์

ขยาย operand โดยเพิ่มระยะห่างจากขอบรอบๆ Tensor รวมถึงระหว่างองค์ประกอบของ tensor ด้วย padding_value ที่กำหนด

edge_padding_low และ edge_padding_high จะระบุจำนวนระยะห่างจากขอบที่เพิ่มขึ้นในส่วนล่าง (ถัดจากดัชนี 0) และระดับไฮเอนด์ (ถัดจากดัชนีสูงสุด) ของแต่ละมิติข้อมูลตามลำดับ ระยะห่างจากขอบอาจเป็นค่าลบได้ โดยค่าสัมบูรณ์ของระยะห่างจากขอบเชิงลบจะระบุจำนวนองค์ประกอบที่จะนำออกจากมิติข้อมูลที่ระบุ

interior_padding ระบุระยะห่างจากขอบที่เพิ่มระหว่างองค์ประกอบ 2 รายการในแต่ละมิติข้อมูล ซึ่งต้องไม่เป็นค่าลบ ระยะห่างจากขอบภายในเกิดขึ้นก่อนระยะห่างจากขอบเนื่องจากระยะห่างจากขอบที่เป็นลบจะนำองค์ประกอบออกจากตัวถูกดำเนินการแบบบุนวมภายใน

อย่างเป็นทางการ result[result_index] ให้คำนิยามไว้ว่า

  • operand[operand_index] หาก result_index = edge_padding_low + operand_index * (interior_padding + 1)
  • หากไม่ใช่ padding_value

อินพุต

ป้ายกำกับ ชื่อ ประเภท ข้อจำกัด
(1) operand tensor หรือต่อ tensor ที่วัดปริมาณด้วย tensor (C1), (C2), (C4)
(I2) padding_value tensor แบบ 0 มิติหรือต่อ tensor ที่วัดปริมาณแล้ว (C1)
(1) edge_padding_low ค่าคงที่ tensor แบบ 1 มิติของประเภท si64 (C1), (C4)
(I4) edge_padding_high ค่าคงที่ tensor แบบ 1 มิติของประเภท si64 (C1), (C4)
(1) interior_padding ค่าคงที่ tensor แบบ 1 มิติของประเภท si64 (C2-C4)

เอาต์พุต

ชื่อ ประเภท ข้อจำกัด
result tensor หรือต่อ tensor ที่วัดปริมาณด้วย tensor (C3-C6)

ข้อจำกัด

  • (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 = dense<[0, 1]> : tensor<2xi64>,
  edge_padding_high = dense<[2, 1]> : tensor<2xi64>,
  interior_padding = dense<[1, 2]> : tensor<2xi64>
} : (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 Tensor แบบ 0 มิติของประเภท ui32

ตัวอย่าง

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

ตัวอย่างอื่นๆ

Popcnt

อรรถศาสตร์

ดำเนินการนับจำนวนบิตตามองค์ประกอบตามจำนวนบิตที่กำหนดไว้ใน operand Tensor และสร้าง result Tensor

อินพุต

ป้ายกำกับ ชื่อ ประเภท ข้อจำกัด
(1) operand Tensor ของประเภทจำนวนเต็ม (C1)

เอาต์พุต

ชื่อ ประเภท ข้อจำกัด
result Tensor ของประเภทจำนวนเต็ม (C1)

ข้อจำกัด

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

ตัวอย่าง

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

ตัวอย่างอื่นๆ

พาวเวอร์

อรรถศาสตร์

คำนวณเลขยกกำลังของ lhs tensor ด้วย rhs Tensor และสร้าง result Tensor ระบบจะดำเนินการดังต่อไปนี้โดยขึ้นอยู่กับประเภทองค์ประกอบ

  • สำหรับจำนวนเต็ม: เลขยกกำลังจำนวนเต็ม
  • สำหรับเลขทศนิยม: pow จาก IEEE-754
  • สำหรับจำนวนเชิงซ้อน: เลขชี้กำลังเชิงซ้อน
  • สำหรับประเภทที่เล็กลง: dequantize_op_quantize(power, lhs, rhs, type(result))

อินพุต

ป้ายกำกับ ชื่อ ประเภท ข้อจำกัด
(1) lhs tensor ของจำนวนเต็ม จุดลอยตัว หรือชนิดเชิงซ้อน หรือ tensor ที่วัดปริมาณด้วยต่อ tensor (C1)
(I2) rhs tensor ของจำนวนเต็ม จุดลอยตัว หรือชนิดเชิงซ้อน หรือ tensor ที่วัดปริมาณด้วยต่อ tensor (C1)

เอาต์พุต

ชื่อ ประเภท ข้อจำกัด
result tensor ของจำนวนเต็ม จุดลอยตัว หรือชนิดเชิงซ้อน หรือ tensor ที่วัดปริมาณด้วยต่อ tensor (C1)

ข้อจำกัด

  • (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 และสร้าง Tensor result เป็นทางการมากขึ้นสำหรับองค์ประกอบ x แต่ละรายการ: real(x) = is_complex(x) ? real_part(x) : x

อินพุต

ป้ายกำกับ ชื่อ ประเภท ข้อจำกัด
(1) operand Tensor ของชนิดจุดลอยตัวหรือเชิงซ้อน (C1), (C2)

เอาต์พุต

ชื่อ ประเภท ข้อจำกัด
result Tensor ของประเภทจุดลอยตัว (C1), (C2)

ข้อจำกัด

  • (C1) shape(result) = shape(operand)
  • (C2) element_type(result) ให้คำจำกัดความไว้ดังนี้
    • complex_element_type(element_type(operand)) หาก is_complex(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]

ตัวอย่างอื่นๆ

recv

อรรถศาสตร์

รับข้อมูลจากช่องที่มี channel_id และสร้าง results

หาก is_host_transfer คือ true การดำเนินการดังกล่าวจะโอนข้อมูลจากโฮสต์ ไม่เช่นนั้น ระบบจะโอนข้อมูลจากอุปกรณ์อื่น ซึ่งหมายถึง มีการกำหนดการติดตั้งใช้งาน แฟล็กนี้ซ้ำกับข้อมูลที่ระบุไว้ใน channel_type ดังนั้นในอนาคตเราวางแผนที่จะเก็บไว้เพียงตัวเดียว (#666)

results ประกอบด้วยค่าเพย์โหลดซึ่งมาก่อนและโทเค็นที่อยู่ท้ายสุด ในอนาคต เรามีแผนที่จะแยกเพย์โหลดและโทเค็นออกเป็นเอาต์พุต 2 แบบแยกกันเพื่อปรับปรุงความชัดเจน (#670)

อินพุต

ป้ายกำกับ ชื่อ ประเภท ข้อจำกัด
(1) token token (C4)
(I2) channel_id ค่าคงที่ของประเภท si64
(1) channel_type enum ของ DEVICE_TO_DEVICE และ HOST_TO_DEVICE (C1)
(I4) is_host_transfer ค่าคงที่ของประเภท i1 (C1)

เอาต์พุต

ชื่อ ประเภท ข้อจำกัด
results จำนวน tensors หลากหลายแบบ, tensors ในเชิงปริมาณ หรือโทเค็น (C2-C4)

ข้อจำกัด

  • (C1) channel_type ให้คำจำกัดความไว้ดังนี้
    • HOST_TO_DEVICE หากเป็น is_host_transfer = true
    • หากไม่ใช่ 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 Tensor

ลำดับของการลดมีการกำหนดการใช้งาน ซึ่งหมายความว่า body และ init_values ต้องเป็นแบบโมนอยด์เพื่อรับประกันว่าการดำเนินการดังกล่าวจะสร้างผลลัพธ์เดียวกันสำหรับอินพุตทั้งหมดในการใช้งานทั้งหมด แต่เงื่อนไขนี้กลับใช้กับการลดยอดนิยมจำนวนมากไม่ได้ เช่น การเพิ่มจุดลอยตัวของ body และ 0 สำหรับ init_values ไม่ได้สร้างโมนอยด์ เพราะการเพิ่มจุดลอยตัวไม่เชื่อมโยงกัน

อย่างเป็นทางการ 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 ที่กำหนดโดยการใช้งานที่ตำแหน่งที่กำหนดการนำไปใช้งาน

อินพุต

ป้ายกำกับ ชื่อ ประเภท ข้อจำกัด
(1) inputs จำนวน tensors แบบแปรผันหรือต่อ tensor ที่วัดปริมาณด้วย tensor (C1-C4), (C6), (C7)
(I2) init_values จำนวน tensors แบบ 0 มิติหรือต่อ tensor เชิงปริมาณ (C2), (C3)
(1) dimensions ค่าคงที่ tensor แบบ 1 มิติของประเภท si64 (C4), (C5), (C7)
(I4) body ฟังก์ชัน (C6)

เอาต์พุต

ชื่อ ประเภท ข้อจำกัด
results จำนวน tensors แบบแปรผันหรือต่อ tensor ที่วัดปริมาณด้วย tensor (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...) เว้นแต่ว่าจะไม่มีมิติข้อมูลขนาด inputs... ที่สอดคล้องกับ dimensions
  • (C8) element_type(results[i]) = Ei สําหรับ i ทั้งหมดใน [0,N)

ตัวอย่าง

// %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 = dense<1> : tensor<1xi64>
} : (tensor<1x6xi64>, tensor<i64>) -> tensor<1xi64>
// %result = [15]

ตัวอย่างอื่นๆ

reduce_precision

อรรถศาสตร์

ทำการแปลง Element-wise จาก operand ไปเป็นประเภทจุดลอยตัวอื่นที่ใช้ exponent_bits และ mantissa_bits และกลับไปใช้ประเภทจุดลอยตัวดั้งเดิมและสร้าง output Tensor

เป็นทางการมากขึ้น:

  • ระบบจะอัปเดตบิตตั๊กแตนของค่าเดิมให้ปัดเศษค่าเดิมให้เป็นค่าที่ใกล้เคียงที่สุดที่แสดงด้วย mantissa_bits โดยใช้อรรถศาสตร์ roundToIntegralTiesToEven
  • จากนั้น หาก mantissa_bits น้อยกว่าจำนวนบิตของตั๊กแตนตำข้าวของค่าเดิม บิตของตั๊กแตนจะถูกตัดเป็น mantissa_bits
  • จากนั้น หากบิตของเลขชี้กำลังของผลลัพธ์ตรงกลางไม่พอดีกับช่วงที่ระบุโดย exponent_bits ผลลัพธ์ตรงกลางจะเกินค่าอนันต์โดยใช้เครื่องหมายเดิมหรือส่วนล่างลงไปเป็น 0 โดยใช้เครื่องหมายเดิม
  • สำหรับประเภทที่แบ่งปริมาณแล้ว ให้เรียกใช้ dequantize_op_quantize( lambda operand: reduce_precision(operand, exponent_bits, mantissa_bits), operand, type(result))

อินพุต

ป้ายกำกับ ชื่อ ประเภท ข้อจำกัด
(1) operand tensor ของชนิดจุดลอยตัวหรือต่อ tensor ที่วัดปริมาณแล้ว (C1)
(I2) exponent_bits ค่าคงที่ของประเภท si32 (C2)
(1) mantissa_bits ค่าคงที่ของประเภท si32 (C3)

เอาต์พุต

ชื่อ ประเภท ข้อจำกัด
output tensor ของชนิดจุดลอยตัวหรือต่อ tensor ที่วัดปริมาณแล้ว (C1)

ข้อจำกัด

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

อรรถศาสตร์

ภายในแต่ละกลุ่มกระบวนการในตารางกระบวนการของ StableHLO ให้ดำเนินการลดค่าโดยใช้ computations กับค่าของ operand Tensor จากแต่ละกระบวนการจะแยกผลลัพธ์การลดตาม 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)

อินพุต

ป้ายกำกับ ชื่อ ประเภท ข้อจำกัด
(1) operand tensor หรือต่อ tensor ที่วัดปริมาณด้วย tensor (C1), (C2), (C7), (C8)
(I2) scatter_dimension ค่าคงที่ของประเภท si64 (C1), (C2), (C8)
(1) replica_groups ค่าคงที่ tensor 2 มิติของประเภท si64 (C3-C5)
(I4) channel_id ค่าคงที่ของประเภท si64 (C6)
(1) use_global_device_ids ค่าคงที่ของประเภท i1 (C6)
(1) computation ฟังก์ชัน (C7)

เอาต์พุต

ชื่อ ประเภท ข้อจำกัด
result tensor หรือต่อ tensor ที่วัดปริมาณด้วย tensor (C8-C9)

ข้อจำกัด

  • (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) ให้คำจำกัดความไว้ดังนี้
    • num_replicas หากใช้ cross_replica
    • num_replicas หากใช้ cross_replica_and_partition
    • num_processes หากใช้ flattened_ids
  • (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

อรรถศาสตร์

ใช้ฟังก์ชันการลด body กับหน้าต่างของ inputs และ init_values และสร้าง results

แผนภาพต่อไปนี้แสดงวิธีคำนวณองค์ประกอบใน results... จาก inputs... โดยใช้ตัวอย่างที่เป็นรูปธรรม

อย่างเป็นทางการคือ 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).

อินพุต

ป้ายกำกับ ชื่อ ประเภท ข้อจำกัด
(1) inputs จำนวน tensors แบบแปรผันหรือต่อ tensor ที่วัดปริมาณด้วย tensor (C1-C4), (C6), (C8), (C10), (C12), (C13), (C15)
(I2) init_values จำนวน tensors แบบ 0 มิติหรือต่อ tensor เชิงปริมาณ (C1), (C13)
(1) window_dimensions ค่าคงที่ tensor แบบ 1 มิติของประเภท si64 (C4), (C5), (C15)
(I4) window_strides ค่าคงที่ tensor แบบ 1 มิติของประเภท si64 (C6), (C7), (C15)
(1) base_dilations ค่าคงที่ tensor แบบ 1 มิติของประเภท si64 (C8), (C9), (C15)
(1) window_dilations ค่าคงที่ tensor แบบ 1 มิติของประเภท si64 (C10), (C11), (C15)
(1) padding ค่าคงที่ tensor 2 มิติของประเภท si64 (C12), (C15)
(i8) body ฟังก์ชัน (C13)

เอาต์พุต

ชื่อ ประเภท ข้อจำกัด
results จำนวน tensors แบบแปรผันหรือต่อ tensor ที่วัดปริมาณด้วย tensor (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) element_type(results[i]) = Ei สำหรับ i ทั้งหมดใน [0,N)

ตัวอย่าง

// %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 = dense<[2, 1]> : tensor<2xi64>,
  window_strides = dense<[4, 1]> : tensor<2xi64>,
  base_dilations = dense<[2, 1]> : tensor<2xi64>,
  window_dilations = dense<[3, 1]> : tensor<2xi64>,
  padding = dense<[[2, 1], [0, 0]]> : tensor<2x2xi64>
} : (tensor<3x2xi64>, tensor<i64>) -> tensor<2x2xi64>
// %result = [[0, 0], [3, 4]]

ตัวอย่างอื่นๆ

เศษ

อรรถศาสตร์

ดำเนินการคำนวณเศษที่เหลือของเงินปันผล lhs และตัวหาร rhs ตัวหาร แล้วสร้าง result Tensor

หรืออย่างเป็นทางการ เครื่องหมายของผลลัพธ์จะนำมาจากตัวหาร และค่าสัมบูรณ์ของผลลัพธ์จะน้อยกว่าค่าสัมบูรณ์ของตัวหาร เศษที่เหลือจะคำนวณเป็น lhs - d * rhs โดย d จะกำหนดโดย:

  • สำหรับจำนวนเต็ม: stablehlo.divide(lhs, rhs)
  • สำหรับเลขทศนิยม: division(lhs, rhs) จาก IEEE-754 ที่มีแอตทริบิวต์การปัดเศษ roundTowardZero
  • สำหรับจำนวนเชิงซ้อน: TBD (#997)
  • สำหรับประเภทที่เล็กลง
    • dequantize_op_quantize(remainder, lhs, rhs, type(result)).

สำหรับประเภทองค์ประกอบจุดลอยตัว การดำเนินการนี้ตรงข้ามกับการดำเนินการ remainder จากข้อกำหนด IEEE-754 โดยที่ d เป็นค่าปริพันธ์ที่ใกล้เคียงที่สุดกับค่าที่แน่นอนของ lhs/rhs โดยมีค่าเสมอกัน

อินพุต

ป้ายกำกับ ชื่อ ประเภท ข้อจำกัด
(1) lhs tensor ของจำนวนเต็ม ชนิดจุดลอยตัว หรือชนิดเชิงซ้อน หรือ tensor ที่วัดปริมาณด้วยต่อ tensor (C1)
(I2) rhs tensor ของจำนวนเต็ม ชนิดจุดลอยตัว หรือชนิดเชิงซ้อน หรือ tensor ที่วัดปริมาณด้วยต่อ tensor (C1)

เอาต์พุต

ชื่อ ประเภท ข้อจำกัด
result tensor ของจำนวนเต็ม ชนิดจุดลอยตัว หรือชนิดเชิงซ้อน หรือ tensor ที่วัดปริมาณด้วยต่อ tensor (C1)

ข้อจำกัด

  • (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 Tensor แบบ 0 มิติของประเภท ui32

ตัวอย่าง

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

ตัวอย่างอื่นๆ

ปรับรูปร่าง

อรรถศาสตร์

ดำเนินการปรับรูป Tensor operand เป็น result Tensor โดยหลักการแล้ว การคงรูปแบบ Canonical ให้คงเดิมแต่อาจเปลี่ยนรูปร่างได้ เช่น จาก tensor<2x3xf32> เป็น tensor<3x2xf32> หรือ tensor<6xf32>

เป็นทางการมากขึ้น result[result_index] = operand[operand_index] โดยที่ result_index และ operand_index มีอันดับเดียวกันในลำดับแบบพจนานุกรมของ index_space(result) และ index_space(operand)

อินพุต

ป้ายกำกับ ชื่อ ประเภท ข้อจำกัด
(1) operand tensor หรือ tensor ที่วัดปริมาณแล้ว (C1-C3)

เอาต์พุต

ชื่อ ประเภท ข้อจำกัด
result tensor หรือ tensor ที่วัดปริมาณแล้ว (C1-C3)

ข้อจำกัด

  • (C1) element_type(result) ให้บริการโดย
    • element_type(operand) หากเป็น !is_per_axis_quantized(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]]

ตัวอย่างอื่นๆ

ย้อนกลับ

อรรถศาสตร์

กลับลำดับขององค์ประกอบใน operand ตาม dimensions ที่ระบุและสร้าง result Tensor เป็นทางการมากขึ้น result[result_index] = operand[operand_index] ซึ่ง

  • operand_index[d] = dim(result, d) - result_index[d] - 1 หากเป็น d ใน dimensions
  • หากไม่ใช่ operand_index[d] = result_index[d]

อินพุต

ป้ายกำกับ ชื่อ ประเภท ข้อจำกัด
(1) operand tensor หรือต่อ tensor ที่วัดปริมาณด้วย tensor (C1), (C3)
(I2) dimensions ค่าคงที่ tensor แบบ 1 มิติของประเภท si64 (C2), (C3)

เอาต์พุต

ชื่อ ประเภท ข้อจำกัด
result tensor หรือต่อ tensor ที่วัดปริมาณด้วย tensor (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 = dense<1> : tensor<1xi64>
} : (tensor<3x2xi32>) -> tensor<3x2xi32>
// %result: [[2, 1], [4, 3], [6, 5]]

ตัวอย่างอื่นๆ

คำตอบ

อรรถศาสตร์

สร้างตัวเลขสุ่มโดยใช้อัลกอริทึม rng_distribution และสร้าง result tensor ของรูปร่างที่กำหนด shape

หากค่าเป็น rng_distribution = UNIFORM ระบบจะสร้างหมายเลขสุ่มหลังจากการกระจายที่สม่ำเสมอในช่วง [a, b) หากเป็น a >= b จะไม่มีการกำหนดลักษณะการทำงาน

หากค่าเป็น rng_distribution = NORMAL ระบบจะสร้างตัวเลขสุ่มขึ้นตามการแจกแจงปกติที่มีค่าเฉลี่ย = a และส่วนเบี่ยงเบนมาตรฐาน = b หากเป็น b < 0 ระบบจะไม่ได้กำหนดลักษณะการทำงาน

วิธีการสร้างตัวเลขสุ่มที่แน่ชัดนั้นกำหนดไว้ว่าการนำไปใช้งาน ตัวอย่างเช่น โฆษณาเหล่านี้อาจใช้หรือไม่มีการกำหนดสถานะ และอาจใช้หรือไม่ใช้สถานะซ่อน

ในการพูดคุยกับผู้ถือผลประโยชน์ร่วมหลายราย พบว่าความเห็นนี้สิ้นสุดลงอย่างมีประสิทธิภาพแล้ว ดังนั้นในอนาคตเราจึงมีแผนที่จะหาวิธีนำการทดสอบออก (#597)

อินพุต

ป้ายกำกับ ชื่อ ประเภท ข้อจำกัด
(1) a tensor แบบ 0 มิติของจำนวนเต็ม บูลีน หรือประเภทจุดลอยตัว (C1), (C2)
(I2) b tensor แบบ 0 มิติของจำนวนเต็ม บูลีน หรือประเภทจุดลอยตัว (C1), (C2)
(1) shape ค่าคงที่ tensor แบบ 1 มิติของประเภท si64 (C3)
(I4) rng_distribution enum ของ UNIFORM และ NORMAL (C2)

เอาต์พุต

ชื่อ ประเภท ข้อจำกัด
result tensor ของจำนวนเต็ม บูลีน หรือประเภทจุดลอยตัว (C1-C3)

ข้อจำกัด

  • (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 ที่เต็มไปด้วยบิตแบบสุ่มแบบเดียวกันและสถานะเอาต์พุตที่อัปเดต output_state โดยใช้อัลกอริทึมของโปรแกรมสร้างตัวเลขสุ่ม rng_algorithm ที่กำหนดสถานะเริ่มต้นเป็น initial_state เอาต์พุตเหล่านี้รับประกันได้ว่าเป็นฟังก์ชันที่กำหนดของ initial_state แต่ไม่รับประกันว่าจะตัดสินได้จากการใช้งานจริง

rng_algorithm เป็นหนึ่งในค่าต่อไปนี้

  • DEFAULT: อัลกอริทึมที่กำหนดการใช้งาน
  • THREE_FRY: ตัวแปรที่กำหนดโดยการใช้งานของอัลกอริทึม Threefry*
  • PHILOX: ตัวแปรที่ปรับใช้ของอัลกอริทึม Philox*

* ดู: Salmon et al. SC 2011. เลขสุ่มคู่ขนาน: ง่ายเหมือนนับ 1, 2, 3

อินพุต

ป้ายกำกับ ชื่อ ประเภท ข้อจำกัด
(1) rng_algorithm enum ของ DEFAULT, THREE_FRY และ PHILOX (C2)
(I2) initial_state Tensor แบบ 1 มิติของประเภท ui64 (C1), (C2)

เอาต์พุต

ชื่อ ประเภท ข้อจำกัด
output_state Tensor แบบ 1 มิติของประเภท ui64 (C1)
output Tensor ของจำนวนเต็มหรือประเภทจุดลอยตัว

ข้อจำกัด

  • (C1) type(initial_state) = type(output_state)
  • (C2) size(initial_state) ให้คำจำกัดความไว้ดังนี้
    • การใช้งานกำหนดไว้หากเป็น rng_algorithm = DEFAULT
    • 2 หาก rng_algorithm = THREE_FRY
    • 2 หรือ 3 หากเป็น rng_algorithm = PHILOX

ตัวอย่าง

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

อรรถศาสตร์

ทำการปัดเศษแบบองค์ประกอบตามจำนวนเต็มที่ใกล้เคียงที่สุด โดยตัดความสัมพันธ์ออกจาก 0 ใน tensor ของ operand และสร้าง Tensor result ใช้การดำเนินการ roundToIntegralTiesToAway จากข้อกำหนด IEEE-754 สำหรับประเภทที่เล็กลง จะแสดงผล dequantize_op_quantize(round_nearest_afz, operand, type(result))

อินพุต

ป้ายกำกับ ชื่อ ประเภท ข้อจำกัด
(1) operand tensor ของชนิดจุดลอยตัวหรือต่อ tensor ที่วัดปริมาณแล้ว (C1)

เอาต์พุต

ชื่อ ประเภท ข้อจำกัด
result tensor ของชนิดจุดลอยตัวหรือต่อ tensor ที่วัดปริมาณแล้ว (C1)

ข้อจำกัด

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

อรรถศาสตร์

ทำการปัดเศษตามองค์ประกอบตามจำนวนเต็มที่ใกล้เคียงที่สุด โดยตัดความสัมพันธ์ที่มีต่อจำนวนเต็มคู่ใน tensor ใน operand และสร้าง Tensor result ใช้การดำเนินการ roundToIntegralTiesToEven จากข้อกำหนด IEEE-754 สำหรับประเภทที่แบ่งปริมาณแล้ว จะแสดงผล dequantize_op_quantize(round_nearest_even, operand, type(result))

อินพุต

ป้ายกำกับ ชื่อ ประเภท ข้อจำกัด
(1) operand tensor ของชนิดจุดลอยตัวหรือต่อ tensor ที่วัดปริมาณแล้ว (C1)

เอาต์พุต

ชื่อ ประเภท ข้อจำกัด
result tensor ของชนิดจุดลอยตัวหรือต่อ tensor ที่วัดปริมาณแล้ว (C1)

ข้อจำกัด

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

อรรถศาสตร์

ดำเนินการประมวลผลรากที่สองตามองค์ประกอบตามองค์ประกอบบน Tensor operand และสร้าง tensor result ระบบจะดำเนินการดังต่อไปนี้โดยขึ้นอยู่กับประเภทองค์ประกอบ

  • สำหรับเลขทศนิยม: rSqrt จาก IEEE-754
  • สำหรับจำนวนเชิงซ้อน: รากที่สองเชิงซ้อน
  • สำหรับประเภทที่เล็กลง: dequantize_op_quantize(rsqrt, operand, type(result))

อินพุต

ป้ายกำกับ ชื่อ ประเภท ข้อจำกัด
(1) operand tensor ของชนิดจุดลอยตัวหรือชนิดเชิงซ้อนหรือต่อ tensor ที่วัดปริมาณด้วย tensor (C1)

เอาต์พุต

ชื่อ ประเภท ข้อจำกัด
result tensor ของชนิดจุดลอยตัวหรือชนิดเชิงซ้อนหรือต่อ tensor ที่วัดปริมาณด้วย tensor (C1)

ข้อจำกัด

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

ตัวอย่างอื่นๆ

scatter

อรรถศาสตร์

สร้าง results Tensor ซึ่งเท่ากับ inputs tensors เว้นแต่ชิ้นส่วนหลายชิ้นที่ระบุโดย scatter_indices จะได้รับการอัปเดตด้วยค่า updates โดยใช้ update_computation

แผนภาพต่อไปนี้แสดงลักษณะที่องค์ประกอบใน updates... จับคู่กับองค์ประกอบใน results... โดยใช้ตัวอย่างที่เป็นรูปธรรม ไดอะแกรมจะเลือกตัวอย่างดัชนี updates... 2-3 รายการและอธิบายรายละเอียดว่าดัชนี results... ใดเกี่ยวข้อง

อย่างเป็นทางการ สำหรับ update_index ทั้งหมดใน index_space(updates[0]):

  • 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]]
  • สำหรับ d_input ใน axes(inputs[0])
    • full_start_index[d_input] = start_index[d_start] หาก d_input = scatter_dims_to_operand_dims[d_start]
    • หากไม่ใช่ full_start_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
  • result_index = full_start_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 โดยตั้งค่า results...[result_index] เป็น 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 แต่ดัชนีที่กระจายอยู่นั้นซ้ำกัน จะไม่มีการกำหนดลักษณะการทำงาน

อินพุต

ป้ายกำกับ ชื่อ ประเภท ข้อจำกัด
(1) inputs จำนวน tensors แบบแปรผันหรือต่อ tensor ที่วัดปริมาณด้วย tensor (C1), (C2), (C4-C6), (C10), (C13), (C15-C16)
(I2) scatter_indices Tensor ของประเภทจำนวนเต็ม (C4), (C11), (C14)
(1) updates จำนวน tensors แบบแปรผันหรือต่อ tensor ที่วัดปริมาณด้วย tensor (C3-C6), (C8)
(I4) update_window_dims ค่าคงที่ tensor แบบ 1 มิติของประเภท si64 (C2), (C4), (C7), (C8)
(1) inserted_window_dims ค่าคงที่ tensor แบบ 1 มิติของประเภท si64 (C2), (C4), (C9), (C10)
(1) scatter_dims_to_operand_dims ค่าคงที่ tensor แบบ 1 มิติของประเภท si64 (C11-C13)
(1) index_vector_dim ค่าคงที่ของประเภท si64 (C4), (C11), (C14)
(i8) indices_are_sorted ค่าคงที่ของประเภท i1
(I9) unique_indices ค่าคงที่ของประเภท i1
(10) update_computation ฟังก์ชัน (C15)

เอาต์พุต

ชื่อ ประเภท ข้อจำกัด
results จำนวน tensors แบบแปรผันหรือต่อ tensor ที่วัดปริมาณด้วย tensor (C15-C17)

ข้อจำกัด

  • (C1) same(shape(inputs...))
  • (C2) rank(inputs[0]) = size(update_window_dims) + size(inserted_window_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]) เว้นแต่ว่าจะไม่รวมขนาดมิติข้อมูลใน inputs[0] ที่สอดคล้องกับ inserted_window_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(inserted_window_dims) and is_sorted(update_window_dims)
  • (C10) 0 <= inserted_window_dims < rank(inputs[0])
  • (C11) size(scatter_dims_to_operand_dims) = index_vector_dim < rank(scatter_indices) ? dim(scatter_indices, index_vector_dim) : 1
  • (C12) is_unique(scatter_dims_to_operand_dims)
  • (C13) 0 <= scatter_dims_to_operand_dims < rank(inputs[0])
  • (C14) 0 <= index_vector_dim <= rank(scatter_indices)
  • (C15) update_computation มีประเภท (tensor<E0>, ..., tensor<EN-1>, tensor<E0>, ..., tensor<EN-1>) -> (tensor<E0>, ..., tensor<EN-1>) ที่ is_promotable(element_type(inputs[i]), Ei)
  • (C16) shape(inputs...) = shape(results...)
  • (C17) element_type(results[i]) = Ei สําหรับ i ทั้งหมดใน [0,N)

ตัวอย่าง

// %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]]
//         ]
// %scatter_indices: [[[0, 2], [1, 0], [2, 1]], [[0, 1], [1, 0], [0, 9]]]
// %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 = [2, 3],
    inserted_window_dims = [0],
    scatter_dims_to_operand_dims = [1, 0],
    index_vector_dim = 2>,
  indices_are_sorted = false,
  unique_indices = false
} : (tensor<3x4x2xi64>, tensor<2x3x2xi64>, tensor<2x3x2x2xi64>) -> tensor<3x4x2xi64>
// %result: [
//           [[1, 2], [5, 6], [7, 8], [7, 8]],
//           [[10, 11], [12, 13], [14, 15], [16, 17]],
//           [[18, 19], [20, 21], [21, 22], [23, 24]]
//          ]

ตัวอย่างอื่นๆ

เลือก

อรรถศาสตร์

สร้าง result Tensor ที่เลือกองค์ประกอบแต่ละรายการจาก on_true หรือ on_false Tensor ตามค่าขององค์ประกอบ pred ที่สอดคล้องกัน เป็นทางการมากขึ้น 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))

อินพุต

ป้ายกำกับ ชื่อ ประเภท ข้อจำกัด
(1) pred Tensor ประเภท i1 (C1)
(I2) on_true tensor หรือต่อ tensor ที่วัดปริมาณด้วย tensor (C1-C2)
(1) on_false tensor หรือต่อ tensor ที่วัดปริมาณด้วย tensor (C2)

เอาต์พุต

ชื่อ ประเภท ข้อจำกัด
result tensor หรือต่อ tensor ที่วัดปริมาณด้วย tensor (C2)

ข้อจำกัด

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

อรรถศาสตร์

กระจายค่าจาก source tensor โดยใช้ scatter ตามผลลัพธ์ของ reduce_window ของ input tensor โดยใช้ select และสร้าง tensor. result

แผนภาพต่อไปนี้แสดงวิธีคำนวณองค์ประกอบใน result จาก operand และ source โดยใช้ตัวอย่างที่เป็นรูปธรรม

เป็นทางการมากขึ้น:

  • selected_values = reduce_window_without_init(...) พร้อมอินพุตต่อไปนี้

    • `inputs = [ตัวถูกดำเนินการ]
    • 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].

อินพุต

ป้ายกำกับ ชื่อ ประเภท ข้อจำกัด
(1) operand tensor หรือต่อ tensor ที่วัดปริมาณด้วย tensor (C1-C4), (C6), (C8-C11)
(I2) source tensor หรือต่อ tensor ที่วัดปริมาณด้วย tensor (C1), (C2)
(1) init_value tensor แบบ 0 มิติหรือต่อ tensor ที่วัดปริมาณแล้ว (C3)
(I4) window_dimensions ค่าคงที่ tensor แบบ 1 มิติของประเภท si64 (C2), (C4), (C5)
(1) window_strides ค่าคงที่ tensor แบบ 1 มิติของประเภท si64 (C2), (C6), (C7)
(1) padding ค่าคงที่ tensor 2 มิติของประเภท si64 (C2), (C8)
(1) select ฟังก์ชัน (C9)
(i8) scatter ฟังก์ชัน (C10)

เอาต์พุต

ชื่อ ประเภท ข้อจำกัด
result tensor หรือต่อ tensor ที่วัดปริมาณด้วย tensor (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 = dense<[3, 1]> : tensor<2xi64>,
  window_strides = dense<[2, 1]> : tensor<2xi64>,
  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)

อินพุต

ป้ายกำกับ ชื่อ ประเภท ข้อจำกัด
(1) inputs จำนวน tensors แบบแปรผันหรือ tensors เชิงปริมาณ
(I2) token token
(1) channel_id ค่าคงที่ของประเภท si64
(I4) channel_type enum ของ DEVICE_TO_DEVICE และ DEVICE_TO_HOST (C1)
(1) is_host_transfer ค่าคงที่ของประเภท i1 (C1)

เอาต์พุต

ชื่อ ประเภท
result token

ข้อจำกัด

  • (C1) channel_type ให้คำจำกัดความไว้ดังนี้
    • DEVICE_TO_HOST หากเป็น is_host_transfer = true
    • หากไม่ใช่ 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

อรรถศาสตร์

ดำเนินการใช้ชิฟท์ด้านซ้ายตามองค์ประกอบบน Tensor lhs ตามจำนวนบิต rhs และสร้าง Tensor result

อินพุต

ป้ายกำกับ ชื่อ ประเภท ข้อจำกัด
(1) lhs Tensor ของประเภทจำนวนเต็ม (C1)
(I2) rhs Tensor ของประเภทจำนวนเต็ม (C1)

เอาต์พุต

ชื่อ ประเภท ข้อจำกัด
result Tensor ของประเภทจำนวนเต็ม (C1)

ข้อจำกัด

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

อรรถศาสตร์

ดำเนินการ Shift ขวาสำหรับเลขคณิตตามองค์ประกอบบน tensor ใน lhs ตามจำนวนบิต rhs และสร้าง result Tensor

อินพุต

ป้ายกำกับ ชื่อ ประเภท ข้อจำกัด
(1) lhs Tensor ของประเภทจำนวนเต็ม (C1)
(I2) rhs Tensor ของประเภทจำนวนเต็ม (C1)

เอาต์พุต

ชื่อ ประเภท ข้อจำกัด
result Tensor ของประเภทจำนวนเต็ม (C1)

ข้อจำกัด

  • (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 และสร้าง Tensor result

อินพุต

ป้ายกำกับ ชื่อ ประเภท ข้อจำกัด
(1) lhs Tensor ของประเภทจำนวนเต็ม (C1)
(I2) rhs Tensor ของประเภทจำนวนเต็ม (C1)

เอาต์พุต

ชื่อ ประเภท ข้อจำกัด
result Tensor ของประเภทจำนวนเต็ม (C1)

ข้อจำกัด

  • (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 และสร้าง tensor 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))

อินพุต

ป้ายกำกับ ชื่อ ประเภท ข้อจำกัด
(1) operand Tensor ของจำนวนเต็มแบบมีเครื่องหมาย ประเภทจุดลอยตัว หรือประเภทเชิงซ้อน หรือ tensor ที่เล็กลงแบบต่อ tensor (C1)

เอาต์พุต

ชื่อ ประเภท ข้อจำกัด
result Tensor ของจำนวนเต็มแบบมีเครื่องหมาย ประเภทจุดลอยตัว หรือประเภทเชิงซ้อน หรือ tensor ที่เล็กลงแบบต่อ tensor (C1)

ข้อจำกัด

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

ตัวอย่างอื่นๆ

ไซน์

อรรถศาสตร์

ดำเนินการดำเนินการไซน์ตามองค์ประกอบใน Tensor operand และสร้าง Tensor result ระบบจะดำเนินการดังต่อไปนี้โดยขึ้นอยู่กับประเภทองค์ประกอบ

  • สำหรับเลขทศนิยม: sin จาก IEEE-754
  • สำหรับจำนวนเชิงซ้อน: ไซน์เชิงซ้อน
  • สำหรับประเภทที่เล็กลง: dequantize_op_quantize(sine, operand, type(result))

อินพุต

ป้ายกำกับ ชื่อ ประเภท ข้อจำกัด
(1) operand tensor ของชนิดจุดลอยตัวหรือชนิดเชิงซ้อนหรือต่อ tensor ที่วัดปริมาณด้วย tensor (C1)

เอาต์พุต

ชื่อ ประเภท ข้อจำกัด
result tensor ของชนิดจุดลอยตัวหรือชนิดเชิงซ้อนหรือต่อ tensor ที่วัดปริมาณด้วย tensor (C1)

ข้อจำกัด

  • (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 โดยใช้ดัชนีเริ่มต้นที่คำนวณแบบคงที่ และสร้าง tensor result start_indices มีดัชนีเริ่มต้นของสไลซ์สำหรับแต่ละมิติข้อมูล ส่วน limit_indices มีดัชนีสิ้นสุด (เฉพาะตัว) สำหรับสไลซ์ของแต่ละมิติข้อมูล และ strides มีข้อมูลขีดคั่นสำหรับแต่ละมิติข้อมูล

อย่างเป็นทางการคือ result[result_index] = operand[operand_index] ที่ไหน operand_index = start_indices + result_index * strides

อินพุต

ป้ายกำกับ ชื่อ ประเภท ข้อจำกัด
(1) operand tensor หรือต่อ tensor ที่วัดปริมาณด้วย tensor (C1-C3), (C5)
(I2) start_indices ค่าคงที่ tensor แบบ 1 มิติของประเภท si64 (C2), (C3), (C5)
(1) limit_indices ค่าคงที่ tensor แบบ 1 มิติของประเภท si64 (C2), (C3), (C5)
(I4) strides ค่าคงที่ tensor แบบ 1 มิติของประเภท si64 (C2), (C4)

เอาต์พุต

ชื่อ ประเภท ข้อจำกัด
result tensor หรือต่อ tensor ที่วัดปริมาณด้วย tensor (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 = dense<[1, 2]> : tensor<2xi64>,
  limit_indices = dense<[3, 4]> : tensor<2xi64>,
  strides = dense<1> : tensor<2xi64>
} : (tensor<3x4xi64>) -> tensor<2x2xi64>
// % result: [
//            [1, 1],
//            [1, 1]
//           ]

ตัวอย่างอื่นๆ

จัดเรียง

อรรถศาสตร์

จัดเรียงชิ้นส่วน 1 มิติของ inputs ตามมิติข้อมูล dimension ร่วมกัน โดยอิงตาม comparator และสร้าง results

dimension จะอนุญาตค่าลบซึ่งมีอรรถศาสตร์ที่อธิบายไว้ด้านล่าง ซึ่งต่างจากอินพุตที่คล้ายกันในการดําเนินการอื่นๆ ในอนาคตระบบอาจไม่อนุญาตให้ใช้การให้สิทธิ์นี้เนื่องด้วยเหตุผลด้านความสอดคล้อง (#1377)

หาก is_stable เป็นจริง การจัดเรียงจะคงที่ กล่าวคือ ลำดับขององค์ประกอบที่ถือว่าเท่ากันโดยตัวเปรียบเทียบจะยังคงเดิม สำหรับกรณีที่มีอินพุตเดียว องค์ประกอบ 2 รายการ ได้แก่ e1 และ e2 จะถือว่าเท่ากันโดยตัวเปรียบเทียบในกรณีที่ comparator(e1, e2) = comparator(e2, e1) = false เท่านั้น ดูความเป็นทางการด้านล่าง เพื่อดูว่าข้อมูลเหล่านี้เข้ากับอินพุตต่างๆ อย่างไร

อย่างเป็นทางการ สำหรับ result_index ทั้งหมดใน index_space(results[0]):

  • 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 หากอาร์กิวเมนต์ด้านซ้ายมือน้อยกว่าอาร์กิวเมนต์ที่ 2 ด้านขวามือ
  • 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.

อินพุต

ป้ายกำกับ ชื่อ ประเภท ข้อจำกัด
(1) inputs จำนวน tensors แบบแปรผันหรือต่อ tensor ที่วัดปริมาณด้วย tensor (C1-C5)
(I2) dimension ค่าคงที่ของประเภท si64 (C4)
(1) is_stable ค่าคงที่ของประเภท i1
(I4) comparator ฟังก์ชัน (C5)

เอาต์พุต

ชื่อ ประเภท ข้อจำกัด
results จำนวน tensors แบบแปรผันหรือต่อ tensor ที่วัดปริมาณด้วย tensor (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]]

ตัวอย่างอื่นๆ

sqrt

อรรถศาสตร์

ดำเนินการใช้รากที่สองของเอลิเมนต์ใน Tensor operand และสร้าง Tensor result ระบบจะดำเนินการดังต่อไปนี้โดยขึ้นอยู่กับประเภทองค์ประกอบ

  • สำหรับเลขทศนิยม: squareRoot จาก IEEE-754
  • สำหรับจำนวนเชิงซ้อน: รากที่สองเชิงซ้อน
  • สำหรับประเภทที่เล็กลง: dequantize_op_quantize(sqrt, operand, type(result))

อินพุต

ป้ายกำกับ ชื่อ ประเภท ข้อจำกัด
(1) operand tensor ของชนิดจุดลอยตัวหรือชนิดเชิงซ้อนหรือต่อ tensor ที่วัดปริมาณด้วย tensor (C1)

เอาต์พุต

ชื่อ ประเภท ข้อจำกัด
result tensor ของชนิดจุดลอยตัวหรือชนิดเชิงซ้อนหรือต่อ tensor ที่วัดปริมาณด้วย tensor (C1)

ข้อจำกัด

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

ตัวอย่างอื่นๆ

ลบ

อรรถศาสตร์

ทำการลบ tensors 2 แบบ lhs และ rhs แล้วสร้าง result tensor ระบบจะดำเนินการดังต่อไปนี้โดยขึ้นอยู่กับประเภทองค์ประกอบ

  • สำหรับจำนวนเต็ม: การลบจำนวนเต็ม
  • สำหรับเลขทศนิยม: subtraction จาก IEEE-754
  • สำหรับจำนวนเชิงซ้อน: การลบเชิงซ้อน
  • สำหรับประเภทที่เล็กลง
    • dequantize_op_quantize(subtract, lhs, rhs, type(result)).

อินพุต

ป้ายกำกับ ชื่อ ประเภท ข้อจำกัด
(1) lhs tensor ของจำนวนเต็ม จุดลอยตัว หรือชนิดเชิงซ้อน หรือ tensor ที่วัดปริมาณด้วยต่อ tensor (C1)
(I2) rhs tensor ของจำนวนเต็ม จุดลอยตัว หรือชนิดเชิงซ้อน หรือ tensor ที่วัดปริมาณด้วยต่อ tensor (C1)

เอาต์พุต

ชื่อ ประเภท ข้อจำกัด
result tensor ของจำนวนเต็ม จุดลอยตัว หรือชนิดเชิงซ้อน หรือ tensor ที่วัดปริมาณด้วยต่อ tensor (C1)

ข้อจำกัด

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

ตัวอย่างอื่นๆ

Tanh

อรรถศาสตร์

ดำเนินการดำเนินการไฮเปอร์โบลิกแทนเจนต์แบบ Element-wise ใน tensor operand และสร้าง Tensor result ระบบจะดำเนินการดังต่อไปนี้โดยขึ้นอยู่กับประเภทองค์ประกอบ

  • สำหรับเลขทศนิยม: tanh จาก IEEE-754
  • สำหรับจำนวนเชิงซ้อน: ไฮเปอร์โบลิกแทนเจนต์เชิงซ้อน
  • สำหรับประเภทที่เล็กลง
    • dequantize_op_quantize(tanh, operand, type(result)).

อินพุต

ป้ายกำกับ ชื่อ ประเภท ข้อจำกัด
(1) operand tensor ของชนิดจุดลอยตัวหรือชนิดเชิงซ้อนหรือต่อ tensor ที่วัดปริมาณด้วย tensor (C1)

เอาต์พุต

ชื่อ ประเภท ข้อจำกัด
result tensor ของชนิดจุดลอยตัวหรือชนิดเชิงซ้อนหรือต่อ tensor ที่วัดปริมาณด้วย tensor (C1)

ข้อจำกัด

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

ตัวอย่างอื่นๆ

สลับตำแหน่ง

อรรถศาสตร์

เรียงสับเปลี่ยนมิติข้อมูลของ operand Tensor โดยใช้ permutation และสร้าง result Tensor อย่างเป็นทางการคือ result[result_index] = operand[operand_index] ที่ result_index[d] = operand_index[permutation[d]]

อินพุต

ป้ายกำกับ ชื่อ ประเภท ข้อจำกัด
(1) operand tensor หรือ tensor ที่วัดปริมาณแล้ว (C1-C4)
(I2) permutation ค่าคงที่ tensor แบบ 1 มิติของประเภท si64 (C2-C4)

เอาต์พุต

ชื่อ ประเภท ข้อจำกัด
result tensor หรือ tensor ที่วัดปริมาณแล้ว (C1), (C3-C4)

ข้อจำกัด

  • (C1) element_type(result) ให้บริการโดย
    • element_type(operand) หากเป็น !is_per_axis_quantized(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 = dense<[2, 1, 0]> : tensor<3xi64>
} : (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

ข้อมูลที่ป้อนจะอ่านจากสามเหลี่ยมล่างของ a เท่านั้น หาก lower เป็น true หรือสามเหลี่ยมบนของ 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))

อินพุต

ป้ายกำกับ ชื่อ ประเภท ข้อจำกัด
(1) a tensor ของชนิดจุดลอยตัวหรือชนิดเชิงซ้อนหรือต่อ tensor ที่วัดปริมาณด้วย tensor (C1-C3)
(I2) b tensor ของชนิดจุดลอยตัวหรือชนิดเชิงซ้อนหรือต่อ tensor ที่วัดปริมาณด้วย tensor (C1-C4)
(1) left_side ค่าคงที่ของประเภท i1 (C3)
(I4) lower ค่าคงที่ของประเภท i1
(1) unit_diagonal ค่าคงที่ของประเภท i1
(1) transpose_a enum ของ NO_TRANSPOSE, TRANSPOSE และ ADJOINT

เอาต์พุต

ชื่อ ประเภท ข้อจำกัด
result tensor ของชนิดจุดลอยตัวหรือชนิดเชิงซ้อนหรือต่อ tensor ที่วัดปริมาณด้วย tensor (C1)

ข้อจำกัด

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

tuple

อรรถศาสตร์

สร้าง Tuple result จากค่า val

อินพุต

ป้ายกำกับ ชื่อ ประเภท ข้อจำกัด
(1) val จำนวนค่าที่แตกต่างกัน (C1)

เอาต์พุต

ชื่อ ประเภท ข้อจำกัด
result tuple (C1)

ข้อจำกัด

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

อรรถศาสตร์

ทำการแปลง tensor เชิงปริมาณ operand เป็น tensor แบบจุดลอยตัว result ตามพารามิเตอร์เชิงปริมาณที่กำหนดโดยประเภท operand

เป็นทางการมากขึ้นแล้วนะ result = dequantize(operand)

อินพุต

ป้ายกำกับ ชื่อ ประเภท ข้อจำกัด
(1) operand tensor ที่วัดปริมาณแล้ว (C1), (C2)

เอาต์พุต

ชื่อ ประเภท ข้อจำกัด
result Tensor ของประเภทจุดลอยตัว (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

อรรถศาสตร์

แปลง tensor แบบ Floating Point หรือ tensor เชิงปริมาณ operand เป็น tensor ที่วัดปริมาณด้วย result ตามพารามิเตอร์การทำเชิงปริมาณที่กำหนดโดยประเภท result

อย่างเป็นทางการ

  • หากเป็น is_float(operand)
    • result = quantize(operand, type(result)).
  • หากเป็น is_quantized(operand)
    • float_result = dequantize(operand).
    • result = quantize(float_result, type(result)).

อินพุต

ป้ายกำกับ ชื่อ ประเภท ข้อจำกัด
(1) operand tensor ของชนิดจุดลอยตัวหรือแบบตัวปริมาณ (C1), (C2)

เอาต์พุต

ชื่อ ประเภท ข้อจำกัด
result tensor ที่วัดปริมาณแล้ว (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

ลักษณะการทำงานของการวนซ้ำที่ไม่มีสิ้นสุดคือ TBD (#383)

อินพุต

ป้ายกำกับ ชื่อ ประเภท ข้อจำกัด
(1) operand จำนวน tensors หลากหลายแบบ, tensors ในเชิงปริมาณ หรือโทเค็น (C1-C3)
(I2) cond ฟังก์ชัน (C1)
(1) body ฟังก์ชัน (C2)

เอาต์พุต

ชื่อ ประเภท ข้อจำกัด
results จำนวน tensors หลากหลายแบบ, tensors ในเชิงปริมาณ หรือโทเค็น (C3)

ข้อจำกัด

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

ตัวอย่างอื่นๆ

Xor

อรรถศาสตร์

ดำเนินการ XOR ตามองค์ประกอบของ tensor 2 รายการ lhs และ rhs แล้วสร้าง result tensor ระบบจะดำเนินการดังต่อไปนี้โดยขึ้นอยู่กับประเภทองค์ประกอบ

  • สำหรับบูลีน: ตรรกะ XOR
  • สำหรับจำนวนเต็ม: Bitwise XOR

อินพุต

ป้ายกำกับ ชื่อ ประเภท ข้อจำกัด
(1) lhs Tensor ของประเภทบูลีนหรือจำนวนเต็ม (C1)
(I2) rhs Tensor ของประเภทบูลีนหรือจำนวนเต็ม (C1)

เอาต์พุต

ชื่อ ประเภท ข้อจำกัด
result Tensor ของประเภทบูลีนหรือจำนวนเต็ม (C1)

ข้อจำกัด

  • (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 จะดำเนินการโดยระบุค่าอินพุตให้กับฟังก์ชัน main และค่าเอาต์พุตการคำนวณ ระบบจะคํานวณค่าเอาต์พุตของฟังก์ชันโดยการเรียกใช้กราฟของ Ops ที่รูทในตัวเลือก return ที่สอดคล้องกัน

ลำดับการดำเนินการมีการกำหนดไว้สำหรับการใช้งานตราบใดที่สอดคล้องกับโฟลว์ข้อมูล กล่าวคือ เมื่อมีการดำเนินการ Ops ก่อนที่จะใช้งาน ใน StableHLO การดำเนินการที่ส่งผลข้างเคียงทั้งหมดจะใช้ 1 โทเค็นและสร้างโทเค็น 1 รายการ (สามารถรวมโทเค็นหลายรายการไว้ในโทเค็นเดียวผ่าน after_all ได้) เพื่อให้ลำดับการดำเนินการของผลข้างเคียงสอดคล้องกับโฟลว์ข้อมูลด้วย คำสั่งการดำเนินการที่เป็นไปได้ของโปรแกรมตัวอย่างด้านบนคือ %0%1%2%3%4return หรือ %3%0%1%2%4return

หรืออย่างเป็นทางการ กระบวนการของ StableHLO ประกอบด้วย 1) โปรแกรม StableHLO, 2) สถานะการดำเนินการ (ยังไม่ได้ดำเนินการ หรือดำเนินการแล้ว) และ 3) ค่าขั้นกลางที่กระบวนการกําลังดําเนินการ ได้แก่ 1) โปรแกรม StableHLO กระบวนการเริ่มต้นด้วยค่าอินพุตสำหรับฟังก์ชัน main แล้วดำเนินการต่อผ่านกราฟของการดำเนินการอัปเดตสถานะการดำเนินการและค่ากลางและค่าสุดท้ายด้วยค่าเอาต์พุต การประกาศอย่างเป็นทางการจะมีขึ้นภายหลัง (#484)

การดำเนินการพร้อมกัน

โปรแกรม StableHLO ดำเนินการพร้อมกันได้ โดยจัดระเบียบเป็นตารางกระบวนการ 2 มิติของ num_replicas โดย num_partitions ซึ่งทั้ง 2 โปรแกรมมีประเภท ui32

ในตารางกริดกระบวนการของ StableHLO กระบวนการของ StableHLO ดำเนินการ num_replicas * num_partitions รายการพร้อมกัน แต่ละกระบวนการมี process_id = (replica_id, partition_id) ที่ไม่ซ้ำกัน โดยที่ replica_id ใน replica_ids = range(num_replicas) และ partition_id ใน partition_ids = range(num_partitions) ซึ่งทั้งคู่มีประเภท ui32

ทุกๆ โปรแกรมทราบขนาดของตารางกริดกระบวนการ (ในอนาคต เราวางแผนที่จะทำให้เป็นส่วนที่ชัดเจนของโปรแกรม StableHLO #650)) และทราบตำแหน่งภายในตารางกริดของกระบวนการเป็นแบบคงที่สำหรับทุกกระบวนการ แต่ละกระบวนการมีสิทธิ์เข้าถึงตำแหน่งภายในตารางกริดของกระบวนการผ่านการดำเนินการ replica_id และ partition_id

ภายในตารางกระบวนการ โปรแกรมอาจเหมือนกันทั้งหมด (ในรูปแบบ "โปรแกรมเดียว ข้อมูลหลายรายการ") หรือแตกต่างกันได้ (ในรูปแบบ "หลายโปรแกรม ข้อมูลหลายรายการ") หรืออื่นๆ ระหว่างนั้น ในอนาคต เราวางแผนที่จะเพิ่มการรองรับสำนวนอื่นๆ ของการกำหนดโปรแกรม StableHLO พร้อมกัน ซึ่งรวมถึง GSPMD (#619)

ภายในตารางกริดของกระบวนการ กระบวนการส่วนใหญ่จะเป็นอิสระจากกัน กล่าวคือมีสถานะการดำเนินการแยกกัน ค่าอินพุต/สื่อกลาง/เอาต์พุตแยกกัน และการดำเนินการส่วนใหญ่จะดำเนินการแยกกันระหว่างกระบวนการ โดยมีข้อยกเว้นของการดำเนินการโดยรวมจำนวนหนึ่งตามที่อธิบายไว้ด้านล่าง

เนื่องจากการดำเนินการของการดำเนินการส่วนใหญ่ใช้เฉพาะค่าจากกระบวนการเดียวกัน การอ้างอิงค่าเหล่านี้ด้วยชื่อจึงมักไม่ชัดเจน อย่างไรก็ตาม เมื่ออธิบายความหมายของการดำเนินการโดยรวมนั้นไม่เพียงพอ และเป็นที่มาของสัญลักษณ์ name@process_id เพื่ออ้างถึงค่า name ภายในกระบวนการใดกระบวนการหนึ่ง (จากมุมมองนี้ name ที่ไม่เข้าเกณฑ์อาจมองได้ว่าเป็นชวเลขสำหรับ name@(replica_id(), partition_id()))

คำสั่งดำเนินการข้ามกระบวนการจะกำหนดตามการติดตั้งใช้งาน ยกเว้นการซิงค์ที่เกิดจากการสื่อสารแบบจุดต่อจุดและการดำเนินการร่วมตามที่อธิบายไว้ด้านล่าง

การสื่อสารแบบจุดต่อจุด

กระบวนการของ StableHLO สามารถสื่อสารกันได้ผ่านช่องทางของ StableHLO แชแนลจะแสดงด้วยรหัสเชิงบวกประเภท si64 คุณสามารถส่งค่าไปยังแชแนลและรับค่าจากแชแนลได้โดยอาศัยการดำเนินการที่หลากหลาย

ความเป็นทางการเพิ่มเติม เช่น รหัสแชแนลเหล่านี้มาจากที่ใด โปรแกรมรับรู้ถึงรหัสเหล่านี้อย่างไร และขั้นตอนการซิงค์ข้อมูลแบบใดมาจากข้อมูลดังกล่าว จะแจ้งภายหลัง (#484)

การสื่อสารผ่านสตรีมมิง

กระบวนการของ StableHLO ทุกกระบวนการมีสิทธิ์เข้าถึงอินเทอร์เฟซสตรีมมิง 2 รายการดังนี้

  • Infeed ที่อ่านได้
  • Outfeed ที่ระบบเขียนได้

และต่างจากแชแนลที่ใช้สื่อสารระหว่างกระบวนการต่างๆ จึงมีกระบวนการอยู่ทั้ง 2 ฝั่ง ในฟีดในฟีดและฟีดภายนอกมีการกำหนดไว้แล้ว

ความเป็นทางการเพิ่มเติม เช่น การสื่อสารผ่านสตรีมมิงมีอิทธิพลต่อคำสั่งการดำเนินการอย่างไรและประเภทของการซิงค์ที่จะนำมาใช้ในภายหลัง เช่น แจ้งภายหลัง (#484)

การดำเนินการร่วมกัน

ระบบดำเนินการร่วมกัน 6 รายการใน StableHLO ได้แก่ all_gather, all_reduce, all_to_all, collective_broadcast, collective_permute และ reduce_scatter การดำเนินการทั้งหมดนี้แยกกระบวนการในตารางกระบวนการ StableHLO ออกเป็นกลุ่มกระบวนการ StableHLO และดำเนินการคำนวณร่วมภายในแต่ละกลุ่มกระบวนการ โดยแยกจากกลุ่มกระบวนการอื่นๆ

ภายในกลุ่มกระบวนการแต่ละกลุ่ม การดำเนินการร่วมอาจพบอุปสรรคในการซิงค์ ความเป็นทางการเพิ่มเติม เช่น การให้รายละเอียดว่าการซิงค์นี้เกิดขึ้นเมื่อใด กระบวนการต่างๆ มาถึงอุปสรรคนี้ได้อย่างไร และจะเกิดอะไรขึ้นหากไม่เป็นเช่นนั้น จะแจ้งภายหลัง (#484)

หากกลุ่มกระบวนการเกี่ยวข้องกับการสื่อสารแบบข้ามพาร์ติชัน กล่าวคือ มีกระบวนการในกลุ่มกระบวนการที่มีรหัสพาร์ติชันแตกต่างกัน การดำเนินการของ ฝั่งองค์กร จะต้องใช้แชนเนล และการทำงานร่วมกันแบบรวมต้องมี channel_id ที่เป็นบวกประเภท si64 การสื่อสารข้ามแบบจำลองไม่จำเป็นต้องมี แชแนล

การคำนวณที่ดำเนินการโดยกลุ่มการดำเนินการร่วมกันนั้นเฉพาะเจาะจงสำหรับแต่ละการดำเนินการ และมีคำอธิบายในส่วนการดำเนินการของแต่ละส่วนด้านบน อย่างไรก็ตาม กลยุทธ์ที่แบ่งตารางกระบวนการออกเป็นกลุ่มกระบวนการจะมีการแชร์กันระหว่างการดำเนินการเหล่านี้ ซึ่งมีอธิบายไว้ในส่วนนี้ อย่างเป็นทางการคือ StableHLO รองรับ กลยุทธ์ 4 แบบต่อไปนี้

cross_replica

เฉพาะการสื่อสารจากตัวจำลองที่เกิดขึ้นภายในแต่ละกลุ่มกระบวนการเท่านั้น กลยุทธ์นี้ใช้ replica_groups ซึ่งเป็นรายการรหัสตัวจำลอง และคำนวณผลคูณคาร์ทีเซียนของ replica_groups ภายในวันที่ partition_ids 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 ซึ่งเป็นรายการรหัสพาร์ติชัน และคำนวณผลคูณคาร์ทีเซียนของ partition_groups ตาม replica_ids 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 ได้รับการตรวจสอบผ่านชุดข้อจำกัดขนาดใหญ่สำหรับการดำเนินการรายบุคคล ซึ่งจะตัดข้อผิดพลาดประเภทต่างๆ ก่อนการเรียกใช้ อย่างไรก็ตาม เงื่อนไขข้อผิดพลาดยังคงเกิดขึ้นได้ เช่น เมื่อมีข้อมูลเกินจํานวนเต็ม การเข้าถึงเกินขอบเขต ฯลฯ ข้อผิดพลาดทั้งหมดเหล่านี้ส่งผลให้เกิดลักษณะการทํางานที่กําหนดการติดตั้งใช้งาน ซึ่งอาจมีการเปลี่ยนแปลงในอนาคต (#1157) เว้นแต่จะมีการเรียกอย่างชัดแจ้ง

ข้อยกเว้นของกฎนี้คือ ข้อยกเว้นจุดลอยตัวในโปรแกรม StableHLO มีลักษณะการทำงานที่กำหนดไว้อย่างชัดเจน การดำเนินการที่ทำให้เกิดข้อยกเว้นซึ่งกำหนดโดยมาตรฐาน IEEE-754 (การดำเนินการที่ไม่ถูกต้อง การแบ่งทีละศูนย์ การล้น ส่วนที่เกินมา หรือข้อยกเว้นที่ไม่ตรง) จะให้ผลลัพธ์เริ่มต้น (ตามที่กำหนดไว้ในมาตรฐาน) และดำเนินการต่อไปโดยไม่เพิ่มแฟล็กสถานะที่เกี่ยวข้อง ซึ่งคล้ายกับการจัดการข้อยกเว้น raiseNoFlag จากมาตรฐาน ข้อยกเว้นสำหรับการดำเนินการที่ไม่เป็นมาตรฐาน (เช่น เลขคณิตที่ซับซ้อนและฟังก์ชันสืบเนื่องบางอย่าง) มีการกำหนดการนำไปใช้งาน

เครื่องหมาย

ในการอธิบายไวยากรณ์ เอกสารนี้ใช้เวอร์ชัน ISO ที่แก้ไขแล้วของไวยากรณ์ EBNF (ISO/IEC 14977:1996, Wikipedia) โดยมีการแก้ไข 2 ประการ ได้แก่ 1) กฎกำหนดโดยใช้ ::= แทนที่จะเป็น =

2) การต่อกันจะแสดงโดยใช้การวางตัวต่อกันแทนการใช้ ,

สำหรับการอธิบายอรรถศาสตร์ (เช่น ภายในส่วน "ประเภท" "ค่าคงที่" และ "Ops") เราจะใช้สูตรที่อิงตามไวยากรณ์ Python ที่ขยายเพิ่มพร้อมด้วยการรองรับการแสดงการทำงานของอาร์เรย์อย่างกระชับตามที่อธิบายไว้ด้านล่าง วิธีนี้ใช้ได้ดีกับข้อมูลโค้ดสั้นๆ แต่ในบางกรณีซึ่งพบได้ไม่บ่อยนักเมื่อต้องขอข้อมูลโค้ดขนาดใหญ่ เราจะใช้ไวยากรณ์ Python แบบวานิลลาซึ่งมีการระบุไว้อย่างชัดเจนเสมอ

สูตร

มาสำรวจวิธีการทำงานของสูตรตามตัวอย่างจากข้อกำหนด dot_general กัน หนึ่งในข้อจำกัดสำหรับการดำเนินการนี้มีลักษณะดังต่อไปนี้ dim(lhs, lhs_batching_dimensions...) = dim(rhs, rhs_batching_dimensions...)

ชื่อที่ใช้ในสูตรนี้มาจากแหล่งที่มา 2 แหล่ง ได้แก่ 1) ฟังก์ชันส่วนกลาง (เช่น dim) 2) คำนิยามสมาชิกขององค์ประกอบโปรแกรมที่สอดคล้องกัน ซึ่งก็คืออินพุต lhs, lhs_batching_dimensions, rhs และ rhs_batching_dimensions ที่กำหนดไว้ในส่วน "อินพุต" ของ dot_general

ดังที่กล่าวไว้ข้างต้น ไวยากรณ์ของสูตรนี้คือแบบ Python ที่มีส่วนขยายบางส่วนที่เน้นความกระชับ เพื่อให้เข้าใจสูตร เรามาเปลี่ยนรูปแบบเป็นไวยากรณ์ Python แบบวานิลลากัน

ตอบ) ในสูตรเหล่านี้ เราใช้ = เพื่อแสดงความเท่ากัน ดังนั้นขั้นตอนแรกในการได้รับไวยากรณ์ Python จะแทนที่ = ด้วย == ดังนี้ dim(lhs, lhs_batching_dimensions...) == dim(rhs, rhs_batching_dimensions...)

B) นอกจากนี้ สูตรเหล่านี้ยังรองรับจุดไข่ปลา (...) ซึ่งเปลี่ยนนิพจน์สเกลาร์เป็นนิพจน์ tensor โดยสรุปแล้ว f(xs...) หมายถึง "สำหรับ x สเกลาร์แต่ละรายการใน tensor xs ให้คำนวณสเกลาร์ f(x) แล้วแสดงผลลัพธ์สเกลาร์เหล่านี้ทั้งหมดรวมกันเป็นผลลัพธ์ Tensor" ในไวยากรณ์ 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 โดยหวังว่าเนื้อหาจะยังเข้าใจได้ง่ายโดยแยกเป็นรายกรณีไป โปรดแจ้งให้เราทราบหากบางสูตรดูไม่ชัดเจนและเราจะพยายามปรับปรุง

คุณจะสังเกตเห็นว่าสูตรใช้จุดไข่ปลาเพื่อขยายรายการทุกประเภท รวมถึง tensors, รายการ tensors (ซึ่งอาจเกิดจากจำนวน tensors แปรปรวน) ฯลฯ นี่เป็นอีกเรื่องหนึ่งที่เราไม่ได้ระบุความเป็นทางการที่แน่นอน (เช่น รายการไม่ได้เป็นส่วนหนึ่งของระบบประเภท StableHLO ที่เข้าใจได้ง่าย) และอาศัยการเข้าใจรูปแบบ

ค) สัญลักษณ์สำคัญข้อสุดท้ายที่เราใช้คือการออกอากาศโดยนัย แม้ว่าตัวเลือกของ StableHLO จะไม่รองรับการออกอากาศโดยนัย แต่สูตรเหล่านี้ก็รองรับในรูปแบบของความกระชับเช่นกัน สรุปง่ายๆ ก็คือ หากใช้สเกลาร์ในบริบทที่คาดว่า tensor ก็จะแสดงสเกลาร์เป็นรูปร่างที่คาดไว้

ต่อไปนี้คือข้อจำกัดอีก 1 ข้อเพื่อแสดงตัวอย่าง dot_general ต่อ 0 <= lhs_batching_dimensions < rank(lhs) ตามที่ระบุไว้ในข้อมูลจำเพาะของ dot_general lhs_batching_dimensions คือ Tensor แต่ทั้ง 0 และ rank(lhs) เป็นสเกลาร์ หลังจากเราใช้การออกอากาศโดยนัยแล้ว สูตรจะกลายเป็น [0, ..., 0] <= lhs_batching_dimensions < [rank(lhs), ..., rank(lhs)]

เมื่อใช้กับการดำเนินการ dot_general ที่เฉพาะเจาะจง สูตรนี้จะประเมินโดยใช้ tensor ของบูลีน เมื่อใช้สูตรเป็นข้อจำกัด ข้อจำกัดจะระงับหากสูตรประเมินเป็น true หรือกับ tensor ที่มีองค์ประกอบ 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 (ประเภทตามที่กำหนดในส่วน "ประเภท") ตามที่ให้คำจำกัดความไว้ในส่วน "ฟังก์ชันร่วม)Function

ชื่ออาจหมายถึงค่าที่ต่างกัน ทั้งนี้ขึ้นอยู่กับบริบท กล่าวอย่างเจาะจงคือ ส่วน "Semantics" สำหรับ Ops (และองค์ประกอบที่เทียบเท่าสำหรับองค์ประกอบอื่นๆ ของโปรแกรม) จะกำหนดตรรกะรันไทม์ ดังนั้นอินพุตทั้งหมดจึงพร้อมใช้งานเป็น Value ในทางตรงกันข้าม ส่วน "ข้อจำกัด" สำหรับการดำเนินการ (และที่เทียบเท่า) จะกำหนดตรรกะ "เวลาคอมไพล์" ซึ่งก็คือสิ่งที่มักดำเนินการก่อนรันไทม์ ดังนั้นจะมีเฉพาะอินพุตคงที่ที่พร้อมใช้งานเป็น 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 ในข้อจำกัดเท่านั้น

ฟังก์ชัน

การสร้างประเภทต่างๆ

โดยจะไม่มีฟังก์ชันที่ใช้สร้างประเภทได้ แต่เราจะใช้ไวยากรณ์ประเภทโดยตรงแทนเนื่องจากรูปแบบนี้จะกระชับกว่า เช่น (tensor<E>, tensor<E>) -> (tensor<E>) แทนที่จะเป็น function_type( [tensor_type([], E), tensor_type([], E)], [tensor_type([], E)])

ฟังก์ชันเกี่ยวกับประเภท

  • element_type กำหนดไว้ในประเภท tensor และประเภท tensor ที่วัดปริมาณแล้วและผลลัพธ์กลับมา ตามลําดับ ส่วน TensorElementType หรือ QuantizedTensorElementType ของ TensorType หรือ QuantizedTensorType ที่สอดคล้องกัน
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 พร้อมใช้งานสำหรับ ทุกประเภท เช่น is_float(x) จะแสดงผล true หาก x เป็น FloatType หาก 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) จะแสดงผลส่วน TensorElementType ของ TensorType ที่ตรงกัน หาก x เป็นค่าหรือตัวยึดตำแหน่ง ฟังก์ชันนี้จะเป็นทางลัดสำหรับ member_name(type(x)) หาก x ไม่ใช่ประเภทที่มีสมาชิกที่เหมาะสม หรือมีค่าหรือตัวยึดตำแหน่งของประเภทดังกล่าว ระบบจะแสดงผล None

โครงสร้างของค่า

  • operation_name(*xs: Value | Type) -> Value พร้อมใช้งานสำหรับการดำเนินการทั้งหมด ตัวอย่างเช่น add(lhs, rhs) รับค่า tensor 2 ค่า lhs และ rhs และแสดงค่าเอาต์พุตของการประเมินการดำเนินการ add ด้วยอินพุตเหล่านี้ สำหรับการดำเนินการบางอย่าง เช่น broadcast_in_dim ประเภทของเอาต์พุตคือ "การรับน้ำหนัก" นั่นคือจำเป็นสำหรับการประเมินการดำเนินการ ในกรณีนี้ ฟังก์ชันนี้ จะใช้ประเภทเหล่านี้เป็นอาร์กิวเมนต์

ฟังก์ชันของค่า

  • โอเปอเรเตอร์และฟังก์ชันทั้งหมดของ Python พร้อมใช้งาน เช่น ทั้งเครื่องหมาย subscription และ Slicing จาก Python สามารถจัดทำดัชนีเป็น tensors, tensors แบบวัดปริมาณ และ tuple ได้

  • to_destination_type(x: Value, destination_type: Type) -> Value กำหนดไว้ตาม tensors และแสดงผลค่าที่แปลงแล้วของ x โดยอิงตาม type(x) และ destination_type ดังนี้

def to_destination_type(x: Value, destination_type: Type) -> Value:
  if type(x) == destination_type:
    return x

  if is_quantized(destination_type):
    if is_quantized(type(x)):
      return quantize(x, destination_type)
    assert is_float(type(x))
    return quantize(x, destination_type)

  if is_quantized(type(x)):
    assert destination_type = expressed_type(type(x))
    return dequantize(type(x))

  return convert(x, destination_type)

มีการพูดคุยล่วงหน้าเกี่ยวกับการรวมการดำเนินการ convert, uniform_quantize และ uniform_dequantize (#1576) หลังจากผสานแล้ว เราไม่จำเป็นต้องใช้ฟังก์ชันข้างต้น และจะใช้ชื่อการดำเนินการสำหรับ convert แทนได้

  • is_nan(x: Value) -> Value จะได้รับการกำหนดใน tensors และแสดงผล true หากองค์ประกอบทั้งหมดของ x เป็น NaN หรือ false ในกรณีอื่นๆ หาก x ไม่ใช่ Tensor จะแสดงผล None

  • มีการกำหนด is_sorted(x: Value) -> Value ใน tensors และจะแสดงผล true หากองค์ประกอบของ x ได้รับการจัดเรียงจากน้อยไปมากตามลำดับพจนานุกรมของดัชนีจากน้อยไปมากของดัชนี หรือ false ในกรณีอื่นๆ หาก x ไม่ใช่ Tensor จะแสดงผล None

  • is_unique(x: Value) -> Value จะได้รับการกำหนดใน Tensor และแสดงค่า true หาก x ไม่มีองค์ประกอบที่ซ้ำกันหรือ false ในกรณีอื่นๆ หาก x ไม่ใช่ Tensor จะแสดงผล None

  • member_name(x: Value) -> Any สำหรับคำจำกัดความสมาชิกทั้งหมด member_name สำหรับค่าทั้งหมด เช่น real_part(x) จะแสดงผลส่วน RealPart ของ ComplexConstant ที่ตรงกัน หาก x ไม่ใช่ค่าที่มีสมาชิกที่เหมาะสม ระบบจะแสดงผล None

  • same(x: Value) -> Value จะได้รับการกำหนดใน tensors และแสดงผล true หากองค์ประกอบ x ทั้งหมดเท่ากัน หรือ false ในกรณีอื่นๆ หาก tensor ไม่มีองค์ประกอบ ระบบจะนับเป็น "ทั้งหมดเท่ากับซึ่งกันและกัน" กล่าวคือ ฟังก์ชันจะแสดงผล true หาก x ไม่ใช่ Tensor จะแสดงผล None

  • split(x: Value, num_results: Value, axis: Value) -> Value กำหนดไว้ใน Tensor และแสดงผลส่วน num_results ของ x ตามแกน axis หาก x ไม่ใช่ Tensor หรือ dim(x, axis) % num_results != 0 จะแสดงผล None

การคํานวณรูปร่าง

  • axes(x: Value | Placeholder | Type) -> Value เป็นทางลัดสำหรับ range(rank(x))

  • dim(x: Value | Placeholder | Type, axis: Value) -> Value เป็นทางลัดสำหรับ shape(x)[axis]

  • dims(x: Value | Placeholder | Type, axes: List) -> List เป็นทางลัดสำหรับ list(map(lambda axis: dim(x, axis), axes))

  • index_space(x: Value | Placeholder | Type) -> Value กำหนดไว้ใน Tensor และแสดงดัชนี size(x) สำหรับ TensorType ที่สอดคล้องซึ่งเรียงลำดับแบบพจนานุกรมจากน้อยไปมาก เช่น [0, ..., 0], [0, ..., 1], ..., shape(x) - 1 หาก x ไม่ใช่ประเภท tensor, ประเภท tensor ที่เล็กลง หรือค่าหรือตัวยึดตำแหน่งของประเภทเหล่านี้ จะแสดงผล None

  • rank(x: Value | Placeholder | Type) -> Value เป็นทางลัดสำหรับ size(shape(x))

  • shape(x: Value | Placeholder | Type) -> Value กำหนดไว้ในส่วน "ฟังก์ชันเกี่ยวกับประเภท" ผ่าน member_name

  • size(x: Value | Placeholder | Type) -> Value เป็นทางลัดสำหรับ reduce(lambda x, y: x * y, shape(x))

การคํานวณเชิงปริมาณ

  • def baseline_element_type(x: Value | Placeholder | Type) -> Type เป็น ทางลัดสำหรับ element_type(baseline_type(x))

  • baseline_type กำหนดไว้ในประเภท tensor และประเภท tensor ที่วัดปริมาณแล้ว แล้วแปลงค่าเหล่านี้เป็น "baseline" กล่าวคือ เป็นประเภทที่มีรูปร่างเหมือนกันแต่มีพารามิเตอร์เชิงปริมาณของประเภทองค์ประกอบจะรีเซ็ตเป็นค่าเริ่มต้น ข้อมูลนี้ใช้เป็นเคล็ดลับที่มีประโยชน์ในการเปรียบเทียบทั้ง tensor และ tensor ในเชิงปริมาณอย่างเท่าเทียมกัน ซึ่งต้องใช้ค่อนข้างบ่อย สำหรับประเภทที่เล็กลง การดำเนินการนี้ช่วยให้เปรียบเทียบประเภทที่ไม่สนใจพารามิเตอร์เชิงปริมาณ ซึ่งได้แก่ shape, storage_type, expressed_type, storage_min, storage_max และ quantization_dimension (สำหรับประเภทที่เล็กลงตามแกน 1 แกน) ต้องตรงกันทั้งหมด แต่ scales กับ zero points อาจแตกต่างกัน

def baseline_type(x: Value | Placeholder | Type) -> Type:
  if type(x) == TensorType:
    return x
  if type(x) == QuantizedTensorType:
    element_type = quantized_tensor_element_type(x)
    baseline_element_type = QuantizedTensorElementType(
      storage_type = storage_type(element_type),
      storage_min = storage_min(element_type),
      storage_max = storage_max(element_type),
      expressed_type = expressed_type(element_type),
      quantization_dimension = quantization_dimension(element_type),
      scales = [constant(1.0, expressed_type(element_type))] * dim(x, quantization_dimension(element_type)),
      zero_points = [constant(0, storage_type(element_type))] * dim(x, quantization_dimension(element_type)))
    return QuantizedTensorType(shape(x), baseline_element_type)
  if type(x) is not Type:
    return baseline_element_type(type(x))
  • dequantize กำหนดไว้ในประเภท tensor ที่วัดปริมาณแล้วและเปลี่ยนให้เป็น tensor แบบจุดลอยตัว กรณีนี้เกิดขึ้นผ่านการแปลงองค์ประกอบที่วัดปริมาณแล้วซึ่งแสดงค่าจำนวนเต็มของประเภทพื้นที่เก็บข้อมูลให้เป็นค่าจุดลอยตัวที่สอดคล้องกันของประเภทที่แสดงโดยใช้จุด 0 และมาตราส่วนที่เชื่อมโยงกับประเภทองค์ประกอบที่เล็กลง
def compute_zero_points(quantized_type, result_type):
  if is_per_tensor_quantized(quantized_type):
    return broadcast_in_dim(constant(zero_point(quantized_type), storage_type(quantized_type)), [], result_type)
  if is_per_axis_quantized(quantized_type):
    for i in index_space(result_type):
      d = quantization_dimension(quantized_type)
      zero_points[i] = zero_points(quantized_type)[i[d]]
    return zero_points

def compute_scales(quantized_type, result_type):
  if is_per_tensor_quantized(quantized_type):
    return broadcast_in_dim(constant(scale(quantized_type), expressed_type(quantized_type)), [],
            type(result_type))
  if is_per_axis_quantized(quantized_type):
    for i in index_space(result_type):
      d = quantization_dimension(quantized_type)
      scales[i] = scales(quantized_type)[i[d]]
    return scales

def dequantize(x: Value) -> Value:
  assert is_quantized(x)
  x_storage = bitcast_convert(x, storage_type(x))
  x_storage_sub = x_storage - compute_zero_points(type(x), type(x_storage))
  x_expressed_sub = convert(x_storage_sub, expressed_type(x))
  return x_expressed_sub * compute_scales(type(x), type(x_expressed_sub))
  • quantize กำหนดไว้ในประเภท tensor ของจุดลอยตัว แล้วเปลี่ยนให้เป็น tensor เชิงปริมาณ กรณีนี้เกิดขึ้นผ่านการแปลงค่าจุดลอยตัวของประเภทที่แสดงเป็นค่าจำนวนเต็มที่สอดคล้องของประเภทพื้นที่เก็บข้อมูลโดยใช้จุด 0 และมาตราส่วนที่เชื่อมโยงกับประเภทองค์ประกอบที่วัดปริมาณแล้ว
def quantize(x: Value, type: Type) -> Value:
  assert is_float(x) and is_quantized(type)
  x_expressed_rounded = round_nearest_even(x / compute_scales(type, type(x)))
  x_storage_rounded = convert(x_expressed_rounded, storage_type(type))
  x_storage_add = x_storage_rounded + compute_zero_points(type, type(x_storage_rounded))
  x_storage = clamp(storage_min(type), x_storage_add, storage_max(type))
  return bitcast_convert(x_storage, type)
  • dequantize_op_quantize ใช้เพื่อระบุการคำนวณแบบ Element-wise ใน Tensor ที่วัดปริมาณ จะแสดงผลเท่ากัน กล่าวคือ เปลี่ยนองค์ประกอบที่ปริมาณเป็นเชิงปริมาณเป็นประเภทที่แสดงผล จากนั้นดำเนินการ แล้วคำนวณปริมาณ กล่าวคือ เปลี่ยนผลลัพธ์กลับเป็นประเภทพื้นที่เก็บข้อมูล ในขณะนี้ ฟังก์ชันนี้ทำงานได้เฉพาะ สำหรับการวัดปริมาณต่อ tensor เท่านั้น ระบบกำลังดำเนินการคำนวณจำนวนตามแกน (#1574)
def dequantize_op_quantize(op, *inputs_and_output_type):
  inputs = inputs_and_output_type[:-1]
  output_type = inputs_and_output_type[-1]

  float_inputs = map(dequantize, inputs)
  float_result = op(*float_inputs)
  return quantize(float_result, output_type)

def dequantize_batch_norm_grad_or_training_quantize(op, *inputs_and_output_types):
  inputs = inputs_and_output_type[:-3]
  float_inputs = map(dequantize, inputs)
  float_results = op(*float_inputs)
  return map(quantize, float_results, inputs_and_output_type[-3:])

def dequantize_compare(lhs, rhs, comparison_direction):
  float_lhs = dequantize(lhs)
  float_rhs = dequantize(rhs)
  return compare(float_lhs, float_rhs, comparison_direction, FLOAT)

def dequantize_select_quantize(pred, on_true, on_false, output_type):
  float_on_true = dequantize(on_true)
  float_on_false = dequantize(on_false)
  float_result = select(pred, float_on_true, float_on_false)
  return quantize(float_result, output_type)

การคำนวณแบบตารางกริด

  • cross_partition(replica_groups: Value) -> Value ดูส่วน "cross_replica" ด้านบน

  • cross_replica(replica_groups: Value) -> Value ดูส่วน "cross_replica" ด้านบน

  • cross_replica_and_partition(replica_groups: Value) -> Value ดูส่วน "cross_replica_and_partition" ด้านบน

  • flattened_ids(replica_groups: Value) -> Value ดูส่วน "flattened_ids" ด้านบน