Compatibilidade com StableHLO

O StableHLO é uma opset de computação de ML compatível com versões anteriores inspirada em HLO/MHLO. Este documento explica o tipo e a extensão das garantias de compatibilidade que o StableHLO fornece, com base no processo estabelecido no RFC de compatibilidade.

Versions

A versão atual do StableHLO pode ser encontrada em Version.h.

Na série 0.x.x, a versão secundária é tocada sempre que ocorrem mudanças na opset StableHLO ou no formato de serialização StableHLO, e a versão de patch é enviada sempre que integramos o StableHLO downstream, ou seja, no repositório openxla/xla.

Garantias

Seis meses de compatibilidade com versões anteriores:artefatos portáteis serializados por uma versão antiga da libStablehlo têm a mesma semântica* quando são desserializados por uma nova versão do libStablehlo, se essas versões são criadas com base em confirmações de openxla/stablehlo com menos de seis meses de diferença.

Um mês de compatibilidade com versões futuras:artefatos portáteis serializados por uma nova versão da libStablehlo têm a mesma semântica* quando desserializados por uma versão antiga do libStablehlo. Isso ocorre quando essas versões são criadas com base em confirmações openxla/stablehlo com menos de um mês de intervalo, a menos que o programa esteja usando novos recursos introduzidos desde a versão antiga.

* Os programas StableHLO são convertidos de/para artefatos portáteis por meio de APIs de compatibilidade, e a semântica desses programas é definida pela especificação do StableHLO. Consulte a seção "Fora do escopo" para conferir exemplos do que não é abordado por essa definição de compatibilidade.

APIs

Artefatos portáteis podem ser criados usando a ferramenta stablehlo-translate ou diretamente nas APIs C++ ou Python. A serialização precisa de uma versão de destino do StableHLO para gravar um artefato escrito no formato #.#.#. Consulte Version.h para ver a versão atual. A desserialização usa a versão atual do StableHLO para ler um artefato.

stablehlo-translate

Essa é a maneira mais fácil de criar e ler um artefato portátil.

# Write a StableHLO program to a portable artifact
$ stablehlo-translate --serialize file.mlir --target=0.9.0 > portable_artifact.mlir.bc

# Read StableHLO portable artifact
$ stablehlo-translate --deserialize portable_artifact.mlir.bc

C++

Para fluxos de trabalho programáticos, o StableHLO fornece as seguintes APIs de compatibilidade:

// From: #include "stablehlo/api/PortableApi.h"

// Get the current StableHLO version.
//
// This value can be used as the `targetVersion` argument to
// `serializePortableArtifact`.
std::string getCurrentVersion();

// Get the minimum supported StableHLO version.
//
// This value can be used as the `targetVersion` argument to
// `serializePortableArtifact`.
std::string getMinimumVersion();

// From: #include "stablehlo/dialect/Serialization.h"

// Write a StableHLO program to a portable artifact
// Writes a stable payload for `module` to `os`. If compatibility with a
// previous version of StableHLO is required, provide the required version
// string `#.#.#` for `targetVersion`.
//
// Can fail if `module` cannot be expressed in the `targetVersion` version of
// StableHLO, e.g. if it's using new or removed features, or if it involves
// unsupported dialects.
LogicalResult serializePortableArtifact(ModuleOp module,
                                        StringRef targetVersion,
                                        raw_ostream& os);

// Read StableHLO portable artifact
//
// Can fail if `sourceStr` cannot be expressed in the current version of
// StableHLO, e.g. if it's using incompatible features. Returns nullptr if
// `sourceStr` is invalid or fails to deserialize.
OwningOpRef<ModuleOp> deserializePortableArtifact(StringRef sourceStr,
                                                  MLIRContext* context);

Consulte stablehlo/api/PortableApi.h e stablehlo/dialect/Serialization.h para ver as APIs completas.

Consulte StablehloTranslateMain.cpp para ver um exemplo de uso dessas APIs.

Python

O StableHLO também fornece vinculações Python para as APIs de compatibilidade de C++:

def get_current_version() -> str: ...
def get_minimum_version() -> str: ...
def serialize_portable_artifact(module: ir.Module, target_version: str) -> bytes: ...
def serialize_portable_artifact(module: str, target_version: str) -> bytes: ...
def deserialize_portable_artifact(context: ir.Context, artifact: bytes) -> ir.Module: ...
def deserialize_portable_artifact(artifact: bytes) -> str: ...

Consulte StablehloModule.cpp para ver as APIs completas do Python.

Consulte stablehlo.py > test_serialization_apis para ver exemplos de ida e volta de como usar as APIs de serialização do Python.

Testes

Temos um pacote de compatibilidade em stablehlo/tests que envolve um compêndio abrangente de operações do StableHLO serializadas para todas as versões compatíveis do StableHLO. Para cada solicitação de envio, estamos testando a compatibilidade com versões anteriores e posteriores, ou seja, que o pacote pode ser desserializado no HEAD (compatibilidade com versões anteriores), se o compêndio pode ser serializado para todas as versões de StableHLO compatíveis e se os resultados são sintaticamente idênticos aos programas StableHLO originais.

Trabalho futuro

Criar um pacote de compatibilidade no upstream MLIR:usando os aprendizados de estabelecimento e manutenção de garantias de StableHLO, planejamos contribuir com um pacote de compatibilidade para o upstream MLIR para fornecer detecção antecipada de falhas de compatibilidade acidentais na infraestrutura de bytecode MLIR (#1632).

Usar implementação de referência: no momento, o teste de compatibilidade consiste em desserializar o pacote de compatibilidade serializado por versões mais antigas da libStablehlo e garantir que a desserialização produz programas sintaticamente idênticos. Planejamos usar também uma implementação de referência nesses testes, relaxando o requisito excessivamente oneroso de identidade sintática e testando de forma abrangente a implementação de referência (#1245).

Fora do escopo

Artefatos não portáteis:as garantias de compatibilidade são fornecidas apenas para artefatos portáteis criados de forma muito específica. Outros tipos de artefatos, como representação estilizada do dialeto StableHLO ou até mesmo representação de bytecode do dialeto StableHLO, não têm garantias de compatibilidade.

Recursos não especificados: podemos fazer alterações incompatíveis em recursos que têm suporte histórico nos programas StableHLO, mas que ainda não fazem parte da especificação StableHLO. Por exemplo, não fornecemos garantias de compatibilidade para atributos não registrados.

Compatibilidade com bugs:podemos fazer mudanças incompatíveis se a implementação no libStablehlo contradiz a especificação do StableHLO. Por exemplo, se uma definição no dialeto VHLO estiver incorreta ou se um verificador no dialeto StableHLO não corresponder à especificação.

Precisão numérica:o StableHLO tem várias operações com precisão definida pela implementação nos consumidores e até mesmo no mesmo consumidor em todas as versões. Como resultado, o StableHLO não tem como objetivo oferecer garantias sobre precisão numérica, embora isso possa mudar no futuro (#1156).

A compatibilidade de origem (link em inglês) com as APIs C, C++ e Python no libStablehlo é um objetivo ambicioso. No momento, não oferecemos garantias de compatibilidade com a fonte, mas avise se esse for um caso de uso importante para você e podemos conversar sobre como oferecer suporte (#1247).