You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
This is a kick-off discussion to settle several architectural decisions around QDMI, interoperability, and how we expose an entire software stack to other stacks.
Context recap
QDMI today is two C interfaces:
Device interface (C header/ABI): implemented by providers and third parties; each implementation is nameshifted via a unique prefix to avoid symbol collisions in-process. This interface contains device/property queries and job submission/management (plus authentication via sessions).
Client interface (C header/ABI): a neutral, non-nameshifted mirror of the device interface that adds a device handle as first argument to most methods. A QDMI “driver” loads one or more provider device libraries (nameshifted), exposes enumeration and returns opaque handles to use devices via the client interface.
Above QDMI we’re building:
A compiler infrastructure (MLIR-based) that uses QDMI queries to tailor compilation and QDMI job APIs to submit programs and retrieve results; sessions handle auth.
A scheduler and other orchestration components.
Frontend adapters (e.g., Qiskit, PennyLane) that drive the stack.
Big question 1 — Do we need the client interface? Should we standardize the compiler↔QDMI boundary?
Observation: While working on a QDMI driver implementation for the MQT (see ✨ MQT QDMI Driver munich-quantum-toolkit/core#1010) we noticed that our C++ driver already has an object-oriented abstraction. Writing a FoMaC C++ wrapper over the C client interface risks duplicating many of the same concepts, feeling redundant.
Tension:
If we let the driver expose a FoMaC API directly (skipping the client interface), the compiler stack becomes tightly coupled to the specific driver. That improves ergonomics short-term but loses plug-and-play interoperability with other drivers/stacks.
If we keep the client interface as the canonical boundary, we preserve the ability to mix-and-match compilers, drivers, and devices across organizations (e.g., MQV collaborations), at the cost of boilerplate and a stricter ABI.
Options (not mutually exclusive):
Keep and evolve the client interface (recommended for interoperability):
Formalize versioning and capability negotiation (feature bits/extensions, error codes, profiles).
Reference FoMaC bindings (C++/Rust/Python) that wrap the client interface in ergonomic types while remaining driver-agnostic.
Provide conformance tests for drivers and bindings.
Driver-native high-level API (ergonomics first):
A driver may additionally expose a C++ API tailored to a specific stack.
The compiler can talk to this API directly where interop isn’t required.
We keep the client interface for interop scenarios and upstream collaborations.
Proposed stance:
Prioritize interoperability as a core goal. Keep the client interface and invest in it (versioning, capability discovery, conformance tests). Build reference C++ FoMaC libraries layered over the client interface to remove boilerplate for users.
Document this decision and avoid re-litigating unless we plan a v2 with a different approach.
Big question 2 — How do we expose an entire software stack to other stacks (stack-as-device), without bypassing schedulers?
Constraints we established in prior discussions:
We do not share individual provider device libraries with external stacks. That would create contention outside our scheduler’s control.
Sharing direct access to a driver’s client interface also bypasses scheduling and policies.
Desire: Wrap the whole software stack (scheduler + compiler + drivers + devices) behind a QDMI-compatible façade, so another stack can consume it via the same primitives. This enables A to consume B’s stack and vice versa.
Challenges:
A stack may manage multiple devices. A naïve “stack looks like one device” wrapper either hides multiplicity or requires duplicating N exposed devices.
We lack a notion of composite/hierarchical devices and device graphs in QDMI v1.
Properties and capabilities across multiple child devices: how to surface them (union/intersection/selection)? How to identify and select a child at job submission time?
For stack-as-device composition, should device selection be explicit (client chooses) or delegated (provider/driver schedules), or both?
Proposed next steps:
Reaffirm the client interface as the portability boundary for compilers and drivers, with FoMaC bindings layered on top. Or decide that this should be handled differently
Outline a concept for interoperability between two stacks relying on QDMI and start the development of a small proof-of-concept.
Explicitly tagging some people here because I think this is a pretty fundamental discussion: @ystade @echavarria-lrz @mnfarooqi
Your input on this would be highly appreciated.
This is a kick-off discussion to settle several architectural decisions around QDMI, interoperability, and how we expose an entire software stack to other stacks.
Context recap
Big question 1 — Do we need the client interface? Should we standardize the compiler↔QDMI boundary?
Big question 2 — How do we expose an entire software stack to other stacks (stack-as-device), without bypassing schedulers?
Proposed next steps:
Explicitly tagging some people here because I think this is a pretty fundamental discussion: @ystade @echavarria-lrz @mnfarooqi
Your input on this would be highly appreciated.