Основная цель интерпретатора StableHLO — предоставить эталонную реализацию семантики опсета StableHLO в соответствии с его спецификацией. Вторичная цель — чтобы реализация точно следовала спецификации, отдавая предпочтение читаемости над производительностью, чтобы обеспечить дополнительную ясность семантике даже самых сложных операций, таких как Convolution
, Gather
/ Scatter
и DotGeneral
.
На данный момент OpenXLA поддерживает интерпретацию 91 из 96 предусмотренных операций StableHLO. Семантика остальных трех операций ( FftOp
, RngOp
, RngBitGeneratorOp
) задокументирована в spec.md и завершены первоначальные исследования о том, как двигаться дальше (полный список операций и их последний статус см. в status.md ). Эти окончательные улучшения будут реализованы по мере необходимости сообщества.
Объем
Мы разделили опсет StableHLO на 11 категорий, состоящих в общей сложности из 118 операций (см. Приложение ). Рабочий поток справочной реализации организует работу по реализации интерпретатора для 100 % операций StableHLO, как определено в спецификации StableHLO. Мы планируем завершить всю или почти всю работу в этом рабочем направлении в StableHLO v1.0. Из 96 операций, которые в настоящее время имеют спецификацию, мы можем интерпретировать 91 операцию через OpenXLA (остальные 5 см. в разделе «Особые случаи »).
Спецификация
Основное требование к интерпретатору — соответствие 1:1 спецификации. Спецификация позволяет стандартизировать интерпретатор для аналогичных операций, что приводит к модульной, высококачественной реализации интерпретатора.
Особые случаи
Разнообразный
В этой категории есть разлагаемые операции, будущее которых на данный момент неясно. В этой категории есть три специальные операции, которые интерпретатор на данный момент не поддерживает:
-
FftOp
-
RngOp
-
RngBitGeneratorOp
FftOp
относится к категории «Разное», но в отличие от других операций в этой категории, эта операция не имеет прохода расширения, и поддержка этого в StableHLO — это незавершенная работа.
RngOp
и RngBitGeneratorOp
можно разложить на операции MHLO, но при декомпозиции вводится XlaRngGetAndUpdateStateOp
, который является операцией, специфичной для MHLO. Поддерживающая интерпретация этих двух операций является незавершенной работой.
Инструмент для преобразования оставшихся операций в этой категории в операции StableHLO, поддерживаемые интерпретатором, находится в hlo_expand_main.cc .
Нет в ХЛО
Помимо специфицированных операций, эта категория состоит из 8 неспециализированных операций (см. Категории операций StableHLO ), которые планируется вывести из StableHLO. У большинства этих операций уже есть проходы в mhlo для преобразования их в эквивалентные операции StableHLO.
Инструмент для преобразования оставшихся операций в этой категории в эквивалентные операции StableHLO, поддерживаемые интерпретатором, находится в mlir-hlo-opt.cc .
Квантование
Поддержка интерпретатора для операции stablehlo.constant
с квантованным типом не поддерживается и отслеживается через #1691 .
Инструкции по использованию
Создание эталонного интерпретатора
Интерпретатор можно собрать и протестировать с помощью Bazel или CMake (предпочтительно). Полные инструкции см. в README.md .
Базель:
bazel build //...
CMake:
mkdir -p build && cd build
cmake .. -GNinja \
-DLLVM_ENABLE_LLD="$LLVM_ENABLE_LLD" \
-DCMAKE_BUILD_TYPE=Release \
-DLLVM_ENABLE_ASSERTIONS=On \
-DMLIR_DIR=${PWD}/../llvm-build/lib/cmake/mlir
Для запуска интерпретатора у нас есть инструмент перевода для интерпретации программ StableHLO, написанных на MLIR.
stablehlo-translate --interpret <path/to/program>
Диалект переводчика
Диалект Interpreter
содержит различные служебные операции, связанные с интерпретатором. В частности, оператор interpreter.run_parallel
(семантику операций и примеры использования см. в InterpreterOps.td ) позволяет интерпретировать операции распространения, а также планирует добавить дополнительные утилиты в зависимости от потребностей сообщества.
Чек-диалект
Диалект Check
используется для сравнения значений времени выполнения интерпретатора с ожидаемыми значениями. Выходные данные программы StableHLO можно протестировать с помощью различных операций проверки (семантику операций и примеры использования см. в CheckOps.td ).
Написание тестовых программ
Мы используем инструмент LLVM Lit для запуска и сравнения сгенерированного файла, чтобы сравнить его с выводом интерпретатора (примеры тестов см. в стабильном файле/tests/interpret ).
Тестирование AddOp
(пример из Interpret_add.mlir ):
// RUN: stablehlo-translate --interpret %s
func.func @add_op_scalar() {
%0 = stablehlo.constant dense<2> : tensor<i4>
%1 = stablehlo.constant dense<3> : tensor<i4>
%2 = stablehlo.add %0, %1 : tensor<i4>
check.expect_eq_const %2, dense<5> : tensor<i4>
func.return
}
Операции тестирования в категории «Распространение» требуют запуска их с помощью утилиты interpreter.run_parallel
op.
Тестирование AllReduceOp
(пример из all_reduce.mlir ):
// RUN: stablehlo-translate --interpret %s
module @cross_replica {
func.func public @all_reduce(%operand : tensor<4xi64>) -> tensor<4xi64> {
%result = "stablehlo.all_reduce"(%operand) ({
^bb0(%arg0: tensor<i64>, %arg1: tensor<i64>):
%0 = stablehlo.add %arg0, %arg1 : tensor<i64>
stablehlo.return %0 : tensor<i64>
}) {
replica_groups = dense<[[0, 1]]> : tensor<1x2xi64>,
channel_handle = #stablehlo.channel_handle<handle = 0, type = 0>
} : (tensor<4xi64>) -> tensor<4xi64>
return %result : tensor<4xi64>
}
func.func public @main() {
%inputs0 = stablehlo.constant dense<[1, 2, 3, 4]> : tensor<4xi64>
%inputs1 = stablehlo.constant dense<[5, 6, 7, 8]> : tensor<4xi64>
%results:2 = "interpreter.run_parallel"(%inputs0, %inputs1) {
programs=[[@all_reduce], [@all_reduce]]
} : (tensor<4xi64>, tensor<4xi64>) -> (tensor<4xi64>, tensor<4xi64>)
check.expect_eq_const %results#0, dense<[6, 8, 10, 12]> : tensor<4xi64>
check.expect_eq_const %results#1, dense<[6, 8, 10, 12]> : tensor<4xi64>
func.return
}
}
Отладка StableHLO
После выполнения шагов сборки StableHLO двоичные файлы StableHLO для инструментов из stablehlo/tools
должны находиться в /build/bin
. Для пошагового выполнения кода можно использовать общие инструменты отладки, такие как GDB:
gdb --args ./build/bin/stablehlo-translate -allow-unregistered-dialect --interpret ./stablehlo/tests/interpret/<test>.mlir
Приложение
Преобразование различных операций
# batch_norm_grad
hlo-expand --batch_norm_grad_expander <path/to/hlo_module>
# batch_norm_inference
hlo-expand --batch_norm_inference_expander <path/to/hlo_module>
# batch_norm_training
hlo-expand --batch_norm_training_expander <path/to/hlo_module>
# cholesky
hlo-expand --cholesky_expander <path/to/hlo_module>
# constant
# Supported in StableHLO interpreter.
# fft
# TBD
# iota
# Supported in StableHLO interpreter.
# rng
# TBD
# rng_bit_generator
# TBD
# triangular_solve
hlo-expand --triangular_solve_expander <path/to/hlo_module>
Преобразование не в операциях HLO
# dot
mlir-hlo-opt -mhlo-legalize-dot-to-dot-general <path/to/input>
# einsum
mlir-hlo-opt -mhlo-legalize-einsum-to-dot-general <path/to/input>
# torch_index_select
mlir-hlo-opt -mhlo-legalize-torch-index-select-to-gather <path/to/input>
# unary_einsum
mlir-hlo-opt --canonicalize -mhlo-legalize-einsum-to-dot-general <path/to/input>
Категории операций StableHLO
Категории | Мнемоника | Общий |
---|---|---|
119 | ||
Поток управления | after_all, случай, если, оптимизация_барьер, в то время как | 5 |
Перемещение данных | Broadcast_in_dim, объединение, динамический_срез, динамический_обновление_срез, сбор, дополнение, изменение формы, реверс, разброс, срез, сортировка, транспонирование | 12 |
Распределение | all_gather, all_reduce, all_to_all, коллективное_пермуте, подача, выдача, идентификатор_раздела, получение, уменьшение_разброса, идентификатор_реплики, отправка | 11 |
Динамизм | динамический_broadcast_in_dim, динамический_конв, динамический_сбор, динамический_йота, динамический_пад, динамический_ресформа, get_dimension_size, реальный_динамический_срез, set_dimension_size | 9 |
Поэлементно | abs, добавить и, atan2, bitcast_convert, cbrt, ceil, зажим, сравнить, комплексный, преобразовать, косинус, count_leading_zeros, разделить, экспоненциальный, exponential_minus_one, пол, imag, is_finite, log, log_plus_one, логистический, карта, максимум, минимум, умножить, отрицать, нет или, popcnt, степень, действительное, уменьшить_точность, остаток, round_nearest_afz, round_nearest_even, rsqrt, select,shift_left,shift_right_arithmetic,shift_right_ologic, знак, синус, sqrt, вычитание, tan, tanh, xor | 48 |
Расширяемость | custom_call, get_tuple_element, кортеж | 3 |
Разнообразный | пакетная_норма_град, пакетная_норма_вывода, пакетная_норма_тренировка, холески, константа, БПФ, йота, rng, rng_bit_generator, triangular_solve | 10 |
Модульность | вызов, функция, модуль, возврат | 4 |
Не в HLO | широковещательная передача, create_token, сумма перекрестных реплик, точка, einsum, torch_index_select, unary_einsum | 8 |
Квантование | униформа_деквантизация, униформа_квантизация | 2 |
Снижение | свертка, dot_general, уменьшить, уменьшить_окно, select_and_scatter | 5 |