-chlo-legalize-to-stablehlo

แปลงจากโฟลว์การดำเนินการของ CHLO เป็น StableHLO และการดำเนินการของ Shape

-shape-legalize-to-stablehlo

ทำให้การดำเนินการที่เกี่ยวข้องกับรูปร่างเป็นไปตามกฎหมายใน StableHLO

การส่งผ่านการทดลองที่ทำให้การดำเนินการที่เกี่ยวข้องกับรูปร่างเป็นการดำเนินการ StableHLO ที่ถูกต้องตามกฎหมาย

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

-stablehlo-canonicalize-dynamism

แปลงการดำเนินการ StableHLO แบบไดนามิกให้เป็นการดำเนินการแบบคงที่

แทนที่การดำเนินการ StableHLO แบบไดนามิก เช่น DynamicReshapeOp ด้วยการดำเนินการแบบคงที่ที่สอดคล้องกัน เช่น DynamicReshapeOp เป็น ReshapeOp หรือ DynamicBroadcastInDim เป็น BroadcastInDim หากองค์ประกอบแบบไดนามิกทั้งหมดของการดำเนินการเหล่านี้เป็นค่าคงที่จริงๆ

  %c = stablehlo.constant dense<16> : tensor<1xi32>
  %0 = stablehlo.dynamic_broadcast_in_dim %cst, %c, dims = [] : (tensor<f32>, tensor<1xi32>) -> tensor<16xf32>

  ==>

  %0 = stablehlo.broadcast_in_dim %cst, dims = [] : (tensor<f32>) -> tensor<16xf32>

-stablehlo-check-shape-assertions

_Check stablehlo.custom_call @shapeassertion ops.

ตรวจสอบการเรียกที่กำหนดเองของ shape_assertion

การยืนยันรูปร่างจะตรวจสอบข้อจำกัดเกี่ยวกับมิติข้อมูลแบบไดนามิกใน StableHLO ตัวอย่างเช่น หากเฟรมเวิร์กจำเป็นต้องบังคับใช้ข้อจำกัดของ DimA < 2 ก็อาจปล่อย IR ต่อไปนี้ออกมา

%dimA = <get_dimension_size or input arg> : tensor<i32>
%c2 = stablehlo.constant dense<2> : tensor<i32>
%is_lt = stablehlo.compare LT %dimA, %c2 : tensor<i1>
stablehlo.custom_call @shape_assertion(%is_lt) { error_message = "DimA must be less than 2" }

หลังจากผ่านการตรวจสอบแล้ว หากรูปร่างถูกต้อง ระบบจะนำstablehlo.custom_call ออก

ตัวเลือก

-enable-shape-assertions : Whether shape assertions may generate errors.

-stablehlo-compatibility-expander

ตัวขยายความเข้ากันได้สำหรับการดำเนินการ StableHLO

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

เหตุใดจึงต้องเลือกใช้บัตรนี้

บางครั้งจะใช้การเพิ่มประสิทธิภาพการดำเนินการ StableHLO เพื่อลดความซับซ้อนในการจัดการรูปแบบทั่วไปบางอย่างในระบบนิเวศ OpenXLA ซึ่งรวมถึงสิ่งต่างๆ เช่น TanOp ซึ่งมีการรองรับเฟรมเวิร์กและคอมไพเลอร์สูง รวมถึงมิติข้อมูลการจัดกลุ่มแบบรวบรวม/กระจาย ซึ่งแสดงได้ โดยใช้ Slice แต่ทำให้การ Sharding ยากขึ้นมาก สำหรับหมวดหมู่ฟีเจอร์ใหม่นี้ เราไม่มีการดาวน์เกรดอัตโนมัติ เนื่องจากอาจทิ้งข้อมูลสำคัญที่ใช้ในการเพิ่มประสิทธิภาพในภายหลัง พาสนี้สามารถใช้เพื่อขยายการดำเนินการเหล่านี้ตามเวอร์ชันเป้าหมายเพื่อเพิ่มความเข้ากันได้สูงสุด โดยอาจทำให้การคอมไพล์มีประสิทธิภาพน้อยลง

func.func @tan_op_non_complex(%arg0: tensor<4xf64>) -> tensor<4xf64> {
  %1 = stablehlo.tan %arg0 : tensor<4xf64>
  func.return %1 : tensor<4xf64>
}

==>

func.func @tan_op_non_complex(%arg0: tensor<4xf64>) -> tensor<4xf64> {
  %0 = stablehlo.sine %arg0 : tensor<4xf64>
  %1 = stablehlo.cosine %arg0 : tensor<4xf64>
  %2 = stablehlo.divide %0, %1 : tensor<4xf64>
  return %2 : tensor<4xf64>
}

ตัวเลือก

-target : The target version. Must be a version of the form #.#.#.

-stablehlo-complex-math-expander

ตัวขยายสำหรับการดำเนินการทางคณิตศาสตร์ที่ซับซ้อนของ StableHLO

การดำเนินการทางคณิตศาสตร์เชิงซ้อนของ StableHLO คือการแยกส่วนโดยใช้ การดำเนินการทางคณิตศาสตร์จริงของ StableHLO

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

func.func @sqrt_op_complex(%arg0: tensor<4xcomplex<f64>>) -> tensor<4xcomplex<f64>> {
  %1 = stablehlo.sqrt %arg0 : tensor<4xcomplex<f64>>
  func.return %1 : tensor<4xcomplex<f64>>
}

==>

func.func @sqrt_op_complex(%arg0: tensor<4xcomplex<f64>>) -> tensor<4xcomplex<f64>> {
  TBD
  return %2 : tensor<4xcomplex<f64>>
}

-stablehlo-convert-to-signless

Pass to transform the IR to be on signless integers.

-stablehlo-legalize-composite-to-call

แทนที่การดำเนินการแบบคอมโพสิตด้วยการเรียกการแยกส่วน

แทนที่การดำเนินการแบบคอมโพสิตด้วยการเรียกการแยกส่วน เช่น การดำเนินการด้านล่าง

stablehlo.composite "my_namespace.my_op" %arg0, %arg1 {
  decomposition = @bar,
  version = 1,
  composite_attributes = {
    "my_attribute": "my_value"
  }
}

จะกลายเป็น

func.call @bar(%arg0, %arg1)

คุณยกเว้นคอมโพสิตบางส่วนจากการเปลี่ยนรูปแบบนี้ได้โดยใช้แฟล็ก "except" เช่น

stablehlo-opt --stablehlo-legalize-composite-to-call=except='foo.baz,foo.qux'

ตัวเลือก

-except : Names of composites that should not be replaced with calls.

-stablehlo-legalize-deprecated-ops

เปลี่ยนการดำเนินการที่เลิกใช้งานแล้วเป็นการดำเนินการที่รองรับได้ดี

RFC การเลิกใช้งาน Opset ของ StableHLO v1.0 (#2283) เสนอให้นำการดำเนินการที่ซ้ำซ้อนหลายรายการออก การส่งผ่านนี้จะช่วยประเมินผลกระทบของการนำออกเหล่านี้ในไปป์ไลน์การคอมไพล์ต่างๆ โดยการทำให้การนำออกเหล่านี้ถูกต้องตามกฎหมายเพื่อนำไปใช้กับรายการที่คล้ายกันซึ่งรองรับในระยะยาว

ตัวเลือก

-fail-on-unused : Fail on (mostly) unused ops that are deprecated without any fallback.

-stablehlo-legalize-qdq-to-quantized-op

ผสานรูปแบบ (ยกเลิกการหาปริมาณ การดำเนินการแบบจุดลอย และการหาปริมาณ) เข้ากับการดำเนินการที่หาปริมาณแล้วของ StableHLO

ผสานรูปแบบ (ยกเลิกการควอนไทซ์ การดำเนินการแบบจุดลอย และควอนไทซ์) เข้ากับการดำเนินการที่ควอนไทซ์ของ StableHLO หมายเหตุ: การส่งผ่านจะไม่ลบ Op ที่มีอยู่ ตัวอย่างเช่น โปรแกรมต่อไปนี้

func.func @add(%arg0: tensor<16x16x!quant.uniform<ui8:f32, 34.0:16>>) -> tensor<16x16x!quant.uniform<ui8:f32, 34.0:16>> {
  %0 = stablehlo.uniform_dequantize %arg0 : (tensor<16x16x!quant.uniform<ui8:f32, 34.0:16>>) -> tensor<16x16xf32>
  %1 = stablehlo.abs %0 : tensor<16x16xf32>
  %2 = stablehlo.uniform_quantize %1 : (tensor<16x16xf32>) -> tensor<16x16x!quant.uniform<ui8:f32, 34.0:16>>
  func.return %2 : tensor<16x16x!quant.uniform<ui8:f32, 34.0:16>>
}

จะกลายเป็น

func.func @add(%arg0: tensor<16x16x!quant.uniform<u8:f32, 3.400000e+01:16>>) -> tensor<16x16x!quant.uniform<u8:f32, 3.400000e+01:16>> {
  %0 = stablehlo.uniform_dequantize %arg0 : (tensor<16x16x!quant.uniform<u8:f32, 3.400000e+01:16>>) -> tensor<16x16xf32>
  %1 = stablehlo.abs %0 : tensor<16x16xf32>
  %2 = stablehlo.abs %arg0 : tensor<16x16x!quant.uniform<u8:f32, 3.400000e+01:16>>
  %3 = stablehlo.uniform_quantize %1 : (tensor<16x16xf32>) -> tensor<16x16x!quant.uniform<u8:f32, 3.400000e+01:16>>
  return %2 : tensor<16x16x!quant.uniform<u8:f32, 3.400000e+01:16>>
}

-stablehlo-legalize-quant-to-math

แปลงจากการดำเนินการเชิงปริมาณ StableHLO เป็นการดำเนินการทางคณิตศาสตร์ดั้งเดิมของ StableHLO

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

func.func @add(%arg0: tensor<!quant.uniform<i8:f32,1.0:0>>, %arg1: tensor<!quant.uniform<i8:f32,2.0:1>>) ->  tensor<!quant.uniform<i8:f32,3.0:2>> {
  %0 = "stablehlo.add"(%arg0, %arg1) : (tensor<!quant.uniform<i8:f32,1.0:0>>, tensor<!quant.uniform<i8:f32,2.0:1>>) -> tensor<!quant.uniform<i8:f32,3.0:2>>
  func.return %0 : tensor<!quant.uniform<i8:f32,3.0:2>>
}

จะกลายเป็น

func.func @add(%arg0: tensor<i8>, %arg1: tensor<i8>) -> tensor<i8> {
  %0 = stablehlo.convert %arg0 : (tensor<i8>) -> tensor<f32>
  %cst = stablehlo.constant dense<0.333333343> : tensor<f32>
  %1 = chlo.broadcast_multiply %0, %cst : (tensor<f32>, tensor<f32>) -> tensor<f32>
  %cst_0 = stablehlo.constant dense<2.000000e+00> : tensor<f32>
  %2 = chlo.broadcast_add %1, %cst_0 : (tensor<f32>, tensor<f32>) -> tensor<f32>
  %3 = stablehlo.round_nearest_even %2 : tensor<f32>
  %4 = stablehlo.convert %3 : (tensor<f32>) -> tensor<i32>
  %5 = stablehlo.convert %arg1 : (tensor<i8>) -> tensor<f32>
  %cst_1 = stablehlo.constant dense<0.666666686> : tensor<f32>
  %6 = chlo.broadcast_multiply %5, %cst_1 : (tensor<f32>, tensor<f32>) -> tensor<f32>
  %cst_2 = stablehlo.constant dense<1.33333337> : tensor<f32>
  %7 = chlo.broadcast_add %6, %cst_2 : (tensor<f32>, tensor<f32>) -> tensor<f32>
  %8 = stablehlo.round_nearest_even %7 : tensor<f32>
  %9 = stablehlo.convert %8 : (tensor<f32>) -> tensor<i32>
  %c = stablehlo.constant dense<2> : tensor<i32>
  %10 = chlo.broadcast_add %4, %9 : (tensor<i32>, tensor<i32>) -> tensor<i32>
  %11 = chlo.broadcast_subtract %10, %c : (tensor<i32>, tensor<i32>) -> tensor<i32>
  %c_3 = stablehlo.constant dense<-128> : tensor<i32>
  %c_4 = stablehlo.constant dense<127> : tensor<i32>
  %12 = stablehlo.clamp %c_3, %11, %c_4 : tensor<i32>
  %13 = stablehlo.convert %12 : (tensor<i32>) -> tensor<i8>
  return %13 : tensor<i8>
}

-stablehlo-legalize-quantized-op-to-qdq

แยกการดำเนินการ StableHLO ที่มีการวัดปริมาณออกเป็นรูปแบบ (เลิกวัดปริมาณ การดำเนินการแบบจุดลอย และวัดปริมาณ)

แยกโปรแกรมที่ได้รับการควอนไทซ์ของ StableHLO โดยใช้การดำเนินการควอนไทซ์/ยกเลิกควอนไทซ์แบบสม่ำเสมอ ตัวอย่างเช่น โปรแกรมต่อไปนี้

func.func @add(%arg0: tensor<!quant.uniform<i8:f32,1.0:0>>, %arg1: tensor<!quant.uniform<i8:f32,2.0:1>>) ->  tensor<!quant.uniform<i8:f32,3.0:2>> {
  %0 = "stablehlo.add"(%arg0, %arg1) : (tensor<!quant.uniform<i8:f32,1.0:0>>, tensor<!quant.uniform<i8:f32,2.0:1>>) -> tensor<!quant.uniform<i8:f32,3.0:2>>
  func.return %0 : tensor<!quant.uniform<i8:f32,3.0:2>>
}

จะกลายเป็น

func.func @add(%arg0: tensor<!quant.uniform<i8:f32, 1.000000e+00>>, %arg1: tensor<!quant.uniform<i8:f32, 2.000000e+00:1>>) -> tensor<!quant.uniform<i8:f32, 3.000000e+00:2>> {
  %0 = stablehlo.uniform_dequantize %arg0 : (tensor<!quant.uniform<i8:f32, 1.000000e+00>>) -> tensor<f32>
  %1 = stablehlo.uniform_dequantize %arg1 : (tensor<!quant.uniform<i8:f32, 2.000000e+00:1>>) -> tensor<f32>
  %2 = stablehlo.add %0, %1 : tensor<f32>
  %3 = stablehlo.uniform_quantize %2 : (tensor<f32>) -> tensor<!quant.uniform<i8:f32, 3.000000e+00:2>>
  return %3 : tensor<!quant.uniform<i8:f32, 3.000000e+00:2>>
}

-stablehlo-legalize-to-vhlo

ทำให้ StableHLO เป็น VHLO ถูกกฎหมาย

แปลง StableHLO เป็นการดำเนินการเวอร์ชันล่าสุดใน VHLO จากนั้นสามารถลดเวอร์ชันของ Op เหล่านี้เป็น VHLO เวอร์ชันเก่าเพื่อความเข้ากันได้แบบย้อนกลับโดยใช้ VhloToVersionPass

stablehlo.exponential %[[ARG0]] <{result_accuracy = DEFAULT}> : tensor<f32>
# ====>
"vhlo.exponential_v2"(%[[ARG0]]) <{result_accuracy = #vhlo.DEFAULT_v1}> : !vhlo.tensor_v1<!vhlo.f32_v1>

ดูรายละเอียดทั้งหมดเกี่ยวกับวิธีใช้ VHLO เพื่อรักษาความเข้ากันได้แบบย้อนกลับและไปข้างหน้าได้ที่ vhlo.md > The VHLO dialect

ตัวเลือก

-allow-other-dialects : Allow serialization to use other (potentially unstable) dialects, inserts unrealized casts between dialects.

-stablehlo-refine-arguments

ปรับรูปร่างอาร์กิวเมนต์ของฟังก์ชันหลัก

แก้ไขอาร์กิวเมนต์ของฟังก์ชันหลักโดยใช้ลายเซ็นประเภทอินพุต ห่อหุ้มอาร์กิวเมนต์ใน custom_call @stablehlo.shape_refinement_operand_wrapper เพื่อให้ IR ยังคงใช้ได้ก่อนที่จะเรียกใช้การปรับแต่งรูปร่าง

func.func public @main(%arg0: tensor<?xf32>) -> tensor<?xf32> {
  ...
}

==>

func.func public @main(%arg0: tensor<16xf32>) -> tensor<?xf32> {
  %c = stablehlo.constant dense<16> : tensor<1xi64>
  %0 = stablehlo.custom_call @stablehlo.shape_refinement_operand_wrapper(%arg0, %c) {...}
    : (tensor<16xf32>, tensor<1xi64>) -> tensor<?xf32>
  ...
}

refinedTypesOption ใช้เพื่อระบุรายการประเภทที่ปรับแต่งแล้วได้ คุณระบุค่านี้ได้ใน MLIR ด้วย --types='tensor<...>,tensor<...>' หรือ ส่งไปยังเมธอดสร้างบัตร รายการประเภทการปรับแต่งต้องระบุประเภทของอาร์กิวเมนต์ทั้งหมดไปยังเมธอด main ที่กำลังปรับแต่ง

ตัวเลือก

-types : The new types to be used for the main function's arguments, specified as an MLIR TypeRange 'tensor<1x2xf32>, ...'

-stablehlo-refine-shapes

ปรับแต่งรูปร่างในโปรแกรม StableHLO

อธิบายโปรแกรม StableHLO โดยการปรับแต่งรูปร่างภายในการดำเนินการ

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

พาสนี้จะนำ custom_call @shape_refinement_operand_wrapper ออกโดย แทนที่การใช้ผลลัพธ์ด้วยตัวถูกดำเนินการโดยตรง และเผยแพร่ รูปร่างแบบคงที่ตลอดทั้งโปรแกรม

  %c = stablehlo.constant dense<16> : tensor<1xi64>
  %0 = stablehlo.custom_call @stablehlo.shape_refinement_operand_wrapper(%arg0, %c) {...}
      : (tensor<16xf32>, tensor<1xi64>) -> tensor<?xf32>
  %1 = stablehlo.add %0, %0 : tensor<?xf32>

  ==>

  %1 = stablehlo.add %arg0, %arg0 : tensor<16xf32>

โมดูลที่ใช้ได้สำหรับการปรับแต่งรูปร่างต้องมีพร็อพเพอร์ตี้ต่อไปนี้

  • รูปร่างแบบไดนามิกทั้งหมดจะขึ้นอยู่กับรูปร่างอินพุตเท่านั้น (ไม่มีการขึ้นต่อกันของรูปร่างกับเนื้อหาอาร์เรย์อินพุต) เราเรียกการดำเนินการที่ ขึ้นอยู่กับรูปร่างอินพุตแบบทรานซิทีฟเท่านั้น (เช่น ตามที่ระบุโดย stablehlo.get_dimension_size) หรือค่าคงที่ส่วนกลาง เช่น ค่าที่แก้ไขแล้ว ของจำนวนเต็มเชิงสัญลักษณ์ (เช่น เทนเซอร์ : A = 5) ว่าเป็นการดำเนินการ dimension ค่ามิติข้อมูลทั้งหมดสามารถแก้ไขเป็นค่าคงที่ได้ผ่าน การพับค่าคงที่ระหว่างกระบวนการ
  • ฟังก์ชันระดับกลางอาจใช้อาร์กิวเมนต์โทเค็นจำนวนหนึ่ง (ประเภท !stablehlo.token) ที่จุดเริ่มต้นของรายการอาร์กิวเมนต์ ตามด้วยอาร์กิวเมนต์ค่าคงที่ส่วนกลางบางรายการซึ่งเป็นสเกลาร์จำนวนเต็มคงที่ เช่น ค่าที่แก้ไขแล้วของจำนวนเต็มเชิงสัญลักษณ์ (เช่น เทนเซอร์ : A = 5)
  • ฟังก์ชันระดับกลางบางฟังก์ชันอาจแสดงผลการคำนวณค่าคงที่ส่วนกลาง กล่าวคือ floordiv ค่า symint ฟังก์ชันเหล่านี้จะระบุโดย การคืนค่าคงที่หลังจากการปรับแต่งเท่านั้น ฟังก์ชันเหล่านี้จะอยู่ในบรรทัด
  • การเรียกฟังก์ชันเดียวทั้งหมดจะส่งผลให้มีรูปร่างอาร์กิวเมนต์เดียวกัน และจะไม่มีการเรียกฟังก์ชันแบบ เรียกซ้ำ / เรียกซ้ำร่วม

-stablehlo-wrap-in-composite

ห่อหุ้มการดำเนินการ StableHLO ที่ไม่ใช่คอมโพสิตในการดำเนินการคอมโพสิต

ห่อหุ้มการดำเนินการ StableHLO ในการดำเนินการ stablehlo.composite

เช่น ลองพิจารณาโปรแกรม StableHLO อย่างง่ายต่อไปนี้

func.func @main(%arg0 : tensor<2xf32>, %arg1 : tensor<2xf32>) -> tensor<2xf32> {
  %0 = stablehlo.add %arg0, %arg1 : tensor<2xf32>
  return %0 : tensor<2xf32>
}

การใช้บัตรนี้เพื่อสรุปการดำเนินการของ stablehlo.add จะส่งผลให้เกิดโปรแกรมต่อไปนี้

func.func @main(%arg0: tensor<2xf32>, %arg1: tensor<2xf32>) -> tensor<2xf32> {
  %0 = stablehlo.composite "stablehlo.add" %arg0, %arg1 {decomposition = @stablehlo.add.impl} : (tensor<2xf32>, tensor<2xf32>) -> tensor<2xf32>
  return %0 : tensor<2xf32>
}
func.func private @stablehlo.add.impl(%arg0: tensor<2xf32>, %arg1: tensor<2xf32>) -> tensor<2xf32> {
  %0 = stablehlo.add %arg0, %arg1 : tensor<2xf32>
  return %0 : tensor<2xf32>
}

หมายเหตุ:

  • แอตทริบิวต์ name ของการดำเนินการ stablehlo.composite ที่สร้างขึ้น จะเหมือนกับชื่อของการดำเนินการเดิมที่ ห่อหุ้มไว้เสมอ (เช่น หากคุณห่อหุ้มการดำเนินการ stablehlo.add คอมโพสิต จะมีชื่อเป็น "stablehlo.add" ด้วย)
  • ฟังก์ชันส่วนตัวที่แคปซูลการดำเนินการเดิม (อ้างอิงโดยแอตทริบิวต์ decomposition ของการดำเนินการ stablehlo.composite) จะตั้งชื่อตามรูปแบบ <op_name>.impl[.N] โดยที่ <op_name> คือชื่อของการดำเนินการเดิม และ N คือตัวระบุจำนวนเต็มที่ไม่ซ้ำกันซึ่งสร้างขึ้นเพื่อป้องกัน การตั้งชื่อที่ขัดแย้งกันภายในโมดูล

คุณใช้บัตรนี้ได้ 2 วิธีที่แตกต่างกัน ดังนี้

โหมด 1: การใช้งานบรรทัดคำสั่ง

โหมดนี้มีไว้สำหรับการแก้ไขข้อบกพร่องหรือการทดสอบ เนื่องจากมีการควบคุมแอตทริบิวต์ของstablehlo.compositeการดำเนินการที่สร้างขึ้นน้อยที่สุด โดยจะครอบคลุมอินสแตนซ์ทั้งหมดของการดำเนินการที่ระบุโดยใช้ตัวเลือก op-names (รายการชื่อการดำเนินการที่คั่นด้วยคอมมา) แอตทริบิวต์ของ การดำเนินการ stablehlo.composite ที่สร้างขึ้นใหม่จะเหมือนกับ แอตทริบิวต์ของการดำเนินการเดิม

ตัวอย่างการใช้งาน:

stablehlo-opt input.mlir --stablehlo-wrap-in-composite=op-names='stablehlo.add,stablehlo.mul' -o output.mlir

โหมดที่ 2: การรวมโมดูลทั้งโมดูลแบบเป็นโปรแกรมด้วยการจัดการแอตทริบิวต์ที่กำหนดเอง

โหมดนี้จะขยายการห่อหุ้มแบบเป็นโปรแกรมไปยังทั้งโมดูล ซึ่งจะช่วยให้คุณควบคุมได้อย่างละเอียดว่าจะห่อหุ้มการดำเนินการใดและแอตทริบิวต์ของการดำเนินการนั้น ซึ่งทำได้โดยใช้ createStablehloWrapInCompositePass API ซึ่งรับ CompositeAttributeProviderMap เป็นอาร์กิวเมนต์

CompositeAttributeProviderMap คือแผนที่ที่กำหนดการดำเนินการที่ควรพิจารณาสำหรับการห่อหุ้มและวิธีจัดการแอตทริบิวต์ โดยมีความหมายดังนี้

  • คีย์ (mlir::TypeID): TypeID ของการดำเนินการ MLIR หากการดำเนินการ TypeIDตรงกับคีย์ในแผนที่ การดำเนินการนั้นจะกลายเป็นตัวเลือกสำหรับการห่อ
  • ค่า (ฟังก์ชัน Lambda): ฟังก์ชัน Lambda ประเภท std::function<std::optional<NamedAttrList>(Operation*)> ฟังก์ชันนี้ จะใช้กับการดำเนินการที่อาจเกิดขึ้นแต่ละรายการ
    • อินพุต: mlir::Operation* ซึ่งเป็นอินสแตนซ์ของ ประเภทการดำเนินการที่สอดคล้องกับคีย์ TypeID
    • ค่าที่ส่งคืน: std::optional<NamedAttrList>
      • หาก Lambda แสดงผล NamedAttrList (อยู่ใน std::optional) ระบบจะรวมการดำเนินการไว้ในการดำเนินการ stablehlo::composite และใช้แอตทริบิวต์ที่แสดงผลเพื่อตั้งค่าแอตทริบิวต์ของคอมโพสิต
      • หาก Lambda แสดงผล std::nullopt ระบบจะไม่ ห่อหุ้มการดำเนินการ ซึ่งช่วยให้เลือกแรปตามเกณฑ์ที่กำหนดเองได้

ตัวอย่าง (C++)


stablehlo::CompositeAttributeProviderMap compositeAttributeProviderMap;

compositeAttributeProviderMap[mlir::TypeID::get<mlir::stablehlo::AddOp>()] =
  [](mlir::Operation* op) -> std::optional<mlir::NamedAttrList> {
  // Custom logic to determine if and how to wrap the operation.
  // Example: Only wrap if it's on a specific type.
  if (mlir::isa<mlir::Float32Type>(op->getOperand(0).getType())) {
    return mlir::NamedAttrList(op->getAttrs());
  }
  return std::nullopt; // Do not wrap.
};

pm.addPass(createStablehloWrapInCompositePass(compositeAttributeProviderMap, compositeVersion));
if (mlir::failed(pm.run(module))) {
  return;
}

ตัวเลือก

-op-names : The names of the ops to wrap.
-version  : The version number of the composite op.

-vhlo-legalize-to-stablehlo

แปลง VHLO เป็น StableHLO

-vhlo-to-version

แปลงระหว่างเวอร์ชันของ VHLO เพื่อความเข้ากันได้

แปลงระหว่างเวอร์ชันของ VHLO สำหรับการอัปเกรดและดาวน์เกรด IR เพื่อ รักษาความเข้ากันได้แบบย้อนหลังและไปข้างหน้า

"vhlo.exponential_v2"(%[[ARG0]]) <{result_accuracy = DEFAULT}>
# ==( -target=1.0.0 )==>
"vhlo.exponential_v1"(%[[ARG0]])
# ==( -target=1.9.0 )==>
"vhlo.exponential_v2"(%[[ARG0]]) <{result_accuracy = DEFAULT}>

ดูรายละเอียดทั้งหมดเกี่ยวกับวิธีใช้ VHLO เพื่อรักษาความเข้ากันได้แบบย้อนกลับและไปข้างหน้าได้ที่ vhlo.md > The VHLO dialect

ตัวเลือก

-target : The target version. Must be a version of the form #.#.# .