Twist 谓词、Orientation 枚举与 n-hop 源相对门控
本页所有地址均适用于
libtpu-0.0.40-cp314wheel 中的libtpu.so(build-id89edbbe81c5b328a958fe628a9f2207d,构建libtpu_lts_20260413_b_RC00)。其他版本会有所不同。.textVMA 等于文件偏移(基址0xe63c000);所有地址均为 VMA。以下每个符号都存在于完整符号二进制中,并已与 IDA 反编译结果交叉核对。
摘要
三个很小、按字节钉住的事实门控了整个扭曲环面子系统,本页负责这三者。第一是 twist 资格谓词:只有当切片最长轴恰好是最短轴的两倍时,即 max_dim_size_ == 2 * min_dim_size_,该切片才可被降低为扭曲环面;这是 TwistedTorusND::UpdateMinMaxDims 内部的一个致命 CHECK。第二是 Orientation 枚举,即密集的 0..6 枚举,用来在故障链路记录以及每个静态路由 hop 上命名环面轴。第三是 is_nhop_source_relative 标志(Target[+0x3fb]),这个单字节门控选择 ICI next-hop 路由表是相对于每个源芯片计算,还是按绝对目的 ID 建索引。
Orientation 枚举是本页的重心。Direction::OrientationToDimension 和 proto 描述符共同表明 4/5/6 = A/B/C:这是物理 X/Y/Z 环面轴之外的三个额外逻辑维度(逻辑维度 3/4/5),不是物理轴的带符号/负向变体。负 SerDes 方向由 Direction 消息上的一个独立 polarity 字段承载,而不是由额外 orientation 值承载。本页记录该枚举,从二进制中证明它,并解释为什么 OrientationsToTpuDegradedAxes 只折叠 1/2/3(degraded-axis ingest path 消耗的物理轴子集)。
熟悉环面 collective 和维度顺序路由的读者可以这样把握框架:一个“twist”需要一条加倍轴来折叠(因此有 2·min 谓词);需要一个轴命名枚举来描述每条链路指向哪里(因此有 Orientation);还需要一个路由表约定 bit(因此有 is_nhop_source_relative)。重新实现契约是:
- 谓词。
max_dim_size_ == 2 * min_dim_size_,在UpdateMinMaxDims中以致命CHECK强制执行,并伴随twist() == true门控、三个dim_sizes_[i] >= 1检查,以及num_min_dims_ + num_max_dims_ == num_dims_分区检查。 - 枚举。
Orientation {0=UNKNOWN_ORIENTATION, 1=X, 2=Y, 3=Z, 4=A, 5=B, 6=C};OrientationToDimension(o) = (o == 0 ? INVALID_ARGUMENT : o - 1);伴随字段Polarity {0=UNKNOWN, 1=POSITIVE, 2=NEGATIVE}承载方向。 - 路由门控。
Target::IsNhopSourceRelative()读取Target[+0x3fb];默认值为(routing_strategy == ROUTING_NHOP);DragonfishTarget用每切片字节覆盖它,并断言基础字节未设置。
| Twist 谓词 | TwistedTorusND::UpdateMinMaxDims @ 0x137d0260;CHECK "max_dim_size_ == 2 * min_dim_size_" @ 0x137d037a(all_reduce_strategies.cc:1900) |
| 谓词致命字符串 | "Max. dim size should be 2 times the min. in a twisted torus" |
| K / 2K 字段 | min_dim_size_ = this[+0x5f8];max_dim_size_ = this[+0x5f0];num_max_dims_ = this[+0x600];num_min_dims_ = this[+0x608] |
Orientation 枚举 | accel_ssw::deepsea::proto::Orientation {0 UNKNOWN, 1 X, 2 Y, 3 Z, 4 A, 5 B, 6 C}(dimension.proto) |
o → dim 映射 | Direction::OrientationToDimension @ 0x20c027c0 — o == 0 ⇒ error; else o - 1 |
Polarity 枚举 | {0 UNKNOWN_POLARITY, 1 POSITIVE, 2 NEGATIVE}(dimension.proto) |
| n-hop 访问器(基础) | Target::IsNhopSourceRelative @ 0x1d6159a0 — return byte[this+0x3fb] |
| n-hop 访问器(Dragonfish) | DragonfishTarget::IsNhopSourceRelative @ 0x1d48f020 — 每切片字节 + CHECK(!base) |
| n-hop 默认值 | GetDefaultConfiguredProperties @ 0x20acee40 — is_nhop = (routing_strategy == 2 == ROUTING_NHOP) |
| 路由枚举 | TpuRoutingStrategyProto {0 ROUTING_DEFAULT, 1 ROUTING_MESH, 2 ROUTING_NHOP} |
| Limited-ICI 路由消费者 | tpu::RoutingTableEntryForICILimitedRouting @ 0x1fc58040 |
| 置信度 | 高(反编译验证过的谓词 CHECK 字符串、OrientationToDimension 函数体、两个 n-hop 访问器、默认配置打包),除非某行/标注另有说明 |
本页负责谓词、枚举和路由门控。该谓词所保护的 BuildStrategy 驱动在 BuildStrategy;K/2K 计数所分类的三种形状在 Shape Folds;坐标折叠在 GetReplicaPair3DOnTwistedTorus。本页修正的 Orientation → degraded-byte 映射在 Degraded-Axis Ingest。枚举参与的打包 (hop<<6 | polarity<<3 | orientation) 路由 hop 在 GetStaticPath。
1. Twist 资格谓词
只有当一条环面轴恰好是最短轴长度的两倍,并且每条轴要么是该短长度 K、要么是长长度 2K 时,切片在几何上才有资格进行扭曲环面降低。这两个条件都是致命 CHECK,也就是说,一个没有满足它们却到达 TwistedTorusND::UpdateMinMaxDims 的切片会中止编译,而不是回退。(picker 的 C-ii 分支只是在形状看起来 twisted 时才构造 TwistedTorusND;UpdateMinMaxDims 是第二道、权威的防线,见 SelectNDStrategy。)
TwistedTorusND::UpdateMinMaxDims — 0x137d0260
该函数把三条环面维度加载到 dim_sizes_[0..2],将它们排序为 min_dim_size_(短轴 K)和 max_dim_size_(长轴 2K),统计有多少条轴等于每个长度,并强制五个不变量。反编译(轻度清理,SIMD 计数循环已概括)如下:
// TwistedTorusND::UpdateMinMaxDims @ 0x137d0260
// chip_config = Target[+0x3b8] (decompile: *((_QWORD*)a2 + 119))
int64 cfg = *((_QWORD *)a2 + 119);
// (1) the twist-enable gate — the chip_config twist() byte must be set
CHECK(*(byte*)(cfg + 163) == 1, "target.Topology()->twist() == true"); // chip_cfg+0xa3
// load the three torus dims into dim_sizes_[0..2] (note the X/Y/Z source order below)
this->dim_sizes_[0] = *(int*)(cfg + 92); // this[+0xb8] (chip_cfg+0x5c)
this->dim_sizes_[1] = *(int*)(cfg + 88); // this[+0xc0] (chip_cfg+0x58)
this->dim_sizes_[2] = *(int*)(cfg + 96); // this[+0xc8] (chip_cfg+0x60)
// (2) every dim must be >= 1
CHECK(dim_sizes_[2] >= 1, "dim_sizes_[2] >= 1");
CHECK(dim_sizes_[1] >= 1, "dim_sizes_[1] >= 1");
CHECK(dim_sizes_[0] >= 1, "dim_sizes_[0] >= 1");
this->num_dims_ = 3; // this[+0x598]
// 3-way min/max sort via cmov: max_dim_size_ = max, min_dim_size_ = min
this->max_dim_size_ = max(dim0, dim1, dim2); // this[+0x5f0] == 2K
this->min_dim_size_ = min(dim0, dim1, dim2); // this[+0x5f8] == K
// (3) THE TWIST PREDICATE
if (this->max_dim_size_ != 2 * this->min_dim_size_) {
CHECK_FAIL("max_dim_size_ == 2 * min_dim_size_"); // all_reduce_strategies.cc:1900
LOG(FATAL) << "Max. dim size should be 2 times the min. in a twisted torus";
}
// vpcmpeqq count loops: how many of the 3 dims equal MAX (2K) / MIN (K)
this->num_max_dims_ = count(dims == max_dim_size_); // this[+0x600]
this->num_min_dims_ = count(dims == min_dim_size_); // this[+0x608]
// (4) the partition check — every dim is either the max or the min, nothing between
CHECK(num_min_dims_ + num_max_dims_ == num_dims_,
"num_min_dims_ + num_max_dims_ == num_dims_"); // :1904
// LOG(FATAL) << "Dimension sizes should either be maximum or minimum";
```text
> **注意 — 谓词就是本页标题中的 CHECK。** `max_dim_size_ == 2 * min_dim_size_` 是使环面“可 twist”的唯一条件。如果 `max == 3·min`(例如 `K, K, 3K` 切片),谓词失败并中止编译;不存在 `3·K` twist。伴随的分区 `CHECK` 随后禁止第三种不同长度:类似 `K, 2K, 1.5K` 的切片会在两个极值上通过 `2·min` 检查,却会在 `num_min + num_max == num_dims` 上失败。二者合起来把几何限制为恰好 `{K, 2K}` 两种长度,这正是三个 `TwistedTorusShape` 情形所枚举的内容。
### 计数分类什么
`num_max_dims_`(`2K` 计数)和 `num_min_dims_`(`K` 计数)相加为 `num_dims_ == 3`,并选择形状:
| `(num_max, num_min)` | 长度 | `TwistedTorusShape` |
|---|---|---|
| `(1, 2)` | `K, K, 2K` | `TWIST_SHAPE_K_K_2K` |
| `(2, 1)` | `K, 2K, 2K` | `TWIST_SHAPE_K_2K_2K` |
| 泛化长轴 | `K, 2K, nK` | `TWIST_SHAPE_K_2K_NK` |
`BuildStrategy` 读取这两个计数,以决定哪些轴承载 `K→2K` 接缝,以及哪条轴承载加倍环。字节级形状情形接线在 [Shape Folds](shape-folds.md);按颜色的接缝应用在 [BuildStrategy](buildstrategy.md)。本页只确立这些计数存在,并由谓词门控。
> **注意 — `dim_sizes_` 源顺序是 X/Y/Z 打乱的。** 三次加载从 `chip_cfg+0x5c` 取 `dim_sizes_[0]`,从 `+0x58` 取 `[1]`,从 `+0x60` 取 `[2]`。在 chip-config 布局中,`+0x58`/`+0x5c`/`+0x60` 字是 X/Y/Z 维度,所以 `dim_sizes_` 存储为 `{Y, X, Z}`。min/max 排序与顺序无关,所以谓词不受影响;复制字段偏移的重新实现者必须保留这一打乱顺序,以匹配 `BuildStrategy` 之后进行的逐轴 `num_*_dims_` 记账。
---
## 2. `Orientation` 枚举
`Orientation` 是命名环面轴的密集 proto 枚举。它出现在故障链路记录(哪条轴故障)、`Direction` 消息(链路指向哪边)以及每个打包静态路由 hop 上。它定义在 `dimension.proto`(`accel_ssw::deepsea::proto`)中。
### 2.1 枚举值
从 `dimension.proto` 的嵌入式 `FileDescriptorProto` 中的 `EnumDescriptorProto` 值列表按字节精确读取(每个 `EnumValueDescriptorProto` 都是 `12 05 0a 01 <ascii> 10 <num>`):
| value | name | descriptor bytes | 逻辑维度(`o-1`) |
|---:|---|---|---:|
| `0` | `UNKNOWN_ORIENTATION` | (`10 00` default) | —(错误) |
| `1` | `X` | `12 05 0a 01 58 10 01` | `0` |
| `2` | `Y` | `12 05 0a 01 59 10 02` | `1` |
| `3` | `Z` | `12 05 0a 01 5a 10 03` | `2` |
| `4` | `A` | `12 05 0a 01 41 10 04` | `3` |
| `5` | `B` | `12 05 0a 01 42 10 05` | `4` |
| `6` | `C` | `12 05 0a 01 43 10 06` | `5` |
ASCII 字节字面就是 `'X'`/`'Y'`/`'Z'`/`'A'`/`'B'`/`'C'`(`0x58`/`0x59`/`0x5a`/`0x41`/`0x42`/`0x43`)。密集枚举范围 `0..6` 由 `NameOfDenseEnum<Orientation, 0, 6>` 实例化(`0x22471c50`)和 `Orientation_descriptor`(`0x20c0ad20`)确认。
> **注意 — `4/5/6` 不是负轴。** 描述符把它们命名为 `A/B/C`:三个*额外逻辑维度*(逻辑维度 `3/4/5`),而不是物理 `X/Y/Z` 的带符号变体。负 SerDes 方向是 `polarity` 字段(§2.3),完全是另一个概念。
### 2.2 `Direction::OrientationToDimension` — `0x20c027c0`
这是证明 `o → dimension` 映射的函数。它很简单且对所有输入有定义:
```c
// accel_ssw::deepsea::slice_builder::Direction::OrientationToDimension @ 0x20c027c0
// -> absl::StatusOr<int> (result struct in a1; *a2 = the Orientation value)
StatusOr<int> OrientationToDimension(const Orientation& o) {
if (*o) // o != UNKNOWN_ORIENTATION (0)
return *o - 1; // X/Y/Z/A/B/C -> dim 0/1/2/3/4/5
return MakeErrorImpl<INVALID_ARGUMENT>( // <3> = INVALID_ARGUMENT
"Unknown orientation", /*len*/19, /*col*/87,
"platforms/accel_ssw/deepsea/slice_builder/friends/direction.cc");
}因此,对全部六个具名值,该映射恰好是 dim = orientation - 1,唯一错误情形是 UNKNOWN_ORIENTATION。支持的维度数是六个(A/B/C 到达逻辑维度 3/4/5),即使物理 3-D 环面只使用 X/Y/Z(1/2/3)。
注意 — 为什么只有
1/2/3会降级一条轴。tpu::OrientationsToTpuDegradedAxes(0x1fc57d00,记录于 Degraded-Axis Ingest)只测试== 1、== 2、== 3并设置 X/Y/Z degraded byte;它忽略0和4/5/6。这是正确的,不是 bug:degraded-axis 机制会把死链路从物理 3-D 环面环中折出,只有X/Y/Z是物理环面轴。故障的A/B/C链路(如果切片上存在)没有可折出的物理环面轴,因此不会产生 degraded byte。
2.3 Direction 消息和 Polarity
对一条链路而言,Orientation 从不单独传递。链路的完整方向是一个 Direction 消息,其中 orientation 与 polarity 配对:
// dimension.proto (accel_ssw.deepsea.proto)
message Direction {
Orientation orientation = 1; // which axis: X/Y/Z/A/B/C
Polarity polarity = 2; // which way along it: +/-
}
enum Polarity { UNKNOWN_POLARITY = 0; POSITIVE = 1; NEGATIVE = 2; }
```text
**负向** SerDes 方向是 `polarity = NEGATIVE`,*不是*第四/第五/第六个 orientation 值。这也是 degraded-axis 折叠完全忽略 polarity 的结构性原因:`-X` SerDes 上的 degraded 链路具有 `orientation = X (1)`、`polarity = NEGATIVE (2)`,并折叠到与 `+X` 故障*相同*的 `X` degraded byte;对绕开死链路的路由而言,重要的是轴,而不是沿轴的方向。每芯片 ICI 链路表按完整 `(orientation, polarity)` 对建索引:运行时为每个芯片持有一个 `flat_hash_map<Direction, PhysicalIciLink>`(使用 `DirectionHash` / `DirectionEqual`),因此 `+X` 和 `-X` 是不同的 map key,但属于同一条轴。
静态路由发射器也会把同一个 `(hop_count, polarity, orientation)` 三元组打包进每条轴的一个字节中,即 `(hop_count << 6) | (polarity << 3) | (orientation & 7)`,所以该枚举的低 3 位正好足以容纳 `0..6`。路由 hop 打包见 [GetStaticPath](../routing/get-static-path.md)。
---
## 3. `is_nhop_source_relative` 路由门控
`is_nhop_source_relative` 是一个 configured-properties 单字节,用来选择 ICI next-hop 路由表的索引方式:**源相对**(每个源芯片的表是相对源的偏移映射)或**绝对**(条目按目的芯片 ID 建索引)。它与 degraded bytes 一样搭载在同一个 `TpuConfiguredProperties` POD 上,并由同一个 `CreateFromTopology` 摄取,见 [degraded-axis 页面上的 POD 布局](../collectives/degraded-axis.md)(`+0x3` 是此字节)。本页负责*访问器*和*默认规则*;它所控制的实际路由表生成在 [GetStaticPath](../routing/get-static-path.md) 和 [Route-Table Generation](../routing/route-table-generation.md)。
### 3.1 基础访问器 — `Target::IsNhopSourceRelative` @ `0x1d6159a0`
纯字节加载,即 `CreateFromTopology` 从 `TpuConfiguredProperties[+0x3]` 写入的 `Target[+0x3fb]` 字节:
```c
// xla::jellyfish::Target::IsNhopSourceRelative @ 0x1d6159a0
__int64 Target::IsNhopSourceRelative(Target *this) {
return *((unsigned __int8 *)this + 1019); // 1019 == 0x3fb
}+0x3fb 是紧随 X/Y/Z degraded 三字节(+0x3f8/+0x3f9/+0x3fa)之后、routing-strategy int32(+0x3fc)之前的字节。整个 5 字节块就是 writer 落下的扁平配置;这是 POD +0x3 槽位的反向映射。
3.2 Dragonfish 覆盖 — DragonfishTarget::IsNhopSourceRelative @ 0x1d48f020
较新一代的 Target 不会简单返回基础字节。它会断言基础字节未设置,然后返回一个每切片字节:
// xla::jellyfish::DragonfishTarget::IsNhopSourceRelative @ 0x1d48f020
__int64 DragonfishTarget::IsNhopSourceRelative(DragonfishTarget *this) {
// the base Target flag MUST be false on Dragonfish — fatal CHECK otherwise
CHECK(!Target::IsNhopSourceRelative(this),
"!JellyfishTarget::IsNhopSourceRelative()"); // target_dragonfish.cc:28
// value comes from the adjacent per-slice/topology struct (Target[+0x940] + 0x49)
return *(unsigned __int8 *)(*((_QWORD *)this + 296) + 73LL); // [[this+0x940]+0x49]
}
```text
`this+296` 个 qword `= +0x940`(邻接的切片/拓扑结构,紧邻存放在 `Target+0x928` 的 `MultiSliceTopologyAndLocation*`);`+73 = +0x49`。因此 Dragonfish 会用每切片源相对字节*替换* configured-properties 字节,并强制通用 `Target[+0x3fb]` 字节在此路径上从未设置。
> **陷阱 — 这是替换并断言,不是 OR。** 该访问器先用一个致命 `CHECK` 断言基础字节为 `false`,然后无条件返回每切片字节(`[[+0x940]+0x49]`,`target_dragonfish.cc:28`)。它不是 inclusive-or fallback `base || per_slice`:如果基础字节曾在 Dragonfish target 上设置,进程会中止,而不是静默 OR。
### 3.3 默认值 — `GetDefaultConfiguredProperties` @ `0x20acee40`
当没有提供每切片覆盖时,默认配置从路由策略派生该标志:
```c
// tpu::GetDefaultConfiguredProperties @ 0x20acee40 (this = TpuTopology; this[+0xa4] = routing_strategy)
unsigned __int64 GetDefaultConfiguredProperties(const TpuTopology *topo) {
uint32_t rs = topo[+0xa4]; // routing_strategy
return ((uint64_t)rs << 32) // routing_strategy in high dword (POD +0x4)
| ((uint8_t)(rs == 2) << 24); // is_nhop_source_relative = (rs == ROUTING_NHOP) (POD +0x3)
// degraded bytes (POD +0x0..+0x2) left zero
}因此 is_nhop_source_relative 默认等于 routing_strategy == 2 == ROUTING_NHOP。路由策略枚举从 tpu_routing_strategy.proto 按字节精确读取:
| value | name | descriptor bytes |
|---|---|---|
0 | ROUTING_DEFAULT | 12 13 0a 0f ROUTING_DEFAULT 10 00 |
1 | ROUTING_MESH | 12 10 0a 0c ROUTING_MESH 10 01 |
2 | ROUTING_NHOP | 12 10 0a 0c ROUTING_NHOP 10 02 |
3.4 limited-ICI 路由消费者
该标志的下游效果是 n-hop 路由表生成。查询路径为:
tpu::IsReachableOverLimitedIci @0x1fc57fe0
entry = RoutingTableEntryForICILimitedRouting(topo, src, dst)
return entry.ok && entry.target_port >= 0
tpu::RoutingTableEntryForICILimitedRouting @0x1fc58040
bounds-check src/dst against [topo+0x70] chip count
require [topo+0x60] (routing_strategy) == 1 (ROUTING_MESH) else InvalidArgument
read x_wrapping byte[topo+0xa0], y_wrapping byte[topo+0xa1], dims[topo+0x58]
build slice_builder::Topology(dims_span, wrap_span) (ctor @0x20bf3320)
entry = viperlite_pod::DmaDestinationRoutingTableEntryMapper::Map(
src, dst, ToroidalTopology, RoutingScheme) (@0x1fc584e0)
// RoutingScheme == 2 -> MapTwoAxesReachable @0x1fc58fa0
// RoutingScheme == 0 -> MapOneTwoFourEightHopNeighborsReachable @0x1fc588a0
// 3-D topology -> error "toplogy must be 2d for limited ICI routing, z:"
```text
Limited-ICI routing 是一个 **2-D n-hop 方案**(两条轴上的 1/2/4/8-hop 邻居可达性);路由条目由 slice-builder 的 `RoutingTableGenerator::GetNextHopAction`(`0x1fbda6a0`)生成。`is_nhop_source_relative` 选择这些 next-hop 条目是相对于源芯片坐标计算(每个源一个 offset-from-source map),还是按绝对目的芯片 ID 建索引。路由发射层会读取该标志,Dragonfish 路径中的 `CHECK "!JellyfishTarget::IsNhopSourceRelative()"`(§3.2)保护一个绝对路由断言。完整 hop 偏移表和 `GetNextHopAction` 函数体在 [GetStaticPath](../routing/get-static-path.md) 和 [Route-Table Generation](../routing/route-table-generation.md);本页只钉住该*标志*及其默认值。
---
## 4. 函数与枚举映射
| 符号 | 地址 | 作用 |
|---|---|---|
| `TwistedTorusND::UpdateMinMaxDims` | `0x137d0260` | twist 谓词 + 维度排序 + K/2K 计数 |
| `Direction::OrientationToDimension` | `0x20c027c0` | `o == 0 ⇒ error; else dim = o − 1` |
| `Orientation_descriptor` | `0x20c0ad20` | 枚举描述符(`dimension.proto`) |
| `NameOfDenseEnum<Orientation,0,6>` | `0x22471c50` | 确认密集 `0..6` 范围 |
| `tpu::OrientationsToTpuDegradedAxes` | `0x1fc57d00` | 只折叠 `1/2/3`(X/Y/Z)— 见 [degraded-axis](../collectives/degraded-axis.md) |
| `Target::IsNhopSourceRelative` | `0x1d6159a0` | `return byte[this+0x3fb]` |
| `DragonfishTarget::IsNhopSourceRelative` | `0x1d48f020` | 每切片字节 + `CHECK(!base)` |
| `GetDefaultConfiguredProperties` | `0x20acee40` | `is_nhop = (routing_strategy == 2)` |
| `tpu::IsReachableOverLimitedIci` | `0x1fc57fe0` | `entry.target_port >= 0` 可达性查询 |
| `tpu::RoutingTableEntryForICILimitedRouting` | `0x1fc58040` | 2-D limited-ICI 路由条目;`ROUTING_MESH` 门控 |