Skip to content

PennyLane Backline: QPM Prototype - allocate QEC controllers, decoders and transports per reservation - #159

Merged
DougSO merged 9 commits into
openQSE:mainfrom
josephleekl:backline-qpm
Oct 22, 2026
Merged

DougSO merged 9 commits into
openQSE:mainfrom
josephleekl:backline-qpm

Conversation

@josephleekl

@josephleekl josephleekl commented Oct 20, 2026 •

Copy link
Copy Markdown
Contributor

This PR adds the QFw side of the Backline integration: a Backline QPM (backline-local) that lets a job request the classical QEC resources real-time error correction needs, alongside its quantum reservation. The QPM matches the request against the site inventory, allocates a controller, decoder and transport, and starts a catalyst-executor with them loaded. The program, compiled locally with Catalyst, then runs on that executor.

  • svc_qpm.py: UTIL_QPM subclass. reserve handles three request types:
    • no resource_intent: quantum-only reservation (the qfw-slurm gateway path);
    • for_reservation + resource_intent: classical request against an existing reservation. It must be active and not yet placed, and come from the same owner and job;
    • resource_intent only: quantum and classical in one call.
  • matcher.py:
    • Matches a versioned resource intent against the site inventory, in order: QEC code → controller → decoder, transport and latency → free capacity.
    • Rejects with reason codes (unsupported-qec-code, no-matching-controller, capacity-exhausted, …).
    • Returns a placement: controller device, decoder symbol and library, transport, executor address.
  • inventory.yaml: default inventory with a CPU controller on null.qubit, the CPU Steane decoder from the Catalyst wheel, and memcpy. Override with QFW_BACKLINE_INVENTORY.
  • executors.py:
    • Starts one catalyst-executor per reservation, with the Catalyst runtime, controller-device and decoder plugins.
    • Stops it on release, expiry, shutdown, SIGTERM or process exit, killing the whole process group.
  • svc_qrc.py: refuses QRI execution calls, since programs run on the placement, not through QRI.
  • qpm_selection.py, local-services.yaml, site-services.yaml: register provider backline and the backline-local service.
  • Limitations:
    • One executor per reservation, on the QPM host.
    • memcpy only; RDMA endpoints are rejected.
    • One classical request per reservation.

Dependencies

  • No other PR has to merge first. Deploying it on the cluster is the companion QFw-SLURM-Cluster PR (Backline QPM node and --qpu=backline-local).

@DougSO

DougSO commented Oct 22, 2026

Copy link
Copy Markdown
Collaborator

Thanks for this. The reservation logic works as described: I ran the QPM against today's main with the real qhw admission and a stand-in executor launcher.

Couple of notes:

  1. I see a commit removed tests/mock/test_backline_qpm.py and tests/mock/test_backline_executors.py. Without them, nothing in CI covers the new service. Is there a reason they were removed?
  2. CI's ci-syntax fails on both Python versions with E302, expected 2 blank lines, before def backline_profile (svc_qpm.py L24). That is the only failure. One more blank line there fixes it.
  3. The program compiled on the client runs on the executor. The executor binds 0.0.0.0, and nothing checks who connects. So anyone who can reach the port can run code as the user the QPM runs as. On a site plane that is often root, and on our test cluster it is. Consider binding it to the interface clients actually use, and give each reservation a secret the executor checks. This can wait until after the SC26 demo but should be addressed in the future.

Smaller points:

  • The QPM registers as a statevector simulator. A lookup for a statevector simulator that doesn't name a provider could then find a service that refuses every circuit. Its own capability bit would avoid that. QFw: run Pulser programs on Pasqal devices through QRMI #158 takes bit 3 for neutral atoms, so bit 4 would be free.
  • A classical request that names no owner or job passes the ownership check (svc_qpm.py L203-L212). I attached classical resources, and so an executor, to another user's reservation that way. QFw's execution check skips a missing field the same way today, so this matches core. But a classical request also starts an executor and blocks the owner's own request, so requiring the owner and job whenever the reservation records them would be safer.

A client-executed QPM. reserve() matches a resource_intent against the
site inventory, commits the reservation through UTIL_QPM, and returns the
placement the client builds its Backline nodes from. get_reservation()
carries the placement while the reservation is active; release() and
expiry free the inventory entries. Execution calls are refused.

No changes to QFw core.
…uire owner/job on classical requests, flag executor auth TODO
@DougSO
DougSO merged commit 0909b19 into openQSE:main Oct 22, 2026
8 checks passed
@josephleekl

josephleekl commented Oct 22, 2026 •

Copy link
Copy Markdown
Contributor Author

Thanks @DougSO for the review, really appreciate it! I see you merged this before I managed to reply.

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