Megascale Bootstrap Rendezvous — 概览
Megascale bootstrap rendezvous 是一个跨 host 握手流程,用于启动 XLA Megascale multi-slice TPU job。每个 TPU host 上的每个 worker process 在启动时准确参与一次; rendezvous 完成后,每个 process 都持有一份相同的 multi-slice 地址表, 该表把每个 (slice_id, host_id) 对映射到稳定状态 collective 和 host transfer 所需的网络地址。
该 rendezvous 是严格中心化的。一个 process(coordinator)拥有 rendezvous 状态。所有其他 process 都通过 gRPC 联系 coordinator,注册自己的绑定,并阻塞直到 coordinator 组装出完整拓扑。
Rendezvous 完成了什么
Bootstrap 之后:
- 地址表。 每个 process 都知道其他每个 process 的 gRPC endpoint, 并按
(slice_id, host_id)索引。XLA Megascale runtime 使用这张表来填充逐 peer 的NetworkAddressMapping数组,该数组驱动所有后续MegaScaleTransport.Sendcollective RPC 和 DCN host transfer。 - 一致的拓扑视图。 所有 process 都对
MultiSliceTopologyInfo达成一致: 总 slice 数、逐 slice host 数、逐 sliceTpuTopologyArgsProto,以及统一的 endpoint 列表。该一致性由 coordinator 对每个传入 topology proto 与它第一次看到的 proto 运行proto2::util::MessageDifferencer::Compare来强制保证。 - 单次完成通知。 当 coordinator 的
TopologyCoordinator达到 quorum 时, 每个阻塞的 worker 会同时解除阻塞。迟到者会收到同一个 response 的缓存副本, 不会迫使 coordinator 重新计算。 - 每个 worker 一个共享的
incarnation_id。 每个 worker 都会把逐 process 的NewGlobalID()注入自己的请求;coordinator 会记住每个(slice_id, host_id)slot 上的最新值,以便检测并警告静默的 worker 重启。
Rendezvous 如何位于 tpunetd 和 PJRT 之间
Megascale bootstrap 是 TPU cluster bringup 的中间层:
text
PJRT distributed CoordinationService (xla.coordination)
↑ (Python 层 rendezvous:shard 分配、run id、...)
│
┌──┴───────────────────────────────────────────────────┐
│ xla::megascale::runtime::CommunicationBackend │
│ - MEGASCALE_PORT 上的 GrpcTransport server │
│ - 在 coordinator process 上: │
│ TopologyCoordinator (跨 slice rendezvous) │
│ BarrierCoordinator map (逐 id rendezvous) │
│ ErrorReporter │
│ - 在每个 process 上: │
│ address table, peer Send fan-out, HeartBeat │
└──┬────────────────────────────────────────────────────┘
↑ 使用 tpunetd 的逐 host 芯片坐标绑定作为输入
│
┌──┴────────────────────────────────────────────────────┐
│ superpod::tpunetd_client::TpunetdClient │
│ - SessionMaster 通过 UDS 与 tpunetd 通信 │
│ - 在此 slice 内启动 ICI fabric │
│ - 在此 slice 内执行 BroadcastBarrier rendezvous │
└──┬────────────────────────────────────────────────────┘
↑
tpunetd daemon: SessionControl + ICI fabric controller
```text
这些层的分界:
- **tpunetd 处理 slice 内 bringup**:ICI 链路配置、路由表、全局时间计数器同步、
逐 host `SetChipCoordinates`。它的 `SessionMaster::BroadcastBarrier`
是同一个 slice 中所有 host 共享的 *within-slice* rendezvous。
- **MegaScaleTransport 处理 slice 间 bringup**:把每个 slice 的逐 host
网络 endpoint 聚合为一张 cluster-wide 地址表。本节记录的就是这个 rendezvous。
- **PJRT CoordinationService 是独立通道**:不同的 proto namespace
(`xla.coordination`)、不同的 gRPC 端口、不同的抽象(Python 层 run identity
对 C++ 层 chip identity)。二者从不共享 Barrier ID。
依赖图是单向的:tpunetd 必须先完成,Megascale 才能启动;Megascale 必须先完成,
稳定状态 collective 或 HeartBeat 才能开始。
## 单次往返
该 rendezvous 对每个 worker 来说正好是**一次 gRPC 往返**:
```text
worker N (slice_id=S, host_id=H)
│
│ GetMultiSliceTopologyRequest {
│ slice_id = S
│ host_id = H
│ host_addresses = [HostNetworkAddress { ... }]
│ topology_args = TpuTopologyArgsProto (from tpunetd)
│ incarnation_id = per-process util::random::NewGlobalID()
│ } (在 backend ctor 中计算一次,存储于 +0x28)
▼
gRPC /xla.megascale.runtime.MegaScaleTransport/GetMultiSliceTopology
│
▼
coordinator process:
CommunicationBackend::OnTopologyRequestReceived(req, reply_cb)
├─ TracedMutexLock backend.mu (TracedMutex at +0xe0)
├─ topology_coordinator_ = *(backend + 0x1a0)
├─ if null → MakeErrorImpl<13> "TopologyCoordinator not initialized." error
└─ topology_coordinator_->AddRequest(req, reply_cb)
│
├─ 将 reply_cb 暂存进 pending vector
├─ ProcessRequest(req)
│ ├─ 验证 topology_args 与第一次看到的内容匹配
│ │ (MessageDifferencer::Compare)
│ ├─ flat_hash_map<int, SliceState>[slice_id]
│ │ .num_hosts_seen++
│ └─ 将 host_addresses 追加到 slice 的 host list
├─ if IsComplete():
│ ├─ response = CreateResponse()
│ │ - 组装 MultiSliceTopologyInfo
│ │ - 对 SliceInfo* 和
│ │ NetworkAddressMapping*
│ │ 排序(byte-stable)
│ ├─ LogUniqueIds(slice_id, host_id, response)
│ │ - re-key drift warnings
│ ├─ state_ = 2 (completed)
│ ├─ Notification.Notify()
│ └─ 对每个 pending callback 执行 cb(response)
└─ else if state_ == 0 → ScheduleStatusReport()
worker N 接收 response;CommunicationBackend::DiscoverTopologyAndAddressBindings
将其作为 StatusOr<tuple<MultiSliceTopologyAndLocationProto,
EndpointAddresses>> 返回,调用方用它填充地址表。同一个基于模板的 Coordinator<Req, Resp, Callback> 机制也驱动 BarrierCoordinator 流程:每个 barrier_id 对应一个 BarrierCoordinator,并由 CommunicationBackend 偏移 +0x1b0 处的 flat_hash_map<string, unique_ptr<BarrierCoordinator>> 索引。
本节的组织方式
- Coordinator 选举 — 由 env-var 驱动的单个 coordinator process 选择。
- Worker 注册 —
GetMultiSliceTopologyRequestschema 和 gRPC server 侧 callback 链。 - 拓扑交换 —
TopologyCoordinator内部: SliceState map、ProcessRequest、CreateResponse、MessageDifferencer校验,以及 response 使用的 byte-stable sort。 - 收敛 — 通用
Coordinator<>模板的 state machine、 pending-callback vector、absl::Notification和ReportStatus周期性 logger。 - 故障处理 — timeout、部分 registration、re-key warning, 以及从失败 bootstrap 到
ErrorReporter和RapidEye的路径。 - tpunetd 关系 — tpunetd 为什么必须先完成; 它的
TpuTopologyArgsProto和芯片坐标状态如何馈入 Megascale。 - ICI 交接 — 从 tpunetd 的
SetChipCoordinates/SetGlobalChipId/SetRoutingTable结果到 rendezvous 请求中HostNetworkAddress字段的显式数据依赖。