-chlo-legalize-to-stablehlo

התאמה חוקית מתהליך הפעולות של CHLO לתהליך הפעולות של StableHLO ו-Shape ops

-shape-legalize-to-stablehlo

הפיכת פעולות שקשורות לצורה לחוקיות ב-StableHLO

שלב ניסיוני שמכשיר פעולות שקשורות לצורה לפעולות StableHLO.

שילוב של חישובי הצורה והנתונים באמצעות שלב אופציונלי יאפשר לסביבה העסקית של StableHLO לנצל את צינורות העיבוד ל-compilation שמשתמשים בפעולות של StableHLO כדי ליצור מודלים של דינמיות.

-stablehlo-aggressive-folder

קיפול פעולות של StableHLO

אפשרויות

-fold-float : Allow for potentially lossy computations using float type.

-stablehlo-aggressive-simplification

יצירת גרסה קנונית של פעולות 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-compatibility-expander

כלי להרחבת התאימות לפעולות של StableHLO

אופרטורים של StableHLO מקבלים עדכונים או אופרטורים חדשים מוצגים בגרסאות האחרונות. הכרטיס הזה מרחיב את התאימות לאחור לגרסאות ישנות יותר של StableHLO, על ידי פירוק פעולות StableHLO חדשות יותר לפעולות מקבילות שנתמכות בגרסאות הישנות האלה.

למה זה כרטיס שצריך להביע הסכמה כדי להשתמש בו?

לפעמים משתמשים בשיפורים של פעולות StableHLO כדי לפשט מאוד את הטיפול בדפוסים נפוצים מסוימים בסביבה העסקית של OpenXLA. למשל, TanOp, שיש לו תמיכה גבוהה במסגרת ובמקרמל, וכן מאפייני צבירה/פיזור של קבוצות, שאפשר לייצג באמצעות פרוסות, אבל הם מקשים מאוד על חלוקה למקטעים. בקטגוריה הזו של תכונות חדשות, אנחנו לא מציעים שדרוג לאחור אוטומטי, כי הוא עלול למחוק מידע חשוב שמשמש אותנו בשיפורים הבאים. אפשר להשתמש במעבר הזה כדי להרחיב את הפעולות האלה על סמך גרסת יעד, כדי למקסם את התאימות על חשבון הידור פחות אופטימלי.

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-convert-to-signless

העברה כדי להפוך את ה-IR למספרים שלמים ללא סימן.

-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‏ #2283 בנושא הוצאה משימוש של קבוצות פעולות (Opset) ב-StableHLO v1.0, מוצע להסיר כמה פעולות מיותרות. בעזרת המעבר הזה אפשר להעריך את ההשפעה של הסרת הפונקציות האלה בצינורות עיבוד נתונים שונים של הידור, על ידי הפיכת הפונקציות האלה לחוקיות ביחס למקבילות שלהן שנתמכות לטווח ארוך.

אפשרויות

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

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

מיזוג של דפוס (ביטול קידוד, פעולה של נקודה צפה וקידוד) לפעולה בקידוד של StableHLO

מיזוג של דפוס (ביטול קידוד, פעולה של נקודה צפה וקידוד) לפעולה בקידוד של StableHLO הערה: התהליך לא מוחק פעולות קיימות. לדוגמה, התוכנית הבאה

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

המרה מפעולות מותנות (quantized) של 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 שעברה כיווץ לתבנית (ביטול כיווץ, פעולה של נקודה צפה וקידוד).

פירוט תוכניות שקיבלו קצובת (quantized) ב-StableHLO באמצעות פעולות קצובת/ביטול קצובת (dequantize) אחידות. לדוגמה, התוכנית הבאה

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

Legalize StableHLO to VHLO

-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) או במשתנים קבועים גלובליים כמו הערכים המנוהלים של מספרים שלמים סמליים (כלומר, tensor : A = 5), כפעולות dimension. אפשר לפתור את כל ערכי המאפיינים לקבועים באמצעות קיפול קבועים בין תהליכים (inter-procedural constant folding).
  • פונקציות ביניים יכולות לקבל מספר ארגומנטים של אסימונים (מסוג ‎!stablehlo.token) בתחילת רשימת הארגומנטים, ואחריהם כמה ארגומנטים של קבועים גלובליים שהם סקלריים שלמים קבועים, כמו הערכים שהוגדרו של מספרים שלמים סמליים (כלומר, : A = 5).
  • פונקציות ביניים מסוימות עשויות להחזיר חישובים של קבועים גלובליים, כלומר floordiv על ערכים של symint. פונקציות כאלה מחזירות רק ערכים קבועים אחרי השיפור. הפונקציות האלה מוטמעות בקוד.
  • כל הקריאות לפונקציה אחת מנותבות לאותו צורת ארגומנטים, ולא מתבצעות קריאות פונקציה רפליקטיביות או רפליקטיביות-משותפות. ### -vhlo-legalize-to-stablehlo

הפיכת VHLO ל-StableHLO לצורכי רגולציה

-vhlo-to-version

המרת גרסאות של VHLO

אפשרויות

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