Skip to content

Demand struct sync even in CPU mode - #829

Open
TysonRayJones wants to merge 1 commit into
develfrom
always-demand-sync
Open

TysonRayJones wants to merge 1 commit into
develfrom
always-demand-sync

Conversation

@TysonRayJones

@TysonRayJones TysonRayJones commented Sep 30, 2026 •

Copy link
Copy Markdown
Member

This PR makes synchronisation of heap structs unconditionally necessary, whereas we presently relax this in CPU mode for user convenience - a convenience which makes the API inconsistent across modes and encourages a bug! I have labelled this as an "API break" but it's really "removing a dangerous user shortcut".

Context

Heap structs, like CompMatr, are dangerous for users to modify/initialise directly because they have a corresponding GPU buffer in GPU mode which must be overwritten. Users are encouraged to use functions like setCompMatr() which will mark the struct as having been "synced". Passing an unsynced GPU struct to an API function will trigger an error:

CompMatr m = createCompMatr(3);

m.cpuElems[0][0] = 1;
...

// m is un-synced; below throws in GPU mode
applyCompMatr(qureg, targs, numTargs, m); 

Error: The CompMatr has yet not been synchronised with its persistent GPU memory, so potential changes to its elements are being ignored. Please call syncCompMatr() after manually modifying elements, or overwrite all elements with setCompMatr() which automatically synchronises.

If a user does not call the setters, and instead opts to manually overwrite the struct elements like above, and if the struct has a GPU buffer, then the user is required to call syncCompMatr() before passing the struct to functions like applyCompMatr(). The syncCompMatr() function copies the struct's CPU data to the GPU buffer. If the struct has no GPU buffer (for example, because the QuEST environment is not GPU-accelerated), then the function has no effect, except to mark the struct as "synced".

Problem

Presently, we disable sync validation in CPU mode, since it's functionally unnecessary. A user can run the above code without error. But this...

  • Breaks the intended agnosticism between QuEST's deployment modes! We should discourage/forbid convenience skips/hacks which break agnosticism.
  • Encourages errors when users migrate from CPU to GPU. In the present design, CPU users may be unaware of the need to ever sync because we are not penalising them, and will be astonished when later moving to GPU.
  • Requires sync-related doc/error messages are GPU specific, explaining the need to update GPU buffers. It's an implementation leak!

Solution

The solution in this PR is to unconditionally demand heap-structs to be synced - to simply remove the CPU validation relaxation. The error messages are updated accordingly, and some missing sync validation unit tests are added.
The above example becomes:

CompMatr m = createCompMatr(3);

m.cpuElems[0][0] = 1;
...

syncCompMatr(m);
applyCompMatr(qureg, targs, numTargs, m); 

and runs without error in all modes.

This PR also adds FullStateDiagMatr sync validation which was erroneously missing from calcExpecNonHermitianFullStateDiagMatr and calcExpecNonHermitianFullStateDiagMatrPower. This bug probably results from these functions not validating Hermiticity, which itself contains the sync check for brevity.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant