TracePoints 主注册表
本页中的所有地址、id 和偏移均适用于来自
libtpu-0.0.40-cp314wheel 的libtpu.so(build-id89edbbe81c5b328a958fe628a9f2207d)。该二进制文件未剥离符号,完整 C++ 符号存在,且.textVMA 等于文件偏移。其他版本会有所不同。
摘要
本页是 libtpu 设备端 profiler 的主 trace-point id→name 注册表:这张表把每个线上 trace_point_id(codec 解码的 8 位 TraceHeader 字段)映射到人类可读的事件名、其所属硬件 band,以及消费它的 subscriber。它是 decode → XSpace 扇出的索引:当 DecodeTraceBuffers 遍历一个 16 字节 packet 时,它读到的线上 trace_point_id 只是一个数字;这个数字的含义,即它命名哪个事件、落到哪条设备 line、由哪组 begin/end tracker 配对,都在这里定义。
注册表不是二进制中的静态表。它由 ConvertTpuTraceToXPlaneV2<TraceEntry>(204 个符号引用)在运行时构建;该函数第一次看到每个片上 core 时,会运行对应 family 的 CoreContext setup lambda,注册固定集合的 TraceEventSubscriber,每个 subscriber 都带有一个内联的 TracePoints<TraceEntry> int32 id 集。CoreDispatcher::RegisterSubscriber(每个 chip family 一个 out-of-line 符号,共 6 个)把每个 subscriber 插入 FlatHashMap<trace_point_id, vector<subscriber>>。id→name 映射本身是 codec 的逐事件 Decode<EventName>() 跳转表;主注册表则是该命名空间与 lambda 在其上安装的 subscriber 路由的并集。要逐字节精确重建它,必须同时读取两者:codec 的 111 项 decode 名称表,以及各 family lambda 为每个 subscriber 选择的 id-set。
id 空间是分 band的。deepsea 各代(pxc/vfc/vlc/glc/gfc)把 trace_point_id 打包到一个有空洞的 0..255 空间中,并按硬件来源分区:UHI host-bridge、OCI 片上互连、ICI 片间互连、DMA、base 80 的 TensorCore sync/fence band、base 109 的 SparseCore band、base 104/200 的 throttle band,以及 base 160 的 MGR/power band。旧式 jxc(jellyfish)一代使用完全不同的 16 位 id 命名空间。本页负责按 band 汇总 id→name/subscriber/tracker;按 band 的payload 字段解码由 payload 页面负责,id→name codec 分发由 TraceEntriesCoder 负责。
对于重新实现,契约是:
- deepsea 0..255
trace_point_id空间的 band 分区:每个硬件来源拥有哪个连续 id 范围,以及它的 band base。 - 每个 band 的 id→name 映射:codec 的
Decode<Name>()附加到每个 id 的事件名(每个 decode/translation 步骤依赖的 wire→human 映射)。 - id→subscriber 扇出:CoreContext lambda 安装的
FlatHashMap路由;一个 id 可以驱动 N 个 subscriber 的结构事实(id 85 → 4)。 - begin/end tracker 匹配键:哪些 id 输入哪些有状态 tracker(Step/Task/Overlay/Sync/Dma),以及它用哪个字段配对 span。
| 注册表构建器 | xprof::tpu::ConvertTpuTraceToXPlaneV2<TraceEntry> — pxc @0xf1d4360(+5 个 family) |
| CoreContext setup lambda | pxc @0xf1eb2e0, gfc @0xf229100, glc @0xf214640, vfc @0xf201bc0, vlc @0xf1f5940, jxc @0xf1da7c0 |
| 路由结构 | CoreDispatcher FlatHashMap<trace_point_id (u16 @ TraceHeader+0x18), vector<shared_ptr<TraceEventSubscriber>>> |
| 注册调用 | CoreDispatcher::RegisterSubscriber(this, const TracePoints&, shared_ptr<sub>) — pxc @0xf1ecee0(+5) |
| 分发(drain) | CoreDispatcher::Dispatch @0xf1ed280 — movzwl 0x18(%rax),%edx 读取 id,call *0x10(vtable) 扇出 |
| Id→name 来源 | 通过 111 项 rel32 跳转表 @0xab85bc0 的逐事件 Decode<Name>()(codec) |
| Subscriber 数量 / family | pxc 8 · gfc 19 · glc 19 · vfc 17 · vlc 11 · jxc 10 |
速览 — band 及其 id 范围
| Band | Base / 范围(deepsea) | 来源 | Subscriber | Payload 页面 |
|---|---|---|---|---|
| UHI | OCI sub-channel (*UhiBridge) | Host bridge | (raw path) | uhi-oci-ici-dma |
| OCI | OciMessage*(20 个事件) | 片上互连 | (raw path) | uhi-oci-ici-dma |
| ICI | IciPacket* | 片间互连 | (raw path) | uhi-oci-ici-dma |
| DMA | CMQ/CMN/HDE req+data-end | DMA 引擎 | DmaSubscriber(jxc) | uhi-oci-ici-dma |
| Sync/Fence | base 80(80..90) | TensorCore | Sync + ScalarFence ×2 | sc-band / vfc-vlc-gfc |
| Throttle | base 104(vfc/vlc)/ 200(gfc/glc) | 电源管理 | PowerThrottle | vfc-vlc-gfc |
| SparseCore | base 109(109..120) | SparseCore | 6 个 SC subscriber | sc-band |
| MGR/Power | base 160 + 168/169 | MGR firmware | PState/Firmware/Spi | vfc-vlc-gfc |
| BarnaCore | pxc — 无 SC band | 仅 pxc | (仅 TC 扇出) | jxc-legacy |
| jxc legacy | 16 位 jellyfish ns | jellyfish gen | HbmMux + Dma + 8 | jxc-legacy |
NOTE — “raw path” 表示该 band 在 deepsea CoreContext lambda 中没有专用 subscriber。UHI/OCI/ICI id 会落到 raw
TraceEventSubscriber十进制字符串 XEvent 路径(FastIntToBuffer 名称回退),而不是语义化 subscriber。参见 § 未绑定 band。下方的名称仍然是权威 codec decode 名称;缺失的是路由。
id 如何变成事件
注册机制
注册表是惰性组装的。ConvertTpuTraceToXPlaneV2<TraceEntry> 启动一个工作线程,并在第一次看到某个 ChipCoreId 时运行该 family 的 CoreContext setup lambda({lambda(shared_ptr<TraceEntryWrapper>)}::operator())。该 lambda 构建每个 core 的 TpuXPlaneBuilder,然后执行 N 次 RegisterSubscriber 调用;N 是每个 family 的 subscriber 数量(8/19/19/17/11/10)。
// CoreContext setup lambda — schematic of one register call
// (pxc @0xf1eb2e0; one of 8 such blocks)
function RegisterOne(dispatcher, kind, id_set[], n, line):
sub = operator_new(...) // allocate the subscriber
sub.vtable = SubscriberVtable[kind] // or call its out-of-line ctor
// most subscribers are wrapped in a ThreadedSubscriber (vtable + ClosureThread
// worker @0xf1ede60 at +0xa0); HLO/SparseCore/Dma/HbmMux are NOT wrapped.
tp = TracePoints<TraceEntry>() // std::vector<int32> on the stack
buf = _Znwm(4 * n) // {ptr@+0x0, size@+0x8, cap@+0x10}
write_ids(buf, id_set, n) // movl/movabs/vmovaps id stores
tp.size = n // movq $n, slot+0x8
CoreDispatcher::RegisterSubscriber(dispatcher, tp, sub) // @0xf1ecee0
free(buf) // tp freed after each callRegisterSubscriber 遍历 TracePoints 集中的每个 id,并把 sub 追加到 FlatHashMap[id]。这使注册表成为一个multimap:用重叠 id-set 注册两个 subscriber,意味着单个线上 id 会解析为一个 subscriber 向量,并且 drain 时其中每一个都会运行。
QUIRK — id-set 不是 codec 的属性。codec 知道如何把 id 85 解码成一个
TraceEntry;它不知道在 deepsea gen 上 id 85 必须驱动四个不同 consumer。decode 命名空间(111 项)和路由(少量 id 上的 8..19 个 subscriber)是两个独立结构,只在这里连接。若重新实现时从 decode 表构建路由,并假设“一个 decoder,一个 consumer”,则对每个扇出 id 都是错误的。
id 写入编码
内联的 TracePoints int32 缓冲区使用三种 x86 惯用写法之一填充,取决于集合大小。读回这些写入就是下方每个 id-set 被逐字节精确恢复的方法:
| 集合大小 | 编码 | 示例 |
|---|---|---|
| 1 | movl $id,(buf) | movl $0x54,… → {84}(pxc reg3, @0xf1ec331) |
| 2 | movabs $0xHI00000000LO,%rcx; mov %rcx,(buf) | movabs $0x5a00000059 → {89,90}(@0xf1ec0be) |
| 4 | vmovaps rodata,%xmm0; vmovups %xmm0,(buf) | @0xa2d6b40 → {81,82,88,87}(pxc sync) |
| >4 | 一个 4-id vmovaps base + 按 id 的 movl $id,off(newbuf) 增长复制 | SC-Syncs {111..116},大小 6(movq $0x6 @0xf22af00) |
4-id sync vector 位于 .rodata @0xa2d6b40,解码为 {81,82,88,87};其余两个 sync id {86,80} 通过 movabs $0x5000000056 追加。SpiSampler 对 {168,169} 是 movabs $0xa9000000a8。
分发(drain)路径
drain 时,CoreDispatcher::Dispatch @0xf1ed280 用 movzwl 0x18(%rax),%edx @0xf1ed2c4 读取线上 id,探测 FlatHashMap,并对每个已注册 subscriber 在 @0xf1ed422/43c/498/4de 调用 *0x10(vtable)(subscriber 的 ProcessTraceEntry)。miss,即某个 id 未注册 subscriber,是未绑定 band 的去向。
Sync / Fence Band(base 80)
用途
TensorCore sync-flag 和 scalar-fence band:80..90 id 范围承载每个 sync-flag update/read/wait 和 scalar-fence start/end。这是唯一带有函数体内字面选择 mask(0x1c7)的 band,也是唯一一个直接在这里解码配对语义(wait BEGIN → wait END)的 band。
注册表
| id | 事件名(codec) | subscriber | tracker / 键 |
|---|---|---|---|
| 80 | TCS_EXTERNAL_SYNC_FLAG_UPDATE_DMA_DONE | SyncSubscriber | SyncTracker(END, DMA-done) |
| 81 | TCS_INTERNAL_SET_SYNC_FLAG | SyncSubscriber | (instant) |
| 82 | TCS_INTERNAL_ADD_SYNC_FLAG | SyncSubscriber | (instant) |
| 84 | TCS_INTERNAL_SET_TRACEMARK | TensorCoreStepSubscriber | StepTracker(TraceMark id) |
| 85 | TCS_INTERNAL_TRACE_INSTRUCTION | Hlo + Overlay + OnDeviceTraceMe + LloOp | OverlayTracker(overlay_id) |
| 86 | TCS_INTERNAL_UNSUCCESSFUL_SYNC_ATTEMPT | SyncSubscriber | SyncTracker(wait BEGIN) |
| 87 | TCS_INTERNAL_SUCCESSFUL_SYNC_ATTEMPT | SyncSubscriber | (instant — pxc 中不与 tracker 配对) |
| 88 | TCS_INTERNAL_READ_SYNC_FLAG | SyncSubscriber | (instant) |
| 89 | TCS_INTERNAL_SCALAR_FENCE_START | ScalarFenceSubscriber ×2 | fence span(lines 9 + 62) |
| 90 | TCS_INTERNAL_SCALAR_FENCE_END | ScalarFenceSubscriber ×2 | fence span |
该邻域还存在两个 codec 名称,但没有被任何 deepsea lambda subscriber 绑定:TCS_INTERNAL_CORE_INTERRUPT 和 TCS_INTERNAL_HOST_INTERRUPT(decode 名称已在 .rodata 中确认;路由未安装 — (unbound, HIGH))。
0x1c7 选择 mask
SyncSubscriber::ProcessTraceEntry(pxc @0xf1eeee0)加载 mov $0x1c7,%esi @0xf1eef3d,并用它测试 (1 << (id - 80))。band base 是 80,因此:
0x1c7 = 0b1_1100_0111 = bits {0,1,2,6,7,8} = ids {80,81,82,86,87,88}这是规范的 band-base 编码:sync trace_point_id 的“selection-mask bit”为 (1 << (id - 80))。它排除 84(tracemark → StepTracker)、85(trace-instruction → 4 路扇出)和 89/90(scalar fence → ScalarFence),这些都由各自注册的 subscriber 路由。
GOTCHA —
0x1c7mask 是FlatHashMap路由的补充,不是替代。SyncSubscriber 注册在{80,81,82,86,87,88}(mask 集)上,分发已经过滤到这些 id;函数体内 mask 是第二道看似冗余的过滤。只确认 Sync 带有这种函数体内字面 mask。其他所有 subscriber 都纯粹由其注册集合路由;FlatHashMap是权威选择结构。不要假设其他 band 存在隐藏 bitmask(LOW 置信度:它们有)。
SparseCore Band(base 109)
用途
SparseCore instruction/task/sync band:id 109..120 承载 SC tracemark、trace-instruction、sfence/sync/barrier start-stop 对,以及 task issue→commit span。存在于 gfc/glc/vfc;不存在于 pxc 和 vlc。
NOTE — subscriber 绑定的 SC id 是 109..120,但完整 SC codec band 从更低的 id 108 开始(
ScInstructionCoreInterrupt,未绑定 — 没有 deepsea lambda subscriber 路由它),并延伸到 id 132/133 以及 gfc-only PMU samples 134/135。这里的“Base 109”是最低的已路由 id,而不是 band floor;完整的线上 SC 子范围 108..133/135(以及位于其中的 SC-issued OCI 事件 124..130)归payload-sc-band.md所有。
注册表
| id | 事件名(codec) | subscriber | tracker / 键 |
|---|---|---|---|
| 109 | ScInstructionSetTracemark | SC-Hlo + SC-Task + SC-Step | StepTracker(SC TraceMark) |
| 110 | ScInstructionTraceInstruction | SC-Hlo + SC-Task + SC-Overlay + SC-OnDeviceTraceMe | OverlayTracker(SC overlay_id) |
| 111 | ScInstructionSfenceStart | SparseCoreSyncsSubscriber | sfence span |
| 112 | ScInstructionSfenceStop | SparseCoreSyncsSubscriber | sfence span |
| 113 | ScInstructionSyncStart | SparseCoreSyncsSubscriber | sync span |
| 114 | ScInstructionSyncStop | SparseCoreSyncsSubscriber | sync span |
| 115 | ScInstructionBarrierStart | SparseCoreSyncsSubscriber | barrier span |
| 116 | ScInstructionBarrierStop | SparseCoreSyncsSubscriber | barrier span |
| 119 | ScTaskIssueFromScs | SC-Hlo + SC-Task | TaskTracker(task tag, ISSUE) |
| 120 | ScTaskCommitOnSct | SC-Hlo + SC-Task | TaskTracker(task tag, COMMIT) |
相邻但未被 SC lambda subscriber 绑定的 codec 名称:ScInstructionSyncWatchStart / ScInstructionSyncWatchStop 和 ScInstructionCoreInterrupt(decode 名称存在;(unbound, HIGH))。SC-Syncs subscriber 的 id-set 写作 movabs $0x7200000071 {113,114},随后增长 +0x73{115}+0x74{116}+0x6f{111}+0x70{112},大小 6(movq $0x6,-0x110 @0xf22af00)。
Subscriber 名单(gfc/glc/vfc)
| # | subscriber | TracePoints 集 | XLine | 角色 |
|---|---|---|---|---|
| 5 | SparseCoreHloSubscriber | {109,110,119,120} | — | SC XLA-op 名称 |
| 6 | SparseCoreTaskSubscriber | {109,110,119,120} | — | → TaskTracker |
| 7 | SparseCoreOverlaySubscriber | {110} | 142 SC Overlay | → OverlayTracker |
| 8 | SparseCoreOnDeviceTraceMeSubscriber | {110} | 100 SC TraceMe | TraceMe span |
| 9 | SparseCoreStepSubscriber | {109} | 117 SC Steps | → StepTracker |
| 10 | SparseCoreSyncsSubscriber | {111,112,113,114,115,116} | 67 SC Syncs | sfence/sync/barrier |
QUIRK — id 109 和 110 各自扇出到不同的 subscriber 集。109(tracemark)命中 Hlo+Task+Step;110(trace-instruction)命中 Hlo+Task+Overlay+TraceMe。Task subscriber 监听完整
{109,110,119,120},但只有 119/120 对实际配成 span;109/110 为完整性而到达它。这是 TensorCore 85 扇出的 SC 对应物。
OCI / ICI / UHI Bands(互连)
用途
片上(OCI)、片间(ICI)和 host-bridge(UHI)互连 band。它们承载线上事件量的大部分:跨引擎的 message issue/receive、ICI link packet 流,以及 UHI host-bridge 流量;但在 deepsea CoreContext lambda 中没有专用语义 subscriber。
注册表(代表性 — OCI message 事件)
OCI band 的 decode 名称形成 20 事件的 OciMessage* family,命名片上 message 的每一跳:
| 事件名(codec) | 含义 |
|---|---|
OciMessageIssuedFromTcs | 从 TensorCore sequencer 发出的 message |
OciMessageIssuedFromMgr | 从 MGR firmware 发出的 message |
OciMessageMsgIssuedFromEngine / ...FromQnm | engine / QNM 发出 |
OciMessageSentByBc / ...BySc / ...ByCmnde / ...ByHde | 按 source block 的 egress |
OciMessageSentByUhiBridge / OciMessageReceivedByUhiBridge | UHI band — host-bridge hop |
OciMessageReceivedByBc / ...BySc / ...ByMgr | 按 dest block 的 ingress |
OciMessageGeneratedInIcrEgressDma / ...IngressDma | ICR DMA-bridge 生成 |
OciMessagePacketReceivedInIcr / OciMessagePacketSentToOci | OCI/ICR 边界 |
OciMessageSyncFlagUpdateFromDstEngine | 经 OCI 携带的 sync-flag update |
ICI link flow 使用并行的 IciPacket* decode family:IciPacketControlPacketInjectedByIcrDmaBridge / ...QueuedForLocalIngress / ...ReceivedByIcrDmaBridge,匹配的 IciPacketDataPacket* 三元组,以及 link 侧的 IciPacketPacketQueuedForLinkTransmission / ...ReceivedOnLinkInput / ...TransmittedOnLinkOutput。
UHI band 不是独立 id 范围,而是 OCI/ICR 事件中命名 UHI host bridge(*UhiBridge)的子集。UhiBridge 符号存在;UHI 事件搭载在 OCI codec 上。
NOTE — OCI/ICI/UHI band 的逐 id 数值归 codec decode table 所有(有空洞的 0..255 跳转表索引)。本页声明名称和band 成员关系,两者都已从
.rodata逐字节确认;互连 band 的精确 id→name 数值配对作为跳转表索引位于 codec 页面。
未绑定 band — deepsea 上的 UHI/OCI/ICI/DMA
CoreContext lambda 只注册约 8..19 个语义 subscriber(Sync/Step/Hlo/Overlay/TraceMe/Llo/ScalarFence/SparseCore*/Firmware/Throttle/Spi)。占主导的互连和 DMA band 在 FlatHashMap 中没有条目,因此在 deepsea gens 上它们会落到 raw TraceEventSubscriber 路径:事件名变为 id 的 FastIntToBuffer 十进制字符串,并作为通用 XEvent 发出,或者该 id 被丢弃。具体是哪一种,以及 deepsea gens 上是否注册了单独的 DmaSubscriber(它只在 jxc 上存在),未解决 (LOW)。这是主注册表中最大的完整性缺口:线上流量最多的 band,语义绑定最少。
DMA Band
用途
DMA started/completed band:CMQ/CMN/HDE descriptor request + data-end 事件,按 dma_id 配对。在 jxc 上它是一等 DmaSubscriber;在 deepsea 上它未绑定(见上)。
注册表
| 元素 | 值 |
|---|---|
| request decode 名称 | CmnDmaRequestEastSideLane / ...WestSideLane / CmnDmaRequestSet |
| DMA 引擎 | CMQ(queue)、CMN/CMNDE(notify)、HDE(host) |
| 配对键 | dma_id = GetDmaId() — first descriptor = BEGIN,data-end = END |
| jxc subscriber | DmaSubscriber — 基于 MemoryCommand()/GetDmaId() 路由,不是静态 id-set |
| jxc HBM mux | HbmMuxSubscriber — HBM-mux band,基于 MemoryCommand 路由 |
GOTCHA — jxc
DmaSubscriber和HbmMuxSubscriber完全不注册TracePointsint32 集。它们基于已解码的MemoryCommand()accessor 动态路由,而不是基于线上trace_point_id。如果重新实现时预期每个 subscriber 都带有 id-set,就会错误建模这两个;它们是注册机制的例外。
Throttle Band(base 104 / 200)
用途
电源管理 cycle-skip band:throttle 事件由 RunLengthTracker<unsigned int> 按键处理,把连续 cycle-skip sample 合并成 run。band base 依 gen 而定:vfc/vlc 上是 104,gfc/glc 上是 200。
注册表
| id | 事件 | subscriber |
|---|---|---|
| 104 | ThrottleCycleSkip band base(vfc/vlc) | PowerThrottleSubscriber |
| 200 | ThrottleCycleSkip band base(gfc/glc) | PowerThrottleSubscriber |
deepsea throttle decode 名称按 brake 来源形成很深的 ThrottleCycleSkip* 分类:...ElectricalBrakeEventCycleSkipLdidtBrake、...ElectricalDroopEvent...LdidtDroop、...ExternalBrakeEvent...ExtBrake、...ExternalThrottleEvent...ExtThrottle,以及 PPM family(...PpmBrakeEventDidtAggressive/Nominal、...OvershootAggressive/Nominal、...SustainedAggressive/Nominal,再加 rising/falling-edge 变体)。RunLengthTracker 的逐 sample 累积键(每个 run 目标是哪条 thermal/power counter line)未解码 (LOW)。vfc base 写作 movl $0x68 = 104 @0xf2027ae;gfc 为 movl $0xc8 = 200 @0xf229cee。
MGR / Power Band(base 160)
用途
MGR firmware power/p-state band:base 160 加 168/169 SPI sampler 对。这些 subscriber 包装 RunLengthTracker<double>(firmware)/ <...EventBuilder>(SPI)累加器,而不是配对 begin/end span。
注册表
| id | 事件 | subscriber |
|---|---|---|
| 160 | MgrFwEvent / MGR band base | PStateTrackerSubscriber + FirmwareSubscriber(gfc/glc 上还有第 2 个 component FW) |
| 168 | SPI sampler(gfc/glc) | SpiSamplerSubscriber |
| 169 | SPI sampler(gfc/glc) | SpiSamplerSubscriber |
第 2 个 FirmwareSubscriber(仅 gfc/glc)包装 RunLengthTracker<FirmwareComponentEventBuilder>,并发出逐 component power line(kComponents 120..130 / 134..138)。SpiSamplerSubscriber(SpiSamplerSubscriber / PowerSpiSamplerEventBuilder 已确认)包装 RunLengthTracker<PowerSpiSamplerEventBuilder>,lines 118/119,id-set {168,169}(movabs $0xa9000000a8 @0xf22c3aa)。vfc/vlc 既没有第 2 个 Firmware,也没有 SPI sampler。MGR base 是 movl $0xa0 = 160。
pxc(BarnaCore)Gen
用途
pxc(pufferfish)是 BarnaCore gen,即最简单的 deepsea family,8 个 subscriber,没有 SparseCore band,也没有 power/throttle subscriber。它的高 id 空间只包含 TC sync/fence/instruction band。
注册表
| # | subscriber | TracePoints | XLine | tracker/key |
|---|---|---|---|---|
| 1 | SyncSubscriber(threaded) | {80,81,82,86,87,88} mask 0x1c7 | 17 | sync_flag_number |
| 2 | ScalarFenceSubscriber(threaded) | {89,90} | 9 Scalar Unit | fence span |
| 3 | TensorCoreStepSubscriber(threaded) | {84} | 1 Steps | TraceMark id |
| 4 | TensorCoreHloSubscriber | {85} | 3 XLA Ops | (HLO name) |
| 5 | TensorCoreOverlaySubscriber(threaded) | {85} | 7 TC Overlay | overlay_id |
| 6 | TensorCoreOnDeviceTraceMeSubscriber | {85} | 6 XLA TraceMe | TraceMe span |
| 7 | LloOpEventSubscriber(threaded) | {85} | 8 Tensor Core | (LLO op) |
| 8 | ScalarFenceSubscriber(threaded) | {89,90} | 62 Barna Core Fence | fence span |
id 85(TCS_INTERNAL_TRACE_INSTRUCTION)的 4 路扇出在这里最清楚:subscriber 4/5/6/7 都注册 {85}。它们共享的 -0xc0 {85} 栈缓冲区只分配一次、释放一次(@0xf1ecafb)。subscriber 2 和 8 都是在 {89,90} 上的 ScalarFenceSubscriber,但发到不同设备 line(9 Scalar Unit 与 62 Barna Core Fence),由 +0x18 line 字段区分(movl $0x9,0x18 vs movl $0x3e,0x18 = 62)。
jxc(jellyfish)Legacy Gen
用途
jxc(jellyfish)是旧式 PerformanceTraceEntry gen,是唯一使用旧 codec 的 family,具有不同于 deepsea 0..255 band 的 16 位 id 命名空间,也是唯一带有 HbmMux + Dma subscriber 的 gen。10 个 subscriber(lambda @0xf1da7c0)。
注册表(jellyfish 16 位 id)
| # | subscriber | TracePoints(jellyfish ids) |
|---|---|---|
| 1 | HbmMuxSubscriber(threaded) | (HBM-mux band;基于 MemoryCommand 路由) |
| 2 | DmaSubscriber | (基于 MemoryCommand()/GetDmaId() 路由) |
| 3 | SyncSubscriber(threaded) | {0xa3d,0xa3e,0xa42,0xa43,0xa44,0x93c} |
| 4 | ScalarFenceSubscriber(threaded) | {0xa45,0xa46} = {2629,2630} |
| 5 | TensorCoreStepSubscriber(threaded) | (TC SetTracemark,jellyfish id) |
| 6 | TensorCoreHloSubscriber | (TC TraceInstruction,jellyfish id) |
| 7 | TensorCoreOverlaySubscriber(threaded) | (same) |
| 8 | TensorCoreOnDeviceTraceMeSubscriber | (same) |
| 9 | LloOpEventSubscriber(threaded) | (same) |
| 10 | ScalarFenceSubscriber(threaded) | {0xa45,0xa46} |
sync id-set 打包为 movabs $0xa430a440a3e0a3d @0xf1db880(16 位半字 0xa3d/0xa3e/0xa44/0xa43)+ movl $0x93c0a42({0xa42,0x93c})。ScalarFence 集是 movl $0xa460a45({0xa45,0xa46})。TC 单 id 集(subscriber 5..9)和 HbmMux band 未逐项枚举 (LOW);jellyfish-id → event-name cross-walk 归 jxc legacy payload page 所有。jellyfish::TraceOperand 和 PerformanceTraceEntry 符号已确认存在。
QUIRK — jxc subscriber 3/4/10 复用与 deepsea gens 相同的 C++ subscriber 类型(SyncSubscriber、ScalarFenceSubscriber),但喂给它们的是完全不同命名空间中的 id。subscriber 类型可移植;id-set 不可移植。按 deepsea band base(80/109/160)索引的跨 gen 路由表会静默误路由每个 jxc 事件;唯一共同点是 subscriber 分类,不是 id。
五个有状态 Tracker — 匹配键
tracker 是 subscriber 之上的 begin/end 配对层。每个 tracker 消费固定 id 子集,并在一个字段上配对 span;这是 SyncTracker(sync_flag_number) 和 DmaSubscriber(dma_id) 的类似层。
| tracker | 输入(trace_point_ids) | begin 事件 | end 事件 | MATCH KEY |
|---|---|---|---|---|
| SyncTracker | 80,86(+81,82,87,88 instant) | 86 UNSUCCESSFUL_SYNC(ProcessSyncBlock) | 80 DMA_DONE(ProcessSyncUnblock) | sync_flag_number |
| DmaSubscriber | CMQ/CMN/HDE req + data-end | First()/MemoryCommand | Last()/MemoryDataEnd | dma_id = GetDmaId() |
| StepTracker | 84(TC)/ 109(SC) | TraceMark 0x7fffffff | TraceMark 0x7ffffffe | TraceMark id(state+0x8) |
| TaskTracker | 119,120(仅 SC) | 119 ScTaskIssueFromScs | 120 ScTaskCommitOnSct | task tag(FlatHashMap) |
| OverlayTracker | 85(TC)/ 110(SC) | operand kind 0xd(open) | operand kind 0x9(close) | overlay_id(state+0x8) |
StepTracker — TraceMark id,sentinel 区分
StepTracker::ProcessTraceEntry<gfc> @0xf231900 读取 id 并按 core type 分发:TC(id 0x54=84,marker 来自 TcsInternalSetTracemark_globals_+0x18)或 SC(id 0x6d=109,来自 ScInstructionSetTracemark_globals_+0x18)。它构建 TraceMarkEntry{+0x0 step_id, +0x8 mark_type, +0x10 gtc, +0x18 flag},并调用共享的 StepTracker::ProcessTraceEntry @0xf2c4480。Mark-type sentinel(cmp @0xf2c44bd/4f1/4513/4580/4589):
0x7fffffff step-BEGIN marker → close any open step, open a new one keyed by the marker id
0x7ffffffe step-END marker → close the open step, emit StepInfo{step_id, start, end}
0x7ffffff9 intra-step marker → annotate the open step without closing it状态结构:+0x8 = 当前 step id(匹配键),+0x10 = start gtc,+0x28 = flag,+0x30 = present。
TaskTracker — task tag,FlatHashMap keyed
TaskTracker::ProcessTraceEntry<gfc> @0xf2394e0。id 0x77=119(ScTaskIssueFromScs,oneof 0x4d)从 ScTaskIssueFromScs_globals_+0x28 读取 tag,并在 FlatHashMap<tag, pending> 中记录 pending task(probe mulq 0x28(%r12),cap cmp 0x38(%r12))。id 0x78=120(ScTaskCommitOnSct,oneof 0x4e)从 +0x20 读取匹配 tag,查找它,并在匹配时通过 ProcessTaskCommit @0xf2c4ce0 发出 TaskInfo{+0x8 tag, +0x50 present}。Begin = 119,end = 120,key = task tag。仅 SparseCore。
OverlayTracker — overlay_id operand
OverlayTracker::ProcessTraceEntry<gfc> @0xf2335c0 按 core-type selector(state+0x0:2=TC,5=SC)分发,过滤 id + block_id(+0x1c 对 state+0x4),并提取 operand:TC id 0x55=85(operand 来自 TcsInternalTraceInstruction_globals_+0x18)/ SC id 0x6e=110(来自 ScInstructionTraceInstruction_globals_+0x18)。OverlayTracker::ProcessTraceOperand @0xf2c3e40 按 operand kind 分支:
0xd overlay OPEN → record overlay_id at state+0x8 (match key), active flag +0xc, start gtc +0x10
0x9 overlay CLOSE → emit OverlayInfo{overlay_id, start, end=gtc}, clear +0x8/+0x10两者都搭载在 id 85(TC)/ 110(SC)上;open/close 判别项是 operand kind,而不是独立 id。
相关结构 / 表偏移
| 结构 | 布局 |
|---|---|
TracePoints<TraceEntry> | std::vector<int32> {ptr@+0x0, size@+0x8, cap@+0x10};在栈上构建,每次 register 后释放 |
CoreDispatcher map | FlatHashMap<u16 id (TraceHeader+0x18), vector<shared_ptr<TraceEventSubscriber>>> |
TraceEventSubscriber base | +0x08/+0x0c core_id/chip_id filter;+0x10 TpuXPlaneBuilder*;+0x18 每 id XEventMetadata* cache / line 字段 |
ThreadedSubscriber | vtable + ClosureThread worker(pxc 中 ThreadLoop @0xf1ede60)位于 +0xa0;wrapped vtable 内联设置 |
StepTracker state | +0x8 step id(key),+0x10 start gtc,+0x28 flag,+0x30 present |
TaskTracker state | FlatHashMap<tag, pending>;TaskInfo{+0x8 tag, +0x50 present} |
OverlayTracker state | +0x8 overlay_id(key),+0xc active flag,+0x10 start gtc |
| sync id rodata | @0xa2d6b40 = {81,82,88,87};+{86,80} 通过 movabs $0x5000000056 |
交叉引用
- TraceEntriesCoder — 16 字节 packet codec;拥有 id→
Decode<Name>()跳转表和双 id-space 分发 - Profiling overview — 注册表在 device-trace pipeline 中的位置
- Payload — UHI/OCI/ICI/DMA — interconnect 和 DMA band 的逐 id 字段解码
- Payload — SparseCore band — ids 109..120 的字段解码
- Payload — vfc/vlc/gfc — sync/throttle/MGR band 的字段解码
- Payload — jxc legacy — jellyfish 16 位 id 命名空间和
PerformanceTraceEntry字段解码 - XEvent metadata ids — 注册表馈入的 subscriber→XEvent metadata 命名
- TraceEntry → XEvent — dispatch 下游的 subscriber
ProcessTraceEntry→ XEvent 成形