性能:GF (GhPerf 465×31)
本页所有地址均适用于
libtpu-0.0.40-cp314wheel 中的libtpu.so(构建libtpu_lts_20260413_b_RC00,BuildID md589edbbe81c5b328a958fe628a9f2207d)。该二进制未剥离符号。段映射:.text/.rodataVMA == 文件偏移;.data.rel.roVMA − 0x200000 == 文件偏移;.dataVMA − 0x400000 == 文件偏移。本页中的每个单元格整数、分配大小和kResources字节都直接从 GF 构造函数和二进制的.rodata读取。
摘要
本页转储 6acc60406 (TPU7x / "GF" / gfc) GhostlitePerformance 占用网格,即按代划分的 Instruction × Resource 二维表,用来定价每条 LLO 指令占用各个 intra-op 微流水线端口的周期数。它是 libtpu 中类似 LLVM WriteRes/ProcResource 矩阵的结构,但这里是通过读取填充它的构造函数重建出来的,而不是在 .td 文件中声明。该网格为 465 × 31:465 个 GhostlitePerformance::Instruction 行(按代分类器的输出,对每个已定价行而言 == LloOpcode)和 31 个 GhostlitePerformance::Resource 列(EUP / cross-lane / Xlu / matrix-result 微流水线阶段)。旁边还有一个按同一 Instruction 索引的扁平 465 项延迟数组。二者都是 GfcCycleTable 拥有的堆对象。
GF 网格是 性能:GL 中记录的 Ghostlite(GL,v6e,476 行)网格的 gfc 同胞:它们是同一个 GhostlitePerformance 类的两个实例,具有相同的 31-int 行(每行 0x7c 字节)、字节完全相同的 GetResourceUsage/GetLatency/GetResources 方法,以及位于 @0xb43cdc4 的同一个 kResources 静态对象(二进制中恰好只有一个 GhostlitePerformance::kResources 符号;GL 和 GF 没有不同的排列)。二者的差异在于行数(465 对 476,6acc60406 去掉了 11 个 v6e shift/saturate 和 BarnaCore-wait opcode)、单元格值和基础延迟(GF EUP/transcendental op 延迟 212/204,而 GL 为 192/182),以及由不同的构造函数构建(GfcCycleTable 实例使用 sub_1C8D3740,GlcCycleTable 实例使用 GhostlitePerformanceC1 @0x1c8cbc80)。Xlu 读取的一个运行时差异不在网格中,而在成本表辅助函数中:GfcCycleTable::GetCyclesForThroughputHelper 读取 res 0x10 (16),而 GlcCycleTable 读取 res 0x0f (15),二者都索引同一个共享网格对象。
本页严格限定于 GhostlitePerformance 网格。配套的 GfcCycleTable MxuLatencyTable(按 modifier × MxuResource 的 reservation 矩阵、matmul/matpush 吞吐,以及 ComputeDmaLevels)见 MXU 延迟:GF;这里引用它但不重复。该网格向成本模型贡献的单个数值是卷积的 R[2] Xlu 项:grid[mxres-instr][res 0x10] = 4,补全 6acc60406 conv 成本三元组,而 MXU 延迟:GF 提供 R[0]/R[1]。
对于重新实现,契约是:
GhostlitePerformance对象布局(延迟数组 + 由std::vector<int>行组成的二维网格)、GF 分配大小(new 0x744/new 0x2b98/new 0x7c)以及0x1d1计数。GetResourceUsage(instr, res)读取路径:两次边界检查、24 字节行跨度、直接读取row.data[res];与 GL accessor 及其内联孪生@0x1c8da1a0字节完全相同。- 由占用方 LLO 类命名的 31 个资源列、行分类到指令区段,以及 Xlu deposit 列(res
0x10= 4)。 0xff默认回退:465 行中只有约 92 行被写入;其余保持latency = 255,并由跨代不变的CycleTable::GetResource路径定价,而不是由该网格定价。- GF-vs-GL 网格差异(行数、基础延迟、构造函数分离,以及每个 helper 的 Xlu res 索引;不是共享的
kResources差异)。
| 类 | xla::ghostlite::GhostlitePerformance(GF 变体;构造函数未命名/误符号化) |
| 所有者 / 分配 | GfcCycleTable this+0x10 — operator new(0x30) 然后 sub_1C8D3740 |
| Ctor | @0x1c8d3740 — latency new 0x744(465 int32,memset 0xff),grid new 0x2b98(465 × 24),rows new 0x7c(31 int32) |
| 读取路径 | GhostlitePerformance::GetResourceUsage @0x1c8d3700;内联孪生 @0x1c8da1a0 |
| 延迟读取 | GhostlitePerformance::GetLatency @0x1c8d36e0 |
| 列顺序 | GhostlitePerformance::GetResources @0x1c8d36c0 → kResources @0xb43cdc4(31 字节,0..30 的排列)— 由 GL 和 GF 共享 |
| 网格形状 | 465 行(0x1d1)× 31 资源(0x1f);92 行中共有 285 个已填充单元格 |
| Xlu deposit 列 | res 0x10 (16) — 对每个 matrix-result / Cmem / transpose-result op,cell = 4(conv R[2]) |
| 默认值 | 未写入行:latency 0xff = 255,grid cell 0 — 由 CycleTable::GetResource 定价,而不是网格 |
对象布局与构建
目的
该网格在构造 GfcCycleTable 时只构建一次。cycle table 在堆上分配两个对象:位于 this+0x10 的 GhostlitePerformance 网格,以及位于 this+0x18 的 MxuLatencyTable。二者各有自己的构造函数。本页覆盖前者。
// GfcCycleTable::GfcCycleTable @0x1c89eec0
v4 = operator new(0x30u); sub_1C8D3740(v4); // GhostlitePerformance grid → this+0x10
v6 = operator new(0xA0u); sub_1C8BB1C0(v6); // MxuLatencyTable → this+0x18
```text
这个 `0x30` 字节对象是六个 qword 的 `GhostlitePerformance` 头部(两个 `{ptr, size, cap}` 三元组);网格*主体*单独在堆上分配。
### 结构
`GhostlitePerformance` 是共享的网格族布局(PF/VF/GL/GF 中相同,只有宽度不同,见 [性能家族概览](performance-overview.md)):
```c
struct GhostlitePerformance { // 0x30-byte header, body on the heap
int32* latency; // +0x00 ; new 0x744 = 1860 B = 465 int32, memset 0xff
u64 latency_size; // +0x08 ; = 0x1d1 = 465
u64 latency_cap; // +0x10 ; = 0x1d1
vector<int>* grid; // +0x18 ; new 0x2b98 = 11160 B = 465 × 24
u64 grid_outer_count; // +0x20 ; = 0x1d1 = 465 (the GetResourceUsage outer bound)
u64 grid_outer_cap; // +0x28 ; = 0x1d1
// each grid row is a 24-B std::vector<int>:
// { int* data (new 0x7c = 124 B = 31 int32, zero-init), size = 0x1f = 31, cap = 0x1f }
};构造函数 sub_1C8D3740 无法反编译(Hex-Rays 对这个 27 143 字节的填充函数不返回 cfunc);以下每个事实都从其反汇编读取。开头序列字节级精确如下:
; sub_1C8D3740 @0x1c8d3740 (head)
new(0x744) ; latency array → [rbx+0]
[rbx+0x10] = 0x1d1 ; latency cap = 465
memset(latency, 0xff, 0x744)
[rbx+0x08] = 0x1d1 ; latency size = 465
new(0x2b98) ; grid body → [rbx+0x18]
[rbx+0x28] = 0x1d1 ; grid cap = 465
loop r13 = 0x10 .. 0x2ba8 step 0x18: ; 465 rows, 24-B stride
new(0x7c) ; row data = 31 int32
vxorps + 4× vmovups ; zero-init 124 B
[row+0x10] = 0x1f ; row cap = 31
[row+0x08] = 0x1f ; row size = 31
[rbx+0x20] = 0x1d1 ; grid outer count = 465
; then 465 latency stores + 285 grid-cell stores follow
```text
> **注意 —** 该构造函数支撑了符号清晰的 accessor `xla::ghostlite::GhostlitePerformance::GetResourceUsage` / `GetResources` / `GetLatency`,所以二进制中的*类*名是正确的;只有 GF 变体的*构造函数*未命名(`sub_1C8D3740`)。具名 ctor 符号 `_ZN3xla9ghostlite20GhostlitePerformanceC1Ev` 属于 **GL** 变体(`@0x1c8cbc80`,476 行)。这两个函数不同,分配大小不同(`0x744`/`0x2b98` 对 `0x770`/`0x2ca0`),单元格值也不同;请按代确认。
### 存储计数
构造函数正好发出 **750** 个 `mov DWORD PTR [reg+disp], imm` 存储:465 个延迟项 + 285 个网格单元格。每个延迟存储都由 `cmp [rbx+8], idx; jbe <trap>` 保护,并在文件相对偏移 `idx*4` 处写入 `latency[idx]`,这把延迟数组索引固定为稠密的 `0..464`。例如,指令 `0x151` 的延迟存储是 `mov dword ptr [rax+0x544], 0x7f`,而 `0x544 = 0x151 * 4`,所以 `latency[0x151] = 127`。这种直接偏移寻址是在字节级证明:对每个已定价行,**外层网格索引就是 LloOpcode**(分类器 `GetGhostliteInstruction` 在这些行上是恒等映射)。
---
## GetResourceUsage 读取路径
### 目的
`GetResourceUsage(instr, res)` 是每个网格读取者都会经过的唯一 accessor。它与 GL accessor 以及网格家族其余成员**字节完全相同**:两次边界检查、用 `lea` 计算 24 字节行跨度、直接读取单元格。因此一个描述覆盖 GF、GL、VF 和 PF。
### 算法
```c
// xla::ghostlite::GhostlitePerformance::GetResourceUsage @0x1c8d3700
__int64 GetResourceUsage(perf, u32 instr, u8 res) {
if (perf[0x20] <= instr) // outer bound: grid_outer_count = 465
BUG(); // ud2
row_base = perf[0x18]; // grid body ptr
v = 3 * instr; // lea rax+rax*2
if (row_base[8*v + 8] <= res) // inner bound: row.size = 31
BUG();
return *(u32*)(row_base[8*v] + 4*res); // grid[instr][res]
}8 * (3 * instr) 是 24 字节行跨度(每个 std::vector<int> 头部为 24 字节);row_base[8*v] 是该行的 data 指针,row_base[8*v+8] 是其 size。内联孪生 sub_1C8DA1A0 从成本表吞吐分发处到达,与它逐指令相同。
GetLatency(instr) @0x1c8d36e0 是更简单的同级函数:if (perf[1] <= instr) BUG(); return latency[instr](边界 [perf+8],返回调度器把 true-dependency edge 提升到的流水线深度)。
// xla::ghostlite::GhostlitePerformance::GetLatency @0x1c8d36e0
__int64 GetLatency(perf, u32 instr) {
if (perf[1] <= instr) BUG(); // latency_size = 465
return *(u32*)(perf[0] + 4*instr);
}
```text
> **陷阱 —** 外层索引是 `GhostlitePerformance::Instruction`,即按代分类器 `GetGhostliteInstruction @0x1c8b1740` 的输出(对 WORD 表二分搜索,范围以 258 种子化,通过 GOT relocation 到达),**不是**从指令 word 读出的原始 LLO opcode。对于已定价行,分类器解析为与 LloOpcode 相同的序号(由上面的 `latency[0x151]` 直接偏移存储证明),所以这些行的轴*就是* opcode;但如果重新实现时不经过分类器而直接用原始 opcode 索引网格,会把未定价行和 MXU fan-out 行索引错。
### 列顺序 — `GetResources`
`GetResources()` `@0x1c8d36c0` 返回静态 `kResources` 字节数组 `@0xb43cdc4`(`lea` 目标,`edx = 0x1f = 31`):按填充 / 遍历顺序排列的 31 个资源索引。二进制中读取的字节:
```text
GhostlitePerformance kResources @0xb43cdc4 (31 B) — shared by GL and GF:
1d 1c 06 03 04 1a 07 08 09 0a 14 10 18 1e 0b 11 00 19 12 13 0c 15 0d 16 0e 17 1b 01 02 05 0f这是 {0..30} 的一个排列(31 个索引全部出现且没有重复)。Xlu deposit 索引 0x10 位于遍历位置 11(数组以 …02 05 0f 结尾,即 res 0x0f 是最后访问的列)。GetResourceLatency @0x1c8b1e60 迭代该数组:它调用 GetResources(),然后对每列循环调用 GetResourceUsage(instr, kResources[i]),把一行归约为单个每指令延迟(带有按列 overlap 规则:多数列取简单 max,MXU 资源会触发致命日志 "Did not expected to have MXU resource for ",res 0x19 带有特殊 FIFO-push/pop 调整)。
注意 — 二进制中只有一个
xla::ghostlite::GhostlitePerformance::GetResources()::kResources符号,位于@0xb43cdc4。GL(476 行)和 GF(465 行)实例都是同一个类,并从同一个GetResources方法返回这个同一数组;它们没有不同的按代排列。相邻地址上的同胞类有自己的数组:PufferfishPerformance::kResources @0xb43cd94(20 B)、ViperfishPerformance::kResources @0xb43cda8(28 B)。地址0xb43cde3只是0xb43cdc4 + 0x1f,也就是 31 项 GhostlitePerformance 数组之后的下一个字节,而不是第二个数组。请把列顺序绑定到@0xb43cdc4。
31 个资源列
目的
网格的内轴是 GhostlitePerformance::Resource,这是一个含 31 个值的 intra-op EUP / cross-lane / Xlu / matrix-result 微流水线端口枚举。二进制中没有 Resource::ToString,所以这些列按功能命名:通过读取哪些 LLO 指令类向每列 deposit 周期(外层索引为 opcode),并用两个具名 accessor GetXluPathReservation 和 GetResourceLatency 锚定。这些名字在含义上足以重新实现(说明每列保留哪个物理端口),但不是字面符号名。
注意 — 这个 31 宽的
GhostlitePerformance::Resource枚举不同于 23 槽的按 bundleResourceVector(资源枚举),层级更低。该网格为 intra-op 微流水线阶段占用定价;ResourceVector是更高层成本模型 deposit 到的按 bundle 功能单元累加器。kResources给出的是网格的列遍历顺序,而不是ResourceVector槽顺序。
按占用方 LLO 类划分的列
| col | 角色(功能名) | 占用方 LLO 区段(GF) | 示例单元格 |
|---|---|---|---|
| r0 | 地址 / 索引 load-store 生成 | kParameterAddress, kVectorLoadIndexed | 2 |
| r1 | vector load/store sublane-shuffle (Cmem) | kVectorLoadSublaneShuffle, kVectorLoadIndexed | 2 |
| r2 | scalar store / sync-flag (SFRF) | kScalarStore, kVectorSyncFlag{Add,Set}* | 1, 2 |
| r3..r6 | EUP transcendental-prep 阶段 A–D | kVector{Subtract,Pack,Tanh,Pow2,Rsqrt,…} F32/Bf16 | 16/4/9/3, 20/8/13/7 |
| r7 | EUP gain-latch / AndPop setup | kVector{SigShft,Sinq,Cosq,Erf}F32AndPop | 52 |
| r8..r11 | EUP-result-pop FIFO 阶段 A–D | kVector{Tanh,Pow2,Reciprocal,…}Bf16AndPop | 2/1/3/9, 6/5/7/13 |
| r12..r15 | cross-lane / transpose-result 阶段 A–D | kVector{EupResult,XlaneResult}*, kVectorMultiply* | 35/34/40/18 |
| r16 | Xlu / matrix-result deposit 端口 | kVectorCmemResult, kVectorMatresAdd, kVectorTransposeClear, kVectorMultiplyF32 | 4 |
| r17..r20 | mxres-result 子阶段 A–D(cmem/matres 扩展) | kVectorCmemResult/MatresAdd/TransposeClear | 40/44/25/3 |
| r21..r24 | pack / extract / U64-multiply 阶段 A–D | kVector{Xor,PseudoPack,MultiplyU64,Extract}* | 21/50/50/32 |
| r25 | scalar-move | kScalarMove | 1 |
| r26..r27 | vector-min (bf16 / u32) | kVectorMinimum{Bf16,U32} | 4, 1 |
| r28..r30 | BarnaCore scalar-sync-wait / public-access read | kVsetptstate, kBarnaCoreScalarWait{Lt,Ge,Gt,Eq,Ne}*, …SyncPublicAccessRead | 5/7/3 |
Xlu/matrix-result deposit 列(res 0x10)是卷积成本模型通过吞吐分发读取的唯一列,且其单元格统一为 4。它的命名是确定的,因为两个独立锚点一致:反汇编为每个 matrix-result op 向其中存储 4,专用 accessor GetXluPathReservation(GL 孪生)也正是读取这一类列。
Xlu Deposit 列与吞吐读取
目的
有一列携带 matrix-result (Xlu) 吞吐,卷积成本模型把它作为 R[2] 项读取。在 GF 上,成本表 helper 读取 res 0x10 (= 16);在 GL 上,对应 helper 读取 res 0x0f (= 15)。这是两个 GetCyclesForThroughputHelper 函数体之间的硬编码差异,不是网格或 kResources(共享)的差异:每个 helper 都把自己的字面量 res 传给同一个 GetResourceUsage。构造函数对每个 matrix-result / Cmem / transpose-result 指令都向 res-0x10 单元格写入 4:
; per matrix-result row in sub_1C8D3740:
mov dword ptr [row + 0x40], 4 ; row[0x40] = grid[instr][res 0x10] = 4
```text
(`0x40 = res 16 * 4 bytes`。)六个卷积相关 mxres 行在 `@0x1c8d7722 / 7866 / 79aa / 7bea / 7ce6 / 82ce` 写入该单元格;cross-lane 区段(0x14d..0x158)中还有许多 matrix-result 行也写入它,总计 28 个单元格携带 res `0x10`。
### 成本表绑定
GF 成本路径**不是**通过 `LatencyTableGhostlite::GetXluPathReservation` 到达 res `0x10`(该 accessor 读取 res `0x0f`,见下方对比)。它通过吞吐分发 `GfcCycleTable::GetCyclesForThroughputHelper @0x1c89f400` 到达;其中 Xlu-family case 以 `res = 16` 调用内联 `GetResourceUsage` 孪生:
```c
// GfcCycleTable::GetCyclesForThroughputHelper @0x1c89f400 (Xlu/mxres cases)
case 23: instr = 344 /*0x158*/; goto xlu; // CT 0x17
case 27: instr = 351 /*0x15f*/; goto xlu; // CT 0x1b
case 28: instr = 337 /*0x151*/; goto xlu; // CT 0x1c
case 29: instr = 339 /*0x153*/; goto xlu; // CT 0x1d
case 30: instr = 341 /*0x155*/; goto xlu; // CT 0x1e
case 31: instr = 345 /*0x159*/; goto xlu; // CT 0x1f
xlu: result = sub_1C8DA1A0(perf /*GfcCycleTable+0x10*/, instr, 16); // res 0x10因此,对全部六个 case,thru(CT 0x17/0x1b/0x1c/0x1d/0x1e/0x1f) = grid[instr][0x10] = 4。六个 mxres 行及其完整已填充单元格(从构造函数字节精确读取)如下:
Instruction | LLO 名称 | GetLatency | 已填充单元格 (res:cy) |
|---|---|---|---|
0x151 | kVectorCmemResult | 127 | r16:4 r17:40 r18:44 r19:25 r20:3 |
0x153 | kVectorMatresAdd | 101 | r16:4 r17:8 r18:11 r19:35 r20:3 |
0x155 | kVectorTransposeClear | 113 | r16:4 r17:4 r18:20 r19:39 r20:3 |
0x158 | kVectorMultiplyF32 | 127 | r12:35 r13:34 r14:40 r15:18 r16:4 |
0x159 | kVectorMultiplyU32 | 114 | r12:35 r13:34 r14:40 r15:18 r16:4 |
0x15f | kVectorXorU32 | 141 | r16:4 r21:21 r22:50 r23:50 r24:32 |
对比 —
LatencyTableGhostlite::GetXluPathReservation @0x1c8b21c0在直接处理kVectorSetPermutePattern(opcode0x8b= 139,返回3·(is_transpose != 0) + 1)之后,尾调用GetResourceUsage(perf, GetGhostliteInstruction(v), 15),即 res0x0f。这个LatencyTableGhostliteaccessor(共享的ghostlite命名空间)不是 GF 卷积路径;GF convR[2]由GfcCycleTable::GetCyclesForThroughputHelper以 res0x10(16) 读取,而GlcCycleTable::GetCyclesForThroughputHelper @0x1c89ed20读取 res0x0f(15)。因此 Xlu 列索引按成本表 helper 绑定,而不是按kResources数组绑定:GF helper 为0x10,GL helper 为0x0f,二者都索引同一个共享 31 列网格。
conv R[2] 项
6acc60406 卷积成本三元组现在完全数值化。另两个项来自 GF MXU reservation 矩阵:
R[0]matpush = matpush_count ·array[8]= 2 (bf16) / 4 (fp8)R[1]matmul = op_count ·array[3]· 0.5 / Target / EPF,其中array[3]= 4 (bf16) / 8 (fp8)R[2]Xlu =grid[mxres-instr][0x10]· ChunksPerTile · rem = 4 · ChunksPerTile · rem(与 dtype 无关)
行分类与列填充
目的
465 行中只有约 92 行被填充;该网格是稀疏的。已填充行聚集成可识别的指令区段,镜像 EUP / matrix-result 微流水线。本节给出区段结构(不是全部 465 行;稠密区段是 EUP/transcendental 和 matrix-result 簇,opcode 0x121..0x16x)以及每列单元格计数。
区段(GF)
| 区段 | 行 (GhPerf::Instruction) | 列 | 延迟 | 角色 |
|---|---|---|---|---|
| address / load-store / sync | 0x2d, 0x30, 0x32, 0x78..0x7f | r0..r2 | 1–3 | address gen, scalar store, sync-flag |
| EUP transcendental-prep | 0x121..0x13b | r3..r6 | 212 / 204 | 按 dtype 的 prep 阶段(携带 {4 bf16 / 8 fp8}) |
| EUP gain-push setup | 0x140..0x143 | r7 | 1 | AndPop gain-latch setup (52) |
| EUP-result-pop FIFO | 0x144..0x14b | r8..r11 | 4 / 8 | transcendental 之后的 drain 阶段 |
| cross-lane / transpose result | 0x14c..0x159 | r12..r15 | 1, 114–127 | permute / rotate / multiply result 阶段 |
| Xlu / matrix-result deposit | 0x14d..0x158 (matres ops) | r16 | — | conv R[2] 单元格 (= 4) |
| mxres-result 子阶段 | 0x151/0x153/0x155/0x157 | r17..r20 | 101–141 | cmem / matres / transpose 扩展 |
| pack / extract / U64 | 0x15f..0x168 | r21..r24 | 141, 145 | Xor/PseudoPack/MultiplyU64/Extract |
| tail (move / min / BarnaCore) | 0x17b, 0x1a1..0x1b6 | r25..r30 | 1, 3, 7 | scalar-move, vector-min, BarnaCore scalar-sync-wait |
每列单元格计数(GF,总计 285)
r0:2 r1:2 r2:7 r3:15 r4:27 r5:27 r6:27 r7:4 r8:8 r9:8 r10:8 r11:8
r12:11 r13:11 r14:11 r15:11 r16:28 r17:4 r18:4 r19:4 r20:4
r21:10 r22:10 r23:10 r24:10 r25:1 r26:1 r27:1 r28:4 r29:6 r30:1
```text
EUP-prep 阶段 r4/r5/r6(各 27 个单元格)和 Xlu deposit r16(28 个单元格)是填充最多的列;该网格本质上主要是 EUP/transcendental + matrix-result 定价表。注意 EUP-prep 列 r4 携带与 `MxuLatencyTable` matmul 单元格 `array[3]` 相同的按 dtype 量级 `{4 bf16 / 8 fp8}`([MXU 延迟:GF](mxu-latency-gf.md)):两个成本表在按 dtype 的吞吐整数上是一致的。
---
## `0xff` 默认回退
### 目的
延迟数组在任何存储之前会被 `memset` 为 `0xff` (255)。在宽 GhPerf 代(GL/GF)上,之后只有已定价行会被覆盖;GF 上约 465 行中的 92 行。其他约 373 行保持 `latency = 255`,其网格行保持全零。这些指令**不是**由该网格定价;它们的成本来自另一条路径。
### 回退路径
某条指令的 `GhostlitePerformance::Instruction` 行若未写入,其成本通过跨代不变的 `CycleTable::GetResource` op→slot 表(`@0x1c89ce20`,表 `@0xb438aec`)加上按代的 `GetCyclesForThroughput` 解析,并 deposit 到 23 槽 `ResourceVector`([资源枚举](resource-enum.md));`JfCycleTable` 对未定价 op 的默认值为 1 个周期。该网格只用于它实际定价的 EUP / matrix-result / cross-lane 家族。
> **陷阱 —** `0xff` 默认值是真实可观测的值,而不是读取路径会过滤的 sentinel。对未写入行调用 `GetLatency(instr)` 会返回 255,这是有意设置的较大流水线深度,防止未识别 op 被过于激进地调度。重新实现若把延迟数组零初始化(而不是填充 `0xff`),会低估网格没有显式定价的每条指令,并且不会有边界错误提示该问题。请初始化为 255。
---
## GF 与 GL — 两个 GhPerf 网格
GF(`6acc60406`,v7)和 GL(Ghostlite,v6e)网格是**同一个 `GhostlitePerformance` 类**,具有相同方法和同一个 `kResources` 数组,但由两个不同构造函数构建为两个不同堆实例:
| | GF (`6acc60406` / TPU7x) | GL (Ghostlite / v6e) |
|---|---|---|
| 构造函数 | `sub_1C8D3740`(未命名) | `GhostlitePerformanceC1` `@0x1c8cbc80` |
| 延迟分配 | `new 0x744` → 465 int32 | `new 0x770` → 476 int32 |
| 网格分配 | `new 0x2b98` → 465 × 24 | `new 0x2ca0` → 476 × 24 |
| 行宽 | `new 0x7c` = 31 | `new 0x7c` = 31 |
| 已填充 | 285 个单元格 / 92 行 | 358 个单元格 / 132 行 |
| `kResources` | `@0xb43cdc4`(一个共享数组) | `@0xb43cdc4`(同一数组) |
| helper 读取的 Xlu res | res `0x10`(`GfcCycleTable` helper) | res `0x0f`(`GlcCycleTable` helper) |
| EUP/transcendental 延迟 | 212 (bf16) / 204 (fp8/F32) | 192 / 182 |
| 所有者 cycle table | `GfcCycleTable` `@0x1c89eec0` | `GlcCycleTable` `@0x1c89e7e0` |
GL 多出的 **+11 行**(476 对 465)来自 GL ctor 的 `new 0x770`/`new 0x2ca0`(476 项)对 GF 的 `new 0x744`/`new 0x2b98`(465 项);GL ctor 在 `[rax+0x744]` 写入 `latency[465]`,这个索引对 GF 的 465 项数组越界。额外 opcode 是位于 GF 最后有效 opcode 之后的 v6e shift/saturate 和 BarnaCore-wait 行;`6acc60406` 去掉了它们。二者共享类契约(对象布局、三个 accessor 方法、单一 `kResources`、31 宽枚举、EUP/matrix-result 区段结构)以及 conv `R[2]` 值 4;不同的是单元格整数、基础延迟、行数,以及每个成本表 helper 传给共享 `GetResourceUsage` 的 `res` 字面量。
---
## 示例 — 一个 `6acc60406` bf16 Conv Xlu Deposit
一个 `6acc60406` bf16 卷积通过读取 `kVectorCmemResult`(`Instruction 0x151`,CT `0x1c` 的 conv mxres op)来为其 matrix-result (Xlu) 项定价:
1. 成本表分发 `GfcCycleTable::GetCyclesForThroughputHelper @0x1c89f400` 的 case 28 设置 `instr = 0x151`、`res = 16`。
2. `GetResourceUsage(perf, 0x151, 16)` 边界检查 `0x151 < 465` 和 `16 < 31`,计算 `row = grid + 0x151*24`,并返回 `row.data[16] = 4`。
3. conv 成本模型相乘:`R[2] = 4 · ChunksPerTile · rem`。
4. 结合 MXU reservation 矩阵([MXU 延迟:GF](mxu-latency-gf.md)):bf16 下 `R[0] = 2`、`R[1] = 4`,三元组为 `{2, 4, 4}`。
该 op 的 `GetLatency(0x151) = 127` 另行限制依赖边的流水线深度。对于 fp8,matmul/matpush 两项加倍为 `{4, 8}`,但 Xlu 单元格保持 4;该网格单元格与 dtype 无关。
---
## 函数与数据映射
| 名称 | 地址 | 角色 |
|---|---|---|
| `GfcCycleTable::GfcCycleTable` | `0x1c89eec0` | 分配 `0x30` perf 网格 + `0xa0` MxuLatency |
| GF `GhostlitePerformance` ctor | `0x1c8d3740` | 填充 465 个 latency + 285 个 grid cell(未命名;不可反编译) |
| `GhostlitePerformance::GetResourceUsage` | `0x1c8d3700` | `grid[instr][res]`;外层 `[+0x20]`,24-B stride,内层 `[row+8]` |
| 内联 `GetResourceUsage` 孪生 | `0x1c8da1a0` | 字节完全相同;CT-throughput 调用目标 |
| `GhostlitePerformance::GetLatency` | `0x1c8d36e0` | `latency[instr]`,边界 `[+0x8]` |
| `GhostlitePerformance::GetResources` | `0x1c8d36c0` | 返回 `kResources` |
| `GhostlitePerformance::…::kResources` | `0xb43cdc4` | 31 字节列遍历顺序(GL/GF 共享) |
| `GfcCycleTable::GetCyclesForThroughputHelper` | `0x1c89f400` | Xlu case → `GetResourceUsage(instr, 16)` |
| `GetGhostliteInstruction` | `0x1c8b1740` | LloOpcode → `GhPerf::Instruction`(二分搜索) |
| `LatencyTableGhostlite::GetResourceLatency` | `0x1c8b1e60` | 迭代全部 31 列,按列 overlap 归约 |
| `LatencyTableGhostlite::GetXluPathReservation` | `0x1c8b21c0` | `ghostlite` accessor — 读取 res `0x0f`;不是 GF conv 路径 |
| `CycleTable::GetResource` | `0x1c89ce20` | `0xff` 默认行的回退 op→slot 表 |
---
## 交叉引用
- [性能家族概览](performance-overview.md) — 网格家族对象布局、共享的 `GetResourceUsage` 读取路径,以及资源数量演进
- [性能:GL (GhPerf 476×31)](performance-gl-ghperf.md) — Ghostlite v6e 网格;+11 行、Xlu deposit res `0x0f`、基础延迟 192/182
- [MXU 延迟:GF (6acc60406)](mxu-latency-gf.md) — `MxuLatencyTable` reservation 矩阵、conv `R[0]`/`R[1]` 项,以及 `ComputeDmaLevels`
- [资源枚举](resource-enum.md) — 23 槽的按 bundle `ResourceVector`,不同于 31 宽的 `GhostlitePerformance::Resource` 微流水线枚举
- [MXU 槽](../isa/slot-mxu.md) — matrix-result 资源列保留的物理 MXU 子单元