Was ist der VHLO-Dialekt?
Der VHLO-Dialekt (versioned StableHLO) wird für die Serialisierung und Stabilität verwendet. Sie bietet einen Snapshot des StableHLO-Dialekts zu einem bestimmten Zeitpunkt, indem einzelne Programmelemente versioniert werden.
VHLO ist ein nur zum Hinzufügen einzelner Dialekt mit versionierten Vorgängen, Typen und Attributen. Das bedeutet, dass ein Feature, das dem Dialekt einmal hinzugefügt wurde, in keiner Weise mehr geändert werden kann, die sich auf die Semantik auswirkt.
Alle Änderungen an einem Vorgang, Typ oder Attribut erfordern eine neue Version, die dem Dialekt hinzugefügt wird. Wenn beispielsweise eine hypothetische my_op
zu StableHLO in 0.9.0 hinzugefügt, aber in 0.11.0 geändert wurde, ergibt sich in VHLO Folgendes:
// This represents the StableHLO version of the op from 0.9.0 -> 0.10.0
// Both the lower and the upper bound of versions are inclusive
def VHLO_MyOpV1 : VHLO_Op<"my_op_v1", "0.9.0", "0.10.0"> {
let arguments = (ins
VHLO_AnyType:$operand
);
let results = (outs VHLO_AnyType:$result);
}
// This represents the StableHLO version of the op from 0.11.0 -> current
def VHLO_MyOpV2 : VHLO_Op<"my_op_v2", "0.11.0", "current"> {
let arguments = (ins
VHLO_AnyType:$operand,
VHLO_AnyAttr:$attr // New attribute added to StableHLO in 0.11.0
);
let results = (outs VHLO_AnyType:$result);
}
Der StableHLO-Dialekt hat nur die neueste Version des Vorgangs. Im laufenden Beispiel hätte der StableHLO-Dialekt bei v0.11.0 nur den StableHLO_MyOp
mit operand
und attr
, während VHLO jede Phase der Entwicklung des Vorgangs erfasst.
Warum ist VHLO nützlich?
Ein versionierter Dialekt ermöglicht es uns, frühere Versionen des StableHLO-Vorgangs anzusteuern. Dies schließt die Vorwärts- und Abwärtskompatibilität bei Konvertierungen zwischen Vorgängen im VHLO-Dialekt ein.
Aufwärtskompatibilität: Die Aufwärtskompatibilität wird durch eine Konvertierung in eine VHLO und ein Downgrade von Vorgängen auf eine Zielversion bereitgestellt. Wenn jeder Vorgang/Typ/Attr in einem VHLO-Programm auf die Zielversion herabgestuft werden kann, ist diese garantiert deserialisierbar und in StableHLO für einen Nutzer, der eine Version verwendet, die größer oder gleich der Zielversion ausgeführt wird, da VHLO zu diesem Zeitpunkt einen Snapshot des Vorgangs hat.
Diese Downgrade-Konvertierung schlägt fehl, wenn Vorgänge oder Funktionen verwendet werden, die in der vorherigen Version des Vorgangs nicht vorhanden waren. Das bedeutet, dass die Aufwärtskompatibilität beim Producer und nicht zur Laufzeit erkannt wird.
Abwärtskompatibilität: Die Abwärtskompatibilität wird bereitgestellt, indem VHLO-Vorgänge auf ihre neueste Version (falls erforderlich) aktualisiert und dann ein Vorgang wieder in StableHLO konvertiert wird. Alle VHLO-Programme innerhalb des Kompatibilitätsfensters können auf StableHLO aktualisiert werden. Das bedeutet, dass verschiedene Versionen von Nutzern dieselbe VHLO-Nutzlast aus einer früheren Version deserialisieren können.
Noch wichtiger ist, dass VHLO hinter der Serialisierung abstrahiert ist. Das bedeutet, dass ML-Frameworks (Produzenten) nur StableHLO-Vorgänge ansprechen müssen und Compiler-Back-Ends (Nutzer) nur die neueste Version unterstützen müssen, also den StableHLO-Vorgangssatz. Konvertierungen zu und von VHLO werden mit Maschinen durchgeführt, die im StableHLO-Repository verwaltet werden.
Versionen des MLIR-Bytecode-Formats
Zur Aufrechterhaltung der Aufwärtskompatibilität haben StableHLO-Versionen eine zugehörige MLIR-Bytecode-Format-Version. Darüber hinaus verwendet die neueste Version von StableHLO die neueste Version von MLIR Bytecode Format. Wenn die MLIR Bytecode Format-Version erhöht wird, erhöht der nächste StableHLO-Release die Nebenversion und aktualisiert Version.cpp, um die neueste MLIR-Bytecode-Format-Version zu verwenden.
Weitere Informationen zum MLIR-Bytecodeformat und zu den Gründen für seine Verwendung in StableHLO finden Sie unter bytecode.md.
Nicht kompatible Änderungen
Alle Änderungen mit Auswirkungen auf die Kompatibilität müssen den RFC-Prozess durchlaufen. Dies gilt auch für das Hinzufügen, Verwerfen oder Umbenennen eines Elements. Sobald der RFC genehmigt wurde, findest du hier einige Beitragsrichtlinien:
Erhöhen Sie die Versionsnummer in Version.h.
Erhöhen Sie vor dem Aktualisieren von VHLO-Vorgängen, Attributen, Typen oder Conversions die Nebenversionsnummer in Version.h. Alle neuen VHLO-Features würden diese erweiterte Version verwenden, z. B. nach dem Überschreiben von 0.10.0 --> 0.11.0
, würde ein neuer Vorgang in VhloOps.td Folgendes verwenden:
VHLO_Op<"abs_v2", "0.11.0", "current">
Erforderliche VHLO-Implementierung und -Conversions hinzufügen
Der genaue Code, der zum Einbinden einer neuen Funktion erforderlich ist, kann variieren, aber zum größten Teil muss Folgendes geändert werden:
- Für alle Änderungen:
- Aktualisieren Sie das Versionsprotokoll in VhloDialect.td
- Für neue Vorgänge:
- Fügen Sie den Vorgang in VhloOps.td hinzu.
- Fügen Sie in StablehloLegalizeToVhlo.cpp „StableHLO“ → VHLO-Konvertierung hinzu.
- Fügen Sie in VhloLegalizeToStablehlo.cpp VHLO → StableHLO-Konvertierung hinzu
- Für neue Versionen vorhandener Vorgänge:
- Fügen Sie den Vorgang in VhloOps.td hinzu.
- Aktualisierung von StableHLO auf VHLO-Zuordnung in MapStablehloToVhlo.h
- Konvertierung zwischen neuen und alten Vorgangsversionen in VhloToVersion.cpp hinzufügen
- Für neue Typen oder Attribute:
- Fügen Sie den Typ in VhloTypes.td oder das Attribut in VhloAttrs.td hinzu.
- Fügen Sie in StablehloLegalizeToVhlo.cpp „StableHLO“ → VHLO-Konvertierung hinzu.
- Fügen Sie in VhloLegalizeToStablehlo.cpp VHLO → StableHLO-Konvertierung hinzu
Ein aktuelles Beispiel für eine kompatibilitätsbezogene Einreichung war das Hinzufügen von zwei FP8-Typen sowie deren Implementierung in VHLO in #1379.
Einheitentests hinzufügen / aktualisieren
Der Mitwirkende einer inkompatiblen Änderung ist sowohl für positive als auch negative Einheitentests der Funktion sowie für Kompatibilitätseinheitentests verantwortlich.
Zum Testen der Kompatibilitätseinheiten muss stablehlo_legalize_to_vhlo.mlir aktualisiert werden, um sicherzustellen, dass StableHLO-Umläufe mit der neuesten Version von VHLO durchgeführt werden. Außerdem werden alle erforderlichen zusätzlichen Vorwärts- und Abwärtskompatibilitätstests durchgeführt.
Einige Beispiele:
- Abwärtskompatibilität, positive Tests: vhlo_to_version_upgrade.mlir
- Aufwärtskompatibilität, positive Tests: vhlo_to_version_downgrade.mlir
- Aufwärtskompatibilität, negative Tests: vhlo_to_version_downgrade_invalid.0_9_0.mlir
Versionierten Serialisierungstest hinzufügen
Nachdem Sie stablehlo_legalize_to_vhlo.mlir
einen Testpunkt hinzugefügt haben, erstellen Sie eine versionierte Kopie der Datei mit dem Namen stablehlo_legalize_to_vhlo.0_X_0.mlir
wie folgt und eine Bytecode-Version dieser Datei mit der Erweiterung .0_X_0.mlir.bc
. Fügen Sie geeignete FileCheck-Zeilen für Tests zur Aufwärts- und Abwärtskompatibilität hinzu.
$ export TARGET_VERSION=0.X.0
$ export TARGET_FILENAME=${TARGET_VERSION//./_}
$ cp stablehlo/tests/stablehlo_legalize_to_vhlo.mlir stablehlo/tests/stablehlo_legalize_to_vhlo.$TARGET_FILENAME.mlir
$ build/bin/stablehlo-translate --serialize --target=$TARGET_VERSION --strip-debuginfo stablehlo/tests/stablehlo_legalize_to_vhlo.$TARGET_FILENAME.mlir > stablehlo/tests/stablehlo_legalize_to_vhlo.$TARGET_FILENAME.mlir.bc
# Replace RUN commands in stablehlo/tests/stablehlo_legalize_to_vhlo.0_X_0.mlir with the following for 0.X.0:
// RUN: stablehlo-opt --mlir-print-op-generic %s.bc | FileCheck %s
// RUN: stablehlo-translate --deserialize %s.bc | stablehlo-translate --serialize --target=0.X.0 | stablehlo-opt --mlir-print-op-generic | FileCheck %s
// RUN: diff <(stablehlo-translate --deserialize %s.bc | stablehlo-opt) <(stablehlo-opt --strip-debuginfo %s)
// RUN: diff %s.bc <(stablehlo-translate --serialize --target=0.X.0 --strip-debuginfo %s)
Beispiel für einen versionierten Test in #1430.