#15 - Add DGX Spark sweep tooling and RDMA loopback prereqs#97
Conversation
Stacks on the bench-infra PR (#α) which provides --seconds, TokenBucketPacer,
and the bench-output format these scripts parse.
- examples/run_spark_bench.sh: Spark-tuned sweep driver with per-backend
payload/batch matrices, CPU pins, drop-source dispatch (DPDK imissed/
ierrors/nombuf, RDMA CQ errors, socket /proc/net/udp drops + nstat
retrans), and one CSV row per cell into bench-results/.
- scripts/spark_data_fill.sh: one-shot driver that runs the full bench
matrix across DPDK / socket-UDP / socket-TCP, with hugepage pre-flight
and orphan-hugepage cleanup between runs.
- scripts/setup_spark_rdma_loopback.sh: idempotent host prereq pinning
static ARP entries and source-based policy routing for the Spark
single-NIC cross-cable RoCE loopback. Hardcodes the Spark CX-7 netdev
names, MAC addresses, and 1.1.1.1 / 2.2.2.2 IPs from
daqiri_bench_rdma_tx_rx_spark.yaml — the technique generalizes to any
single-NIC RoCE loopback, the script does not. Renamed from the
earlier setup_rdma_loopback.sh draft to make the platform scope
obvious in the directory listing.
- examples/rdma_bench.cpp: raise kMaxOutstanding 5→20 to match num_bufs
in the YAML configs. Lifts small-payload pps 8–22× on Spark (4 KB:
4→39 msg/s, 8 KB: 4→88, 64 KB: 32→255) without affecting the 8 MB /
1 MB cells already saturated at depth 5. The new comment documents
why the constant cannot exceed num_bufs (post_req / free_tx_burst
ordering in the same loop iteration would deadlock instead of
throttling). A follow-up tracks the deeper architectural fix
(interleave drain with post, bulk tx_ring dequeue, configurable depth).
- .gitignore: pcie_schematic.png (generated by tune_system.py).
Includes fixes for two parsing bugs Greptile flagged on the original
draft of run_spark_bench.sh:
- /proc/net/udp drops column is decimal (%lu in net/ipv4/udp.c), not
hex. Drop the strtonum("0x" ...) treatment that was silently
multiplying drop counts whenever the column value contained any
digit > 9.
- Socket bench emits sent_packets / sent_bytes (not RDMA's
send_completions / send_bytes), so the RDMA-keyed fallback was
always returning empty for socket backends and producing
zero-filled CSV rows. Dispatch the fallback on $BACKEND.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Signed-off-by: rgurunathan <rgurunathan@nvidia.com>
|
| Filename | Overview |
|---|---|
| examples/run_spark_bench.sh | New Spark sweep driver; good drop-source dispatch and decimal /proc/net/udp parse, but nvidia-smi dmon column indices ($5/$6) are wrong for -s pucvmet — sm% and mem% land at $3/$4 with that flag, so the CSV records encoder/decoder utilization under the gpu_sm_pct/gpu_mem_pct headers. |
| examples/rdma_bench.cpp | kMaxOutstanding raised 5→20 with a clear comment explaining the deadlock bound (post_req/free_tx_burst ordering); BurstParams free contract is correctly maintained on all exit paths in post_req. |
| scripts/setup_spark_rdma_loopback.sh | Idempotent RDMA loopback prereq script; correctly flushes routes and deletes rules before re-adding, static ARP self-entries are intentional for the cross-cable RoCE loopback topology. |
| scripts/spark_data_fill.sh | Orchestration driver with solid hugepage pre-flight checks, auto-detected ETH_DST_ADDR, and orphan-hugepage cleanup between runs; correctly captures wrapper exit code via PIPESTATUS[0]. |
| .gitignore | Adds bench-results/ and pcie_schematic.png (tune_system.py output) to .gitignore. |
Reviews (1): Last reviewed commit: "#15 - Add DGX Spark sweep tooling and RD..." | Re-trigger Greptile
| local gpu_sm gpu_mem | ||
| gpu_sm="$(awk '/^ *[0-9]/ { count++; sum += $5 } END { if (count) printf "%.1f", sum/count; else print 0 }' \ | ||
| "$cell_dir/nvidia_smi_dmon.txt" 2>/dev/null || echo 0)" | ||
| gpu_mem="$(awk '/^ *[0-9]/ { count++; sum += $6 } END { if (count) printf "%.1f", sum/count; else print 0 }' \ | ||
| "$cell_dir/nvidia_smi_dmon.txt" 2>/dev/null || echo 0)" |
There was a problem hiding this comment.
The column indices $5 and $6 match the default
nvidia-smi dmon output (where gtemp/mtemp precede sm/mem, giving: idx=$1 pwr=$2 gtemp=$3 mtemp=$4 sm=$5 mem=$6). But the script explicitly passes -s pucvmet, which reorders the groups: power → utilization → clocks → violations → bandwidth → errors → temperature. With that ordering, temperature moves to the end and the utilization metrics shift left: idx=$1 pwr=$2 sm=$3 mem=$4 enc=$5 dec=$6. As written, the CSV columns gpu_sm_pct and gpu_mem_pct will silently record encoder% and decoder% instead of SM and memory utilization. Both happen to be near-zero for GPUDirect workloads, making this easy to miss during testing.
| local gpu_sm gpu_mem | |
| gpu_sm="$(awk '/^ *[0-9]/ { count++; sum += $5 } END { if (count) printf "%.1f", sum/count; else print 0 }' \ | |
| "$cell_dir/nvidia_smi_dmon.txt" 2>/dev/null || echo 0)" | |
| gpu_mem="$(awk '/^ *[0-9]/ { count++; sum += $6 } END { if (count) printf "%.1f", sum/count; else print 0 }' \ | |
| "$cell_dir/nvidia_smi_dmon.txt" 2>/dev/null || echo 0)" | |
| local gpu_sm gpu_mem | |
| # With -s pucvmet the column order is: idx($1) pwr($2) sm($3) mem($4) enc($5)... | |
| # (temperature is moved to the end; $5/$6 in the default layout only hold sm/mem | |
| # when gtemp/mtemp appear between power and utilization, which -s overrides). | |
| gpu_sm="$(awk '/^ *[0-9]/ { count++; sum += $3 } END { if (count) printf "%.1f", sum/count; else print 0 }' \ | |
| "$cell_dir/nvidia_smi_dmon.txt" 2>/dev/null || echo 0)" | |
| gpu_mem="$(awk '/^ *[0-9]/ { count++; sum += $4 } END { if (count) printf "%.1f", sum/count; else print 0 }' \ | |
| "$cell_dir/nvidia_smi_dmon.txt" 2>/dev/null || echo 0)" |
* #15 - Add RDMA benchmark profiling knobs Instrument the RDMA benchmark and manager hot paths so SEND/RECV posting, CQ polling, ring traffic, and app refill behavior can be measured while debugging the perftest gap. Add RDMA tuning hooks for relaxed ordering, SEND signaling cadence, queue depth, SPSC rings, and RDMA buffer alignment, plus a server connection readiness guard. Signed-off-by: Cliff Burdick <cburdick@nvidia.com> * #15 - Remove RDMA benchmark debug instrumentation Drop benchmark-side timing/profile output and remove RDMA manager profiling timers while keeping the non-debug RDMA transport tuning changes. Signed-off-by: Cliff Burdick <cburdick@nvidia.com> * #15 - Avoid RDMA benchmark buffer starvation deadlock Treat TX buffer exhaustion as backpressure in the RDMA benchmark so the worker returns to completion draining before retrying. Also clean up RDMA TX packet burst allocations on partial failure. Signed-off-by: Cliff Burdick <cburdick@nvidia.com> * #15 - Address Greptile RDMA review comments Fix RDMA completion enqueue failure cleanup to avoid returning metadata twice, and document the single-producer/single-consumer invariant for RDMA connection rings. Signed-off-by: Cliff Burdick <cburdick@nvidia.com> * #15 - Retire RDMA send completions on CQ errors Sweep outstanding SEND work requests through an errored CQE so selective signaling cannot orphan unsignaled bursts on TX errors. Signed-off-by: Cliff Burdick <cburdick@nvidia.com> --------- Signed-off-by: Cliff Burdick <cburdick@nvidia.com>
|
Clarifying stack repair state as of 2026-06-03: this PR shows MERGED because it was merged into the stacked base branch Cleanup note: once PR #118 lands, the stale stack branches under |
Summary
Second of a 3-PR stack replacing #72. Layers DGX Spark-specific sweep tooling and the RDMA-bench depth bump on top of #96 (reusable bench infra).
examples/run_spark_bench.sh— Spark-tuned sweep driver with per-backend payload/batch matrices, CPU pins, drop-source dispatch (DPDK imissed/ierrors/nombuf, RDMACQ error, socket/proc/net/udpdrops +nstatretrans), and one CSV row per cell intobench-results/.scripts/spark_data_fill.sh— one-shot driver that runs the full bench matrix across DPDK / socket-UDP / socket-TCP, with hugepage pre-flight and orphan-hugepage cleanup between runs.scripts/setup_spark_rdma_loopback.sh— idempotent host prereq pinning static ARP entries and source-based policy routing for the Spark single-NIC cross-cable RoCE loopback. The script hardcodes the Spark CX-7 netdev names, MACs, and 1.1.1.1 / 2.2.2.2 IPs fromdaqiri_bench_rdma_tx_rx_spark.yaml— the technique generalizes to any single-NIC RoCE loopback, the script does not (thespark_prefix is intentional).examples/rdma_bench.cpp— raisekMaxOutstanding5→20 to matchnum_bufsin the YAML configs. Lifts small-payload pps 8–22× on Spark (4 KB: 4→39 msg/s, 8 KB: 4→88, 64 KB: 32→255) without affecting 8 MB / 1 MB cells already saturated at depth 5. The new comment documents why the constant cannot exceednum_bufs(post_req / free_tx_burst ordering in the same loop iteration would deadlock instead of throttling). A follow-up tracks the deeper architectural fix..gitignore—pcie_schematic.png(generated bytune_system.py).Also includes two parse fixes Greptile flagged on the draft of
run_spark_bench.sh:/proc/net/udpcolumn 13 (drops) is decimal (%luinnet/ipv4/udp.c), not hex. Dropped thestrtonum("0x" ...)treatment that was silently multiplying drop counts whenever the column value contained any digit > 9.sent_packets/sent_bytes, not RDMA'ssend_completions/send_bytes, so the RDMA-keyed fallback was always returning empty for socket backends and producing zero-filled CSV rows. The fallback now dispatches on$BACKEND.Stack
Stacked on #96 — must land after.
PR γ (Spark perf doc) opens next once its checks pass.
Test plan
cmake --build build -j— no warnings.setup_spark_rdma_loopback.shidempotent: two consecutivesudo ./scripts/setup_spark_rdma_loopback.shruns both exit 0;ip rule listshows 4 rules andarp -nshows 4 PERM entries for 1.1.1.1 / 2.2.2.2../examples/run_spark_bench.sh socket-udp smokenow produces a CSV row withpackets=1000, bytes=1472000(pre-fix the same run produced all zeros). Throughput is low because socket-UDP at MTU is bench-bottlenecked on Spark — that's a separate characterization concern for the perf-doc data-fill follow-up, not a wrapper bug../examples/run_spark_bench.sh rdma smokeproducesgbps=83.764on the 8 MB native cell (matches the perf-doc headline) with 0 CQ errors./proc/net/udpdecimal-parse sanity: no order-of-magnitude inflation between the host-sideawksum and the CSV drops field.🤖 Generated with Claude Code