-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-compatibility-expander

توسعه دهنده سازگاری برای عملیات StableHLO.

StableHLO ops به روز رسانی می شود یا عملیات جدید در آخرین نسخه ها معرفی می شود. این مجوز انتخاب، سازگاری با نسخه‌های قدیمی‌تر 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-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

پاس برای تبدیل 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)

زیر مجموعه ای از کامپوزیت ها را می توان با استفاده از پرچم "به جز" از این تبدیل مستثنی کرد، به عنوان مثال:

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

عملیات منسوخ شده را به عملیاتی با پشتیبانی خوب قانونی کنید.

StableHLO v1.0 Opset Deprecations RFC (#2283) پیشنهاد حذف چندین عملیات اضافی را دارد. این پاس به ارزیابی تأثیر این حذف عملیات در خطوط لوله تلفیقی مختلف با قانونی کردن آنها برای همتایان پشتیبانی شده درازمدت آنها کمک می کند.

گزینه ها

-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

از عملیات کوانتیزه شده 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-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

یک op غیر ترکیبی 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>
}

اعمال این پاس برای wrap کردن عملیات 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 یک شناسه عدد صحیح منحصر به فرد است که برای جلوگیری از تداخل نام‌گذاری در ماژول ایجاد می‌شود.

این پاس را می توان به دو روش مجزا استفاده کرد:

حالت 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 یک عملیات با یک کلید در نقشه مطابقت داشته باشد، نامزدی برای بسته بندی می شود.
  • مقادیر (توابع لامبدا): تابع لامبدا از نوع std::function<std::optional<NamedAttrList>(Operation*)> . این تابع برای هر عملیات کاندید اعمال می شود.
    • ورودی: یک mlir::Operation* ، که نمونه ای از نوع عملیات مربوط به کلید TypeID است.
    • مقدار بازگشتی: یک std::optional<NamedAttrList> .
      • اگر لامبدا یک NamedAttrList برگرداند (پیچیده شده در std::optional )، عملیات در یک عملیات stablehlo::composite پیچیده می‌شود و از ویژگی‌های برگشتی برای تنظیم ویژگی‌های ترکیب استفاده می‌شود.
      • اگر لامبدا 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 (op->getOperand(0).getType().isa<mlir::Float32Type>()) {
    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.

گزینه ها

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