Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
90 commits
Select commit Hold shift + click to select a range
e54d0b1
feat(shmem): CPU proxy for IBGDA operations on Pensando AINIC
Aug 3, 2026
5d8813a
feat(shmem): integrate CPU proxy into MORI SHMEM layer
Aug 3, 2026
e04802b
fix(ionic): expose ibv_qp/ibv_cq handles for CPU proxy thread
Aug 3, 2026
ff9ece2
test: cross-NIC DMA capability test for multi-rail approach
Aug 3, 2026
efa6e45
feat: send-side routing — multi-rail QPs + lkey override
Aug 3, 2026
51d2607
wip: send-side routing — per-NIC MR + rkey exchange
Aug 3, 2026
924f285
fix: QP index mapping for proxy — use epIndex-indexed array
Aug 3, 2026
50759a7
wip: save progress — need to debug SIGSEGV in proxy EP test
Aug 3, 2026
102db5e
debug: found SIGSEGV crash location — line 345 in setup()
Aug 3, 2026
e61a4c4
fix: skip parent domain creation in proxy mode to avoid GPU corruption
Aug 3, 2026
62fcf6b
fix: use posix_memalign for proxy ring + document JIT cache invalidation
Aug 3, 2026
3572353
wip: re-enable proxy thread + plain QP + parent domain skip
Aug 3, 2026
dcdd2cd
fix: move per-NIC MR to symmetric_memory + skip 0-QP thread + narrow …
Aug 3, 2026
9bf0280
fix: lazy CQ poll + hipHostRegister for GPU-accessible ring
Aug 3, 2026
49b5d3c
feat: SEND_WITH_IMM atomic emulation + agreed-rail QP mapping + TC fix
Aug 4, 2026
31af7e7
fix: uncached VRAM + PCIe read fence for data/signal ordering
Aug 4, 2026
b4eed72
fix: increase recv WR count to 512 per proxy QP
Aug 4, 2026
3e4fea3
debug: add trace for uncached symmetric memory allocation path
Aug 4, 2026
a3a59b4
fix: conditional hipSetDevice in proxy thread
Aug 4, 2026
9b769e3
cleanup: simplify hipSetDevice in proxy MainLoop
Aug 4, 2026
016a329
fix: replace SEND_WITH_IMM with RDMA_WRITE for signal delivery
Aug 4, 2026
c50ce8e
feat: hybrid signal delivery — RDMA_WRITE for data signals, SEND_WITH…
Aug 4, 2026
e4fbddf
fix: increase proxy ring size to 8192 for large token counts
Aug 4, 2026
a18fd17
fix: increase proxy ring to 64K slots for bench-scale token counts
Aug 4, 2026
db3a42c
fix: remove FENCE from PROXY_SIGNAL_WRITE to unblock bench at scale
Aug 4, 2026
9243d69
cleanup: remove debug logging from proxy thread
Aug 4, 2026
4b235d1
cleanup: remove all debug fprintf from proxy infrastructure
Aug 4, 2026
bdbbb64
fix: remove orphaned fprintf arguments from sed cleanup
Aug 4, 2026
003cbab
cleanup: remove MoRI-RAIL debug prints from context.cpp
Aug 4, 2026
fba19f7
fix: only do per-NIC MR registration for the heap, not sub-allocations
Aug 4, 2026
21da9b6
debug: add minimal traces for vLLM init hang diagnosis
Aug 4, 2026
47770c2
fix: skip redundant MR registration + Allgather for heap sub-allocations
Aug 4, 2026
76e5162
feat: per-NIC proxy threads + targeted quiet for 3.4x dispatch speedup
Aug 5, 2026
e1622ce
v5: Full kernel separation — GpuStates clean, separate ProxyGpuState
Aug 12, 2026
46c069a
v5: Fix proxy dispatch for Warp/Block scope — root cause of AINIC hang
Aug 12, 2026
8eec84b
v5: Remove debug traces from init.cpp and runtime.cpp
Aug 12, 2026
a841a66
v5: Gate application layer proxy changes behind env var
Aug 12, 2026
49c405d
v5: Consolidate env var to MORI_EP_OVER_RDMA only
Aug 12, 2026
82870eb
v5: Revert shmem_ibgda_kernels.hpp to main — no proxy changes needed
Aug 12, 2026
0e7968e
v5: Minimal shmem_device_api.hpp — keep original macros, add one guar…
Aug 12, 2026
1fb0510
v5: Simplify proxy guard to just #ifdef MORI_PROXY_ENABLED
Aug 12, 2026
9cc3949
v6: Use TransportType::PROXY — native dispatch framework
Aug 12, 2026
bc08dfc
v6: Gate proxy dispatch branches with #ifdef MORI_PROXY_ENABLED
Aug 12, 2026
f329260
v6: Fix template specialization signatures and long/unsigned long redefs
Aug 12, 2026
236673b
v6: Remove address-based overloads, fix duplicate GetGlobalProxyStatePtr
Aug 12, 2026
3e98858
v6: Add address-based and signal stubs for all kernel templates
Aug 12, 2026
7947482
refactor: consolidate MORI_EP_OVER_RDMA env var checks
Aug 12, 2026
e1fc7dc
cleanup: move shmem_proxy_state.hpp include to top of internal.hpp
Aug 12, 2026
f3027ee
feat: add ProxyGpuStates as subclass of GpuStates
Aug 12, 2026
0cc49b9
cleanup: remove tp8-1p1d-bench skill file
Aug 12, 2026
b79a125
refactor: use ProxyGpuStates as single gpuStates in ShmemStates
Aug 12, 2026
cfd8cdc
refactor: single-symbol copy with size gated on proxy active
Aug 12, 2026
55caf81
refactor: use Context::IsProxyEnabled() for copy size gate
Aug 12, 2026
485dda6
cleanup: tidy internal.hpp — remove proxy_state include, move forward…
Aug 12, 2026
602833e
refactor: move proxyThreads to init.cpp file-local, use IsProxyEnabled()
Aug 12, 2026
bd0064a
cleanup: use inherited ProxyGpuStates in shmem.hpp weak symbol
Aug 12, 2026
e6d4e88
cleanup: delete shmem_proxy_state.hpp, fix shmem.hpp two-symbol approach
Aug 12, 2026
7082cb2
refactor: align ProxyGpuStates name, move extern + getter to internal…
Aug 12, 2026
5a3963a
fix: restore assert(false) fallthrough in dispatch macros
Aug 12, 2026
f29f4f0
fix: restore separate GpuStates + ProxyGpuStates in ShmemStates
Aug 12, 2026
5564238
rename: proxyGpuState → proxyGpuStates in ShmemStates
Aug 12, 2026
b9c02da
fix: update init.cpp and runtime.cpp for standalone ProxyGpuStates
Aug 12, 2026
433d1e4
cleanup: remove ProxyGpuStates.active field
Aug 12, 2026
bb8e8b1
refactor: use proxyEnabled directly in context.cpp, clean if/else paths
Aug 12, 2026
8ecc796
fix: remove unnecessary (int) cast to match main
Aug 12, 2026
933f8c5
refactor: clean if/else separation in BuildAndConnectInitialEndpoints
Aug 12, 2026
5f76d30
refactor: add GetRailContext() helper, deduplicate agreed-rail formula
Aug 12, 2026
c5e2806
cleanup: symmetric_memory.cpp — remove debug fprintf, use IsProxyEnab…
Aug 12, 2026
7547d18
refactor: keep main's MR registration untouched, single proxy if block
Aug 12, 2026
c8b8196
refactor: optimize proxy sub-allocation path, keep native untouched
Aug 12, 2026
ef8c6ac
refactor: cache proxyEnabled in IonicDeviceContext constructor
Aug 12, 2026
397aaed
cleanup: remove dead duplicate proxy QP block in ionic.cpp
Aug 12, 2026
aa7e241
fix: restore commented-out cqPool.insert from main
Aug 12, 2026
c267827
fix: reorder cqPool/qpPool insert before ibv handle expose
Aug 12, 2026
4b06cbe
cleanup: remove ibvHandle expose from native IBGDA path
Aug 12, 2026
0b19f69
cleanup: deduplicate MORI_DEFINE_GPU_STATES macro
Aug 12, 2026
3634247
fix: add VMM heap support to proxy PutMemNbi and PutSizeImmNbi
Aug 12, 2026
e469c21
fix: rename PROXY_STATE_MAX_NICS → PROXY_MAX_NICS in init.cpp
Aug 12, 2026
60a7674
debug: add traces for hang diagnosis
Aug 12, 2026
d72e52c
debug: add more traces for hang diagnosis (iteration 3)
Aug 12, 2026
555b69e
debug: add proxy thread traces for perf diagnosis
Aug 12, 2026
02d4209
debug: add thread count trace
Aug 12, 2026
3171441
fix: gate Warp/Block proxy kernels on lane 0 / thread 0
Aug 12, 2026
9ed32f2
Revert "fix: gate Warp/Block proxy kernels on lane 0 / thread 0"
Aug 12, 2026
90d8b7b
debug: add proxy thread ops counter on shutdown
Aug 12, 2026
546155b
fix: gate Warp/Block proxy kernels on lane 0 / thread 0
Aug 12, 2026
7e010ad
perf: symmetric agreed-rail formula for even NIC distribution
Aug 13, 2026
13bf51d
Revert "perf: symmetric agreed-rail formula for even NIC distribution"
Aug 13, 2026
13e308a
cleanup: remove all debug traces for v7 release
Aug 13, 2026
6cb8f76
fix: remove orphaned fprintf arguments in init.cpp
Aug 13, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion include/mori/application/application_device_types.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ namespace application {
/* Transport Types */
/* ---------------------------------------------------------------------------------------------- */

enum TransportType { RDMA = 0, P2P = 1, SDMA = 2 };
enum TransportType { RDMA = 0, P2P = 1, SDMA = 2, PROXY = 3 };

// Atomic internal buffer configuration. Defined here (device-safe) rather than in
// the host transport/rdma/rdma.hpp so device kernels (e.g. shmem_ibgda_kernels) can
Expand Down
14 changes: 14 additions & 0 deletions include/mori/application/context/context.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,16 @@ class Context {

RdmaContext* GetRdmaContext() const { return rdmaContext.get(); }
RdmaDeviceContext* GetRdmaDeviceContext() const { return rdmaDeviceContext.get(); }
const std::vector<std::unique_ptr<RdmaDeviceContext>>& GetAllRdmaDeviceContexts() const {
return allRdmaDeviceContexts;
}
bool RdmaTransportEnabled() const { return GetRdmaDeviceContext() != nullptr; }
RdmaDeviceContext* GetRailContext(int peerRank) const {
const int nCtx = static_cast<int>(allRdmaDeviceContexts.size());
int peerLocalGpu = peerRank % nCtx;
int agreedRail = std::max(LocalRankInNode(), peerLocalGpu) % nCtx;
return allRdmaDeviceContexts[agreedRail].get();
}

// Check if P2P connection is possible with a peer (same node)
bool CanUseP2P(int destRank) const;
Expand All @@ -112,6 +121,7 @@ class Context {
// in a test function after the workers had already been spawned.
bool IsSdmaEnabled() const { return sdmaEnabled; }
bool IsP2PDisabled() const { return p2pDisabled; }
bool IsProxyEnabled() const { return proxyEnabled; }

// Returns the initial RDMA endpoint set. Empty until BuildInitialEndpoints()
// has been called. SHMEM consumes this set; CCO does not (it creates its own
Expand Down Expand Up @@ -188,13 +198,17 @@ class Context {
// Snapshotted at construction; see IsSdmaEnabled() / IsP2PDisabled() above.
bool sdmaEnabled{false};
bool p2pDisabled{false};
bool proxyEnabled{false};
std::string myHostname;
std::vector<PeerInfo> peerInfos;
std::vector<PeerCapabilities> peerCaps; // raw capability discovery
std::vector<TransportType> transportTypes; // derived via DefaultPolicyResolve

std::unique_ptr<RdmaContext> rdmaContext{nullptr};
std::unique_ptr<RdmaDeviceContext> rdmaDeviceContext{nullptr};
// One context per available RDMA device/port, indexed by NIC index (0..numNics-1).
// QP-to-NIC mapping is via the agreed-rail formula, not a direct index.
std::vector<std::unique_ptr<RdmaDeviceContext>> allRdmaDeviceContexts;

std::vector<RdmaEndpoint> rdmaEps;
bool initialEndpointsBuilt{false};
Expand Down
11 changes: 11 additions & 0 deletions include/mori/application/memory/symmetric_memory.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,17 @@ class SymmMemManager {
SymmMemObjPtr GetVMMHeapObj() const { return vmmHeapObj; }
size_t GetVMMChunkSize() const { return vmmChunkSize; }

// Per-NIC keys for send-side routing (proxy mode).
// perNicLkeys[nic] = lkey for MY buffer registered on nic's PD.
// perNicPeerRkeys[nic][peer] = rkey for peer's buffer registered on nic's PD.
std::vector<uint32_t> perNicLkeys;
std::vector<std::vector<uint32_t>> perNicPeerRkeys;

// Cached heap rkeys — sub-allocations reuse these instead of doing
// redundant ibv_reg_mr + Allgather for each shmem_malloc.
uint32_t heapLkey_{0};
std::vector<uint32_t> heapRkeys_;

// Common Utilities
SymmMemObjPtr Get(void* localPtr) const;
HeapVAManager* GetHeapVAManager() const { return heapVAManager.get(); }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -153,12 +153,21 @@ class IonicDeviceContext : public RdmaDeviceContext {
uint64_t resource_type);
void create_parent_domain(ibv_context* context, struct ibv_pd* pd_orig);

struct ProxyRecvInfo { void* buf{nullptr}; uint32_t lkey{0}; uint32_t count{0}; };
ProxyRecvInfo GetProxyRecvInfo(uint32_t qpn) {
auto it = proxyRecvInfo.find(qpn);
return (it != proxyRecvInfo.end()) ? it->second : ProxyRecvInfo{};
}

private:
bool proxyEnabled{false};
uint32_t pdn;
struct ibv_pd* pd_uxdma[2];

std::unordered_map<uint32_t, IonicCqContainer*> cqPool;
std::unordered_map<uint32_t, IonicQpContainer*> qpPool;
std::unordered_map<uint32_t, ibv_qp*> proxyQpPool;
std::unordered_map<uint32_t, ProxyRecvInfo> proxyRecvInfo;
};

class IonicDevice : public RdmaDevice {
Expand Down
3 changes: 3 additions & 0 deletions include/mori/core/transport/rdma/ibverbs_handle.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,9 @@ struct IBVerbsHandle {
ibv_cq* cq{nullptr};
ibv_srq* srq{nullptr};
ibv_comp_channel* compCh{nullptr};
void* recvBuf{nullptr};
uint32_t recvLkey{0};
uint32_t recvCount{0};
};

} // namespace core
Expand Down
186 changes: 186 additions & 0 deletions include/mori/core/transport/rdma/proxy/proxy_device_primitives.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,186 @@
// Copyright © Advanced Micro Devices, Inc. All rights reserved.
// MIT License
#pragma once

#include "mori/core/transport/rdma/proxy/proxy_types.hpp"

#ifdef __HIPCC__

namespace mori {
namespace core {

// Returns sequence number (monotonically increasing). Mask with PROXY_RING_MASK for slot index.
inline __device__ uint32_t ProxyReserveSlot(volatile ProxyRing* ring) {
return __hip_atomic_fetch_add(
(uint32_t*)&ring->gpu_head, 1u, __ATOMIC_RELAXED, __HIP_MEMORY_SCOPE_AGENT);
}

inline __device__ void ProxyWaitSlotFree(volatile ProxyRing* ring, uint32_t slot) {
int spins = 0;
while (true) {
uint32_t st = __hip_atomic_load(
(uint32_t*)&ring->cmds[slot].status, __ATOMIC_RELAXED, __HIP_MEMORY_SCOPE_SYSTEM);
if (st == PROXY_FREE || st == PROXY_COMPLETED) break;
if (++spins % 100000 == 0) __builtin_amdgcn_s_sleep(1);
}
}

inline __device__ void ProxyWaitSlotCompleted(volatile ProxyRing* ring, uint32_t slot) {
while (true) {
uint32_t st = __hip_atomic_load(
(uint32_t*)&ring->cmds[slot].status, __ATOMIC_RELAXED, __HIP_MEMORY_SCOPE_SYSTEM);
if (st == PROXY_COMPLETED || st == PROXY_ERROR) break;
__builtin_amdgcn_s_sleep(1);
}
}

inline __device__ uint32_t ProxyPostWrite(
volatile ProxyRing* ring, uint32_t qp_idx,
uint64_t src_addr, uint32_t lkey,
uint64_t dst_addr, uint32_t rkey,
uint32_t length) {
uint32_t seq = ProxyReserveSlot(ring);
uint32_t slot = seq & PROXY_RING_MASK;
ProxyWaitSlotFree(ring, slot);

ring->cmds[slot].op = PROXY_RDMA_WRITE;
ring->cmds[slot].qp_idx = qp_idx;
ring->cmds[slot].src_addr = src_addr;
ring->cmds[slot].dst_addr = dst_addr;
ring->cmds[slot].length = length;
ring->cmds[slot].lkey = lkey;
ring->cmds[slot].rkey = rkey;
ring->cmds[slot].flags = 1;

__threadfence_system();
ring->cmds[slot].status = PROXY_PENDING;
return seq;
}

inline __device__ uint32_t ProxyPostWriteInline(
volatile ProxyRing* ring, uint32_t qp_idx,
uint64_t src_addr, uint32_t lkey,
uint64_t dst_addr, uint32_t rkey,
uint32_t length) {
uint32_t seq = ProxyReserveSlot(ring);
uint32_t slot = seq & PROXY_RING_MASK;
ProxyWaitSlotFree(ring, slot);

ring->cmds[slot].op = PROXY_RDMA_WRITE_INLINE;
ring->cmds[slot].qp_idx = qp_idx;
ring->cmds[slot].src_addr = src_addr;
ring->cmds[slot].dst_addr = dst_addr;
ring->cmds[slot].length = length;
ring->cmds[slot].lkey = lkey;
ring->cmds[slot].rkey = rkey;
ring->cmds[slot].flags = 1;

__threadfence_system();
ring->cmds[slot].status = PROXY_PENDING;
return seq;
}

inline __device__ uint32_t ProxyPostAtomicNonFetch(
volatile ProxyRing* ring, uint32_t qp_idx,
uint64_t dst_addr, uint32_t rkey,
uint64_t add_value, uint32_t lkey,
uint64_t ibuf_addr) {
uint32_t seq = ProxyReserveSlot(ring);
uint32_t slot = seq & PROXY_RING_MASK;
ProxyWaitSlotFree(ring, slot);

ring->cmds[slot].op = PROXY_ATOMIC_FETCH_ADD;
ring->cmds[slot].qp_idx = qp_idx;
ring->cmds[slot].src_addr = ibuf_addr;
ring->cmds[slot].dst_addr = dst_addr;
ring->cmds[slot].length = 8;
ring->cmds[slot].lkey = lkey;
ring->cmds[slot].rkey = rkey;
ring->cmds[slot].atomic_arg = add_value;
ring->cmds[slot].flags = 1;

__threadfence_system();
ring->cmds[slot].status = PROXY_PENDING;
return seq;
}

// Signal write: RDMA_WRITE of value to remote addr on the SAME NIC path
// as the preceding data write. Used for signals paired with data
// (ShmemPutMemNbiSignalThread) to ensure PCIe write ordering.
inline __device__ uint32_t ProxyPostSignalWrite(
volatile ProxyRing* ring, uint32_t qp_idx,
uint64_t dst_addr, uint32_t rkey,
uint64_t value, uint32_t lkey,
uint64_t ibuf_addr) {
uint32_t seq = ProxyReserveSlot(ring);
uint32_t slot = seq & PROXY_RING_MASK;
ProxyWaitSlotFree(ring, slot);

ring->cmds[slot].op = PROXY_SIGNAL_WRITE;
ring->cmds[slot].qp_idx = qp_idx;
ring->cmds[slot].src_addr = ibuf_addr;
ring->cmds[slot].dst_addr = dst_addr;
ring->cmds[slot].length = 8;
ring->cmds[slot].lkey = lkey;
ring->cmds[slot].rkey = rkey;
ring->cmds[slot].atomic_arg = value;
ring->cmds[slot].flags = 1;

__threadfence_system();
ring->cmds[slot].status = PROXY_PENDING;
return seq;
}

inline __device__ uint64_t ProxyPostAtomicFetch(
volatile ProxyRing* ring, uint32_t qp_idx,
uint64_t dst_addr, uint32_t rkey,
uint64_t add_value, uint32_t lkey,
uint64_t ibuf_addr) {
uint32_t seq = ProxyReserveSlot(ring);
uint32_t slot = seq & PROXY_RING_MASK;
ProxyWaitSlotFree(ring, slot);

ring->cmds[slot].op = PROXY_ATOMIC_FETCH_ADD;
ring->cmds[slot].qp_idx = qp_idx;
ring->cmds[slot].src_addr = ibuf_addr;
ring->cmds[slot].dst_addr = dst_addr;
ring->cmds[slot].length = 8;
ring->cmds[slot].lkey = lkey;
ring->cmds[slot].rkey = rkey;
ring->cmds[slot].atomic_arg = add_value;
ring->cmds[slot].flags = 1;
ring->cmds[slot].result = 0;

__threadfence_system();
ring->cmds[slot].status = PROXY_PENDING;

ProxyWaitSlotCompleted(ring, slot);
return ring->cmds[slot].result;
}

// Wait for all ops from [first_seq, first_seq + count) to complete.
// When count > PROXY_RING_SIZE, slots were reused during submission.
// ProxyWaitSlotFree already ensured earlier slots completed before reuse,
// so we only need to wait for the tail — the last PROXY_RING_SIZE slots.
inline __device__ void ProxyQuiet(volatile ProxyRing* ring, uint32_t first_seq, uint32_t count) {
if (count == 0) return;
uint32_t start = first_seq;
if (count > PROXY_RING_SIZE) {
start = first_seq + count - PROXY_RING_SIZE;
}
uint32_t end = first_seq + count;
for (uint32_t seq = start; seq < end; seq++) {
uint32_t slot = seq & PROXY_RING_MASK;
ProxyWaitSlotCompleted(ring, slot);
}
}

// Range variant for multi-warp callers that know the exact range.
inline __device__ void ProxyQuietRange(volatile ProxyRing* ring, uint32_t from, uint32_t to) {
ProxyQuiet(ring, from, to - from);
}

} // namespace core
} // namespace mori

#endif // __HIPCC__
62 changes: 62 additions & 0 deletions include/mori/core/transport/rdma/proxy/proxy_thread.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
// Copyright © Advanced Micro Devices, Inc. All rights reserved.
// MIT License
#pragma once

#if !defined(__HIPCC__) && !defined(__CUDACC__)

#include <infiniband/verbs.h>
#include <pthread.h>

#include <atomic>
#include <vector>

#include "mori/core/transport/rdma/proxy/proxy_types.hpp"

namespace mori {
namespace core {

struct InlineBuf {
uint64_t data[2];
};

struct ProxyQpHandle {
ibv_qp* qp{nullptr};
ibv_cq* cq{nullptr};
uint32_t lkey_override{0};
uint32_t rkey_override{0};
void* recv_buf{nullptr};
uint32_t recv_lkey{0};
uint32_t recv_count{0};
};

class ProxyThread {
public:
ProxyThread() = default;
~ProxyThread();

void Init(ProxyRing* ring, std::vector<ProxyQpHandle> qps, int gpuId = 0);
void Start();
void Shutdown();

private:
static void* ThreadFunc(void* arg);
void MainLoop();
void DrainCq(ProxyQpHandle& qph);
bool BuildWr(volatile ProxyCmd* cmd, ProxyQpHandle& qph,
ibv_send_wr& wr, ibv_sge& sge, uint32_t slot_id,
InlineBuf& ibuf);

ProxyRing* ring_{nullptr};
std::vector<ProxyQpHandle> qps_;
pthread_t thread_{};
std::atomic<bool> running_{false};
uint32_t next_slot_{0};
uint64_t ops_posted_{0};
uint64_t ops_completed_{0};
int gpu_id_{0};
};

} // namespace core
} // namespace mori

#endif // !defined(__HIPCC__) && !defined(__CUDACC__)
Loading