Skip to content

成本模型日志

地址适用于 libtpu-0.0.40-cp314 wheel 中的 libtpu.so(BuildID md5 89edbbe81c5b328a958fe628a9f2207d)。该二进制文件 strip — 下方每个符号都是解混淆后的 C++ 名称。.text/.rodata VMA == 文件偏移;.data.rel.ro VMA - 0x200000 == 文件偏移。其他版本会不同。

摘要

xla_tpu_impure_cost_model_logging_options 是控制 TPU 编译器逐 op 成本模型是否把自身工作转储到编译日志中的唯一开关。它是一个带副作用的可观测性标志:开启它不会改变发出的程序,只会改变 JAX 用户在成本分析输出中看到的内容。这种 "impure" 性质正是它在类型系统中位于当前位置的原因。它的值类型是 AutoOr<CostModelLoggingOptions>,即一个双字段 bool proto,但不同于此构建中的其他 330 个 AutoOr 标志,它不是 TpuCompilationEnvironment (TCE) AutoProto 字段 — 它通过普通的 absl::GetFlag 路径读取,因此永远不会进入经哈希、缓存、可复现编译的表面。它是第 31 个 AutoOr 类型,也是唯一位于 0x12fc____ 段而不是 0x1d7_____ jellyfish 段中的类型。

熟悉 abseil flags 的读者应把它映射到 ABSL_FLAG(AutoOr<T>, …) 惯用法:AutoOr<T> 是三态(AUTO / present-T),FlagImpl+0x58 缓存当前值指针,而 GetFlag 会从该指针上掩掉 2 位 init-lock 标签。它与普通 flag 的差异在于 AutoOr 包装器(一个 cmpb $0,+0x28 has-byte 测试,用于选择 AUTO 还是已存储的子消息),以及这个特定 flag 的消费者是成本模型构建器,而不是 TCE resolver。本页覆盖三件事:(1) 以 CreateCostModelWindowSettingDelegator 为中心的 flag 存储→解析→消费→日志路径;(2) 两个布尔值实际上会让 OpCostManager 分析日志输出什么;(3) 启用日志后用于序列化和解析成本值UnparseFloatingPointVal / SimpleAtod 浮点文本语法 — 重新实现者必须完全匹配的边界 token(infnan、科学计数法、十六进制浮点)。

对重新实现而言,契约是:

  • CostModelLoggingOptions 2-bool proto 布局,以及 AutoOr<CostModelLoggingOptions> 打包方式(present 字节、has 字节、子消息)。
  • 非 TCE 解析路径:内联的 FlagImpl+0x58 / FlagImpl::Read GetFlag 惯用法,以及它为什么绕过 TCE AutoProto resolver 家族。
  • 消费者接线:CreateCostModelWindowSettingDelegator 及其逐 HloInstruction 闭包,包括 field#2 双窗口成本门控。
  • enable_analysis_logging (field#1) 和 log_codegen_and_non_codegen_window_costs_in_analysis (field#2) 会导致 OpCostManager 输出什么。
  • 浮点文本往返语法:UnparseFloatingPointVal<T> 最短 %.*g 渲染并重新解析验证,以及 SimpleAtod/SimpleAtof 摄入时的 inf/nan/hex/overflow 边界行为。
Flag 对象FLAGS_xla_tpu_impure_cost_model_logging_options @ 0x22318950
Flag 类型AutoOr<CostModelLoggingOptions>(第 31 个 AutoOr 类型;非 TCE)
FlagOpsFlagOps<AutoOr<CostModelLoggingOptions>> @ 0x12fc0e00
默认值生成器AbslFlagDefaultGenFor…::Gen @ 0x12fc1260 → AUTO
AbslUnparseFlagxla::jellyfish::AbslUnparseFlag(AutoOr<…> const&) @ 0x12fd01a0
解析位置RunMemorySpaceAssignment @ 0x12fc3080(快速 0x12fc440b / 慢速 0x12fc46d3
消费者CreateCostModelWindowSettingDelegator @ 0x1304e100
消费者闭包逐 HLO DelegationInfo 调用器 @ 0x1304ff00
窗口选择器ShouldUseCodegenWindows @ 0x130d3d40
日志表面OpCostManager::AnalysisLoggingColumns @ 0x1e474c00 / AnalysisLoggingLine @ 0x1e475d20
浮点 unparseUnparseFloatingPointVal<float> @ 0x21113460 / <double> @ 0x211135a0
浮点摄入SimpleAtof @ 0x21171440 / SimpleAtod @ 0x21171580

CostModelLoggingOptions Proto

目的

CostModelLoggingOptions 是一个双字段、全 bool 的消息。它唯一的职责是在一个 AutoOr flag 中携带两个开关,用来控制成本模型日志的详细程度。schema 从生成的 _InternalSerializeTcParseTable 中恢复;两个字段名(enable_analysis_logginglog_codegen_and_non_codegen_window_costs_in_analysis)都作为 .rodata 描述符字符串逐字出现。

c
// xla::jellyfish::CostModelLoggingOptions
message CostModelLoggingOptions {
    optional bool enable_analysis_logging = 1;                                   // value byte @ +0x18
    optional bool log_codegen_and_non_codegen_window_costs_in_analysis = 2;       // value byte @ +0x19
}
// InternalMetadata @ +0x08 ; has-bits uint32 @ +0x10 (bit0=field#1, bit1=field#2)
```text

### 编码

字节布局已由 `CostModelLoggingOptions::_InternalSerialize` @ `0x1db24760` 确认。生成代码读取 `*((DWORD*)this + 4)`(偏移 `+0x10`)处的 has-bits word,然后对 field#1(wire tag `0x08`)发出 `this+24`(`+0x18`)处的字节,对 field#2(wire tag `0x10`)发出 `this+25`(`+0x19`)处的字节:

```c
function _InternalSerialize(this, out):                 // sub_1DB24760
    hasbits = *(u32*)(this + 0x10)
    if (hasbits & 1) && *(u8*)(this + 0x18) == 1:        // field#1 set & true
        emit 0x08, *(u8*)(this + 0x18)                    // tag, value
    if (hasbits & 2) && *(u8*)(this + 0x19) == 1:        // field#2 set & true
        emit 0x10, *(u8*)(this + 0x19)                    // tag, value

TcParseTable _table_ @ 0x21cfa1e8(大小 0x78)以 has_bits_offset 0x10(第一个 dword)开头 — 除了这两个布尔字段之外没有其他字段。Clear 位于 0x1db24740

注意 — 这两个布尔值是独立的可观测性级别,而不是计数。Field#1 (enable_analysis_logging) 打开逐 op 成本转储。Field#2 (log_codegen_and_non_codegen_window_costs_in_analysis) 是一个拓宽器:它让转储同时输出 codegen-window 和 good-enough-window 两种成本变体,使逐 op 的窗口策略差异可见。除非 field#1 也被设置,否则 field#2 没有效果 — 见消费者闭包


AutoOr 存储和非 TCE 解析路径

目的

该 flag 将其值存储为 AutoOr<CostModelLoggingOptions> — 一个三态包装器,要么是 AUTO 哨兵,要么是一个 present 的 CostModelLoggingOptions。让这个 flag 在结构上独特的是它的解析方式:通过普通 abseil GetFlag 惯用法(FlagImpl+0x58 缓存指针),而不是通过 AutoOr<T>::FromProtoOrDie TCE resolver。二进制中没有 AutoOr<CostModelLoggingOptions>::FromProtoOrDie,也没有 AutoOrTypeTraits<CostModelLoggingOptions>::FromAutoProto 符号 — 330 个 TCE AutoProto 字段所使用的整个 FromProto resolver 家族对该类型都不存在。这种缺失就是 "impure" flag 的二进制指纹。

AutoOr 布局

AutoOr<message> 布局直接从 AbslUnparseFlag @ 0x12fd01a0 读取,该函数基于 has-byte 做门控并复制变体:

字段偏移含义
子消息体+0x00嵌入的 CostModelLoggingOptions(或 const Msg* 变体)
variant index+0x20variant<Msg, const Msg*> 判别器
has byte+0x280 => AUTO / 默认;非零 => present message

默认值生成器确认了 AUTO

c
function AbslFlagDefaultGenFor…::Gen(this):              // sub_12FC1260
    *(u8*)(this + 0x00) = 0     // present/body byte
    *(u8*)(this + 0x28) = 0     // has byte = 0  ⇒  AUTO
```text

### 解析算法

`RunMemorySpaceAssignment` @ `0x12fc3080`(`BuildOpCostManager` 调用者)在 `0x12fc440b` 以内联方式读取 flag,使用规范的 `GetFlag(FLAGS_…)` 序列:

```c
function ResolveCostModelLoggingOptions():               // inline @ 0x12fc440b
    p = *(void**)(FLAGS_…cost_model_logging_options + 0x58)   // FlagImpl+0x58 cached ptr
    if (p & 3) != 0:                                          // 2-bit absl init-lock tag set
        goto slow                                            // 0x12fc46d3: FlagImpl::Read @0x21111940
    autoor = (AutoOr<CostModelLoggingOptions>*)(p & ~3)      // mask tag bits
    if *(u8*)(autoor + 0x28) == 0:                           // has byte == 0
        return AUTO/empty default                            // use the default-instance
    idx = *(u8*)(autoor + 0x20)                              // variant index @ +0x20
    return copy_sub_message(autoor)                          // pass to delegator builder

0x12fc46d3 处的慢路径调用 absl::flags_internal::FlagImpl::Read(void*) @ 0x21111940(懒惰 first-touch 初始化器)。这是普通的 abseil 模式;唯一的 AutoOr 特有部分是 cmpb $0,+0x28 has-byte 测试和 +0x20 变体复制。

怪癖 — 这个 flag 的类型是 AutoOr,但不存在于 1121 字段的 TpuCompilationEnvironment::_table_(@ 0x21cfa9e0)中。此构建中的其他每个 AutoOr flag(330 个)都是通过 FromProtoOrDie 解析的 TCE AutoProto 字段。假设“所有 AutoOr flags 都是 TCE 字段”的重新实现者会寻找一个并不存在的 resolver。xla_tpu_impure_* 前缀标记了有意排除在经哈希/缓存的确定性 TCE 表面之外的 flag,因为它们改变的是编译器可观测性,而不是编译结果。

Unparse — AUTO -> "auto"

AbslUnparseFlag(AutoOr<CostModelLoggingOptions> const&) @ 0x12fd01a0 是往返的 OUT 半边。如果 has-byte(+0x28)被设置,它会分派到 proto2::Message::AbslUnparseFlagImpl(TextFormat,带 text:/serialized:/base64: fallback);否则,它会从一个懒惰静态 absl::NoDestructor<std::string> 构造字面量 "auto",该静态对象通过 __cxa_guard + PlacementImpl 从所有 AutoOr unparse 实例共享的 "auto" 源字面量构造一次:

c
function AbslUnparseFlag(out, autoor):                   // sub_12FD01A0
    if *(u8*)(autoor + 0x28):                            // has byte set
        return Message::AbslUnparseFlagImpl(out, …)      // text:/serialized:/base64:
    once: AutoFlagValue = NoDestructor<string>("auto")   // __cxa_guard-guarded
    return copy(out, AutoFlagValue)                      // "auto"
```text

### 函数映射

| 函数 | 地址 | 作用 |
|---|---|---|
| `FlagOps<AutoOr<CostModelLoggingOptions>>` | `0x12fc0e00` | flag 存储 TypeId(FlagImpl `+0x20`) |
| `AbslFlagDefaultGenFor…::Gen` | `0x12fc1260` | 设置 present `+0x00`=0、has `+0x28`=0 → AUTO |
| `AbslUnparseFlag(AutoOr<>)` | `0x12fd01a0` | AUTO→`"auto"`,present→TextFormat |
| `RunMemorySpaceAssignment` | `0x12fc3080` | 解析位置(快速 `0x12fc440b` / 慢速 `0x12fc46d3`) |
| `FlagImpl::Read` | `0x21111940` | 懒惰 first-touch 慢路径初始化器 |

---

## 消费者 — CreateCostModelWindowSettingDelegator

### 目的

解析后的 `CostModelLoggingOptions` 由 `CreateCostModelWindowSettingDelegator` @ `0x1304e100` 消费。它构造一个名为 `"CostModelWindowSettingDelegator"` 的 `OpCostManager::CalculationNode`,逐 HLO instruction 决定应计入哪一种窗口成本策略 — 并且在启用日志时同时计入*两者*,从而让分析转储展示差异。

### 签名和捕获

函数签名(由解混淆符号确认)是:

```c
CreateCostModelWindowSettingDelegator(
    string_view name,
    CostModelFlagOptions const& flag_opts,
    CostModelLoggingOptions const& log_opts,          // the resolved AutoOr value
    unique_ptr<CalculationNode> codegen_node,         // "CostModelWithCodegenWindows"
    unique_ptr<CalculationNode> good_enough_node)     // "CostModelWithGoodEnoughWindows"

它构造一个 AnyInvocable 闭包,按值捕获 CostModelFlagOptions(捕获 +0x00)和 CostModelLoggingOptions(捕获子对象 +0x48,因此 field#2 在 msg+0x19 处的字节落在捕获 +0x61),以及两个子 calculation node。两个子节点名称字符串是 "CostModelWithCodegenWindows""CostModelWithGoodEnoughWindows";delegator 节点名是 "CostModelWindowSettingDelegator";它路由的叶子成本源是 "TpuHloCostAnalysis" — 见 TpuHloCostAnalysis

消费者闭包(逐 HLO) {#the-consumer-closure-per-hlo}

HloInstruction 调用器 @ 0x1304ff00 是一个 RemoteInvoker,返回 CalculationNode::DelegationInfo,并接受 (HloInstruction const&, bool)。该 bool 是一个“是否为 analysis-logging pass”的标志 — 它与 field#2 组合后触发双重 push。下方的 cap 是 lambda 捕获结构(其第一个 qword 被加载到 v7 = *a2):cap+0x00CostModelFlagOptionscap+0x48CostModelLoggingOptionscap+0x68/cap+0x70 是两个捕获的子 CalculationNode 指针。result 是返回的 DelegationInfo,在 result+0x00(codegen)和 result+0x18(good-enough)处有两个 vector<uint64>。反编译体:

c
function WindowSettingClosure(cap, hlo, is_logging_pass): // sub_1304FF00
    result = {}                                          // zero two slot vectors @ +0x00,+0x18
    if ShouldUseCodegenWindows(hlo, cap.flag_opts):      // sub_130D3D40
        result.codegen.push_back(cap + 0x68)             // charge codegen node ptr
        if !is_logging_pass:                  return result
        if *(u8*)(cap + 0x61) == 0:           return result // field#2 clear (cap+0x48 +0x19)
        result.good_enough.push_back(cap + 0x70)         // ALSO charge good-enough node ptr
    else:
        result.codegen.push_back(cap + 0x70)             // charge good-enough node ptr
        if is_logging_pass && *(u8*)(cap + 0x61):
            result.good_enough.push_back(cap + 0x68)     // ALSO charge codegen node ptr
    return result
```text

> **陷阱 —** 反编译器把 `cap+0x68`、`cap+0x70` 和 field#2 字节 `cap+0x61` 都渲染为相对于同一基址寄存器(`v7`),这会让两个 `push_back` 参数看起来像是从 `HloInstruction` 读取。它们并不是:`v7` 是*捕获*结构,`+0x68`/`+0x70` 是被推入结果向量(`_RDI` 和 `_RDI+3`)的两个捕获子节点指针,`+0x61` 是捕获的 `CostModelLoggingOptions` 内部的 field#2(捕获 `+0x48` + 消息字节 `+0x19` = `+0x61`)。`HloInstruction&` 作为转发参数传入,并被直接传给 `ShouldUseCodegenWindows`。捕获布局由 `CreateCostModelWindowSettingDelegator` @ `0x1304e100` 固定,它对捕获执行 `operator new(0x78)`,并把 `CostModelFlagOptions` 复制到 `+0x00`、`CostModelLoggingOptions` 复制到 `+0x48`、子指针复制到 `+0x68`。

净行为:field#2 清除时,每个 op 只计入一种窗口成本变体(由 `ShouldUseCodegenWindows` 选择的那一种)。field#2 设置**** logging pass 活跃时,两种变体都会被计入,因此分析日志可以打印逐 op 的 codegen-vs-good-enough 成本差异。

### 窗口选择器 — ShouldUseCodegenWindows

`ShouldUseCodegenWindows` @ `0x130d3d40` 决定资格。它从 `CostModelFlagOptions` 读取一个 repeated fusion-window enum 列表(指针/计数在 `+0x30` 附近),并对每个 enum 值按 HLO fusion kind 走 jump-table:

```c
function ShouldUseCodegenWindows(hlo, flag_opts):        // sub_130D3D40
    if (hlo.flags & 1) == 0:               return false   // not a fusion
    list = flag_opts.window_kinds_ptr; n = flag_opts.window_kinds_count
    for kind in list[0..n]:
        switch kind:
            case 0:  return true                          // sentinel/terminator
            case 1:  if hlo.IsOutputFusion():  return true // @0x1e5a2fc0
            case 2:  if fusion_util::IsConvLowerable(hlo): return true  // @0x14553620
            case 3:  if hlo.IsLoopFusion():    return true // @0x1e5a2fa0
    return false

NeverUseCodegenWindows @ 0x130d3e80 是取反/覆盖的 sibling,也从 BuildOpCostManager 调用。

函数映射

函数地址作用
CreateCostModelWindowSettingDelegator0x1304e100构建 delegator 节点;按值捕获 CostModelLoggingOptions
window-setting closure (RemoteInvoker)0x1304ff00逐 HLO DelegationInfo;field#2 (+0x61) 门控双重计费
ShouldUseCodegenWindows0x130d3d40codegen-window 资格(fusion-kind jump-table)
NeverUseCodegenWindows0x130d3e80取反/覆盖 sibling
CostModelLoggingOptions ctor (capture)0x1db24640将消息复制到捕获 +0x48

会记录什么

Field#1 — enable_analysis_logging

设置 field#1 时,成本模型运行会通过两个 OpCostManager 方法发出一个逐 op 表格转储:

  • OpCostManager::AnalysisLoggingColumns() const @ 0x1e474c00 — 发出表头行(列标签:cost-metric IDs)。
  • OpCostManager::AnalysisLoggingLine(CostMetricId const&, CalculationNode::Result const&) const @ 0x1e475d20 — 每个 (cost metric, HLO op) 发出一行,读取每个 calculation node 产生的 Result

因此 field#1 的可观测副作用是:对每个 HLO op,把每个 calculation node(TpuHloCostAnalysis、codegen-window 节点、good-enough-window 节点)产生的成本值转储到编译日志。发出的代码不会改变 — 这是纯粹的编译期可观测性。

Field#2 — log_codegen_and_non_codegen_window_costs_in_analysis

Field#2 会拓宽这些行。如消费者闭包所示,它让 window-setting delegator 在分析 pass 中同时计入 codegen-window 和 good-enough-window 成本,因此每个日志行都携带两种变体,逐 op 的 codegen-vs-good-enough 差异可见。

注意 — field#1 锁存到逐 pass “发出 AnalysisLoggingColumns/Line” 决策中的确切 OpCostManager 成员偏移此处没有固定下来(delegator 捕获整个消息;门控日志发出的 field#1 读取点位于 OpCostManager metric-value / compute 路径中,即 GetMetricValue @ 0x1e475160 / ComputeSeconds @ 0x1e475a40)。Field#1 启用转储,field#2 扩宽转储;精确的 latch 偏移是这里唯一未闭合的接缝。

函数映射

函数地址作用
OpCostManager::AnalysisLoggingColumns0x1e474c00表头行(列标签)
OpCostManager::AnalysisLoggingLine0x1e475d20每个 (metric, HLO) 一行
OpCostManager::GetMetricValue0x1e475160metric 读取路径(field#1 latch — 未追踪)
OpCostManager::ComputeSeconds0x1e475a40逐 op seconds 计算(未追踪)

浮点文本语法

记录的成本值是 float 和 double,它们会两次跨越文本边界:由 UnparseFloatingPointVal<T> 序列化输出,再由 SimpleAtof/SimpleAtod 解析回来。这与任何 AutoOr<float>/AutoOr<double> knob 使用的是同一种 float-flag 语法,而其边界 token(infnan、科学计数法、十六进制浮点)正是天真的重新实现会产生分歧的地方。

Unparse — 最短往返 %.*g

UnparseFloatingPointVal<float> @ 0x21113460<double> @ 0x211135a0 会渲染出重新解析后得到完全相同 bit pattern 的最短十进制。算法是先尝试低精度、再验证、再提升:

c
function UnparseFloatingPointVal<float>(value):          // sub_21113460
    s = FormatPack("%.*g", 6, value)                     // 6 sig-figs (try short)
    if (bits(value) & 0x7FFFFFFF) >= 0x7F800000:         // exponent all-ones = inf/nan
        return s                                         // accept libc %g "inf"/"-inf"/"nan", SKIP verify
    if SimpleAtof(s, &v) && v == value:                  // vucomiss exact reparse check
        return s                                         // 6 sig-figs reparses exactly
    return FormatPack("%.*g", 9, value)                  // FLT_DECIMAL_DIG = 9, guaranteed exact
```text

`<double>` 相同,只是精度为 15 然后 17(`DBL_DECIMAL_DIG = 17`),inf/nan 测试为 `bits & 0x7FFFFFFFFFFFFFFF >= 0x7FF0000000000000`,并用 `SimpleAtod` + `vucomisd` 做重新解析验证。

> **怪癖 —** 精度常量是从反汇编中逐字节走读得到的:float 路径在 `0x21113474` 处为短尝试具现化 `movq $0x6,-0x68(%rbp)`,在 `0x2111352b` 处为 fallback 具现化 `movq $0x9,-0x68(%rbp)`;double 路径具现化 `$0xf` (15) @ `0x211135b4` 和 `$0x11` (17) @ `0x2111367d`。反编译 C 把精度渲染成字面量 `4`,因为这个 `4` 是传给 `FormatPack` 的 `mov $0x4,%edx` *参数数量*,不是 `%.*g` 精度 — 精度被放在栈上 `-0x68` 处的 format-arg pack 中,而反编译器把它折叠掉了。应信任反汇编的 `0x6`/`0x9` 和 `0xf`/`0x11`,而不是渲染出的 `4`。

结果是:如果一个 `float` 的最近 6 位十进制已经能精确重新解析(例如存储的 `1.10000002f`,其最短拼写是 `1.1`),它会打印 `"1.1"`。需要全部 9 位的值会 fallback 到 9 位有效数字。没有尾随零噪声;使用规范的 `%g` 拼写,而 `inf`/`-inf`/`nan` 会通过 exponent-all-ones 绕过路径直接从 libc `%g` 发出,不尝试重新解析。

### 摄入 — SimpleAtof / SimpleAtod

`SimpleAtof` @ `0x21171440` 和 `SimpleAtod` @ `0x21171580` 将 string-view 解析为 float/double。`SimpleAtod` 的反编译确认了四阶段语法:

```c
function SimpleAtod(begin, end, out):                    // sub_21171580
    *out = 0
    strip leading  ws while kPropertyBits[c] & 8         // table @ 0xbe7fb70, bit 0x8 = whitespace
    strip trailing ws while kPropertyBits[c] & 8
    if empty:                              return false   // nothing left
    if *p == '+':                                         // bare-sign guard
        if length==1 || p[1]=='-':         return false
        p++                                              // skip the '+'
    q = from_chars(p, end, out, /*fmt=*/3)               // @0x2116a340, chars_format = general (3)
    if errc(q) == 22 || q.ptr != end:                    // 22 = invalid_argument; or trailing garbage
        return false
    if errc(q) == 34:                                    // 34 = result_out_of_range (overflow)
        clamp *out to ±inf                               // sign via vucomisd vs ±1.0 constants
    return true                                          // full-consume, value (or clamped inf) stored

from_chars 使用 chars_format = 3 = scientific | fixedgeneral 格式)调用。hex bit(0x4)未设置,因此 from_chars 内部的 hex-float 分支(test $0x4,%cl @ 0x2116a373/0x2116a380)永远不会被走到:0x/0X 前缀会导致解析失败,而不是被当成十六进制解析。

陷阱 — 两个 errc 码很容易调换。errc(q) == 22std::errc::invalid_argument — 硬拒绝(函数返回 false)。errc(q) == 34std::errc::result_out_of_range溢出情形,会被接受*out 被夹到 ±inf(符号通过针对 qword_A2DF230/qword_A2DE728±1.0 常量的 vucomisd 选择),函数返回 trueSimpleAtod @ 0x21171580SimpleAtof @ 0x21171440 共享这个完全相同的 !=22 && ptr==end、然后 ==34 结构。

边界 Token 表

任何 float/double AutoOr knob 值可接受/拒绝的 token 集(确切的 inf/nan 关键字拼写集合取决于 abseil 的 from_chars 关键字路径接受什么):

Token摄入Unparse 渲染
autoAUTO 哨兵"auto"
1.5 / -0.25OK(general)最短 %g(6/15 然后 9/17 位有效数字)
1e9 / 1E-3OK(scientific)最短 %g
inf / -inf / InfinityOK → ±inf"inf" / "-inf"
nan / NAN / nan(0x1)OK → nan(payload)"nan"
overflow(例如 1e400OK → CLAMP 到 ±inf"inf" / "-inf"
0x1.8p3 / 0x10(hex-float)REJECT(fmt 没有 hex bit)n/a(从不存储)
"" / "+" / "-" / " "REJECT(空 / 裸符号)n/a
leading/trailing whitespace被剥离(kPropertyBits & 0x8n/a

陷阱 — float/double AutoOr knobs 接受 inf/nan,并把溢出夹到 ±inf,但拒绝十六进制浮点 — 不同于整数 AutoOr knobs,后者通过 safe_strto*_base 接受 0x 基数。把所有 numeric knobs 都路由到一个解析器的重新实现者,会错误地把 0x10 作为 float knob 的 16.0 接受。还要注意整数侧的基数不对称:int knobs 摄入 hex,但始终以十进制 unparse。float unparse 从不产生基数歧义(始终是 %g 十进制)。

函数映射

函数地址作用
UnparseFloatingPointVal<float>0x21113460最短 %.*g 6→9,inf/nan 绕过,重新解析验证
UnparseFloatingPointVal<double>0x211135a0最短 %.*g 15→17,inf/nan 绕过
SimpleAtof0x21171440WS-strip + sign-guard + from_chars(fmt=3) float
SimpleAtod0x21171580WS-strip + sign-guard + from_chars(fmt=3) double
from_chars (float)0x2116ada0general 格式;hex bit 清除;±inf clamp 常量
from_chars (double)0x2116a340general 格式;nan@plt 关键字路径
kPropertyBits0xbe7fb70ASCII 属性表;bit 0x8 = whitespace

Sibling 非 TCE AutoOr Flags

xla_tpu_impure_cost_model_logging_options 是恰好五个不是 TCE AutoProto 字段的 AutoOr 类型 flag 之一。其他四个共享“通过 GetFlag 读取,而不是通过 TCE resolver 读取”的性质。这里列出它们,是因为枚举 AutoOr flag 表面的重新实现者必须将它们纳入考虑 — 完美的 330 ↔ 330 AutoOr ↔ AutoProto 恒等关系恰好有这五个残余项。

FlagFlagOps内部类型默认值消费者
xla_tpu_impure_cost_model_logging_options0x12fc0e00CostModelLoggingOptionsAUTOCreateCostModelWindowSettingDelegator @ 0x1304e100
xla_tpu_impure_use_iteration_mask0x1d6b5840boolAUTO (=ON)ShouldUseIterationMask @ 0x1d6b5dc0
xla_tpu_comparison_mode_target_module_regex0x1d700400stringAUTOEnableComparisonMode @ 0x1d6b8ec0(RE2 vs module name)
xla_tpu_enable_lem_scheduler0x1d6b5840boolAUTOregistry-mediated(无直接 FLAGS_ xref)
xla_tpu_explicit_evict_memory_limit_kib0x1d700120int64AUTOregistry-mediated(无直接 FLAGS_ xref)

注意 — xla_tpu_impure_use_iteration_mask 的极性是 AUTO=ON:它的消费者读取 FlagImpl+0x58,执行 and $0x101 ; cmp $0x100 ; setne — 除非用户显式设置 =false,否则为 true,并且还会由 TC version ≥ 3 门控。enable_lem_schedulerexplicit_evict_memory_limit_kib.text没有直接 lea FLAGS_… 引用;它们的有效读取通过某个内联 GetFlag<T> 路径经由 absl flag registry 进行,静态 FLAGS_ 地址扫描无法定位。


相关组件

组件关系
TpuHloCostAnalysisdelegator 路由的叶子成本源("TpuHloCostAnalysis");它的 float costs 就是日志语法序列化的内容
成本模型概览逐代成本模型架构,其 OpCostManager 运行被记录的 calculation-node 树
学习型成本模型客户端sibling AutoOr<message> 成本模型 knob(EmitterLearnedCostModelOptions);为什么发布的模型是数据表驱动
Resource Enum(23 槽)成本值最终归约到的 ResourceVector 模型

交叉引用