Skip to content

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 之后:

  1. 地址表。 每个 process 都知道其他每个 process 的 gRPC endpoint, 并按 (slice_id, host_id) 索引。XLA Megascale runtime 使用这张表来填充逐 peer 的 NetworkAddressMapping 数组,该数组驱动所有后续 MegaScaleTransport.Send collective RPC 和 DCN host transfer。
  2. 一致的拓扑视图。 所有 process 都对 MultiSliceTopologyInfo 达成一致: 总 slice 数、逐 slice host 数、逐 slice TpuTopologyArgsProto,以及统一的 endpoint 列表。该一致性由 coordinator 对每个传入 topology proto 与它第一次看到的 proto 运行 proto2::util::MessageDifferencer::Compare 来强制保证。
  3. 单次完成通知。 当 coordinator 的 TopologyCoordinator 达到 quorum 时, 每个阻塞的 worker 会同时解除阻塞。迟到者会收到同一个 response 的缓存副本, 不会迫使 coordinator 重新计算。
  4. 每个 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 注册GetMultiSliceTopologyRequest schema 和 gRPC server 侧 callback 链。
  • 拓扑交换TopologyCoordinator 内部: SliceState map、ProcessRequestCreateResponseMessageDifferencer 校验,以及 response 使用的 byte-stable sort。
  • 收敛 — 通用 Coordinator<> 模板的 state machine、 pending-callback vector、absl::NotificationReportStatus 周期性 logger。
  • 故障处理 — timeout、部分 registration、re-key warning, 以及从失败 bootstrap 到 ErrorReporterRapidEye 的路径。
  • tpunetd 关系 — tpunetd 为什么必须先完成; 它的 TpuTopologyArgsProto 和芯片坐标状态如何馈入 Megascale。
  • ICI 交接 — 从 tpunetd 的 SetChipCoordinates/SetGlobalChipId/SetRoutingTable 结果到 rendezvous 请求中 HostNetworkAddress 字段的显式数据依赖。