-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 получают обновления или в последних версиях появляются новые операции. Этот дополнительный проход расширяет обратную совместимость со старыми версиями 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
Легализуйте устаревшие операции, заменив их хорошо поддерживаемыми.
В RFC StableHLO v1.0 Opset Deprecations (#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) в начале списка аргументов, за которыми следуют некоторые глобальные константные аргументы, которые являются постоянными целочисленными скалярами, такими как разрешенные значения символических целых чисел (т.е. тензорные
: А = 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
— уникальный целочисленный идентификатор, созданный для предотвращения конфликтов имен внутри модуля.
Этот проход можно использовать двумя разными способами:
Режим 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: программная упаковка всего модуля с настраиваемой обработкой атрибутов
Этот режим расширяет программную переносимость на весь модуль, предлагая детальный контроль над тем, какие операции переносятся и их атрибутами. Это достигается с помощью API createStablehloWrapInCompositePass
, который принимает 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
, операция не переносится. Это позволяет выполнять выборочную переноску на основе пользовательских критериев.
- Если лямбда-выражение возвращает
- Входные данные:
Пример (С++):
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 #.#.# .