把 SIGCOMM 2024 的流量工程集合通信调度器(TE-CCL)生成的调度计划,翻译成 AstraSim 能执行的轨迹,在同一拓扑下仿真,并对比"论文声称的完成时间"与"模拟器实测时间"。
TE-CCL(Traffic-Engineering based Collective Communication)把集合通信建模成多商品流问题,用 MILP 求解器在一个给定拓扑上生成 epoch 化的传输计划(每个时隙谁把哪块数据发给谁)。
"Rethinking Machine Learning Collective Communication as a Multi-Commodity Flow Problem" — Xuting Liu 等, ACM SIGCOMM 2024(Best Paper)。
仓库:https://github.com/microsoft/te-ccl
TE-CCL 说"这个 AllGather 需要 8 个 epoch、完成时间 8.0(抽象单位)"。我们把它的计划原样翻译成 AstraSim 轨迹、在 4×4 Mesh 拓扑上仿真——实测时间是多少?和它声称的完成时间一致吗?
TE-CCL 的输出(schedule JSON)和 AstraSim 的输入(Chakra 轨迹)格式不同,中间需要两个翻译器——这条管线就是本次实验的核心资产。
{
"1-Epoch_Duration": 1.0, # 每时隙时长(归一化单位)
"3-Epochs_Required": 8, # 需要 8 个时隙
"4-Collective_Finish_Time": 8.0, # 声称的完成时间(抽象单位)
"5-Algo_Bandwidth": 200,
"7-Flows": [ # 240 条传输计划
"Chunk 0 from 9 traveled over 9->5 in epoch 0",
"Chunk 0 from 7 traveled over 7->11 in epoch 0",
...
]
}
每条 flow = "某个 chunk 在第 e 个 epoch 从节点 a 传到节点 b"。这正好就是 AstraSim 自定义集合通信(CustomCollective)需要的 send/recv 步骤。
COMM_SEND_NODE SEND_ep0_to_5 | tag=0 | 1MB # epoch 0: 9→5 COMM_RECV_NODE RECV_ep0_from_0 | tag=3 | 1MB COMM_SEND_NODE SEND_ep1_to_9 | tag=4 | 1MB # epoch 1 ...
send 与对应 recv 用相同 comm_tag 配对;同一 epoch 内节点并行,跨 epoch 串行(依赖链)。
TE-CCL 的每个拓扑本质上就是一个 capacity 矩阵(链路带宽)+ alpha 矩阵(链路延迟)。这里直接运行 TE-CCL 的拓扑代码,把 6 个真实拓扑画出来:Mesh(240 条 flow)和 NDv2(210 条 flow,含交换机转发)可直接回放调度。
| 项 | 值 |
|---|---|
| Workload | 16-NPU AllGather,1 MB(Chakra microbenchmark) |
| 拓扑 | 4×4 Mesh(自定义 BasicTopology,曼哈顿距离跳数) |
| 链路 | 50 GB/s;延迟 0 ns(对齐 TE-CCL alpha=0)与 500 ns 两组 |
| 算法 A | TE-CCL 调度(240 条 flow / 8 epochs,custom collective) |
| 算法 B(对照) | 官方原生 Ring AllGather(同一 Mesh 拓扑) |
| 后端 | AstraSim_Analytical_Congestion_Unaware |
| 方案 | 时间 (ns) | 相对 TE-CCL 声称 | TE-CCL 优势 |
|---|---|---|---|
| TE-CCL 声称(8.0 抽象单位 → 换算) | 167,772 | 1.00× | — |
| unaware 后端 · TE-CCL 调度 | 97,655 | 0.58× | 3.0× vs Ring |
| unaware 后端 · 官方 Ring | 293,125 | 1.75× | — |
| aware 后端(含拥塞) · TE-CCL 调度 | 97,655 | 0.58× | 4.4~5.2× vs Ring |
| aware 后端(含拥塞) · 官方 Ring | 429,812 ~ 507,846 | 2.56~3.03× | — |
差异不是错误,而是两种时间模型的根本区别:
| TE-CCL(离散时隙) | AstraSim(事件驱动) | |
|---|---|---|
| 时间单位 | epoch(抽象时隙) | ns(真实时钟) |
| chunk 转发 | 到达后等下一时隙边界才能继续转发 | 到达后立即转发(流水线) |
| 并行语义 | 所有链路按 epoch 同步推进 | 每个 rank 独立事件流,无全局 barrier |
| 延迟 (alpha) | 建模为 alpha(本实验为 0) | latency 参数独立建模 |
| 完成时间 | epochs × epoch_duration(保守估计) | 最长依赖链的实际耗时(更精确) |
# 每 epoch 每条链路最多传输 capacity×epoch_duration 个 chunk epoch_capacity = self.topology.capacity[i][j] * self.epoch_duration ... # capacity=1 时:一个 chunk 必须占满整整一个 epoch 才能传输 # → chunk 到达中间节点后,转发最早发生在下一个 epoch
这就是"时隙化调度器"(TACCL / TE-CCL 通用做法)相对真实系统的固有误差:它给每个传输分配整数时隙,放弃了流水线重叠。AstraSim 精确模拟出这些重叠,所以时间更短。
启用拥塞模型(AstraSim_Analytical_Congestion_Aware)后,两条路径的结果分化明显:
| 算法 | unaware | aware | 拥塞代价 |
|---|---|---|---|
| TE-CCL 调度 | 97,655 ns | 97,655 ns | 0%(完全避开了拥塞) |
| 官方 Ring | 293,125 ns | 429,812~507,846 ns | +46%~73% |
Ring 的拥塞来自:逻辑环在 Mesh 物理拓扑上,相邻逻辑节点的物理路径在多条流之间共享链路(尤其 0-1、14-15 等角落瓶颈边)。TE-CCL 的 MILP 显式平衡了链路负载,所以它的调度在拥塞模型下时间不变——这解释了"流量工程调度"论文的核心价值。
TE-CCL finish(真实 ns) = Epochs_Required × (1 个 chunk 的传输时间)
= 8 × (chunk_bytes ÷ bandwidth)
= 8 × (1048576 B ÷ 50 GB/s)
= 167,772 ns
依据:TE-CCL 的 epoch_duration = 1 / 最快链路容量,而链路容量 = 100 / chunk_size(GB),两者相乘恰好消去归一化,等价于"传一个 chunk 的真实时间"。证明 TE-CCL 的模型 = 纯带宽模型(无拥塞、无延迟),与 AstraSim analytical 后端数学同源。
# WSL2 + Ubuntu 22.04,已装好 AstraSim(三个后端) $ git clone https://github.com/microsoft/te-ccl.git # 走镜像 ghfast.top
$ python3 teccl_schedule_to_plan.py \
--schedule te-ccl/teccl/examples/schedules/mesh_4.json \
--output examples/system/custom_collectives/teccl_mesh4/plan.json \
--collective all_gather
$ cd examples/system/custom_collectives/teccl_mesh4 $ python3 plan_to_et.py --plan plan.json --output-prefix teccl_mesh4 $ cat > mesh_16npus_nolat.yml <<'EOF' topology: [ Mesh ] npus_count: [ 16 ] bandwidth: [ 50.0 ] latency: [ 0.0 ] EOF
$ cd /home/xm/astra-sim $ ./build/astra_analytical/build/bin/AstraSim_Analytical_Congestion_Unaware \ --workload-configuration=examples/workload/microbenchmarks/all_gather/16npus_1MB/all_gather \ --system-configuration=examples/system/custom_collectives/teccl_mesh4/teccl_mesh4_system.json \ --remote-memory-configuration=examples/remote_memory/analytical/no_memory_expansion.json \ --network-configuration=examples/system/custom_collectives/teccl_mesh4/mesh_16npus_nolat.yml # 输出:Wall time: 97655(延迟0)/ 100155(延迟500ns)
# system json 里把 all-gather-implementation-custom 换成: "all-gather-implementation": ["ring"] # 预期:Wall time ~305125
| 文件 | 作用 |
|---|---|
| guide/teccl_schedule_to_plan.py | TE-CCL schedule → plan.json |
| guide/plan_to_et.py | plan.json → Chakra ET(每 rank) |
| examples/system/custom_collectives/teccl_mesh4/ | plan / ET / system json / mesh yml 工作区 |
| extern/.../basic-topology/Mesh.{h,cpp} | 自定义 Mesh 拓扑(unaware + aware 两版) |
| te-ccl/teccl/examples/schedules/ | TE-CCL 自带 schedule(mesh_4 / mesh_6 / ndv2) |