+ 返回推理优化主计划 · + 打开 Phase 2 实验档案 +
+39fc2ba565a3 的 Phase 2
+ 代码和文件调用关系。Phase 1 负责模型服务与请求;Phase 2 负责通信基线、
+ 两节点监控、精确时间切片和逐指标报告。最终正式 Run
+ dsv4pro-phase2-20260731-163620 使用提交
+ 5f24b7d22f98108f6cc234edba6768d55ea0a962,代码树包含本页所述修复。
+ 1. 阅读导航
+ + +2. 总体控制流
+main "$@" → run_all
+ ├─ validate_config
+ ├─ preflight_node_tools
+ │ └─ 两节点 dcgmi discovery -l 必须成功
+ ├─ preflight_clock_sync + preflight_gpus_idle
+ ├─ run_communication_baseline
+ │ ├─ 两节点 CUDA P2P 全矩阵
+ │ ├─ 两节点各自 8-rank AllReduce
+ │ └─ 16-rank AllReduce,CROSS_NIC=0/1/2
+ ├─ start_service → Phase 1 start
+ ├─ capture_static_snapshots before
+ ├─ start_collectors → Head/Worker 同时采集
+ ├─ idle → fixed cases → mixed A/B → cooldown
+ ├─ check_collectors + stop_collectors
+ ├─ capture_static_snapshots after
+ ├─ stop_service → Phase 1 stop
+ ├─ summarize_results
+ │ └─ 按正式 benchmark 窗口生成第 5 节逐项数据表
+ └─ finish_manifest
+
+ all 是唯一正式入口。communication、summarize
+ 和 stop 是排错/恢复 action,不需要在正常执行前手工调用。
+
3. 文件职责与调用关系
+| 文件 | 行数 | 职责 |
|---|---|---|
| config.env | 61 | 节点、Case、分层采样周期、通信尺寸、NCCL 选择和 fail-closed 策略。 |
| run_hardware_contention_attribution.sh | 1036 | 唯一 Shell 编排器:预检、通信文件分发、通信基线、Phase 1 委托、采集器、Case 和清理。 |
| communication_baseline.py | 227 | CUDA P2P 全矩阵及 PyTorch/NCCL AllReduce 正确性、延迟和带宽测试。 |
| hardware_contention_attribution.py | 1480 | 解析所有原始采集器,按 Case 切片,聚合通信并生成 CSV/JSON/report.md。 |
| tests/test_hardware_contention_attribution.py | 322 | 9 项纯 Python 单元测试,覆盖 worker 无仓库依赖、精确窗口、解析器、RDMA 单位和通信聚合。 |
用户
+ └─ Phase2/run_hardware_contention_attribution.sh all
+ ├─ source Phase2/config.env
+ ├─ docker/torchrun → Phase2/communication_baseline.py
+ ├─ env ... bash Phase1/run_quick_map.sh start/fixed/mixed/stop
+ │ └─ Phase1/quick_map_results.py 写 benchmark meta
+ ├─ Shell 采集 Head/Worker 原始时间序列
+ └─ Phase2/hardware_contention_attribution.py summarize
+ ├─ 读取 Phase1 bench/cases/*/meta.json
+ ├─ 读取 Head/Worker 原始监控
+ ├─ 读取 communication/COMM_RESULT
+ └─ 输出逐 Case、逐节点、逐指标表和 report.md
+
+ 3.1 Phase 1 与 Phase 2 的边界
+| 问题 | 由哪个文件负责 | 证据 |
|---|---|---|
| 模型路径、镜像、TP16、EP、显存比例 | Phase 1 config.env + run_quick_map.sh | service/head_server_cmd.txt、worker_server_cmd.txt |
| ISL/OSL/C、random 请求和 mixed A/B | Phase 1 场景表与 benchmark 函数 | bench/*/bench_cmd.txt、bench.json |
| 通信基线、监控周期、Case 选择 | Phase 2 config.env | Phase 2 manifest.json |
| 硬件归因和数值报告 | Phase 2 Python 汇总器 | case_*_summary.csv、report.md |
4. 配置来源
+| 行号 | 配置组 | 关键变量 |
|---|---|---|
config.env:L3-L16 | 入口与节点 | PHASE1_ENTRY、Head/Worker、端口和容器名。 |
L18-L21 | 诊断 Case | 五个 fixed Case、mixed A/B 开关。 |
L23-L39 | 采样与严格性 | GPU/DCGM/RDMA 1 秒;CPU/进程/网络/NUMA/perf 5 秒;精确窗口和采集器 fail-closed。 |
L40-L55 | 通信基线 | 镜像、消息尺寸、迭代次数、P2P 大小、CROSS_NIC 列表、Socket/HCA。 |
L57-L61 | 路径与模式 | RESULT_BASE、Runtime、Dry-run、是否允许部分采集器。 |
+ MEM_FRACTION_STATIC 不在 Phase 2 重复定义。它仍来自 Phase 1,
+ 最终展开为 SGLang 的 --mem-fraction-static。判断某次 Run 的真实值,
+ 应读取 service/head_server_cmd.txt,不能只看默认配置。
+
5. 通信微基准
+5.1 Shell 如何编排
+
+ run_hardware_contention_attribution.sh:L281-L513 负责源码暂存、
+ Docker 命令、两节点同步和清理。所有命令先写入 commands/*.txt:
+
-
+
L281-L319:从 Head 将当次通信脚本暂存到两节点并校验 SHA256。
+ L321-L374:构造容器命令,Head/Worker 各跑一次 P2P。
+ L376-L404:Head/Worker 各跑一次 8-rank AllReduce。
+ L406-L467:每个 CROSS_NIC 值先启动 Worker rank,再运行 Head rank。
+ L469-L513:只清理本实验前缀的通信容器和本次 `/tmp` 暂存目录。
+
+ Docker 使用和 SGLang 一致的 CUDA 13 nightly 镜像,并显式透传
+ rdma_cm、uverbs0、uverbs3。
+ NCCL_DEBUG=INFO 只在微基准中打开,用于证明 NET/IB/GDRDMA 路径。
+ Worker 不要求存在 Git 仓库;容器只读挂载自动分发的
+ /tmp/.../<RUN_ID>/communication_baseline.py。结果目录同时保存
+ 当次源码副本和 SHA256,避免两个节点 checkout 不一致造成版本漂移。
+
5.2 P2P 代码
+
+ communication_baseline.py:L45-L106 遍历所有源 GPU 和目标 GPU,
+ 先调用 torch.cuda.can_device_access_peer,再对 256 MiB FP16 Tensor
+ 做预热和 CUDA Event 计时。输出包括方向、P50/P95 latency 和 GB/s。
+ 汇总器按拓扑拆成同 PCIe Switch 的 PIX 与跨 NUMA 的 SYS。
+
5.3 AllReduce 代码
+
+ communication_baseline.py:L107-L198 初始化 NCCL process group,
+ 对 1 MiB、64 MiB、1 GiB 分别预热和重复测量。每轮先把各 rank latency
+ gather 到 rank 0,使用最慢 rank 作为 collective 完成时间,并检查归约结果:
+
algbw = message_bytes / latency
+busbw = algbw × 2 × (world_size - 1) / world_size
+wrong_values = count(output != expected_sum)
+
+ 这样不会用某个提前返回 rank 的时间美化结果;wrong_values=0
+ 才算正确完成。
+
6. 两节点采集器
+6.1 启动前门禁
+
+ Shell L67-L199 完成配置、工具、时钟和 GPU 空闲检查。
+ preflight_node_tools 不只检查 dcgmi 文件存在,
+ 还实际运行 dcgmi discovery -l;两节点任一 Host Engine 不可用即退出。
+
6.2 采集器包装
+
+ start_stream_collector 位于 Shell L517-L551。
+ 它保存完整命令、PID、唯一进程 tag 和日志;check_collectors 在
+ L722-L740 检查采集器是否提前退出,默认不允许部分成功。
+
| 采集器 | Shell 位置 | 周期 | 输出 |
|---|---|---|---|
nvidia-smi | L552-L565 | 1 秒 | gpu_samples.csv |
| RDMA HCA counters | L566-L592 | 1 秒 | rdma.csv |
| DCGM | L645-L655 | 1 秒 | dcgm_dmon.log |
mpstat | L656-L663 | 5 秒 | mpstat.log |
pidstat -durw | L664-L671 | 5 秒,进程级 | pidstat.log |
sar -n DEV,EDEV | L672-L678 | 5 秒 | sar_net.log |
perf stat | L680-L689 | 5 秒 | perf_stat.log |
numastat | L618-L644 | 5 秒 | numa_samples.csv |
+ CPU、进程、perf 和 sar 的每行均由 Shell 增加
+ wall_time_ns TAB node TAB payload。NUMA 直接转成结构化 CSV,
+ 避免旧版线程级 1 秒日志过大,也让所有指标能按 Case 切片。
+
7. 精确测量窗口
+7.1 Phase 1 如何标记主测量
+
+ Phase 1 run_quick_map.sh:L547-L564 每 100 ms 观察 bench 日志;
+ 发现 Starting main benchmark run 后调用
+ quick_map_results.py mark-measurement-start。
+ quick_map_results.py:L340-L385 用这个起点和
+ bench.json.duration 生成:
+
measurement_started_at
+measurement_ended_at
+measurement_duration_s
+measurement_window_source = bench_main_marker_plus_duration
+
+ 7.2 Phase 2 如何使用
+
+ hardware_contention_attribution.py:L509-L560 优先读取上述字段。
+ 只有兼容旧结果时才可能使用进程级窗口;正式配置
+ REQUIRE_PRECISE_WINDOWS=1 会拒绝任何 fallback。
+ L561-L841 对 GPU、DCGM、CPU、进程、perf、NUMA、netdev 和 RDMA
+ 使用同一个 started_ns ≤ sample ≤ ended_ns 条件。
+
8. 逐指标报告
+
+ Python summarize 位于
+ hardware_contention_attribution.py:L1036-L1378。
+ 它不只生成一个抽象结论,而是按 Phase 2 第 5 节依次写出:
+
| 指标 | 解析函数 | Case 汇总文件 |
|---|---|---|
| GPU | summarize_gpu_rows L377-L413 | case_gpu_summary.csv、case_gpu_node_summary.csv |
| DCGM | parse_dcgm L167-L192 | case_dcgm_summary.csv |
| CPU | parse_mpstat L193-L222 | case_cpu_summary.csv |
| 进程 | parse_pidstat L223-L289 | case_process_summary.csv |
| perf | parse_perf L290-L310 | case_perf_summary.csv |
| NUMA | 结构化 CSV + summarize_case_metrics | case_numa_summary.csv |
| Linux netdev | parse_sar_net L311-L358 | case_netdev_summary.csv |
| RDMA | summarize_rdma_rows L424-L484 | case_rdma_summary.csv |
| P2P/NCCL | load_communication_rows + aggregate_communication_rows L842-L928 | communication_summary.csv、communication_aggregate.csv |
+ report.md 对每组都打印有效样本数、Mean/P95/Max、Head/Worker
+ 或 Case 间比较和源文件。解析不到的值保留为 -,不会被写成 0。
+
9. 结果目录
+results/<RUN_ID>/
+ manifest.json
+ commands/
+ communication/
+ service/
+ bench/<phase1-sub-run>/
+ head/
+ gpu_samples.csv
+ dcgm_dmon.log
+ mpstat.log
+ pidstat.log
+ perf_stat.log
+ sar_net.log
+ numa_samples.csv
+ rdma.csv
+ collector_commands/
+ worker/
+ ...同上...
+ case_windows.csv
+ bench_summary.csv
+ case_gpu_summary.csv
+ case_gpu_node_summary.csv
+ case_dcgm_summary.csv
+ case_cpu_summary.csv
+ case_process_summary.csv
+ case_perf_summary.csv
+ case_numa_summary.csv
+ case_netdev_summary.csv
+ case_rdma_summary.csv
+ communication_summary.csv
+ communication_aggregate.csv
+ summary.json
+ report.md
+
+ 10. 函数行号索引
+10.1 Shell 编排器
+| 行号 | 函数组 | 职责 |
|---|---|---|
| L26-L66 | 日志、远端执行、命令证据 | 基础设施。 |
| L67-L199 | 配置、工具、时钟、GPU 空闲门禁 | 正式运行前 fail-fast。 |
| L200-L268 | Manifest、marker、Phase 1 委托 | 运行身份与复用边界。 |
| L281-L513 | 通信基线 | 按 Run 分发源码、P2P、8/16-rank AllReduce、CROSS_NIC A/B 与清理。 |
| L448-L516 | 服务和静态快照 | 启停 Phase 1 双机服务并保存环境。 |
| L517-L710 | 采集命令与启动 | 两节点分层采样。 |
| L711-L772 | 采集器检查和停止 | fail-closed 与残留清理。 |
| L782-L835 | fixed/mixed Case | 代表负载编排。 |
| L836-L858 | 汇总、Manifest、trap | 结果收口。 |
| L859-L928 | run_all | 完整状态机。 |
| L929-L968 | 辅助 action 与 main | communication/all/summarize/stop 分发。 |
10.2 Python 文件
+| 文件/行号 | 职责 |
|---|---|
communication_baseline.py:L20-L44 | 尺寸解析、分位数和 JSON 结果协议。 |
L45-L106 | CUDA P2P 全矩阵。 |
L107-L198 | NCCL AllReduce 与正确性。 |
hardware_contention_attribution.py:L76-L166 | 时间、CSV、数字统计基础函数。 |
L167-L358 | DCGM、mpstat、pidstat、perf、sar 解析器。 |
L359-L508 | 通信、GPU、RDMA、bench 读取与汇总。 |
L509-L841 | 精确窗口和全部 Case 指标切片。 |
L842-L1035 | 通信聚合、CSV、Marker、Manifest。 |
L1036-L1378 | 全部输出表和逐指标 report.md。 |
L1379-L1480 | CLI 子命令。 |
11. 最终 Run 证据
++ 正式 Run 完成 8/8 benchmark、8/8 精确测量窗口和 18/18 采集器启停。 + 代码产生的各类输出与实验结论一一对应: +
+-
+
manifest.json:Run 身份、提交、时间和最终状态。
+ bench_summary.csv:8 个端到端结果。
+ case_windows.csv:正式 benchmark 精确时间窗。
+ collector_status.csv:两节点采集器生命周期。
+ report.md:逐指标自动报告。
+ analysis.md:阶段归因与 Phase 3 入口。
+