MXU 延迟:PF
地址适用于来自 libtpu-0.0.40-cp314 wheel 的 libtpu.so。其他版本会有所不同。
摘要
本页记录 Pufferfish (v4) 如何为 MXU 流水线占用定价,其中最主要的结论是结构性的:Pufferfish 没有单独的 MxuLatencyTable。 Viperfish、Ghostlite 和 6acc60406 会分别在其 LatencyTable 的 +0x1d8 槽上堆分配一个 reservation-matrix 对象,即每个 MXU op family 一个 flat_hash_map<Modifier, array<int,N>>,并由从 MatmulDataFormat 构造的 modifier key 索引;这个对象在 Pufferfish 成本模型中不存在。二进制中没有 xla::pufferfish::MxuLatencyTable 类;唯一的 MxuLatencyTable 类型是 xla::viperfish::、xla::ghostlite::,以及 anonymous-namespace 的 6acc60406 变体(lookup @0x1c8bdb20, gf.cc)。因此 Pufferfish 的行为类似 Jellyfish/Dragonfish:它把 MXU 占用折入其他成本对象,而不是放进专用的 reservation table。
具体来说,Pufferfish 在两个位置为 MXU 占用定价。第一,matmul throughput 作为 PufferfishPerformance grid 中的一列存在:res 9,一个 96-cell 列,在整个 matmul band(Instruction 0x7a..0xd9)上携带 value-set {8, 16},由 byte-identical grid GetResourceUsage @0x1c8c3880 读取。第二,transpose / cross-lane (Xlu) reservation 由单独的 XluConflictPenaltyTable 定价,这是一张嵌入 LatencyTablePufferfish +0x18 的 3-axis integer table,通过 XposeXLUReservationLatency @0x1c8a13e0 读取。这正是 performance-pf 页面从 grid 侧描述的分拆;本页从 MXU-occupancy 侧描述它,并说明任务简报所要求的 per-(MatmulMode × MatmulDataFormat) reservation-matrix body 为什么在 v4 中不存在。
参照系是同族的其他模型。在 Viperfish 上,matpush 会被压缩为一个 MatpushModifier key,在 flat_hash_map 中查找,并产生一个密集的 per-MxuResource hold cycles array<int,19>({2,1,1} bf16 → {8,7,6} int8-x8)。在 Pufferfish 上,同样的物理占用通过 grid 的 matmul-throughput cell(8 narrow / 16 wide)加 conflict-penalty matrix 表达;reservation map 层完全缺失。v4 成本模型的重新实现不得构建 MxuLatencyTable;它必须通过 PufferfishPerformance(res 9)和 XluConflictPenaltyTable 为 MXU op 定价。
重新实现的契约是:
- Pufferfish 携带没有
MxuLatencyTable对象(没有this+0x00matpush map,没有this+0x20matmul map)——简报中的 reservation-matrix 布局描述的是 Viperfish,不是 PF。 - PF 实际为 MXU throughput 定价的位置:matmul 使用
PufferfishPerformanceres 9({8,16}),latch 使用 matprep band(res 10/11),matrix-result deposit 使用 res 6(kVectorMatres)。 XluConflictPenaltyTable(3-axis[XluInstrType][6][3])以及XposeXLUReservationLatency,它们取代 grid column 或 reservation map 来为 transpose/Xlu reservation 定价。MxuResource列数问题:PF 根本没有MxuResourceenum;它的 MXU 列是 20-wide grid 内的PufferfishPerformance::Resourceordinal。
MxuLatencyTable | 无 —— 二进制中不存在 xla::pufferfish::MxuLatencyTable 符号 |
| MXU throughput | PufferfishPerformance grid res 9(96 cells,value-set {8,16})@0x1c8c3880 |
| Matprep throughput | grid res 10(value 7),res 11/12(transpose-binary / matprep result) |
| Matrix-result deposit | grid res 6 = kVectorMatres(0x77),value 8 |
| Xlu / transpose 定价 | XluConflictPenaltyTable(3-axis)via XposeXLUReservationLatency @0x1c8a13e0 |
| Penalty table | LatencyTablePufferfish +0x18;ctor @0x1c8a1960 中 10 次 SetXluConflictPenaltyBetween 安装 |
MxuResource count | n/a —— PF 使用 PufferfishPerformance::Resource(20 列),不是 per-gen MxuResource enum |
| Generation | Pufferfish,TpuVersion 2 / v4(LatencyTablePufferfish,object 0x1e0 B) |
Pufferfish 没有 MxuLatencyTable
Pufferfish 不拥有 MxuLatencyTable。LatencyTablePufferfish(ctor @0x1c8a1960)没有分配它:它在 [this+0x1d0] 存储 GetSharedPufferfishPerformance,在 [this+0x1d8] 存储 GetSharedPufferfishBarnaCorePerformance(两个 Performance grid,而不是 reservation map),并在 [this+0x18] 构建一个 inline XluConflictPenaltyTable。符号表中任何位置都不存在 xla::pufferfish::MxuLatencyTable 类、ctor 或 GetResourceUsage。
陷阱 — reservation-matrix 模型(
this+0x00处的 matpush map、this+0x20处的 matmul map、array<int,19>body、{2,1,1}/{4,3,2}/{8,7,6}value-set)是 Viperfish 模型(mxu-latency-vf);它从 v5p 才首次出现,而不是 v4。Viperfish、Ghostlite 和6acc60406携带这张表;Jellyfish、Dragonfish 以及 Pufferfish 都没有。不要假设 PF 上的LatencyTable + 0x1d8槽是 reservation map —— 它是第二个Performancegrid。
反编译显示的内容
Pufferfish LatencyTable ctor 会把自身 0x1e0-byte body 清零,设置 vtable,然后连接两个 Performance singleton 和一张 conflict table —— 没有 map 构建,没有 SetReservations,也没有 modifier key 的 flat_hash_map:
function LatencyTablePufferfish(this, version): // @0x1c8a1960
LatencyTable_base(this, version) // zero 0x1e0 body, set vptr off_21C20330
[this+0x1d0] = GetSharedPufferfishPerformance() // TensorCore grid (pf_shared @0x22579a10)
[this+0x1d8] = GetSharedPufferfishBarnaCorePerformance() // BarnaCore grid (pf_bc_shared)
// inline std::vector<int>-shaped scratch at +0x20/+0x74/+0xC8/+0x11C/+0x168/+0x1BC (size/cap 1 or 9)
InitializeConflictLatency(this)
SetXluConflictPenaltyBetween(this, 0, 2, 0, 56) // 10 penalty installs into the +0x18 table
SetXluConflictPenaltyBetween(this, 5, 2, 0, 46)
SetXluConflictPenaltyBetween(this, 0, 5, 0, 17)
SetXluConflictPenaltyBetween(this, 2, 5, 0, 96)
SetXluConflictPenaltyBetween(this, 2, 0, 0, 86)
SetXluConflictPenaltyBetween(this, 0, 2, 1, 56) // second hi-plane duplicates the first five
SetXluConflictPenaltyBetween(this, 5, 2, 1, 46)
SetXluConflictPenaltyBetween(this, 0, 5, 1, 17)
SetXluConflictPenaltyBetween(this, 2, 5, 1, 96)
SetXluConflictPenaltyBetween(this, 2, 0, 1, 86)
```text
对比 Viperfish ctor(`@0x1c8a52c0`,约 27 KB),它会 `new` 一个 `MxuLatencyTable`,并通过 `SetReservations<MatpushModifier>`/`<MatmulModifier>`/`<MatresModifier>`/`<VlxmrModifier>` 填充四个 `flat_hash_map`。Pufferfish 的 ctor 小了两个数量级,因为它没有这样的 map 要构建。MXU 占用已经烘焙进 ctor 只负责指向的 `PufferfishPerformance` grid 中。
> **说明 —** PF ctor 在 `+0x20`、`+0x74`、`+0xC8`、`+0x11C`、`+0x168`、`+0x1BC` 清零填充的 inline `std::vector<int>`-shaped field(每个设置为 `{ptr=0, size=cap=1}` 或 `{..=9}`)是 base `LatencyTable` 的 per-XLU scratch vector,不是 MXU reservation map。它们持有 `{1,1,1,9,1,1}` size/cap seed,即 `xlu_count=2` Pufferfish XLU-edge scratch,并且与 v5p+ `MxuLatencyTable` 的 matmul/matpush reservation family 无关。
---
## Pufferfish 在何处为 MXU 占用定价
### Matmul 和 matprep throughput —— grid
Viperfish 存入其 `MatmulModifier` reservation array 的 matmul throughput,Pufferfish 则存为 grid cell。`PufferfishPerformance::GetResourceUsage(instr, res)` `@0x1c8c3880` 读取 `grid[instr][res]`;matmul band 占用 res 9:
| MXU 角色 | Grid column | Cells | Value(s) | 含义 |
|---|---|---:|---|---|
| matmul throughput | res 9 | 96 | `{8, 16}` | per-issue hold;8 = narrow format,16 = wide |
| matprep throughput | res 10 | 20 | `7` | per-issue matprep latch hold |
| matprep / transpose result A | res 11 | 54 | `{1, 8, 16}` | matprep + transpose-binary + permute/rotate result |
| transpose / permute result B | res 12 | 34 | `{1, 8, 16}` | 第二个 transpose/permute result stage |
| matrix-result (Xlu) deposit | res 6 | 1 | `8` | `kVectorMatres`(0x77)—— conv `R[2]` analog |
res 9 上单一的 value-set `{8, 16}` 是 VF `{2,1,1}/{4,3,2}/{8,7,6}` reservation triplet 的 PF 对应物:narrow(bf16-class)matmul 持有 throughput port 8 cycles,wide(int8/x8-class)matmul 持有 16。不存在单独的 matpush/matmul/matres/vlxmr map,因为 grid 的外层 `Instruction` axis 已经按数据格式把 matmul/matprep opcode 展开到整个 band(通过 `GetPufferfishInstruction` 中的 latch-mode WORD table)。matmul base **latency**(band 开头两个 byte-confirmed format depth 83 和 101,`latency[0x7A]=83`;两者 narrow/wide 归属是推断的,而非逐字节枚举 —— 见 [`performance-pf`](performance-pf.md))是总 op depth;res-9 cell(8 / 16)是约束 back-to-back issue 的 throughput hold。
> **特性 —** matmul-throughput 表示方式会逐代变宽,而 Pufferfish 是最窄的:PF 上是单一 res-9 列(96 cells),VF 上是 res-3 列加 4-stage matprep group(res 4..7),GL/GF 上是更宽的 EUP-AndPop FIFO。同样的物理占用在 PF 上是一列,在 VF 上是七列。把 VF multi-stage matprep group 移植到 PF 的重新实现,会建模 PF 的 20-column grid 并不存在的 resource port。
### Transpose / Xlu reservation —— conflict-penalty table
VF/GL/GF 从 Xlu grid column(`GetXluPathReservation`)读取的 transpose 和 cross-lane (Xlu) reservation,Pufferfish 则从专用 `XluConflictPenaltyTable` 定价。`XposeXLUReservationLatency` `@0x1c8a13e0`:
```c
function XposeXLUReservationLatency(this, mode, earlier, later, a, b): // @0x1c8a13e0
CHECK(IsTranspose(earlier)) // latency_table_pf.cc:62
v = (b - a) + XluConflictPenaltyBetween(&this.penalty /* +0x18 */, earlier, later_lo, later_hi)
if v < -5: v = -6
return v + 7XluConflictPenaltyBetween @0x1c8a0180 是 3-axis lookup —— penalty[XluInstrType][lo<6][hi<3],stride 72*type + 12*lo + 4*hi + 8,返回已存储的 penalty + 1。IsTranspose(type) 是 (type - 2) < 3,因此 XluInstrType ordinal {2,3,4} 是 transpose op;CHECK 强制一对 op 中的 earlier op 必须是 transpose。ctor 安装的 10 个 penalty pair 为 transpose-result producer 与后续 Xlu consumer 之间的 conflict cycles 定价((0→2)=56、(2→5)=96、(2→0)=86、(5→2)=46、(0→5)=17,每个在两个 hi plane 上重复)。
| Accessor | Address | 角色 |
|---|---|---|
XposeXLUReservationLatency | 0x1c8a13e0 | transpose/Xlu reservation = (b−a) + penalty + 7,带 clamp |
LatencyBetweenXposeInstrAndResult | 0x1c8a1520 | 通过 penalty table 计算 transpose-instr → result edge |
XluConflictPenaltyBetween | 0x1c8a0180 | 3-axis read [type][6][3],返回 penalty+1 |
XluConflictPenaltyTable::IsTranspose | 0x1c8a04e0 | (type − 2) < 3 → types {2,3,4} |
SetXluConflictPenaltyBetween (PF) | 0x1c8a17e0 | 安装 penalty;CHECK(!IsPacked(earlier) && !IsPacked(later)) |
陷阱 — conflict-penalty 模型是有方向且成对的,不是 per-op reservation。VF/GL/GF 的
GetXluPathReservation为一个 op 返回一个数字(它持有 Xlu deposit port 的 cycle 数);PF 的XluConflictPenaltyBetween返回 earlier transpose 与 later Xlu op 之间的 penalty。把 PF penalty matrix 映射为 single-op Xlu reservation 的重新实现,会彻底丢失 conflict structure —— PF 把 Xlu hazard 建模为 producer→consumer edge,后续代则建模为 port hold。
MxuResource 问题
简报类比 Viperfish 的 array<int,19> 和 Ghostlite 的 array<int,11>,询问 PF 的 MxuResource 列数。Pufferfish 没有 MxuResource enum。 MxuResource enum 是 MxuLatencyTable 的 value-array index space,而 PF 没有 MxuLatencyTable。MXU sub-unit 反而是 PufferfishPerformance::Resource enum 中的列,即 20-wide grid axis(performance-pf),其中 res 9 是 matmul throughput,res 10 是 matprep,res 6 是 matrix-result deposit。PF 没有 kNumMxuResources CHECK 常量(约束 VF/GL lookup 的 0x13=19 / 0xB=11 bound),因为不存在 per-MxuResource read 需要约束。
因此 Pufferfish 的 resource-count 答案是:MXU 占用存在于 20-column PufferfishPerformance::Resource grid 中,而不是单独的 MxuResource-indexed reservation array 中。MxuResource 模型从 Viperfish 才开始。
| Gen | MxuLatencyTable? | MxuResource count | MXU throughput home |
|---|---|---|---|
| Jellyfish / Dragonfish | no | n/a | inline 15-field latency model |
| Pufferfish | no | n/a | PufferfishPerformance grid res 9 + XluConflictPenaltyTable |
| Viperfish | yes | 19(array<int,19>) | MxuLatencyTable @this+0x1d8 |
| Ghostlite | yes | 11(array<int,11>) | MxuLatencyTable @this+0x1d8 |
6acc60406 (TPU7x) | yes | 11(array<int,11>) | MxuLatencyTable @this+0x1d8(anon-ns,lookup @0x1c8bdb20) |
函数映射
| Function | Address | 角色 |
|---|---|---|
LatencyTablePufferfish::LatencyTablePufferfish | 0x1c8a1960 | ctor —— 连接两个 Performance grid + conflict table;没有 MxuLatencyTable |
PufferfishPerformance::GetResourceUsage | 0x1c8c3880 | MXU throughput read —— grid[instr][res 9] 等 |
PufferfishPerformance::PufferfishPerformance | 0x1c8be080 | grid ctor —— res 9 matmul column(96 cells,{8,16}) |
XposeXLUReservationLatency | 0x1c8a13e0 | 替代 reservation map 的 transpose/Xlu reservation |
XluConflictPenaltyBetween | 0x1c8a0180 | 3-axis penalty table read |
SetXluConflictPenaltyBetween (PF) | 0x1c8a17e0 | 10 个 ctor penalty install |
ResourceUsageFromInstruction (variant 0/1) | 0x1c8a3180 / 0x1c8a31a0 | TC/BarnaCore grid dispatch —— MxuLatencyTable family select 的 analog |
GetSharedPufferfishPerformance singleton | 0x22579a10 | PF 用来为 MXU op 定价的 grid |
viperfish::MxuLatencyTable::MxuLatencyTable | 0x1c8a52c0 | PF 没有的 v5p reservation-table ctor —— 用于对照 |
相关组件
| Name | Relationship |
|---|---|
mxu-latency-overview | per-gen MxuLatencyTable 模型 —— PF 是缺少它的 v4 例外 |
performance-pf | 为 PF MXU throughput(res 9)定价的 PufferfishPerformance grid + conflict table |
mxu-latency-vf | Viperfish array<int,19> reservation matrix —— PF 之前尚未出现的模型 |
matmul-mode-modifiers | MatmulDataFormat code;在 PF 上它们选择 grid band ordinal,而不是 modifier key |
resource-enum | 23-slot per-bundle ResourceVector,不同于 PF 20-column grid |
交叉引用
- MXU 延迟概览 —— per-gen
MxuLatencyTablereservation model;Pufferfish 是像 JF/DF 一样缺少它的 v4 generation - Performance:PF ——
PufferfishPerformancegrid(res 9 matmul throughput,res 6 matrix-result)以及共同承载 PF MXU occupancy 的XluConflictPenaltyTable - MXU 延迟:VF —— Viperfish
array<int,19>reservation matrix,以及 v5p 首次引入的{2,1,1}/{4,3,2}/{8,7,6}value-set - MXU 延迟:GL (Ghostlite) —— Ghostlite
array<int,11>reservation matrix - MXU 延迟:GF (6acc60406) ——
6acc60406array<int,11>reservation matrix(lookup@0x1c8bdb20) - MatmulMode 与 Modifiers ——
MatmulDataFormatcode;在后续 generation 上它们构建 reservation-map key,在 PF 上它们选择 grid band ordinal - MXU Slot —— PF 通过 grid 定价的 LLO MXU instruction slot
- Matprep / IAR / Latch —— 后续代 table 所基于 matpush family key 的 latch/matprep op