Skip to content

TpuHal 类层级

地址适用于 libtpu-0.0.40-cp314 wheel 中的 libtpu.so。其他版本会有所不同。

摘要

TPU 运行时暴露一个芯片代际的四个概念性“产品”——硬件抽象、逐核心执行上下文、成本模型和 ISA 编码器。若重新实现者预期在一个工厂下看到四个并列的 TpuHal* 类,将找不到它们。符号表毫不含糊:实际上只有 TpuHalHardware*tpu::TpuHal* 命名的类。TpuHalCoreTpuHalCostModelTpuHalEncoder 在二进制的符号表中完全不存在——它们是由三个独立类树(tpu::TpuCorexla::jellyfish::CycleTabletpu::TpuCodec/isa::Encoder)承担的角色,HAL 拥有、配对或供给这些类树,但它们不共享 TpuHalFactory 基类,也不是由 HAL 工厂产生。

本页用真实类名、vtable 地址、槽位数量,以及它们之间的单继承边,映射全部四个层级。这四棵树只共享一个轴:tpu::TpuVersion。HAL 工厂通过注册表按它分派;芯片/核心 impl 由 HAL 分配的 family impl 选择;TpuCodec::Create 对它 switch;CycleTable::CreateFunctionRegistry 中查找它。理解这四个“产品”只通过 TpuVersion 耦合——并且只有其中一个是 TpuHal 类——是理解为什么各树的 override 矩阵差异如此之大的前提。

Hardware 树是浅层树:TpuHal(抽象)→ TpuHalHardwareImpl(中间层)→ {Jxc,Pxc,Vxc}HardwareImpl(叶子)。Core/Chip 树深一层。CostModel 和 Encoder 树是扁平的(每个叶子都是抽象根的直接子类,没有共享中间层)。所有继承都是单继承(__si_class_type_info);四棵树中没有任何多重继承。

对重新实现而言,契约是:

  • 只有 TpuHalHardware*TpuHal 类;其他三个角色是以同一个 TpuVersion 为键的独立类树。
  • Hardware 树的基类/中间层/叶子结构、23 槽 vtable,以及 impl 对象布局(Jxc/Pxc 为 208 B,Vxc 为 216 B;helper 指针位于 +200)。
  • 配对的 Core(46/48 槽)和 Chip(25/27 槽)树的深度和槽位数量,以及 CostModel(5 槽)和 Encoder(6/14/20 槽)树。
  • 四棵树之间的所有权与数据流耦合关系。
HAL 对象基类tpu::TpuHal (_ZTV @ 0x21d34420, 23 slots, pure at 2 & 20)
HAL 中间层tpu::TpuHalHardwareImpl (no own _ZTV; _ZTI @ 0x21cc52e0)
HAL 叶子TpuHal{Jxc,Pxc,Vxc}HardwareImpl (_ZTV 0x215fe580 / 0x21608618 / 0x21cabfc0)
Impl 对象大小208 B (Jxc, Pxc) · 216 B (Vxc) · helper pointer at +200 (obj[25])
Core 树tpu::TpuCore (46-slot base) → TpuCoreCommonImplTpuCoreDriverCommonImpl → 3 leaves (48-slot)
Chip 树tpu::TpuChip (25-slot base) → TpuChipCommonImplTpuChipDriverCommonImpl → 3 leaves (27-slot)
CostModel 树xla::jellyfish::CycleTable (5-slot) → {Jf,Pf,Vf,Glc,Gfc}CycleTable (flat, 5 leaves)
Encoder 树tpu::TpuCodec (6-slot) + isa::Encoder (14/20-slot) — not a TpuHal class
共享轴tpu::TpuVersion (0..5)

只有 Hardware 是 TpuHal 类

一次符号扫描即可确定命名问题。二进制中完整的 tpu::TpuHal* 类集合是 Hardware 家族及其支持类;另外三个“产品”名称不存在:

text
present   tpu::TpuHal                     (abstract HAL object base)
present   tpu::TpuHalHardwareImpl         (intermediate)
present   tpu::TpuHal{Jxc,Pxc,Vxc}HardwareImpl
present   tpu::TpuHalFactory              (abstract factory interface)
present   tpu::TpuHalHardwareFactoryBase  (concrete Create/CanCreate)
present   tpu::TpuHal{Jxc,Pxc,Vxc}HardwareFactory
present   tpu::TpuHal{Jxc,Pxc,Vxc}CommonHelper
present   tpu::TpuHalCommonStates         (non-polymorphic data cache; no vtable/RTTI)

absent    tpu::TpuHalCore        — the role is filled by tpu::TpuCore
absent    tpu::TpuHalCostModel   — the role is filled by xla::jellyfish::CycleTable
absent    tpu::TpuHalEncoder     — the role is filled by tpu::TpuCodec / isa::Encoder
```text

> **易错点 —** 并不存在“由一个工厂产生的四个 `TpuHal` 并列产品类型”。`TpuHalFactory` 只产生一种对象——`TpuHal{Jxc,Pxc,Vxc}HardwareImpl`。"Core"、"CostModel" 和 "Encoder" 是真实的逐家族/逐代际层级,但它们分别位于 `tpu::`(Core/Chip)、`xla::jellyfish::`(CostModel)和 `tpu::`/`isa::`(Encoder)中——没有任何一个继承自 `TpuHal` 基类,也没有任何一个由 HAL 工厂构建。若重新实现让四者都派生自一个共同的 `TpuHalFactory`,就无法匹配二进制的类图。

---

## 层级 1 — TpuHalHardware(HAL 对象)

这是工厂实际产生的唯一一棵树。三层结构,全程单继承(由 typeinfo+0x10 处的 `__si_class_type_info` 基类指针验证):

```text
                       (abstract HAL object)
                            tpu::TpuHal
                       _ZTV 0x21d34420   _ZTI 0x21d344e8
                       23 slots; pure-virtual at slot 2 (Type) and slot 20 (CreateAndInitializeChips)
                                |  __si base
                       (intermediate; no own _ZTV)
                       tpu::TpuHalHardwareImpl
                       _ZTI 0x21cc52e0
                       supplies Type (slot 2 → 0x1d3b5480) and the stricter
                       ValidateTopology (slot 19 → 0x1d3b54a0)
                                |  __si base (×3)
        +-----------------------+-----------------------+
        |                       |                       |
  TpuHalJxcHardwareImpl   TpuHalPxcHardwareImpl   TpuHalVxcHardwareImpl
  _ZTV 0x215fe580         _ZTV 0x21608618         _ZTV 0x21cabfc0
  _ZTI 0x215fe648         _ZTI 0x216086e0         _ZTI 0x21cac088
  208 B (0xD0)            208 B (0xD0)            216 B (0xD8)
  helper @ +200           helper @ +200           helper @ +200, flag byte @ +208
        |                       |                       |
        v                       v                       v
  TpuHalJxcCommonHelper   TpuHalPxcCommonHelper   TpuHalVxcCommonHelper
  (heap-owned; freed raw   (heap-owned)            (heap-owned; non-trivial dtor,
   in JxcImpl D2)                                   called then freed in VxcImpl D2)

Vtable 布局 — 23 个槽位

基类 TpuHal vtable 包含 23 个函数指针槽位。槽位 0/1 是析构函数;槽位 2 和 20 在抽象基类中是 __cxa_pure_virtual;其余 20 个携带具体基类实现。中间层 TpuHalHardwareImpl 让该类对三个家族都可实例化——它填充槽位 2(Type),并提供更严格的槽位 19(ValidateTopology)。完整的逐家族 override 矩阵(每个叶子 override 哪些槽位及其地址)位于 HAL 工厂 Override 矩阵 页面;本页记录布局和对象。

TpuHalHardwareImpl::Type(槽位 2,0x1d3b5480)返回常量 0——即 kHardware product-type 标签,三个家族完全相同。TpuHalHardwareImpl::ValidateTopology(槽位 19,0x1d3b54a0)链式调用 TpuHal::ValidateTopology,随后调用 ScanHardwareDevices,比较检测到的 version 和 TpuChipParts::variant_name 与配置拓扑,并在不匹配时以 "Detected hardware version ... does not match with topology ..." 拒绝。

对象布局

impl 对象由家族 CreateImpl 分配并盖上 vtable,并由其 D2 析构函数销毁。二者都确认了布局:

字段偏移类型含义
vtable 指针+0void*逐家族 impl vtable(off_215FE590 / off_21608628 / off_21CABFD0
基类状态+8 ..(TpuHal base)TpuVersion、work-queue、topology 等(由 TpuHal::TpuHal 设置)
helper+200 (obj[25])TpuHal*CommonHelper*堆拥有的 CommonHelper;在 CreateAndInitializeChips 前为 nullptr
mesh_torn_down flag+208uint8仅 VXC — 保护 PreTearDownChips 避免重复 mesh teardown;208 B 的 Jxc/Pxc 对象中不存在

怪异点 — VXC impl 为 216 字节(operator new(0xD8)),比 208 字节(0xD0)的 Jxc 和 Pxc impl 大 8 字节。额外空间是 +208 处的 flag 字节,VxcImpl::PreTearDownChips(0x1d111720)读取它以跳过重复 mesh teardown。CommonHelper 指针在三者中都保持在 +200(obj[25])。若重新实现假设所有家族都是统一的 208 字节对象,就会写越 Jxc/Pxc 分配边界或少分配 Vxc 对象。

两个 D2 析构函数在释放 helper 时也不同:JxcImpl::~JxcImpl(0x0e724de0)重新植入 vtable,读取 obj[25],将其置空,并直接 free()——JXC helper 是 POD-trivial。VxcImpl::~VxcImpl(0x1d111740)在 free() 前调用 TpuHalVxcCommonHelper::~TpuHalVxcCommonHelper(helper)——VXC helper 有非平凡析构函数。


层级 2 — TpuCore 和 TpuChip(逐核心角色)

"Core" 角色是 tpu::TpuCore:位于芯片上的 TensorCore/BarnaCore 执行上下文。它由芯片(TpuChipCommonImpl::CreateCores)创建,而芯片又由 HAL 的 CommonHelper::CreateChips 创建。Core 树有四层——比 Hardware 深一层——并与同样深的 TpuChip 树配对。

text
  tpu::TpuChip  (ROOT)                          tpu::TpuCore  (ROOT)
  _ZTV 0x21cad4e8  (25 slots)                   _ZTV 0x21cad8e8  (46 slots)
     |  __si                                       |  __si
  tpu::TpuChipCommonImpl                        tpu::TpuCoreCommonImpl
  _ZTV 0x21cad3d8                               _ZTV 0x21cad730
     |  __si                                       |  __si
  tpu::TpuChipDriverCommonImpl                  tpu::TpuCoreDriverCommonImpl
  _ZTV 0x215fe828                               _ZTV 0x21cacd50  (_ZTI 0x21cacee0)
     |  __si (×3)                                   |  __si (×3)
  +--+---+----+                                 +--+----+----+
  Jxc  Pxc  Vxc                                 Jxc  Pxc  Vxc
  ChipJxcDriverImpl   .710                       CoreJxcDriverImpl  .ea30
  ChipPxcDriverImpl   .8758                      CorePxcDriverImpl  .8978
  ChipVxcDriverImpl   .c0b0   (27 slots)         CoreVxcDriverImpl  .c2e8   (48 slots)
     |  TpuChipCommonImpl::GetCore(TpuCoreOnChip) ─┘
```text

Core 叶子的逐家族 override 集合几乎完全是 BarnaCore(SparseCore sequencer / address-handler)编程表面——vtable 槽位 25..38——再加上 host-interrupt 管线(槽位 46、47)。TensorCore 的运行/加载/内存表面完全通用,由 `TpuCoreCommonImpl` / `TpuCoreDriverCommonImpl` 实现一次。PXC 独有地 override 槽位 11(`FlushOutfeedQueues`)。

在 Chip 树中,VXC override 的槽位远多于 JXC 或 PXC(throttle、core-dump、host-sync-flag、init、teardown、continuation-queue)——fabric-attached 的 v3/v4/v5 硅片需要自己的机制,而较旧的 PCIe-attached jxc/pxc 继承通用 `TpuChip` 基类 / `TpuChipCommonImpl`。这对应了 VXC 在 Hardware 树中唯一的槽位 18 override。该层之下还有两个使用同一 Jxc/Pxc/Vxc 模式的辅助逐家族树:`TpuChipProfiler*Impl`(`_ZTV` 0x215fff68 / 0x21609060 / 0x21cb1ce0)和 `TpuCoreDebugInterface*DriverImpl`(`_ZTV` 0x215fee10 / 0x21608c10 / 0x21cac550)。(逐槽 Core/Chip override 细节见:[VXC 家族](vxc-family.md) 和各家族页面。)

---

## 层级 3 — CycleTable(成本模型角色)

"CostModel" 角色是 `xla::jellyfish::CycleTable`——而且它完全不在 `tpu::` HAL 运行时中。它是 XLA 后端中的编译器侧类,附着到 `xla::jellyfish::Target`(每个 `TpuVersion` 一个),不由任何 HAL 对象拥有。该树是扁平的:一个抽象根,没有共享中间层,五个叶子各自完全 override 全部五个槽位。

```text
  xla::jellyfish::CycleTable  (abstract ROOT; no own _ZTV)   _ZTI 0x21c20008
     |  __si base of all 5 (each is a direct leaf — no intermediate)
  +-----------+-----------+-----------+-----------+-----------+
  JfCycleTable PfCycleTable VfCycleTable GlcCycleTable GfcCycleTable
  v=0,1        v=2          v=3          v=4           v=5
  _ZTV 0x21c1ffb8 0x21c20048 0x21c200c8  0x21c20148    0x21c201c8

  5 slots, all overridden in every leaf:
    slot 0  ~CycleTable D2
    slot 1  ~CycleTable D0
    slot 2  GetCyclesForThroughput(Instruction) const
    slot 3  EstimateSinCosCost() const
    slot 4  EstimateTanCost() const

分派既不是 switch,也不是 vtable cast,而是 util_registration::FunctionRegistry<TpuVersion, unique_ptr<CycleTable>(const Target&)>CycleTable::Create(Target const&)(0x1c89cc00)读取 target.tpu_version()(Target+920),并调用注册的 lambda;cycle_table.cc 静态初始化器(0x21353460)注册全部六个键 0..5。数据层是逐代 *Performance latency/resource 数组以及用于时钟频率的嵌入 chip_parts.binarypb——成本模型完全由数据表驱动,没有 learned-model 客户端。


层级 4 — TpuCodec 和 isa::Encoder(编码器角色)

"Encoder" 角色是两个耦合层级,二者都不继承任何 TpuHal 类:公开的逐代号 tpu::TpuCodec(运行时调用的 API)和内部的逐家族/逐核心 isa::Encoder(编解码器驱动的 bit-level worker)。

text
  LEVEL A — public codec (6-slot vtable)
  tpu::TpuCodec  (abstract ROOT; no own _ZTV)   _ZTI 0x21d35858
     |  __si base of 5 named + 1 anonymous (v=5)
  +----------+-----------+-----------+-----------+-----------+----------+
  Jellyfish  Dragonfish  Pufferfish  Viperfish   Ghostlite   (anon v=5)
  v=0        v=1         v=2         v=3         v=4         6acc60406
  _ZTV.360f0 .35800      .36148      .361a0      .35c00      sub_1E838380 (no _ZTV)

  6 slots: D2 (shared base @ 0x1e836100), D0, Encode, Decode, EncodeBundle, DecodeBundle
  Factory: TpuCodec::Create(TpuVersion) @ 0x1e835fa0 — jump-table switch on v=0..5

  LEVEL B — bit-level worker (14-slot per-family / 20-slot legacy)
  platforms_deepsea::jellyfish::isa::Encoder  (abstract ROOT; no own _ZTV)  _ZTI 0x21cb6a20
     |  __si
  +-- legacy (20 slots): EncoderJf / EncoderDf / EncoderBcsDf
  +-- per-family (14 slots): EncoderPf*/EncoderVf*/EncoderGl* (TensorCore / BarnaCore / SparseCore)
        each COMPOSES (template, non-virtual) a *CodecBase<...> mixin carrying the
        per-codename bundle bit layout (per-generation wire widths owned by the
        bundle-model pages; JF output fixed at 41 B / operator new(0x29))
```text

`TpuCodec::Create`(0x1e835fa0)是六 case 跳转表 switch;case 0..4 调用命名的 `CreateTpuCodec<X>` 构造器,case 5 调用匿名命名空间 creator(`sub_1E838380`)——v=5 / 6acc60406 编解码器没有命名 C++ 类,也没有恢复出的 vtable。编解码器通过 `tpu::internal::CreateEncoder{JfDf,Pf,Vf,GlGf}` 驱动匹配的 `isa::Encoder` 叶子,这些函数按 `TpuSequencerType`(不是 `TpuVersion`)分派。

> **注意 —** Encoder 不由 Core 拥有。Codec/Encoder(编译器和序列化层)*产生* bundle 字节,后者成为 `TpuCoreProgram`,随后由 `TpuCore*DriverImpl::LoadProgram` 加载并运行。二者的耦合是数据流(program bytes),不是对象所有权。

---

## 四棵树如何关联

不存在单一线性所有权链。四棵树通过一个共享键(`TpuVersion`)和两种不同机制(组合与数据流)耦合:

```text
  TpuHal (HardwareImpl)                         <- the only TpuHal class; built by TpuHalFactory
    └─owns→ N × TpuChip*DriverImpl              (CommonHelper::CreateChips)        [composition]
              └─owns→ M × TpuCore*DriverImpl    (TpuChipCommonImpl::CreateCores)   [composition]
                        └─runs→ TpuCoreProgram  (LoadProgram → TpuCoreProgramHandleImpl)

  TpuCodec (per TpuVersion; static factory, NOT owned by the HAL)
    └─drives→ isa::Encoder leaf  (per TpuSequencerType)
                └─emits→ bundle bytes → TpuCoreProgram                              [data-flow]

  CycleTable (per TpuVersion; attached to xla::jellyfish::Target, NOT owned by the HAL)
    └─reads→ per-gen *Performance arrays; consumed during XLA scheduling           [compiler-side]

Hardware → Chip → Core 是真正的组合链,全部在 tpu:: 运行时中。Encoder 只通过它序列化出的 program bytes 触达 Core。CostModel 两者都不触达——它是由同一 TpuVersion 作为键的编译器侧对象。每棵树分派所依赖的唯一轴都是 tpu::TpuVersion,这正是代号分类(6 代号权威对照)成为整个 target 模型脊柱的原因。


交叉引用

  • 6 代号权威对照TpuVersion,全部四个层级分派所依赖的单一轴
  • HAL 家族 — 构建 Hardware 树叶子的三个工厂类和五个 init module
  • HAL 工厂 Override 矩阵 — Hardware 树完整的 23 槽逐家族 override 矩阵
  • JXC 家族 — Jellyfish (v0) + Dragonfish (v1):Jxc impl、chip、core 和 codec 专门化
  • PXC 家族 — Pufferfish (v2) 专门化
  • VXC 家族 — Viperfish (v3):override 最多 chip/core 槽位的 impl
  • GXC 家族 — Ghostlite (v4) + 6acc60406 (v5),共享 VXC impl vtable