Skip to content

docs(bench): add H100 SXM5 benchmark results alongside A100 baseline - #231

Open
Billy1900 wants to merge 5 commits into
RL-Align:mainfrom
Billy1900:bench/h100-sxm5-results
Open

docs(bench): add H100 SXM5 benchmark results alongside A100 baseline#231
Billy1900 wants to merge 5 commits into
RL-Align:mainfrom
Billy1900:bench/h100-sxm5-results

Conversation

@Billy1900

@Billy1900 Billy1900 commented Jul 19, 2026

Copy link
Copy Markdown

Summary

  • Fills in the previously-pending h100-sxm5 rows in docs/benchmarking/hardware-dashboard.md: logp native/fused (via scripts/run_profile_suite.py), sampling (native vs FlashInfer), and linear_logp SM90-vs-Triton-vs-native, all measured on a real H100 80GB HBM3 (SM90) with the extension built via KERNEL_ALIGN_FORCE_SM90=1.
  • Adds a real Qwen3-30B-A3B validation using downloaded weights and a real forward pass (not synthetic tensors), confirming the README's "56.9 GB weights / 23 GB headroom" claim on actual hardware (measured: 56.87 GB / 79.11 GB → 22.24 GB headroom).
  • Adds a condensed, headline summary in README.md (new "H100 SXM5 Independent Validation" section) that links to the dashboard doc for full methodology, raw CSV/JSON reports (reports/perf_report_NVIDIA_H100_80GB_HBM3*), and exact reproduction commands.
  • Reports the SM90 linear_logp kernel's tradeoffs honestly rather than cherry-picking: it beats the Triton path by 1.7–1.9x at ~600–2500x less memory than the naive materializing path, but does not uniformly beat naive on raw latency (naive wins forward at 2 of 3 vocab sizes tested, and wins backward across the board — tile recomputation trades FLOPs for memory).
  • Documents two gaps found while benchmarking, out of scope for this PR: (1) benchmarks/profiler.py's WORKLOAD_REGISTRY has no sampling-fused workload, so the FlashInfer sampling numbers come from benchmarks/benchmark_sampling.py directly instead of the profiler suite; (2) the experimental, off-by-default fused_logp_sm90 standalone kernel (RL_KERNEL_ENABLE_EXPERIMENTAL_SM90_LOGP=1) currently aborts the process via exit(EXIT_FAILURE) on a failed cuTensorMapEncodeTiled call in csrc/utils/tma_utils.cuh, instead of raising a catchable error.

Addresses #75.

Test plan

  • scripts/run_profile_suite.py --device cuda --dtype float16 --batch-sizes 8,16,32 --seq-lens 128,512 --vocab-sizes 4096,128256 --workloads logp-native,logp-fused — run on H100, raw output committed under reports/.
  • benchmarks/benchmark_sampling.py --g-sizes 32,64,128,256 --vocab-size 128256 --top-k 50 --top-p 0.9 — run on H100.
  • benchmarks/benchmark_linear_logp.py (SM90 build) — run on H100.
  • Real Qwen/Qwen3-30B-A3B weights downloaded and loaded in bf16 on H100; weight VRAM + logprob memory/latency sweep measured directly (script not included in this PR — happy to add it under benchmarks/ if useful as a repeatable workload).
  • MI300X/ROCm rows remain pending (no ROCm hardware available for this pass).

🤖 Generated with Claude Code

Summary by CodeRabbit

  • Documentation
    • Added independently validated NVIDIA H100 SXM5 benchmark results (LogP, sampling, and linear-logp), including profiling commands and clarified limitations.
    • Updated the hardware benchmark dashboard with measured H100 values (keeping MI300 entries marked pending) and clarified FlashInfer token/VRAM reporting gaps.
    • Added real-model validation details for Qwen3-30B-A3B on H100, including VRAM headroom metrics, OOM outcomes, and latency caveats.
  • New Benchmarks & Reports
    • Added new benchmark report artifacts (JSON and raw logs) for H100 LogP, sampling, and Qwen3 model validations comparing native vs RL-Kernel results.

Fills in the h100-sxm5 rows in the hardware benchmark dashboard (logp
native/fused, sampling, linear_logp SM90-vs-Triton-vs-native) and adds a
real Qwen3-30B-A3B validation using downloaded weights and a real forward
pass instead of synthetic tensors, confirming the 56.9 GB / 23 GB headroom
claim on actual hardware.

Reports honestly: the SM90 linear_logp kernel beats Triton and uses far
less memory than the naive path, but does not uniformly beat naive on raw
latency (tile-recompute trades FLOPs for memory). Also documents two gaps
found while benchmarking: no sampling-fused workload in the profiler
suite, and the experimental (off-by-default) fused_logp_sm90 kernel
currently crashes the process on cuTensorMapEncodeTiled failure.

Addresses RL-Align#75.
@Billy1900
Billy1900 requested a review from Flink-ddd as a code owner July 19, 2026 08:33
Copilot AI review requested due to automatic review settings July 19, 2026 08:33
@coderabbitai

coderabbitai Bot commented Jul 19, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

Adds H100 SXM5 benchmark tooling, raw and structured performance reports, and documented LogP, sampling, SM90 kernel, and Qwen3 validation results.

Changes

H100 SXM5 benchmark validation

Layer / File(s) Summary
Real-model benchmark execution
benchmarks/benchmark_qwen3_moe_real_model.py, reports/benchmark_qwen3_30b_a3b_NVIDIA_H100_80GB_HBM3.txt
Adds a CUDA benchmark comparing native and RL-Kernel logprob computation on Qwen models, with latency, VRAM, and OOM reporting.
H100 benchmark artifacts
reports/perf_report_*.json, reports/benchmark_linear_logp_sm90_*.txt, reports/benchmark_sampling_*.txt
Adds structured LogP and sampling metrics plus raw SM90, sampling, and Qwen3 benchmark outputs for H100 SXM5.
Validation documentation
docs/benchmarking/hardware-dashboard.md, README.md
Replaces H100 placeholders with measured LogP and sampling results, adds SM90 and Qwen3 validation sections, and records benchmark limitations.

Estimated code review effort: 3 (Moderate) | ~25 minutes

Possibly related issues

Possibly related PRs

  • RL-Align/RL-Kernel#172: Updates the same hardware dashboard with concrete H100 SXM5 measurements and related documentation.
  • RL-Align/RL-Kernel#214: Covers the same SM90 linear_logp operator through related benchmark and documentation changes.

Suggested labels: needs-gpu-ci

Suggested reviewers: inaniloquentee, flink-ddd, kjldefeated, cybersecurityerial

Sequence Diagram(s)

sequenceDiagram
  participant CLI
  participant QwenModel
  participant CUDA
  participant RLKernel
  CLI->>QwenModel: Load model and obtain hidden states
  QwenModel->>CUDA: Allocate benchmark inputs
  CLI->>CUDA: Measure native logprob
  CLI->>RLKernel: Dispatch linear_logp
  RLKernel->>CUDA: Measure fused logprob
  CUDA-->>CLI: Return latency, VRAM, or OOM results
Loading
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately reflects the main change: adding H100 SXM5 benchmark results next to the existing baseline.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
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.
✨ 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.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull request overview

Adds NVIDIA H100 SXM5 benchmark/validation documentation and accompanying profiler output artifacts to complement the existing A100-focused performance claims, aiming to address Issue #75 by documenting H100 logp, sampling, and linear_logp behavior plus a real-model memory validation.

Changes:

  • Adds H100 logp + sampling-native profiler outputs under reports/ (CSV + timestamped JSON).
  • Updates docs/benchmarking/hardware-dashboard.md with an H100 environment entry and tables summarizing H100 logp/sampling/linear_logp/Qwen3 validation results.
  • Adds a new “H100 SXM5 Independent Validation” section to README.md linking to the dashboard and reports.

Reviewed changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
reports/perf_report_NVIDIA_H100_80GB_HBM3.csv Adds consolidated CSV profiler output including logp sweep and sampling-native rows on H100.
reports/perf_report_NVIDIA_H100_80GB_HBM3_20260719_081350.json Adds timestamped JSON report for H100 logp sweep metrics.
reports/perf_report_NVIDIA_H100_80GB_HBM3_20260719_081405.json Adds timestamped JSON report for H100 sampling-native metrics.
README.md Adds an H100 validation section with headline results and links to dashboard/reports.
docs/benchmarking/hardware-dashboard.md Fills in H100 SXM5 rows and adds summarized tables and methodology notes.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread README.md
Comment thread docs/benchmarking/hardware-dashboard.md Outdated
Comment thread README.md
Comment thread docs/benchmarking/hardware-dashboard.md Outdated

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 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.

Inline comments:
In `@docs/benchmarking/hardware-dashboard.md`:
- Around line 46-49: Update the artifact reference in the benchmarking
documentation to point to the committed timestamped JSON report files, using the
H100 report naming pattern shown in the review comment instead of the
nonexistent CSV path.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: e2caaeac-eb91-47b1-9023-a8a3fb75fb03

📥 Commits

Reviewing files that changed from the base of the PR and between 6df029a and 946edee.

⛔ Files ignored due to path filters (1)
  • reports/perf_report_NVIDIA_H100_80GB_HBM3.csv is excluded by !**/*.csv
📒 Files selected for processing (4)
  • README.md
  • docs/benchmarking/hardware-dashboard.md
  • reports/perf_report_NVIDIA_H100_80GB_HBM3_20260719_081350.json
  • reports/perf_report_NVIDIA_H100_80GB_HBM3_20260719_081405.json

Comment thread docs/benchmarking/hardware-dashboard.md
…gp/Qwen3 numbers

Copilot review on RL-Align#231 correctly flagged that the FlashInfer sampling,
linear_logp SM90, and Qwen3-30B-A3B numbers in the dashboard/README had no
committed raw output to audit against. Fixes that:

- Adds benchmarks/benchmark_qwen3_moe_real_model.py (previously only a
  local scratch script) so the real-model benchmark is itself reviewable
  and reproducible, not just its output.
- Re-runs all three benchmarks and commits their raw console output under
  reports/, then updates the dashboard/README numbers to match those
  committed runs exactly (previous figures were from an earlier,
  uncommitted run and differed by normal run-to-run noise).

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🧹 Nitpick comments (1)
benchmarks/benchmark_qwen3_moe_real_model.py (1)

116-135: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Resolve static analysis errors for loop variables.

Ruff flags hidden and target as potentially undefined (F821) and warns about late-binding in the lambdas (B023). While the code executes correctly because measure evaluates the lambda synchronously and the continue statement prevents execution from reaching the lambdas if initialization fails, explicitly binding these variables in the lambdas and pre-initializing them satisfies static analysis.

🛠️ Proposed fix to satisfy static analysis
-        try:
-            hidden, target = make_batch(n)
-        except torch.cuda.OutOfMemoryError:
-            rows.append([n, "OOM (input alloc)", "OOM (input alloc)", "N/A", "N/A", "N/A"])
-            torch.cuda.empty_cache()
-            continue
-
-        try:
-            native_extra, native_ms = measure(lambda: native_logprob(hidden, lm_head_weight, target))
-            native_str, native_ms_str = f"{native_extra:.2f} GB", f"{native_ms:.2f} ms"
-        except torch.cuda.OutOfMemoryError:
-            native_str, native_ms_str = "OOM", "N/A"
-        torch.cuda.empty_cache()
-
-        try:
-            kernel_extra, kernel_ms = measure(lambda: linear_logp_op(hidden, lm_head_weight, target))
-            kernel_str, kernel_ms_str = f"{kernel_extra:.2f} GB", f"{kernel_ms:.2f} ms"
-        except torch.cuda.OutOfMemoryError:
-            kernel_str, kernel_ms_str = "OOM", "N/A"
+        hidden = target = None
+        try:
+            hidden, target = make_batch(n)
+        except torch.cuda.OutOfMemoryError:
+            rows.append([n, "OOM (input alloc)", "OOM (input alloc)", "N/A", "N/A", "N/A"])
+            torch.cuda.empty_cache()
+            continue
+
+        try:
+            native_extra, native_ms = measure(lambda h=hidden, t=target: native_logprob(h, lm_head_weight, t))
+            native_str, native_ms_str = f"{native_extra:.2f} GB", f"{native_ms:.2f} ms"
+        except torch.cuda.OutOfMemoryError:
+            native_str, native_ms_str = "OOM", "N/A"
+        torch.cuda.empty_cache()
+
+        try:
+            kernel_extra, kernel_ms = measure(lambda h=hidden, t=target: linear_logp_op(h, lm_head_weight, t))
+            kernel_str, kernel_ms_str = f"{kernel_extra:.2f} GB", f"{kernel_ms:.2f} ms"
+        except torch.cuda.OutOfMemoryError:
+            kernel_str, kernel_ms_str = "OOM", "N/A"
🤖 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/benchmark_qwen3_moe_real_model.py` around lines 116 - 135,
Initialize hidden and target before the batch-construction try block so they are
defined on every loop path, then explicitly bind both as default arguments in
the native_logprob and linear_logp_op lambdas passed to measure. Preserve the
existing OOM handling and synchronous measurement behavior.

Source: Linters/SAST tools

🤖 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.

Nitpick comments:
In `@benchmarks/benchmark_qwen3_moe_real_model.py`:
- Around line 116-135: Initialize hidden and target before the
batch-construction try block so they are defined on every loop path, then
explicitly bind both as default arguments in the native_logprob and
linear_logp_op lambdas passed to measure. Preserve the existing OOM handling and
synchronous measurement behavior.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: a1344e09-ef4f-48b1-83f5-5691435ff38c

📥 Commits

Reviewing files that changed from the base of the PR and between 946edee and 55a2b4e.

📒 Files selected for processing (6)
  • README.md
  • benchmarks/benchmark_qwen3_moe_real_model.py
  • docs/benchmarking/hardware-dashboard.md
  • reports/benchmark_linear_logp_sm90_NVIDIA_H100_80GB_HBM3.txt
  • reports/benchmark_qwen3_30b_a3b_NVIDIA_H100_80GB_HBM3.txt
  • reports/benchmark_sampling_NVIDIA_H100_80GB_HBM3.txt
🚧 Files skipped from review as they are similar to previous changes (2)
  • README.md
  • docs/benchmarking/hardware-dashboard.md

Remove del hidden, target which caused flake8 F821 false positives
(pyflakes checks lambda bodies in a deferred pass after the del had
already removed the bindings from scope). Apply black formatting and
fix trailing whitespace/EOF newlines in report files.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

Caution

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

⚠️ Outside diff range comments (3)
benchmarks/benchmark_qwen3_moe_real_model.py (3)

108-110: 🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

Avoid materializing the repeated hidden buffer twice.

repeat(reps, 1)[:n].clone() first allocates the full repeated tensor and then allocates the cloned slice. Near repetition boundaries this temporarily uses almost 2× the requested input memory and can report OOM for a token count that would otherwise fit.

Proposed fix
 def make_batch(n):
-    reps = (n + real_hidden.shape[0] - 1) // real_hidden.shape[0]
-    hidden = real_hidden.repeat(reps, 1)[:n].clone()
+    indices = torch.arange(n, device=real_hidden.device) % real_hidden.shape[0]
+    hidden = real_hidden.index_select(0, indices)
     target = torch.randint(0, vocab_size, (n,), device="cuda")
     return hidden, target
🤖 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/benchmark_qwen3_moe_real_model.py` around lines 108 - 110, Update
make_batch so it constructs the requested n-row hidden tensor directly instead
of materializing the full real_hidden.repeat(reps, 1) result before cloning the
slice. Preserve the existing repeated-row contents and returned shape while
ensuring only the needed input buffer is allocated.

69-82: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Report actual free GPU memory as headroom.

torch.cuda.memory_allocated() only covers tensor allocations belonging to the PyTorch process, so total_gb - weight_gb can overstate usable VRAM by ignoring CUDA context, allocator-reserved/cached memory, and any existing usage. Use torch.cuda.mem_get_info(0) after loading to report headroom, or rename this metric to make clear it is only an allocation estimate.

Proposed fix
-    total_gb = gb(torch.cuda.get_device_properties(0).total_memory)
-    headroom_gb = total_gb - weight_gb
+    free_bytes, total_bytes = torch.cuda.mem_get_info(0)
+    total_gb = gb(total_bytes)
+    headroom_gb = gb(free_bytes)
🤖 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/benchmark_qwen3_moe_real_model.py` around lines 69 - 82, Update
the post-load memory reporting near weight_gb and headroom_gb to use
torch.cuda.mem_get_info(0) after model loading, and derive headroom_gb from the
returned free-memory value. Preserve weight_gb as the PyTorch allocation
estimate, but ensure the reported headroom reflects actual available GPU memory
rather than total memory minus allocations.

88-101: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Do not expose the real-model benchmark with an unvalidated --model option.

AutoModelForCausalLM is generic; checkpoint-specific attributes vary, but benchmarks/benchmark_qwen3_moe_real_model.py:90 directly accesses model.lm_head and benchmarks/benchmark_qwen3_moe_real_model.py:100 directly calls model.model without checking whether the loaded model actually provides these names. Restrict --model to supported Qwen3-compatible checkpoints, or fail fast with validation before accessing architecture-specific modules.

🤖 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/benchmark_qwen3_moe_real_model.py` around lines 88 - 101, Validate
the loaded model in the benchmark before the architecture-specific accesses to
model.lm_head and model.model. Restrict --model to supported Qwen3-compatible
checkpoints or fail fast with a clear error when those required modules are
unavailable, ensuring the benchmark never reaches the lm_head shape logging or
real forward pass with an incompatible model.
🧹 Nitpick comments (1)
benchmarks/benchmark_qwen3_moe_real_model.py (1)

132-139: 🩺 Stability & Availability | 🔵 Trivial

Isolate the experimental SM90 backend from the benchmark process.

The PR documents that fused_logp_sm90 can terminate the process when cuTensorMapEncodeTiled fails. Catching only torch.cuda.OutOfMemoryError cannot preserve partial results in that case; run the risky backend in a subprocess if the benchmark must remain resilient and produce a report.

🤖 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/benchmark_qwen3_moe_real_model.py` around lines 132 - 139, Update
the benchmark flow around the fused log-probability measurement and
linear_logp_op so the experimental SM90 backend runs in an isolated subprocess
when resilience is required. Capture its success, timing, OOM, and abnormal
termination as reportable results, allowing the parent benchmark process to
continue and preserve partial output instead of relying only on
torch.cuda.OutOfMemoryError handling.
🤖 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.

Inline comments:
In `@benchmarks/benchmark_qwen3_moe_real_model.py`:
- Around line 124-134: Update both benchmark callbacks passed to measure in the
native and kernel paths to bind the current hidden and target values at lambda
creation time, using default arguments or functools.partial. Preserve the
existing native_logprob and linear_logp_op calls while ensuring each callback is
independent of later loop-variable reassignment and satisfies Ruff B023.

---

Outside diff comments:
In `@benchmarks/benchmark_qwen3_moe_real_model.py`:
- Around line 108-110: Update make_batch so it constructs the requested n-row
hidden tensor directly instead of materializing the full
real_hidden.repeat(reps, 1) result before cloning the slice. Preserve the
existing repeated-row contents and returned shape while ensuring only the needed
input buffer is allocated.
- Around line 69-82: Update the post-load memory reporting near weight_gb and
headroom_gb to use torch.cuda.mem_get_info(0) after model loading, and derive
headroom_gb from the returned free-memory value. Preserve weight_gb as the
PyTorch allocation estimate, but ensure the reported headroom reflects actual
available GPU memory rather than total memory minus allocations.
- Around line 88-101: Validate the loaded model in the benchmark before the
architecture-specific accesses to model.lm_head and model.model. Restrict
--model to supported Qwen3-compatible checkpoints or fail fast with a clear
error when those required modules are unavailable, ensuring the benchmark never
reaches the lm_head shape logging or real forward pass with an incompatible
model.

---

Nitpick comments:
In `@benchmarks/benchmark_qwen3_moe_real_model.py`:
- Around line 132-139: Update the benchmark flow around the fused
log-probability measurement and linear_logp_op so the experimental SM90 backend
runs in an isolated subprocess when resilience is required. Capture its success,
timing, OOM, and abnormal termination as reportable results, allowing the parent
benchmark process to continue and preserve partial output instead of relying
only on torch.cuda.OutOfMemoryError handling.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 60cdc5bd-c95f-43eb-9c05-1c2c90fe983b

📥 Commits

Reviewing files that changed from the base of the PR and between 55a2b4e and 8b69ca4.

📒 Files selected for processing (4)
  • benchmarks/benchmark_qwen3_moe_real_model.py
  • reports/benchmark_sampling_NVIDIA_H100_80GB_HBM3.txt
  • reports/perf_report_NVIDIA_H100_80GB_HBM3_20260719_081350.json
  • reports/perf_report_NVIDIA_H100_80GB_HBM3_20260719_081405.json
🚧 Files skipped from review as they are similar to previous changes (3)
  • reports/perf_report_NVIDIA_H100_80GB_HBM3_20260719_081350.json
  • reports/perf_report_NVIDIA_H100_80GB_HBM3_20260719_081405.json
  • reports/benchmark_sampling_NVIDIA_H100_80GB_HBM3.txt

Comment on lines +124 to +134
native_extra, native_ms = measure(
lambda: native_logprob(hidden, lm_head_weight, target)
)
native_str, native_ms_str = f"{native_extra:.2f} GB", f"{native_ms:.2f} ms"
except torch.cuda.OutOfMemoryError:
native_str, native_ms_str = "OOM", "N/A"
torch.cuda.empty_cache()

try:
kernel_extra, kernel_ms = measure(
lambda: linear_logp_op(hidden, lm_head_weight, target)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

📐 Maintainability & Code Quality | 🟠 Major | ⚡ Quick win

Bind loop values in both benchmark callbacks.

Ruff reports B023 because these lambdas capture loop-scoped hidden and target. Bind them as default arguments (or use functools.partial) so the code passes lint and does not depend on measure() remaining synchronous.

Proposed fix
             native_extra, native_ms = measure(
-                lambda: native_logprob(hidden, lm_head_weight, target)
+                lambda hidden=hidden, target=target: native_logprob(
+                    hidden, lm_head_weight, target
+                )
             )
...
             kernel_extra, kernel_ms = measure(
-                lambda: linear_logp_op(hidden, lm_head_weight, target)
+                lambda hidden=hidden, target=target: linear_logp_op(
+                    hidden, lm_head_weight, target
+                )
             )
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
native_extra, native_ms = measure(
lambda: native_logprob(hidden, lm_head_weight, target)
)
native_str, native_ms_str = f"{native_extra:.2f} GB", f"{native_ms:.2f} ms"
except torch.cuda.OutOfMemoryError:
native_str, native_ms_str = "OOM", "N/A"
torch.cuda.empty_cache()
try:
kernel_extra, kernel_ms = measure(
lambda: linear_logp_op(hidden, lm_head_weight, target)
native_extra, native_ms = measure(
lambda hidden=hidden, target=target: native_logprob(
hidden, lm_head_weight, target
)
)
native_str, native_ms_str = f"{native_extra:.2f} GB", f"{native_ms:.2f} ms"
except torch.cuda.OutOfMemoryError:
native_str, native_ms_str = "OOM", "N/A"
torch.cuda.empty_cache()
try:
kernel_extra, kernel_ms = measure(
lambda hidden=hidden, target=target: linear_logp_op(
hidden, lm_head_weight, target
)
🧰 Tools
🪛 Ruff (0.16.0)

[warning] 125-125: Function definition does not bind loop variable hidden

(B023)


[warning] 125-125: Function definition does not bind loop variable target

(B023)


[warning] 134-134: Function definition does not bind loop variable hidden

(B023)


[warning] 134-134: Function definition does not bind loop variable target

(B023)

🤖 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/benchmark_qwen3_moe_real_model.py` around lines 124 - 134, Update
both benchmark callbacks passed to measure in the native and kernel paths to
bind the current hidden and target values at lambda creation time, using default
arguments or functools.partial. Preserve the existing native_logprob and
linear_logp_op calls while ensuring each callback is independent of later
loop-variable reassignment and satisfies Ruff B023.

Source: Linters/SAST tools

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.

2 participants