StableHLO to zgodna wstecznie operacja obliczeniowa ML inspirowana HLO/MHLO. W tym dokumencie opisujemy rodzaje i zakres gwarancji zgodności zapewnianych przez StableHLO na podstawie procesu opisanego w specyfikacji zgodności.
Wersje
Aktualną wersję StableHLO znajdziesz w Version.h.
Wersja podrzędna jest napotykana przy każdej zmianie w ustawieniu StableHLO lub formacie serializacji StableHLO, a wersja poprawki jest ponawiana za każdym razem, gdy integrujemy StableHLO w dół strumienia, tj. do repozytorium openxla/xla.
Gwarancje
Według specyfikacji StableHLO w wersji 1.0 okno zgodności zawiera te elementy:
5 lat zgodności wstecznej: przenośne artefakty zserializowane przez starszą wersję biblioteki libStablehlo mają tę samą semantykę* po deserializacji za pomocą nowej wersji biblioteki libStablehlo, pod warunkiem, że te wersje zostały utworzone na podstawie zgłoszeń openxla/stablehlo, które są tworzone w odstępach krótszych niż 5 lat.
Zgodność wsteczna o 2 lata: przenośne artefakty zserializowane przez nową wersję libStablehlo mają tę samą semantykę* po deserializacji za pomocą starej wersji libStablehlo, pod warunkiem że wersje te zostały utworzone na podstawie zgłoszeń openxla/stablehlo, w odstępach mniej niż 2 lat, chyba że program korzysta z nowych funkcji wprowadzonych od poprzedniej wersji.
* Programy StableHLO są konwertowane na przenośne artefakty za pomocą interfejsów API zgodności. Semantyka tych programów jest określona w specyfikacji StableHLO. Więcej przykładów znajdziesz w sekcji „Poza zakresem”.
Interfejsy API
Przenośne artefakty można tworzyć za pomocą narzędzia stablehlo-translate
albo bezpośrednio w interfejsach API C++ lub Pythona. Serializacja wymaga docelowej wersji StableHLO do zapisania artefaktu napisanego w formacie #.#.#
(bieżącą wersję znajdziesz w sekcji Version.h). Wersje poprawek nie mają wpływu na zgodność, dlatego podczas serializacji każdy cel z inną wersją poprawki jest domyślnie ustawiany na 0.
Deserializacja używa bieżącej wersji StableHLO do odczytu artefaktu.
stablehlo-translate
To najprostszy sposób na utworzenie i odczytanie artefaktu przenośnego.
# 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++
W przypadku zautomatyzowanych przepływów pracy StableHLO udostępnia te interfejsy API zgodności:
// 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);
Informacje o pełnych interfejsach API znajdziesz w sekcjach stablehlo/api/PortableApi.h
i stablehlo/dialect/Serialization.h
.
Przykład zastosowania tych interfejsów API znajdziesz w sekcji StablehloTranslateMain.cpp
.
Python
StableHLO udostępnia też powiązania Pythona z interfejsami API zgodności 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: ...
Pełną listę interfejsów API Pythona znajdziesz w sekcji StablehloModule.cpp
.
W sekcji stablehlo.py > test_serialization_apis
znajdziesz przykłady użycia interfejsów API do serializacji w Pythonie w obie strony.
Testy
W stablehlo/tests/vhlo mamy pakiet zgodności, który obejmuje kompleksowy kompendium operacji StableHLO zserializowany na potrzeby wszystkich obsługiwanych wersji StableHLO. W przypadku każdego żądania pull testujemy zgodność wsteczną i przyszłą, tj. czy można zdezorientować pakiet HEAD (zgodność wsteczną), czy kompendium może być zserializowane i kierowane na wszystkie obsługiwane wersje StableHLO (zgodność z wyprzedzeniem), a wyniki są składniowo identyczne z pierwotnymi programami StableHLO.
Praca w przyszłości
Utworzenie pakietu zgodności w projekcie MLIR: na podstawie wniosków z ustalania i utrzymywania gwarancji StableHLO zamierzamy udostępnić pakiet zgodności dla starszych wersji MLIR, aby zapewnić wczesne wykrywanie przypadkowych awarii zgodności w infrastrukturze kodu bajtowego MLIR (#1632).
Użycie implementacji referencyjnej: obecnie testowanie zgodności polega na deserializacji pakietu zgodności zserializowanego za pomocą starszych wersji biblioteki libStablehlo i upewnieniu się, że deserializacja generuje programy o identycznej składni. W tych testach planujemy też zastosować wdrożenie referencyjne, co pozwoli łagodzić nadmiernie uciążliwe wymaganie związane z tożsamością składniową i dokładnie przetestować implementację referencyjną (#1245).
Wykracza poza zakres
Nieprzenośne artefakty: gwarancja zgodności jest zapewniana tylko w przypadku artefaktów przenośnych, które zostały utworzone w określony sposób. Inne rodzaje artefaktów, takie jak stylowa reprezentacja dialektu StableHLO czy nawet reprezentacja dialektu StableHLO za pomocą kodu bajtowego, nie są gwarantowane.
Nieokreślone funkcje: możemy wprowadzać niezgodne zmiany w funkcjach, które były wcześniej obsługiwane w programach StableHLO, ale nie były jeszcze uwzględnione w specyfikacji StableHLO. Na przykład nie udzielamy gwarancji zgodności niezarejestrowanych atrybutów.
Zgodność błędu: możemy wprowadzić niezgodne zmiany, jeśli implementacja w libStablehlo jest sprzeczna ze specyfikacją StableHLO, np. jeśli definicja w dialekcie VHLO jest nieprawidłowa lub weryfikator w dialekcie StableHLO nie pasuje do specyfikacji.
Dokładność liczbowa: StableHLO ma wiele operacji ze zdefiniowaną dokładnością wdrożenia dla różnych klientów, a nawet w ramach tego samego klienta w różnych wersjach. W rezultacie StableHLO nie gwarantuje dokładności liczb, chociaż w przyszłości może się to zmienić (#1156).
Zależy nam na zgodności źródeł interfejsów API w językach C, C++ i Python w libStablehlo. Obecnie nie gwarantujemy zgodności źródeł, ale daj nam znać, jeśli jest to ważny przypadek użycia, abyśmy mogli porozmawiać o jego wspieraniu (#1247).