转置保留延迟
本页中的每个地址、偏移、序号和立即数,都是从
libtpu-0.0.40-cp314wheel 中的libtpu.so逐字节读取的(BuildID md589edbbe81c5b328a958fe628a9f2207d,未 stripped —nm -C可解析每个方法)。.text与.rodata的 VMA 等于其文件偏移(.rodata段位于0x84a0000);.data.rel.roVMA − 0x200000 = 文件偏移。其他 libtpu 构建会有所不同。
摘要
XLU 冲突惩罚表是一个静态的 6×6×3 int32 网格,用于为两个相邻跨 lane 操作之间的最坏情况结构冒险定价。该表无法捕获一种成本:跨 lane fabric 会被一次转置占用多久,而这个占用时间取决于转置的数据形状(其高度 × 宽度)以及其 VxposeMode 的打包密度。XposeXLUReservationLatency 正是提供这一动态项的机制 — 它是在转置序列的最终转置出边上获取的一个计算出来的(而非查表得到的)延迟,会在静态冲突惩罚单元格之上额外加上依赖形状的占用周期数。
参照框架与 MXU 延迟模型使用的 MCSchedModel 风格保留思想相同,但它专门针对跨 lane 单元,并针对上游 LLVM 没有对应物的一个细节:向量转置每个周期移动固定数量的打包元素,而这个吞吐量是操作数元素宽度的函数。未打包的 32-bit 转置(B32)每个 lane 每周期移动 1 个元素;Compressed B8 转置移动 4 个。因此,必须通过跨 lane 引擎排出的非对角元素数量 (width − height),在 B8 中需要的占用周期比 B32 少四倍 — 而这个比率正是 ElementCount(VxposeMode),也就是本页钉住的打包因子。
本页记录三个由字节锚定的部分:
XposeXLUReservationLatency— 动态转置保留公式,覆盖三种延迟表形状(base Jellyfish / GhostLite、Viperfish、Pufferfish),包括选择该公式并把转置形状传入的高层分发器。VxposeMode— 5 个序号的转置模式枚举、它的ElementCount打包因子、存储它的LloInstruction字节、VxposeMode → XluInstrType子表,以及按Target划分的SupportsVectorXpose掩码。MxuStat— 贪心最小 makespan 装箱器读写的每 MXU 运行状态记录。MxuStat记录转置/锁存序列占用的 busy-interval 状态;其布局和区间扩展成本函数在这里钉住。
对于重新实现,契约是:
- 按 generation 的
XposeXLUReservationLatency闭式形式:static_cell + max(0, shape_term),其中 base 形式会将形状项除以2 × ElementCount(vxpose),VF/PF 去掉该除数并增加一个+7设置常数(PF 还会额外取下限)。 - 在
IsFinalTransposeInSequence上选择动态路径,并从最终转置 op 解析vxpose_mode/ height / width 的分发器。 VxposeMode序号{B32, Compressed B16, Compressed B8, Segmented B32, Segmented B16},ElementCount表{1,2,4,1,2},以及+0x44处的LloInstruction字节。- 40 字节的
MxuStat布局,以及LatchLatencyChangeAfterAdding区间扩展增量c + x − y2。
| 动态保留(base/GL) | xla::jellyfish::XluConflictPenaltyTable::XposeXLUReservationLatency @0x1c8a0640 |
| 动态保留(Viperfish) | xla::viperfish::LatencyTableViperfish::XposeXLUReservationLatency @0x1c8a4e60(vtable +0x10) |
| 动态保留(Pufferfish) | xla::pufferfish::LatencyTablePufferfish::XposeXLUReservationLatency @0x1c8a13e0(vtable +0x10) |
| 分发器 | XluConflictPenaltyBetween(LloValue*, LloValue*) @0x1c8a01c0 |
| 原始单元格读取器 | XluConflictPenaltyBetween(XluInstrType, XluInstrType, uint) @0x1c8a0180 |
IsTranspose(XluInstrType) | @0x1c8a04e0 — (t − 2) < 3 ⇒ {2,3,4} |
VxposeMode 字符串 | xla::jellyfish::VxposeModeString @0x1d629f60(5 种情况) |
ElementCount(VxposeMode) | @0x1d62a140 — 0xb53c830 处的 int[5] 表 = {1,2,4,1,2} |
vxpose_mode() 访问器 | LloInstruction::vxpose_mode @0x1d4e7440 — 对 op 0xa6/0xa7 读取 byte[inst + 0x44] |
MxuStat 初始化 / 选择 | AssignMxusForSequenceGroupInternal @0x10f77ca0(初始化 @0x10f77d30,选择 @0x10f784d0) |
| 区间扩展成本 | MxuStat::LatchLatencyChangeAfterAdding @0x10f7f3e0;再平衡 LatencyChangeIfMoveTo @0x10f7fb40 |
| 置信度 | CONFIRMED(字节锚定),除非某行另有说明 |
两条转置占用周期路径
XLU 边模型会在两条路径之一上收取转置占用周期,选择依据是较早的 op 是否为一个转置序列的最终转置:
| 路径 | 选择条件 | 成本 | 函数 |
|---|---|---|---|
| 静态 | 非最终 / op 间冒险 | XluConflictPenaltyTable[from][to][mxuIdx] — 一个固定的 6×6×3 int32 单元格 | 冲突惩罚表 |
| 动态 | 较早的 op IsFinalTransposeInSequence | 静态单元格加上一个数据形状占用项 | XposeXLUReservationLatency(本页) |
动态路径不会替代静态单元格 — 它读取同一个单元格并加上形状项。静态表为结构性 FIFO 冒险定价;动态项为跨 lane datapath 保持占用以排出转置非对角元素的额外周期定价。(第三种消费侧边 — LatencyBetweenXposeInstrAndResult,即下游 op 为读取最终转置结果所支付的延迟 — 位于 @0x1c8a06e0/@0x1c8a4fa0/@0x1c8a1520,vtable +0x30;它随冲突惩罚表一起记录。)
XposeXLUReservationLatency
目的
XposeXLUReservationLatency 是延迟表 vtable 槽 +0x10 处的一个虚方法。它的 demangled 签名为:
long XposeXLUReservationLatency(VxposeMode vx, XluInstrType from, XluInstrType to,
unsigned int mxuIdx, int height, int width) const;vx 是转置的 VxposeMode(在 base 路径上驱动打包除数);from/to 是较早(转置)和较晚 op 的 XluInstrType;mxuIdx 是物理 MXU 实例索引(unit_id & 3,约束 < 3),用于选择静态单元格的第三维;height/width 是转置矩阵的维度,二者都从最终转置 op A 解析。
分发器
XluConflictPenaltyBetween(LloValue* A, LloValue* B) @0x1c8a01c0 是高层入口。它通过 GetXluInstrType 解析两个 op 的 XluInstrType,断言二者都携带有效 unit_id(unit_id == later->unit_id(),CHECK 行 245/246/248),并在 A 是最终转置时经由 vtable 走动态路径。逐字节如下:
// XluConflictPenaltyBetween(LloValue* A /*earlier*/, LloValue* B /*later*/) @0x1c8a01c0
unsigned fromType = GetXluInstrType(A); // @0x1c89ff20
unsigned toType = GetXluInstrType(B);
// unit_id is the 2-bit field in WORD[A+0xb] bits 8-9, gated by valid bit 10 (& 0x400):
unsigned mxuIdx = (HIBYTE(*(u16*)(A + 11)) & 3); // asserts WORD[A+0xb] & 0x400, lines 245/248
LloInstruction* a = LloInstruction::FromValue(A);
if (a->IsFinalTransposeInSequence()) { // @0x1c8a025b
VxposeMode vx = a->vxpose_mode(); // @0x1c8a0267
CHECK(IsTranspose(GetXluInstrType(A))); // else FATAL line 322
int h = a->GetTransposeHeight(); // @0x1c8a0292
CHECK(IsTranspose(GetXluInstrType(A))); // redundant guard, FATAL line 328
int w = a->GetTransposeWidth(); // @0x1c8a02b9
return (*(this->vtable + 0x10))(this, vx, fromType, toType, mxuIdx, h, w); // virtual @0x1c8a02d7
}
// non-final: read the static cell directly (the other path)
return *((u32*)this + 18*fromType + 3*toType + mxuIdx + 2); // == base + 72*from + 12*to + 4*mxuIdx + 8vx、height 和 width 全部来自最终转置 op A,从不来自 B。mxuIdx 是 MXU 实例轴(端口不对称性),与 vx(数据格式轴)是分离的关注点 — 它们是不同维度,只是容易混淆,因为二者最终都会成为同一个调用的参数(见 VxposeMode 与单元格索引说明)。
按 Generation 划分的公式
三个延迟表子类都会重写 vtable +0x10 槽。它们共享静态单元格读取,只在塑造占用项的方式上不同。来自反编译的逐字节形式如下:
// base Jellyfish / GhostLite @0x1c8a0640
long XposeXLUReservationLatency(vx, from, to, mxuIdx, height, width) {
if ((unsigned)(from - 2) >= 3) FATAL("IsTranspose(earlier)", latency_table.cc:335);
if (to >= 6) ud1; // bound check
if (mxuIdx >= 3) ud1; // bound check
int cell = *(int*)(this + 72*from + 12*to + 4*mxuIdx + 8); // raw static cell
int shape = (width - height) / (int)(2 * ElementCount(vx)); // SIGNED idiv @0x1c8a0690
if (shape <= 0) shape = 0; // cmovle to 0
return cell + shape; // NO additive constant
}
// Viperfish @0x1c8a4e60 (vtable +0x10, thunk @0x1c8a4f00)
long XposeXLUReservationLatency(vx, from, to, mxuIdx, height, width) {
if (!IsTranspose(from)) FATAL("IsTranspose(earlier)", latency_table_vf.cc:1038);
int cell = XluConflictPenaltyBetween(from, to, mxuIdx); // == raw cell @0x1c8a0180
int shape = width - height;
if (shape <= 0) shape = 0; // cmovg
return cell + shape + 7; // +7 transpose-setup; NO throughput divisor
}
// Pufferfish @0x1c8a13e0 (vtable +0x10, thunk @0x1c8a1480)
long XposeXLUReservationLatency(vx, from, to, mxuIdx, height, width) {
if (!IsTranspose(from)) FATAL("IsTranspose(earlier)", latency_table_pf.cc:62);
int tmp = (width - height) + XluConflictPenaltyBetween(from, to, mxuIdx); // NO clamp, NO divisor
if (tmp < -5) tmp = -6; // cmp $0xfffffffb / mov $0xfffffffa / cmovl
return tmp + 7; // floor: result >= 1 (when tmp<-5 -> 1)
}边界(to < 6、mxuIdx < 3)和单元格地址算术,与静态表读取器 XluConflictPenaltyBetween(from, to, mxuIdx) @0x1c8a0180 逐字节相同(*(base + 72*from + 12*to + 4*mxuIdx + 8))。base 形式内联单元格读取;VF/PF 调用访问器 — 但读取的是同一个单元格。from − 2 >= 3 测试是内联的 IsTranspose:转置 op 必须是 XluInstrType ∈ {2,3,4}。
解释
| gen | 形状项 | 常数 | 下限 |
|---|---|---|---|
| base / GL | max(0, (width − height) / (2·ElementCount(vx))) | 无 | 由 max(0,·) 隐含 ≥ 0 |
| Viperfish | max(0, width − height) | +7 | ≥ 7 |
| Pufferfish | (width − height)(不 clamp) | +7 | ≥ 1(通过 tmp ≥ −6) |
- 主导成本是静态冲突惩罚单元格 — 最坏情况结构冒险。
- 在 base/GL 路径上,占用加数是非对角元素数量
(width − height)除以每模式转置吞吐量2 × ElementCount(vx)。2·ElementCount(vx) = {2,4,8,2,4}是跨 lane 引擎在该模式下每周期移动的元素数;(width − height)是必须通过它排出的元素数;二者的商是额外占用周期。最宽的未打包B32(除数 2)成本最高;密集打包的B8(除数 8)成本最低 — 打包因子就是吞吐速度提升。 - 方形转置(
width == height)只支付静态单元格(VF/PF 上再加上按 generation 的+7);形状项 clamp 到 0。 - VF 和 PF 去掉除数(将转置建模为 1 element/cycle),并改为增加一个平坦的
+7转置设置常数。PF 还会额外取下限:如果cell + (width − height) < −5,它会 clamp 到−6,因此返回值≥ 1。这可以防止深度负值的静态单元格把保留压到低于一个周期。
数值示例
Base / GhostLite — 一个最终 Compressed B8 转置(vx = 2,ElementCount = 4)馈入一个 permute,height = 8,width = 512,mxuIdx = 0:
shape = (512 - 8) / (2*4) = 504 / 8 = 63 result = cell + 63同一个转置若为未打包 B32(vx = 0,ElementCount = 1):
shape = (512 - 8) / (2*1) = 504 / 2 = 252 result = cell + 252B8 打包让相同转置在 XLU 占用周期上便宜 4× — 正好是 ElementCount 比率 4/1。
Viperfish — 一个最终 B32 转置,height = 128,width = 128(方形):
shape = max(0, 128 - 128) = 0 result = cell + 0 + 7 = cell + 7方形转置只支付静态单元格加 7 周期设置;高/宽不等的转置会再支付 (width − height)。
VxposeMode
目的
VxposeMode 是转置数据格式枚举:它命名元素宽度以及该转置是否为 segmented,并且是 base 保留公式中每模式吞吐量除数的唯一输入。它作为一个单字节字段存储在转置 LloInstruction 上。
枚举
五个序号,经三种独立方式确认 — 字符串表、ElementCount 打包因子以及 XluInstrType 子表全部一致。来自 VxposeModeString @0x1d629f60(五个 switch case,内联字符串写入)、ElementCount @0x1d62a140(0xb53c830 处的 int[5],xxd = 01 00 00 00 02 00 00 00 04 00 00 00 01 00 00 00 02 00 00 00),以及 0xa2dcce0 处的 GetXluInstrType 转置子表(xxd = 02 00 00 00 03 00 00 00 04 00 00 00 02 00 00 00):
| 序号 | VxposeModeString | ElementCount | 每个 32-bit lane 的打包元素 | XluInstrType |
|---|---|---|---|---|
| 0 | "B32" | 1 | 1(未打包 32-bit) | 2 = kTransposeB32 |
| 1 | "Compressed B16" | 2 | 2(打包 16-bit) | 3 = kTransposeB16 |
| 2 | "Compressed B8" | 4 | 4(打包 8-bit) | 4 = kTransposeB8 |
| 3 | "Segmented B32" | 1 | 1(segmented 32-bit) | 2 = kTransposeB32 |
| 4 | "Segmented B16" | 2 | 2(segmented 16-bit) | 3 = kTransposeB16(默认;子表大小 4) |
ElementCount 是每个 32-bit lane 中的打包元素数量:B32 → 1、B16 → 2、B8 → 4。字符串表 case 0 将字面量存为三个字节(0x3342 然后 '2' ⇒ "B32");case 1–4 是对命名字面量的 strcpy。该子表对 vx ∈ {0,1,2,3} 直接按 vxpose_mode 索引;GetXluInstrType @0x1c89ff20 读取 subtable[vx],并将 vx ≥ 4 clamp 到 XluInstrType = 3(kTransposeB16),因此 Segmented B16 表现为 kTransposeB16。
存储位置 — vxpose_mode()
LloInstruction::vxpose_mode() @0x1d4e7440 从 instruction 上读取单个字节。逐字节如下:
// LloInstruction::vxpose_mode() @0x1d4e7440
VxposeMode vxpose_mode() const {
if ((WORD[this] & 0xFFFE) == 0xA6) // opcode 0xa6 (Vxpose) or 0xa7 (VxposeBinary)
return BYTE[this + 0x44]; // the VxposeMode byte
FATAL("LloOpcodeIsTranspose(opcode())"); // llo_instruction.cc:3367
}掩码 & 0xFFFE 让该测试覆盖 0xa6(kVectorTranspose)和 0xa7(kVectorTransposeBinary)二者 — 这对 opcode 只在 bit 0 上不同。VxposeMode 是 LloInstruction + 0x44 处的字节,仅对这两个 opcode 有效;在任何其他 opcode 上读取它都会触发硬 FATAL。
按 Target 划分的支持 — SupportsVectorXpose
某个 generation 是否能发出给定 VxposeMode,由 Target::SupportsVectorXpose(VxposeMode) 控制。逐字节来自每个按 generation 重写的版本:
| Target(gen) | SupportsVectorXpose(vx) | 接受 |
|---|---|---|
JellyfishTarget @0x1d48f780 | vx == 0 | 仅 B32 |
GhostliteTarget @0x1d497160 | vx < 3 | B32、Compressed B16、Compressed B8 |
ViperfishTarget @0x1d49a000 | vx != 2 | 除 Compressed B8 外全部 |
PufferfishTarget @0x1d4940a0 | vx != 2 | 除 Compressed B8 外全部 |
Target(base)@0x1d61ce00 | abstract | — |
注意 — PF/VF 的
SupportsVectorXpose掩码是mode != 2:PF/VF 支持除Compressed B8外的每种模式(vx == 2),而不是只支持B8。这与 Pufferfish 转置 emitter 一致,后者会用InvalidArgument("compressed B8 format is not supported on PxC")拒绝Compressed B8。(如果误判setne/sete极性,ICF-folded 的cmp esi,2; retthunk 可能会被读成mode == 2;反编译体是return a2 != 2。)完整模式集见 XLU op 清单。注意 — segmented 模式仅 Pufferfish。 没有 generation 报告
SupportsVectorXpose支持Segmented B32/Segmented B16(vx3/4)— base =vx==0,GL =vx<3,VF/PF =vx!=2,后者确实接受 3/4。segmented ISA 编码只存在于 deepsea PxC(Pufferfish)指令集中;在其他 generation 上,segmented 模式只能通过子表默认臂到达,而不是通过已确认的 emitter 到达。它们的ElementCount{1,2}和XluInstrType映射已钉住,但其保留成本只在 Pufferfish 转置上被执行。
VxposeMode 不是单元格索引
一个微妙陷阱:XposeXLUReservationLatency 接收 vx(一个 VxposeMode)以及 mxuIdx(静态 6×6×3 单元格的第三个索引),二者是不同的轴:
mxuIdx是物理 MXU 实例 id(unit_id & 3,约束< 3)—XluConflictPenaltyTable[from][to][mxuIdx]的第三维,用于建模每端口冒险不对称性。vx是转置数据格式 — 它只在 base 形状除数中馈入ElementCount(vx);它从不索引静态单元格。
静态单元格的第三个索引是 MXU 实例,而不是转置模式。使用 VxposeMode 索引冲突惩罚单元格的重新实现是错误的。
MxuStat — 装箱器运行状态
目的
转置 op 所属的 MXU/latch 序列会由一个贪心最小 makespan 装箱器(AssignMxusForSequenceGroupInternal @0x10f77ca0)分配到物理 MXU。MxuStat 是该装箱器读写的每 MXU 运行状态记录:每个物理 MXU 一个(Jellyfish 有 4 个)。它记录累积 makespan,以及占用该 MXU 的序列组成的按时间排序 map,每个序列都有一个 busy interval — 这是序列放置时转置保留成本所针对的状态。
布局
MxuStat 为 40 字节(sizeof = 0x28),由数组初始化循环 @0x10f77d30(每次迭代写入五个字段,然后前进 5 个 qword = 40 字节)以及计数算术 (end − 40) / 0x28 + 1 @0x10f7910d 逐字节确认:
struct MxuStat { // 40 bytes; one per physical MXU (Jellyfish = 4)
long accumulated_latency; // +0x00 init 0 running per-MXU makespan term (read in the score)
CycleTable* cycle_table; // +0x08 init arg shared back-ref to the CycleTable arg
btree_node* root; // +0x10 init &EmptyNode absl::btree_map<int, SequenceInfo> root
btree_node* rightmost; // +0x18 init &EmptyNode btree rightmost-node cache
size_t size; // +0x20 init 0 btree element count
};初始化循环对每条记录写入:*p = 0(accumulated_latency)、p[1] = cycle_table_arg、p[2] = p[3] = &EmptyNode(VA 0x2181cb90 处的 absl btree empty sentinel)、p[4] = 0(size)。嵌入在 MxuStat + 0x10 的 btree_map<int, SequenceInfo> 以 int 为 key 存储每个序列,并存储其 SequenceInfo 值;每个 btree slot 是一个 0x48 字节的 pair<const int, SequenceInfo>(int key 在 slot+0,value 跟在后面)。成本函数只读取 value 的 busy interval — busy_start 位于 pair +0x38,busy_end 位于 pair +0x40。完整 SequenceInfo 记录(其 latch_latency 和两个 owning vector<int>)记录在 MxuSequence / SequenceInfo;本页只钉住顶层 MxuStat 布局,以及成本模型消费的区间。
成本函数遍历的 btree 节点布局是标准 absl::btree_node:node+0x0a = 元素数量(u8),node+0x0b = is-internal 标志(u8,0 ⇒ leaf),node+0x10 = 第一个 slot(stride 0x48),node+0x130 = child-pointer 数组(仅 internal 节点)。
区间扩展成本 — LatchLatencyChangeAfterAdding
MxuStat::LatchLatencyChangeAfterAdding @0x10f7f3e0 是每个 (MXU, new-sequence) 的增量:当新的 latch/matmul 序列插入其按时间排序的位置时,MXU 的 occupied window 会增长多少额外 busy 周期。它定位 key == arg 的 slot 及其前驱,然后计算区间扩展增量。逐字节如下(尾部 @0x10f7f5d5):
// MxuStat::LatchLatencyChangeAfterAdding(int key, long new_val, long free) @0x10f7f3e0
// locate slot with key==arg -> found_busy_start (= found_slot interval start)
// locate predecessor of key -> pred_busy_end (= pred_slot interval end)
// CHECK_EQ(new_val == pred_slot.latch_latency) // "latch_latency == prev_it->second.latch_latency"
// // FATAL mxu_latency_balancing.cc:236
long c = max(0, new_val - pred_busy_end); // cmovle to 0
long x = max(0, found_busy_start - free); // cmovle to 0
long y2 = max(0, found_busy_start - pred_busy_end); // cmovle to 0
return (x - y2) + c; // the interval-extension delta反编译器从定位到的 btree slot 上按 qword 偏移 9·idx + 9(found_busy_start)和 9·idx + 10(pred_busy_end)读取 busy 字段 — slot stride 为 9 qword = 0x48,也就是 SequenceInfo 区间对。第 236 行的 CHECK_EQ 断言候选的 latch_latency 与前驱记录值匹配。
贪心选择循环
选择循环 @0x10f784d0 会为每个 MxuSequence 选择使结果 makespan 最小的 MXU。逐字节如下:
long best = 0x7FFFFFFFFFFFFFFF; // running min makespan
int argmin = current_best;
for (int i = 0; i < num_mxus; i++) { // num_mxus = Target MXU count (Jellyfish = 4)
long delta = mxus[i].LatchLatencyChangeAfterAdding(key, new_val, free);
long score = delta + free + mxus[i].accumulated_latency; // accumulated = MxuStat+0x00
if (best <= score) argmin = current_index; // cmovle — smaller index wins ties
if (best > score) /* mark improved */ ;
best = min(best, score); // cmovge
/* advance mxus by stride 0x28 */
}
// assign sequence -> argmin MXUMxuStat 条目之间的 stride 是 0x28(40 字节),再次确认了该布局。score 将区间扩展 delta、free-window free 以及 MXU 的 accumulated_latency 相加;结果 makespan 最小的 MXU 获胜,平局偏向较小索引。转置保留延迟会经由为每个序列的 busy interval 播种的 CycleTable 馈入此 makespan。
第二遍再平衡 MxuStat::LatencyChangeIfMoveTo @0x10f7fb40 会重新评估把已放置序列移动到另一个 MXU 的代价(读取同一个 busy_start/busy_end 区间,并在目标处 tail-call LatchLatencyChangeAfterAdding)。它用 FATAL("it != sequences_.end()", mxu_latency_balancing.cc:267) 防护 missing/self move。第 2 遍是迭代到不动点还是只运行一次改进交换尚未钉住(INFERRED single pass)。
函数映射
| 函数 | 地址 | 作用 |
|---|---|---|
jellyfish::…::XposeXLUReservationLatency | 0x1c8a0640 | base/GL 动态保留;cell + max(0, shape/(2·EC)) |
viperfish::…::XposeXLUReservationLatency | 0x1c8a4e60 | VF 重写;cell + max(0, w−h) + 7(thunk 0x1c8a4f00) |
pufferfish::…::XposeXLUReservationLatency | 0x1c8a13e0 | PF 重写;floor-1、+7、无除数(thunk 0x1c8a1480) |
XluConflictPenaltyBetween(LloValue*, LloValue*) | 0x1c8a01c0 | 分发器;在 IsFinalTransposeInSequence 上选择动态路径 |
XluConflictPenaltyBetween(InstrType, InstrType, uint) | 0x1c8a0180 | 原始静态单元格读取器 base + 72·f + 12·t + 4·m + 8 |
IsTranspose(XluInstrType) | 0x1c8a04e0 | (t − 2) < 3 ⇒ {2,3,4} |
GetXluInstrType(LloValue*) | 0x1c89ff20 | op → XluInstrType;转置子表 0xa2dcce0 = {2,3,4,2} |
VxposeModeString(VxposeMode) | 0x1d629f60 | 5-case enum-name 表 |
ElementCount(VxposeMode) | 0x1d62a140 | 0xb53c830 处的 int[5] = {1,2,4,1,2} |
LloInstruction::vxpose_mode() | 0x1d4e7440 | 对 op 0xa6/0xa7 读取 byte[inst + 0x44] |
JellyfishTarget::SupportsVectorXpose | 0x1d48f780 | vx == 0 |
GhostliteTarget::SupportsVectorXpose | 0x1d497160 | vx < 3 |
ViperfishTarget::SupportsVectorXpose | 0x1d49a000 | vx != 2 |
PufferfishTarget::SupportsVectorXpose | 0x1d4940a0 | vx != 2 |
AssignMxusForSequenceGroupInternal | 0x10f77ca0 | 装箱器;初始化 0x10f77d30,选择 0x10f784d0 |
MxuStat::LatchLatencyChangeAfterAdding | 0x10f7f3e0 | 区间扩展增量 c + x − y2(FATAL 236) |
MxuStat::LatencyChangeIfMoveTo | 0x10f7fb40 | 第 2 遍再平衡评分(FATAL 267) |
尚未钉住的内容
- 完整的
SequenceInfo成员清单(+0x08/+0x18处的两个 owningvector<int>,以及+0x00处的latch_latency):布局逐字节精确,但哪个 int-vector 是 instruction-set list、哪个是 result-chunk list,是从构建点来源推断的。记录在 MxuSequence / SequenceInfo。元素语义为 LOW。 - VF/PF 是否有意将转置建模为 1 element/cycle(去掉的
/(2·ElementCount)除数),还是将吞吐量折入按 generation 的+7/floor 常数 — 二者都是字节精确;设计动机是推断的。 CycleTable::Instruction的逐 instruction cycle 访问器([vtable+0x10]),它为每个序列的busy_start/busy_end播种:求和循环是字节精确的,但Instruction记录体和访问器返回值是基于类型名采信的。- 第 2 遍再平衡终止条件(单次改进交换 vs 迭代到不动点):
LatencyChangeIfMoveTo控制流是字节精确的;外层循环边界为 INFERRED single pass。 Segmented B32/B16(vx3/4)保留成本只在 Pufferfish 转置上可达(segmented ISA 仅 PxC);这里尚未由其他 generation 上的已确认 emitter 执行。
交叉引用
- XLU 冲突惩罚表 — 该项所加到的静态
6×6×3单元格、XluInstrType枚举,以及消费侧LatencyBetweenXposeInstrAndResult边。 - XLU Op 清单 — 跨 lane op 家族、转置 slot-fit 谓词中的
VxposeMode/ElementCount几何,以及Vxpose/VxposeBinaryCompressedB16factory。 - XLU Reemit 成本 —
CyclesAddedByXluOperation,combine/reorder 阶段消费的边际延迟表达式。 - XLU Combine / Source-Bus —
ComputeCombinablePairs以及 XLU 优化器运行的 source-bus pack。 - MXU 延迟概览 — MXU 侧保留模型,其
MxuLatencyTable为 matmul/latch 占用定价;这是本转置保留项的同级项。 - MxuSequence / SequenceInfo — 装箱器存储在每个
MxuStatbtree 中的完整每序列记录,以及set_mxu提交。