Compatibilidad con StableHLO

StableHLO es un conjunto de operaciones de procesamiento de AA retrocompatible inspirado en HLO/MHLO. En este documento, se explica el tipo y el alcance de las garantías de compatibilidad que proporciona StableHLO, según el proceso establecido en la RFC de compatibilidad.

Versiones

La versión actual de StableHLO se puede encontrar en Version.h.

La versión secundaria se transmite cada vez que se realizan cambios en el conjunto de operaciones StableHLO o en el formato de serialización StableHLO, y la versión del parche se transmite cada vez que integramos StableHLO en sentido descendente, es decir, en el repositorio de openxla/xla.

Garantías

Según la RFC de compatibilidad de StableHLO v1.0, la ventana de compatibilidad incluye lo siguiente:

5 años de retrocompatibilidad: los artefactos portátiles serializados por una versión anterior de libStablehlo tienen la misma semántica* cuando se deserializan mediante una versión nueva de libStablehlo si estas versiones se compilan a partir de confirmaciones de openxla/stablehlo con menos de 5 años de diferencia.

2 años de compatibilidad con versiones posteriores: Los artefactos portátiles serializados por una versión nueva de libStablehlo tienen la misma semántica* cuando se deserializan por una versión anterior de libStablehlo si estas versiones se compilan a partir de confirmaciones de openxla/stablehlo con menos de 2 años de diferencia, a menos que el programa use funciones nuevas que se agregaron desde la versión anterior.

* Los programas StableHLO se convierten en y desde artefactos portátiles a través de las APIs de compatibilidad, y la especificación de StableHLO define la semántica de estos programas. Consulta la sección "Fuera del alcance" para ver ejemplos de lo que no abarca esta definición de compatibilidad.

APIs

Los artefactos portátiles se pueden crear con la herramienta stablehlo-translate o directamente en las APIs de C++ o Python. La serialización necesita una versión de destino de StableHLO para escribir un artefacto escrito en formato #.#.# (consulta Version.h para ver la versión actual). Debido a que las versiones de parche no afectan la compatibilidad, cualquier destino con una versión de parche que no sea cero se establece en cero durante la serialización de forma predeterminada. La deserialización usa la versión actual de StableHLO para leer un artefacto.

stablehlo-translate

Esta es la forma más fácil de crear y leer un artefacto 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 los flujos de trabajo programáticos, StableHLO proporciona las siguientes APIs de compatibilidad:

// 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);

Consulta stablehlo/api/PortableApi.h y stablehlo/dialect/Serialization.h para ver las APIs completas.

Consulta StablehloTranslateMain.cpp para ver un ejemplo de uso de estas APIs.

Python

StableHLO también proporciona vinculaciones de Python a las APIs compatibles con 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: ...

Consulta StablehloModule.cpp para ver las API completas de Python.

Consulta stablehlo.py > test_serialization_apis para obtener ejemplos de ida y vuelta del uso de las APIs de serialización de Python.

Pruebas

Tenemos un paquete de compatibilidad en stablehlo/tests/vhlo que incluye un compendio integral de operaciones de StableHLO serializado para todas las versiones de StableHLO compatibles. Para cada solicitud de extracción, probaremos la compatibilidad con versiones anteriores y posteriores, es decir, que el paquete se pueda deserializar como orientado a HEAD (compatibilidad con versiones anteriores), que el compendio pueda serializarse para todas las versiones de StableHLO compatibles (compatibilidad con versiones posteriores) y que los resultados sean sintácticamente idénticos a los programas originales de StableHLO.

Trabajo futuro

Crea un paquete de compatibilidad en MLIR upstream: Con los aprendizajes obtenidos sobre cómo establecer y mantener las garantías de StableHLO, planeamos contribuir con un paquete de compatibilidad en MLIR ascendente para proporcionar detección temprana de fallas de compatibilidad accidentales en la infraestructura del código de bytes de MLIR (#1632).

Usa la implementación de referencias: Por el momento, las pruebas de compatibilidad consisten en deserializar el paquete de compatibilidad serializado por versiones anteriores de libStablehlo y asegurarse de que la deserialización produzca programas sintácticamente idénticos. También planeamos usar una implementación de referencia en estas pruebas para flexibilizar el requisito demasiado costoso de la identidad sintáctica y realizar pruebas exhaustivas de la implementación de referencias (#1245).

Fuera del alcance

Artefactos no portátiles: Las garantías de compatibilidad solo se proporcionan para artefactos portátiles creados de una forma muy específica. Otros tipos de artefactos, p.ej., la representación con formato bonito del dialecto StableHLO o incluso la representación en código de bytes del dialecto StableHLO, no tienen garantías de compatibilidad.

Funciones no especificadas: Es posible que realicemos cambios incompatibles en las funciones que históricamente se admitieron en los programas StableHLO, pero que aún no forman parte de la especificación de StableHLO. P. ej., no proporcionamos garantías de compatibilidad para atributos no registrados.

Compatibilidad con errores: Es posible que realicemos cambios incompatibles si la implementación en libStablehlo contradice la especificación StableHLO; p.ej., si una definición en el dialecto VHLO es incorrecta o si un verificador en el dialecto StableHLO no coincide con la especificación.

Precisión numérica: StableHLO tiene varias operaciones con exactitud definida por la implementación en todos los consumidores y dentro del mismo consumidor en todas las versiones. Por lo tanto, StableHLO no tiene como objetivo garantizar la exactitud numérica, aunque esto puede cambiar en el futuro (#1156).

La compatibilidad con fuentes para las APIs de C, C++ y Python dentro de libStablehlo es un objetivo ambicioso. Por el momento, no ofrecemos garantías de compatibilidad de fuente, pero avísanos si este es un caso de uso importante para ti, y podremos conversar sobre su compatibilidad (#1247).