Skip to content

TpuConfigurationApi

本页所有地址均适用于来自 libtpu-0.0.40-cp314 wheel 的 libtpu.so(构建 libtpu_lts_20260413_b_RC00,build-id md5 89edbbe81c5b328a958fe628a9f2207d,781,691,048 字节,ELF x86-64 DYN,未 stripped;IDA 恢复的 C 名称和反修饰后的 C++ 符号均按原文引用)。.text VMA 等于文件偏移。其他版本会不同。

摘要

TpuConfigurationApi_*分布式 TPU 宿主配置的 C-ABI 正面接口:它负责把一机架 TPU 芯片启动为一个可寻址的 pod,并负责宿主进程对该 pod 发出的查询。开源 TensorFlow tpu_configuration_ops kernel(ConfigureDistributedTPUWaitForDistributedTPU_InitializeHostForDistributedTPU_SetGlobalTPUArray_DisconnectHostFromDistributedTPUSystem)正是通过这个表面调用,方式与这些 kernel 调用 TpuExecutor_* 进行设备工作完全一样。TfTpu_Initialize Bootstrap进程内驱动初始化(单个节点加载 libtpu 驱动核心),而此集群是跨宿主 pod 配置:它协商全局 TPU 数组,等待每个宿主加入,并向运行时暴露每个宿主的容量。

从结构上看,该集群有两层。下层是一组 extern "C" 自由函数,即本页负责的 C-ABI 名册;每个函数都是薄桥,将扁平 op-args 结构解组为真实 C++ 调用,并把生成的 absl::Status 加输出数组重新编组出去。上层是这些桥委托到的 tensorflow:: 命名空间 C++ 自由函数(tensorflow::ConfigureDistributedTputensorflow::WaitForDistributedTpu 等);它们承载真实 mesh 逻辑,由 runtime/pod 页面负责,不在这里负责。名册按领域清晰分为五个 *Op_DoWork 动作(configure / wait / init-host / set-global-array / disconnect)、三个 pod/cache 查询HasTPUPodStateTpusPerHostTpuMemoryLimit,以及 compilation-cache server-address 三件套)和两个数组释放辅助函数FreeCharArrayFreeInt32Array)。

这是一个名册页面。它清点 C-ABI 函数、它们的实现符号 + 地址、每个 *Op_DoWork 读取的 op-args 布局,以及每个桥委托到的 C++ 入口。它不重新推导 ApiFn/不透明句柄 ABI 模型(由 The TfTpu C-API Shim负责)、驱动 bootstrap(由 TfTpu_Initialize Bootstrap负责)或 megascale collective bring-up(由 Megascale Bootstrap负责)。它负责 TpuConfigurationApi_* 名册和 distributed-pod-config 入口映射。

对于重新实现,契约是:

  • 名册:约 13 个 extern "C" 自由函数、它们的地址,以及每个函数桥接到哪个 C++ 入口。
  • op-args ABI:每个 *Op_DoWork 接收一个指向扁平结构的指针,其固定字节偏移保存输入(int32 数组 + 长度、string-view ptr + length、flags)和输出槽(status-cell ptr、*out_size ptr、**out_array ptr)。桥不拥有策略;它只复制字段、调用并写回。
  • status/output-array 协议:每个动作都通过把 absl::status_internal::StatusRep* 存入调用方拥有的 status cell 来返回其 absl::Status(遵循 refcount 纪律),并发出一个堆分配的输出数组(int32[] 或 NUL 结尾 char[]),调用方必须通过 FreeInt32Array / FreeCharArray 释放。
源文件(按 .rodatalearning/45eac/tfrc/executor/stream_executor/tpu_config_c_api.cc
名册规模约 13 个 extern "C" 自由函数(5 个动作、6 个查询、2 个释放辅助函数)
动作地址块0xe8cd4000xe8cdb80(五个 *Op_DoWork
查询/释放地址块0xe8cdbc00xe8cdf80TpuConfigurationApi_*
到达方式ExecutorApiFn() 表(device-runtime 访问器)— 见 overview
跨接缝状态类型写入调用方 status cell 的 absl::status_internal::StatusRep*
输出所有权callee 用 operator new / array new 分配;调用方通过 Free{Char,Int32}Array 释放
证据等级已按 IDA 反编译逐字节确认;名册计数 CERTAIN

范围 — *ApiFn 访问器/探测模型和不透明句柄(ToC/FromC/Destroy)约定在 The TfTpu C-API Shim 中;本页只记录搭载这些表的 TpuConfigurationApi_* 集群。对比 TfTpu_Initialize Bootstrap:那是单节点驱动初始化;这里是多宿主 pod 配置。


1. 名册

三个区域,一张表。“Impl symbol + address” 是 libtpu.so 中的 extern "C" 桥(IDA 恢复名称);“Bridges to” 是它委托到的 tensorflow:: C++ 自由函数。桥地址来自反编译符号地址后缀(_0xADDR.c);它们是精确的。

动作(*Op_DoWork

C-ABI 函数地址桥接到(tensorflow::角色
ConfigureDistributedTpuOp_DoWork0xe8cd400ConfigureDistributedTpu0xe975cc0从此宿主的芯片列表协商全局 TPU mesh;发出序列化 pod topology
WaitForDistributedTpuOp_DoWork0xe8cd640WaitForDistributedTpu0xe9767c0阻塞直到每个宿主的 per-core mapping 都到达;发出合并后的 mesh-common-state blob
InitializeHostForDistributedTpuOp_DoWork0xe8cd9a0InitializeHostForDistributedTpu0xe9771c0将此宿主绑定进已配置 pod;发出本地 core-id int32 数组
SetGlobalTPUArrayOp_DoWork0xe8cda80SetGlobalTPUArray0xe977880把 pod-wide topology proto(字符串)安装进全局状态;仅 status
DisconnectDistributedTpuChipsOp_DoWork0xe8cdb80DisconnectDistributedTpuChips0xe977aa0将宿主从 pod 中拆离;仅 status

查询(pod state + compilation-cache server)

C-ABI 函数地址桥接到(tensorflow::角色
TpuConfigurationApi_HasTPUPodState0xe8cdca0HasTPUPodState0xeaa17c0),经由 GetTPUConfigResourceMgr0x10854020谓词:config ResourceMgr 中是否注册了 pod-state resource?
TpuConfigurationApi_TpusPerHost0xe8cdc00TpusPerHost0xe9742a0Out-param int32:连接到此宿主的 TPU 芯片数
TpuConfigurationApi_TpuMemoryLimit0xe8cdc40TpuMemoryLimit0xe974440Out-param int64(一个 tsl::gtl::IntType<Bytes_tag_>):每 core HBM 字节预算
TpuConfigurationApi_RemoteCompilationCacheSizeInBytes0xe8cdcc0读取 FLAGS_tpu_remote_compilation_cache_size_bytesOut-param int64:远程 compile-cache 最大大小;CHECK ptr 非空且值 >= 0
TpuConfigurationApi_CompilationCacheServerAddressFromConfig0xe8cdda0解析 tensorflow::tpu::TPUHostConfiguration proto从序列化 TPUHostConfiguration 解码 compile-cache server 地址;发出 char[]
TpuConfigurationApi_GetServerAddressAndPort0xe8cdf80GetServerAddressAndPort0xe975a60FLAGS_uberdriver_port + FLAGS_tpu_hostname_override 解析 compile-cache server host:port;发出 char[]

释放辅助函数

C-ABI 函数地址函数体角色
TpuConfigurationApi_FreeCharArray0xe8cdbc0if (p) free(p);释放查询产生的 char[]
TpuConfigurationApi_FreeInt32Array0xe8cdbe0if (p) free(p);释放动作产生的 int32[]

注意 — 文件字符串 tpu_config_c_api.cc(可在 RemoteCompilationCacheSizeInBytesCHECK 位置第 158 行和 CompilationCacheServerAddressFromConfig 错误位置第 175 行看到)确认所有三个三件套都位于一个翻译单元。*Op_DoWork 符号在 IDA 中没有 TpuConfigurationApi_ 前缀,但它们共享同一个源文件和相同的 op-args 桥接模式,因此这里把它们作为一个集群记录。

陷阱 — 两个释放辅助函数是原始 free(),不是 array-delete。它们释放的数组由动作内部的 operator new / operator new[] 产生(例如 InitializeHostForDistributedTpuOp_DoWork 执行 **(a1+48) = operator new(4*n)),然后作为普通指针交回。重新实现者必须用释放方式与 free 兼容的分配器(malloc-backed operator new)来分配输出数组,并且不得运行析构函数:这些是 POD int32/char 缓冲区。只通过这些辅助函数释放;绝不要 delete[] 它们。


2. Op-Args ABI

每个 *Op_DoWork 都接收一个指向扁平 op-args 结构的指针,开源 kernel 会在调用前填充它,并在调用后读取它。桥没有策略:它从固定偏移复制输入,调用 C++ 入口,然后把 status 和输出数组写回固定偏移。接缝上没有 C++ 类型,只有 args 指针、其中的 POD 标量,以及写入 status cell 的 StatusRep*

ConfigureDistributedTpuOp_DoWork0xe8cd400

最丰富的布局。输入是此宿主的芯片坐标 int32 数组;输出是序列化 pod-topology 字节字符串。

c
// op-args struct read by ConfigureDistributedTpuOp_DoWork(a1)
struct ConfigureArgs {
    /* +0   */ void*    self;            // op object (unused by bridge)
    /* +16  */ uint64_t num_chips;       // length of the int32 array  (a1+16)
    /* +24  */ int32_t* chip_array;      // host chip coords           (a1+24)
    /* +32  */ int64_t  arg3;            // span/extra (>=0 guarded)    (a1+32)
    /* +40  */ void*    arg4;            // string_view-ish input       (a1+40)
    /* +48  */ uint64_t* out_size;       // *out_size = topology length (a1+48)
    /* +56  */ char**    out_blob;       // *out_blob = new char[size]  (a1+56)
    /* +64  */ StatusRep** status_cell;  // result Status               (a1+64)
};

function ConfigureDistributedTpuOp_DoWork(args):              // sub_e8cd400
    chips = copy_int32_array(args.chip_array, args.num_chips)  // grows a vector, may realloc
    status = tensorflow::ConfigureDistributedTpu(             // 0xe975cc0
                 chips, args.num_chips, args.arg4, args.arg3, &out)
    store_status(args.status_cell, status)                    // refcount discipline, §3
    n = small_string_size(out)
    *args.out_size  = n
    *args.out_blob  = operator new(n)
    memmove(*args.out_blob, small_string_data(out), n)
    free_temporaries(chips, out)
```text

芯片数组复制循环(第 4077 行)是手工内联的 `std::vector<int>` grow:它会把容量翻倍,防护 `0x3FFFFFFFFFFFFFFF` 元素计数上限,并在溢出时抛出 `vector<int>::__throw_length_error` / `__throw_bad_array_new_length`。输出 blob 处理(第 109135 行)读取 small-string-optimization 判别位(`v25` 符号位),以选择返回 topology 字节的内联存储还是堆存储,即把标准 `absl`/`std::string` SSO 布局作为原始 `data`+`size` 跨过去。

### `WaitForDistributedTpuOp_DoWork`(`0xe8cd640`)

输入是一个 **2-D** 结构:每宿主 `int32` vector 的 vector(从每个宿主收集的 per-core mappings)。桥把它重建为 `vector<vector<int>>`,调用 `WaitForDistributedTpu`,并发出合并后的 mesh-common-state blob。

```c
// op-args struct read by WaitForDistributedTpuOp_DoWork(a1)
struct WaitArgs {
    /* +16 (a1[2]) */ uint64_t num_hosts;     // outer dimension
    /* +24 (a1[3]) */ uint64_t cores_per_host;// inner dimension
    /* +32 (a1[4]) */ int32_t** host_arrays;  // num_hosts pointers to int32[]
    /* +40 (a1[5]) */ void*     mesh_state;    // TpuMeshCommonState* (in/out)
    /* +48 (a1[6]) */ uint64_t* out_size;
    /* +56 (a1[7]) */ char**    out_blob;
    /* +64 (a1[8]) */ StatusRep** status_cell;
};

function WaitForDistributedTpuOp_DoWork(args):                // sub_e8cd640
    mappings = vector<vector<int>>(args.num_hosts)            // __append reserves outer
    for h in 0 .. num_hosts:                                  // nested grow loops
        for c in 0 .. cores_per_host:
            mappings[h].push_back(args.host_arrays[h][c])
    status = tensorflow::WaitForDistributedTpu(               // 0xe9767c0
                 mappings.data, mappings.size, args.mesh_state, &out)
    store_status(args.status_cell, status)
    emit_char_blob(args.out_size, args.out_blob, out)
    destroy(mappings)                                          // frees every inner vector

怪异点 — 内层循环的 trip count 在内层 body 每次迭代都会从 args.cores_per_hostv2[3])重新读取(第 117 行),而不是缓存一次。反编译显示当计数瞬时为零时有一个 while (!v6) skip。重新实现者应把 cores_per_host 视为权威内层边界,但必须容忍运行时修改它:二进制选择防御性重读,而不是快照。

InitializeHostForDistributedTpuOp_DoWork0xe8cd9a0

两个字符串加两个 bool 输入;int32[] 输出(本地 core ids)。

c
// op-args struct read by InitializeHostForDistributedTpuOp_DoWork(a1)
struct InitHostArgs {
    /* +16 */ int64_t  tpu_topology_len;   // (>=0 guarded)
    /* +24 */ char*    tpu_topology;       // serialized topology string_view
    /* +32 */ uint8_t  enable_whole_mesh;  // bool
    /* +33 */ uint8_t  is_master;          // bool
    /* +40 */ uint64_t* out_size;          // # of core ids
    /* +48 */ int32_t** out_core_ids;      // *out = new int32[out_size]
    /* +56 */ StatusRep** status_cell;
};

function InitializeHostForDistributedTpuOp_DoWork(args):      // sub_e8cd9a0
    status = tensorflow::InitializeHostForDistributedTpu(     // 0xe9771c0
                 args.tpu_topology, args.tpu_topology_len,
                 args.enable_whole_mesh, args.is_master, &core_ids)
    store_status(args.status_cell, status)
    n = core_ids.size
    *args.out_size     = n
    *args.out_core_ids = operator new(4 * n)                  // int32[n]
    memmove(*args.out_core_ids, core_ids.data, 4 * n)
    free(core_ids.data)
```text

### `SetGlobalTPUArrayOp_DoWork`(`0xe8cda80`)

纯 string-in / status-out 桥,显式进行 SSO-aware 字符串物化。

```c
function SetGlobalTPUArrayOp_DoWork(len, data, status_cell):  // sub_e8cda80
    // build a NUL-terminated std::string from (data, len), SSO for len <= 0x16
    s = make_string(data, len)
    status = tensorflow::SetGlobalTPUArray(s)                 // 0xe977880
    store_status(status_cell, status)
    if heap_allocated(s): free(s.data)

注意 — 与其他动作不同,SetGlobalTPUArrayDisconnectDistributedTpuChips 把它们的 status cell 作为直接参数(a3 / a2),而不是位于 op-args 结构的某个偏移处。它们不产生输出数组,只产生 status,因此签名更简单:分别是 (len, data, StatusRep**)(self, StatusRep*-cell)。status 协议(§3)相同。

DisconnectDistributedTpuChipsOp_DoWork0xe8cdb80

最薄的动作:一次委托调用加 status 存储。

c
function DisconnectDistributedTpuChipsOp_DoWork(self, status_cell): // sub_e8cdb80
    status = tensorflow::DisconnectDistributedTpuChips(self, status_cell) // 0xe977aa0
    store_status(status_cell, status)                          // in place at *status_cell
```text

---

## 3. Status 与输出数组协议

两个约定由集群中的每个函数共享,也是重新实现者最需要做到 bit-exact 的部分。

### Status:`StatusRep*` 写入调用方 cell,并遵守 refcount 纪律

`absl::Status` 作为单个指针 `absl::status_internal::StatusRep*` 跨越接缝。桥会用标准 `absl::Status` move/ref 协议把它写入调用方拥有的 cell;所有五个动作以及携带 status 的三个查询中,此模式完全相同:

```c
// store_status(cell, new_rep) — the inlined idiom in every bridge
function store_status(StatusRep** cell, StatusRep* new_rep):
    old = *cell
    if (new_rep != old):
        *cell = new_rep
        if ((old & 1) == 0):           // low bit set => "inlined OK", nothing to unref
            StatusRep::Unref(old)
    else:                              // same rep: drop the extra reference we hold
        if ((new_rep & 1) == 0):
            StatusRep::Unref(new_rep)

怪异点 — StatusRep* 的低位是标签,不是地址位。bit 0 置位的值是内联状态(OK sentinel 或小型内联 code),它不拥有堆 StatusRep,绝不能 Unref;每个分支在调用 StatusRep::Unref 前都会防护 (ptr & 1) == 0。把 cell 当作普通指针并无条件 unref 的重新实现者会破坏 OK sentinel 的 refcount。GetServerAddressAndPort 还显示了acquire 侧:当它存储一个借用的 rep 时,会先 _InterlockedIncrement refcount(第 96 行),证明 cell 会取得一个 owning reference。

输出数组:callee 分配,caller 释放

三个产生数组的函数(ConfigureWaitForInitializeHost)和两个产生字符串的查询(CompilationCacheServerAddressFromConfigGetServerAddressAndPort)遵循同一形态:把元素/字节计数写入 *out_size,用 operator new 分配缓冲区,复制进去,然后返回。调用方之后通过 FreeInt32Array(用于 int32[] 输出)或 FreeCharArray(用于 char[] 输出)释放它。对于字符串输出,分配大小是 out_size + 1,复制使用 strncpy,即发出的 char[] 以 NUL 结尾,且 out_size 不包含终止符(见 CompilationCacheServerAddressFromConfig 第 76–81 行、GetServerAddressAndPort 第 112–117 行)。

陷阱 — int32[] 输出按 operator new(4 * n) 定大小(字节数 = 4 * element_count),但 *out_size 被设置为 n(元素数),不是字节数。FreeInt32Array 完全忽略 size(只是裸 free(p)),所以这种不匹配对释放无害;但用 out_size 约束循环的重新实现者必须把它视为元素数,而计算原始 new 大小的一方必须乘以 4。


4. Distributed-Pod 配置入口映射

自上而下读取,该集群就是一个宿主在 TPU pod 内的生命周期。下面的映射为每个阶段列出调用进入的开源 op-kernel、C-ABI 桥,以及承载逻辑的 C++ 入口。

text
TF op kernel (open source)          C-ABI bridge (this binary)              C++ entry (this binary, runtime/pod owned)
─────────────────────────────────   ─────────────────────────────────────  ──────────────────────────────────────────
ConfigureDistributedTPU         ──▶ ConfigureDistributedTpuOp_DoWork    ──▶ tensorflow::ConfigureDistributedTpu  0xe975cc0
                                       (0xe8cd400)                              └─ builds global mesh, emits topology blob
_SetGlobalTPUArray              ──▶ SetGlobalTPUArrayOp_DoWork          ──▶ tensorflow::SetGlobalTPUArray         0xe977880
                                       (0xe8cda80)                              └─ installs pod-wide topology proto
_InitializeHostForDistributedTPU──▶ InitializeHostForDistributedTpuOp.. ──▶ tensorflow::InitializeHostForDistributedTpu 0xe9771c0
                                       (0xe8cd9a0)                              └─ binds host, returns local core ids
WaitForDistributedTPU           ──▶ WaitForDistributedTpuOp_DoWork      ──▶ tensorflow::WaitForDistributedTpu     0xe9767c0
                                       (0xe8cd640)                              └─ barrier across hosts, merges mesh state
[runtime queries, any time]     ──▶ TpuConfigurationApi_HasTPUPodState  ──▶ tensorflow::HasTPUPodState            0xeaa17c0
                                       (0xe8cdca0)                              └─ via GetTPUConfigResourceMgr     0x10854020
                                ──▶ TpuConfigurationApi_TpusPerHost      ──▶ tensorflow::TpusPerHost              0xe9742a0
                                ──▶ TpuConfigurationApi_TpuMemoryLimit   ──▶ tensorflow::TpuMemoryLimit           0xe974440
_DisconnectHostFromDistributed.. ──▶ DisconnectDistributedTpuChipsOp..  ──▶ tensorflow::DisconnectDistributedTpuChips 0xe977aa0
                                       (0xe8cdb80)                              └─ removes host from pod
```text

这个顺序是多宿主 launcher 复现的契约:一个宿主配置全局数组,每个宿主设置它并在本地初始化,所有宿主在 wait barrier rendezvous,随后运行时在整个 session 中查询 pod state 和 per-host capacity,最后任一宿主断开连接。compile-cache 三件套(`RemoteCompilationCacheSizeInBytes`、`CompilationCacheServerAddressFromConfig`、`GetServerAddressAndPort`)与 bring-up 序列正交:它解析*编译缓存服务器*所在位置,由 `FLAGS_tpu_remote_compilation_cache_size_bytes`、`FLAGS_uberdriver_port`、`FLAGS_tpu_hostname_override` 以及序列化 `tensorflow::tpu::TPUHostConfiguration` proto 驱动。

> **注意 —** `HasTPUPodState` 是唯一通过 resource manager 而不是直接自由函数的查询:桥首先调用 `tensorflow::GetTPUConfigResourceMgr`(`0x10854020`)获取 config `ResourceMgr`,然后调用 `tensorflow::HasTPUPodState(rmgr)`(`0xeaa17c0`)。pod-state 对象是在该 manager 中按 key 注册的 resource;“has pod state” 就是 “resource 存在”。这就是宿主区分 “pod already configured” 与 “fresh bring-up” 的方式。
>
> **怪异点 —** `RemoteCompilationCacheSizeInBytes` 不调用 `tensorflow::` 入口,而是读取一个进程全局。它首先在 out-pointer 为空时 `CHECK` 失败(`tpu_config_c_api.cc:158` 处的 LogMessageFatal),然后返回缓存值(初始化后为 `unk_2225C260`)或实时 flag `FLAGS_tpu_remote_compilation_cache_size_bytes`,并在结果为负时再次 `CHECK` 失败(`:161`)。这是一个有硬前置条件的查询,不是可返回 status 的可失败调用:其签名中没有 status cell。

---

## 相关组件

| 名称 | 关系 |
|---|---|
| `tensorflow::ConfigureDistributedTpu / WaitForDistributedTpu / InitializeHostForDistributedTpu / SetGlobalTPUArray / DisconnectDistributedTpuChips` | 五个 `*Op_DoWork` 桥委托到的 C++ 自由函数;承载 mesh 逻辑 |
| `tensorflow::GetTPUConfigResourceMgr` | 解析 `HasTPUPodState` 探测的 config `ResourceMgr` |
| `tensorflow::tpu::TPUHostConfiguration`(proto) | 由 `CompilationCacheServerAddressFromConfig` 解析,以提取缓存服务器地址 |
| `absl::status_internal::StatusRep` | refcounted status 对象,其指针跨接缝进入调用方 status cell |
| `ExecutorApiFn()` table | 到达这些 C-ABI 入口所经由的 device-runtime 函数指针结构 |
| `FLAGS_uberdriver_port / FLAGS_tpu_hostname_override / FLAGS_tpu_remote_compilation_cache_size_bytes` | compile-cache 查询读取的进程 flags |

## 交叉引用

- [The TfTpu C-API Shim](overview.md) — 此集群搭载的 `*ApiFn` 访问器模式和不透明句柄约定;列出九个集群中 `TpuConfigurationApi_*` 的名册映射
- [TfTpu_Initialize Bootstrap](../lifecycle/tftpu-initialize-bootstrap.md) — *进程内驱动*初始化;与本页的*跨宿主 pod*配置对比
- [Megascale Bootstrap](../megascale/bootstrap/overview.md) — 分层位于 pod 配置之上的 collective-runtime bring-up
- [TpuPlatform & TpuNodeContext](tpu-platform-and-topology.md) — `TpuPlatform::TpusPerHost` / `TpuMemoryLimit` 是这里同名查询的 SE-object-model sibling
- [TpuExecutor 名册](tpu-executor-roster.md) — 同一批 op kernel 为设备工作调用的 per-device runtime C-ABI 集群
- [back to index](../index.md) — Part III — Tpu C-Shim Layer