Repository navigation
Conversation
Signed-off-by: Neil Kale <263453039+kalectory@users.noreply.github.com>
Greptile SummaryThis PR restores FlashAttention 2 eligibility for padded Q/V head dimensions up to 256 on sm103 by removing a stale architecture allowlist.
Confidence Score: 5/5The PR appears safe to merge with no concrete blocking or independently actionable non-blocking issues identified. The change narrowly removes an obsolete architecture filter while retaining FlashAttention 2’s padded head-dimension bounds, and the reviewed selection and dispatch paths reveal no established regression. Important Files Changed
Reviews (1): Last reviewed commit: "Restore FlashAttention 2 head dim suppor..." | Re-trigger Greptile |
|
/te-ci L0 |
applying NVIDIA/TransformerEngine#3360 to TE 2.16 <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Medium Risk** > Changes attention backend selection at Megatron init via `exec` on TE internals; mitigated by SM guards, literal 2.16.0 source matching, and idempotent no-ops on unaffected GPUs, but wrong TE versions or arch-specific FA2 issues could still affect training memory or numerics. > > **Overview** > Backports **NVIDIA/TransformerEngine#3360** for the pinned **transformer-engine 2.16.0** so Megatron training can select **FlashAttention 2** for **head_dim 256** (e.g. Gemma 2/3) on GPUs outside TE’s SM allowlist (notably **sm103** B300/GB300, also sm86/sm89). > > A runtime patch **recompiles and rebinds** TE’s `get_attention_backend` to drop the erroneous `head_dim > 192` + compute-capability gate, keeping only FA2’s real limits (`<= 256`, `% 8 == 0`). It **no-ops** on sm80/90/100/120, when TE isn’t importable, or when TE source no longer matches 2.16.0, and clears TE’s memoized `_attention_backends` after apply. > > **Megatron only:** `patch_fa2_head_dim_allowlist()` runs in `make_megatron_module()` before `provide_distributed_model()` (policy and ref workers). A **verify script** and README document repro and numerics vs unfused attention. > > Remove this patch when the TE pin includes upstream #3360. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit 1d9d8c9. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> <!-- /CURSOR_SUMMARY --> --------- Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
Moves the TE pin from 2.16.0 to 2.19.0 across the `megatron` extra and `override-dependencies`. Packaging: * `transformer-engine` and `transformer-engine-cu13` move off the `astral-cu130` index, which stops at 2.16.0, onto PyPI -- which publishes both prebuilt at 2.19.0 (the meta as `py3-none-any`, carrying the whole pure-Python `transformer_engine/pytorch/` tree; the core as manylinux_2_28 wheels for x86_64 and aarch64). The core pin loses its `+cu.13.0` local segment, which was an Astral-index artifact; TE-torch's own metadata asks for a bare `transformer_engine_cu13==2.19.0`, so the two still agree without an override. * `transformer-engine-torch` has no prebuilt wheel for torch 2.13 anywhere (PyPI is sdist-only), so it keeps pointing at self-built wheels, now under the `cu13torch2.13-te2.19` tag on NovaSky-AI/skyrl-wheels: 3 interpreters (cp312/313/314) x 2 arches, GLIBC_2.34 floor, same as the existing release. The FA2 head_dim backport is RETARGETED, not deleted: TE's `head_dim > 192` compute-capability allowlist is still present in 2.19.0. NVIDIA/TransformerEngine#3360, which removes it, is open and unmerged. What changed is the spelling: 2.16.x expresses the gate against `head_dim_qk`, and 2.17.0 onward against `fa2_padded_head_dim = max(head_dim_qk, head_dim_v)`. The clause is otherwise character-identical. `patch_fa2_head_dim.py` matched only the 2.16.0 text and was written to no-op on anything else, so under a naive bump it would have silently stopped applying and quietly dropped Gemma-style head_dim=256 to unfused attention on every arch outside sm80/90/100/120. It now matches both spellings, and when it matches neither it reports whether an allowlist is still present in the source rather than implying it was fixed upstream. Confirmed against the published meta wheels: the gate is present in 2.16.0, 2.16.1, 2.17.0, 2.17.1, 2.18.0 and 2.19.0 -- as `head_dim_qk` in the 2.16 line and `fa2_padded_head_dim` from 2.17.0 on. Verified on an installed 2.19.0 that the retargeted patch fires: gate present before, absent after, idempotent. Also refreshes the stale TE-gate comments in `pyproject.toml`, all re-read from 2.19.0's source: the flash-attn bound went `max_version = 2.8.3` to `2.8.4` exclusive (so the `flash-attn==2.8.3` pin is held by the combined FA2+FA4 wheel requirement, not by TE), FA4 is now allowed under context parallelism for cp_comm_type p2p/all_gather/a2a, and TE's own FA4 arch gate now excludes `< sm90`, so sm86/sm87/sm89 no longer need SKYRL_DISABLE_FA4. Verified on torch 2.13.0+cu130 / sm89: `te.Linear` and `te.TransformerLayer` fwd+bwd pass, megatron-core at the pinned rev imports `megatron.core.extensions.transformer_engine` cleanly, and both fake-INT4 QAT tripwires still hold (`TEGroupedLinear._get_weight_tensors` exists and `GroupedLinear.forward` still calls it). Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Bumps the `transformer-engine` pin from 2.16.0 to 2.19.0. ## Packaging - `transformer-engine` and `transformer-engine-cu13` move off the `astral-cu130` index (it stops at 2.16.0) onto PyPI, which publishes both prebuilt at 2.19.0: the meta as `py3-none-any` (it carries the whole pure-Python `transformer_engine/pytorch/` tree), the core as `manylinux_2_28` wheels for x86_64 and aarch64. - The core pin loses its `+cu.13.0` local segment, which was an Astral-index artifact. `transformer-engine-torch`'s own metadata asks for a bare `transformer_engine_cu13==2.19.0`, so the two still agree without an override. - `transformer-engine-torch` has no prebuilt wheel for torch 2.13 anywhere (PyPI only has an sdist). The new wheels are published at **[`cu13torch2.13-te2.19`](https://github.com/NovaSky-AI/skyrl-wheels/releases/tag/cu13torch2.13-te2.19)** on `NovaSky-AI/skyrl-wheels`: cp312/313/314 × x86_64/aarch64, GLIBC_2.34 floor (same as `cu13torch2.13`). Both arches were built by one script using pip-wheel CUDA 13.0.88, with no system CUDA. aarch64 was built on an Anyscale `m7g.12xlarge` job. - `uv.lock` is regenerated. Exactly three packages changed: `transformer-engine` 2.16.0 → 2.19.0, `transformer-engine-cu13` 2.16.0+cu.13.0 → 2.19.0, `transformer-engine-torch` 2.16.0 → 2.19.0. No packages were added or removed. TE 2.19's new `nvidia-cudnn-frontend>=1.28.0` requirement is already locked at 1.30.0. ## FA2 `head_dim` backport: retargeted, not deleted TE's `head_dim > 192` compute-capability allowlist is **still present in 2.19.0**. [NVIDIA/TransformerEngine#3360](NVIDIA/TransformerEngine#3360), which removes it, is still open. What changed is the spelling: | release | gate | |---|---| | 2.16.0, 2.16.1 | `head_dim_qk > 192 and device_compute_capability not in (...)` | | 2.17.0 – 2.19.0 | `fa2_padded_head_dim > 192 and device_compute_capability not in (...)` | (#2836 removed the `head_dim_qk` form, and it came back as `fa2_padded_head_dim` before v2.17 shipped.) `patch_fa2_head_dim.py` only matched the 2.16.0 text and was written to quietly do nothing on anything else. Under a plain version bump it would have stopped applying without any error, sending `head_dim=256` (Gemma 2/3) to unfused attention on every arch outside sm80/90/100/120. It now matches both spellings. If it matches neither, it logs a warning that says whether an allowlist is still in the source, instead of implying upstream fixed it. Verified on an installed 2.19.0: gate present before, absent after, and calling the patch again is a no-op. `patches/te/README.md` now records the history and how to check for removal at the source level. ## Other comment refreshes (re-read from 2.19.0 source) - The flash-attn bound is now `version < max_version = 2.8.4` (it was `2.8.3`). The `flash-attn==2.8.3` pin is now held by the combined FA2+FA4 wheel requirement, not by TE. - FA4 is now allowed under context parallelism for `cp_comm_type` p2p/all_gather/a2a. - TE's own FA4 arch gate now excludes `< sm90`, so sm86/sm87/sm89 no longer need `SKYRL_DISABLE_FA4=1`. ## NVRTC regression: TE now pinned to the pip NVRTC TE 2.19 fails MXFP8 RMSNorm on any machine whose `/usr/local/cuda` is CUDA 12.x: `NVRTC_ERROR_COMPILATION` in `rmsnorm_fwd_kernel.cu`, with syntax errors in `cuda_fp8.hpp`. TE's loader prefers the system NVRTC (`NVRTC_HOME` / `CUDA_HOME` / `/usr/local/cuda`) over the pip `nvidia-cuda-nvrtc` wheel. In 2.19 it also sets `NVTE_CUDA_INCLUDE_DIR` to the pip `nvidia/cu13` headers, so NVRTC 12.9 ends up compiling against CUDA 13 headers. **This is a regression from 2.16.** 2.16 uses the same loader order but leaves the include dir unset, so system NVRTC and system headers still match. The same standalone repro (a `te.LayerNormLinear` RMSNorm forward under MXFP8) passes on 2.16.0 and fails on 2.19.0. `patches/te/pin_nvrtc.py` sets `NVRTC_HOME` to the pip `nvidia/cu{major}` from `skyrl/backends/skyrl_train/__init__.py`, which runs before every SkyRL TE/Megatron import. It takes 0.3 ms and doesn't import torch. It does nothing when the user sets `NVTE_CUDA_INCLUDE_DIR`, when `NVRTC_HOME` already holds a `libnvrtc`, or when TE is already imported. A tripwire test fails once TE starts preferring its pip NVRTC, which is when the patch can be deleted. ## Also in this PR - **Merged upstream `main`.** The old base was missing `patches/vllm/patch_model_runner_registry.py` (restored by #2363) while `weight_receivers.py` imported it. Every MXFP8 weight sync failed with `ModuleNotFoundError`. - **vLLM 0.30 FP8 KV scale hooks** (independent of TE; fixes `qwen3.5-0.8b-dense_mxfp8_fp8kv`, which generated NaN on `main` too). Both post-boot safety nets for the serialized-FP8 KV/attention scales were silently disabled: - **Runner registry:** it only wrapped the V1 `GPUModelRunner.load_model`. vLLM 0.30 defaults to Model Runner V2, so `current_model_runner()` returned `None` and the post-sync normalization returned early. It now wraps both runners. - **Post-wake patch:** it targeted `GPUModelRunner.post_kv_cache_wake_up`, which 0.30 removed. It now wraps `Worker.wake_up`. `skyrl_wake_for_weight_sync` wakes the allocator directly, so it calls the same helper. - vLLM-marked tests pin both hooks to the installed vLLM, so a future rename fails loudly. - **GPU test conftest:** sets `RAY_worker_register_timeout_seconds=600` for raylets the tests start; it does nothing when attaching to an existing cluster. Each worker boots through `uv run --isolated`, and the 35B row's 8 workers starting at once took longer than Ray's 60 s default, so the actor became unschedulable. - **`.agents/docs/dependency_bumps.md`:** the required test matrix for TE bumps, which is all Megatron GPU CI labels plus the manual B200 MXFP8 rows. ## Verification On torch 2.13.0+cu130 / L4 (sm89), x86_64 cp312: - `te.Linear` and `te.TransformerLayer` fwd+bwd pass with finite outputs. - megatron-core at the pinned rev `d476c21b` imports `megatron.core.extensions.transformer_engine`, `transformer_engine_spec_provider`, `transformer.attention` and `gpt_layer_specs` cleanly. - Both fake-INT4 QAT tripwires still hold: `TEGroupedLinear._get_weight_tensors` exists and `GroupedLinear.forward` still calls it. - The MXFP8 surfaces used by `weight_sync/fp8/quantize.py` are unchanged (`MXFP8Quantizer(fp8_dtype=, rowwise=, columnwise=)`, `tex.DType`). For all six wheels, a script checked the tag, the `.so` architecture, the layout, the glibc floor and the `cu13==2.19.0` pin. `pre-commit run --all-files` passes. On 8x B200 (sm100), `pytest -m b200 -k mxfp8 tests/backends/skyrl_train/gpu/gpu_ci/megatron/test_megatron_models.py`: | row | before | after | |---|---|---| | `qwen3.5-0.8b-dense_mxfp8` | ❌ NVRTC compile error | ✅ | | `qwen3.5-0.8b-dense_mxfp8_fp8kv` | ❌ NaN logprobs (also on `main`) | ✅ | | `qwen3.5-35b-a3b_b200_tp1_ep8_mxfp8` | ❌ Ray workers fail to register (also on `main`) | ✅ | - All 3 rows pass with an explicit `NVRTC_HOME`, before the pin patch and the wake-hook fix landed. - Both 0.8B rows pass on the pushed code with `NVRTC_HOME` unset, so they rely on the pin patch alone. The log contains no `Run-time NVRTC version: 12` line. - The 35B row wasn't rerun after those last two changes. The 0.8B rows exercise both. New CPU tests (`tests/backends/skyrl_train/patches/{te,vllm}/`, `test_vllm_compat_fp8_kv_scales.py`) pass under both the `skyrl-train` and `fsdp`/`megatron` extras. **Not yet run:** the full CPU pytest suites, the labeled GPU CI (`run_megatron_gpu_ci`, `run_megatron_gpu_ci_models`, `run_h100_gpu_ci`), and any forward pass on aarch64 (the build host was CPU-only). 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Signed-off-by: Eric Tang <erictang000@gmail.com> Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
@kalectory @cyanguwa This regression is still on One thing to consider before dropping the clause entirely. flash-attn's hdim256 backward picks its kernel by opt-in shared memory per block ( A narrower fix is to add
The three sm103 cases above 192 fail on current |
|
@0z5a, thanks for the comment. Looks like the author closed the PR himself, cc @kalectory. Overall, I still think this change is necessary, at least for sm103. @0z5a, could you please submit a PR for the narrower fix you mentioned? I think it's safer to just enable sm103 for now and leave sm86/89 out. Thanks! |
|
@cyanguwa Thanks! The narrower fix is up as #3714. It adds only The |
Description
Restore the FlashAttention 2 head-dimension behavior from #2836. #2629 preserved the new padded Q/V head-dimension handling but accidentally reintroduced the exact compute-capability allowlist that #2836 removed.
On B300 (sm103), that allowlist rejects a padded head dimension of 256 and falls back to quadratic unfused attention.
Type of change
Changes
Testing
Status quo
TP=4) and four to rollout inference. Qwen3.6-27B used BF16 THD attention, head dim 256, Transformer Engine 2.11.0, and FlashAttention 2.8.3.sm103) and silently selectedUnfusedDotProductAttentioninstead.torch.OutOfMemoryErrorduring forward.After the fix
forward_backwardtook 413.2s, the Adam optimizer step took 9.6s, and grad norm was finite at 1776.48. This validates FlashAttention 2 and 64k context on the four-B300 trainer configuration.Checklist: