Skip to content

DSA: probe Paddle, not sys.modules["torch"], for framework metadata - #13

Merged
sneaxiy merged 1 commit into
PFCCLab:paddle/v1.28.0from
ForFishes:paddle/v1.28.0-fix-framework-probe
Sep 4, 2026
Merged

DSA: probe Paddle, not sys.modules["torch"], for framework metadata#13
sneaxiy merged 1 commit into
PFCCLab:paddle/v1.28.0from
ForFishes:paddle/v1.28.0-fix-framework-probe

Conversation

@ForFishes

Copy link
Copy Markdown

Follow-up to #12. 1.28.0's framework-neutral metadata refactor (python/cudnn/tensor_adapter.py, plus the _torch() helper in python/cudnn/api_base.py) identifies the framework with sys.modules.get("torch"). That probe does not work on this branch, and the failure is not subtle: both DSA indexer backward wrappers are unusable.

Why the probe fails here

paddle.enable_compat(scope={"cudnn"}) rewrites only the module-level import torch of the modules it loads — it never registers the shim in sys.modules. Meanwhile a real PyTorch is routinely installed alongside Paddle in the same environment (in ours: PyTorch 2.12 + Paddle 3.4). So sys.modules["torch"] resolves to real PyTorch, which describes neither Paddle's dtypes nor its devices, strides or current stream.

Note that a function-level import torch does not help either, for the same reason — the fix has to name Paddle explicitly.

Symptoms fixed

  • APIBase._check_dtype took its "not a dtype" branch for every Paddle dtype, because isinstance(paddle.bfloat16, torch.dtype) is False for real torch:

    ValueError: Expected dtype to be a torch.dtype or list, got <class 'paddle.dtype'>
      at python/cudnn/api_base.py, from IndexerBackward.check_support()
    

    This fires in check_support(), i.e. before compile()/execute(), so indexer_backward_wrapper and dense_indexer_backward_wrapper both fail unconditionally. In our downstream test suite that was ~60 failing DSA/indexer tests.

  • tensor_adapter.detect_framework returned "unknown" for Paddle tensors. Two silent downgrades follow: default_stream handed back the CUDA legacy default stream instead of Paddle's current stream (a correctness hazard for anything overlapping with framework work), and get_strides fell through to a C-contiguous guess instead of reading the real strides.

  • _raw_stream / _get_default_stream read .cuda_stream off the stream object. Paddle exposes the raw handle as stream_base.raw_stream — the same handle deepseek_sparse_attention/utils/runtime.resolve_stream already uses, so the two now agree.

  • TensorDesc.is_contiguous dereferenced torch.contiguous_format unconditionally; Paddle does not define it. The formats are now looked up defensively so the default (memory_format=None) path cannot break.

Verification

Downstream (PaddleFleet DSA/indexer/CSA, single card, B30Z sm_103), 22 test files:

  • before this patch: test_cudnn_dsa_indexer_bwd 16 failed / 19 passed, test_hybrid_mla_warmup_kl_cudnn 28 failed / 5 passed, test_mqa_latent_attention 8 failed, test_indexer_loss_overlap 5 failed, test_block_sparse_dsa_gradcheck 13 failed, test_hysparse_mqa_gather_dsa 6 failed, test_cudnn_dsa_indexer_docmask 3 failed;
  • after: all of the above pass. The one remaining failure in that suite is a stale negative-control assertion that fails identically on paddle/v1.27.0, so it is unrelated to 1.28.0.

We also added a host-side regression test downstream that asserts the probe resolves to Paddle, that _check_dtype accepts Paddle dtypes in both scalar and list form, that Paddle tensors are recognised by the adapter, that strides are read rather than guessed, and that default_stream matches Paddle's current stream. Four of its seven cases fail without this patch.

Perf on the same setup is unaffected by this patch; for the record, paddle/v1.28.0 is a solid win over paddle/v1.27.0 on the sparse DSA indexer backward at our production shape (b=1, s_q=s_k=8192, h=64, d=128, topk=2048): 4.757 ms -> 3.095 ms end to end.

pre-commit (black, line length 160) is clean.

1.28.0's framework-neutral refactor reads dtypes, devices, strides and the
current stream through ``sys.modules.get("torch")``. That probe is wrong on this
branch: ``paddle.enable_compat(scope={"cudnn"})`` rewrites only the module-level
``import torch`` of the modules it loads and never puts the shim in
``sys.modules``, while a real PyTorch is routinely installed alongside Paddle in
the same environment -- so the probe returns real torch and every Paddle tensor
is misclassified.

Symptoms this fixes, all of them on the DSA path:

* ``APIBase._check_dtype`` took the "not a dtype" branch for every Paddle dtype
  (``isinstance(paddle.bfloat16, torch.dtype)`` is False) and raised
  ``ValueError: Expected dtype to be a torch.dtype or list, got
  <class 'paddle.dtype'>`` from ``check_support()``. Both indexer backward
  wrappers were unusable; ~60 PaddleFleet DSA/indexer tests failed.
* ``tensor_adapter.detect_framework`` returned "unknown" for Paddle tensors, so
  ``default_stream`` handed back the CUDA legacy default stream instead of
  Paddle's current stream, and ``get_strides`` fell through to a C-contiguous
  guess.
* ``_raw_stream``/``_get_default_stream`` read ``.cuda_stream`` off the Stream
  object; Paddle exposes the raw handle as ``stream_base.raw_stream`` (the same
  handle ``deepseek_sparse_attention/utils/runtime.resolve_stream`` uses).
* ``TensorDesc.is_contiguous`` dereferenced ``torch.contiguous_format``
  unconditionally, which Paddle does not define; look the formats up
  defensively so the default (``memory_format=None``) path cannot break.
@ForFishes
ForFishes force-pushed the paddle/v1.28.0-fix-framework-probe branch from 0f2cada to 267d853 Compare September 3, 2026 17:08
@sneaxiy
sneaxiy merged commit 6956336 into PFCCLab:paddle/v1.28.0 Sep 4, 2026
1 of 2 checks passed
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