Skip to content

[QDP] Builder backends name GPUs only; every encode result is a QdpTensor - #1505

Merged
400Ping merged 3 commits into
apache:mainfrom
400Ping:qdp-gpu-backend-selectors
Oct 30, 2026
Merged

400Ping merged 3 commits into
apache:mainfrom
400Ping:qdp-gpu-backend-selectors

Conversation

@400Ping

@400Ping 400Ping commented Oct 11, 2026 •

Copy link
Copy Markdown
Member

Related Issues

Related: #1177, #1189 (origin of the PyTorch reference), #1155, #1292 (AMD route), #1320, #1323 (CPU fallback being removed), #1414 (_qdp importable ≠ GPU usable), #1467, #1331 (reference the old names / removed helper), #1477 / #1483 (overlapping files, see below).

Changes

  • Bug fix
  • New feature
  • Refactoring
  • Documentation
  • Test
  • CI/CD pipeline
  • Other

Why

QDP is GPU-only, but the Python builders made it look like it was not:

  • QuantumDataLoader / QdpBenchmark took .backend("pytorch"), which ran the pure-PyTorch reference from torch_ref.py — on CPU when no CUDA device was found. The reference was added in Add pure-PyTorch reference implementations #1189 as a benchmark baseline ("to compare with current impl"), not as a backend, yet it was listed next to the real one and people concluded "QDP runs on CPU with the PyTorch backend".
  • The same backend was called "rust" on the builders and "cuda" on QdpEngine.
  • QuantumDataLoader.backend("auto") silently fell back to PyTorch (and therefore CPU) when _qdp was missing, contradicting the docs ("PyTorch is not used as an automatic fallback").
  • The builders could not use the AMD route at all, although QdpEngine(backend="amd") exists ([Feature][QDP] Add AMD GPU support via Triton backend #1155).
  • Backend / BACKEND / force_backend and the QdpTensor facade were exported but never used by any production code; Backend.PYTORCH reinforced the misconception.
  • The CUDA route returned the native _qdp tensor while the AMD route returned a torch.Tensor, so switching backends changed the result type.

How

Backend selection (loader.py, api.py)

  • .backend() on both builders takes "cuda" (default) or "amd"; the loader also takes "auto".
  • "auto" picks "cuda" when _qdp.cuda_available() is true, else "amd" when is_triton_amd_available() is true, else raises RuntimeError. No CPU fallback.
  • "rust" and "pytorch" are rejected with ValueError. torch_ref.py is unchanged and still used directly by the benchmark scripts and parity tests.
  • New AMD paths: QuantumDataLoader._create_amd_iterator (synthetic and .npy / .pt / .pth sources, batches built on CPU and moved by the engine) and QdpBenchmark._run_throughput_amd (Python loop over TritonAmdEngine.encode).
  • QdpBenchmark defaults to f32, matching QdpEngine and the native synthetic loader; the AMD loader mirrors the native precision rules (synthetic f32, files f64, .dtype() honoured).

Result type (backend.py, loader.py, tensor.py)

  • QdpEngine.encode() and every loader backend return QdpTensor; .value is the backend-native object (_qdp.QuantumTensor on CUDA, torch.Tensor on AMD), .backend is "cuda" or "amd". torch.from_dlpack(qt) and qt.to_torch() work on both.
  • QdpTensor.__dlpack__ forwards extra DLPack keyword arguments (max_version, …).

Removed / renamed

Docs

  • python-api.md: backend model rewritten around "cuda" / "amd" / "auto", result type and dtype() documented, PyTorch reference no longer presented as an encoder.
  • AMD encoding support corrected to all six methods in getting-started.md, concepts.md, python-api.md (stale since [QDP] Close AMD-vs-CUDA encoder parity: add iqp, iqp-z, phase #1292); TRITON_AMD_BACKEND.md no longer mentions the non-existent QuantumTensorWrapper.
  • qumat_qdp._backend removed from docs/api/qumat_qdp.yml.

Tests

  • test_fallback.py → test_backend_selection.py: selector validation and auto routing, runnable without a GPU.
  • New qdp/qdp-python/tests/test_amd_builders.py (@pytest.mark.rocm): AMD loader synthetic and file sources, precision, auto on a ROCm host, benchmark throughput/latency — real TritonAmdEngine, no fakes.
  • Routing and Triton router tests updated to the QdpTensor contract.

Breaking changes

  • .backend("rust") → .backend("cuda"); .backend("pytorch") removed.
  • QuantumDataLoader.backend("auto") raises instead of falling back to PyTorch.
  • Backend, BACKEND, force_backend removed from qumat_qdp.
  • RustQdpEngine → NativeQdpEngine; is_cuda_available → is_native_cuda_available.
  • QdpEngine.encode() and QuantumDataLoader return QdpTensor on every backend (use .value for the native object).
  • QdpBenchmark default dtype is f32.
  • qumat_qdp._backend → qumat_qdp._native.

Checklist

  • Added or updated unit tests for all changes
  • Added or updated documentation for all changes

…nsor

Signed-off-by: 400Ping <jiekaichang@apache.org>

@ryankert01 ryankert01 left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

lg, I thought it probably be okay.

Signed-off-by: Jie-Kai Chang <jiekaichang@apache.org>
@400Ping
400Ping merged commit fce9be4 into apache:main Oct 30, 2026
6 of 8 checks passed
@400Ping 400Ping mentioned this pull request Nov 2, 2026
2 of 3 tasks
400Ping added a commit that referenced this pull request Nov 2, 2026
Three workflows went red on main after #1505 merged:

- Wheel Build: the wheel smoke test still imported `qumat_qdp._backend`,
  which #1505 removed in favour of `qumat_qdp._native`.
- Python Testing: #1551 landed `testing/qdp_python/test_engine_init.py`
  after #1505 branched, importing `is_cuda_available`, which #1505 renamed
  to `is_native_cuda_available`.
- Pre-commit (ty): `test_triton_amd_backend.py` asserted `.shape` on a
  `QdpTensor`, which has no such attribute; and the `type: ignore[misc]` on
  `_QdpDataset` in `loader.py` became unused after the refactor.

Signed-off-by: Jie-Kai Chang <jiekaichang@apache.org>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants