O principal objetivo do intérprete do StableHLO é fornecer uma referência
implementação à semântica da opset StableHLO de acordo com
especificação. A meta secundária é que a implementação acompanhe de perto
da especificação, favorecendo a legibilidade em vez do desempenho, para oferecer mais clareza
à semântica até mesmo das operações mais envolvidas, como Convolution
,
Gather
/Scatter
e DotGeneral
.
No momento, o OpenXLA suporta a interpretação de 91 de 96 especificações
Operações de StableHLO. As três operações restantes (FftOp
, RngOp
, RngBitGeneratorOp
) têm
a semântica é documentada em
spec.md e têm
concluído as investigações iniciais sobre como avançar (consulte
status.md
para uma lista completa das operações e o status mais recente delas). Os resultados
as melhorias serão implementadas conforme necessário.
Escopo
Categorizamos a opset StableHLO em 11 categorias, que consistem em 118 operações em total (consulte o Apêndice). Implementação de referência fluxo de trabalho organiza o trabalho de implementação de um intérprete para 100% das operações StableHLO, conforme definido na especificação StableHLO. Estamos planeja concluir todo ou quase todo o trabalho neste fluxo de trabalho no StableHLO v1.0 Das 96 operações que têm uma especificação atualmente, podemos interpretar 91 operações por meio OpenXLA (consulte Casos especiais para saber os cinco restantes).
Especificação
O principal requisito para o intérprete é ter uma correspondência individual com o especificação. A especificação permite padronizar o intérprete em operações semelhantes que levam à implementação modular e de alta qualidade do intérprete.
Casos especiais
Diversos
Esta categoria tem operações decombináveis com um futuro incerto no momento. Há três operações específicas nesta categoria que o intérprete não oferece suporte momento:
FftOp
RngOp
RngBitGeneratorOp
FftOp
está classificado como "Diversos", mas, ao contrário de outras operações nessa categoria,
essa operação não tem passagem de expansão, e o suporte a ela no StableHLO é
Em andamento.
RngOp
e RngBitGeneratorOp
podem ser decompostos em operações MHLO, mas
a decomposição introduz uma XlaRngGetAndUpdateStateOp
, que é uma classe MHLO específica
operação A interpretação de suporte dessas duas operações está em andamento.
A ferramenta para converter as operações restantes nessa categoria em operações StableHLO que o interpretador reside em hlo_expand_main.cc.
Não está em HLO
Além das operações especificadas, essa categoria consiste em 8 operações não especificadas (consulte categorias de operações do StableHLO), que serão movido para fora de StableHLO. A maioria dessas operações tem cartões mhlo para e convertê-los em operações equivalentes a StableHLO.
Ferramenta para converter as operações restantes nessa categoria em operações StableHLO equivalentes. que o intérprete suporta fica em mlir-hlo-opt.cc.
Quantização.
O suporte a intérpretes para a operação stablehlo.constant
com tipo quantizado é
incompatível e rastreado por
1691 (link em inglês).
Instruções de uso
Como criar o intérprete de referência
O intérprete pode ser criado e testado usando o Bazel ou o CMake (preferencial). Para total consulte README.md.
Bazel:
bazel build //...
O 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
Para executar o intérprete, temos uma ferramenta de tradução que interpreta programas StableHLO escritos em MLIR.
stablehlo-translate --interpret <path/to/program>
O dialeto do intérprete
O dialeto Interpreter
contém várias operações utilitárias relacionadas à
intérprete. Especificamente, o interpreter.run_parallel
(consulte
InterpreterOps.td
para semântica de operações e uso de exemplo), o op permite a interpretação de operações de distribuição e muito mais
os concessionárias de serviços públicos planejam ser adicionados com base nas necessidades da comunidade.
O dialeto de verificação
O dialeto Check
é usado para comparar os valores de ambiente de execução do interpretador com o esperado
e a distribuição dos valores dos dados. As saídas do programa StableHLO podem ser testadas com várias operações de verificação (consulte
CheckOps.td
para semântica de operações e uso de exemplo).
Como criar programas de teste
Usamos a ferramenta lit do LLVM para executar e comparar com o arquivo gerado para diferenciá-lo da saída do intérprete. Consulte stablehlo/tests/interpret como testes).
Testando AddOp
(amostra de
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
}
As operações de teste na categoria "Distribuição" exigem a execução delas por meio do
Operação utilitária interpreter.run_parallel
Testando AllReduceOp
(amostra de
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
}
}
Como depurar StableHLO
Seguindo as etapas de build do StableHLO, os binários do StableHLO para ferramentas
stablehlo/tools
precisa residir em /build/bin
. Ferramentas de depuração comuns, como
O GDB pode ser usado para percorrer o código:
gdb --args ./build/bin/stablehlo-translate -allow-unregistered-dialect --interpret ./stablehlo/tests/interpret/<test>.mlir
Apêndice
Converter operações diversas
# 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>
Converter que não está em operações HLO
# broadcast
mlir-hlo-opt -mhlo-legalize-broadcast-to-broadcast-in-dim <path/to/input>
# create_token
mlir-hlo-opt -mhlo-legalize-create-token-to-after-all <path/to/input>
# cross-replica-sum
mlir-hlo-opt -mhlo-legalize-cross-replica-sum-to-all-reduce <path/to/input>
# 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>
Categorias de operações do StableHLO
Categorias | Mnemônicos | Total |
---|---|---|
119 | ||
Fluxo de controle | after_all, case, if, otimização_barrier, enquanto | 5 |
Movimentação de dados. | broadcast_in_dim, concatenar, dynamic_slice, dynamic_update_slice, reunir, preencher, remodelar, reverter, dispersão, fatiar, ordenar, transpor | 12 |
Distribuição | all_gather, all_reduce, all_to_all, collective_permute, infeed, outfeed, particiona_id, recv, Reduce_scatter, replica_id, enviar | 11 |
Dinamismo | dynamic_broadcast_in_dim, dynamic_conv, dynamic_gather, dynamic_iota, dynamic_pad, dynamic_reshape, get_dimension_size, real_dynamic_slice, set_dimension_size | 9 |
Elementwise | abs, e, e, e, e, atan2, | 48 |
Extensibilidade | custom_call, get_TPU_element, tupla | 3 |
Diversos | batch_norm_grad, batch_norm_inference, batch_norm_training, cholesky, constante, fft, iota, rng, rng_bit_generator, triangular_solve | 10 |
Modularidade | chamar, função, módulo, retorno | 4 |
Fora do HLO | broadcast, create_token, cross-replica-sum, ponto, einsum, torch_index_select, unary_einsum | 8 |
Quantização. | uniform_dequantize, uniform_quantize | 2 |
Redução | convvolução, ponto_geral, reduzir, reduzir_janela, select_and_scatter | 5 |