Skip to content

Support explicit DSA top-k backends and tie policies - #108

Merged
Zhichenzzz merged 8 commits into
radixark:miles-mainfrom
zianglih:codex/dsa-topk-backend
Oct 2, 2026
Merged

Zhichenzzz merged 8 commits into
radixark:miles-mainfrom
zianglih:codex/dsa-topk-backend

Conversation

@zianglih

@zianglih zianglih commented Sep 29, 2026 •

Copy link
Copy Markdown
  • I, the PR author, have personally reviewed every line of this PR.

What does this PR do?

@HumansAnd

Configure ordinary DSA top-k independently of score/attention kernels.

  • API: dsa_indexer_topk_backend=None|torch|flashinfer, dsa_indexer_topk_deterministic=False, dsa_indexer_topk_tie_break=0|1|2 (unset/small/large), with CLI flags. None retains kernel selection; reject CSA/V4 and non-FlashInfer tie options.
  • Selection: sorted Torch; FlashInfer top_k(sorted=False, deterministic=..., tie_break=..., dsa_graph_safe=True). Preserve scores/order; int32 indices; -inf→-1. Ties use original columns without score bias.
  • cuDNN: reuse BSHD, packed-CP/THD and chunked CP1 scores with absolute offsets and existing masks. No extra mask pass. No-aux fusion and index-sharing split attention use a private sorted/compacted index copy.
  • Boundary: fused selection requires cuDNN/ReLU/zero aux loss; unsupported masks/coordinates, including TP-local multi-packed CP, fail. dsa_kernel_backend=none or attention_backend=unfused enables reference training with selector-preserving backward.
  • Overhead: cached B200/B300 empty-row backward avoids compaction/sync; other architectures compact. Only default selection keeps its nonempty proof. No public row flag, version/API probes, wrapper fallback or SGLang dependency.
  • Precision: native head weights are BF16; Miles outputs FP32 from BF16 operands. cuDNN Frontend #1311 adds FP32 forward inputs; projection wiring and FP32 auxiliary recompute/backward remain separate.

Issue tracking

Validation

Current CPU validation

8c1a1300c01577c4bb4fddcfaf70ba0cd28a83ee: merge scorer dispatch, remove gradient-tuple slicing and require selector fields directly; update fixtures, retain test cases and numerical paths.

macOS/Torch 2.14.0 CPU doubles; overlapping counts. Python/diff/changed-file Black pass; no new Ruff findings, baseline style issues retained. No GPU/distributed/perf rerun; historical commits remain below.

.venv-tests/bin/python native-dsa-ownership-audit-001/check_optional_autograd.py
.venv-tests/bin/python native-dsa-ownership-audit-001/check_megatron_cleanup.py
.venv-tests/bin/python native-dsa-ownership-audit-001/check_megatron_hook_fixtures_cpu.py
.venv-tests/bin/python test-value-review-001/run_megatron_strict_cpu.py megatron
.venv-tests/bin/python test-value-review-001/check_megatron_attention_cpu.py

Complete CPU output for this checkout:

PASS torch 2.14.0: optional argument explicit=False; fixed trailing None accepted
PASS torch 2.14.0: optional argument explicit=True; fixed trailing None accepted
PASS megatron: 48 before/after CPU chunk cases; identical selector results, scores, FE calls/offsets and internal-topk counts
PASS megatron: existing split-loss backward with original mock signature
PASS megatron: test_dsa_kernel_hooks_return_none_without_backend_function
PASS megatron: test_dsa_kernel_hooks_log_declined_backend
PASS megatron: test_dsa_kernel_hooks_dispatch_to_backend
W0930 15:15:53.803000 47077 torch/distributed/elastic/multiprocessing/redirects.py:35] NOTE: Redirects are currently not supported in MacOs.
/Users/ziangli/playground/projects/miles-dsa-backend-audit/megatron/megatron/core/transformer/transformer_config.py:3300: UserWarning: full scope is deprecated. Use empty cuda_graph_modules to capture the whole layer.
  warnings.warn(
Owned config source: /Users/ziangli/playground/projects/miles-dsa-backend-audit/megatron/megatron/core/transformer/transformer_config.py
PASS test_explicit_fused_topk_config_rejects_unsupported_training ({'dsa_indexer_loss_coeff': 0.1}, 'auxiliary loss')
PASS test_explicit_fused_topk_config_rejects_unsupported_training ({'dsa_kernel_backend': 'tilelang'}, 'requires dsa_kernel_backend')
PASS test_explicit_fused_topk_config_rejects_unsupported_training ({'dsa_indexer_scoring_relu': False}, 'requires dsa_kernel_backend')
PASS test_explicit_fused_topk_config_rejects_unsupported_training ({'dsa_kernel_backend': 'none', 'dsa_indexer_loss_coeff': 0.1}, None)
PASS test_explicit_fused_topk_config_rejects_unsupported_training ({'attention_backend': <AttnBackend.unfused: 3>, 'dsa_indexer_loss_coeff': 0.1}, None)
PASS test_multi_packed_cp_local_tp_slice_rejects_unsupported_layout
PASS test_reference_indexer_loss_retains_external_indices_and_backward (False,)
PASS test_reference_indexer_loss_retains_external_indices_and_backward (True,)
PASS test_skip_layer_reuses_external_selection_without_recomputing ('plain',)
PASS test_skip_layer_reuses_external_selection_without_recomputing ('padded',)
PASS test_torch_selector_keeps_torch_topk_ties_and_masks
11 selected CPU cases passed. No GPU/distributed execution.
PASS CPU scorer probe: CP1 forced chunks {'packed': False, 'nonzero': False, 'offsets': [None, [17], [34], [51], [68], [85], [102], [119]]}
PASS CPU scorer probe: CP1 forced chunks {'packed': False, 'nonzero': True, 'offsets': [None, [17], [34], [51], [68], [85], [102], [119]]}
PASS CPU scorer probe: CP1 forced chunks {'packed': True, 'nonzero': False, 'offsets': [None, [17], [34], [51], [68], [85], [102], [119]]}
PASS CPU scorer probe: CP1 forced chunks {'packed': True, 'nonzero': True, 'offsets': [None, [17], [34], [51], [68], [85], [102], [119]]}
15 total CPU cases/probes passed. GPU cuDNN execution not validated.
CPU-only isolated repository test bodies; Torch 2.14.0; CUDA=False
PASS megatron: split_attention_backward[(9, 0),mixed]
PASS megatron: split_attention_backward[(9, 0),empty]
PASS megatron: split_attention_backward[(10, 0),nonempty]
PASS megatron: split_attention_backward[(10, 0),mixed]
PASS megatron: split_attention_backward[(10, 3),empty]
PASS megatron: split_attention_backward[(10, 1),mixed]
PASS megatron: test_cudnn_full_fusion_accepts_varlen_when_indexer_loss_disabled
PASS megatron: test_cudnn_full_fusion_skips_varlen_dense_indexer_loss_under_no_grad
PASS megatron: test_cudnn_full_fusion_accepts_local_varlen_for_sparse_indexer_loss
PASS megatron: test_cudnn_full_fusion_strips_flagged_plain_causal_varlen
PASS megatron: test_cudnn_sparse_attention_uses_supplied_topk_length
PASS megatron: ignored_topk_slots[full_fusion]
PASS megatron: ignored_topk_slots[split_attention]
PASS megatron: full_fusion_nonempty_proof[external_topk=False]
PASS megatron: full_fusion_nonempty_proof[external_topk=True]
PASS megatron: Torch selector preserves native order and masked entries
PASS megatron: FlashInfer CPU API double preserves 3D shape/order/masks/options
megatron: 17 CPU cases passed. CUDA numerical test was not executed.

Historical GPU validation at 524ff28f

  • Environment: C2 node with 8 NVIDIA B300 GPUs; each suite below uses one GPU, sequentially. Container radixark/miles:dev-202609291651, digest sha256:1f5e2f9ea617010024d814fba9f48dba12fd90447a2a042c26d287ee422db138; driver 590.48.01; CUDA 13.0.88; torch 2.13.0+cu130; TE 2.17.0; cuDNN frontend 1.28.0; FlashInfer 0.6.18.
  • Setup: Checkout the pinned GPU revision at /root/dsa-native-glm52/megatron in that image; use installed DSA/FlashInfer and TE checkout. Tests set policies directly, without SGLang environment variables.
  • Compatibility: Recorded GPU tests used frontend1.28. Current ordinary DSA trusts the supplied frontend directly; source audits do not replace GPU validation.
  • Commands:
cd /root/dsa-native-glm52/megatron
export CUDA_VISIBLE_DEVICES=1
export PYTHONPATH="$PWD:/root/TransformerEngine"

/opt/sglang/bin/python -m torch.distributed.run \
  --nproc-per-node=1 --master-port=29519 -m pytest -q \
  tests/unit_tests/transformer/experimental_attention_variant/test_dsa_topk_backend.py \
  -m 'not flaky and not flaky_in_dev'

/opt/sglang/bin/python -m torch.distributed.run \
  --nproc-per-node=1 --master-port=29519 -m pytest -q \
  tests/unit_tests/transformer/experimental_attention_variant/test_dsa_native_parity.py \
  -k 'indexer_topk or split_topk_hook or sparse_attention_uses_supplied_topk_length' \
  -m 'not flaky and not flaky_in_dev'
  • Historical raw results:
52 passed, 114 warnings in 8.34s
21 passed, 69 deselected, 24 warnings in 0.94s
  • Historical selection/score coverage: FlashInfer deterministic on/off and unset/small/large ties; masked rows; Torch/int32/-1; real cuDNN BSHD/THD tied/nonzero unequal-weight BF16 scores against FP32; fused single/multi-packed CP and chunk offsets.
  • Historical dispatch/backward coverage: CLI, skip-layer reuse, unsupported key positions, old-API/TP-slice fallback, no-aux dispatch, dense/sparse loss gradients, nonempty/empty-row backward and default masks/top-k/lengths. These describe the pinned historical revision.
  • Validation limits: Local CP tensors, not distributed/exhaustive model validation. Historical fallbacks are superseded. Reference positive-loss performance is untested. Flaky cases excluded; unused /opt/data download failures retained in successful raw output.
Complete final focused GPU output (52 cases)
Flax classes are deprecated and will be removed in Diffusers v1.0.0. We recommend migrating to PyTorch classes or pinning your version of Diffusers.
Flax classes are deprecated and will be removed in Diffusers v1.0.0. We recommend migrating to PyTorch classes or pinning your version of Diffusers.
LANG_RL Log directory: None
Test data not found at /opt/data. Downloading...
ERROR:tests.test_utils.python_scripts.download_unit_tests_dataset:  Error downloading/extracting datasets.zip: [Errno 2] No such file or directory: '/opt/data/datasets.zip'
ERROR:tests.test_utils.python_scripts.download_unit_tests_dataset:  Error downloading/extracting tokenizers.zip: [Errno 2] No such file or directory: '/opt/data/tokenizers.zip'
Test data downloaded successfully.
....................................................
=============================== warnings summary ===============================
../../../opt/sglang/lib/python3.12/site-packages/torch/jit/_script.py:1488
../../../opt/sglang/lib/python3.12/site-packages/torch/jit/_script.py:1488
../../../opt/sglang/lib/python3.12/site-packages/torch/jit/_script.py:1488
  /opt/sglang/lib/python3.12/site-packages/torch/jit/_script.py:1488: DeprecationWarning: `torch.jit.script` is deprecated. Please switch to `torch.compile` or `torch.export`.
    warnings.warn(

../../../opt/sglang/lib/python3.12/site-packages/transformer_engine/__init__.py:103
  /opt/sglang/lib/python3.12/site-packages/transformer_engine/__init__.py:103: RuntimeWarning: Detected a Jax installation but could not find the shared object file for the Transformer Engine Jax extension library. If this is not intentional, please reinstall Transformer Engine with `pip install transformer_engine[jax]` or build from source with `NVTE_FRAMEWORK=jax`.
    warnings.warn(

megatron/core/dist_checkpointing/strategies/torch.py:69
  /root/dsa-native-glm52/megatron/megatron/core/dist_checkpointing/strategies/torch.py:69: DeprecationWarning: transformer_engine.pytorch.float8_tensor is deprecated and will be removed in a future release. Float8Tensor should be imported directly through `from transformer_engine.pytorch import Float8Tensor`
    from transformer_engine.pytorch.float8_tensor import Float8Tensor

../../../opt/sglang/lib/python3.12/site-packages/torch/jit/_script.py:365: 14 warnings
  /opt/sglang/lib/python3.12/site-packages/torch/jit/_script.py:365: DeprecationWarning: `torch.jit.script_method` is deprecated. Please switch to `torch.compile` or `torch.export`.
    warnings.warn(

megatron/core/tensor_parallel/random.py:83
  /root/dsa-native-glm52/megatron/megatron/core/tensor_parallel/random.py:83: DeprecationWarning: Using deprecated internal API from Transformer Engine. transformer_engine.pytorch.fp8 will be removed in a future release.
    from transformer_engine.pytorch.fp8 import FP8GlobalStateManager, fp8_autocast

megatron/core/inference/contexts/__init__.py:9
  /root/dsa-native-glm52/megatron/megatron/core/inference/contexts/__init__.py:9: DeprecationWarning: The following imports from `dynamic_context.py` will be removed in this file in `megatron-core` 0.14. The imports here result in a cyclic import issue that causes rotary embeddings to import from Apex rather than Transformer Engine.
    warnings.warn(

megatron/rl/inference/inference_interface.py:15
  /root/dsa-native-glm52/megatron/megatron/rl/inference/inference_interface.py:15: PydanticDeprecatedSince20: Support for class-based `config` is deprecated, use ConfigDict instead. Deprecated in Pydantic V2.0 to be removed in V3.0. See Pydantic V2 Migration Guide at https://errors.pydantic.dev/2.13/migration/
    class InferenceInterface(BaseModel):

megatron/rl/__init__.py:31
megatron/rl/__init__.py:31
  /root/dsa-native-glm52/megatron/megatron/rl/__init__.py:31: PydanticDeprecatedSince20: The `__fields__` attribute is deprecated, use the `model_fields` class property instead. Deprecated in Pydantic V2.0 to be removed in V3.0. See Pydantic V2 Migration Guide at https://errors.pydantic.dev/2.13/migration/
    cls.Library.type_names[register_type.__fields__['type_name'].default] = register_type

tests/unit_tests/transformer/experimental_attention_variant/test_dsa_topk_backend.py::test_cudnn_score_hook_uses_external_tie_policy[tied-bshd-1]
tests/unit_tests/transformer/experimental_attention_variant/test_dsa_topk_backend.py::test_external_selection_preserves_fused_packed_cp_scores[tied-1-1]
tests/unit_tests/transformer/experimental_attention_variant/test_dsa_topk_backend.py::test_external_selection_preserves_fused_packed_cp_scores[tied-1-2]
  /opt/sglang/lib/python3.12/site-packages/cudnn/deepseek_sparse_attention/score_recompute/dense_score_recompute_sm100.py:327: DeprecationWarning: Migrated to examples/CuTeDSL/helpers/dynamic_persistent_tile_scheduler.py (BSD-3). The wheel copy will be removed in a future release.
    tile_sched_params = utils.ClcDynamicPersistentTileSchedulerParams(

tests/unit_tests/transformer/experimental_attention_variant/test_dsa_topk_backend.py::test_cudnn_score_hook_uses_external_tie_policy[tied-bshd-1]
tests/unit_tests/transformer/experimental_attention_variant/test_dsa_topk_backend.py::test_external_selection_preserves_fused_packed_cp_scores[tied-1-1]
tests/unit_tests/transformer/experimental_attention_variant/test_dsa_topk_backend.py::test_external_selection_preserves_fused_packed_cp_scores[tied-1-2]
  /opt/sglang/lib/python3.12/site-packages/nvidia_cutlass_dsl/dsl_packages/cutlass/utils/dynamic_persistent_tile_scheduler.py:209: DeprecationWarning: Migrated to examples/CuTeDSL/helpers/dynamic_persistent_tile_scheduler.py (BSD-3). The wheel copy will be removed in a future release.
    new_params = ClcDynamicPersistentTileSchedulerParams(

tests/unit_tests/transformer/experimental_attention_variant/test_dsa_topk_backend.py::test_cudnn_score_hook_uses_external_tie_policy[tied-bshd-1]
tests/unit_tests/transformer/experimental_attention_variant/test_dsa_topk_backend.py::test_external_selection_preserves_fused_packed_cp_scores[tied-1-1]
tests/unit_tests/transformer/experimental_attention_variant/test_dsa_topk_backend.py::test_external_selection_preserves_fused_packed_cp_scores[tied-1-2]
  /opt/sglang/lib/python3.12/site-packages/nvidia_cutlass_dsl/dsl_packages/cutlass/utils/dynamic_persistent_tile_scheduler.py:392: DeprecationWarning: Migrated to examples/CuTeDSL/helpers/dynamic_persistent_tile_scheduler.py (BSD-3). The wheel copy will be removed in a future release.
    return ClcDynamicPersistentTileScheduler(

tests/unit_tests/transformer/experimental_attention_variant/test_dsa_topk_backend.py: 81 warnings
  /opt/sglang/lib/python3.12/site-packages/nvidia_cutlass_dsl/dsl_packages/cutlass/utils/dynamic_persistent_tile_scheduler.py:341: DeprecationWarning: Migrated to examples/CuTeDSL/helpers/dynamic_persistent_tile_scheduler.py (BSD-3). The wheel copy will be removed in a future release.
    return ClcDynamicPersistentTileScheduler(

-- Docs: https://docs.pytest.org/en/stable/how-to/capture-warnings.html
==================================== PASSES ====================================
_________________ test_external_topk_cli_fields_are_generated __________________
------------------------------ Captured log setup ------------------------------
ERROR    tests.test_utils.python_scripts.download_unit_tests_dataset:download_unit_tests_dataset.py:80   Error downloading/extracting datasets.zip: [Errno 2] No such file or directory: '/opt/data/datasets.zip'
ERROR    tests.test_utils.python_scripts.download_unit_tests_dataset:download_unit_tests_dataset.py:80   Error downloading/extracting tokenizers.zip: [Errno 2] No such file or directory: '/opt/data/tokenizers.zip'
============================= slowest 15 durations =============================
2.02s call     tests/unit_tests/transformer/experimental_attention_variant/test_dsa_topk_backend.py::test_cudnn_score_hook_uses_external_tie_policy[tied-bshd-1]
1.41s call     tests/unit_tests/transformer/experimental_attention_variant/test_dsa_topk_backend.py::test_flashinfer_selector_matches_public_api[False-0-shape0]
0.98s call     tests/unit_tests/transformer/experimental_attention_variant/test_dsa_topk_backend.py::test_flashinfer_selector_matches_public_api[False-2-shape0]
0.91s call     tests/unit_tests/transformer/experimental_attention_variant/test_dsa_topk_backend.py::test_cudnn_score_hook_uses_external_tie_policy[nonzero-bshd-1]
0.81s call     tests/unit_tests/transformer/experimental_attention_variant/test_dsa_topk_backend.py::test_external_selection_preserves_fused_packed_cp_scores[tied-1-2]
0.77s call     tests/unit_tests/transformer/experimental_attention_variant/test_dsa_topk_backend.py::test_external_selection_preserves_fused_packed_cp_scores[tied-1-1]
0.64s setup    tests/unit_tests/transformer/experimental_attention_variant/test_dsa_topk_backend.py::test_external_topk_cli_fields_are_generated
0.21s call     tests/unit_tests/transformer/experimental_attention_variant/test_dsa_topk_backend.py::test_reference_indexer_loss_retains_external_indices_and_backward[False]
0.15s call     tests/unit_tests/transformer/experimental_attention_variant/test_dsa_topk_backend.py::test_flashinfer_selector_matches_public_api[False-1-shape0]
0.05s call     tests/unit_tests/transformer/experimental_attention_variant/test_dsa_topk_backend.py::test_external_score_chunks_preserve_global_mask_offsets[tied-packed-chunks-1]
0.04s call     tests/unit_tests/transformer/experimental_attention_variant/test_dsa_topk_backend.py::test_external_topk_cli_fields_are_generated
0.02s call     tests/unit_tests/transformer/experimental_attention_variant/test_dsa_topk_backend.py::test_skip_layer_reuses_external_selection_without_recomputing[plain]
0.01s call     tests/unit_tests/transformer/experimental_attention_variant/test_dsa_topk_backend.py::test_skip_layer_reuses_external_selection_without_recomputing[packed_tail]
0.01s call     tests/unit_tests/transformer/experimental_attention_variant/test_dsa_topk_backend.py::test_skip_layer_reuses_external_selection_without_recomputing[padded]

(1 durations < 0.005s hidden.  Use -vv to show these durations.)
=========================== short test summary info ============================
PASSED tests/unit_tests/transformer/experimental_attention_variant/test_dsa_topk_backend.py::test_external_topk_cli_fields_are_generated
PASSED tests/unit_tests/transformer/experimental_attention_variant/test_dsa_topk_backend.py::test_flashinfer_selector_matches_public_api[False-0-shape0]
PASSED tests/unit_tests/transformer/experimental_attention_variant/test_dsa_topk_backend.py::test_flashinfer_selector_matches_public_api[False-0-shape1]
PASSED tests/unit_tests/transformer/experimental_attention_variant/test_dsa_topk_backend.py::test_flashinfer_selector_matches_public_api[False-1-shape0]
PASSED tests/unit_tests/transformer/experimental_attention_variant/test_dsa_topk_backend.py::test_flashinfer_selector_matches_public_api[False-1-shape1]
PASSED tests/unit_tests/transformer/experimental_attention_variant/test_dsa_topk_backend.py::test_flashinfer_selector_matches_public_api[False-2-shape0]
PASSED tests/unit_tests/transformer/experimental_attention_variant/test_dsa_topk_backend.py::test_flashinfer_selector_matches_public_api[False-2-shape1]
PASSED tests/unit_tests/transformer/experimental_attention_variant/test_dsa_topk_backend.py::test_flashinfer_selector_matches_public_api[True-0-shape0]
PASSED tests/unit_tests/transformer/experimental_attention_variant/test_dsa_topk_backend.py::test_flashinfer_selector_matches_public_api[True-0-shape1]
PASSED tests/unit_tests/transformer/experimental_attention_variant/test_dsa_topk_backend.py::test_flashinfer_selector_matches_public_api[True-1-shape0]
PASSED tests/unit_tests/transformer/experimental_attention_variant/test_dsa_topk_backend.py::test_flashinfer_selector_matches_public_api[True-1-shape1]
PASSED tests/unit_tests/transformer/experimental_attention_variant/test_dsa_topk_backend.py::test_flashinfer_selector_matches_public_api[True-2-shape0]
PASSED tests/unit_tests/transformer/experimental_attention_variant/test_dsa_topk_backend.py::test_flashinfer_selector_matches_public_api[True-2-shape1]
PASSED tests/unit_tests/transformer/experimental_attention_variant/test_dsa_topk_backend.py::test_torch_selector_keeps_torch_topk_ties_and_masks
PASSED tests/unit_tests/transformer/experimental_attention_variant/test_dsa_topk_backend.py::test_cudnn_score_hook_uses_external_tie_policy[tied-bshd-1]
PASSED tests/unit_tests/transformer/experimental_attention_variant/test_dsa_topk_backend.py::test_cudnn_score_hook_uses_external_tie_policy[tied-bshd-2]
PASSED tests/unit_tests/transformer/experimental_attention_variant/test_dsa_topk_backend.py::test_cudnn_score_hook_uses_external_tie_policy[tied-packed-thd-1]
PASSED tests/unit_tests/transformer/experimental_attention_variant/test_dsa_topk_backend.py::test_cudnn_score_hook_uses_external_tie_policy[tied-packed-thd-2]
PASSED tests/unit_tests/transformer/experimental_attention_variant/test_dsa_topk_backend.py::test_cudnn_score_hook_uses_external_tie_policy[nonzero-bshd-1]
PASSED tests/unit_tests/transformer/experimental_attention_variant/test_dsa_topk_backend.py::test_cudnn_score_hook_uses_external_tie_policy[nonzero-bshd-2]
PASSED tests/unit_tests/transformer/experimental_attention_variant/test_dsa_topk_backend.py::test_cudnn_score_hook_uses_external_tie_policy[nonzero-packed-thd-1]
PASSED tests/unit_tests/transformer/experimental_attention_variant/test_dsa_topk_backend.py::test_cudnn_score_hook_uses_external_tie_policy[nonzero-packed-thd-2]
PASSED tests/unit_tests/transformer/experimental_attention_variant/test_dsa_topk_backend.py::test_external_score_chunks_preserve_global_mask_offsets[tied-packed-chunks-1]
PASSED tests/unit_tests/transformer/experimental_attention_variant/test_dsa_topk_backend.py::test_external_score_chunks_preserve_global_mask_offsets[tied-packed-chunks-2]
PASSED tests/unit_tests/transformer/experimental_attention_variant/test_dsa_topk_backend.py::test_external_score_chunks_preserve_global_mask_offsets[tied-cp-zigzag-chunks-1]
PASSED tests/unit_tests/transformer/experimental_attention_variant/test_dsa_topk_backend.py::test_external_score_chunks_preserve_global_mask_offsets[tied-cp-zigzag-chunks-2]
PASSED tests/unit_tests/transformer/experimental_attention_variant/test_dsa_topk_backend.py::test_external_score_chunks_preserve_global_mask_offsets[nonzero-packed-chunks-1]
PASSED tests/unit_tests/transformer/experimental_attention_variant/test_dsa_topk_backend.py::test_external_score_chunks_preserve_global_mask_offsets[nonzero-packed-chunks-2]
PASSED tests/unit_tests/transformer/experimental_attention_variant/test_dsa_topk_backend.py::test_external_score_chunks_preserve_global_mask_offsets[nonzero-cp-zigzag-chunks-1]
PASSED tests/unit_tests/transformer/experimental_attention_variant/test_dsa_topk_backend.py::test_external_score_chunks_preserve_global_mask_offsets[nonzero-cp-zigzag-chunks-2]
PASSED tests/unit_tests/transformer/experimental_attention_variant/test_dsa_topk_backend.py::test_external_score_hook_declines_explicit_key_positions
PASSED tests/unit_tests/transformer/experimental_attention_variant/test_dsa_topk_backend.py::test_skip_layer_reuses_external_selection_without_recomputing[plain]
PASSED tests/unit_tests/transformer/experimental_attention_variant/test_dsa_topk_backend.py::test_skip_layer_reuses_external_selection_without_recomputing[packed_tail]
PASSED tests/unit_tests/transformer/experimental_attention_variant/test_dsa_topk_backend.py::test_skip_layer_reuses_external_selection_without_recomputing[padded]
PASSED tests/unit_tests/transformer/experimental_attention_variant/test_dsa_topk_backend.py::test_external_selection_declines_combined_indexer_loss_hooks
PASSED tests/unit_tests/transformer/experimental_attention_variant/test_dsa_topk_backend.py::test_external_selection_preserves_fused_packed_cp_scores[tied-1-1]
PASSED tests/unit_tests/transformer/experimental_attention_variant/test_dsa_topk_backend.py::test_external_selection_preserves_fused_packed_cp_scores[tied-1-2]
PASSED tests/unit_tests/transformer/experimental_attention_variant/test_dsa_topk_backend.py::test_external_selection_preserves_fused_packed_cp_scores[tied-2-1]
PASSED tests/unit_tests/transformer/experimental_attention_variant/test_dsa_topk_backend.py::test_external_selection_preserves_fused_packed_cp_scores[tied-2-2]
PASSED tests/unit_tests/transformer/experimental_attention_variant/test_dsa_topk_backend.py::test_external_selection_preserves_fused_packed_cp_scores[nonzero-1-1]
PASSED tests/unit_tests/transformer/experimental_attention_variant/test_dsa_topk_backend.py::test_external_selection_preserves_fused_packed_cp_scores[nonzero-1-2]
PASSED tests/unit_tests/transformer/experimental_attention_variant/test_dsa_topk_backend.py::test_external_selection_preserves_fused_packed_cp_scores[nonzero-2-1]
PASSED tests/unit_tests/transformer/experimental_attention_variant/test_dsa_topk_backend.py::test_external_selection_preserves_fused_packed_cp_scores[nonzero-2-2]
PASSED tests/unit_tests/transformer/experimental_attention_variant/test_dsa_topk_backend.py::test_packed_cp_without_causal_offset_api_uses_global_row_fallback[1]
PASSED tests/unit_tests/transformer/experimental_attention_variant/test_dsa_topk_backend.py::test_packed_cp_without_causal_offset_api_uses_global_row_fallback[2]
PASSED tests/unit_tests/transformer/experimental_attention_variant/test_dsa_topk_backend.py::test_multi_packed_cp_local_tp_slice_uses_global_row_fallback[1]
PASSED tests/unit_tests/transformer/experimental_attention_variant/test_dsa_topk_backend.py::test_multi_packed_cp_local_tp_slice_uses_global_row_fallback[2]
PASSED tests/unit_tests/transformer/experimental_attention_variant/test_dsa_topk_backend.py::test_split_attention_backward_skips_compaction_only_for_known_nonempty_rows[False]
PASSED tests/unit_tests/transformer/experimental_attention_variant/test_dsa_topk_backend.py::test_split_attention_backward_skips_compaction_only_for_known_nonempty_rows[True]
PASSED tests/unit_tests/transformer/experimental_attention_variant/test_dsa_topk_backend.py::test_no_auxiliary_loss_keeps_full_fused_dispatch
PASSED tests/unit_tests/transformer/experimental_attention_variant/test_dsa_topk_backend.py::test_reference_indexer_loss_retains_external_indices_and_backward[False]
PASSED tests/unit_tests/transformer/experimental_attention_variant/test_dsa_topk_backend.py::test_reference_indexer_loss_retains_external_indices_and_backward[True]
52 passed, 114 warnings in 8.34s
Complete final existing-default regression output
Flax classes are deprecated and will be removed in Diffusers v1.0.0. We recommend migrating to PyTorch classes or pinning your version of Diffusers.
Flax classes are deprecated and will be removed in Diffusers v1.0.0. We recommend migrating to PyTorch classes or pinning your version of Diffusers.
LANG_RL Log directory: None
Test data not found at /opt/data. Downloading...
ERROR:tests.test_utils.python_scripts.download_unit_tests_dataset:  Error downloading/extracting datasets.zip: [Errno 2] No such file or directory: '/opt/data/datasets.zip'
ERROR:tests.test_utils.python_scripts.download_unit_tests_dataset:  Error downloading/extracting tokenizers.zip: [Errno 2] No such file or directory: '/opt/data/tokenizers.zip'
Test data downloaded successfully.
.....................
=============================== warnings summary ===============================
../../../opt/sglang/lib/python3.12/site-packages/torch/jit/_script.py:1488
../../../opt/sglang/lib/python3.12/site-packages/torch/jit/_script.py:1488
../../../opt/sglang/lib/python3.12/site-packages/torch/jit/_script.py:1488
  /opt/sglang/lib/python3.12/site-packages/torch/jit/_script.py:1488: DeprecationWarning: `torch.jit.script` is deprecated. Please switch to `torch.compile` or `torch.export`.
    warnings.warn(

../../../opt/sglang/lib/python3.12/site-packages/transformer_engine/__init__.py:103
  /opt/sglang/lib/python3.12/site-packages/transformer_engine/__init__.py:103: RuntimeWarning: Detected a Jax installation but could not find the shared object file for the Transformer Engine Jax extension library. If this is not intentional, please reinstall Transformer Engine with `pip install transformer_engine[jax]` or build from source with `NVTE_FRAMEWORK=jax`.
    warnings.warn(

megatron/core/dist_checkpointing/strategies/torch.py:69
  /root/dsa-native-glm52/megatron/megatron/core/dist_checkpointing/strategies/torch.py:69: DeprecationWarning: transformer_engine.pytorch.float8_tensor is deprecated and will be removed in a future release. Float8Tensor should be imported directly through `from transformer_engine.pytorch import Float8Tensor`
    from transformer_engine.pytorch.float8_tensor import Float8Tensor

../../../opt/sglang/lib/python3.12/site-packages/torch/jit/_script.py:365: 14 warnings
  /opt/sglang/lib/python3.12/site-packages/torch/jit/_script.py:365: DeprecationWarning: `torch.jit.script_method` is deprecated. Please switch to `torch.compile` or `torch.export`.
    warnings.warn(

megatron/core/tensor_parallel/random.py:83
  /root/dsa-native-glm52/megatron/megatron/core/tensor_parallel/random.py:83: DeprecationWarning: Using deprecated internal API from Transformer Engine. transformer_engine.pytorch.fp8 will be removed in a future release.
    from transformer_engine.pytorch.fp8 import FP8GlobalStateManager, fp8_autocast

megatron/core/inference/contexts/__init__.py:9
  /root/dsa-native-glm52/megatron/megatron/core/inference/contexts/__init__.py:9: DeprecationWarning: The following imports from `dynamic_context.py` will be removed in this file in `megatron-core` 0.14. The imports here result in a cyclic import issue that causes rotary embeddings to import from Apex rather than Transformer Engine.
    warnings.warn(

megatron/rl/inference/inference_interface.py:15
  /root/dsa-native-glm52/megatron/megatron/rl/inference/inference_interface.py:15: PydanticDeprecatedSince20: Support for class-based `config` is deprecated, use ConfigDict instead. Deprecated in Pydantic V2.0 to be removed in V3.0. See Pydantic V2 Migration Guide at https://errors.pydantic.dev/2.13/migration/
    class InferenceInterface(BaseModel):

megatron/rl/__init__.py:31
megatron/rl/__init__.py:31
  /root/dsa-native-glm52/megatron/megatron/rl/__init__.py:31: PydanticDeprecatedSince20: The `__fields__` attribute is deprecated, use the `model_fields` class property instead. Deprecated in Pydantic V2.0 to be removed in V3.0. See Pydantic V2 Migration Guide at https://errors.pydantic.dev/2.13/migration/
    cls.Library.type_names[register_type.__fields__['type_name'].default] = register_type

-- Docs: https://docs.pytest.org/en/stable/how-to/capture-warnings.html
==================================== PASSES ====================================
_________ test_cudnn_indexer_topk_varlen_uses_logical_query_positions __________
------------------------------ Captured log setup ------------------------------
ERROR    tests.test_utils.python_scripts.download_unit_tests_dataset:download_unit_tests_dataset.py:80   Error downloading/extracting datasets.zip: [Errno 2] No such file or directory: '/opt/data/datasets.zip'
ERROR    tests.test_utils.python_scripts.download_unit_tests_dataset:download_unit_tests_dataset.py:80   Error downloading/extracting tokenizers.zip: [Errno 2] No such file or directory: '/opt/data/tokenizers.zip'
============================= slowest 15 durations =============================
0.60s setup    tests/unit_tests/transformer/experimental_attention_variant/test_dsa_native_parity.py::test_cudnn_indexer_topk_varlen_uses_logical_query_positions
0.04s call     tests/unit_tests/transformer/experimental_attention_variant/test_dsa_native_parity.py::test_cudnn_indexer_topk_multi_packed_cp_uses_segmented_thd
0.03s call     tests/unit_tests/transformer/experimental_attention_variant/test_dsa_native_parity.py::test_cudnn_indexer_topk_multi_packed_cp_selects_all_segment_keys[scores-odd-k]
0.03s call     tests/unit_tests/transformer/experimental_attention_variant/test_dsa_native_parity.py::test_cudnn_indexer_topk_multi_packed_cp_selects_all_segment_keys[indices-odd-k]
0.02s call     tests/unit_tests/transformer/experimental_attention_variant/test_dsa_native_parity.py::test_cudnn_indexer_topk_multi_packed_cp_selects_all_segment_keys[indices-even-k]
0.02s call     tests/unit_tests/transformer/experimental_attention_variant/test_dsa_native_parity.py::test_cudnn_indexer_topk_multi_packed_cp_selects_all_segment_keys[scores-even-k]
0.01s call     tests/unit_tests/transformer/experimental_attention_variant/test_dsa_native_parity.py::test_cudnn_indexer_topk_varlen_uses_logical_query_positions

(8 durations < 0.005s hidden.  Use -vv to show these durations.)
=========================== short test summary info ============================
PASSED tests/unit_tests/transformer/experimental_attention_variant/test_dsa_native_parity.py::test_cudnn_indexer_topk_varlen_uses_logical_query_positions
PASSED tests/unit_tests/transformer/experimental_attention_variant/test_dsa_native_parity.py::test_cudnn_indexer_topk_score_chunks_preserve_global_query_offsets
PASSED tests/unit_tests/transformer/experimental_attention_variant/test_dsa_native_parity.py::test_cudnn_indexer_topk_tie_break_prefers_lower_indices
PASSED tests/unit_tests/transformer/experimental_attention_variant/test_dsa_native_parity.py::test_cudnn_indexer_topk_repeated_varlen_ends_keep_distinct_query_rows
PASSED tests/unit_tests/transformer/experimental_attention_variant/test_dsa_native_parity.py::test_cudnn_indexer_topk_nonlocal_varlen_ends_avoid_global_score_rows
PASSED tests/unit_tests/transformer/experimental_attention_variant/test_dsa_native_parity.py::test_cudnn_indexer_topk_local_varlen_keeps_compact_query_rows
PASSED tests/unit_tests/transformer/experimental_attention_variant/test_dsa_native_parity.py::test_cudnn_indexer_topk_multi_packed_cp_uses_segmented_thd
PASSED tests/unit_tests/transformer/experimental_attention_variant/test_dsa_native_parity.py::test_cudnn_indexer_topk_multi_packed_cp_selects_all_segment_keys[indices-odd-k]
PASSED tests/unit_tests/transformer/experimental_attention_variant/test_dsa_native_parity.py::test_cudnn_indexer_topk_multi_packed_cp_selects_all_segment_keys[indices-even-k]
PASSED tests/unit_tests/transformer/experimental_attention_variant/test_dsa_native_parity.py::test_cudnn_indexer_topk_multi_packed_cp_selects_all_segment_keys[scores-odd-k]
PASSED tests/unit_tests/transformer/experimental_attention_variant/test_dsa_native_parity.py::test_cudnn_indexer_topk_multi_packed_cp_selects_all_segment_keys[scores-even-k]
PASSED tests/unit_tests/transformer/experimental_attention_variant/test_dsa_native_parity.py::test_cudnn_indexer_topk_single_packed_cp_uses_absolute_seq_lens
PASSED tests/unit_tests/transformer/experimental_attention_variant/test_dsa_native_parity.py::test_cudnn_indexer_topk_single_packed_cp_prefix_crops_keys_per_chunk
PASSED tests/unit_tests/transformer/experimental_attention_variant/test_dsa_native_parity.py::test_cudnn_indexer_topk_indices_only_filters_masked_varlen_scores
PASSED tests/unit_tests/transformer/experimental_attention_variant/test_dsa_native_parity.py::test_cudnn_indexer_topk_indices_only_compacts_invalid_prefix_entries
PASSED tests/unit_tests/transformer/experimental_attention_variant/test_dsa_native_parity.py::test_cudnn_indexer_topk_can_return_topk_scores
PASSED tests/unit_tests/transformer/experimental_attention_variant/test_dsa_native_parity.py::test_cudnn_indexer_topk_tie_break_does_not_bias_selected_scores
PASSED tests/unit_tests/transformer/experimental_attention_variant/test_dsa_native_parity.py::test_cudnn_indexer_topk_scores_reapply_varlen_bounds
PASSED tests/unit_tests/transformer/experimental_attention_variant/test_dsa_native_parity.py::test_cudnn_split_topk_hook_uses_indexer_topk
PASSED tests/unit_tests/transformer/experimental_attention_variant/test_dsa_native_parity.py::test_cudnn_indexer_topk_scores_local_varlen_keeps_compact_query_rows
PASSED tests/unit_tests/transformer/experimental_attention_variant/test_dsa_native_parity.py::test_cudnn_sparse_attention_uses_supplied_topk_length
21 passed, 69 deselected, 24 warnings in 0.94s

Paired TP1/CP4/EP4 trainer comparison

Both frozen-trajectory arms exited 0 on the same C2 B300 node/image above, each with four actor GPUs: TP1/CP4/EP4/PP1, expertTP1, no sequence parallelism. The separate eight-GPU rollout/training E2E follows.

Arm Miles Megatron
baseline 3439ec75132d99dab443402e894eaa314e666d92 a84b105473eca9c9c6e49dbf1c8aa460c5cf796e
candidate 0d6cb7bee4ee1586ee64ba1fd3827a432dcbe657 524ff28f2463b93c7c3ede29c7981cef499f7b2d
  • Workload: Pinaster/GLM-5.2_5layer (3 dense/2 MoE), top-k2048; 2 steps×64 samples×100 active response tokens. Identical frozen tokens/logprobs/rewards/masks/routing, fresh processes/optimizers, separate conversions of one BF16 HF checkpoint. Config/tokenizer/rollout hashes checked; weight payloads un-hashed.
  • Precision/recipe: Routed experts NVFP4 fake-QDQ/BF16 TE GEMMs; shared experts high precision. CPU-offloaded Adam LR1e-6/WD0.1, full one-layer recompute, dynamic2048-token batching, pad1024, FlashInfer large ties; same environment/model script. Both override old TP4/CP1: Miles contiguous --allgather-cp, native zigzag --cp-comm-type allgather.
  • Timing method: actor_train includes optimizer; train adds scoring/advantages/logging. Primary-rank wall timer (TP0,last PP,effective DP/CP0), no CUDA sync/events, not rank-max/kernel time. Step0 cold first-use/compile with persistent disk caches; step1 one observation. Excludes loading/conversion/launch/generation/publication/train_wait; W&B off.
  • Input/numeric audit: Inverse CP reconstructs4 ranks/step; exact tokens/masks/IDs/rollout logprobs. Eight dump/log checks pass atol1e-8/rtol1e-4. Tables: masked sample means; artifacts: token means/quantiles. Step1 pre-update scores include step0 updates.
Step Metric Miles s Native s Native time change Miles/native
0 perf/ref_log_probs_time 39.5068266392 26.2062740326 -33.6665% 1.507533
0 perf/log_probs_time 6.01725268364 3.63321995735 -39.6200% 1.656176
0 perf/actor_train_time 106.782449484 78.2634403706 -26.7076% 1.364398
0 perf/train_time 152.944163799 108.740454435 -28.9019% 1.406507
1 perf/ref_log_probs_time 0.266575574875 0.389870643616 +46.2515% 0.683754
1 perf/log_probs_time 0.216864109039 0.280049324036 +29.1359% 0.774378
1 perf/actor_train_time 30.5207357407 27.4330701828 -10.1166% 1.112553
1 perf/train_time 31.6448955536 28.7393035889 -9.1819% 1.101102

Negative time change means shorter execution.

Single subsequent step: actor 10.12% less time, total trainer 9.18% less, actor scoring 29.14% more, reference scoring 46.25% more; no steady-state throughput claim.

Step Samples Active tokens Signed native-minus-Miles mean Absolute mean Absolute p95 Absolute p99 Absolute maximum Paired rollout-sampled k3
0 64 6400 7.50382273691e-05 0.00746450160514 0.0304687261581 0.0333590221405 0.065366268158 7.39096856201e-05
1 64 6400 0.000196773331845 0.00746794320061 0.0305829763412 0.0332132148743 0.0638394355774 7.38775364494e-05

Frozen-rollout file hashes also match.

Train–inference KL: logged sample mean train/train_rollout_kl, inference-sampled low-variance k3 estimate of KL(inference || trainer) with FP32 clamps, not full-vocabulary KL. CP reduction differs by a few 1e-9; reference KL and paired discrepancy are separate.

Arm Step Logged train/rollout abs diff Train–inference KL (train/train_rollout_kl) Reference kl_loss PPO kl Loss Grad norm
baseline 0 0.0108880940825 9.71974222920835e-05 0.000173180829734 -0.000222310074605 0 0
baseline 1 0.0109125245363 9.61235273280181e-05 0.000150387350004 0.000150050225784 0 0
candidate 0 0.01115302369 0.00010137323988601565 0.000140120697324 0 0 0
candidate 1 0.0108721591532 9.742614929564297e-05 0.00011259841267 0 0 0
  • KL definitions: rollout-to-trainer k3: d=train_logp-rollout_logp, z=clamp(d,-20,20), mean(clamp(exp(z)-1-z,-10,10)), computed in FP32. Paired k3: delta=native_logp-Miles_logp, mean(exp(delta)-1-delta), unclamped. Samples come from inference, not the baseline trainer, so paired k3 is a discrepancy, not unbiased/exact policy KL. kl_loss is reference-policy and ppo_kl optimization-policy diagnostics.
  • Important limits: All128 rewards/losses/gradient norms zero; weight decay may update weights. Execution/sampled-score evidence, not learning/quality. Lengths201–343<top-k2048 do not exercise valid-key boundary ties (GPU suite does). BF16-vs-FP32 projection is not proven causal for differences; attention/CP arithmetic differs. Numeric/weight-update/KL CI checkers disabled; offline audit separate.
Complete raw recorded paired perf, rollout, and training-step metrics

Restore each key's prefix, then merge common with dict(zip(columns,values)). All records/keys/values/arms/steps round-trip to the original raw evidence, which retains timestamps/PIDs.

[
{"kind":"perf","prefix":"perf/","common":{"mfu_peak_tflops":2250.0},"columns":["update_weights_time","data_preprocess_time","train_wait_time","ref_log_probs_time","log_probs_time","actor_train_time","train_time","log_probs_tflops","ref_log_probs_tflops","actor_train_tflops","actor_train_tok_per_s","actor_train_mfu","step_time","wait_time_ratio"],"rows":[
{"record":0,"arm":"Miles","step":0,"values":[9.632110595703125e-05,0.006532907485961914,3.35579252243042,39.506826639175415,6.017252683639526,106.78244948387146,152.9441637992859,3.8693686599096466,0.5893403984450714,0.6541234743734369,153.43345352341498,0.00029072154416597196,156.2999563217163,0.0214702076789011]},
{"record":1,"arm":"Miles","step":1,"values":[0.00010251998901367188,0.009912490844726562,1.5883934497833252,0.26657557487487793,0.21686410903930664,30.52073574066162,31.644895553588867,105.10535757057274,85.50513202681296,2.24046824281824,525.5443425838033,0.0009957636634747734,33.23328900337219,0.047795252814795144]},
{"record":6,"arm":"native","step":0,"values":[0.0001010894775390625,0.009304046630859375,0.324535608291626,26.206274032592773,3.6332199573516846,78.26344037055969,108.74045443534851,6.4083565614352045,0.8884501827262794,0.8924844924753784,209.3442343248069,0.00039665977443350154,109.06499004364014,0.0029756167232195194]},
{"record":7,"arm":"native","step":1,"values":[0.00010442733764648438,0.009916543960571289,1.4353315830230713,0.38987064361572266,0.28004932403564453,27.433070182800293,28.739303588867188,81.3913042043224,58.464467889679256,2.492638947035271,584.6957665736078,0.001107839532015676,30.17463517189026,0.04756748755524909]}
]},
{"kind":"rollout","prefix":"rollout/","common":{"response_lengths":100.0,"rewards":0.0,"truncated":1.0,"raw_reward":0.0,"advantages":0.0,"returns":0.0},"columns":["rollout_log_probs","total_lengths","ref_log_probs","log_probs"],"rows":[
{"record":2,"arm":"Miles","step":0,"values":[-10.37608551979065,256.0,-10.376765310764313,-10.376266777515411]},
{"record":3,"arm":"Miles","step":1,"values":[-10.290511727333069,250.625,-10.290502071380615,-10.290469765663147]},
{"record":8,"arm":"native","step":0,"values":[-10.37608551979065,256.0,-10.376913666725159,-10.376191258430481]},
{"record":9,"arm":"native","step":1,"values":[-10.290511727333069,250.625,-10.29033637046814,-10.29027271270752]}
]},
{"kind":"step","prefix":"train/","common":{"loss":0.0,"pg_loss":0.0,"entropy_loss":0.0,"pg_clipfrac":0.0,"tis_clipfrac":0.0,"grad_norm":0.0,"lr-pg_0":1e-06,"lr-pg_1":1e-06,"lr-pg_2":1e-06},"columns":["ppo_kl","ess_ratio","train_rollout_logprob_abs_diff","train_rollout_kl","kl_loss","ois","tis","tis_abs","step"],"rows":[
{"record":4,"arm":"Miles","step":0,"values":[-0.0002223100746050477,0.9998570084571838,0.010888094082474709,9.71974222920835e-05,0.00017318082973361015,1.0002942085266113,0.9999154210090637,0.010886028409004211,0]},
{"record":5,"arm":"Miles","step":1,"values":[0.0001500502257840708,0.999860405921936,0.010912524536252022,9.61235273280181e-05,0.00015038735000416636,0.9999205470085144,1.000138282775879,0.010914952494204044,1]},
{"record":10,"arm":"native","step":0,"values":[0.0,1.0,0.011153023689985275,0.00010137323988601565,0.0001401206973241642,0.9999999403953552,0.999994695186615,0.011153263971209526,0]},
{"record":11,"arm":"native","step":1,"values":[0.0,1.0,0.010872159153223038,9.742614929564297e-05,0.0001125984126701951,1.000000238418579,1.0003365278244019,0.010876685380935669,1]}
]}
]
  • Reproduction helpers: pinned setup, helpers and scalar results. README includes repository/checkpoint/seed preparation, test environment and final full-E2E command. Extract into $REPRO/public-repro, use the paired commits above, prepare seeds, then run GPU commands sequentially:
export REPRO=/workspace/dsa-repro
export ROLLOUTS='/root/shared_data/dsa-seed/dump_details/rollout_data/{rollout_id}.pt'
set -o pipefail
for arm in before after; do
  impl=miles
  if [ "$arm" = after ]; then impl=megatron; fi
  python "$REPRO/public-repro/paired_dsa_runner.py" \
    --action convert --impl "$impl" \
    --miles-root "$REPRO/miles-$arm" --megatron-root "$REPRO/megatron-$arm" \
    --checkpoint-name "GLM-5.2_5layer-paired-$arm" \
    --run-id "dsa-$arm-convert" --output-root "$REPRO/results" \
    2>&1 | tee "$REPRO/logs/$arm-convert.log"
done
for arm in before after; do
  impl=miles
  if [ "$arm" = after ]; then impl=megatron; fi
  python "$REPRO/public-repro/paired_dsa_runner.py" \
    --action run --impl "$impl" \
    --miles-root "$REPRO/miles-$arm" --megatron-root "$REPRO/megatron-$arm" \
    --checkpoint-name "GLM-5.2_5layer-paired-$arm" \
    --run-id "dsa-$arm-cp4" --output-root "$REPRO/results" --rollouts "$ROLLOUTS" \
    2>&1 | tee "$REPRO/logs/$arm-cp4.log"
done
python "$REPRO/public-repro/compare_dsa_metrics.py" \
  --baseline-train-dir "$REPRO/results/dsa-before-cp4/dump_details/train_data" \
  --candidate-train-dir "$REPRO/results/dsa-after-cp4/dump_details/train_data" \
  --baseline-log "$REPRO/logs/before-cp4.log" --candidate-log "$REPRO/logs/after-cp4.log" \
  --miles-root "$REPRO/miles-after" \
  --output-prefix "$REPRO/logs/paired-cp4-comparison"

Final full CP4 E2E

Completed dsa-w4a16-cp4-final on Miles 41975f2d9589c417783ed38effc75865531fd2da and Megatron 524ff28f2463b93c7c3ede29c7981cef499f7b2d: four actor GPUs (TP1/CP4/EP4/PP1/expertTP1), four rollout GPUs, two fresh steps, success 2026-09-29 22:07:58, wrapper wall time 726.1579617420211 s. Fresh trajectories are separate from the frozen pair above. Miles final adds only the early negative-loss guard and CPU test to paired 0d6cb7be.

The wrapper reused assets and called the real test's execute(), overriding only run ID, independent Megatron import path, disabled W&B and launcher-owned Ray lifetime. Two successful publications: default → 1 before rollout 0, then 1 → 2 before rollout 1. All 64 samples/rollout have the expected version; mixed-version ratios are zero. The unchanged loop skips final publication when no next rollout/evaluation is due.

Step Actor score s Ref score s Actor train s Total train s Train/rollout absolute diff Low-var k3 Reference KL Loss Grad norm
0 2.82337117195 59.3978788853 70.3478653431 133.205298424 0.0111276991665 9.90308544715e-05 0.000111419067252 0 0
1 0.273497819901 0.327144861221 29.0327274799 30.2696113586 0.0109319016337 9.72032503341e-05 0.000122881872812 0 0

Eight CP shards reassemble into 64 samples/6,400 active tokens per step. Four dump/log checks pass atol=1e-8, rtol=1e-4, maximum difference 3.55270458385e-09; zero same-run paired deltas only audit extraction. All 128 rewards/losses/gradients are zero; responses hit 100 tokens. This verifies execution/version progress, not learning, quality or long-context boundaries. Numeric CI checkers remain disabled; this section makes no full-model validation claim.

Raw final-E2E records (separate from paired replay):

Use the scalar encoding above; these records are from the separate final E2E.

2026-09-29 22:07:58,161	SUCC cli.py:67 -- Job 'miles-8ac3f59f390944d884ae21d494312edf' succeeded
(MegatronTrainRayActorWithConcurrencyGroups pid=199636) [2026-09-29 22:04:50.692 actor_cell00000_rank00000] structured_log.py:28 - actor cls=MegatronTrainRayActorWithConcurrencyGroups fn=update_weights phase=end ok=true elapsed_s=2.4
(MegatronTrainRayActorWithConcurrencyGroups pid=199636) [2026-09-29 22:07:13.868 actor_cell00000_rank00000] structured_log.py:28 - actor cls=MegatronTrainRayActorWithConcurrencyGroups fn=update_weights phase=end ok=true elapsed_s=1.2
[
{"kind":"perf","prefix":"perf/","common":{"mfu_peak_tflops":2250.0},"columns":["update_weights_implementation_time","finalize_and_resume_engines_time","update_weights_time","data_preprocess_time","train_wait_time","ref_log_probs_time","log_probs_time","actor_train_time","train_time","log_probs_tflops","ref_log_probs_tflops","actor_train_tflops","actor_train_tok_per_s","actor_train_mfu","step_time","wait_time_ratio"],"rows":[
{"record":0,"arm":"final-full-E2E","step":0,"values":[2.2860162258148193,0.023979663848876953,2.3967437744140625,0.009305000305175781,9.883866310119629,59.397878885269165,2.823371171951294,70.34786534309387,133.2052984237671,8.246513665697249,0.3919831716180397,0.9929072690100206,232.89974642575896,0.00044129211956000917,143.08916473388672,0.06907487599428909]},
{"record":1,"arm":"final-full-E2E","step":1,"values":[1.1596965789794922,0.024682998657226562,1.209233283996582,0.008936166763305664,3.3599729537963867,0.3271448612213135,0.2734978199005127,29.032727479934692,30.269611358642578,83.3409923819187,69.6742710238696,2.355298489322431,552.4799559767741,0.001046799328587747,33.629584312438965,0.09991122466992833]}
]},
{"kind":"rollout","prefix":"rollout/","common":{"response_lengths":100.0,"rewards":0.0,"truncated":1.0,"raw_reward":0.0,"advantages":0.0,"returns":0.0},"columns":["rollout_log_probs","total_lengths","ref_log_probs","log_probs"],"rows":[
{"record":2,"arm":"final-full-E2E","step":0,"values":[-10.322879791259766,256.0,-10.322923600673676,-10.322820544242859]},
{"record":3,"arm":"final-full-E2E","step":1,"values":[-10.288553476333618,250.625,-10.288492321968079,-10.2886803150177]}
]},
{"kind":"rollout_perf","prefix":"","common":{"rollout/raw_reward_unfiltered":0.0,"rollout/num_training_samples":64,"rollout/episode_raw_reward":0.0,"rollout/episode_response_length/mean":100.0,"rollout/episode_response_length/median":100.0,"rollout/episode_response_length/max":100,"rollout/episode_response_length/min":100,"rollout/episode_total_response_length/mean":100.0,"rollout/response_len/mean":100.0,"rollout/response_len/median":100.0,"rollout/response_len/max":100,"rollout/response_len/min":100,"rollout/zero_std/count_0":8,"rollout/zero_std/all_zero_percentage":0.0,"rollout/zero_std/all_one_percentage":0.0,"rollout/repetition_frac":0.0,"rollout/truncated_ratio":1.0,"rollout/weight_version/mixed_version_ratio":0.0},"columns":["rollout/prefix_cache_hit_rate","rollout/avg_cached_tokens_per_sample","rollout/weight_version/mean","rollout/weight_version/median","rollout/weight_version/max","rollout/weight_version/min","perf/rollout_time","perf/tokens_per_gpu_per_sec","perf/longest_sample_tokens_per_sec","perf/effective_tokens_per_gpu_per_sec","perf/longest_effective_sample_tokens_per_sec"],"rows":[
{"record":4,"arm":"final-full-E2E","step":0,"values":[0.05128205128205128,8.0,1.0,1.0,1,1,7.243313789367676,220.89337098009062,13.805835686255664,220.89337098009062,13.805835686255664]},
{"record":5,"arm":"final-full-E2E","step":1,"values":[0.006639004149377593,1.0,2.0,2.0,2,2,0.6896185874938965,2320.123078199601,145.00769238747506,2320.123078199601,145.00769238747506]}
]},
{"kind":"step","prefix":"train/","common":{"loss":0.0,"pg_loss":0.0,"entropy_loss":0.0,"pg_clipfrac":0.0,"ppo_kl":0.0,"ess_ratio":1.0,"tis_clipfrac":0.0,"grad_norm":0.0,"lr-pg_0":1e-06,"lr-pg_1":1e-06,"lr-pg_2":1e-06},"columns":["train_rollout_logprob_abs_diff","train_rollout_kl","kl_loss","ois","tis","tis_abs","step"],"rows":[
{"record":6,"arm":"final-full-E2E","step":0,"values":[0.011127699166536331,9.903085447149351e-05,0.00011141906725242734,0.9999999403953552,1.0001581907272339,0.011130120605230331,0]},
{"record":7,"arm":"final-full-E2E","step":1,"values":[0.010931901633739471,9.720325033413246e-05,0.00012288187281228602,1.000000238418579,0.9999712109565735,0.010932303965091705,1]}
]}
]

Formatting and static checks

Historical scoped formatting at 524ff28f2463b93c7c3ede29c7981cef499f7b2d: six Python files versus fork base. tools/autoformat.sh hardcodes NVIDIA's remote/base, so its commands ran with fork-local scope. Black 26.3.0, isort 5.13.2, Ruff 0.9.10, pylint 3.2.6.

Check Result
uv run --active --no-project isort / isort --check Pass
ruff check --no-fix Pass
git diff --check / python -m py_compile Pass
black --check --diff Five files pass; requests only existing unrelated transformer_config.py formatting changes
pylint Only existing transformer_config.py long lines; same diagnostics reproduced against unmodified fork base
Optional mypy --explicit-package-bases --follow-imports=skip Not passing: local lint environment lacks torch/FlashInfer/cuDNN stubs and existing source has typing errors

Contribution process

Pre-checks

  • I have added relevant unit tests
  • I have added relevant functional tests
  • I have added proper typing to my code
  • I have added relevant documentation (config fields and CLI help)
  • I have run tools/autoformat.sh on my PR (equivalent fork-scoped commands run; existing baseline failures documented above)

Code review

Ready for review.

128K (131,072 tokens) TP1/CP4/EP4 W4A16 trainer comparison

Both backends replay identical frozen five-layer GLM-5.2 trajectories; CP reconstruction verifies tokens, masks and inference logprobs.

Environment and provenance

{"digest":"sha256:686518570f7f460e73986d613457604e7012e2581f9f3d39568bc221ec7c277c","driver":"590.48.01","environment_repair":"Pinned opentelemetry-api==1.44.0 to match installed SDK 1.44.0; original image API 1.45.0 failed Ray dashboard startup before model execution.","hardware":"1 C2 node, 8 B300 (4 trainer GPUs, TP1/CP4/EP4)","hf_revision":"1c749139f70e158e4420ba67f342bef1de2e650d","image":"radixark/miles:dev-202609292119","megatron":"524ff28f2463b93c7c3ede29c7981cef499f7b2d","miles":"41975f2d9589c417783ed38effc75865531fd2da","packages":{"flashinfer-python":"0.6.18","miles":"0.1.1","nvidia-cudnn-frontend":"1.28.0","ray":"2.58.0","sglang":"0.5.21.dev65+g57e7d0e","tilelang":"0.1.14","torch":"2.13.0+cu130","transformer-engine":"2.17.0","transformers":"5.12.1"},"prefill_graphs":"Explicitly disabled (--sglang-cuda-graph-backend-prefill disabled); decode graph settings unchanged.","sglang":"57e7d0e848d8812c9deb4673b96e8e4626d6e794"}

Both arms used the identical historical commits above.

Step Samples Actual total length min–max Response length min–max Active response tokens Total tokens
0 64 131072–131072 100–100 6400 8388608
1 64 131072–131072 100–100 6400 8388608
Step Trainer metric Miles s Native s Native time change Miles/native speedup
0 perf/log_probs_time 117.386121988 30.6103844643 -73.9233% 3.834846×
0 perf/ref_log_probs_time 183.824376822 66.5336251259 -63.8059% 2.762879×
0 perf/actor_train_time 563.100072145 161.609277725 -71.3001% 3.484330×
0 perf/train_time 865.042739391 259.495624542 -70.0020% 3.333554×
1 perf/log_probs_time 110.620069504 28.2891044617 -74.4268% 3.910342×
1 perf/ref_log_probs_time 110.630075693 29.0073103905 -73.7799% 3.813869×
1 perf/actor_train_time 499.504445314 119.95538187 -75.9851% 4.164085×
1 perf/train_time 721.48490119 177.98739481 -75.3304% 4.053573×

The timer definitions/exclusions above apply: step 0 includes first use; step 1 is one subsequent observation. Negative time change means shorter execution.

Step Paired signed log-prob mean Paired absolute mean Absolute p95 Absolute p99 Absolute max Paired sampled k3 discrepancy
0 0.000212674624345 0.00925292631524 0.0313818216324 0.035488986969 0.0681376457214 9.98814586759e-05
1 7.34574743547e-05 0.0094086864288 0.0313520908356 0.0345467996597 0.0731163024902 9.94528590437e-05
Backend Step Train/inference abs log-prob diff Train–inference KL Reference kl_loss PPO kl Loss Grad norm
miles 0 0.0616831220686 0.0032339124009 0.000697825860698 3.83043952752e-05 0 0
miles 1 0.0613812245429 0.00317833176814 0.0006728915032 5.6259050325e-05 0 0
megatron 0 0.0616175457835 0.00322441314347 0.000654250441585 0 0 0
megatron 1 0.0609608739614 0.00313318730332 0.000641794584226 0 0 0

The sample-weighted train–inference KL and paired k3 definitions above apply. Dump scores are pre-update; paired k3 is a discrepancy, not full-vocabulary or unbiased policy KL. All 8 CP dump/log checks pass atol=1e-8, rtol=1e-4; max absolute difference 1.1017546056e-08.

Complete raw scalar metrics (losslessly factored)

For each row, restore the key prefix and merge common with dict(zip(columns, values)). This retains every original scalar metric and is automatically round-trip checked.

[
{"kind":"perf","prefix":"perf/","common":{"mfu_peak_tflops":2250.0},"columns":["update_weights_time","data_preprocess_time","train_wait_time","ref_log_probs_time","log_probs_time","actor_train_time","train_time","log_probs_tflops","ref_log_probs_tflops","actor_train_tflops","actor_train_tok_per_s","actor_train_mfu","step_time","wait_time_ratio"],"rows":[
{"record":0,"arm":"baseline","step":0,"values":[9.5367431640625e-05,0.5797655582427979,23.90319275856018,183.82437682151794,117.38612198829651,563.100072145462,865.0427393913269,484.4558257209162,309.36261903518954,302.9748714434151,14897.188643643123,0.1346554984192956,888.9459321498871,0.02688936626410009]},
{"record":1,"arm":"baseline","step":1,"values":[9.322166442871094e-05,1.0143084526062012,22.524129629135132,110.6300756931305,110.62006950378418,499.50444531440735,721.4849011898041,514.0874609021195,514.0409630899999,341.54885620820386,16793.860552572034,0.15179949164809062,744.0090308189392,0.03027400030930077]},
{"record":6,"arm":"candidate","step":0,"values":[0.00012087821960449219,1.014634609222412,14.903969287872314,66.53362512588501,30.610384464263916,161.60927772521973,259.4956245422363,1857.813668508717,854.7315819394853,1055.6644666039836,51906.722918859545,0.46918420737954825,274.39959383010864,0.054314837277419356]},
{"record":7,"arm":"candidate","step":1,"values":[0.00010132789611816406,1.0053410530090332,22.89513325691223,29.007310390472412,28.289104461669922,119.95538187026978,177.9873948097229,2010.2577207090353,1960.4847843699108,1422.2385799459707,69931.06827897203,0.6321060355315425,200.88252806663513,0.11397274555066154]}
]},
{"kind":"rollout","prefix":"rollout/","common":{"response_lengths":100.0,"rewards":0.0,"truncated":1.0,"raw_reward":0.0,"total_lengths":131072.0,"advantages":0.0,"returns":0.0},"columns":["rollout_log_probs","ref_log_probs","log_probs"],"rows":[
{"record":2,"arm":"baseline","step":0,"values":[-10.301874160766602,-10.30439281463623,-10.304338455200195]},
{"record":3,"arm":"baseline","step":1,"values":[-10.308305740356445,-10.311294555664062,-10.310310363769531]},
{"record":8,"arm":"candidate","step":0,"values":[-10.301874160766602,-10.304998397827148,-10.30412483215332]},
{"record":9,"arm":"candidate","step":1,"values":[-10.308305740356445,-10.311031341552734,-10.310235977172852]}
]},
{"kind":"step","prefix":"train/","common":{"loss":0.0,"pg_loss":0.0,"entropy_loss":0.0,"pg_clipfrac":0.0,"tis_clipfrac":0.0,"grad_norm":0.0,"lr-pg_0":1e-06,"lr-pg_1":1e-06,"lr-pg_2":1e-06},"columns":["ppo_kl","ess_ratio","train_rollout_logprob_abs_diff","train_rollout_kl","kl_loss","ois","tis","tis_abs","step"],"rows":[
{"record":4,"arm":"baseline","step":0,"values":[3.830439527519047e-05,0.9998349547386169,0.06168312206864357,0.0032339124009013176,0.0006978258606977761,1.0000450611114502,1.0007715225219727,0.06168534979224205,0]},
{"record":5,"arm":"baseline","step":1,"values":[5.625905032502487e-05,0.9998306632041931,0.061381224542856216,0.003178331768140197,0.000672891503199935,1.0000290870666504,1.001174807548523,0.06147060543298721,1]},
{"record":10,"arm":"candidate","step":0,"values":[0.0,1.0,0.061617545783519745,0.0032244131434708834,0.0006542504415847361,1.0,1.0009747743606567,0.06163110211491585,0]},
{"record":11,"arm":"candidate","step":1,"values":[0.0,1.0,0.06096087396144867,0.0031331873033195734,0.0006417945842258632,1.0,1.001202940940857,0.06105007976293564,1]}
]}
]

All 128 rewards and every loss/gradient norm are zero; this is execution/numerics evidence, not reward-driven learning. Weight decay can still update weights.

  • Controls: 130,972 repeated-text DAPO input tokens + 100 sampled tokens; original W4A16, top-k and batching settings. Prefill graphs disabled; decode defaults retained. No OOM or 64K fallback.
  • Scope: step 1 actor 4.1641×, total trainer 4.0536× faster. Paired scores differ (~0.0094 mean absolute); this does not establish bitwise parity. Historical short-context runs used another image/baseline, so this is not a controlled cross-length scaling curve.
  • Timing boundary: existing unsynchronized primary-rank timers; initial replay loading/packing and debug saves excluded. Ordinary microbatch replay transfers remain included. Step 1 includes each arm's own step-0 update.
  • Warning: TileLang 0.1.14 emitted shared-memory synchronization warnings for baseline sparse-MLA forward/backward kernels; their numerical impact and race freedom were not established.
  • Reproduce: pinned setup, conversion, helpers and full evidence. After setup:
cd "$REPRO/public-repro"
C=(--miles-root "$REPRO/miles" --megatron-root "$REPRO/megatron"
   --model-dir "$REPRO/models" --data-dir "$REPRO/datasets"
   --output-root "$REPRO/long-results" --sequence-length 131072)
python run_w4a16_long_context.py "${C[@]}" --action generate --impl megatron --run-id seed
for impl in miles megatron; do
  python run_w4a16_long_context.py "${C[@]}" --action run --impl "$impl" --run-id "$impl" \
    --rollouts "$REPRO/long-results/seed/dump_details/rollout_data/{rollout_id}.pt"
done

Signed-off-by: Ziang Li <ziangli@umich.edu>
Signed-off-by: Ziang Li <ziangli@umich.edu>
Signed-off-by: Ziang Li <ziangli@umich.edu>
@zianglih
zianglih marked this pull request as ready for review September 30, 2026 08:24
Signed-off-by: Ziang Li <ziangli@umich.edu>

@Zhichenzzz Zhichenzzz left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

LGTHuman

@Zhichenzzz

Copy link
Copy Markdown
Collaborator

Reviewed at head 8918ef3. High-quality implementation — I verified the autograd input-count compatibility (ctx.num_inputs slicing), backward reuse of forward-saved indices, and _ensure_dsa_namespace ordering, and found no unconditionally-triggered correctness bug. Findings, ordered by severity:

1. [Risk — medium] External top-k path drops the _topk_in_bounds out-of-bounds guard

The external early-returns in dsa_cudnn_kernels.py (_indexer_topk_bshd ~L1400, and the _indexer_topk_multi_packed_cp_thd external branch) skip the _topk_in_bounds validity mask that the internal path applies at the end (~L1432-1443); the multi-packed-CP branch additionally skips the internal wrapper's local_seq_lens column trimming and runs select_dsa_topk over the full cuDNN scores width. Correctness then rests entirely on "the cuDNN scorer emits -inf for every out-of-bounds / non-causal column" — the fact that the internal path needed local_seq_lens + _topk_in_bounds suggests that isn't an unconditional contract. If some cuDNN version leaves finite garbage in padding columns, the external selector picks illegal key indices and sparse attention silently reads cross-sequence/future KV. Suggest keeping one _topk_in_bounds pass before the external early return — it's idempotent on already -1 slots and cheap.

2. [Risk — low/medium] The packed_thd and cp_size==1 and sq==skv branch of attention_rows_nonempty relies on a data-side invariant

dsa.py:2156-2172 asserts every row is non-empty because each packed row contains its own KV position. If the packed buffer has trailing pad rows not marked by real_token_mask_q (query_valid_rows is None but cu_seqlens_q[-1] < total rows), those rows can have empty varlen windows while the flag is True, so FusedSparseAttentionFunc.backward skips the nonzero row compaction that protected them and feeds topk_length==0 rows to the cuDNN backward wrapper (potential NaN grads). If the data pipeline guarantees total thd rows == cu_seqlens[-1], fine — but worth an assertion or a comment stating the invariant.

3. [Risk — low] External top-k + indexer loss silently degrades to the O(sq·sk) dense reference path

run_fused_qk_topk_with_loss returns None and the fully-fused path refuses when loss_coeff > 0 with an external backend; only a debug-level _log_declined_hook fires. Enabling both in training silently materializes the full [b, sq, sk] scores — a big memory/speed cliff on long sequences. Suggest a one-time warning on first trigger.

4. [Nit] Inconsistent predicates in _indexer_topk_from_score_chunks

L659 gates the offset on uses_external_topk(topk_config) while L703 selects the branch on topk_config is not None. Equivalent today (callers only pass a config when external), but a future backend=None config would score with the wrong top-left causal offset before select_dsa_topk raises. Suggest using uses_external_topk in both places.

5. [Nit] Naive-path index dtype flips between int64 and int32 depending on config

dsa.py:723-735: the external branch returns int32 from select_dsa_topk, the original returns int64 from torch.topk. Current consumers tolerate both, but any new direct torch.gather(..., index=topk_indices) consumer would only break when the external backend is enabled. Worth noting in the fused_qk_topk_naive docstring.

Test coverage is strong (tie policies, legacy-cuDNN fallback, TP-local slice fallback, skip-layer reuse, backward compaction skip, monkeypatched "internal kernel must not run" assertions). The one assumption not defended across cuDNN versions is finding 1.

Signed-off-by: Ziang Li <ziangli@umich.edu>
Signed-off-by: Ziang Li <ziangli@umich.edu>
Signed-off-by: Ziang Li <ziangli@umich.edu>
Signed-off-by: Ziang Li <ziangli@umich.edu>
@Zhichenzzz
Zhichenzzz merged commit fd15ee2 into radixark:miles-main Oct 2, 2026
HJSang added a commit that referenced this pull request Oct 9, 2026
Re-based directly on miles-main (no longer stacked on GDN2, which was
closed as unadopted by any open-source model). Same content as the
original port, re-derived from a fresh cherry-pick of upstream 788e9e1
so this PR's diff only carries KDA, not GDN2.

Adds experimental_attention_variant="kda": a channel-wise Gated DeltaNet
variant with direct Q/K/V/F/G projections and a separate beta projection,
backed by fla.ops.kda.chunk_kda. Also brings in the generic primitives this
commit packages alongside KDA: MLA output gating (attention_output_gate /
gated_attention_proj_granularity), a HybridModel-aware qk_clip traversal,
and a MoE router metric-indexing refactor.

kda.py itself needed no hand-adaptation: it was already authored upstream
against the same headwise/chunkwise-CP, selective-recompute base class our
common.py/gdn.py carry, so it applies as a clean add.

Kept the earlier decision not to eagerly normalize
experimental_attention_variant from "gated_delta_net" to "gdn" in
__post_init__ (re-introduced by this upstream commit): our fork's
dsv4_hybrid/gated_delta_net validation checks still key off the literal
"gated_delta_net" string, so mutating it before those checks run would
silently disable them. is_gated_delta_net_variant (non-mutating,
canonically defined in transformer_config.py per #102/#108) is used
everywhere a GDN/KDA family check is needed instead.

Adopted upstream's `not self.is_hybrid_model` condition in place of a
narrower "only gated_delta_net requires linear_attention_freq" check for
the same requirement, since it is the more general form already present
in this file.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UawmJvYe7WkXApRw26ZFMd
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