默认 DebugOptions
本页所有地址、结构体偏移和字段编号映射均适用于
libtpu0.0.40(cp314 manylinux 构建,libtpu_lts_20260413_b_RC00,libtpu.sobuild-id89edbbe81c5b328a958fe628a9f2207d)。其他版本会重排字段偏移布局并产生差异。
摘要
xla::DefaultDebugOptionsIgnoringFlags() @ 0x1e66a860 是构造每次 TPU 编译起始基线 xla.DebugOptions 消息的单一函数。它运行在任何 flag、环境覆盖或 PJRT CompileOptions.debug_options merge 之前。名称是字面含义:它构建二进制内默认值,并忽略 flag 层,因此其函数体就是 290 字段消息的权威种子。在 upstream OpenXLA 中,等价函数是 xla/debug_options_flags.cc 中的 DefaultDebugOptionsIgnoringFlags();这里是 TPU plugin 编译进去的副本。
Proto3 不携带 descriptor 级默认值,每个标量的 wire 默认值都是零值(false / 0 / "" / enum-0)。有效默认值是这个构造器在零状态之上存储的内容。因此函数体可以干净地分成两类:它显式写入的字段(本文档记录的非零种子),以及它从不触碰的约 218 个字段,这些字段保留入口处 DebugOptions::DebugOptions(this, 0) 基础构造调用(第 60 行)建立的 proto-zero 默认值。本页负责 explicit-write → value 映射。它不负责字段 schema,字段编号、名称和类型位于 debugoptions-proto.md。它也不负责 flag 覆盖(xla-flag-atlas.md)或 AUTO/-1 sentinel 解析(autoproto-autoor-resolution.md)。
反编译函数体是一段扁平的原始结构体 store 序列:*((_DWORD *)this + N) = value、*((_BYTE *)this + N) = 0/1、… |= mask,以及把多个相邻字段打包进一次 8 字节 move 的 packed QWORD 写入。把 store 映射回 proto 字段,需要将其 (offset, has-bit) 对与各个 set_xla_* accessor 匹配;下面每个 CONFIRMED 行都是这样锚定的。|= mask 写入是 proto2 has-bit OR(消息 _has_bits_ word 中位于偏移 8–55 的 presence flag);它们记录某字段被设置过,但不改变其值,本身并不是默认值。
对重实现而言,契约是:
- base-zero 不变量:任何缺席于此构造器的字段都保留其 proto3 零值;构造器从不清除非零基底,只负责播种。
- 显式种子表:函数体写入的 field → value 对,通过
(offset, has-bit)→ accessor 匹配恢复。 - 打包约定:一个 QWORD store(
0x1E0000000A)如何播种两个相邻 int 字段(低 DWORD = 字段 N,高 DWORD = 字段 N+1),以及 float 字段如何搭乘 packed QWORD 的上半部分。 - repeated-enum 种子:两个
RepeatedField<int>会逐元素 append(xla_gpu_enable_command_buffer和第二个 command-buffer 列表),而不是作为标量存储。
| 函数 | xla::DefaultDebugOptionsIgnoringFlags() |
| 地址 | 0x1e66a860(约 610 行反编译代码) |
| Base ctor | 第 60 行的 DebugOptions::DebugOptions(this, 0) — 先将全部 290 个字段清零 |
| 消息 | xla.DebugOptions(290 个存活字段,descriptor index 403) |
| 显式 scalar/string 种子 | 约 70 个 store(本页表格) |
| Repeated-enum 种子 | 2 个列表(offset 160 ×6 elems,offset 288 ×3 elems) |
| Map 种子 | xla_gpu_analytical_latency_estimator_options(6 个 string→string 对) |
| 未触碰(proto-zero)字段 | 约 218 个 — 保持 false/0/""/enum-0 |
| 记录中的 caller | AllocateFlags() 0x1e6b8020,随后是 PJRT 编译路径 |
默认值如何恢复
store 到字段的映射问题
反编译器针对原始 DebugOptions 对象渲染函数体,它没有 proto 字段名,只有进入 C++ 消息布局的字节偏移。如下行:
*((_DWORD *)this + 142) = 4; // 0x1e66a860 + body; offset 568
*((_BYTE *)this + 24) |= 0x20u; // has-bit OR
```text
意思是“在字节偏移 568 处存储 32 位值 4,然后在偏移 24 的 `_has_bits_` word 中设置 has-bit `0x20`”。要命名该字段,需要将这个精确的 `(value-offset, has-bit-offset, has-bit-mask)` 三元组与生成的 `set_xla_*(…)` accessor 匹配,每个 accessor 都正好写入一个字段的偏移并 OR 一个 has-bit。`xla_gpu_autotune_level` 的 accessor(`0x1e66b860`)写入 `*((_DWORD *)this + 142)` 并 OR `*((_BYTE *)this + 24) |= 0x20`,完全匹配。因此偏移 568 是字段 123,其默认值是 **4**。
下面每个 CONFIRMED 行都以这种方式锚定:offset/has-bit 对已与字段的 `set_*` accessor 交叉检查。只知道 offset 的行(在 grep 预算内未执行 accessor 交叉检查)标记为 HIGH;按语义推断的 packed-pair 成员按注明标记为 HIGH 或 MEDIUM。
### 打包约定
编译器会把相邻 store 合并成宽 move。反复出现三种模式:
```c
*(_QWORD *)((char *)this + 844) = 0x1E0000000ALL; // two int32 fields
// offset 844 (low DWORD) = 0x0000000A = 10 -> field 327
// offset 848 (high DWORD) = 0x0000001E = 30 -> field 328
*((_QWORD *)this + 84) = 0x3F8CCCCD00000000LL; // a float in the upper half
// offset 672 (low DWORD) = 0 -> adjacent int/bool group
// offset 676 (high DWORD) = 0x3F8CCCCD = 1.1f -> a float field
*(_QWORD *)((char *)this + 92) = 0x101010100000003LL; // int + four bools
// offset 92 (low DWORD) = 3 -> field 31 (backend_optimization_level)
// offsets 96,97,98,99 = 01 01 01 01 -> four adjacent bool fields = true坑点 — 单个 QWORD store 不是一个字段。偏移 92 处的
0x101010100000003一次播种了五个 proto 字段:int32xla_backend_optimization_level(低 DWORD = 3)加上 96–99 处四个 byte 宽 bool,每个都设为 1。把 QWORD 当作一个 64 位字段值的重实现会把五个字段全弄错。要按字节 lane 对照布局解码 packed store。怪癖 — 反编译函数体中的
&stru_800000、&unk_1E00007、&stru_1000100不是指针。IDA 把宽立即数0x800000、0x1E00007、0x1000100错标成数据符号,是因为其数值与某个 section/struct 地址碰撞。它们是整数/packed-pair literal:0x800000= 8 388 608(8 MiB),0x1000100= packed{int=256, …}对。
显式种子表
构造器在零基底之上写入的值。Offset 是进入 DebugOptions C++ 对象的字节偏移;field# 是 debugoptions-proto.md 上的 proto 字段。“Confidence” 反映 (offset, has-bit) 对是否已匹配到具名 accessor(CONFIRMED),或仅按 offset 定位 / 从打包推断(HIGH/MEDIUM)。
已确认 scalar 种子(accessor 锚定)
| Field# | Name | Type | Offset | Default |
|---|---|---|---|---|
| 31 | xla_backend_optimization_level | int32 | 92 | 3 |
| 123 | xla_gpu_autotune_level | int32 | 568 | 4 |
| 142 | xla_multiheap_size_constraint_per_heap | int32 | 584 | -1 |
| 228 | xla_gpu_redzone_padding_bytes | int64 | 680 | 8388608 (8 MiB) |
| 237 | xla_gpu_collective_permute_decomposer_threshold | int64 | 688 | 0x7FFFFFFFFFFFFFFF (INT64_MAX) |
| 311 | xla_cmd_buffer_trace_cache_size | int64 | 816 | 16 |
| 327 | xla_gpu_executable_warn_stuck_timeout_seconds | int32 | 844 | 10 |
| 328 | xla_gpu_executable_terminate_timeout_seconds | int32 | 848 | 30 |
最后两个是规范 packed pair:第 548 行 *(_QWORD *)((char *)this + 844) = 0x1E0000000A 一次 move 写入二者(0x0A=10 位于 844 的低 lane,0x1E=30 位于 848 的高 lane)。两个 offset 都已由 accessor 确认。
高置信 scalar 种子(offset 定位)
这些 store 在函数体中没有歧义,但其 set_* accessor 未在 grep 预算内逐个交叉检查;offset 和 value 是字节精确的,字段分配基于与已确认邻居的布局相邻性。
| Offset | Store (body line) | Decoded value | Type inferred |
|---|---|---|---|
| 568 (field 123) | *((_DWORD*)this+142)=4 | 4 | int32 (autotune_level) |
| 576 (field 132) | *((_DWORD*)this+144)=-1 | -1 | int32 (xla_dump_max_hlo_modules) |
| 644 | *((_DWORD*)this+161)=5 | 5 | int32 |
| 712 | *((_QWORD*)this+89)=15 | 15 | int64 |
| 724 | *((_DWORD*)this+181)=95 | 95 | int32 |
| 728 | *((_QWORD*)this+91)=100000 | 100000 | int64 |
| 768 | *((_QWORD*)this+96)=100 | 100 | int64 |
| 792 | *((_QWORD*)this+99)=16 | 16 | int64 |
| 812 | *((_DWORD*)this+203)=256 | 256 | int32 |
| 836 | *((_DWORD*)this+209)=32 | 32 | int32 |
| 956 | *((_DWORD*)this+239)=2 | 2 | enum/int32 |
| 976 | *((_DWORD*)this+244)=40 | 40 | int32 |
| 984 | *((_DWORD*)this+246)=20 | 20 | int32 |
| 1008 | *((_DWORD*)this+252)=1800 | 1800 | int32 (timeout s) |
| 1024 | *((_QWORD*)this+128)=0x400000 | 4194304 (4 MiB) | int64 |
| 1040 | *((_QWORD*)this+130)=2048 | 2048 | int64 |
注意 — 其中若干是独立于符号匹配也可识别的 XLA 默认值:256(
xla_gpu_memory_limit_slop_factor类)、1800 s(30 分钟 terminate timeout)、4 MiB / 8 MiB(collective-combine/redzone 字节阈值)、INT64_MAX(“无阈值” sentinel)。值是字节精确的;只有精确字段名带有 HIGH(而非 CONFIRMED)提示。
Packed-pair int/enum 种子
| Body line | Store | Low lane (offset → value) | High lane (offset → value) |
|---|---|---|---|
| 548 | +844 = 0x1E0000000A | 844 → 10 (field 327) | 848 → 30 (field 328) |
| 553 | +936 = 0x2800000014 | 936 → 20 (0x14) | 940 → 40 (0x28) |
| 63 | +92 = 0x101010100000003 | 92 → 3 (field 31) | 96–99 → bool 1,1,1,1 |
Float 种子(上半部分打包)
DebugOptions 中存在两个 float 字段(xla_gpu_auto_spmd_partitioning_memory_budget_ratio 字段 225,xla_gpu_autotune_gemm_rtol 字段 316)。二者都通过 packed QWORD 的上半部分播种:
| Body line | Store | Float lane | Value |
|---|---|---|---|
| 491 | *((_QWORD*)this+84)=0x3F8CCCCD00000000 | offset 676 = 0x3F8CCCCD | 1.1f |
| 543 | *((_QWORD*)this+103)=0x53DCCCCCD | offset 824 = 0x3DCCCCCD | 0.1f |
0x3F8CCCCD 解码为 IEEE-754 single 1.1000000238…,0x3DCCCCCD 解码为 0.1000000015…,也就是规范的 1.1 和 0.1 float literal。+103 store 还在 float 上方的 lane 中携带 0x5,播种一个相邻小 int。
String 种子(ArenaStringPtr::Set)
| Body line | Offset | Value | Likely field |
|---|---|---|---|
| 69 | 80 | "./cuda_sdk_lib" (len 14) | xla_gpu_cuda_data_dir (61) |
| 551 | 520 | "inf" (len 3) | 一个 GPU string-typed timeout/mode 字段 |
所有其他 ArenaStringPtr::Set(... &nptr, 0) 调用(offset 408、432、464、472、480、488、496)都设置空字符串,它们是显式 no-op 种子,会重新建立 "",与 proto-zero 默认值一致。为完整性列出它们,但它们不增加非零默认值。
怪癖 —
"./cuda_sdk_lib"和"inf"是烘焙进共享 upstream 默认值中的 GPU/host-platform 字符串,即使没有 TPU 代码读取xla_gpu_cuda_data_dir。这是 libtpu 未经 TPU 裁剪地编译了完整 OpenXLADefaultDebugOptionsIgnoringFlags函数体(包含 GPU 默认值)的直接证据,与 proto 携带全部 183 个xla_gpu_*字段一致。见overview.md。
Boolean 种子
函数体写入约 40 个独立的 *((_BYTE *)this + N) = 0/1 store,另有四个 bool 打包在 offset-92 QWORD 中。列出 40 个原始 (offset, 0|1) 行会成为反模式字节倾倒;结构才是重点:
bool stores in DefaultDebugOptionsIgnoringFlags (line / offset / value):
set to 1 (true):
91, 620, 631, 929, 1055, 910, 895, 989, 588, 622, 665, 621, 742,
894, 671, 637, 930, 806, 743, 878, 933, 909, 1007, 1006, 932, 964,
1053, 567, 567(+1) and the 4 packed bools at 96-99
set to 0 (false, explicit):
555, 100, 629, 563, 596, 575, 589, 782, 546, 966, 907, 547, 697,
859, 965, 103, 736, 809, 991, 554, 739, 961, 934, 811, 885, 630,
636, 1013, 905, 783, 1035, 664, 877, 698, 857, 740, 1014, 833,
856, 1034, 858, 879, 884, 931, 892, 904, 928, 1012, 911, 988, 967,
950, 1015, 982, 980, 1004, 1032, 1033
```text
> **注意 —** 显式 `= 0` bool store 相对于零基底是冗余的(第 60 行已经清除了它们),编译器发出它们是因为源码无条件赋值 `set_field(false)`。它们不改变有效默认值;它们只强制 has-bit,使字段序列化为“显式设置为 false”,而不是“缺席”。该 presence 区分是前端的“默认值触碰了这里”信号(见 [`debugoptions-proto.md`](debugoptions-proto.md) 上的 proto3-optional presence 模型)。
>
> **坑点 —** 因为约 60 个 bool 被显式写入 `false` *且*设置 has-bit,从这些默认值发出的 wire-level `DebugOptions` **不是**稀疏的,它会为构造器命名的每个字段携带 presence bit,而不只是非零字段。只序列化非零字段的重实现会产生字节不同(但语义相等)的消息,并破坏任何 has-bit-sensitive consumer。
具名的 true-by-default bool 没有在 grep 预算内全部与 accessor 匹配;计数和 offset 列表是字节精确的,单个字段名按布局为 HIGH 置信度。可靠命名的 `true` 默认值(由与 accessor 锚定邻居相邻确认)包括与 `xla_backend_optimization_level` 同处 offsets 96–99 的四个 packed bool。
---
## Repeated-Enum 种子 — Command Buffer 列表
两个 `RepeatedField<int>` 成员通过 `GrowNoAnnotate` + index store 逐元素填充,而不是作为标量写入。二者都是 `CommandBufferCmdType` 枚举列表(枚举:`INVALID=0, FUSION=1, CUBLAS=2, CUDNN=3, COLLECTIVES=4, CONDITIONAL=5, WHILE=6, CUSTOM_CALL=7, CUBLASLT=8, DYNAMIC_SLICE_FUSION=9, …` — 见 [`debugoptions-proto.md`](debugoptions-proto.md))。
```c
// list at offset 160 (field 258 region) — 6 elements appended:
// 1, 2, 8, 7, 3, 9
// = FUSION, CUBLAS, CUBLASLT, CUSTOM_CALL, CUDNN, DYNAMIC_SLICE_FUSION
// list at offset 288 — 3 elements appended:
// 4, 5, 3
// = COLLECTIVES, CONDITIONAL, CUDNNappend 惯用法是同一个六行 RepeatedField<int>::GrowNoAnnotate / *((_DWORD *)this + 41) = newcount / array[idx] = enumval 块按元素重复(函数体第 98–285 行)。因此默认启用的 command-buffer 命令集是 {FUSION, CUBLAS, CUBLASLT, CUSTOM_CALL, CUDNN, DYNAMIC_SLICE_FUSION}。
| List offset | Element enum values | Decoded |
|---|---|---|
| 160 | 1, 2, 8, 7, 3, 9 | FUSION, CUBLAS, CUBLASLT, CUSTOM_CALL, CUDNN, DYN_SLICE_FUSION |
| 288 | 4, 5, 3 | COLLECTIVES, CONDITIONAL, CUDNN |
注意 — 两个列表是不同的 repeated 字段(不同 base offset:160 vs 288,并有各自独立的 count word:
this+41和this+73)。哪个是xla_gpu_enable_command_buffer(258)、哪个是第二个 command-buffer enable 列表,未在预算内消歧;二者都是 TPU 上惰性的 GPU-namespace 字段,但由于共享 upstream 函数体播种它们,所以仍被播种。
Map 种子 — Analytical Latency Estimator Options
构造器通过 Map::TryEmplaceInternal(函数体第 335–468 行)填充一个 map<string,string>(xla_gpu_analytical_latency_estimator_options,字段 357,约 offset 216),包含六个默认 key→value 对:
nccl_op_launch_us -> "-1"
nic_speed_gbps -> "-1"
chunk_prep_us -> "-1"
rtt_us -> "-1"
chunk_size_bytes -> "-1"
gpus_per_node -> "-1"
```text
每个值都是字符串 `"-1"`,即这些 GPU NCCL 建模旋钮的 AUTO/unknown sentinel。这里的 `-1` 约定是 [`autoproto-autoor-resolution.md`](autoproto-autoor-resolution.md) 中记录的同一个“稍后解析”sentinel 的字符串形式。在 TPU 上这些是惰性的(不会运行 GPU latency estimator),但共享函数体仍会播种它们。
| Key | Default value |
|---|---|
| `nccl_op_launch_us` | `"-1"` |
| `nic_speed_gbps` | `"-1"` |
| `chunk_prep_us` | `"-1"` |
| `rtt_us` | `"-1"` |
| `chunk_size_bytes` | `"-1"` |
| `gpus_per_node` | `"-1"` |
---
## 未触碰字段 — Proto-Zero 默认值
在 290 个字段中,构造器显式播种约 70 个 scalar/string + 2 个 repeated 列表 + 1 个 map。其余约 218 个字段在 `DebugOptions::DebugOptions(this, 0)` base 调用之后从未被写入,因此保持 proto3 零默认值:
| Field type | Untouched default |
|---|---|
| `bool` | `false` |
| `int32` / `int64` | `0` |
| `float` | `0.0` |
| `string` | `""` |
| `enum` | value-0 entry(例如 `StepMarkerLocation::STEP_MARK_AT_ENTRY=0`、`DetectionMode::DETECTION_MODE_NONE=0`、`ShapeChecks::IGNORE=0`) |
| `repeated` / `map` | empty |
> **注意 —** `xla_step_marker_location` (108) 由此构造器保留在 proto-zero `STEP_MARK_AT_ENTRY=0`:`DefaultDebugOptionsIgnoringFlags` @ `0x1e66a860` **没有**任何 store 写入 step-marker 字段的 offset。此构建中的任何非零 step-marker 默认值都来自 *flag* 层或 PJRT merge,而不是这个构造器。两个连接到 flag 的字段 `xla_tpu_detect_nan`(135,offset 580)和 `xla_tpu_detect_inf`(136)同样**没有**在这里写入,二者都因缺少 store 而保持 `false`。
>
> **坑点 —** “未触碰”只相对于*这个*函数。consumer 看到的有效运行时默认值是 `DefaultDebugOptionsIgnoringFlags()` 输出**随后**叠加 flag 层(`AllocateFlags`/`MakeDebugOptionsFlags`)和 PJRT `CompileOptions.debug_options` merge。此处为 proto-zero 的字段仍可能以非零值到达编译器。本页只是*第一*层;覆盖顺序见 [`xla-flag-atlas.md`](xla-flag-atlas.md)。
---