StableHLO 兼容性

StableHLO 是一个向后兼容的机器学习计算运算集,其灵感来源于 HLO/MHLO。 本文档根据兼容性 RFC 中建立的流程,说明了 StableHLO 提供的兼容性保证的类型和程度。

Versions

您可以在 Version.h 中找到当前的 StableHLO 版本。

在 0.x.x 系列中,每次对 StableHLO 运算集或 StableHLO 序列化格式进行更改时,次要版本都会递增,而每次我们将 StableHLO 下游(即 openxla/xla 代码库)集成时,补丁版本都会递增。

保证

6 个月的向后兼容性:如果由旧版 libStablehlo 序列化的可移植工件* 被新版 libStablehlo 反序列化,如果这些版本是基于间隔不到 6 个月的 Openxla/stablehlo 提交内容构建的。

具有 1 个月的向前兼容性:如果由旧版 libStablehlo 进行反序列化,则由新版 libStablehlo 序列化的可移植工件* 如果这些版本是基于间隔不到 1 个月的 openxla/stablehlo 提交内容构建的,那么除非该程序使用的是自旧版本以来引入的新功能。

* StableHLO 程序通过兼容性 API 与可移植工件相互转换,这些程序的语义由 StableHLO 规范定义。请参阅“范围外”部分,查看此兼容性定义未涵盖的内容示例。

API

您可以使用 stablehlo-translate 工具创建可移植的工件,也可以直接在 C++ 或 Python API 中创建。序列化需要 StableHLO 的目标版本,才能编写以 #.#.# 格式编写的工件(如需了解当前版本,请参阅 Version.h)。反序列化使用当前版本的 StableHLO 读取工件。

stablehlo-translate

这是创建和读取可移植工件的最简单方法。

# 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++

对于程序化工作流,StableHLO 提供了以下兼容性 API:

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

如需了解完整的 API,请参阅 stablehlo/api/PortableApi.hstablehlo/dialect/Serialization.h

如需查看这些 API 的用法示例,请参阅 StablehloTranslateMain.cpp

Python

StableHLO 还提供对 C++ 兼容性 API 的 Python 绑定:

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: ...

如需了解完整的 Python API,请参阅 StablehloModule.cpp

如需查看使用 Python 序列化 API 的往返示例,请参阅 stablehlo.py > test_serialization_apis

测试

我们在 stablehlo/test 中有一套兼容性测试套件,其中包含针对所有受支持的 StableHLO 版本序列化的 StableHLO 操作综合概要。对于每个拉取请求,我们正在测试向后和向前兼容性,即套件可针对 HEAD(向后兼容性)进行反序列化;框架可序列化,以针对所有受支持的 StableHLO 版本(前向兼容性),以及结果在语法上与原始 StableHLO 程序完全相同。

后续工作

在 MLIR 上游创建兼容性测试套件:利用在建立和维护 StableHLO 保证的过程中积累的经验,我们计划为 MLIR 上游贡献兼容性套件,以便及早检测 MLIR 字节码基础架构中意外的兼容性破坏 (#1632)。

使用参考实现:目前,兼容性测试包括对由旧版 libStablehlo 序列化的兼容性测试套件进行反序列化,并确保反序列化生成的程序在语法上完全相同。我们计划还在这些测试中使用参考实现,以放宽过于繁重的语法标识要求,并全面测试参考实现 (#1245)。

不在范围内

不可移植的工件:兼容性保证仅适用于以非常具体的方式创建的可移植工件。其他类型的工件(例如 StableHLO 方言的美观输出表示,甚至是 StableHLO 方言的字节码表示)没有兼容性保证。

未规范的功能:对于过去在 StableHLO 程序中支持但尚未纳入 StableHLO 规范的功能,我们可能会做出不兼容的更改,例如,对于未注册的属性,我们不提供兼容性保证。

bug 兼容性:如果 libStablehlo 中的实现与 StableHLO 规范相冲突(例如,VHLO 方言中的定义不正确,或者 StableHLO 方言中的验证程序不符合规范),我们可能会进行不兼容的更改。

数值精度:StableHLO 具有多个操作,这些操作都由实现定义的精度(针对各使用方甚至同一使用方的不同版本)。因此,StableHLO 并不保证数值准确性,但这种保证将来可能会发生变化 (#1156)。

为实现 libStablehlo 中的 C、C++ 和 Python API 的源代码兼容性是一个宏伟的目标。目前,我们不提供源代码兼容性保证,但如果此用例对您很重要,请告知我们,我们可以讨论如何支持它 (#1247)。