Skip to content

[WS2][kernels] Deterministic Qwen3 SwiGLU forward (CUDA SM90 + Triton) - #258

Open
bitborne wants to merge 2 commits into
RL-Align:mainfrom
bitborne:codex/qwen3-swiglu-forward-sm90
Open

[WS2][kernels] Deterministic Qwen3 SwiGLU forward (CUDA SM90 + Triton)#258
bitborne wants to merge 2 commits into
RL-Align:mainfrom
bitborne:codex/qwen3-swiglu-forward-sm90

Conversation

@bitborne

@bitborne bitborne commented Aug 2, 2026

Copy link
Copy Markdown
Collaborator

Summary

This PR adds the missing Qwen3 SwiGLU forward activation boundary:

hidden_local = SiLU(gate_local) * up_local

It includes:

  • a BF16 CUDA SM90 implementation
  • a Triton implementation with the same interface
  • PyTorch FP32 reference validation
  • registry dispatch and build integration
  • correctness, invariance, smoke, and benchmark coverage

Integration contract

This implementation follows the fixed layout in #239.

gate_local [M_local, 6144] --\
                                  SiLU(gate) * up --> hidden_local [M_local, 6144]
up_local   [M_local, 6144] --/
  • Gate and Up come from two independent ColumnParallel GEMMs.
  • M_local = B * S / 2 for the fixed CP=2 layout.
  • Inputs and output are BF16 CUDA tensors.
  • Element math is performed in FP32 and rounded on BF16 store.
  • The output is contiguous and remains TP feature-sharded.
  • The operator runs on the caller's current CUDA stream.
  • It does not synchronize or mutate the inputs.
  • It contains no TP/CP collective and no Down GEMM.

The intended integration entry point is:

swiglu = kernel_registry.get_op("swiglu", device=gate_local.device)
hidden_local = swiglu(gate_local, up_local)

Scope

This draft only covers the forward activation operator.

The following remain outside this PR:

This PR references the missing activation TODO in #239 and does not close the issue.

Backend behavior

On SM90, registry dispatch prefers:

CUDA SM90 -> Triton -> PyTorch reference

Each optimized backend is bitwise invariant to unrelated batch, chunk, and padding rows. CUDA and Triton are compared against the independent FP32 oracle using the shared #108 elementwise tolerance.

Cross-backend bitwise equality is not currently required because the CUDA and Triton exponential implementations may differ.

Validation

Passed locally:

  • pre-commit run --from-ref upstream/main --to-ref HEAD
  • Python compileall
  • clang-format --dry-run --Werror csrc/cuda/activation/swiglu_sm90.cu
  • bash -n ci/run_gpu_ci.sh
  • git diff --check upstream/main...HEAD
  • GPG signature verification
  • DCO Signed-off-by

GPU runtime validation was not available locally. Before this PR is marked ready, the CUDA and Triton paths should be exercised on H100 through the repository's needs-gpu-ci workflow and in the composed Gate/Up → SwiGLU → Down integration.

Integration follow-up

The downstream integration should confirm:

  • Gate and Up outputs can be passed through the registry interface without conversion.
  • GEMM, activation, and Down execute with the expected stream ordering.
  • Down consumes the contiguous BF16 activation output directly.
  • The composed test records the actual selected backend and does not silently validate a fallback.

Refs #239

Summary by CodeRabbit

  • New Features
    • Added BF16 SwiGLU activation support with automatic backend selection.
    • Added optimized Triton and Hopper SM90 CUDA implementations.
    • Added input validation, empty-tensor handling, and consistent output behavior.
    • Added configurable intermediate dimensions for operator checks and benchmarks.
  • Documentation
    • Expanded activation operator documentation with usage, requirements, backend behavior, accuracy expectations, and benchmarking guidance.
  • Tests
    • Added coverage for numerical accuracy, input contracts, noncontiguous inputs, padding invariance, and cross-backend consistency.

@coderabbitai

coderabbitai Bot commented Aug 2, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 5cb2efb6-16a4-4bc9-8ebe-2c229a815617

📥 Commits

Reviewing files that changed from the base of the PR and between 50b3430 and 75987a9.

📒 Files selected for processing (5)
  • rl_engine/kernels/registry.py
  • setup.py
  • tests/test_kernel_registry.py
  • tests/test_swiglu.py
  • tests/test_swiglu_forward_backends.py
🚧 Files skipped from review as they are similar to previous changes (1)
  • setup.py

📝 Walkthrough

Walkthrough

Adds BF16 SwiGLU implementations for CUDA SM90 and Triton. It integrates hardware-gated dispatch, build configuration, operator specifications, validation tests, CI smoke checks, benchmarks, and documentation.

Changes

SwiGLU backend integration

Layer / File(s) Summary
SM90 native kernel and build wiring
csrc/cuda/activation/swiglu_sm90.cu, csrc/ops.cpp, setup.py, rl_engine/_C.pyi, envs.py, ci/run_gpu_ci.sh
Adds the BF16 SM90 CUDA kernel, extension binding, conditional compilation, public stub, and activation-specific CI flag forwarding.
Python backend implementations
rl_engine/kernels/ops/cuda/activation/*, rl_engine/kernels/ops/triton/activation/*
Adds validated CUDA SM90 and Triton SwiGLU modules with BF16 forward execution and package exports.
Dispatch and operator specifications
rl_engine/kernels/registry.py, rl_engine/kernels/gtest/operator_specs.py, rl_engine/kernels/gtest/operator_inputs.py, scripts/check_operator.py, tests/test_swiglu.py
Registers SwiGLU backends, applies device-specific backend selection, supports configurable intermediate dimensions, and separates registry tests.
Validation, benchmark, and documentation
tests/test_swiglu_forward_backends.py, tests/test_kernel_registry.py, scripts/ci_smoke.py, benchmarks/benchmark_swiglu.py, docs/operators/activation.md
Adds reference, invariance, contract, cross-backend, dispatch, smoke, and latency validation, plus updated operator documentation.

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

Sequence Diagram(s)

sequenceDiagram
  participant OpRegistry
  participant SwiGLUSM90Op
  participant swiglu_forward_sm90
  participant CUDAKernel
  OpRegistry->>SwiGLUSM90Op: select SM90 backend on Hopper
  SwiGLUSM90Op->>swiglu_forward_sm90: pass validated BF16 inputs
  swiglu_forward_sm90->>CUDAKernel: launch SiLU(gate) × up
  CUDAKernel-->>SwiGLUSM90Op: return BF16 output
Loading

Possibly related PRs

Suggested reviewers: flink-ddd, kjldefeated, inaniloquentee

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 6.45% 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
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely describes the main change: deterministic Qwen3 SwiGLU forward implementations for CUDA SM90 and Triton.
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.

@bitborne bitborne changed the title feat(ws2): add deterministic Qwen3 SwiGLU forward backends [WS2][kernels] Deterministic Qwen3 SwiGLU forward (CUDA SM90 + Triton) Aug 2, 2026
@Flink-ddd
Flink-ddd requested a review from frank-2077 August 3, 2026 06:37
Add BF16 CUDA SM90 and Triton forward implementations for SiLU(gate) * up, including dispatch, validation, CI, docs, and the Qwen3-8B TP-local 6144-wide test contract.

Refs RL-Align#239

Signed-off-by: Schatten <czhengt@qq.com>
@bitborne
bitborne force-pushed the codex/qwen3-swiglu-forward-sm90 branch from cb732a9 to 50b3430 Compare August 7, 2026 06:19
@bitborne
bitborne marked this pull request as ready for review August 7, 2026 06:19

@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: 3

🧹 Nitpick comments (2)
tests/test_swiglu.py (1)

168-169: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Keep a deterministic SwiGLU registry fallback test.

This change removes the only supplied assertion for kernel_registry.get_op("swiglu"). Add a CPU-targeted assertion for NativeSwiGLUOp. This validates the operator key and fallback without requiring CUDA or Triton.

Proposed test
 def test_registry_dispatches_native_silu():
     assert isinstance(kernel_registry.get_op("silu"), NativeSiLUOp)
+
+def test_registry_dispatches_native_swiglu_on_cpu():
+    assert isinstance(
+        kernel_registry.get_op("swiglu", device="cpu"),
+        NativeSwiGLUOp,
+    )
🤖 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 `@tests/test_swiglu.py` around lines 168 - 169, Add a CPU-targeted test
alongside test_registry_dispatches_native_silu that calls
kernel_registry.get_op("swiglu") and asserts the result is a NativeSwiGLUOp,
preserving deterministic coverage of the SwiGLU registry key and native fallback
without CUDA or Triton.
tests/test_swiglu_forward_backends.py (1)

31-33: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Test the Triton fallback on supported non-Hopper CUDA devices.

The registry selects TRITON_SWIGLU for CUDA before the PyTorch backend. This marker skips every Triton test unless the device is SM90.

Gate these tests on CUDA, Triton, and BF16 support instead of Hopper. If Triton is intentionally Hopper-only, add the same hardware gate to registry dispatch.

🤖 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 `@tests/test_swiglu_forward_backends.py` around lines 31 - 33, Update the
requires_triton_sm90 marker to gate tests on CUDA availability, Triton
availability, and BF16 support rather than requiring _IS_SM90, so Triton
fallback tests run on supported non-Hopper devices. Preserve the existing skip
behavior and reason text unless the registry dispatch is instead changed to
restrict TRITON_SWIGLU to Hopper hardware.
🤖 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 `@ci/run_gpu_ci.sh`:
- Line 141: Update the KERNEL_ALIGN_ACTIVATION_SM90 export in ci/run_gpu_ci.sh
to preserve the variable’s raw value without adding literal single-quote
characters, so empty and numeric values remain valid for envs.env_flag and
setup.py.

In `@rl_engine/kernels/registry.py`:
- Around line 364-368: Make CUDA backend selection in get_op device-aware
instead of relying on the hardware adjustment performed by
_adjust_priority_for_hardware() at registry construction. Before caching or
returning a backend for device "cuda:N", validate SM90 eligibility against that
requested device and exclude CUDA_SWIGLU_SM90 on non-Hopper devices. Update the
CUDA backend cache key or structure so eligibility is not shared across
incompatible devices, preserving fallback to another SwiGLU backend.

In `@setup.py`:
- Around line 184-189: Update the activation SM90 setup logic around
enable_activation_sm90 so that enabling the backend validates
csrc/cuda/activation/swiglu_sm90.cu exists and raises a build error when it is
missing; only append the source and corresponding flags when validation
succeeds.

---

Nitpick comments:
In `@tests/test_swiglu_forward_backends.py`:
- Around line 31-33: Update the requires_triton_sm90 marker to gate tests on
CUDA availability, Triton availability, and BF16 support rather than requiring
_IS_SM90, so Triton fallback tests run on supported non-Hopper devices. Preserve
the existing skip behavior and reason text unless the registry dispatch is
instead changed to restrict TRITON_SWIGLU to Hopper hardware.

In `@tests/test_swiglu.py`:
- Around line 168-169: Add a CPU-targeted test alongside
test_registry_dispatches_native_silu that calls kernel_registry.get_op("swiglu")
and asserts the result is a NativeSwiGLUOp, preserving deterministic coverage of
the SwiGLU registry key and native fallback without CUDA or Triton.
🪄 Autofix

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: b3da3fbe-8b78-42ae-858f-25c7a3197d22

📥 Commits

Reviewing files that changed from the base of the PR and between 2e08ef6 and 50b3430.

📒 Files selected for processing (19)
  • benchmarks/benchmark_swiglu.py
  • ci/run_gpu_ci.sh
  • csrc/cuda/activation/swiglu_sm90.cu
  • csrc/ops.cpp
  • docs/operators/activation.md
  • envs.py
  • rl_engine/_C.pyi
  • rl_engine/kernels/gtest/operator_inputs.py
  • rl_engine/kernels/gtest/operator_specs.py
  • rl_engine/kernels/ops/cuda/activation/__init__.py
  • rl_engine/kernels/ops/cuda/activation/swiglu.py
  • rl_engine/kernels/ops/triton/activation/__init__.py
  • rl_engine/kernels/ops/triton/activation/swiglu.py
  • rl_engine/kernels/registry.py
  • scripts/check_operator.py
  • scripts/ci_smoke.py
  • setup.py
  • tests/test_swiglu.py
  • tests/test_swiglu_forward_backends.py

Comment thread ci/run_gpu_ci.sh
export FORCE_CUDA=1
export MAX_JOBS=8
export KERNEL_ALIGN_FORCE_SM90="'"${KERNEL_ALIGN_FORCE_SM90}"'"
export KERNEL_ALIGN_ACTIVATION_SM90="'"${KERNEL_ALIGN_ACTIVATION_SM90}"'"

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

Remove literal quote characters from the export value.

This expression exports '' for the empty default and '1' when the value is 1. envs.env_flag rejects both values, so setup.py raises ValueError and blocks the GPU CI build.

Proposed fix
-export KERNEL_ALIGN_ACTIVATION_SM90="'"${KERNEL_ALIGN_ACTIVATION_SM90}"'"
+export KERNEL_ALIGN_ACTIVATION_SM90="${KERNEL_ALIGN_ACTIVATION_SM90}"
📝 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
export KERNEL_ALIGN_ACTIVATION_SM90="'"${KERNEL_ALIGN_ACTIVATION_SM90}"'"
export KERNEL_ALIGN_ACTIVATION_SM90="${KERNEL_ALIGN_ACTIVATION_SM90}"
🧰 Tools
🪛 Shellcheck (0.11.0)

[info] 141-159: Expressions don't expand in single quotes, use double quotes for that.

(SC2016)

🤖 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 `@ci/run_gpu_ci.sh` at line 141, Update the KERNEL_ALIGN_ACTIVATION_SM90 export
in ci/run_gpu_ci.sh to preserve the variable’s raw value without adding literal
single-quote characters, so empty and numeric values remain valid for
envs.env_flag and setup.py.

Source: Linters/SAST tools

Comment thread rl_engine/kernels/registry.py Outdated
Comment thread setup.py
Signed-off-by: Schatten <czhengt@qq.com>
@Flink-ddd

Copy link
Copy Markdown
Collaborator

please resolve the code conflicts, Thanks.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants