StableHLO 是一个受 HLO/MHLO 启发的向后兼容机器学习计算运算集。 本文档介绍了 StableHLO 根据兼容性 RFC 中建立的流程,所提供兼容性保证的类型和程度。
Versions
您可以在 Version.h 中找到最新版本的 StableHLO。
每次对 StableHLO 运算集或 StableHLO 序列化格式进行更改时,次要版本都会提升;每当我们向下游集成 StableHLO(即集成到 openxla/xla 代码库时)时,补丁版本都会提升。
保证
根据 StableHLO v1.0 兼容性 RFC,兼容性窗口包含以下内容:
提供 5 年的向后兼容性:如果由旧版 libStablehlo 序列化的可移植工件*被新版 libStablehlo 反序列化,如果这些版本是基于时间少于 5 年的 openxla/stablehlo 提交内容构建的,则这些工件具有相同的语义*。
向前兼容性长达 2 年:如果由旧版 libStablehlo 反序列化的可移植工件是根据时间间隔不到 2 年的 openxla/stablehlo 提交内容构建的,那么当这些版本被旧版 libStablehlo 反序列化时,这些可移植工件具有相同的语义*,除非程序使用的是自旧版本以来引入的新功能。
* 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.h
和 stablehlo/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/tests/vhlo 中有一套兼容性套件,其中包含已针对所有受支持的 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)。