Compare commits
No commits in common. "e9c5f85500e9aa289c27d8658269c25435ad08ec" and "66d1db85810be9479a269befd1dffed90b1d3627" have entirely different histories.
e9c5f85500
...
66d1db8581
@ -1,9 +1,5 @@
|
|||||||
# sskj — 多平台大模型推理性能基准测试项目
|
# sskj — 多平台大模型推理性能基准测试项目
|
||||||
|
|
||||||
> **更新(2026-07-31 16:18:35 CST)**
|
|
||||||
>
|
|
||||||
> 修复 Phase 2 双节点通信基线在 Worker 启动后立即退出的问题。唯一入口仍只在 Head `174.1.51.5` 执行;脚本现在按 `RUN_ID` 将 `communication_baseline.py` 自动暂存到 Head/Worker 的 `/tmp`,校验 SHA256 后只读挂载进通信容器,并在结果目录保存当次源码与哈希。Worker `174.1.51.7` 不再依赖同路径 Git 工作树,异常退出也会清理暂存文件。新增回归测试后 Phase 2 单元测试为 9/9。
|
|
||||||
>
|
|
||||||
> **更新(2026-07-31 15:59:49 CST)**
|
> **更新(2026-07-31 15:59:49 CST)**
|
||||||
>
|
>
|
||||||
> 在 DeepSeek-V4-Pro 双机 Pro6000D 推理优化主计划和 Phase 2 实施档案中增加 `phase2_code.html` 的直接入口,便于从阶段状态、实验命令与结果页面跳转到对应代码调用关系和逐行实现说明。
|
> 在 DeepSeek-V4-Pro 双机 Pro6000D 推理优化主计划和 Phase 2 实施档案中增加 `phase2_code.html` 的直接入口,便于从阶段状态、实验命令与结果页面跳转到对应代码调用关系和逐行实现说明。
|
||||||
|
|||||||
@ -105,7 +105,7 @@
|
|||||||
<p class="eyebrow">Standalone Code Walkthrough / Phase 2</p>
|
<p class="eyebrow">Standalone Code Walkthrough / Phase 2</p>
|
||||||
<h1>DSV4-Pro 双机 Pro6000D SGLang 硬件竞争归因:代码详解</h1>
|
<h1>DSV4-Pro 双机 Pro6000D SGLang 硬件竞争归因:代码详解</h1>
|
||||||
<div class="meta">
|
<div class="meta">
|
||||||
行号基线:<code>39fc2ba565a3</code>
|
行号基线:<code>30664faa41f8</code>
|
||||||
生成时间:2026-07-31 15:25:00 CST
|
生成时间:2026-07-31 15:25:00 CST
|
||||||
唯一入口:<code>run_hardware_contention_attribution.sh all</code>
|
唯一入口:<code>run_hardware_contention_attribution.sh all</code>
|
||||||
</div>
|
</div>
|
||||||
@ -114,7 +114,7 @@
|
|||||||
|
|
||||||
<main>
|
<main>
|
||||||
<div class="callout">
|
<div class="callout">
|
||||||
<strong>文档边界:</strong>本文只解释提交 <code>39fc2ba565a3</code> 的 Phase 2
|
<strong>文档边界:</strong>本文只解释提交 <code>30664faa41f8</code> 的 Phase 2
|
||||||
代码和文件调用关系。Phase 1 负责模型服务与请求;Phase 2 负责通信基线、
|
代码和文件调用关系。Phase 1 负责模型服务与请求;Phase 2 负责通信基线、
|
||||||
两节点监控、精确时间切片和逐指标报告。
|
两节点监控、精确时间切片和逐指标报告。
|
||||||
</div>
|
</div>
|
||||||
@ -161,10 +161,10 @@
|
|||||||
<thead><tr><th>文件</th><th>行数</th><th>职责</th></tr></thead>
|
<thead><tr><th>文件</th><th>行数</th><th>职责</th></tr></thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
<tr><td class="path">config.env</td><td>61</td><td>节点、Case、分层采样周期、通信尺寸、NCCL 选择和 fail-closed 策略。</td></tr>
|
<tr><td class="path">config.env</td><td>61</td><td>节点、Case、分层采样周期、通信尺寸、NCCL 选择和 fail-closed 策略。</td></tr>
|
||||||
<tr><td class="path">run_hardware_contention_attribution.sh</td><td>1036</td><td>唯一 Shell 编排器:预检、通信文件分发、通信基线、Phase 1 委托、采集器、Case 和清理。</td></tr>
|
<tr><td class="path">run_hardware_contention_attribution.sh</td><td>968</td><td>唯一 Shell 编排器:预检、通信基线、Phase 1 委托、采集器、Case 和清理。</td></tr>
|
||||||
<tr><td class="path">communication_baseline.py</td><td>227</td><td>CUDA P2P 全矩阵及 PyTorch/NCCL AllReduce 正确性、延迟和带宽测试。</td></tr>
|
<tr><td class="path">communication_baseline.py</td><td>227</td><td>CUDA P2P 全矩阵及 PyTorch/NCCL AllReduce 正确性、延迟和带宽测试。</td></tr>
|
||||||
<tr><td class="path">hardware_contention_attribution.py</td><td>1480</td><td>解析所有原始采集器,按 Case 切片,聚合通信并生成 CSV/JSON/report.md。</td></tr>
|
<tr><td class="path">hardware_contention_attribution.py</td><td>1480</td><td>解析所有原始采集器,按 Case 切片,聚合通信并生成 CSV/JSON/report.md。</td></tr>
|
||||||
<tr><td class="path">tests/test_hardware_contention_attribution.py</td><td>322</td><td>9 项纯 Python 单元测试,覆盖 worker 无仓库依赖、精确窗口、解析器、RDMA 单位和通信聚合。</td></tr>
|
<tr><td class="path">tests/test_hardware_contention_attribution.py</td><td>308</td><td>8 项纯 Python 单元测试,覆盖精确窗口、解析器、RDMA 单位和通信聚合。</td></tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
@ -212,23 +212,19 @@
|
|||||||
<h2 id="communication">5. 通信微基准</h2>
|
<h2 id="communication">5. 通信微基准</h2>
|
||||||
<h3>5.1 Shell 如何编排</h3>
|
<h3>5.1 Shell 如何编排</h3>
|
||||||
<p>
|
<p>
|
||||||
<code>run_hardware_contention_attribution.sh:L281-L513</code> 负责源码暂存、
|
<code>run_hardware_contention_attribution.sh:L269-L447</code> 负责 Docker 命令、
|
||||||
Docker 命令、两节点同步和清理。所有命令先写入 <code>commands/*.txt</code>:
|
两节点同步和清理。所有命令先写入 <code>commands/*.txt</code>:
|
||||||
</p>
|
</p>
|
||||||
<ul>
|
<ul>
|
||||||
<li><code>L281-L319</code>:从 Head 将当次通信脚本暂存到两节点并校验 SHA256。</li>
|
<li><code>L300-L323</code>:Head/Worker 各跑一次 P2P。</li>
|
||||||
<li><code>L321-L374</code>:构造容器命令,Head/Worker 各跑一次 P2P。</li>
|
<li><code>L324-L353</code>:Head/Worker 各跑一次 8-rank AllReduce。</li>
|
||||||
<li><code>L376-L404</code>:Head/Worker 各跑一次 8-rank AllReduce。</li>
|
<li><code>L354-L416</code>:每个 CROSS_NIC 值先启动 Worker rank,再运行 Head rank。</li>
|
||||||
<li><code>L406-L467</code>:每个 CROSS_NIC 值先启动 Worker rank,再运行 Head rank。</li>
|
<li><code>L417-L447</code>:只清理本实验前缀的通信容器。</li>
|
||||||
<li><code>L469-L513</code>:只清理本实验前缀的通信容器和本次 `/tmp` 暂存目录。</li>
|
|
||||||
</ul>
|
</ul>
|
||||||
<p>
|
<p>
|
||||||
Docker 使用和 SGLang 一致的 CUDA 13 nightly 镜像,并显式透传
|
Docker 使用和 SGLang 一致的 CUDA 13 nightly 镜像,并显式透传
|
||||||
<code>rdma_cm</code>、<code>uverbs0</code>、<code>uverbs3</code>。
|
<code>rdma_cm</code>、<code>uverbs0</code>、<code>uverbs3</code>。
|
||||||
<code>NCCL_DEBUG=INFO</code> 只在微基准中打开,用于证明 NET/IB/GDRDMA 路径。
|
<code>NCCL_DEBUG=INFO</code> 只在微基准中打开,用于证明 NET/IB/GDRDMA 路径。
|
||||||
Worker 不要求存在 Git 仓库;容器只读挂载自动分发的
|
|
||||||
<code>/tmp/.../<RUN_ID>/communication_baseline.py</code>。结果目录同时保存
|
|
||||||
当次源码副本和 SHA256,避免两个节点 checkout 不一致造成版本漂移。
|
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<h3>5.2 P2P 代码</h3>
|
<h3>5.2 P2P 代码</h3>
|
||||||
@ -378,7 +374,7 @@ measurement_window_source = bench_main_marker_plus_duration</code></pre>
|
|||||||
<tr><td>L26-L66</td><td>日志、远端执行、命令证据</td><td>基础设施。</td></tr>
|
<tr><td>L26-L66</td><td>日志、远端执行、命令证据</td><td>基础设施。</td></tr>
|
||||||
<tr><td>L67-L199</td><td>配置、工具、时钟、GPU 空闲门禁</td><td>正式运行前 fail-fast。</td></tr>
|
<tr><td>L67-L199</td><td>配置、工具、时钟、GPU 空闲门禁</td><td>正式运行前 fail-fast。</td></tr>
|
||||||
<tr><td>L200-L268</td><td>Manifest、marker、Phase 1 委托</td><td>运行身份与复用边界。</td></tr>
|
<tr><td>L200-L268</td><td>Manifest、marker、Phase 1 委托</td><td>运行身份与复用边界。</td></tr>
|
||||||
<tr><td>L281-L513</td><td>通信基线</td><td>按 Run 分发源码、P2P、8/16-rank AllReduce、CROSS_NIC A/B 与清理。</td></tr>
|
<tr><td>L269-L447</td><td>通信基线</td><td>P2P、8/16-rank AllReduce、CROSS_NIC A/B。</td></tr>
|
||||||
<tr><td>L448-L516</td><td>服务和静态快照</td><td>启停 Phase 1 双机服务并保存环境。</td></tr>
|
<tr><td>L448-L516</td><td>服务和静态快照</td><td>启停 Phase 1 双机服务并保存环境。</td></tr>
|
||||||
<tr><td>L517-L710</td><td>采集命令与启动</td><td>两节点分层采样。</td></tr>
|
<tr><td>L517-L710</td><td>采集命令与启动</td><td>两节点分层采样。</td></tr>
|
||||||
<tr><td>L711-L772</td><td>采集器检查和停止</td><td>fail-closed 与残留清理。</td></tr>
|
<tr><td>L711-L772</td><td>采集器检查和停止</td><td>fail-closed 与残留清理。</td></tr>
|
||||||
@ -407,7 +403,7 @@ measurement_window_source = bench_main_marker_plus_duration</code></pre>
|
|||||||
</table>
|
</table>
|
||||||
|
|
||||||
<footer>
|
<footer>
|
||||||
本文只描述提交 <code>39fc2ba565a3</code>。Nsight Systems、SGLang Profiler 和
|
本文只描述提交 <code>30664faa41f8</code>。Nsight Systems、SGLang Profiler 和
|
||||||
Kernel Timeline 属于 Phase 3,不加入 Phase 2,避免重复采集和职责混淆。
|
Kernel Timeline 属于 Phase 3,不加入 Phase 2,避免重复采集和职责混淆。
|
||||||
</footer>
|
</footer>
|
||||||
</main>
|
</main>
|
||||||
|
|||||||
@ -574,11 +574,11 @@ dsv4pro_pro6000d_2node_sglang_hardware_contention_attribution/</code></pre>
|
|||||||
<tr><th>文件</th><th>职责</th><th>当前状态</th></tr>
|
<tr><th>文件</th><th>职责</th><th>当前状态</th></tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
<tr><td><code>run_hardware_contention_attribution.sh</code></td><td>唯一 Shell 入口;按 Run 分发通信代码、通信基线、服务启停、双节点采集器、Case 编排、门禁和 Trap 清理</td><td class="pass">已实现</td></tr>
|
<tr><td><code>run_hardware_contention_attribution.sh</code></td><td>唯一 Shell 入口;通信基线、服务启停、双节点采集器、Case 编排、门禁和 Trap 清理</td><td class="pass">已实现</td></tr>
|
||||||
<tr><td><code>config.env</code></td><td>Phase 1 相对路径、节点、代表 Case、分层采样周期、通信基线与 fail-closed 策略</td><td class="pass">已实现</td></tr>
|
<tr><td><code>config.env</code></td><td>Phase 1 相对路径、节点、代表 Case、分层采样周期、通信基线与 fail-closed 策略</td><td class="pass">已实现</td></tr>
|
||||||
<tr><td><code>communication_baseline.py</code></td><td>CUDA P2P 全矩阵与 PyTorch/NCCL 8/16-rank AllReduce 微基准</td><td class="pass">已实现</td></tr>
|
<tr><td><code>communication_baseline.py</code></td><td>CUDA P2P 全矩阵与 PyTorch/NCCL 8/16-rank AllReduce 微基准</td><td class="pass">已实现</td></tr>
|
||||||
<tr><td><code>hardware_contention_attribution.py</code></td><td>精确窗口、全部采集器解析、逐 Case 汇总、通信聚合和逐指标报告</td><td class="pass">已实现</td></tr>
|
<tr><td><code>hardware_contention_attribution.py</code></td><td>精确窗口、全部采集器解析、逐 Case 汇总、通信聚合和逐指标报告</td><td class="pass">已实现</td></tr>
|
||||||
<tr><td><code>tests/test_hardware_contention_attribution.py</code></td><td>Worker 无仓库依赖、GPU/RDMA、精确窗口、DCGM/CPU 解析、通信聚合和结果生成测试</td><td class="pass">9/9 通过</td></tr>
|
<tr><td><code>tests/test_hardware_contention_attribution.py</code></td><td>GPU/RDMA、精确窗口、DCGM/CPU 解析、通信聚合和结果生成测试</td><td class="pass">8/8 通过</td></tr>
|
||||||
<tr><td><code>README.md</code></td><td>唯一入口、范围和结果目录说明</td><td class="pass">已实现</td></tr>
|
<tr><td><code>README.md</code></td><td>唯一入口、范围和结果目录说明</td><td class="pass">已实现</td></tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
@ -602,8 +602,6 @@ dsv4pro_pro6000d_2node_sglang_hardware_contention_attribution/</code></pre>
|
|||||||
head_server.log
|
head_server.log
|
||||||
worker_server.log
|
worker_server.log
|
||||||
communication/
|
communication/
|
||||||
communication_baseline.py
|
|
||||||
communication_baseline.sha256
|
|
||||||
p2p_head.log
|
p2p_head.log
|
||||||
p2p_worker.log
|
p2p_worker.log
|
||||||
allreduce_head_8gpu.log
|
allreduce_head_8gpu.log
|
||||||
@ -648,8 +646,8 @@ dsv4pro_pro6000d_2node_sglang_hardware_contention_attribution/</code></pre>
|
|||||||
|
|
||||||
<h2>8. 验收结果</h2>
|
<h2>8. 验收结果</h2>
|
||||||
<ul>
|
<ul>
|
||||||
<li class="pass">最终代码固定到提交 <code>39fc2ba565a3</code>;Shell 语法检查和三个 Python 文件编译通过。</li>
|
<li class="pass">最终代码固定到提交 <code>30664faa41f8</code>;Shell 语法检查和三个 Python 文件编译通过。</li>
|
||||||
<li class="pass">Phase 1 精确窗口 4/4 单元测试通过;Phase 2 worker 分发、采集、解析与通信聚合 9/9 单元测试通过。</li>
|
<li class="pass">Phase 1 精确窗口 4/4 单元测试通过;Phase 2 采集、解析与通信聚合 8/8 单元测试通过。</li>
|
||||||
<li class="pass">完整 Dry-run 不启动服务即可展开全部模型、采集和通信命令;通信子流程生成 2 个 P2P、2 个单机 AllReduce、6 个双机 rank 命令。</li>
|
<li class="pass">完整 Dry-run 不启动服务即可展开全部模型、采集和通信命令;通信子流程生成 2 个 P2P、2 个单机 AllReduce、6 个双机 rank 命令。</li>
|
||||||
<li class="pass">最终代码默认要求精确测量窗口、两端 DCGM 可用和全部必需采集器存活,缺失时 fail-closed。</li>
|
<li class="pass">最终代码默认要求精确测量窗口、两端 DCGM 可用和全部必需采集器存活,缺失时 fail-closed。</li>
|
||||||
<li>首次 Run 的性能数据保留在第 10 节;最终代码尚未在 16 卡上复跑,因此新通信基线和逐指标表暂不填写虚构数值。</li>
|
<li>首次 Run 的性能数据保留在第 10 节;最终代码尚未在 16 卡上复跑,因此新通信基线和逐指标表暂不填写虚构数值。</li>
|
||||||
@ -668,7 +666,6 @@ dsv4pro_pro6000d_2node_sglang_hardware_contention_attribution/</code></pre>
|
|||||||
<tr><td>2026-07-31 13:27:51 CST</td><td>完成正式双机 Run</td><td>Run <code>dsv4pro-phase2-20260731-130125</code>:8/8 benchmark 成功,总用时 26 分 26 秒,无 OOM</td></tr>
|
<tr><td>2026-07-31 13:27:51 CST</td><td>完成正式双机 Run</td><td>Run <code>dsv4pro-phase2-20260731-130125</code>:8/8 benchmark 成功,总用时 26 分 26 秒,无 OOM</td></tr>
|
||||||
<tr><td>2026-07-31 13:40:03 CST</td><td>完成首轮结果归因</td><td>排除原始双 Rail 带宽饱和、整机 CPU 饱和和频率塌陷作为首要原因;锁定 TP16 Kernel、调度与同步时间线</td></tr>
|
<tr><td>2026-07-31 13:40:03 CST</td><td>完成首轮结果归因</td><td>排除原始双 Rail 带宽饱和、整机 CPU 饱和和频率塌陷作为首要原因;锁定 TP16 Kernel、调度与同步时间线</td></tr>
|
||||||
<tr><td>2026-07-31 15:25:00 CST</td><td>完成最终 Phase 2 代码</td><td>提交 <code>30664faa41f8</code>:精确主测量窗口、双节点 DCGM 门禁、5 秒低开销 Host 采样、PCIe/NCCL 基线和逐指标自动报告均已通过本地验证</td></tr>
|
<tr><td>2026-07-31 15:25:00 CST</td><td>完成最终 Phase 2 代码</td><td>提交 <code>30664faa41f8</code>:精确主测量窗口、双节点 DCGM 门禁、5 秒低开销 Host 采样、PCIe/NCCL 基线和逐指标自动报告均已通过本地验证</td></tr>
|
||||||
<tr><td>2026-07-31 16:18:35 CST</td><td>修复 Worker 通信代码路径</td><td>提交 <code>39fc2ba565a3</code>:通信脚本按 Run 自动分发并校验哈希,Worker 不再要求存在同路径 Git 仓库;9/9 回归测试通过</td></tr>
|
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
|
|||||||
@ -12,9 +12,6 @@ RUN_ID="${RUN_ID:-dsv4pro-phase2-$(date +%Y%m%d-%H%M%S)}"
|
|||||||
RESULT_DIR="${RESULT_BASE}/${RUN_ID}"
|
RESULT_DIR="${RESULT_BASE}/${RUN_ID}"
|
||||||
RESULT_TOOL="${SCRIPT_DIR}/hardware_contention_attribution.py"
|
RESULT_TOOL="${SCRIPT_DIR}/hardware_contention_attribution.py"
|
||||||
COMMUNICATION_TOOL="${SCRIPT_DIR}/communication_baseline.py"
|
COMMUNICATION_TOOL="${SCRIPT_DIR}/communication_baseline.py"
|
||||||
COMMUNICATION_STAGE_DIR="/tmp/${EXPERIMENT}_communication/${RUN_ID}"
|
|
||||||
COMMUNICATION_STAGE_TOOL="${COMMUNICATION_STAGE_DIR}/communication_baseline.py"
|
|
||||||
COMMUNICATION_CONTAINER_TOOL="/opt/phase2/communication_baseline.py"
|
|
||||||
MARKERS_PATH="${RESULT_DIR}/markers.csv"
|
MARKERS_PATH="${RESULT_DIR}/markers.csv"
|
||||||
SERVICE_DIR="${RESULT_DIR}/service"
|
SERVICE_DIR="${RESULT_DIR}/service"
|
||||||
COMMAND_DIR="${RESULT_DIR}/commands"
|
COMMAND_DIR="${RESULT_DIR}/commands"
|
||||||
@ -35,15 +32,6 @@ print_command() {
|
|||||||
printf '\n'
|
printf '\n'
|
||||||
}
|
}
|
||||||
|
|
||||||
sha256_file() {
|
|
||||||
local path="$1"
|
|
||||||
if command -v sha256sum >/dev/null 2>&1; then
|
|
||||||
sha256sum "${path}" | awk '{print $1}'
|
|
||||||
else
|
|
||||||
shasum -a 256 "${path}" | awk '{print $1}'
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
node_is_local() {
|
node_is_local() {
|
||||||
local node="$1"
|
local node="$1"
|
||||||
local local_ips
|
local local_ips
|
||||||
@ -145,7 +133,7 @@ validate_config() {
|
|||||||
|
|
||||||
preflight_node_tools() {
|
preflight_node_tools() {
|
||||||
local node="$1"
|
local node="$1"
|
||||||
local required="nvidia-smi docker mpstat pidstat sar numastat perf sha256sum"
|
local required="nvidia-smi docker mpstat pidstat sar numastat perf"
|
||||||
local tool
|
local tool
|
||||||
for tool in ${required}; do
|
for tool in ${required}; do
|
||||||
if ! run_on_node "${node}" "command -v '${tool}' >/dev/null"; then
|
if ! run_on_node "${node}" "command -v '${tool}' >/dev/null"; then
|
||||||
@ -278,46 +266,6 @@ run_phase1_action() {
|
|||||||
"${command[@]}"
|
"${command[@]}"
|
||||||
}
|
}
|
||||||
|
|
||||||
stage_communication_tool() {
|
|
||||||
local provenance_tool="${RESULT_DIR}/communication/communication_baseline.py"
|
|
||||||
local provenance_hash="${RESULT_DIR}/communication/communication_baseline.sha256"
|
|
||||||
mkdir -p "${RESULT_DIR}/communication"
|
|
||||||
install -m 0644 "${COMMUNICATION_TOOL}" "${provenance_tool}"
|
|
||||||
printf '%s %s\n' \
|
|
||||||
"$(sha256_file "${provenance_tool}")" \
|
|
||||||
"$(basename "${provenance_tool}")" \
|
|
||||||
> "${provenance_hash}"
|
|
||||||
|
|
||||||
if [[ "${DRY_RUN}" == "1" ]]; then
|
|
||||||
log "[DRY] stage communication tool on both nodes: ${COMMUNICATION_STAGE_TOOL}"
|
|
||||||
return 0
|
|
||||||
fi
|
|
||||||
|
|
||||||
local expected_hash actual_hash node
|
|
||||||
expected_hash="$(sha256_file "${COMMUNICATION_TOOL}")"
|
|
||||||
for node in "${HEAD_NODE}" "${WORKER_NODE}"; do
|
|
||||||
if node_is_local "${node}"; then
|
|
||||||
mkdir -p "${COMMUNICATION_STAGE_DIR}"
|
|
||||||
install -m 0644 "${COMMUNICATION_TOOL}" "${COMMUNICATION_STAGE_TOOL}"
|
|
||||||
else
|
|
||||||
ssh -o BatchMode=yes -o StrictHostKeyChecking=no "${node}" \
|
|
||||||
"mkdir -p '${COMMUNICATION_STAGE_DIR}' && \
|
|
||||||
cat > '${COMMUNICATION_STAGE_TOOL}' && \
|
|
||||||
chmod 0644 '${COMMUNICATION_STAGE_TOOL}'" \
|
|
||||||
< "${COMMUNICATION_TOOL}"
|
|
||||||
fi
|
|
||||||
actual_hash="$(
|
|
||||||
run_on_node "${node}" "sha256sum '${COMMUNICATION_STAGE_TOOL}'" |
|
|
||||||
cut -d' ' -f1
|
|
||||||
)"
|
|
||||||
if [[ "${actual_hash}" != "${expected_hash}" ]]; then
|
|
||||||
log "ERROR: staged communication tool hash mismatch node=${node}"
|
|
||||||
return 1
|
|
||||||
fi
|
|
||||||
log "staged communication tool node=${node} sha256=${actual_hash}"
|
|
||||||
done
|
|
||||||
}
|
|
||||||
|
|
||||||
build_communication_docker_command() {
|
build_communication_docker_command() {
|
||||||
local output_name="$1"
|
local output_name="$1"
|
||||||
local container_name="$2"
|
local container_name="$2"
|
||||||
@ -333,7 +281,7 @@ build_communication_docker_command() {
|
|||||||
--shm-size 20g
|
--shm-size 20g
|
||||||
--ulimit memlock=-1
|
--ulimit memlock=-1
|
||||||
--ulimit stack=67108864
|
--ulimit stack=67108864
|
||||||
-v "${COMMUNICATION_STAGE_TOOL}:${COMMUNICATION_CONTAINER_TOOL}:ro"
|
-v "${REPO_ROOT}:${REPO_ROOT}:ro"
|
||||||
-e "NCCL_SOCKET_IFNAME=${NCCL_SOCKET_IFNAME}"
|
-e "NCCL_SOCKET_IFNAME=${NCCL_SOCKET_IFNAME}"
|
||||||
-e "NCCL_IB_HCA=${NCCL_IB_HCA}"
|
-e "NCCL_IB_HCA=${NCCL_IB_HCA}"
|
||||||
-e "NCCL_CROSS_NIC=${cross_nic}"
|
-e "NCCL_CROSS_NIC=${cross_nic}"
|
||||||
@ -356,7 +304,7 @@ run_p2p_baseline() {
|
|||||||
local command
|
local command
|
||||||
build_communication_docker_command \
|
build_communication_docker_command \
|
||||||
command "${container}" python3 2 \
|
command "${container}" python3 2 \
|
||||||
"${COMMUNICATION_CONTAINER_TOOL}" p2p \
|
"${COMMUNICATION_TOOL}" p2p \
|
||||||
--node "${role}" \
|
--node "${role}" \
|
||||||
--size "${P2P_SIZE}" \
|
--size "${P2P_SIZE}" \
|
||||||
--warmup "${P2P_WARMUP}" \
|
--warmup "${P2P_WARMUP}" \
|
||||||
@ -385,7 +333,7 @@ run_single_node_allreduce() {
|
|||||||
--nnodes=1 \
|
--nnodes=1 \
|
||||||
--nproc-per-node=8 \
|
--nproc-per-node=8 \
|
||||||
--master-port "${master_port}" \
|
--master-port "${master_port}" \
|
||||||
"${COMMUNICATION_CONTAINER_TOOL}" all-reduce \
|
"${COMMUNICATION_TOOL}" all-reduce \
|
||||||
--scope "${role}_8gpu" \
|
--scope "${role}_8gpu" \
|
||||||
--sizes "${COMMUNICATION_SIZES}" \
|
--sizes "${COMMUNICATION_SIZES}" \
|
||||||
--repetitions "${COMMUNICATION_REPETITIONS}" \
|
--repetitions "${COMMUNICATION_REPETITIONS}" \
|
||||||
@ -419,7 +367,7 @@ run_two_node_allreduce() {
|
|||||||
worker_command "${worker_container}" torchrun "${cross_nic}" \
|
worker_command "${worker_container}" torchrun "${cross_nic}" \
|
||||||
"${common_args[@]}" \
|
"${common_args[@]}" \
|
||||||
--node-rank=1 \
|
--node-rank=1 \
|
||||||
"${COMMUNICATION_CONTAINER_TOOL}" all-reduce \
|
"${COMMUNICATION_TOOL}" all-reduce \
|
||||||
--scope two_node_16gpu \
|
--scope two_node_16gpu \
|
||||||
--sizes "${COMMUNICATION_SIZES}" \
|
--sizes "${COMMUNICATION_SIZES}" \
|
||||||
--repetitions "${COMMUNICATION_REPETITIONS}" \
|
--repetitions "${COMMUNICATION_REPETITIONS}" \
|
||||||
@ -429,7 +377,7 @@ run_two_node_allreduce() {
|
|||||||
head_command "${head_container}" torchrun "${cross_nic}" \
|
head_command "${head_container}" torchrun "${cross_nic}" \
|
||||||
"${common_args[@]}" \
|
"${common_args[@]}" \
|
||||||
--node-rank=0 \
|
--node-rank=0 \
|
||||||
"${COMMUNICATION_CONTAINER_TOOL}" all-reduce \
|
"${COMMUNICATION_TOOL}" all-reduce \
|
||||||
--scope two_node_16gpu \
|
--scope two_node_16gpu \
|
||||||
--sizes "${COMMUNICATION_SIZES}" \
|
--sizes "${COMMUNICATION_SIZES}" \
|
||||||
--repetitions "${COMMUNICATION_REPETITIONS}" \
|
--repetitions "${COMMUNICATION_REPETITIONS}" \
|
||||||
@ -476,19 +424,6 @@ cleanup_communication_containers() {
|
|||||||
done
|
done
|
||||||
}
|
}
|
||||||
|
|
||||||
cleanup_communication_runtime() {
|
|
||||||
[[ "${DRY_RUN}" == "1" ]] && return 0
|
|
||||||
local node
|
|
||||||
for node in "${HEAD_NODE}" "${WORKER_NODE}"; do
|
|
||||||
run_on_node "${node}" "rm -rf '${COMMUNICATION_STAGE_DIR}'" || true
|
|
||||||
done
|
|
||||||
}
|
|
||||||
|
|
||||||
cleanup_communication() {
|
|
||||||
cleanup_communication_containers
|
|
||||||
cleanup_communication_runtime
|
|
||||||
}
|
|
||||||
|
|
||||||
run_communication_baseline() {
|
run_communication_baseline() {
|
||||||
[[ "${RUN_COMMUNICATION_BASELINE}" == "1" ]] || {
|
[[ "${RUN_COMMUNICATION_BASELINE}" == "1" ]] || {
|
||||||
log "SKIP communication baseline by configuration"
|
log "SKIP communication baseline by configuration"
|
||||||
@ -499,7 +434,6 @@ run_communication_baseline() {
|
|||||||
preflight_gpus_idle "${HEAD_NODE}"
|
preflight_gpus_idle "${HEAD_NODE}"
|
||||||
preflight_gpus_idle "${WORKER_NODE}"
|
preflight_gpus_idle "${WORKER_NODE}"
|
||||||
fi
|
fi
|
||||||
stage_communication_tool
|
|
||||||
run_p2p_baseline head "${HEAD_NODE}"
|
run_p2p_baseline head "${HEAD_NODE}"
|
||||||
run_p2p_baseline worker "${WORKER_NODE}"
|
run_p2p_baseline worker "${WORKER_NODE}"
|
||||||
run_single_node_allreduce head "${HEAD_NODE}" "${COMMUNICATION_MASTER_PORT}"
|
run_single_node_allreduce head "${HEAD_NODE}" "${COMMUNICATION_MASTER_PORT}"
|
||||||
@ -509,7 +443,6 @@ run_communication_baseline() {
|
|||||||
run_two_node_allreduce "${cross_nic}"
|
run_two_node_allreduce "${cross_nic}"
|
||||||
done
|
done
|
||||||
cleanup_communication_containers
|
cleanup_communication_containers
|
||||||
cleanup_communication_runtime
|
|
||||||
}
|
}
|
||||||
|
|
||||||
start_service() {
|
start_service() {
|
||||||
@ -917,7 +850,6 @@ cleanup() {
|
|||||||
stop_collectors || true
|
stop_collectors || true
|
||||||
stop_service || true
|
stop_service || true
|
||||||
cleanup_communication_containers || true
|
cleanup_communication_containers || true
|
||||||
cleanup_communication_runtime || true
|
|
||||||
if (( rc != 0 )) && [[ -f "${RESULT_DIR}/manifest.json" ]]; then
|
if (( rc != 0 )) && [[ -f "${RESULT_DIR}/manifest.json" ]]; then
|
||||||
finish_manifest ABORTED || true
|
finish_manifest ABORTED || true
|
||||||
fi
|
fi
|
||||||
@ -1003,7 +935,7 @@ run_communication_only() {
|
|||||||
preflight_node_tools "${WORKER_NODE}"
|
preflight_node_tools "${WORKER_NODE}"
|
||||||
preflight_clock_sync
|
preflight_clock_sync
|
||||||
fi
|
fi
|
||||||
trap cleanup_communication EXIT INT TERM
|
trap cleanup_communication_containers EXIT INT TERM
|
||||||
run_communication_baseline
|
run_communication_baseline
|
||||||
python3 "${RESULT_TOOL}" summarize-communication "${RESULT_DIR}"
|
python3 "${RESULT_TOOL}" summarize-communication "${RESULT_DIR}"
|
||||||
trap - EXIT INT TERM
|
trap - EXIT INT TERM
|
||||||
|
|||||||
@ -15,20 +15,6 @@ import hardware_contention_attribution as attribution # noqa: E402
|
|||||||
|
|
||||||
|
|
||||||
class HardwareContentionAttributionTest(unittest.TestCase):
|
class HardwareContentionAttributionTest(unittest.TestCase):
|
||||||
def test_communication_tool_is_staged_without_worker_repo_dependency(
|
|
||||||
self,
|
|
||||||
) -> None:
|
|
||||||
script = (
|
|
||||||
EXPERIMENT_DIR / "run_hardware_contention_attribution.sh"
|
|
||||||
).read_text(encoding="utf-8")
|
|
||||||
|
|
||||||
self.assertIn("stage_communication_tool", script)
|
|
||||||
self.assertIn(
|
|
||||||
'-v "${COMMUNICATION_STAGE_TOOL}:${COMMUNICATION_CONTAINER_TOOL}:ro"',
|
|
||||||
script,
|
|
||||||
)
|
|
||||||
self.assertNotIn('-v "${REPO_ROOT}:${REPO_ROOT}:ro"', script)
|
|
||||||
|
|
||||||
def test_gpu_summary_ignores_na_and_computes_percentiles(self) -> None:
|
def test_gpu_summary_ignores_na_and_computes_percentiles(self) -> None:
|
||||||
with tempfile.TemporaryDirectory() as temporary:
|
with tempfile.TemporaryDirectory() as temporary:
|
||||||
path = Path(temporary) / "gpu_samples.csv"
|
path = Path(temporary) / "gpu_samples.csv"
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user