评价此页

LibTorch 稳定 ABI#

创建日期:2025年3月17日 | 最后更新日期:2025年8月19日

此笔记最终将包含更多关于如何在 torch/csrc/stable 中使用 API 的详细信息。目前,它包含了一个内部表示的表格

  1. 自定义扩展中的类型:用户自定义库中使用的类型。

  2. StableIValue 表示:类型到用户模型与 libtorch.so 之间进行 ABI 稳定交互的稳定转换。

  3. libtorch 中的类型:libtorch.so (或任何与 libtorch 二进制链接的代码) 中使用的类型。

  4. Schema 类型:由 schema 描述的类型,我们将其视为 native_functions.yaml 中 ATen op 的事实来源,以及通过 TORCH_LIBRARY 或 torch.library 注册到 dispatch 的用户自定义运算符的来源。

自定义扩展中的类型

StableIValue 表示

libtorch 中的类型

Schema 类型

std::optional<S>

如果存在值,则将原始数据按位复制到 uint64_t 的前导字节中,表示 S 的新 StableIValue。如果不存在值,则为 nullptr。

std::optional<T>

类型?

torch::stable::Tensor

将底层 AtenTensorHandle 的原始数据按位复制到 uint64_t 的前导字节中

at::Tensor

张量

RAIIATH (过时)

将底层 AtenTensorHandle 的原始数据按位复制到 uint64_t 的前导字节中

at::Tensor

张量

torch::headeronly::ScalarType

将翻译后的底层枚举按位复制到 uint64_t 的前导字节中

torch::headeronly::ScalarType

ScalarType

int32_t

按位复制到 uint64_t 的前导字节中

at::Layout

Layout

int32_t

按位复制到 uint64_t 的前导字节中

at::MemoryFormat

MemoryFormat

布尔值

按位复制到 uint64_t 的前导字节中

布尔值

布尔值

int64_t

按位复制到 uint64_t 的前导字节中

int64_t

int

double

按位复制到 uint64_t 的前导字节中

double

浮点数

?

?

c10::Device

设备

?

?

c10::Stream

?

?

c10::complex

complex

?

?

at::Scalar

Scalar

?

?

std::string/const char*/ivalue::ConstantString

str

?

?

at::Storage

Storage

?

?

at::Generator

生成器

?

?

c10::List<T>

Type[]

?

?

ivalue::Tuple<T>

(Type, …)

?

?

c10::SymInt

SymInt

?

?

c10::SymFloat

SymFloat

?

?

c10::SymBool

SymBool

?

?

at::QScheme

QScheme

我们有信心支持的类型是表格中具有完整行的那些。您可以依赖这个子集以获得正确的 ABI 稳定性。

对于有限的一组用例,我们还隐式支持任何可以表示为 64 位 StableIValues 的字面类型,因为默认的 reinterpret_cast 会成功。(例如:c10::Device。) 这些类型目前在尽最大努力的基础上是 ABI 稳定的,但将来可能会中断,因此只能用于短期测试。

您可以在自定义内核中始终使用 StableIValue 抽象来处理 c10::Device 等类型的操作,即使在自定义扩展中没有设备的标准定义表示,也可以通过不检查 StableIValue 来实现。例如,自定义运算符可以接受 StableIValue device 作为参数,并直接使用 aoti_torch_call_dispatcher 将其传递给 aten 运算符。

如何使用基于栈的 API#

aoti_torch_call_dispatcher 是我们认为的基于栈的 API,因为它接收 StableIValues 栈作为输入,这与 torch::jit::stack 的 IValues 相关。使用 dispatcher 可能会让您接触到基于栈的 API,因此我们在此记录一些不变性

  1. 栈是从左到右填充的。a. 例如,表示参数 arg0arg1arg2 的栈将在索引 0 处有 arg0,在索引 1 处有 arg1,在索引 2 处有 arg2。b. 返回值也是从左到右填充的,例如,ret0 将在索引 0 处,ret1 将在索引 1 处,依此类推。

  2. 栈始终拥有其持有的对象的拥有权。a. 调用基于栈的 API 时,您必须将拥有引用传递给调用栈,并从返回栈中窃取引用。b. 注册您的函数以通过栈调用时,您必须从您的参数栈中窃取引用,并将新引用推入栈中。