Skip to content

Commit bbd801c

Browse files
authored
Merge branch 'dev' into codex/ci-pr-critical-path
2 parents ad26330 + e34b4c0 commit bbd801c

21 files changed

Lines changed: 941 additions & 371 deletions

File tree

Justfile

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -875,8 +875,11 @@ sync-deps:
875875
# the toolkit is installed AND an NVIDIA GPU is present. Pure Rust users
876876
# and machines without a GPU skip this -- mirrors `pecos python build`.
877877
if {{pecos}} cuda check -q 2>/dev/null && nvidia-smi -L 2>/dev/null | grep -q "^GPU "; then
878-
echo "CUDA toolkit + NVIDIA GPU detected -- including CUDA Python packages"
879-
SYNC_ARGS+=(--group cuda)
878+
# Pick the cuda group matching the CUDA major (default cuda13).
879+
CUDA_GROUP=cuda13
880+
if nvcc --version 2>/dev/null | grep -qE "release 12[.,]"; then CUDA_GROUP=cuda12; fi
881+
echo "CUDA toolkit + NVIDIA GPU detected -- including CUDA Python packages ($CUDA_GROUP)"
882+
SYNC_ARGS+=(--group "$CUDA_GROUP")
880883
fi
881884
uv sync "${SYNC_ARGS[@]}"
882885

crates/pecos-cli/src/cli/cuda_cmd.rs

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -218,7 +218,8 @@ fn run_validate(path: Option<String>) -> Result<()> {
218218
}
219219

220220
/// CLI entry point for `pecos cuda setup-python`. Validates the toolkit is
221-
/// present, then runs `uv sync --locked --group cuda` and prints next-step hints.
221+
/// present, then runs `uv sync --locked --group <cuda12|cuda13>` (matching the
222+
/// detected CUDA major) and prints next-step hints.
222223
fn run_setup_python() -> Result<()> {
223224
if find_cuda().is_none() {
224225
eprintln!("Error: CUDA toolkit not found.");
@@ -239,17 +240,27 @@ fn run_setup_python() -> Result<()> {
239240
Ok(())
240241
}
241242

242-
/// Run `uv sync --locked --group cuda` to install Python CUDA packages.
243+
/// Pick the CUDA-major dependency group (`cuda12` / `cuda13`) for the detected
244+
/// toolkit, defaulting to `cuda13` (the recommended, latest path).
245+
pub(super) fn cuda_python_group() -> &'static str {
246+
let is_cuda12 = find_cuda()
247+
.and_then(|path| get_cuda_version(&path).ok())
248+
.is_some_and(|version| version.split('.').next() == Some("12"));
249+
if is_cuda12 { "cuda12" } else { "cuda13" }
250+
}
251+
252+
/// Run `uv sync --locked --group <cuda12|cuda13>` to install Python CUDA packages.
243253
///
244254
/// Reusable from other CLI commands (e.g. `pecos setup`) once they've already
245255
/// confirmed the user wants this. Does NOT validate toolkit presence -- caller
246256
/// is responsible for that check.
247257
pub(super) fn install_cuda_python_packages() -> Result<()> {
248-
println!("Installing CUDA Python packages (cupy, cuquantum, pytket-cutensornet)...");
258+
let group = cuda_python_group();
259+
println!("Installing CUDA Python packages (cupy, cuquantum, pytket-cutensornet) [{group}]...");
249260
println!();
250261

251262
let status = Command::new("uv")
252-
.args(["sync", "--locked", "--group", "cuda"])
263+
.args(["sync", "--locked", "--group", group])
253264
.status();
254265

255266
match status {
@@ -263,7 +274,7 @@ pub(super) fn install_cuda_python_packages() -> Result<()> {
263274
eprintln!("Failed to install CUDA Python packages.");
264275
eprintln!();
265276
eprintln!("You may need to install manually:");
266-
eprintln!(" uv sync --locked --group cuda");
277+
eprintln!(" uv sync --locked --group {group}");
267278
Err(Error::Cuda(
268279
"Failed to install CUDA Python packages".to_string(),
269280
))

crates/pecos-cli/src/cli/setup_cmd.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,7 @@ fn print_status_summary(skip_llvm: bool, skip_cuda: bool, skip_cmake: bool) {
131131
if super::cuda_cmd::cuda_python_packages_installed() {
132132
println!(" cupy: installed (CUDA Python packages synced)");
133133
} else {
134-
println!(" cupy: not installed (~500 MB via `uv sync --locked --group cuda`)");
134+
println!(" cupy: not installed (~500 MB via `pecos cuda setup-python`)");
135135
}
136136
}
137137

@@ -353,7 +353,7 @@ fn setup_cuda_python(mode: PromptMode) -> Result<()> {
353353
}
354354

355355
if confirm(
356-
"Install CUDA Python packages? (cupy, cuquantum, pytket-cutensornet via `uv sync --locked --group cuda`)",
356+
"Install CUDA Python packages? (cupy, cuquantum, pytket-cutensornet via `pecos cuda setup-python`)",
357357
true, // default yes when CUDA toolkit + NVIDIA GPU are present
358358
mode,
359359
) {

docs/development/DEVELOPMENT.md

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -62,10 +62,12 @@ For developers who want to contribute or modify PECOS:
6262
|---------------|-------------------------------------------------------------|-------------------------------|
6363
| `examples` | Running notebooks under `examples/` or DataFrame benchmarks | `uv sync --group examples` |
6464
| `numpy-compat`| Verifying older NumPy/SciPy minimums | `uv sync --group numpy-compat`|
65-
| `cuda` | Building/running GPU simulators (requires CUDA toolkit) | `uv sync --group cuda` |
65+
| `cuda13` | GPU simulators on CUDA 13 (Turing/CC 7.5+; requires CUDA toolkit) | `uv sync --group cuda13` |
66+
| `cuda12` | GPU simulators on CUDA 12 (incl. V100/Volta) | `uv sync --group cuda12` |
6667

6768
Combine groups with multiple `--group` flags
68-
(e.g. `uv sync --group examples --group cuda`).
69+
(e.g. `uv sync --group examples --group cuda13`). Pick one CUDA major --
70+
`cuda12` and `cuda13` are mutually exclusive.
6971

7072
6. **LLVM 14 Setup (Required for LLVM IR/QIS Support)**
7173

docs/user-guide/cuda-setup.md

Lines changed: 48 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,10 @@ Both approaches require:
3131

3232
### Hardware Requirements
3333

34-
- **NVIDIA GPU** with Compute Capability 7.0 or higher
34+
- **NVIDIA GPU** with Compute Capability **7.5 or higher** (Turing and newer) for the
35+
default CUDA 13 path. Current cuStateVec (cuQuantum >= 25.09) and CUDA 13 dropped
36+
Volta, so **V100 / CC 7.0** is supported only via the CUDA 12 path with an older,
37+
Volta-capable cuQuantum pinned `cuquantum-python-cu12>=25.3,<25.9` (see below).
3538
- To check your GPU: `nvidia-smi`
3639
- To check compute capability: Visit [NVIDIA's GPU Compute Capability List](https://developer.nvidia.com/cuda-gpus)
3740

@@ -119,22 +122,27 @@ If `nvcc` is not found, ensure CUDA's bin directory is in your PATH.
119122
PECOS uses `uv` as the package manager. Install the CUDA-related Python packages:
120123

121124
```bash
122-
# Install CUDA 13 packages
123-
uv pip install cupy-cuda13x>=13.0.0
124-
uv pip install cuquantum-python-cu13>=25.3.0
125-
uv pip install pytket-cutensornet>=0.12.0
125+
# CUDA 13 (Turing / CC 7.5+ GPUs):
126+
uv pip install "cupy-cuda13x>=13.0.0" "cuquantum-python-cu13>=25.9.0" "pytket-cutensornet>=0.12.0"
127+
128+
# CUDA 12:
129+
uv pip install "cupy-cuda12x>=13.0.0" "cuquantum-python-cu12>=25.3.0" "pytket-cutensornet>=0.12.0"
126130
```
127131

128-
**Important**: Use packages matching your CUDA version:
129-
- For CUDA 13: `cupy-cuda13x`, `cuquantum-python-cu13`
130-
- For CUDA 12: `cupy-cuda12x`, `cuquantum-python-cu12`
132+
**Important**:
133+
- Install packages matching your CUDA major (CUDA 13 -> `*-cu13` / `*-cuda13x`; CUDA 12 -> `*-cu12` / `*-cuda12x`). Do **not** install both.
134+
- PECOS requires the **`cuquantum.bindings` API (cuQuantum >= 25.03)**; older cuQuantum is rejected with a clear error when you use `CuStateVec`. The lowest CUDA 13 wheel is `25.9.0`.
135+
- **V100 / Volta (CC 7.0)**: pin `cuquantum-python-cu12>=25.3,<25.9` (cuStateVec dropped Volta at 25.09).
131136

132137
### Step 5: Install PECOS with CUDA Support
133138

134139
#### Option A: Install from PyPI with CUDA extras
135140

136141
```bash
137-
uv pip install quantum-pecos[cuda]
142+
# CUDA 13 (recommended); use [cuda12] for CUDA 12. These pull the Python cuStateVec
143+
# / MPS stack (CuPy + cuquantum-python). The Rust GPU backend is a separate install
144+
# (see "Rust cuQuantum Bindings Setup" below): pip install pecos-rslib-cuda
145+
uv pip install "quantum-pecos[cuda13]"
138146
```
139147

140148
#### Option B: Install from source (for development)
@@ -148,8 +156,8 @@ just build-cuda # Build with CUDA support
148156
just devc # Full dev cycle: clean + build-cuda + test
149157
just devcl # Dev cycle + linting
150158

151-
# Option 2: Manual installation
152-
uv pip install -e "./python/quantum-pecos[all,cuda]"
159+
# Option 2: Manual installation (use [all,cuda12] for CUDA 12)
160+
uv pip install -e "./python/quantum-pecos[all,cuda13]"
153161
```
154162

155163
## Verification
@@ -203,14 +211,15 @@ uv run pytest python/quantum-pecos/tests/pecos/integration/state_sim_tests/test_
203211

204212
## Package Versions
205213

206-
Current recommended versions (as of 2025):
214+
Minimum versions (CUDA 13 path shown; for CUDA 12 use the `-cu12` / `-cuda12x` equivalents):
215+
216+
| Package | Minimum | Purpose |
217+
|---------|---------|---------|
218+
| cupy-cuda13x | 13.0.0 | NumPy/SciPy for GPU |
219+
| cuquantum-python-cu13 | 25.9.0 | cuQuantum Python API (the `cuquantum.bindings >= 25.03` surface; lowest cu13 wheel is 25.9.0) |
220+
| pytket-cutensornet | 0.12.0 | MPS simulator |
207221

208-
| Package | Version | Release Date | Purpose |
209-
|---------|---------|--------------|---------|
210-
| cupy-cuda13x | 13.6.0+ | Aug 2025 | NumPy/SciPy for GPU |
211-
| cuquantum-python-cu13 | 25.9.0+ | Sept 2025 | cuQuantum Python API |
212-
| custatevec-cu13 | 1.10.0+ | Sept 2025 | State vector operations (included in cuquantum) |
213-
| pytket-cutensornet | 0.12.0+ | 2025 | MPS simulator |
222+
For CUDA 12 the floor is `cuquantum-python-cu12>=25.3.0`; **V100/Volta** needs `>=25.3,<25.9`.
214223

215224
## Troubleshooting
216225

@@ -226,20 +235,27 @@ export LD_LIBRARY_PATH=/usr/local/cuda-13/lib64:$LD_LIBRARY_PATH
226235
source ~/.bashrc
227236
```
228237

229-
#### 2. `CuStateVec is None` or tests are skipped
238+
#### 2. `CuStateVec` unavailable / constructing it raises
230239

231-
**Solution**: Python packages not properly installed or CUDA Toolkit version mismatch.
240+
`import pecos` always works, but constructing `CuStateVec` (or
241+
`QuantumSimulator("CuStateVec")`) without CuPy and a bindings-era cuQuantum raises
242+
an actionable error naming what to install/upgrade. PECOS requires the
243+
`cuquantum.bindings` API (cuQuantum >= 25.03); the legacy top-level
244+
`cuquantum.custatevec` is not used.
232245

233246
```bash
234-
# Verify installations
235-
python -c "import cupy; print(cupy.__version__)"
236-
python -c "from cuquantum import custatevec; print('OK')"
247+
# Ask PECOS directly (no GPU needed):
248+
python -c "from pecos.simulators.custatevec._cuquantum_compat import custatevec_available, custatevec_unavailable_reason; print(custatevec_available(), '|', custatevec_unavailable_reason())"
237249

238-
# Reinstall if needed
239-
uv pip uninstall cupy-cuda13x cuquantum-python-cu13
240-
uv pip install cupy-cuda13x cuquantum-python-cu13
250+
# Or check the underlying packages:
251+
python -c "import cupy; print(cupy.__version__)"
252+
python -c "from cuquantum.bindings import custatevec; print('OK')"
241253
```
242254

255+
If the reason says cuQuantum "predates the cuquantum.bindings API", upgrade to
256+
`cuquantum-python-cu13>=25.9.0` (CUDA 13) or `cuquantum-python-cu12>=25.3.0`
257+
(CUDA 12; V100/Volta `>=25.3,<25.9`).
258+
243259
#### 3. CUDA version mismatch errors
244260

245261
**Problem**: Mixing CUDA 12 and CUDA 13 packages.
@@ -281,7 +297,7 @@ If you encounter issues:
281297
1. Check [NVIDIA cuQuantum Documentation](https://docs.nvidia.com/cuda/cuquantum/latest/)
282298
2. Check [pytket-cutensornet GitHub Issues](https://github.com/Quantinuum/pytket-cutensornet/issues)
283299
3. Check [PECOS GitHub Issues](https://github.com/PECOS-packages/PECOS/issues)
284-
4. Verify your GPU compute capability is 7.0 or higher
300+
4. Verify your GPU compute capability is 7.5+ (CUDA 13) or 7.0 (V100 via the capped CUDA 12 path)
285301

286302
## Alternative: Using Conda
287303

@@ -451,12 +467,12 @@ To use GPU simulators in PECOS:
451467

452468
### Option A: Python cuQuantum Bindings (Easier Setup)
453469

454-
1. **Verify NVIDIA GPU** (Compute Capability 7.0+)
455-
2. **Install CUDA Toolkit 13** (system-level)
456-
3. **Install Python packages**: `cupy-cuda13x`, `cuquantum-python-cu13`, `pytket-cutensornet`
457-
4. **Install PECOS with `[cuda]` extras**:
470+
1. **Verify NVIDIA GPU** (Compute Capability 7.5+ for CUDA 13; V100/CC 7.0 only via the capped CUDA 12 path)
471+
2. **Install CUDA Toolkit 13** (system-level; or CUDA 12)
472+
3. **Install Python packages**: `cupy-cuda13x`, `cuquantum-python-cu13`, `pytket-cutensornet` (or the `-cu12`/`-cuda12x` equivalents)
473+
4. **Install PECOS with the matching CUDA extra**:
458474
```bash
459-
uv pip install quantum-pecos[cuda]
475+
uv pip install "quantum-pecos[cuda13]" # or [cuda12] for CUDA 12
460476
# or for development:
461477
just build-cuda
462478
```

docs/user-guide/qec-guppy.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -389,7 +389,7 @@ results = (
389389
.quantum(state_vector())
390390
.noise(depolarizing_noise().with_uniform_probability(0.001))
391391
.seed(42)
392-
.run(1000)
392+
.run(100)
393393
)
394394
```
395395

docs/user-guide/simulators.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -254,7 +254,8 @@ results = sim(Qasm(circuit)).quantum(CuStateVec).run(100)
254254
- cuQuantum and cupy packages
255255

256256
```bash
257-
pip install quantum-pecos[cuda]
257+
# CUDA 13 (recommended); use [cuda12] for CUDA 12 / V100. Do not install both.
258+
pip install "quantum-pecos[cuda13]"
258259
```
259260

260261
See [CUDA Setup Guide](cuda-setup.md) for detailed installation instructions.

pyproject.toml

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,11 @@ requires-python = ">=3.10"
77
dependencies = []
88

99
[project.optional-dependencies]
10-
# Keep this in sync with the cuda dependency group below. The extra supports
11-
# `uv sync --extra cuda`; the group supports `uv run --group cuda ...`.
12-
cuda = ["quantum-pecos[cuda]==0.8.0.dev8"]
10+
# Keep these in sync with the cuda dependency groups below. The extras support
11+
# `uv sync --extra cuda13`; the groups support `uv run --group cuda13 ...`.
12+
# Pick the extra matching your CUDA major -- do not install both.
13+
cuda13 = ["quantum-pecos[cuda13]==0.8.0.dev8"]
14+
cuda12 = ["quantum-pecos[cuda12]==0.8.0.dev8"]
1315

1416
[tool.uv.workspace]
1517
members = [
@@ -67,12 +69,22 @@ numpy-compat = [ # NumPy/SciPy compatibility tests - verify compatibility with s
6769
"numpy>=1.15.0",
6870
"scipy>=1.1.0",
6971
]
70-
cuda = [ # CUDA Python packages for GPU-accelerated simulations (requires CUDA toolkit)
71-
"quantum-pecos[cuda]==0.8.0.dev8",
72+
cuda13 = [ # CUDA 13 Python packages for GPU-accelerated simulations (requires CUDA toolkit)
73+
"quantum-pecos[cuda13]==0.8.0.dev8",
74+
]
75+
cuda12 = [ # CUDA 12 Python packages for GPU-accelerated simulations
76+
"quantum-pecos[cuda12]==0.8.0.dev8",
7277
]
7378

7479
[tool.uv]
7580
default-groups = ["dev", "test"]
81+
# CUDA 12 and CUDA 13 stacks are mutually exclusive (separate cupy/cuquantum
82+
# wheels per CUDA major). Declare them conflicting so the lock never co-resolves
83+
# both -- co-resolution downgrades cu12 to satisfy cu13.
84+
conflicts = [
85+
[{ extra = "cuda12" }, { extra = "cuda13" }],
86+
[{ group = "cuda12" }, { group = "cuda13" }],
87+
]
7688
# Prevent uv from caching native workspace wheels - always use freshly built versions.
7789
# This fixes stale code issues when uv sync/run reinstalls cached old wheels.
7890
# See: https://github.com/astral-sh/uv/issues/11390

python/quantum-pecos/README.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -178,7 +178,8 @@ Certain simulators from `pecos.simulators` require external packages that are no
178178

179179
**Quick install** (after installing CUDA Toolkit):
180180
```bash
181-
uv pip install quantum-pecos[cuda]
181+
# CUDA 13 (recommended); use [cuda12] for CUDA 12 / V100. Do not install both.
182+
uv pip install "quantum-pecos[cuda13]"
182183

183184
# For development with CUDA support:
184185
make build-cuda # Build with CUDA

python/quantum-pecos/pyproject.toml

Lines changed: 22 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -70,26 +70,37 @@ all = [
7070
"quantum-pecos[stim]",
7171
]
7272

73-
# CUDA dependencies. See docs/user-guide/cuda-setup.md for detailed installation instructions
74-
# Requires CUDA Toolkit 13 or 12 installed at system level first.
75-
# For Ubuntu/Pop!_OS: sudo apt install cuda-toolkit-13
76-
# These packages work with uv/pip once CUDA toolkit is installed.
77-
# Note: CUDA packages require Python 3.11+ due to cuquantum-python-cu13 requirements
78-
cuda = [
79-
"pecos-rslib-cuda==0.8.0.dev8",
80-
"cupy-cuda13x>=13.0.0; python_version >= '3.11'", # Use cupy-cuda12x for CUDA 12
81-
"cuquantum-python-cu13>=25.3.0; python_version >= '3.11'", # Use cuquantum-python-cu12 for CUDA 12
73+
# CUDA dependencies for the Python cuStateVec / MPS backends. See
74+
# docs/user-guide/cuda-setup.md. Requires a system CUDA toolkit and a matching NVIDIA
75+
# driver. Pick the extra matching your CUDA major -- do NOT install both (mixing
76+
# cupy-cudaXXx wheels is unsupported). Python 3.11+ required.
77+
# uv pip install -e .[cuda13] # CUDA 13, Turing/CC 7.5+ GPUs (recommended)
78+
# uv pip install -e .[cuda12] # CUDA 12
79+
# V100/Volta (CC 7.0): cuStateVec dropped Volta at 25.09, so pin
80+
# cuquantum-python-cu12>=25.3,<25.9 manually (see cuda-setup.md).
81+
# The Rust GPU backend (CudaStateVec/CudaStabilizer) is a separate install:
82+
# pip install pecos-rslib-cuda
83+
cuda13 = [
84+
"cupy-cuda13x>=13.0.0; python_version >= '3.11'",
85+
"cuquantum-python-cu13>=25.9.0; python_version >= '3.11'",
86+
"pytket-cutensornet>=0.12.0; python_version >= '3.11'",
87+
]
88+
cuda12 = [
89+
"cupy-cuda12x>=13.0.0; python_version >= '3.11'",
90+
"cuquantum-python-cu12>=25.3.0; python_version >= '3.11'",
8291
"pytket-cutensornet>=0.12.0; python_version >= '3.11'",
8392
]
84-
# Install with: uv pip install -e .[cuda]
8593

8694
# Dependency groups are defined at workspace root (pyproject.toml)
8795
# Package-specific groups can be added here if needed
8896

97+
[tool.uv]
98+
# CUDA 12 and CUDA 13 use different, mutually exclusive cupy/cuquantum wheels.
99+
conflicts = [[{ extra = "cuda12" }, { extra = "cuda13" }]]
100+
89101
[tool.uv.sources]
90102
pecos-rslib = { workspace = true }
91103
pecos-rslib-llvm = { workspace = true }
92-
pecos-rslib-cuda = { workspace = true }
93104

94105
[tool.hatch.build.targets.wheel]
95106
packages = ["src/pecos"]

0 commit comments

Comments
 (0)