From 5ae18e5f81a1bc183e9e5b7b2915d3abdf9f77d1 Mon Sep 17 00:00:00 2001 From: Joseph Lee Date: Mon, 20 Jul 2026 13:24:08 -0400 Subject: [PATCH 01/12] Define runtime transport layer interface for backline backends --- runtime/include/Transport.hpp | 190 ++++++++++++++++++++++++++++++++++ 1 file changed, 190 insertions(+) create mode 100644 runtime/include/Transport.hpp diff --git a/runtime/include/Transport.hpp b/runtime/include/Transport.hpp new file mode 100644 index 0000000000..a601bc2a02 --- /dev/null +++ b/runtime/include/Transport.hpp @@ -0,0 +1,190 @@ +// Copyright 2026 Xanadu Quantum Technologies Inc. + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 + +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#pragma once +#include +#include +#include + +namespace catalyst::transport { + +/** + * @brief Data-plane strategy: which engine issues the transfer. + */ +enum class DataPath : std::uint8_t { + CpuVerbs, // Plain ibverbs on CPU. + GpuEngine, // Gpu-initiated comms. + Other, +}; + +/** + * @brief Memory kind: selects the allocation and registration path. + */ +enum class MemKind : std::uint8_t { + CpuRam, + GpuHbm, + Ddr, + Other, +}; + +/** + * @brief Out-of-band connection parameters for bringing up a session. + */ +struct ConnectInfo { + std::string peer; + std::uint16_t oob_port; +}; + +/** + * @brief Locally allocated and registered memory region. + */ +struct MemRegion { + void *addr = nullptr; + std::uint64_t size = 0; + std::uint32_t lkey = 0; + std::uint32_t rkey = 0; + MemKind kind = MemKind::CpuRam; +}; + +/** + * @brief Handle to a peer's memory region, exchanged over the out-of-band channel. + */ +struct PeerRef { + std::uint32_t rkey = 0; + std::uint64_t remote_addr = 0; + std::uint64_t size = 0; +}; + +/** + * @brief Configuration for the data-movement channel a session uses. + */ +struct ChannelDesc { + DataPath data_path = DataPath::CpuVerbs; + bool persistent = true; +}; + +/** + * @brief Stateful transport session shared by the controller and coprocessor roles. + * + * Methods must be called in this order: + * 1. connect - bring up QPs + the out-of-band channel + * 2. alloc_memory - register the region (needs the connected context) + * 3. exchange_keys - swap region handles over the out-of-band channel + * 4. establish_channel - program the channel from the local + peer regions + * 5. (coprocessor) set_coprocessor_fn / (controller) set_max_in_flight - before start() + * 6. start / collect / stop + */ +class TransportSession { + public: + virtual ~TransportSession() = default; + + /** + * @brief Bring up the connection (out-of-band handshake and QP transition to RTS). + * + * @param info Peer address and out-of-band port. + * + * @return `int` + */ + virtual int connect(const ConnectInfo &info) = 0; + + /** + * @brief Allocate and register a memory region on the device. + * + * @param size Size of the region in bytes. + * @param kind Memory kind selecting the allocation and registration path. + * @param access Access flags for the registration. + * + * @return `MemRegion` The allocated and registered region. + */ + virtual MemRegion alloc_memory(std::size_t size, MemKind kind, std::uint32_t access) = 0; + + /** + * @brief Advertise a local region and receive the peer's region over the out-of-band channel. + * + * @param local The local region to advertise. + * + * @return `PeerRef` The peer's advertised region. + */ + virtual PeerRef exchange_keys(const MemRegion &local) = 0; + + /** + * @brief Program the data movement this session will run (single channel per session). + * + * @param desc Channel configuration. + * @param local The local memory region. + * @param peer The peer's memory region. + */ + virtual void establish_channel(const ChannelDesc &desc, const MemRegion &local, + const PeerRef &peer) = 0; + + /** + * @brief Launch the engine (non-blocking; runs until stop()). + */ + virtual void start() = 0; + + /** + * @brief Wait for a result and write it out. + * + * @param outputs Array of output buffers to write into. + * @param n Number of output buffers. + * + * @return `int` + */ + virtual int collect(void *const *outputs, std::size_t n) = 0; + + /** + * @brief Stop the engine and join. Idempotent. + */ + virtual void stop() = 0; +}; + +/** + * @brief Controller role: writes syndromes out and receives corrections. + */ +class ControllerSession : public TransportSession { + public: + /** + * @brief Set the sliding-window depth: how many syndromes to keep in flight. + * + * Call before start(). A value of 1 means strict one-in-flight. + * + * @param n Maximum number of syndromes in flight. + */ + virtual void set_max_in_flight(std::uint32_t n) = 0; +}; + +/** + * @brief Opaque function to run on the coprocessor. May include a persistent kernel on the GPU. + */ +using CoprocessorFn = std::size_t (*)(const void *in, std::size_t in_len, void *out, + std::size_t out_cap, void *ctx); + +/** + * @brief Coprocessor role: receives syndromes, decodes, and returns corrections. + */ +class CoprocessorSession : public TransportSession { + public: + /** + * @brief Bind the coprocessor function this session runs. + * + * Call before start(). `fn` is a local function pointer; `ctx` is passed + * back to `fn` on every invocation and may be null. + * + * @param fn The coprocessor function to run per received syndrome. + * @param ctx Opaque context passed to `fn` on each invocation; may be null. + */ + virtual void set_coprocessor_fn(CoprocessorFn fn, void *ctx) = 0; +}; + +} // namespace catalyst::transport From 5e7633379073f71d8ef7370f29a46a4711abef30 Mon Sep 17 00:00:00 2001 From: Joseph Lee Date: Mon, 20 Jul 2026 13:28:01 -0400 Subject: [PATCH 02/12] update changelog --- doc/releases/changelog-dev.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/doc/releases/changelog-dev.md b/doc/releases/changelog-dev.md index 532835a10e..3ccd5df3c2 100644 --- a/doc/releases/changelog-dev.md +++ b/doc/releases/changelog-dev.md @@ -12,6 +12,9 @@

Improvements 🛠

+* A new runtime transport layer for remote/local executors is introduced. + [(#3043)](https://github.com/PennyLaneAI/catalyst/pull/3043) + * A `BufferizableOpInterface` implementation is now added for `catalyst.launch_kernel` operation and it is now bufferizable. [(#3024)](https://github.com/PennyLaneAI/catalyst/pull/3024) From 279a2b4962f17582b83b933761aa1dcbb98ff467 Mon Sep 17 00:00:00 2001 From: Joseph Lee Date: Mon, 20 Jul 2026 14:35:20 -0400 Subject: [PATCH 03/12] comments --- runtime/include/Transport.hpp | 21 +++++---------------- 1 file changed, 5 insertions(+), 16 deletions(-) diff --git a/runtime/include/Transport.hpp b/runtime/include/Transport.hpp index a601bc2a02..d8813d22cc 100644 --- a/runtime/include/Transport.hpp +++ b/runtime/include/Transport.hpp @@ -71,7 +71,6 @@ struct PeerRef { */ struct ChannelDesc { DataPath data_path = DataPath::CpuVerbs; - bool persistent = true; }; /** @@ -82,7 +81,7 @@ struct ChannelDesc { * 2. alloc_memory - register the region (needs the connected context) * 3. exchange_keys - swap region handles over the out-of-band channel * 4. establish_channel - program the channel from the local + peer regions - * 5. (coprocessor) set_coprocessor_fn / (controller) set_max_in_flight - before start() + * 5. (coprocessor) set_coprocessor_fn before start() * 6. start / collect / stop */ class TransportSession { @@ -150,19 +149,9 @@ class TransportSession { }; /** - * @brief Controller role: writes syndromes out and receives corrections. + * @brief Controller role: writes messages out and receives corrections. */ -class ControllerSession : public TransportSession { - public: - /** - * @brief Set the sliding-window depth: how many syndromes to keep in flight. - * - * Call before start(). A value of 1 means strict one-in-flight. - * - * @param n Maximum number of syndromes in flight. - */ - virtual void set_max_in_flight(std::uint32_t n) = 0; -}; +class ControllerSession : public TransportSession {}; /** * @brief Opaque function to run on the coprocessor. May include a persistent kernel on the GPU. @@ -171,7 +160,7 @@ using CoprocessorFn = std::size_t (*)(const void *in, std::size_t in_len, void * std::size_t out_cap, void *ctx); /** - * @brief Coprocessor role: receives syndromes, decodes, and returns corrections. + * @brief Coprocessor role: receives messages, process, and returns corrections. */ class CoprocessorSession : public TransportSession { public: @@ -181,7 +170,7 @@ class CoprocessorSession : public TransportSession { * Call before start(). `fn` is a local function pointer; `ctx` is passed * back to `fn` on every invocation and may be null. * - * @param fn The coprocessor function to run per received syndrome. + * @param fn The coprocessor function to run per received message. * @param ctx Opaque context passed to `fn` on each invocation; may be null. */ virtual void set_coprocessor_fn(CoprocessorFn fn, void *ctx) = 0; From a319b39d7fd8961170530a8856f4ed7c6a406de0 Mon Sep 17 00:00:00 2001 From: Joseph Lee Date: Mon, 20 Jul 2026 15:15:12 -0400 Subject: [PATCH 04/12] update changelog --- doc/releases/changelog-dev.md | 1 + 1 file changed, 1 insertion(+) diff --git a/doc/releases/changelog-dev.md b/doc/releases/changelog-dev.md index 3ccd5df3c2..42490dbf5d 100644 --- a/doc/releases/changelog-dev.md +++ b/doc/releases/changelog-dev.md @@ -461,6 +461,7 @@ JiaRung Jian, Jacob Kitchen, Korbinian Kottmann, Christina Lee, +Joseph Lee, Rylan Malarchick, Mehrdad Malekmohammadi, River McCubbin, From 8dccc6201341549f6eab86fbf504625e1af92826 Mon Sep 17 00:00:00 2001 From: Hong-Sheng Zheng Date: Mon, 20 Jul 2026 16:19:33 -0400 Subject: [PATCH 05/12] update interface --- runtime/include/Transport.hpp | 24 ++++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/runtime/include/Transport.hpp b/runtime/include/Transport.hpp index d8813d22cc..241ec5bdf4 100644 --- a/runtime/include/Transport.hpp +++ b/runtime/include/Transport.hpp @@ -136,22 +136,42 @@ class TransportSession { * @brief Wait for a result and write it out. * * @param outputs Array of output buffers to write into. + * @param output_bytes Array of output buffer sizes. * @param n Number of output buffers. * * @return `int` */ - virtual int collect(void *const *outputs, std::size_t n) = 0; + virtual int collect(void *const *outputs, const std::size_t *output_bytes, std::size_t n) = 0; /** * @brief Stop the engine and join. Idempotent. */ virtual void stop() = 0; + + /** + * @brief Last round-trip time, in nanoseconds (for testing purposes). + * + * @return `std::uint64_t` + */ + virtual std::uint64_t last_rtt_ns() const { return 0; } }; /** * @brief Controller role: writes messages out and receives corrections. */ -class ControllerSession : public TransportSession {}; +class ControllerSession : public TransportSession { + public: + // Build the work item in slot `work_item_idx` from `schema`. + virtual void commit_work_item(std::uint32_t work_item_idx, std::uint64_t in_bytes, + std::uint64_t out_bytes) = 0; + + // Fire one round using work item `work_item_idx` and whatever payload is currently in + // data_slot(). Pairs with a subsequent collect(). Returns 0 on success. + virtual int kick(std::uint32_t work_item_idx = 0) = 0; + + // Current round's outbound slot in the transport-owned ring. + virtual void *data_slot() = 0; +}; /** * @brief Opaque function to run on the coprocessor. May include a persistent kernel on the GPU. From da41e922e25b95094421775cd8acfcef1f905bc5 Mon Sep 17 00:00:00 2001 From: Hong-Sheng Zheng Date: Mon, 20 Jul 2026 16:24:55 -0400 Subject: [PATCH 06/12] chagne type --- runtime/include/Transport.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/runtime/include/Transport.hpp b/runtime/include/Transport.hpp index 241ec5bdf4..3a5ed0ce8d 100644 --- a/runtime/include/Transport.hpp +++ b/runtime/include/Transport.hpp @@ -141,7 +141,7 @@ class TransportSession { * * @return `int` */ - virtual int collect(void *const *outputs, const std::size_t *output_bytes, std::size_t n) = 0; + virtual int collect(void *const *outputs, const std::uint64_t *output_bytes, std::size_t n) = 0; /** * @brief Stop the engine and join. Idempotent. From 5282f5a1d099dd02762d1cb4092def25f49a144d Mon Sep 17 00:00:00 2001 From: Hong-Sheng Zheng Date: Mon, 20 Jul 2026 16:42:09 -0400 Subject: [PATCH 07/12] update comment --- runtime/include/Transport.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/runtime/include/Transport.hpp b/runtime/include/Transport.hpp index 3a5ed0ce8d..4ed87cbe32 100644 --- a/runtime/include/Transport.hpp +++ b/runtime/include/Transport.hpp @@ -161,7 +161,7 @@ class TransportSession { */ class ControllerSession : public TransportSession { public: - // Build the work item in slot `work_item_idx` from `schema`. + // Build the work item in slot `work_item_idx` from in_bytes and out_bytes. virtual void commit_work_item(std::uint32_t work_item_idx, std::uint64_t in_bytes, std::uint64_t out_bytes) = 0; From 22cd621cba1e34fb6b67717587d48626849abbc1 Mon Sep 17 00:00:00 2001 From: Hong-Sheng Zheng Date: Mon, 20 Jul 2026 18:32:57 -0400 Subject: [PATCH 08/12] update interface --- runtime/include/Transport.hpp | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/runtime/include/Transport.hpp b/runtime/include/Transport.hpp index 4ed87cbe32..29c4cc81f1 100644 --- a/runtime/include/Transport.hpp +++ b/runtime/include/Transport.hpp @@ -135,13 +135,12 @@ class TransportSession { /** * @brief Wait for a result and write it out. * - * @param outputs Array of output buffers to write into. - * @param output_bytes Array of output buffer sizes. - * @param n Number of output buffers. + * @param correction Output buffer to write the result into. + * @param bytes Capacity of the output buffer, in bytes. * * @return `int` */ - virtual int collect(void *const *outputs, const std::uint64_t *output_bytes, std::size_t n) = 0; + virtual int collect(void *correction, std::uint64_t bytes) = 0; /** * @brief Stop the engine and join. Idempotent. @@ -167,7 +166,7 @@ class ControllerSession : public TransportSession { // Fire one round using work item `work_item_idx` and whatever payload is currently in // data_slot(). Pairs with a subsequent collect(). Returns 0 on success. - virtual int kick(std::uint32_t work_item_idx = 0) = 0; + virtual int kick(std::uint32_t work_item_idx) = 0; // Current round's outbound slot in the transport-owned ring. virtual void *data_slot() = 0; From 76305703ada3b8660a444eee9e78ca72ae2063ac Mon Sep 17 00:00:00 2001 From: Hong-Sheng Zheng Date: Tue, 21 Jul 2026 09:57:42 -0400 Subject: [PATCH 09/12] Update runtime/include/Transport.hpp Co-authored-by: Mehrdad Malek <39844030+mehrdad2m@users.noreply.github.com> --- runtime/include/Transport.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/runtime/include/Transport.hpp b/runtime/include/Transport.hpp index 29c4cc81f1..d90be2e428 100644 --- a/runtime/include/Transport.hpp +++ b/runtime/include/Transport.hpp @@ -135,7 +135,7 @@ class TransportSession { /** * @brief Wait for a result and write it out. * - * @param correction Output buffer to write the result into. + * @param replies Output buffer to write the result into. * @param bytes Capacity of the output buffer, in bytes. * * @return `int` From da12f304844939d1130d3dd2f84c72b56fa9c371 Mon Sep 17 00:00:00 2001 From: Hong-Sheng Zheng Date: Tue, 21 Jul 2026 09:58:30 -0400 Subject: [PATCH 10/12] Apply suggestion from @mehrdad2m Co-authored-by: Mehrdad Malek <39844030+mehrdad2m@users.noreply.github.com> --- runtime/include/Transport.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/runtime/include/Transport.hpp b/runtime/include/Transport.hpp index d90be2e428..aecfdd68ba 100644 --- a/runtime/include/Transport.hpp +++ b/runtime/include/Transport.hpp @@ -140,7 +140,7 @@ class TransportSession { * * @return `int` */ - virtual int collect(void *correction, std::uint64_t bytes) = 0; + virtual int collect(void *replies, std::uint64_t bytes) = 0; /** * @brief Stop the engine and join. Idempotent. From 5490f086cb6607927479cbf53d4e87a73707ca5b Mon Sep 17 00:00:00 2001 From: Hong-Sheng Zheng Date: Tue, 21 Jul 2026 09:58:37 -0400 Subject: [PATCH 11/12] Apply suggestion from @mehrdad2m Co-authored-by: Mehrdad Malek <39844030+mehrdad2m@users.noreply.github.com> --- runtime/include/Transport.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/runtime/include/Transport.hpp b/runtime/include/Transport.hpp index aecfdd68ba..085c3b0edb 100644 --- a/runtime/include/Transport.hpp +++ b/runtime/include/Transport.hpp @@ -156,7 +156,7 @@ class TransportSession { }; /** - * @brief Controller role: writes messages out and receives corrections. + * @brief Controller role: writes messages out and receives replies. */ class ControllerSession : public TransportSession { public: From 5d639c5c7696a96790f954088d63e93025b7d329 Mon Sep 17 00:00:00 2001 From: Hong-Sheng Zheng Date: Tue, 21 Jul 2026 09:58:43 -0400 Subject: [PATCH 12/12] Apply suggestion from @mehrdad2m Co-authored-by: Mehrdad Malek <39844030+mehrdad2m@users.noreply.github.com> --- runtime/include/Transport.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/runtime/include/Transport.hpp b/runtime/include/Transport.hpp index 085c3b0edb..7f8f7b07c0 100644 --- a/runtime/include/Transport.hpp +++ b/runtime/include/Transport.hpp @@ -179,7 +179,7 @@ using CoprocessorFn = std::size_t (*)(const void *in, std::size_t in_len, void * std::size_t out_cap, void *ctx); /** - * @brief Coprocessor role: receives messages, process, and returns corrections. + * @brief Coprocessor role: receives messages, process, and returns replies. */ class CoprocessorSession : public TransportSession { public: