Skip to content

Always build the CPU backend and the UHF builds; SBD_SKIP_BACKENDS; CPU-only analyses take no device - #93

Merged
Sophia Wen (hfwen0502) merged 7 commits into
mainfrom
build-all-backends
Nov 10, 2026
Merged

Sophia Wen (hfwen0502) merged 7 commits into
mainfrom
build-all-backends

Conversation

@hfwen0502

@hfwen0502 Sophia Wen (hfwen0502) commented Nov 9, 2026 •

Copy link
Copy Markdown
Member

Fixes #73.

Build. Every install now builds the CPU backend, the unrestricted (-D_UHF) builds of the CPU and Thrust backends, and every GPU backend the detected toolchain supports: Thrust and OpenMP offload under nvc++, OpenMP offload under amdclang++.

  • New SBD_SKIP_BACKENDS leaves GPU backends out, as a comma-separated list of gpu (alias gpu_thrust) and gpu_omp_offload. It refuses cpu and unknown names.
  • A summary at the end of the build lists each backend, and for a GPU backend it did not build, why: skipped, no GPU compiler found, or NVIDIA only.
  • Why the CPU backend is always built: it is the default device, and it carries the variance evaluator the Thrust backend lacks. A build without it failed a solve with no device=, and the test suite unless SBD_TEST_DEVICE was set (SBD_TEST_DEVICE must be set to test a build without the CPU backend #73). With the UHF builds always present, a session can take restricted and unrestricted FCIDUMPs alike.
  • SBD_BUILD_BACKEND is deprecated. It still works, with a warning, and is read as a skip list: cpu skips both GPU backends, gpu the offload one, gpu_omp_offload the Thrust one; auto and all skip nothing. Each now also builds the CPU backend. SBD_BUILD_BACKEND=all no longer stops the build when no GPU compiler is found; the summary says only the CPU backend was built.
  • SBD_BUILD_UHF is no longer read; setting it warns.

CPU-only analyses take no device. sbd.analysis.variance() and caop_variance() always run upstream's evaluator on the CPU, with MPI and OpenMP, whichever device the state was solved on, and sbd.spectrum.green_function_from_coefficients() reevaluates saved coefficients on the CPU. They now use the CPU backend, except that variance, in a process that has already loaded the OpenMP-offload backend, calls the same CPU code from that module, since loading the CPU backend next to it would leave offload running on the host for the rest of the process. The device argument, which only chose between modules running the same CPU code, is removed from all three; the release note lists this under upgrade notes. green_function() still takes cpu or gpu, and refuses gpu-omp.

Error messages name only devices. When a requested backend was missing, the errors from init() and get_backend() listed the internal unrestricted builds (cpu-uhf, gpu-uhf) among the usable devices. They now list what sbd.available_backends() does. When no device was given, init() says the default cpu backend is the one missing.

Docs.

  • The README's backend section is now a feature-by-backend table: TPB, GDB, the CAOP ground state and Green's function, UHF FCIDUMPs, and variance and PT2.
  • INSTALL.md documents SBD_SKIP_BACKENDS and the deprecations, and both it and the docs front page point to the README table.
  • Runtime error messages no longer suggest SBD_BUILD_BACKEND or SBD_BUILD_UHF; a missing CPU backend now says the install is incomplete.
  • CI's docs job and tox.ini use SBD_SKIP_BACKENDS.

A test fix found along the way. The in-process CAOP tests built their config from the backend under test but solved with no device, so they used the session's default device, which depends on which test initializes the session first. Run after the spectrum tests, the Thrust-only check that t_comm_size > b_comm_size is refused ran on the CPU instead and failed. Each solve now names the backend its config came from.

Checked:

  • Each variable case prints the expected plan or error.
  • On an 8× H100 server with NVHPC:
    • each skip combination and the deprecated SBD_BUILD_BACKEND=gpu_omp_offload build exactly the expected modules;
    • SBD_TEST_DEVICE must be set to test a build without the CPU backend #73's reproducer, a build that previously had no CPU backend tested with SBD_TEST_DEVICE unset, now passes;
    • the full suite passes on the cpu, gpu and gpu-omp backends, single-process and under MPI;
    • after a gpu-omp solve, variance runs from the offload module without loading the CPU backend;
    • the CAOP and spectrum tests pass in either order.
  • On an 8× MI250X server with ROCm:
    • the default build makes the CPU and OpenMP-offload backends and reports Thrust as NVIDIA only; SBD_SKIP_BACKENDS=gpu_omp_offload builds the CPU backend alone;
    • the suite passes on the cpu and gpu-omp backends, single-process and under MPI;
    • after a gpu-omp solve, variance runs from the offload module without loading the CPU backend;
    • requesting --device gpu names only cpu and gpu-omp as usable.
  • The docs build without warnings.

🤖 Generated with Claude Code

…ENDS opts GPU out

Every install now builds the CPU backend and every GPU backend the detected toolchain
supports (Thrust and OpenMP offload under nvc++, OpenMP offload under amdclang++), and
the unrestricted (-D_UHF) builds of the CPU and Thrust backends. SBD_SKIP_BACKENDS
leaves GPU backends out: a comma-separated list of gpu (alias gpu_thrust) and
gpu_omp_offload. It refuses 'cpu' and unknown names. The build ends with a summary of
each backend, and for a GPU backend it did not build, why.

A GPU-only install failed a solve with no device= and the test suite unless
SBD_TEST_DEVICE was set (#73): the CPU backend is the default device, and carries the
variance evaluator the Thrust backend lacks. With the UHF builds always present, a
session can take restricted and unrestricted FCIDUMPs alike.

SBD_BUILD_BACKEND is deprecated: it still works, with a warning, read as a skip list
(cpu skips both GPU backends, gpu the offload one, gpu_omp_offload the Thrust one;
auto and all skip nothing). =all no longer stops the build without a GPU compiler; the
summary says only the CPU backend was built. SBD_BUILD_UHF is no longer read, and
setting it warns. Runtime messages, INSTALL.md, the READMEs, the API docs, tox.ini and
the docs workflow follow.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
variance() and caop_variance() always run upstream's evaluator on the CPU, with MPI
and OpenMP, whichever device the state was solved on. With the CPU backend now in
every install, they use it, with one exception: in a process that has already loaded
the OpenMP-offload backend, they call the same CPU code from that module instead,
since loading the CPU backend next to it would leave offload running on the host for
the rest of the process. The device argument, which chose between modules that run
the same CPU code, is removed.

The evaluator search no longer looks through loaded_backends(), so the unrestricted
builds it lists can no longer reach get_backend, and the helper that filtered them
out is gone. The selection test covers the new rule and the loaded-UHF cases; a test
checks that neither function takes device.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The README's backend table said "everything" for cpu and gpu, which hid that the
Green's function uses the GPU only for its on-the-fly Hamiltonian, and left the
variance analysis to a sentence. It is now a feature-by-backend table: TPB, GDB, the
CAOP ground state and Green's function, UHF FCIDUMPs, and energy variance and PT2,
which always run on the CPU. INSTALL.md's Verify section and the docs front page
point to it, and lose what the build change made untrue: an OpenMP-offload-only
install, and a gpu-omp row that named only GDB.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…s no device

green_function_from_coefficients() evaluates the saved block-Lanczos coefficients on
a new grid or broadening; it reads neither the Hamiltonian nor the state and runs on
the CPU. Like variance(), it no longer takes device, and uses the CPU backend.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The in-process CAOP tests built their config from the backend fixture's module but
called sbd.caop_diag_from_files without a device, so the solve used the session's
default device. That default is set by whichever test initializes the session first:
a test that runs before any use of the backend fixture leaves it at 'cpu'. Run after
test_spectrum.py, the Thrust-only check that t_comm_size > b_comm_size is refused
then solved on the CPU, which allows it, and failed. Each solve now passes the device
of the module its config came from.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The "not usable" errors from init() and get_backend() printed the internal scan,
which also holds the unrestricted builds ('cpu-uhf', 'gpu-uhf'). On an AMD host,
--device gpu answered "Usable: ['cpu', 'gpu-omp', 'cpu-uhf']", naming a value no
caller can pass. Both now list available_backends(). init() also says when the
device was not given and the default 'cpu' was the one missing.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… the build

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@hfwen0502
Sophia Wen (hfwen0502) merged commit 1ae90ca into main Nov 10, 2026
15 checks passed
@hfwen0502
Sophia Wen (hfwen0502) deleted the build-all-backends branch November 10, 2026 14:47
Sophia Wen (hfwen0502) added a commit that referenced this pull request Nov 10, 2026
It was added in #91 and removed in #93, both after 1.7.2, so the next release
should neither introduce it nor say it is gone. setup.py no longer warns about
it, and the two unreleased notes no longer mention it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Sophia Wen (hfwen0502) added a commit that referenced this pull request Nov 10, 2026
* examples: UHF on gpu, how the UHF build is chosen, a runnable --initial_det, workflow links

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* README: why the SQD integration is TPB only, citing Qiskit/qiskit-sqd#389

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* README: why use the bindings rather than upstream's apps

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* READMEs: trim, launch on several ranks or GPUs, and say what the bindings pick for you

Every README from the top level down. Commands now run on several ranks or one
rank per GPU wherever the step parallelizes; single-process ones are left where
the step is serial. Long explanations of upstream internals are cut to what a
user acts on, and repeated warnings appear once.

The top-level README says the bindings choose the code path themselves -- the
UHF build from the FCIDUMP, the CPU evaluator after an offload solve -- and that
a feature a device does not support raises an error naming the device to use.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* examples README: only the pinned upstream is tested; drop SBD_BUILD_UHF from INSTALL

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Drop SBD_BUILD_UHF everywhere: no release ever had it

It was added in #91 and removed in #93, both after 1.7.2, so the next release
should neither introduce it nor say it is gone. setup.py no longer warns about
it, and the two unreleased notes no longer mention it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* docs: front page matches the README; sbd page covers CAOP and device=

The docs front page gains "What it does" and the reason for the bindings, the
README's feature-by-backend table in place of the device-only one, why the SQD
loop is TPB only (Qiskit/qiskit-sqd#389), and the pinned-upstream caveat for the
examples. Its separate TPB-or-GDB section folds into "What it does". The sbd API
page's intro now names CAOP and says what device= does and that an unsupported
device raises an error naming the ones that do.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* analysis README: variance works for restricted and UHF FCIDUMPs alike

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* analysis README: organized by use case, covering both evaluators and extrapolate.py

It opened with the TPB/GDB evaluator only and reached CAOP and extrapolate.py late
or in passing. It now starts with the two tools and a table of which upstream
evaluator each kind of state uses and with which methods, then one section per
task: check a molecular state, check a CAOP state, estimate the exact energy from
a series, compare two ways of growing a subspace, and run it in the same job. How
the estimate works and its settings follow. The other READMEs' links follow the
renamed sections.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* examples README: a too-small CAOP basis leaves PT2 well short, not most of the way

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* analysis README: drop the TPB-vs-GDB growth comparison

It compared two solvers' expansion schemes rather than showing the analysis, and
its own notes said none of its states had converged. Its one lesson for the
analysis, comparing subspaces at matched dimension by variance and E + PT2, is
now a sentence under the series section.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

SBD_TEST_DEVICE must be set to test a build without the CPU backend

1 participant