-chlo-legalize-to-stablehlo

CHLO operasyon akışından StableHLO ve Shape operasyonlarına geçişi yasallaştırır

-shape-legalize-to-stablehlo

Şekille ilgili işlemleri StableHLO'ya aktarma

Şekille ilgili işlemleri StableHLO işlemlerine yasallaştıran deneysel bir geçiş.

İsteğe bağlı bir geçişle şekil ve veri hesaplamalarını bir araya getirmek, StableHLO ekosisteminin dinamizmi modellemek için StableHLO işlemlerini kullanan derleme işlem hatlarından yararlanmasını sağlayabilir.

-stablehlo-canonicalize-dynamism

Dinamik StableHLO işlemlerini statik işlemlere dönüştürür.

Bu işlemlerin tüm dinamik öğeleri aslında sabitlerse DynamicReshapeOp gibi dinamik StableHLO işlemlerini DynamicReshapeOp ile ReshapeOp veya DynamicBroadcastInDim ile BroadcastInDim gibi karşılık gelen statik işlemlerle değiştirir.

  %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 özel çağrılarını doğrulayın.

Şekil onayları, StableHLO'daki dinamik boyutlarla ilgili kısıtlamaları doğrular. Örneğin, bir çerçevenin DimA < 2 kısıtlamasını zorunlu kılması gerekiyorsa aşağıdaki IR yayınlanabilir:

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

Geçişten sonra şekiller doğruysa stablehlo.custom_call kaldırılır.

Seçenekler

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

-stablehlo-compatibility-expander

StableHLO işlemleri için uyumluluk genişletici.

StableHLO işlemleri, en son sürümlerde güncellenir veya yeni işlemler kullanıma sunulur. Bu etkinleştirme seçeneği, yeni StableHLO işlemlerini eski sürümler tarafından desteklenen eşdeğer işlemlere ayırarak eski StableHLO sürümleriyle geriye dönük uyumluluğu genişletir.

Bu kart neden isteğe bağlı olarak etkinleştiriliyor?

Zaman zaman, StableHLO işlem optimizasyonları, OpenXLA ekosistemindeki belirli yaygın kalıpların işlenmesini büyük ölçüde basitleştirmek için kullanılır. Bu, yüksek çerçeve ve derleyici desteğine sahip TanOp'un yanı sıra dilimler kullanılarak gösterilebilen ancak parçalama işlemini çok daha zor hale getiren toplama/dağıtma toplu işleme boyutlarını içerir. Bu yeni özellik kategorisinde, sonraki optimizasyonlarda kullanılan önemli bilgileri silebileceği için otomatik olarak önceki sürüme geçme seçeneği sunmuyoruz. Bu geçiş, hedef sürüme göre bu işlemleri genişletmek için kullanılabilir. Böylece, derleme işlemi daha az optimal olabilir ancak uyumluluk en üst düzeye çıkarılır.

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

Seçenekler

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

-stablehlo-complex-math-expander

StableHLO karmaşık matematik işlemleri için genişletici.

StableHLO karmaşık matematik işlemleri, StableHLO gerçek matematik işlemleri kullanılarak yapılan ayrıştırmalardır.

Bu ifade, karmaşık sayıları veya karmaşık matematik işlemlerini yerel olarak destekleyen bir donanım olmadığı varsayımına dayanmaktadır. Bu nedenle, derleyicilerin uygulayabileceği karmaşık matematik işlemleriyle ilgili yedek mekanizmalar gereksizdir. Bu geçiş etkinleştirildiğinde tüm StableHLO karmaşık matematik işlemleri genişletilir.

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'yi işaretsiz tam sayılara dönüştürmek için iletilir.

-stablehlo-legalize-composite-to-call

Birleşik işlemleri, ayrıştırmalarına yapılan bir çağrıyla değiştirir.

Birleşik işlemleri, ayrıştırılmış hallerine yapılan çağrılarla değiştirir. Örneğin:

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

Şu hale gelir:

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

Birleşiklerin bir alt kümesi, "except" işareti kullanılarak bu dönüşümün dışında tutulabilir. Örneğin:

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

Seçenekler

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

-stablehlo-legalize-deprecated-ops

Kullanımdan kaldırılan işlemleri iyi desteklenen işlemlere dönüştürün.

StableHLO v1.0 Opset Deprecations RFC (#2283), birkaç gereksiz işlemin kaldırılmasını öneriyor. Bu geçiş, uzun vadeli desteklenen karşılıklarını yasal hale getirerek bu optimizasyon kaldırmalarının çeşitli derleme işlem hatlarındaki etkisini değerlendirmeye yardımcı olur.

Seçenekler

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

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

Fuse (de-quantize, floating-point operation and quantize) pattern into StableHLO quantized operation

Fuse (de-quantize, floating-point operation and quantize) pattern into StableHLO quantized operation Not: The pass does not delete any preexisting op. For example, the following program

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

Şu hale gelir:

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 nicelendirilmiş işlemleri StableHLO temel matematik işlemlerine dönüştürün.

UniformQuantized türlerini kullanan StableHLO programlarını semantik olarak eşdeğer tamsayı matematik işlemlerine dönüştürün.

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

Şu hale gelir:

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

Kuantize edilmiş StableHLO işlemini (de-quantize, kayan nokta işlemi ve quantize) desenine ayırın.

Tek tip nicelendirme/nicelendirme kaldırma işlemleri kullanarak StableHLO nicelendirilmiş programlarını ayrıştırın. Örneğin, aşağıdaki program

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

Şu hale gelir:

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'yu VHLO'ya dönüştürme

StableHLO'yu VHLO'daki en son işlem sürümüne yasal hale getirin. Bu işlemler daha sonra VhloToVersionPass kullanılarak ileriye dönük uyumluluk için VHLO'nun eski sürümlerine indirilebilir.

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

VHLO'nun ileri ve geri uyumluluğu korumak için nasıl kullanıldığıyla ilgili tüm ayrıntılar için vhlo.md > The VHLO dialect (vhlo.md > VHLO lehçesi) bölümüne bakın.

Seçenekler

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

-stablehlo-refine-arguments

Ana işlevin bağımsız değişken şekillerini iyileştirir.

Giriş türü imzasını kullanarak ana işlevin bağımsız değişkenlerini değiştirir. Şekil iyileştirme çalıştırılmadan önce IR'nin geçerli kalması için bağımsız değişkenleri custom_call @stablehlo.shape_refinement_operand_wrapper içine alır.

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, ayrıntılı türlerin listesini belirtmek için kullanılabilir. Bu, MLIR'de --types='tensor<...>,tensor<...>' ile belirtilebilir veya kart oluşturma yöntemine iletilebilir. İyileştirme türü listesi, iyileştirilen main yöntemine yönelik her bağımsız değişkenin türünü belirtmelidir.

Seçenekler

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

-stablehlo-refine-shapes

StableHLO programındaki şekilleri iyileştirir.

İşlemlerdeki şekilleri hassaslaştıran bir StableHLO programını adım adım açıklar.

Bu kartın temel kullanım alanı, dinamik olarak şekillendirilmiş programları statik şekillere özelleştirmektir. Dinamik olarak şekillendirilmiş bir StableHLO programı doğru yapıya sahipse bağımsız değişken türlerini dinamik şekillerden statik şekillere güncellemek ve bu geçişi çalıştırmak, statik şekilleri program genelinde yayar.

Bu geçiş, sonucu doğrudan işlenenle değiştirerek custom_call @shape_refinement_operand_wrapper öğesini kaldırır ve statik şekilleri program boyunca yayar.

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

Şekil iyileştirme için geçerli olan modüller aşağıdaki özelliklere sahip olmalıdır:

  • Tüm dinamik şekiller yalnızca giriş şekillerine bağlıdır (giriş dizisi içeriğine bağlı şekil yoktur). Yalnızca giriş şekillerine (ör. stablehlo.get_dimension_size tarafından verilen) veya sembolik tam sayıların çözümlenmiş değerleri (ör. tensor : A = 5) gibi genel sabitlere geçişli olarak bağlı olan işlemlere dimension işlemleri diyoruz. Tüm boyut değerleri, yordamlar arası sabit katlama yoluyla sabitlere dönüştürülebilir.
  • Ara işlevler, bağımsız değişken listesinin başında bir dizi jeton bağımsız değişkeni (!stablehlo.token türünde) alabilir.Ardından, sembolik tam sayıların çözümlenmiş değerleri (ör. tensor : A = 5) gibi sabit tam sayı skalerleri olan bazı genel sabit bağımsız değişkenler gelebilir.
  • Bazı ara işlevler, genel sabitler üzerinde hesaplamalar döndürebilir. Örneğin, floordiv semint değerleri üzerinde. Bu işlevler, yalnızca iyileştirme işleminden sonra sabit değerler döndürerek belirtilir. Bu işlevler satır içi olarak eklenir.
  • Tek bir işlev için yapılan tüm çağrılar aynı bağımsız değişken şekillerine çözümlenir ve yinelemeli / birlikte yinelemeli işlev çağrıları yapılmaz.

-stablehlo-wrap-in-composite

Bileşik olmayan bir StableHLO işlemini bileşik bir işlemle sarmalar.

StableHLO işlemlerini stablehlo.composite işlemleriyle sarmalar.

Örneğin, basit bir StableHLO programını ele alalım:

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

Bu geçişi stablehlo.add işlemleri için uyguladığınızda aşağıdaki program elde edilir:

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

Notlar:

  • Oluşturulan stablehlo.composite işleminin name özelliği, her zaman sarmalanan orijinal işlemin adıyla aynı olur (ör. bir stablehlo.add işlemini sarmalarsanız bileşik işlem de "stablehlo.add" olarak adlandırılır).
  • Orijinal işlemi kapsayan özel işlev (stablehlo.composite işleminin decomposition özelliği tarafından referans verilir) <op_name>.impl[.N] kalıbı kullanılarak adlandırılır. Burada <op_name>, orijinal işlemin adıdır ve N, modül içinde adlandırma çakışmalarını önlemek için oluşturulan benzersiz bir tam sayı tanımlayıcıdır.

Bu kart iki farklı şekilde kullanılabilir:

1. Mod: Komut satırı kullanımı

Bu mod, oluşturulan stablehlo.composite işlemlerinin özellikleri üzerinde minimum kontrol sunduğu için hata ayıklama veya test amaçlıdır. op-names (işlem adlarının virgülle ayrılmış listesi) seçenekleri kullanılarak belirtilen işlemlerin tüm örneklerini kapsar. Yeni oluşturulan stablehlo.composite işleminin özellikleri, orijinal işlemin özellikleriyle aynı olur.

Kullanım örneği:

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

2. Mod: Özelleştirilmiş özellik işleme ile programatik modül genelinde sarmalama

Bu mod, programatik sarmalama özelliğini modülün tamamına genişleterek hangi işlemlerin sarmalanacağı ve bunların özellikleri üzerinde ayrıntılı kontrol sağlar. Bu işlem, createStablehloWrapInCompositePass API'si kullanılarak gerçekleştirilir. Bu API, bağımsız değişken olarak CompositeAttributeProviderMap alır.

CompositeAttributeProviderMap, hangi işlemlerin sarmalama için dikkate alınması gerektiğini ve özelliklerinin nasıl işlenmesi gerektiğini belirleyen bir haritadır. Anlamı şöyledir:

  • Anahtarlar (mlir::TypeID): Bir MLIR işleminin TypeID. Bir işlemin TypeID haritadaki bir anahtarla eşleşirse bu işlem sarmalama için aday olur.
  • Değerler (Lambda İşlevleri): std::function<std::optional<NamedAttrList>(Operation*)> türünde Lambda işlevi. Bu işlev, her aday işlem için uygulanır.
    • Giriş: TypeID tuşuna karşılık gelen işlem türünün bir örneği olan mlir::Operation*.
    • Döndürülen Değer: Bir std::optional<NamedAttrList>.
      • Lambda NamedAttrList (std::optional içine sarılmış) döndürürse işlem stablehlo::composite işlemine sarılır ve döndürülen özellikler, bileşiğin özelliklerini ayarlamak için kullanılır.
      • Lambda std::nullopt değerini döndürürse işlem sarmalanmaz. Bu, özel ölçütlere göre seçici sarmalama yapılmasını sağlar.

Örnek (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;
}

Seçenekler

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

-vhlo-legalize-to-stablehlo

VHLO'yu StableHLO'ya dönüştürme

-vhlo-to-version

Uyumluluk için VHLO sürümleri arasında dönüştürme yapın.

İleriye ve geriye dönük uyumluluğu korumak için IR yükseltme ve düşürme işlemlerinde VHLO sürümleri arasında dönüştürme yapar.

"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'nun ileri ve geri uyumluluğu korumak için nasıl kullanıldığıyla ilgili tüm ayrıntılar için vhlo.md > The VHLO dialect (vhlo.md > VHLO lehçesi) bölümüne bakın.

Seçenekler

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