MOSP-CUDA#
MOSP-CUDA is the GPU implementation of DynaMOSP (IPDPS 2025, IEEE TPDS 2025;
dyng.citation("sssp")), originally ported from a SYCL version. Its SOSP update, after the
fixes below one persistent cooperative CUDA kernel per objective, is the CUDA backend of dynG’s
sssp.
Repository |
|
Pinned commit |
|
Paper snapshot |
tag |
History |
35 commits, 2025-08 to 2026-09; 34 by S M Shovan, 1 under the placeholder identity |
Ported in |
M1b (the fused kernel, the device graph, the CUDA resources), M7 (the combined graph on the GPU and the MOSP tree: mosp: dynamic multi-objective shortest paths) |
Parity |
byte-identical on the 495-case golden corpus, which MOSP-CUDA’s own export reproduces file for file; cross-backend equal; within the performance gates at locked clocks (M1b certificate, ADR 0018) |
Before the port, the two originals were cross-checked once on the corpus: MOSP-CUDA@e220ee2 and MOSP-OpenMP@c352151 give identical files (PLAN 6.3 step 2), so a difference could only be the port’s.
What was ported, from which files#
MOSP-CUDA@e220ee2 |
dynG |
|---|---|
|
|
|
the device copy of a CUDA graph ( |
|
the shared readers and writers of |
|
|
the stage timers with |
profiler stages with optional CUDA-event device times |
What was fixed in the original before the port#
The same correctness fixes as MOSP-OpenMP (M-a subtree invalidation instead of counting to infinity; M-c lowest-id ties, which made CUDA and OpenMP byte-identical), plus the GPU work:
M-b: Step 1 moved from a serial host loop to the GPU (roots marked by one kernel, subtrees invalidated by pointer jumping, invalidated vertices and insertion heads pulling their best in-neighbour).
MP1, MP2: invalidation, pull and near-far push, then one persistent cooperative kernel that runs the whole update of one objective (roots, invalidation, pull, near-far push, unpack) in one launch instead of a loop of kernels with a host round trip per iteration; MP4 the packed-word overflow; MP3 the combined graph on the GPU (for
mosp, 0.2).H-M1 / H-M2: the in-memory pipeline (inputs read once, the batch applied once).
M-d, M-e: the preference vector and the seeded change generator, as in MOSP-OpenMP.
The fixed code is 6-16x faster per objective than the paper’s code on the connectivity-safe 50K batch, and a batch that disconnects vertices no longer takes minutes (roadNet-PA: 39.1 s per objective before, the connectivity-safe batch’s time after); sssp: dynamic single-source shortest paths, section 8.
What differs in dynG#
A data race in the counter
invalidated: MOSP-CUDA@e220ee2 reads it from the candidate-list counter while other threads already append the insertion heads; dynG’s kernel sums per-thread counts (ADR 0017 item 1). The trees were never affected.The packing boundary: at the limit where (distance, parent) still fits one 64-bit word, MOSP-CUDA packs one edge weight earlier than MOSP-OpenMP, so
stats::packed_parentscan differ between the cuda and the host backends there (n = 2^17 - 1). The trees are equal for canonical input trees; for non-canonical imported trees inside the packing window the host backends (as MOSP-OpenMP) and cuda (as MOSP-CUDA) return different tie parents (ADR 0029, option A).Placement: a graph belongs to the resources that built it; results live in device memory and are read with
to_vector()ordyng.Array(host copies in Python); the device graph is uploaded once per batch inside the commit, as the original’s is.Engines: without cooperative launch,
engine::automaticruns the multi-kernel operators engine (M7, decision O24; ADR 0026), which follows MOSP_ESCHER@4b86159’s host loop of kernels with this kernel’s semantics and returns the same bytes;engine::fusedraisesnot_supported_errorthere.Registers: the port keeps the original’s 59 registers per thread of the int32 instantiation and the same co-resident grid (M1b certificate section 11).
Combined graph (M7):
combinedGraphGpu.cu’scombinedEdge,countEdgesKernel, the CUB scan andfillEdgesKernelaremosp’s CUDA combine step (cpp/src/algorithms/mosp/cuda.cu);sospFromScratchGpuon the combined graph is sssp’s static solve on a view;mospUpdateismosp::update().Not ported (yet): the file-path API of the library (
parallelCombinedGraph),mainwriting into relative paths,using namespace std.
The mapping of every name is section 9 of sssp: dynamic single-source shortest paths.