Skip to content

bench(comm): expose all-reduce controls and rank timings - #4434

Open
DocJlm wants to merge 3 commits into
flashinfer-ai:mainfrom
DocJlm:agent/issue-3825-b300-ar-latency
Open

DocJlm wants to merge 3 commits into
flashinfer-ai:mainfrom
DocJlm:agent/issue-3825-b300-ar-latency

Conversation

@DocJlm

@DocJlm DocJlm commented Aug 10, 2026

Copy link
Copy Markdown

📌 Description

This PR makes the allreduce_fusion benchmark suitable for reproducing small, fixed-latency communication regressions without changing the AllReduce API or CUDA kernels.

It:

  • makes validation and measured launches honor the global --enable_pdl setting instead of hardcoding PDL on in the timed path;
  • exposes the existing strategy, completion-signaling, FP32-accumulation, L2-cache, and cross-rank aggregation controls;
  • preserves rank-local timing vectors and applies the requested max, rank0, or mean aggregation exactly once;
  • reports median, population standard deviation, and linear-interpolated p90;
  • optionally writes append-only JSONL with every rank's raw timing vector and request provenance;
  • converges process-group and MNNVL initialization failures across MPI ranks, and only destroys process groups owned by the benchmark.

The historical routine benchmarked forced oneshot and twoshot strategies, and that remains the default. The one intentional default correction is PDL: the routine now follows the global CLI contract, so PDL is off unless --enable_pdl is present.

🔍 Related Issues

Related to #3825. This benchmark-only change does not claim to fix the reported latency regression.

It also follows the PDL CLI semantics introduced in #3435.

🚀 Pull Request Checklist

Thank you for contributing to FlashInfer! Before we review your pull request, please make sure the following items are complete.

✅ Pre-commit Checks

  • I have installed pre-commit by running pip install pre-commit (or used your preferred method).
  • I have installed the hooks with pre-commit install.
  • I have rerun the hooks after the review follow-up commit.

If you are unsure about how to set up pre-commit, see the pre-commit documentation.

🧪 Tests

  • Tests have been added or updated as needed.
  • All tests are passing (unittest, etc.).

Validation performed:

  • 17 CPU-only unit tests for controls, aggregation, p90, fail-closed JSONL handling, and collective process-group ownership;
  • Linux focused pytest: 16 tests plus 3 subtests passed;
  • Linux pre-commit run --all-files: all hooks passed on the initial five-file patch and again for aa056ac2 in a clean WSL-native clone; the latter avoids Windows worktree line-ending conversion;
  • 2×B300/SM103 integrated smoke, BF16, hidden size 4096, TP=2, CUDA Events without CUDA Graphs:
    • tokens=8, forced oneshot, PDL off, early completion request, warm L2, rank aggregation=max, 10 warmups/50 samples;
    • tokens=64, auto strategy, PDL on, late completion request, FP32 accumulation, cold L2, rank aggregation=rank0, 10 warmups/30 samples;
    • tokens=4, forced oneshot and twoshot, PDL off, warm L2, rank aggregation=mean, 10 warmups/30 samples.
  • all four GPU validation runs passed; raw vectors had the expected lengths, the declared aggregation reproduced exactly, and recomputed median/p90/std matched the emitted summaries.

Reviewer Notes

Please focus on the request-vs-effective provenance wording and whether the optional raw JSONL surface is appropriately scoped. strategy_request, trigger_completion_at_end_request, and timing_mode_request deliberately do not claim backend-resolved behavior that the current APIs cannot observe.

This contribution was developed with assistance from OpenAI Codex. I reviewed the code, test coverage, and the archived B300 evidence before submission.

Summary by CodeRabbit

  • New Features

    • Added configurable AllReduce strategies, completion signaling, PDL, FP32 accumulation, cache controls, and timing modes.
    • Added rank-aware timing aggregation with p90 metrics and optional raw JSONL output.
    • Added coordinated process-group validation, error handling, and fallback behavior.
    • Expanded benchmark results with strategy, configuration, timing, and world-size metadata.
  • Documentation

    • Updated benchmark documentation with configuration details and a two-rank example command.
  • Tests

    • Added comprehensive coverage for configuration, timing, distributed validation, error handling, and JSONL output.

@coderabbitai

coderabbitai Bot commented Aug 10, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

The AllReduce benchmark now supports configurable strategies, execution controls, rank-aware timing aggregation, p90 reporting, raw JSONL output, coordinated distributed initialization, and expanded result metadata. Shared utilities, documentation, and unit tests cover these behaviors.

Changes

AllReduce benchmark controls and timing

Layer / File(s) Summary
Shared controls, timing, and output utilities
benchmarks/routines/allreduce_comm_utils.py
Added CLI controls, strategy and timing selection, rank aggregation, statistical summaries, JSONL writing, and distributed error handling.
Distributed initialization and backend selection
benchmarks/routines/allreduce_comm.py, benchmarks/routines/allreduce_comm_utils.py
Added process-group validation, coordinated initialization errors, collective MNNVL fallback to TRT-LLM, ownership tracking, and conditional cleanup.
Configurable execution and result reporting
benchmarks/routines/allreduce_comm.py, benchmarks/routines/flashinfer_benchmark_utils.py
Passed runtime controls through validation and execution. Added cache-aware timing, configurable aggregation, p90 summaries, result metadata, and rank-consistent JSONL error handling.
Validation coverage and documentation
tests/test_allreduce_comm_utils.py, benchmarks/README.md
Added utility tests and documented the controls, timing semantics, output behavior, backend limitations, and a two-rank example command.

Estimated code review effort: 4 (Complex) | ~45 minutes

Sequence Diagram(s)

sequenceDiagram
  participant CLI
  participant allreduce_comm
  participant ProcessGroup
  participant AllReduceBackend
  participant JSONL
  CLI->>allreduce_comm: provide strategy and execution controls
  allreduce_comm->>ProcessGroup: validate or initialize distributed state
  allreduce_comm->>AllReduceBackend: run AllReduce validation and iterations
  AllReduceBackend-->>allreduce_comm: return per-rank timing samples
  allreduce_comm->>JSONL: write aggregated timing metadata
  JSONL-->>allreduce_comm: return write status
  allreduce_comm-->>CLI: return benchmark results
Loading

Possibly related PRs

Suggested labels: op: comm

Suggested reviewers: aleozlx, sricketts, dhiraj113

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 60.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Title check ✅ Passed The title clearly summarizes the main changes: exposing AllReduce controls and rank timing data.
Description check ✅ Passed The description includes all required sections and provides detailed changes, related issues, checks, tests, and reviewer notes.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@DocJlm

DocJlm commented Aug 10, 2026

Copy link
Copy Markdown
Author

Local pre-commit, focused tests, and the 2xB300 integrated smoke are complete. Could a maintainer please approve the external CI for this PR? @flashinfer-bot run

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
benchmarks/routines/allreduce_comm.py (1)

454-469: 🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

A rank-local kernel failure makes the ranks diverge at comm.allgather.

bench_gpu_time can raise RuntimeError on one rank only. That rank returns None at Line 463. The other ranks continue to comm.allgather at Line 469 and block. The run then hangs instead of reporting an error.

Convert the failure into a collective decision before the gather.

🛡️ Proposed fix
+    local_bench_error = None
     try:
         times = bench_gpu_time(
             ...
         )
     except RuntimeError as e:
-        if rank == 0:
-            elem_size = torch.tensor([], dtype=input_dtype).element_size()
-            msg_size_mb = num_tokens * hidden_size * elem_size / (1024 * 1024)
-            print(
-                f"[ERROR] Kernel failed for shape=({num_tokens}, {hidden_size}) "
-                f"msg_size={msg_size_mb:.1f} MiB: {e}"
-            )
-        return None
+        times = []
+        local_bench_error = f"{type(e).__name__}: {e}"
+
+    bench_error = gather_rank_errors(comm, "AllReduce benchmark", local_bench_error)
+    if bench_error is not None:
+        if rank == 0:
+            elem_size = torch.tensor([], dtype=input_dtype).element_size()
+            msg_size_mb = num_tokens * hidden_size * elem_size / (1024 * 1024)
+            print(
+                f"[ERROR] Kernel failed for shape=({num_tokens}, {hidden_size}) "
+                f"msg_size={msg_size_mb:.1f} MiB: {bench_error}"
+            )
+        return None
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@benchmarks/routines/allreduce_comm.py` around lines 454 - 469, Update the
RuntimeError handling in the benchmark routine around bench_gpu_time so all
ranks participate in a collective failure decision before returning. Communicate
whether any rank failed, ensure every rank takes the same return path when a
failure occurs, and only execute comm.allgather when no rank has failed;
preserve the existing rank-0 error reporting.
🧹 Nitpick comments (2)
benchmarks/routines/allreduce_comm.py (1)

686-700: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Remove the dead assignment to needs_mnnvl.

Line 696 sets needs_mnnvl = False, but no later code reads needs_mnnvl. The value has no effect.

♻️ Proposed cleanup
             if args.ar_backend == "auto":
                 # Preserve one collective control flow: every rank falls back
                 # to TRT-LLM instead of letting auto re-select failed MNNVL.
                 backend_list = ["trtllm"]
-                needs_mnnvl = False
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@benchmarks/routines/allreduce_comm.py` around lines 686 - 700, Remove the
unused needs_mnnvl = False assignment from the MNNVL initialization failure
branch in the allreduce backend selection flow. Preserve the backend_list
fallback to ["trtllm"] and the surrounding control flow unchanged.
benchmarks/routines/allreduce_comm_utils.py (1)

165-184: 🩺 Stability & Availability | 🔵 Trivial | ⚡ Quick win

allow_nan=False can abort the JSONL write for valid benchmark records.

bench_gpu_time can produce nan values, and the result dict already uses torch.nan for tflops elsewhere in the benchmark. If any timing value is NaN, json.dumps raises ValueError and the whole record is dropped. The caller converts this into a cross-rank RuntimeError, so one NaN sample aborts the benchmark run.

Consider writing null for non-finite values instead of failing.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@benchmarks/routines/allreduce_comm_utils.py` around lines 165 - 184, Update
append_jsonl to serialize non-finite numeric values, including NaN and infinity,
as JSON null rather than raising from json.dumps. Preserve existing JSON output
for finite values and ensure complete benchmark records are still written.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Outside diff comments:
In `@benchmarks/routines/allreduce_comm.py`:
- Around line 454-469: Update the RuntimeError handling in the benchmark routine
around bench_gpu_time so all ranks participate in a collective failure decision
before returning. Communicate whether any rank failed, ensure every rank takes
the same return path when a failure occurs, and only execute comm.allgather when
no rank has failed; preserve the existing rank-0 error reporting.

---

Nitpick comments:
In `@benchmarks/routines/allreduce_comm_utils.py`:
- Around line 165-184: Update append_jsonl to serialize non-finite numeric
values, including NaN and infinity, as JSON null rather than raising from
json.dumps. Preserve existing JSON output for finite values and ensure complete
benchmark records are still written.

In `@benchmarks/routines/allreduce_comm.py`:
- Around line 686-700: Remove the unused needs_mnnvl = False assignment from the
MNNVL initialization failure branch in the allreduce backend selection flow.
Preserve the backend_list fallback to ["trtllm"] and the surrounding control
flow unchanged.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: e0dd8bc7-992e-4a34-91a0-3925388b411b

📥 Commits

Reviewing files that changed from the base of the PR and between 2ab910c and fd76ec2.

📒 Files selected for processing (5)
  • benchmarks/README.md
  • benchmarks/routines/allreduce_comm.py
  • benchmarks/routines/allreduce_comm_utils.py
  • benchmarks/routines/flashinfer_benchmark_utils.py
  • tests/test_allreduce_comm_utils.py

@DocJlm

DocJlm commented Aug 10, 2026

Copy link
Copy Markdown
Author

Addressed the review in commit 4de67ad: rank-local �ench_gpu_time failures are now gathered before any rank enters the raw-sample �llgather, so all ranks take the same return path; the dead
eeds_mnnvl assignment is removed. I kept �llow_nan=False intentionally: a non-finite timing vector is invalid evidence and writing JSON
ull would make the raw vector and its summaries unrecomputable. I added an explicit fail-closed unit test for that policy. All 17 focused unit tests, py_compile, and git diff --check pass.

@DocJlm

DocJlm commented Aug 10, 2026

Copy link
Copy Markdown
Author

Correction: the remote Linux hook invocation for commit 4de67ad did not complete because the SSH file transfer stalled; I am not counting it as a pass. The verified follow-up checks are 17 focused unit tests, py_compile, and git diff --check. The full Linux pre-commit suite passed on the preceding five-file patch, and maintainer CI has been requested. I will update this comment only after the follow-up files actually pass the remote hooks.

@DocJlm

DocJlm commented Aug 10, 2026

Copy link
Copy Markdown
Author

Follow-up verification is now complete at aa056ac2. Commit aa056ac2 contains only the one-line ruff-format adjustment to the review fix in 4de67ad8. In a clean WSL-native filesystem clone (avoiding Windows checkout CRLF conversion), pre-commit run --all-files passed every hook; the 17 focused unit tests, py_compile, and git diff --check also pass. The earlier interrupted B300 SSH hook invocation remains excluded rather than being retroactively counted.

@coderabbitai coderabbitai Bot mentioned this pull request Aug 19, 2026
5 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant