diff --git a/.gitignore b/.gitignore index ceaa48d..eca4b33 100644 --- a/.gitignore +++ b/.gitignore @@ -224,3 +224,6 @@ __marimo__/ # Personal Superset lifecycle overrides .superset/config.local.json + +# Performance harness run logs +dev/perf/**/*.log diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 94625fa..0dfd90b 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -4,8 +4,11 @@ repos: hooks: - id: check-merge-conflict - id: check-yaml + # Recorded measurement artefacts and review patches must stay byte-exact. - id: end-of-file-fixer + exclude: ^dev/(research/|perf/.*/(results|review-[^/]+)/) - id: trailing-whitespace + exclude: ^dev/(research/|perf/.*/(results|review-[^/]+)/) - id: mixed-line-ending - id: debug-statements diff --git a/CHANGELOG.md b/CHANGELOG.md index 067042a..e2b5c1a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,14 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [0.11.0] - 2026-10-02 + +### Changed + +- **Shortest Paths**: `shortest_paths` / `shortest_paths_to` (and therefore `spf`, `spf_to`, max-flow, `FlowPolicy` and KSP spur searches) now run Dijkstra on a monotone bucket queue whenever the graph's edge costs fit 65,536 buckets (`max_cost / gcd(costs) + 1`), which covers unit, uniform and small-integer cost graphs including zero-cost pseudo attachments; wider or int64-offset costs keep the binary heap. The active bucket is ordered by the same `(-bottleneck, node)` key as the heap, so the pop order and every output (distances, predecessor order, single-path capacity ties, early exit) are bit-identical; a differential test in the C++ suite enforces this. Scratch arrays are now a thread-local workspace reset per search (only the touched nodes when few were touched), which removes the O(N) initialisation that dominated small destination-limited searches on large graphs. Measured sequentially on an M4 Max: 1.4–1.8x on weighted random graphs, 1.1–1.3x on unit-cost graphs, 2.4–3.0x on near-destination queries; path graphs (frontier of one node) are about 1.3x slower in absolute terms of a few microseconds, and graphs that fall back to the heap (`W > 65536`) are within a few percent of the previous heap on full-source searches while their small destination-limited searches are still about 2.8x faster. `StrictMultiDiGraph` exposes `max_cost()` / `cost_gcd()`; the C++ functions take an optional trailing `SpfQueue` for tests, and `NGRAPH_CORE_SPF_QUEUE=heap|bucket` overrides the choice process-wide. The search also skips settled neighbours before scanning their parallel edges and sizes the predecessor output from live per-node counts, which makes dense unit-cost fabrics about 1.3x faster; a frontier of one node is held inline, which halves the path-graph penalty. +- **Max-Flow**: `calc_max_flow` and `FlowState::place_max_flow` with `require_capacity=false` computed the identical cost-only shortest-path DAG on every tier; it is now computed once per call. Results are unchanged. +- **Internals**: `FlowPolicy` no longer copies the path DAG when returning a bundle, and the `spf` / `spf_to` bindings move the DAG into the Python result instead of copying it. + ## [0.10.0] - 2026-09-13 ### Fixed diff --git a/README.md b/README.md index c5d7fba..6bd2eff 100644 --- a/README.md +++ b/README.md @@ -110,6 +110,9 @@ bindings/python/ # pybind11 bindings python/netgraph_core/ # Python package tests/cpp/ # C++ tests (googletest) tests/py/ # Python tests (pytest) +dev/ # Developer scripts (not shipped): checks, coverage, +dev/perf/ # performance tooling and recorded A/B/A results, +dev/research/ # research prototypes and their evidence ``` ## Development @@ -123,6 +126,9 @@ make cpp-test # C++ tests only make cov # Combined coverage report (C++ + Python) ``` +Performance work (harnesses, old/new/old protocol, recorded measurements) is +described in [dev/perf/README.md](dev/perf/README.md). + ## Environment Variables | Variable | Effect | @@ -130,6 +136,7 @@ make cov # Combined coverage report (C++ + Python) | `NGRAPH_CORE_PROFILE=1` | Enable profiling of C++ hot paths (`profiling_dump()` / `profiling_reset()`). | | `NGRAPH_CORE_BATCH_THREADS` | Worker threads for `batch_max_flow` (default: hardware concurrency). Set to `1` when calling from your own worker pool. | | `NGRAPH_CORE_SENSITIVITY_THREADS` | Worker threads for `sensitivity_analysis` (default: hardware concurrency). | +| `NGRAPH_CORE_SPF_QUEUE` | Frontier queue for SPF: `heap` forces the reference binary heap, `bucket` prefers the bucket queue where the graph is eligible. Unset (default) selects automatically; both give bit-identical results. Read once per process; for benchmarking and diagnosis. | ## Requirements diff --git a/bindings/python/module.cpp b/bindings/python/module.cpp index 3cbd5ca..e01488f 100644 --- a/bindings/python/module.cpp +++ b/bindings/python/module.cpp @@ -209,12 +209,12 @@ PYBIND11_MODULE(_netgraph_core, m, py::mod_gil_not_used()) { py::array_t dist_arr(res.first.size()); auto* out = dist_arr.mutable_data(); for (std::size_t i=0;i(maxc) : static_cast(res.first[i]); - return py::make_tuple(std::move(dist_arr), res.second); + return py::make_tuple(std::move(dist_arr), std::move(res.second)); } else if (dtype == "float64") { py::array_t dist_arr(res.first.size()); auto* out = dist_arr.mutable_data(); for (std::size_t i=0;i::infinity() : static_cast(res.first[i]); - return py::make_tuple(std::move(dist_arr), res.second); + return py::make_tuple(std::move(dist_arr), std::move(res.second)); } else { throw py::value_error("dtype must be 'float64' or 'int64'"); } @@ -258,12 +258,12 @@ PYBIND11_MODULE(_netgraph_core, m, py::mod_gil_not_used()) { py::array_t dist_arr(res.first.size()); auto* out = dist_arr.mutable_data(); for (std::size_t i=0;i(maxc) : static_cast(res.first[i]); - return py::make_tuple(std::move(dist_arr), res.second); + return py::make_tuple(std::move(dist_arr), std::move(res.second)); } else if (dtype == "float64") { py::array_t dist_arr(res.first.size()); auto* out = dist_arr.mutable_data(); for (std::size_t i=0;i::infinity() : static_cast(res.first[i]); - return py::make_tuple(std::move(dist_arr), res.second); + return py::make_tuple(std::move(dist_arr), std::move(res.second)); } else { throw py::value_error("dtype must be 'float64' or 'int64'"); } diff --git a/dev/perf/README.md b/dev/perf/README.md new file mode 100644 index 0000000..d9c6cc0 --- /dev/null +++ b/dev/perf/README.md @@ -0,0 +1,21 @@ +# Performance tooling + +Developer-only tools for measuring NetGraph-Core. Nothing here ships in the +wheel or the sdist, and nothing here is run by CI; the repository gates +(`make check-ci`, `make sanitize-test`) remain the acceptance tests. + +- [`spf_queue/`](spf_queue/): the shortest-path frontier queue and workspace + work (plan, parity harness, old-versus-new bit-gate, NetGraph-level + benchmark, recorded A/B/A results and the independent review). Start with + [`spf_queue/PLAN.md`](spf_queue/PLAN.md). +- [`../benchmark_profiling_overhead.py`](../benchmark_profiling_overhead.py): + SPF and placement micro-benchmark used for the PGO training run + (`make install-pgo`) and for measuring profiling overhead. + +Conventions for performance claims (see `AGENTS.md`): verify correctness +first (bit-identical outputs where the contract is exact, certificates for +flows), then measure old/new/old in fresh processes on one quiet machine, +record load, hashes and raw samples, and treat differences inside the +run-to-run band as inconclusive. The research record behind the queue work, +including the Apple GPU investigation that preceded it, is in +[`../research/`](../research/). diff --git a/dev/perf/spf_queue/PLAN.md b/dev/perf/spf_queue/PLAN.md new file mode 100644 index 0000000..1696f0c --- /dev/null +++ b/dev/perf/spf_queue/PLAN.md @@ -0,0 +1,581 @@ +# CPU optimisation implementation plan + +Status: implemented in the working tree (P0–P2 and the P3 fallback review +below); not yet committed or released. +Consolidated on 27 September 2026 against NetGraph-Core `fbab119`, revised the +same day after the [queue-substitution experiment](./), then updated +with the implementation and its old/new/old measurements. This is the current +CPU plan, superseding the implementation-order guidance in the two Metal +research reports. Those reports and their raw measurements remain the historical +evidence; the earlier BFS/Dial prototypes are now understood as special cases of +one queue. + +## Implementation status (27 September 2026) + +What landed, as one change on top of `fbab119`: + +- `StrictMultiDiGraph::from_arrays` records `max_cost()` and `cost_gcd()` in + its existing cost scan; they follow copies and moves as members. +- `shortest_paths_core` and `shortest_paths_to_core` share one relaxation loop + templated on the queue. `HeapQueue` is the reference binary heap on + `(cost, -bottleneck, node)`; `BucketQueue` is the ordered bucket queue + (`W = max_cost / gcd + 1` cyclic buckets, 64-bit occupancy bitmap, active + bucket kept as a heap on `(-bottleneck, node)`). Dispatch is + `W <= 65536`; `SpfQueue::Heap` or `NGRAPH_CORE_SPF_QUEUE=heap` forces the + reference route, `Bucket`/`bucket` prefers the bucket queue when eligible. +- Scratch state is a thread-local workspace per direction with touched-node + tracking and a hybrid reset (sparse when fewer than a quarter of the nodes + were touched, wholesale otherwise; the same predicate chooses how outputs are + materialised). An RAII lease restores the invariant on every exit path, + including the reverse search's fanout exceptions. Arrays shrink when a much + smaller graph is searched; entry arrays and buckets keep their capacity. +- Tests: `ShortestPaths.QueueDifferential_Forward` / `_Reverse` (forced heap + against forced bucket over ten random graph families, the option matrix, + five destinations, twice on the reused workspace; more than 25,000 + comparisons), `_ComparisonHasTeeth`, `BucketQueueKeepsCapacityOrderedPredecessors`, + `WorkspaceIsResetAfterFanoutThrow`, `WorkspaceReuseAcrossGraphSizesAndEmptyGraphs`, + `StrictMultiDiGraph.CostSummaryMaxAndGcd`, and a Python test that runs the + same script under both `NGRAPH_CORE_SPF_QUEUE` values and unset. +- Documentation: README environment table and CHANGELOG (Unreleased). No + Python API change; `_docs.py` is unchanged. + +Gates passed on the final code (logs in [cpu_queue/](./)): + +- Old-versus-new bit-gate ([bitgate/](bitgate/)): a C++ program that + exercises forward and reverse SPF with fanout, `calc_max_flow` in every + placement mode, `batch_max_flow`, `sensitivity_analysis`, `FlowPolicy` + place/rebalance/remove sequences and KSP through the public API, built once + against the `fbab119` sources and once against the working tree. 6,226 + output lines, identical SHA-256, also with the new build forced onto the heap. +- `bash .superset/workspace.sh check`: lint, types, 177 C++ tests, 466 Python + tests. `make sanitize-test`: 177 C++ tests under ASan/UBSan. +- NetGraph `dev/check_core_integration.sh` against this worktree: a wheel built + in a fresh environment, 1,278 NetGraph tests passed. +- The research harness, rebuilt against the new production sources, still + matches its copies of the old loop across 1,351,168 comparisons on both + routes. + +One finding from the first old/new/old pass that the earlier experiment could +not show: the new code's *heap* route (the fallback for `W > 65536`) was 8–15% +slower than the old heap. Two causes were fixed: the scratch arrays were reached +through the thread-local struct, so their base pointers were reloaded around +every store (now hoisted to raw pointers for the search), and the heap +comparator was a static function that decays to a function pointer inside +`std::push_heap`/`pop_heap` (now a functor, as the old lambda was). The +measured tables below are from the final code. + +A second finding concerns measurement, not Core: NetGraph's failure Monte Carlo +results differ between processes of the *same* build unless `PYTHONHASHSEED` +is fixed (set-iteration order), so the NetGraph driver pins it; with the seed +fixed, old and new digests agree ([hashseed-determinism.txt](results/netgraph/hashseed-determinism.txt)). + +## Independent review (2 October 2026) + +An independent reviewer (the `gpt-6-astra` model through the `codex` CLI, brief +and full report in [cpu_queue/review-astra/](review-2026-10/)) was +asked whether all easily achievable, reasonable optimisations had been +considered and verified. Its verdict: the algorithm choice is sound and the +weighted-graph and small-query gains reproduce independently, but several +small changes were missed, one exception path was wrong, and the retained +memory statement was false. Each finding was re-verified here before adoption +(harness parity on both routes, the old-versus-new bit-gate, the repository +gates and a fresh old/new/old sequence; tables below are from the final code). + +Adopted: + +- **Exception safety (reviewer finding 1, reproduced).** The source or target + node's distance was written before its `touched.push_back`; a throwing + allocation there left an unrecorded modification that the next same-sized + search would see. Nodes are now recorded before their entries are written, + and `WorkspaceLease` documents that rule. +- **Skip settled neighbours before scanning their parallel edges (finding + 3).** A settled node cannot be improved with non-negative costs and no longer + accepts equal-cost or capacity-tie updates, so its group is skipped before + any edge or bottleneck is examined. Dense unit fabrics, which the earlier + passes recorded as neutral, now gain about 1.3x. +- **One-pass predecessor output (finding 4).** Implemented as a live per-node + count maintained by the search (exact sizing, no over-reservation) rather + than the reviewer's reserve-and-append variant; the second list walk is gone. +- **Inline single-item frontier (finding 5).** A frontier of one node is held + inline and promoted into the buckets on the next push; chain graphs improve + from about 2.1x slower to about 1.6x slower than the old heap. +- **Retention bound (finding 6, counterexample reproduced).** Bucket item + storage accumulated the high-water marks of every bucket ever used. The queue + now drops its item storage when it exceeds four times the last search's peak + frontier plus 4,096 items, the growable buffers are released whenever the + node arrays shrink, and the code comment and this plan describe the actual + policy instead of "at most the largest graph". +- **Bitmap bookkeeping (finding 8).** `begin`/`end` touched every occupancy + word (O(W/64) per search, measurable for tiny searches at large `W`); the + words set during a search are now listed and only those are cleared. +- **Fixed-routing callers (finding 2).** `calc_max_flow` and + `FlowState::place_max_flow` with `require_capacity=false` recomputed an + identical cost-only search on every tier; the result is now computed once per + invocation. Outputs are bit-identical (bit-gate). +- **Two redundant copies (findings 10 and 13).** `get_path_bundle` moves its + DAG into the returned pair, and the `spf`/`spf_to` bindings move the DAG into + the Python tuple instead of copying it. +- **Measurement corrections.** Reverse-search rows are now part of the Core + sequence (P2's gate was previously marked done without them); the unit-cost + rows are described as "no demonstrated regression" rather than "within + drift"; the heap-route delta is recorded as unexplained (the reviewer's + ablations of touched tracking, item layout and front-copy pop all showed no + gain); and the earlier claim that a distance-only API would remove the O(N) + output floor was wrong, since a distance vector still has N entries. + +Recorded as follow-ups, not done: + +- A narrower internal result for callers that only inspect `dist[dst]` or the + DAG (max-flow, FlowPolicy, KSP spur searches), which is the only lever left + for tiny searches on large graphs (finding 9). +- KSP's per-spur O(N+E) mask allocations and copies (finding 11), and + `place_on_dag`'s quadratic parent grouping on wide ECMP DAGs (finding 14), + both outside the search. +- `W_max` on a second platform, a two-level occupancy summary for very wide + ranges, and the reviewer's boundary rows (at `W` = 65,535–65,536 full + searches still gain about 1.4x while first-neighbour queries pay 9–17% + against the new heap route), which argue against raising the limit from the + full-search sweep alone (finding 8). +- A zero-copy int64 distance result in the bindings (finding 13), and the + stale `has_min_flow` memo-key discriminator in `FlowPolicy` (finding 10). +- Refuted by the reviewer: a gcd early-out in graph construction (finding 12). + +### Measured against the previous production build + +Both sequences ran one fresh process per phase in the order old (A1), new, +new forced onto the heap route, old (A2), on the final code (after the +independent review). The old build is the `fbab119` sources; the harness +binaries and the NetGraph extension modules are hashed in each +`environment.txt`. Load averages were 3.8–5.9 during both sequences because +other sessions were active; the desktop was not isolated, so differences under +about 5% are within run-to-run noise here. Earlier sequences on the +pre-review code are kept in the same directories' history +(the reviewer's own runs). + +Core level ([results-core](results/core/), harness `ref` = the +production function of each build, sequential, nine samples, medians in ms): + +| Workload: case / nodes / edges / queries / destination | W | Old A1 / A2 | New | New, forced heap | Old / new | +|---|---:|---:|---:|---:|---:| +| random / 1,024 / 8,192 / 1 / none | 32 | 0.107 / 0.102 | 0.067 | 0.089 | 1.52–1.60 | +| random / 4,096 / 32,768 / 256 / none | 32 | 211.6 / 207.6 | 132.6 | 221.3 | 1.57–1.60 | +| random / 16,384 / 131,072 / 64 / none | 32 | 254.4 / 250.6 | 150.9 | 266.1 | 1.66–1.69 | +| random / 65,536 / 524,288 / 1 / none | 32 | 21.21 / 19.03 | 11.51 | 23.14 | 1.65–1.84 | +| random, degree 32 / 4,096 / 131,072 / 64 / none | 32 | 112.0 / 110.6 | 77.1 | 115.4 | 1.43–1.45 | +| random, masked / 16,384 / 131,072 / 64 / none | 32 | 230.0 / 229.2 | 140.9 | 236.7 | 1.63 | +| random / 262,144 / 2,097,152 / 1 / none | 32 | 136.6 / 133.8 | 96.2 | 130.3 | 1.39–1.42 | +| random / 1,024 / 8,192 / 64 / farthest | 32 | 10.81 / 10.65 | 7.09 | 11.21 | 1.50–1.52 | +| random / 16,384 / 131,072 / 64 / farthest | 32 | 251.6 / 250.5 | 149.8 | 264.0 | 1.67–1.68 | +| random / 65,536 / 524,288 / 16 / farthest | 32 | 324.3 / 330.2 | 201.2 | 336.0 | 1.61–1.64 | +| uniform cost 31 / 16,384 / 131,072 / 64 / none | 2 | 181.4 / 177.1 | 146.3 | 178.6 | 1.21–1.24 | +| unit grid / 10,000 / 39,600 / 1 / none | 2 | 0.614 / 0.618 | 0.459 | 0.635 | 1.34–1.35 | +| unit fabric / 800 / 320,000 / 64 / none | 2 | 143.9 / 144.3 | 110.2 | 111.1 | 1.31 | +| pseudo src/sink fabric / 802 / 320,200 / 64 / fixed pair | 2 | 143.4 / 143.9 | 108.0 | 110.3 | 1.33 | +| chain / 2,048 / 2,047 / 1 / none | 32 | 0.021 / 0.021 | 0.027 | 0.029 | 0.77–0.78 | +| random / 1,024 / 8,192 / 64 / first neighbour | 32 | 0.116 / 0.115 | 0.043 | 0.038 | 2.70–2.72 | +| random / 16,384 / 131,072 / 64 / first neighbour | 32 | 1.160 / 1.158 | 0.402 | 0.392 | 2.88 | +| random / 65,536 / 524,288 / 64 / first neighbour | 32 | 4.351 / 4.254 | 1.506 | 1.517 | 2.83–2.89 | +| random / 262,144 / 2,097,152 / 16 / first neighbour | 32 | 4.509 / 4.053 | 1.491 | 1.471 | 2.72–3.02 | +| reverse: random / 4,096 / 32,768 / 64 | 32 | 55.85 / 55.34 | 34.23 | 58.82 | 1.62–1.63 | +| reverse: random / 16,384 / 131,072 / 16 | 32 | 66.55 / 66.34 | 38.67 | 69.33 | 1.72 | +| reverse: unit fabric / 800 / 320,000 / 16 | 2 | 45.43 / 45.72 | 37.15 | 36.90 | 1.22–1.23 | +| reverse: chain / 2,048 / 2,047 / 1 | 32 | 0.002 / 0.003 | 0.001 | 0.001 | 2.57–2.61 | + +Cost-range sweep (random 16,384 / 131,072, 16 full-source queries, costs in +`1..K`), same sequence: + +| K | W | Old A1 / A2 | New | New, forced heap | Old / new | +|---:|---:|---:|---:|---:|---:| +| 1 | 2 | 44.4 / 45.3 | 36.5 | 44.9 | 1.22–1.24 | +| 31 | 32 | 64.5 / 62.6 | 37.2 | 65.9 | 1.68–1.73 | +| 1,023 | 1,024 | 59.2 / 58.9 | 35.3 | 64.5 | 1.67–1.68 | +| 32,767 | 32,768 | 51.3 / 51.2 | 42.7 | 53.3 | 1.20 | +| 1,048,575 | heap fallback | 49.7 / 49.5 | 52.8 | 51.6 | 0.94 | +| 33,554,431 | heap fallback | 51.0 / 49.6 | 51.2 | 52.8 | 0.97–1.00 | + +NetGraph level ([results-netgraph](results/netgraph/), +[bench_netgraph.py](bench_netgraph.py) run by NetGraph's interpreter +against each build with `PYTHONHASHSEED=0`, five samples, medians in ms, every +workload's result digest identical across all four phases): + +| Workload | Old A1 / A2 | New | New, forced heap | Old / new | +|---|---:|---:|---:|---:| +| full-source `spf`, 2-tier Clos 200×200 (400 sources) | 214.2 / 212.7 | 163.4 | 164.6 | 1.30–1.31 | +| full-source `spf`, weighted grid 100×100 (50 sources) | 220.8 / 220.3 | 181.7 | 245.4 | 1.21–1.22 | +| bound-context `max_flow`, Clos 200×200, combine, ×50 | 52.6 / 51.9 | 47.1 | 46.8 | 1.10–1.12 | +| `max_flow` with 100 link-exclusion sets, Clos 100×100 | 44.3 / 43.0 | 40.4 | 39.3 | 1.06–1.10 | +| bound-context `max_flow`, weighted grid, combine, ×20 | 202.9 / 202.1 | 174.6 | 219.1 | 1.16 | +| `max_flow`, weighted grid, pairwise corners, ×5 | 204.0 / 200.6 | 208.2 | 212.9 | 0.96–0.98 | +| demand placement, backbone_clos matrix, ×50 | 69.2 / 67.4 | 69.0 | 68.7 | 0.98–1.00 | +| placement Monte Carlo, backbone_clos, 300 iterations | 74.5 / 75.3 | 67.8 | 71.4 | 1.10–1.11 | +| max-flow Monte Carlo, backbone_clos, 300 iterations | 29.3 / 29.1 | 27.6 | 29.0 | 1.06 | +| KSP k=8, 3-tier Clos, 56 leaf pairs | 54.7 / 53.4 | 46.3 | 46.2 | 1.15–1.18 | +| `max_flow`, 3-tier Clos, 56 pod pairs, combine | 167.5 / 166.1 | 168.2 | 171.8 | 0.99–1.00 | +| placement, 3-tier Clos, 64 WCMP + 8 ECMP demands | 366.4 / 363.3 | 376.3 | 368.9 | 0.97 | +| placement with 20 link-failure sets, 3-tier Clos | 7,646 / 7,548 | 7,640 | 7,571 | 0.99–1.00 | +| scenario square_mesh.yaml, 100 iterations, serial | 10.3 / 10.3 | 9.9 | 9.9 | 1.04 | +| scenario nsfnet.yaml, 200 iterations, serial | 958.2 / 939.1 | 929.6 | 912.2 | 1.01–1.03 | +| scenario backbone_clos.yml, 100 iterations, serial | 82.3 / 81.1 | 78.3 | 77.6 | 1.04–1.05 | + +Reading of the two sequences: + +- **Weighted graphs** (`W` between 32 and 32,768) gain 1.4–1.8x at the Core + level, forward and reverse, and 1.16–1.22x end to end on the weighted grid + workloads in NetGraph, where graph preparation, Python and placement share + the time. +- **Unit-cost fabrics** (`W = 2`), the class NetGraph's Clos scenarios and + pseudo source/sink max-flow graphs belong to, now gain 1.2–1.35x at the Core + level (settled-neighbour skip and one-pass output, adopted from the review) + and 1.06–1.3x through NetGraph's SPF, max-flow, KSP and Monte Carlo paths. + The wide-ECMP placement rows (0.97–1.00) are not a demonstrated regression: + they lie inside the run-to-run band and are dominated by placement, whose + quadratic parent grouping is a recorded follow-up. +- **Small destination-limited searches** gain 2.7–3.0x from the workspace + regardless of the queue (the forced-heap column matches the bucket column). +- **Fallback class** (`W > 65,536`): the two fallback rows are 0.94 and + 0.97–1.00 of the old heap; the forced-heap column on eligible graphs is + 0.82–0.97, which is the same unexplained route penalty. The reviewer's + ablations (touched tracking, item layout, front-copy pop) showed no gain, + so its cause remains open; it is recorded, not rationalised. +- **Chain graphs** are now 0.77x (about +6 µs on a 21 µs query) on the bucket + route after the inline single-item frontier, from 0.47x before. +- **Correctness**: every NetGraph workload digest was identical across old, + new and the forced heap; the Core parity, differential tests and the + old-versus-new bit-gate remain the semantic evidence, since these digests + only summarise distances and parent counts. + +## What the experiment established (27 September 2026) + +Harness: [cpu_queue/](./) is plain C++ (no Objective-C++ or Metal) and +compiles the production `shortest_paths.cpp` beside a copy of its forward loop +with the queue and workspace injected ([spf_variants.hpp](spf_variants.hpp), +[harness.cpp](harness.cpp)). Results are in +[cpu_queue/results](results/first/) and [cpu_queue/results-short](results/short/); +the earlier research results are untouched. + +**Parity.** 1,351,168 comparisons against the production `shortest_paths`, +bit-exact on distances, `parent_offsets`, `parents` and `via_edges`, over: twelve +masked random seeds, six graphs with zero-cost cycles, int64-offset costs (which +exercise the heap fallback), a unit grid, uniform cost 31, costs to 100,000, a +fabric with NetGraph-style zero-cost pseudo source/sink attachments, a chain, a +dense fabric and a 12-node multigraph with self-loops, parallel edges and +residuals at multiples of `kMinCap`; times `{multipath, single-path}` × +`{multi-edge, single-edge}` × `{Deterministic, PreferHigherResidual}` × +`{require_capacity}` × `{residual}` × `{masks}` × destinations `{none, first +neighbour, farthest, self, arbitrary}`, each run twice on a reused workspace. +Zero mismatches for every queue/workspace variant. The checker has teeth: +dropping the bottleneck key from the bucket comparator produces 167,636 +mismatches. ASan/UBSan runs of the same matrix are clean +([plain](results/first/correctness.txt), +[sanitized](results/first/correctness-sanitized.txt), +[teeth](results/first/correctness-teeth.txt)). + +**Timing.** Sequential, single thread, one process per variant, production +reference first and last (A1/A2), nine samples after two checked warmups, +medians in milliseconds for the whole query set, every timed result verified +against the reference outside the timed interval. `bucket` is the ordered bucket +queue; `fresh` allocates scratch per query as production does; `sparse` reuses a +workspace and resets only touched nodes; `hybrid` picks full or sparse reset +from the touched count after the search. Load average was 2.9–4.1 on 14 cores +throughout; the desktop was not isolated. + +| Workload: case / nodes / edges / queries / destination | W | Production A1 / A2 | bucket, fresh | bucket, sparse | bucket, hybrid | +|---|---:|---:|---:|---:|---:| +| random / 1,024 / 8,192 / 1 / none | 32 | 0.101 / 0.104 | 0.078 | 0.069 | — | +| random / 4,096 / 32,768 / 256 / none | 32 | 198.7 / 205.8 | 117.7 | 122.1 | — | +| random / 16,384 / 131,072 / 64 / none | 32 | 238.8 / 245.6 | 133.4 | 140.3 | 142.5 † | +| random / 65,536 / 524,288 / 1 / none | 32 | 18.38 / 19.63 | 10.96 | 10.68 | 10.80 † | +| random, degree 32 / 4,096 / 131,072 / 64 / none | 32 | 106.7 / 109.0 | 64.1 | 65.8 | — | +| random, masked / 16,384 / 131,072 / 64 / none | 32 | 219.5 / 225.3 | 130.6 | 138.4 | — | +| random / 262,144 / 2,097,152 / 1 / none | 32 | 119.7 / 125.2 | 83.6 | 87.0 | 84.5 † | +| random / 1,024 / 8,192 / 64 / farthest | 32 | 10.13 / 10.43 | 6.26 | 6.55 | — | +| random / 16,384 / 131,072 / 64 / farthest | 32 | 240.0 / 246.3 | 134.8 | 140.8 | — | +| random / 65,536 / 524,288 / 16 / farthest | 32 | 289.4 / 299.9 | 162.7 | 176.1 | — | +| uniform cost 31 / 16,384 / 131,072 / 64 / none | 2 | 170.3 / 175.4 | 142.4 | 140.7 | — | +| unit grid / 10,000 / 39,600 / 1 / none | 2 | 0.614 / 0.622 | 0.466 | 0.497 | — | +| unit fabric / 800 / 320,000 / 64 / none | 2 | 142.1 / 143.6 | 126.1 | 127.9 | 142.1 † | +| pseudo src/sink fabric / 802 / 320,200 / 64 / fixed pair | 2 | 140.6 / 142.2 | 125.5 | 127.2 | — | +| chain / 2,048 / 2,047 / 1 / none | 32 | 0.021 / 0.021 | 0.045 | 0.045 | 0.041 † | +| random / 1,024 / 8,192 / 64 / first neighbour | 32 | 0.105 / 0.120 | 0.111 | 0.043 | — | +| random / 16,384 / 131,072 / 64 / first neighbour | 32 | 1.044 / 1.171 | 1.190 | 0.393 | 0.390 † | +| random / 65,536 / 524,288 / 64 / first neighbour | 32 | 4.034 / 4.207 | 4.332 | 1.489 | 1.484 † | +| random / 262,144 / 2,097,152 / 16 / first neighbour | 32 | 3.872 / 3.997 | 4.090 | 1.449 | 1.442 † | + +† from the [second, shorter sequence](results/short/), whose own +production A1/A2 were 240.6 / 245.4, 18.51 / 18.77, 137.8 / 141.6, 0.021 / 0.023, +1.047 / 1.104, 4.206 / 4.305, 3.913 / 19.193 and 119.5 / 124.2 for the rows marked. + +Cost-range sweep, random 16,384 nodes / 131,072 edges, 16 full-source queries, +costs uniform in `1..K` ([sweep files](results/first/)): + +| K | W | Production | bucket, sparse | Ratio | +|---:|---:|---:|---:|---:| +| 1 | 2 | 43.7 | 35.2 | 1.24 | +| 31 | 32 | 62.1 | 35.8 | 1.74 | +| 1,023 | 1,024 | 58.2 | 34.1 | 1.71 | +| 32,767 | 32,768 | 50.0 | 35.0 | 1.43 | +| 1,048,575 | 1,048,576 | 48.6 | 46.8 | 1.04 | +| 33,554,431 | fallback | 48.9 | 56.5 (harness heap) | — | + +Interpretation to carry into implementation: + +- **Weighted graphs, `W` ≤ 32,768: 1.4–1.8x** over the production heap under + the full contract, sequentially, whether the query is full-source, farthest + destination or masked. Production A1/A2 drift was 2–7% on these rows (up to + 14% on sub-millisecond rows), so these clear the decision gate on this + machine. The 1,024-node single query improves 1.3–1.5x. +- **Uniform-cost graphs: 1.1–1.3x, and inconclusive on the dense fabric.** With + `W = 2` the queue is a small share of the work; edge scanning dominates the + 800-node fabric with 320,000 edges (0.97–1.13x across the two sequences). The + unit grid improves 1.32x, uniform cost 31 improves 1.2x. +- **Destination-limited queries that touch few nodes are bounded by O(N) + per-query overhead, not by the queue.** Production spends about 1.6 µs at + 1,024 nodes, 16 µs at 16,384, 63 µs at 65,536 and 242 µs at 262,144 per + first-neighbour query; the queue variant alone does not change this. Reusing + the workspace with a full reset changes nothing (consistent with the earlier + thread-local measurement recorded in the perf notes), while resetting only + touched nodes removes about 60% (2.4–3.0x). The remaining floor is the + N-sized `dist` and `parent_offsets` outputs that the API returns. +- **Hybrid reset is the right default:** it matches sparse on small queries and + full reset on full-graph queries, where sparse tracking costs 3–5%. +- **Chain graphs regress 1.7–2.1x (+15–24 µs on a 21 µs query)** in this + pre-implementation experiment (later reduced to 1.3x by the inline + single-item frontier adopted from the review). Every pop + advances the active bucket, so the per-pop bookkeeping (occupancy bitmap, + heap rebuild of a one-element bucket) exceeds a one-element binary heap. + Replacing the modulo by a power-of-two mask did not remove it. This is the + smallest absolute regression in the matrix and no production caller runs on + a path graph, but it is repeatable and must be recorded, not hidden. +- **Sorting each bucket once instead of heaping it is slower** on weighted + graphs (up to 8%) and equal on uniform graphs, except the unit grid (0.393 vs + 0.466). It is not worth a second queue. +- **The harness's own heap copy runs 7–14% slower than production** on the + random workloads. The cause is not isolated (candidates: the touched-node + branch per relaxation, runtime mode checks, scratch arrays reached through a + struct instead of locals). Production work must therefore be measured against + production, not against the harness heap, and P1 must check that its + workspace integration does not carry this penalty. The bucket gain is far + larger than the penalty. +- **Decomposition of the earlier prototype gain.** The research Dial package + reached 3.6x over native on the 16k/64 batch with ten workers and a relaxed + contract (no capacity ordering, canonical incoming-CSR DAG, cached eligibility + bitmap). The contract-preserving queue alone gives 1.8x sequentially. Roughly + half of the prototype's advantage came from dropping the contract and is not + available to production; the other half is. +- **One unattributed transient.** In two of twelve fresh-allocation phases the + 262,144-node first-neighbour set took 19 ms instead of 4 ms (once in the + harness heap copy, once in the production reference A2); none of fourteen + reused-workspace phases did. A page-fault probe in a fresh process showed + neither faults nor slowness. It is recorded as environmental variance, not as + a property of either implementation. +- Timings are sequential and cover synthetic graphs; ten-worker batch timings + from the research are not comparable row for row. No end-to-end flow + improvement is measured yet. + +## What the first consolidation overlooked + +1. **Every production caller is destination-limited.** `calc_max_flow`, + `FlowState::place_max_flow`, `FlowPolicy::get_path_bundle` and the KSP spur + searches all pass `dst`; only NetGraph's cost/DAG-cache paths call `spf` + without one. The earlier dispatch table sent destination-limited searches + to the existing implementation, which would have excluded the callers that + dominate placement time. Early-exit parity is now verified, so + destination-limited queries are in scope from the first enablement. +2. **Zero-cost edges are the normal case downstream.** NetGraph attaches pseudo + source/sink nodes with cost-0 augmentation edges, so "any zero-cost graph + stays on the heap" would have excluded every max-flow analysis. Zero-cost + pushes land in the active bucket's heap and are verified against the native + settled-node acyclicity rule; the dispatch condition is only `W`. +3. **The dominant fixed cost of small queries is O(N) scratch initialisation**, + which no queue change touches; touched-node reset addresses it and was not + in the previous plan (which specified a complete reset). +4. **Uniform non-unit costs** are covered by the gcd stride rather than by a + separate BFS; they were previously flagged as untested. +5. **Reverse SPF** (`shortest_paths_to_core`) has the same queue and takes the + same substitution mechanically; it is not yet measured. KSP's private + `dijkstra_single` is a cost-only search on a different key and is out of + scope for the first change. +6. **Ordered parity is not an open research question**; it follows from queue + monotonicity. The plan no longer needs "investigate per-layer ordering" or + "a LIFO vector is not sufficient" as open items. + +## Contract and fallback rules + +Keep `Cost=int64_t`, `Cap=double`, the unreachable sentinel and graph cost-sum +bound. Preserve validation, empty graphs, invalid/blocked endpoints, masks, +reverse DAG orientation, parallel-edge IDs, multipath selection, single-path +capacity ties, destination early exit and `fanout_edges` behaviour. The queue +key stays `(distance, -bottleneck_capacity, node_id)` with the existing +`kEpsilon` stale-entry and re-push semantics; boolean eligibility cannot replace +the capacity values used for ordering. SPF excludes `rem < kMinCap` when +capacity gating applies; a supplied residual forces that gate. + +Dispatch is a graph property, decided before the search starts: + +| Condition | Route | +|---|---| +| `W = max_cost / gcd + 1 ≤ W_max` (any mix of zero and positive costs, any selection mode, any destination, forward or reverse once P2 lands) | Ordered bucket queue | +| `W > W_max` (wide or int64-offset costs) | Existing heap | +| Forced reference (tests, benchmarks) | Existing heap | + +`W_max` starts at 65,536 (2^16): the sweep shows 1.4x at `W = 32,768` and +break-even near `W = 2^20`. Memory per workspace is `W` empty vector headers +plus a `W`-bit occupancy bitmap, about 1.6 MB at the limit. Widening the range +(two-level occupancy summary, or a radix heap whose last level is ordered the +same way) is later work with its own sweep. The graph-level `max_cost` is an +upper bound for every masked query, so no per-query rescan is needed; a +masked-out wide edge merely wastes empty buckets. + +## Implementation sequence + +### P0 — Parity oracle and forced route (done) + +The harness is the parity oracle. Before production work, add the equivalent +differential test to [tests/cpp](../../../tests/cpp/shortest_paths_tests.cpp): +the forced-heap route against the dispatched route over random graphs, the +option matrix and the destination set above, bit-exact on all four output +arrays, plus a guard test proving the comparison rejects a wrong ordering. +Forcing must be reachable from tests and benchmarks without a public API +(an internal function parameter or a build/env switch used only there). + +Keep the measured originals and hashes intact; write new results to new +directories. Dynamic profiling of NetGraph callers (full versus +destination-limited counts, touched fraction, weight range) remains useful for +the downstream gate but no longer blocks the first enablement, because both +call classes are covered. + +**Exit:** differential test with teeth in the C++ suite; forced route available. + +### P1 — Queue and workspace in the forward search (done) + +Work in [shortest_paths.cpp](../../../src/shortest_paths.cpp) and +[strict_multidigraph.cpp](../../../src/strict_multidigraph.cpp): + +- Record `max_cost` and the cost gcd in `from_arrays`'s existing cost scan as + members, so they follow copies and moves; no process-global cache keyed by a + graph address. +- Replace the priority queue in `shortest_paths_core` with the ordered bucket + queue when `W ≤ W_max`; keep the heap code path intact for the fallback and + the forced route. Keep the relaxation loop shared between routes (one loop, + two queue types), as the harness does, so parity is structural. +- Give the search a reusable workspace (distances, bottlenecks, predecessor + heads/tails, settled flags, entry arrays, queue buckets) with touched-node + tracking and the hybrid reset. Concurrency: `batch_max_flow` and + `sensitivity_analysis` run on `std::async` threads and Python callers release + the GIL, so the workspace must be per thread (thread-local) or caller-owned; + it must hold no pointer into a graph, residual or mask. Bound retained memory: + one workspace per thread sized to the largest graph seen, and state the bound + (or add a shrink rule) in the code comment and in `_docs.py` if it is + observable. Returned vectors must own their data. +- Early exit leaves items in buckets; clear only occupied buckets. + +**Exit:** the existing positive-cost SPF output hash and the flow output hash +from the August review are unchanged; the differential test passes; the full +suite and `make sanitize-test` pass; A/B/A against `main` on the harness +workloads reproduces the table above within drift, including the recorded +chain regression; no new implicit threads. + +### P2 — Reverse search and KSP (done for the reverse search) + +Apply the same substitution to `shortest_paths_to_core` (same key, in-adjacency) +and measure it with reverse workloads added to the harness. Leave KSP's +`dijkstra_single` alone unless profiling shows it matters. + +**Exit:** parity for reverse results including `fanout_edges`, and a measured +result either way. + +### P3 — Limits, regressions and dispatch review (fallback reviewed; second machine class pending) + +Confirm `W_max` on a second machine class (Linux/x86 CI-class hardware), and +decide the chain-like regime: the inline single-item frontier cut the recorded +regression to about 6 µs on a 21 µs query; either accept that residual on +frontier-of-one searches or reduce the per-pop advance cost and re-measure. Do +not choose the queue per query retrospectively; the rule stays a graph property. + +**Exit:** dispatch rule frozen with a held-out workload pass. + +### P4 — Downstream validation, then batching and GPU reconsideration (validation done; batching/GPU unchanged) + +Run NetGraph's profiles and representative demand/flow runs with the chosen +Core build, including residual updates, mask changes, cache hit/miss cases, +all placement modes and path-cost constraints. For max-flow behaviour, check +feasibility, conservation and optimality/cut certificates with nonuniform +costs, masks and cost-factor cases; SPF distance agreement alone does not +satisfy this gate. + +Explicit CPU batching stays conditional on demonstrated independent-query +callers: deterministic result order, bounded worker count, per-worker scratch +and bounded output memory. Sequential flow augmentations with changing +residuals cannot be batched as if independent. Any public batch or +distance-only extension must preserve current defaults and update bindings and +`_docs.py` together; a distance-only result would also remove the O(N) output +floor measured above, which is the only remaining lever for tiny queries on +large graphs. It is not a prerequisite for shipping this change. + +Revisit GPU only against the accepted CPU implementation and matching result +contracts; this plan does not require Metal, GPU frontier queues or automatic +CPU/GPU selection. + +## Acceptance and validation + +Correctness gates precede performance claims. Cover forward/reverse results, +both edge tie-break policies, multipath/single-path, multi-edge/single-edge, +parallel edges, self-loops, zero-cost cycles, isolated vertices, empty graphs, +invalid and blocked endpoints, all-masked graphs and malformed spans. Include +costs above `2^53`, near the constructor's bound, `W` at and just above +`W_max`, long chains, duplicate/stale queue entries, uniform non-unit weights, +and capacity values at/around `kMinCap` and the tie epsilon. Mutate masks and +residual contents in place between calls, including changes that leave +eligibility unchanged. Verify graph lifetime, workspace reuse across graphs of +different sizes, concurrent callers, repeated determinism, fanout validation, +target early exit and capped enumeration. + +Relevant existing suites include [C++ SPF](../../../tests/cpp/shortest_paths_tests.cpp), +[masking](../../../tests/cpp/masking_tests.cpp), +[Python edge selection](../../../tests/py/test_spf_edge_select.py), +[path enumeration](../../../tests/py/test_paths_resolve.py), +[reverse SPF](../../../tests/py/test_spf_to.py), +[memoisation](../../../tests/py/test_flow_policy_spf_memo.py), +[thread safety](../../../tests/py/test_thread_safety.py), and +[lifetime safety](../../../tests/py/test_lifetime_safety.py). + +For each change, run correctness-checked old/new/old in fresh processes on one +quiet machine, same build settings, with builds/tests excluded from the timed +run. Record raw samples, hashes, workload parameters, load, fallback counts and +peak memory. Keep warm reused-query timing, first-query timing and +changing-input end-to-end timing separate. Ship a class only when the new median +improves beyond both A1/A2 drift and sample variability, with no unrecorded +regression in its supported classes or reference fallback. A single M4 result +is insufficient to set `W_max` for every supported platform. + +Reproduce the experiment from the repository root: + +```sh +bash dev/perf/spf_queue/build.sh +build/perf/cpu-queue correctness +bash dev/perf/spf_queue/run_aba.sh +python3 dev/perf/spf_queue/summarize.py +bash dev/perf/spf_queue/build.sh sanitize +ASAN_OPTIONS=detect_leaks=0 build/perf/cpu-queue-sanitize correctness +``` + +For implementation changes, run: + +```sh +bash .superset/workspace.sh setup # when the worktree environment needs setup +bash .superset/workspace.sh check # rebuild extension, lint, types, C++ and Python +make sanitize-test # required for C++ changes +bash /Users/networmix/ws/NetGraph/dev/check_core_integration.sh \ + /absolute/path/to/the/chosen/NetGraph-Core-worktree +``` + +Use the actual worktree's absolute path for downstream verification. Local +checks do not replace CI. The prior research passed 170 C++ and 465 Python +tests plus sanitizers; that is baseline evidence, not completion of any +implementation gate. + +**Immediate next step:** review and commit the working-tree change (a +version bump and CHANGELOG date at release time), then confirm `W_max` on a +Linux/x86 CI-class machine before treating the chain-graph and wide-cost +fallback numbers as portable. Batching and GPU work remain later, conditional +items. diff --git a/dev/perf/spf_queue/README.md b/dev/perf/spf_queue/README.md new file mode 100644 index 0000000..9b1c88d --- /dev/null +++ b/dev/perf/spf_queue/README.md @@ -0,0 +1,65 @@ +# Ordered bucket queue experiment (CPU only) + +Plain C++ harness (no Objective-C++ or Metal) behind the +[CPU optimisation plan](PLAN.md). It compiles the production +`src/shortest_paths.cpp` next to a copy of its forward search loop in which only +the priority queue and the scratch workspace are pluggable, then checks every +variant bit-exactly against the production function and times them. + +- `spf_variants.hpp`: `HeapQueue` (production key), `BucketHeapQueueT` (monotone + cyclic buckets, active bucket kept as a heap on `(-bottleneck, node)`; the + `` instantiation masks instead of taking a modulo), `BucketSortQueue` + (sorted active bucket plus a side heap), `Workspace` (fresh, full reset, + sparse reset, hybrid reset) and `spf_variant`, the shared loop. +- `harness.cpp`: workload generators (the research generator verbatim, plus + uniform, wide, zero-cost-cycle and pseudo source/sink cases), the parity + matrix, timing and the cost-range sweep. Variant names are + `{ref, heap, bucket, bucket2, bsort}-{fresh, full, sparse, hybrid}`. +- `run_aba.sh`: one fresh process per variant, production reference first and + last, plus the sweep. `summarize.py` prints Markdown tables. +- `results/first/`: the first sequence (nine samples), sweep files, load readings, + source hashes and the parity outputs (plain, sanitized and the teeth check + built with `-DSPFX_BAD_ORDER`, which must fail). `results/short/`: the second + sequence for the hybrid and power-of-two variants. + +```sh +bash dev/perf/spf_queue/build.sh +build/perf/cpu-queue correctness +build/perf/cpu-queue time bucket-hybrid 9 +build/perf/cpu-queue sweep bucket-sparse 9 2097152 +bash dev/perf/spf_queue/run_aba.sh +python3 dev/perf/spf_queue/summarize.py +``` + +Timings are sequential and single-threaded; they are not comparable row for row +with the ten-worker batch timings in the research reports. + +## Production verification (after the change landed in `src/shortest_paths.cpp`) + +- `bitgate/dump.cpp`: exercises forward/reverse SPF, max-flow, batch max-flow, + sensitivity, `FlowPolicy` sequences and KSP through the public C++ API; built + once against the previous sources (`git archive` of the base commit) and once + against the working tree. `bitgate/sha256.txt` records the identical digests + of `old.txt` and `new.txt` (and of the new build forced onto the heap route). +- `run_core_aba.sh` + `results/core/` (+ `summarize_core.py`): old/new/old on + the harness workloads, where `ref` is the production function of the sources + each binary was built from (`cpu-queue-old` is built from a `git archive` of + the base commit); `b-new-heap` forces the heap route in the new binary as an + in-binary control. +- `bench_netgraph.py` + `run_netgraph_aba.sh` + `results/netgraph/`: old/new/old + on NetGraph workloads run through NetGraph's own API and interpreter (full + SPF, bound-context max-flow with pseudo nodes, failure exclusions, demand + placement with WCMP and ECMP policies, failure Monte Carlo, KSP, and three of + the shipped scenarios end to end with `parallelism: 1`). Each workload + returns a checksum that must agree across builds; `summarize_netgraph.py` + tabulates medians and checks the checksums. The driver pins + `PYTHONHASHSEED=0`: NetGraph's Monte Carlo digests otherwise differ between + two processes of the same build (`results/netgraph/hashseed-determinism.txt`). +- `review-2026-10/`: brief, full report, patches, experiment sources and + raw results of the independent review (2 October 2026); what was adopted + from it is listed in the plan. Its full-source experimental copies, session + log and 10 MB bit-gate dumps were not kept (they are reproducible from the + patches against the base commit). `bash build.sh old` builds the + old-source harness binary from `git archive` of the base commit. +- Timing modes now include reverse-search rows (`dst` = `reverse`), which are + production-only (the harness variants implement the forward loop). diff --git a/dev/perf/spf_queue/bench_netgraph.py b/dev/perf/spf_queue/bench_netgraph.py new file mode 100644 index 0000000..3424d75 --- /dev/null +++ b/dev/perf/spf_queue/bench_netgraph.py @@ -0,0 +1,393 @@ +#!/usr/bin/env python3 +"""Realistic NetGraph workloads for the Core old/new A/B/A. + +Run with NetGraph's interpreter and PYTHONPATH pointing at the Core build under +test (see run_netgraph_aba.sh). Prints CSV rows: + workload,label,median_s,samples,checksum,samples_s +Every workload returns a checksum of its results that must be identical across +builds; the driver compares them. +""" + +from __future__ import annotations + +import hashlib +import json +import random +import statistics +import sys +import time +from pathlib import Path + +NETGRAPH = Path.home() / "ws" / "NetGraph" +sys.path.insert(0, str(NETGRAPH)) + +import numpy as np # noqa: E402 +from ngraph.analysis import FailureManager # noqa: E402 +from ngraph.analysis.context import AnalysisContext # noqa: E402 +from ngraph.analysis.functions import demand_placement_analysis # noqa: E402 +from ngraph.model.network import Link, Network, Node # noqa: E402 +from ngraph.scenario import Scenario # noqa: E402 +from ngraph.types.base import Mode # noqa: E402 + +import netgraph_core # noqa: E402 + + +def norm(obj): + """JSON-safe, order-stable view of nested results (tuple keys become strings).""" + if isinstance(obj, dict): + skip = { + "metadata", + "execution_time", + "duration", + "timestamp", + "started_at", + "finished_at", + "run_id", + "id", + } + return { + str(k): norm(v) + for k, v in sorted(obj.items(), key=lambda kv: str(kv[0])) + if str(k) not in skip + } + if isinstance(obj, (list, tuple, set, frozenset)): + items = [norm(v) for v in obj] + return sorted(items, key=str) if isinstance(obj, (set, frozenset)) else items + if isinstance(obj, float): + return repr(obj) + if isinstance(obj, (str, int, bool)) or obj is None: + return obj + if hasattr(obj, "to_dict"): + return norm(obj.to_dict()) + return str(obj) + + +def digest(obj) -> str: + return hashlib.sha256(json.dumps(norm(obj), sort_keys=True).encode()).hexdigest()[ + :16 + ] + + +def clos(leaves: int, spines: int, cap: float = 100.0) -> Network: + net = Network() + for i in range(leaves): + net.add_node(Node(f"leaf/leaf{i:03d}")) + for j in range(spines): + net.add_node(Node(f"spine/spine{j:03d}")) + for i in range(leaves): + for j in range(spines): + net.add_link( + Link(f"leaf/leaf{i:03d}", f"spine/spine{j:03d}", capacity=cap, cost=1.0) + ) + return net + + +def grid(rows: int, cols: int, seed: int = 3) -> Network: + rng = random.Random(seed) + net = Network() + for r in range(rows): + for c in range(cols): + net.add_node(Node(f"g/r{r:03d}c{c:03d}")) + for r in range(rows): + for c in range(cols): + if c + 1 < cols: + net.add_link( + Link( + f"g/r{r:03d}c{c:03d}", + f"g/r{r:03d}c{c + 1:03d}", + capacity=10.0, + cost=float(rng.randint(1, 20)), + ) + ) + if r + 1 < rows: + net.add_link( + Link( + f"g/r{r:03d}c{c:03d}", + f"g/r{r + 1:03d}c{c:03d}", + capacity=10.0, + cost=float(rng.randint(1, 20)), + ) + ) + return net + + +def clos3(pods: int, leaves: int, spines: int, supers: int) -> Network: + """Three-tier Clos: per pod a leaf/spine mesh, spines meshed to super-spines.""" + net = Network() + for k in range(supers): + net.add_node(Node(f"ss/ss{k:03d}")) + for p in range(pods): + for i in range(leaves): + net.add_node(Node(f"pod{p:02d}/leaf/leaf{i:03d}")) + for j in range(spines): + net.add_node(Node(f"pod{p:02d}/spine/spine{j:03d}")) + for i in range(leaves): + for j in range(spines): + net.add_link( + Link( + f"pod{p:02d}/leaf/leaf{i:03d}", + f"pod{p:02d}/spine/spine{j:03d}", + capacity=100.0, + cost=1.0, + ) + ) + for j in range(spines): + for k in range(supers): + net.add_link( + Link( + f"pod{p:02d}/spine/spine{j:03d}", + f"ss/ss{k:03d}", + capacity=400.0, + cost=1.0, + ) + ) + return net + + +def scenario_text(name: str, iterations: int) -> str: + path = NETGRAPH / "scenarios" / name + text = path.read_text() + text = text.replace("parallelism: auto", "parallelism: 1").replace( + "parallelism: 8", "parallelism: 1" + ) + text = text.replace("iterations: 1000", f"iterations: {iterations}") + return text + + +def results_digest(scenario: Scenario) -> str: + out = {} + for step in scenario.results.get_steps_by_execution_order(): + data = scenario.results.get_step(step) + out[step] = {k: v for k, v in data.items() if k not in ("metadata",)} + return digest(out) + + +def build_workloads() -> dict[str, tuple[callable, int]]: + """Return name -> (fn returning checksum, inner repetitions).""" + wl: dict[str, tuple[callable, int]] = {} + sel = netgraph_core.EdgeSelection( + multi_edge=True, + require_capacity=False, + tie_break=netgraph_core.EdgeTieBreak.DETERMINISTIC, + ) + + clos200 = clos(200, 200) + ctx_clos200 = AnalysisContext.from_network(clos200) + n_clos = ctx_clos200.multidigraph.num_nodes() + + def spf_clos(): + acc = [] + for s in range(n_clos): + dist, dag = ctx_clos200.algorithms.spf(ctx_clos200.handle, s, selection=sel) + acc.append((int(np.asarray(dist).sum()), int(len(dag.parents)))) + return digest(acc) + + wl["spf_full_clos_200x200"] = (spf_clos, 1) + + grid100 = grid(100, 100) + ctx_grid = AnalysisContext.from_network(grid100) + + def spf_grid(): + acc = [] + for s in range(0, 10000, 200): + dist, dag = ctx_grid.algorithms.spf(ctx_grid.handle, s, selection=sel) + d = np.asarray(dist) + acc.append((int(d[d < 2**62].sum()), int(len(dag.parents)))) + return digest(acc) + + wl["spf_full_grid_100x100_weighted"] = (spf_grid, 5) + + ctx_mf_clos = AnalysisContext.from_network( + clos200, + source="^leaf/leaf00[0-9]$", + sink="^leaf/leaf19[0-9]$", + mode=Mode.COMBINE, + ) + wl["maxflow_clos_200x200_combine"] = (lambda: digest(ctx_mf_clos.max_flow()), 50) + + clos100 = clos(100, 100) + ctx_fail = AnalysisContext.from_network( + clos100, + source="^leaf/leaf00[0-9]$", + sink="^leaf/leaf09[0-9]$", + mode=Mode.COMBINE, + ) + link_ids = sorted(clos100.links) + rng = random.Random(11) + exclusions = [set(rng.sample(link_ids, 12)) for _ in range(100)] + + def maxflow_failures(): + return digest([ctx_fail.max_flow(excluded_links=ex) for ex in exclusions]) + + wl["maxflow_failures_clos_100x100_x100"] = (maxflow_failures, 1) + + ctx_mf_grid = AnalysisContext.from_network( + grid100, source="^g/r00[0-9]c000$", sink="^g/r09[0-9]c099$", mode=Mode.COMBINE + ) + wl["maxflow_grid_100x100_weighted_combine"] = ( + lambda: digest(ctx_mf_grid.max_flow()), + 20, + ) + wl["maxflow_grid_100x100_weighted_pairwise"] = ( + lambda: digest( + AnalysisContext.from_network( + grid100, source="^g/r000c000$", sink="^g/r099c099$", mode=Mode.PAIRWISE + ).max_flow() + ), + 5, + ) + + backbone = Scenario.from_yaml(scenario_text("backbone_clos.yml", 1000)) + demands = [ + td.to_dict() for td in backbone.demand_set.get_set("baseline_traffic_matrix") + ] + wl["placement_backbone_clos"] = ( + lambda: digest( + demand_placement_analysis(backbone.network, set(), set(), demands) + ), + 50, + ) + + fm = FailureManager( + network=backbone.network, + failure_policy_set=backbone.failure_policy_set, + policy_name="weighted_modes", + ) + wl["placement_mc_backbone_clos_x300"] = ( + lambda: digest( + fm.run_demand_placement_monte_carlo( + demands_config=demands, iterations=300, parallelism=1, seed=42 + ) + ), + 1, + ) + wl["maxflow_mc_backbone_clos_x300"] = ( + lambda: digest( + fm.run_max_flow_monte_carlo( + source="^metro1/dc1/.*", + target="^metro2/dc1/.*", + mode="combine", + iterations=300, + parallelism=1, + seed=7, + ) + ), + 1, + ) + + fabric = clos3(pods=8, leaves=16, spines=8, supers=16) + ctx_fabric = AnalysisContext.from_network(fabric) + wl["ksp_clos3_pairwise_k8"] = ( + lambda: digest( + { + f"{k[0]}->{k[1]}": [str(p) for p in v] + for k, v in ctx_fabric.k_shortest_paths( + "^pod00/leaf/leaf00[0-3]$", + "^pod0[1-7]/leaf/leaf00[0-1]$", + mode=Mode.PAIRWISE, + max_k=8, + ).items() + } + ), + 1, + ) + wl["maxflow_clos3_pod_pairs_combine"] = ( + lambda: digest( + [ + AnalysisContext.from_network( + fabric, + source=f"^pod{a:02d}/leaf/.*", + sink=f"^pod{b:02d}/leaf/.*", + mode=Mode.COMBINE, + ).max_flow() + for a in range(8) + for b in range(8) + if a != b + ] + ), + 1, + ) + fabric_demands = [ + { + "source": f"^pod{a:02d}/leaf/.*", + "target": f"^pod{b:02d}/leaf/.*", + "mode": "pairwise", + "priority": 0, + "volume": 2000.0, + "flow_policy": policy, + } + for a in range(8) + for b in range(8) + if a != b + for policy in ("TE_WCMP_UNLIM",) + ] + [ + { + "source": f"^pod{a:02d}/leaf/.*", + "target": f"^pod{(a + 1) % 8:02d}/leaf/.*", + "mode": "pairwise", + "priority": 1, + "volume": 500.0, + "flow_policy": "SHORTEST_PATHS_ECMP", + } + for a in range(8) + ] + wl["placement_clos3_wcmp_and_ecmp"] = ( + lambda: digest(demand_placement_analysis(fabric, set(), set(), fabric_demands)), + 1, + ) + fabric_links = sorted(fabric.links) + rng2 = random.Random(5) + fabric_exclusions = [set(rng2.sample(fabric_links, 6)) for _ in range(20)] + wl["placement_clos3_failures_x20"] = ( + lambda: digest( + [ + demand_placement_analysis(fabric, set(), ex, fabric_demands) + for ex in fabric_exclusions + ] + ), + 1, + ) + + def run_scenario(name: str, iterations: int): + def fn(): + sc = Scenario.from_yaml(scenario_text(name, iterations)) + sc.run() + return results_digest(sc) + + return fn + + wl["scenario_square_mesh_iter100"] = (run_scenario("square_mesh.yaml", 100), 1) + wl["scenario_nsfnet_iter200"] = (run_scenario("nsfnet.yaml", 200), 1) + wl["scenario_backbone_clos_iter100"] = (run_scenario("backbone_clos.yml", 100), 1) + return wl + + +def main() -> int: + label = sys.argv[1] if len(sys.argv) > 1 else "run" + samples = int(sys.argv[2]) if len(sys.argv) > 2 else 5 + only = sys.argv[3].split(",") if len(sys.argv) > 3 else None + wl = build_workloads() + print("workload,label,median_s,samples,checksum,samples_s", flush=True) + for name, (fn, reps) in wl.items(): + if only and name not in only: + continue + checksum = fn() # warm-up and reference checksum + times = [] + for _ in range(samples): + t0 = time.perf_counter() + for _ in range(reps): + c = fn() + times.append(time.perf_counter() - t0) + if c != checksum: + raise SystemExit( + f"nondeterministic result in {name}: {c} != {checksum}" + ) + print( + f"{name},{label},{statistics.median(times):.6f},{samples},{checksum},{';'.join(f'{t:.6f}' for t in times)}", + flush=True, + ) + return 0 + + +if __name__ == "__main__": + raise SystemExit(main()) diff --git a/dev/perf/spf_queue/bitgate/dump.cpp b/dev/perf/spf_queue/bitgate/dump.cpp new file mode 100644 index 0000000..1ef7ba4 --- /dev/null +++ b/dev/perf/spf_queue/bitgate/dump.cpp @@ -0,0 +1,157 @@ +// Old-versus-new output bit-gate. Built once against the previous sources and +// once against the working tree; the SHA-256 of stdout must match. Exercises +// forward/reverse SPF, max-flow, batch max-flow, sensitivity, FlowPolicy +// placement sequences and KSP through the public C++ API only. +#include "netgraph/core/algorithms.hpp" +#include "netgraph/core/backend.hpp" +#include "netgraph/core/constants.hpp" +#include "netgraph/core/flow_graph.hpp" +#include "netgraph/core/flow_policy.hpp" +#include "netgraph/core/k_shortest_paths.hpp" +#include "netgraph/core/max_flow.hpp" +#include "netgraph/core/options.hpp" +#include "netgraph/core/shortest_paths.hpp" +#include "netgraph/core/strict_multidigraph.hpp" + +#include +#include +#include +#include + +using namespace netgraph::core; + +struct Case { + StrictMultiDiGraph g; + std::unique_ptr nm, em; + std::vector residual; + NodeId src = 0, dst = 1; + std::span nmask() const { return {nm.get(), size_t(g.num_nodes())}; } + std::span emask() const { return {em.get(), size_t(g.num_edges())}; } +}; + +static Case make(unsigned seed, int n, int degree, Cost max_cost, int zero_pct, bool duplex, bool pseudo) { + std::mt19937 rng(seed); + std::vector s, d; std::vector cap; std::vector cost; + auto add = [&](int u, int v, Cost c, double k) { s.push_back(u); d.push_back(v); cost.push_back(c); cap.push_back(k); }; + for (int u = 0; u < n; ++u) for (int k = 0; k < degree; ++k) { + int v = k == 0 ? (u + 1) % n : int(rng() % n); + Cost c = (int(rng() % 100) < zero_pct) ? 0 : 1 + Cost(rng() % unsigned(max_cost)); + double w = 1.0 + double(rng() % 100) / 7.0; + add(u, v, c, w); if (duplex) add(v, u, c, w); + } + Case c; + NodeId src = 0, dst = n / 2; + int total = n; + if (pseudo) { + int k = std::max(1, n / 8); + for (int u = 0; u < k; ++u) add(n, u, 0, 1e9); + for (int u = n - k; u < n; ++u) add(u, n + 1, 0, 1e9); + src = n; dst = n + 1; total = n + 2; + } + c.g = StrictMultiDiGraph::from_arrays(total, s, d, cap, cost); + c.src = src; c.dst = dst; + int N = c.g.num_nodes(), E = c.g.num_edges(); + c.nm = std::make_unique(N); c.em = std::make_unique(E); + for (int i = 0; i < N; ++i) c.nm[i] = rng() % 29 != 0 || i == src || i == dst; + for (int i = 0; i < E; ++i) c.em[i] = rng() % 13 != 0; + c.residual.assign(c.g.capacity_view().begin(), c.g.capacity_view().end()); + for (int i = 0; i < E; ++i) if (rng() % 11 == 0) c.residual[i] = (rng() % 2) ? 0.0 : kMinCap / 2; + return c; +} + +static void dump_res(const std::pair, PredDAG>& r) { + for (auto v : r.first) std::printf("%lld,", (long long)v); + std::printf("|"); + for (auto v : r.second.parent_offsets) std::printf("%d,", v); + std::printf("|"); + for (auto v : r.second.parents) std::printf("%d,", v); + std::printf("|"); + for (auto v : r.second.via_edges) std::printf("%d,", v); + std::printf("\n"); +} + +static void dump_summary(double total, const FlowSummary& sm) { + std::printf("flow %.17g cut:", total); + for (auto e : sm.min_cut.edges) std::printf("%d,", e); + std::printf(" costs:"); + for (size_t i = 0; i < sm.costs.size(); ++i) std::printf("%lld=%.17g,", (long long)sm.costs[i], sm.flows[i]); + std::printf(" ef:"); + for (auto f : sm.edge_flows) std::printf("%.17g,", f); + std::printf("\n"); +} + +int main() { + auto be = make_cpu_backend(); + auto algs = std::make_shared(be); + std::vector cases; + cases.push_back(make(1, 60, 4, 31, 0, true, false)); + cases.push_back(make(2, 80, 3, 31, 20, true, true)); + cases.push_back(make(3, 120, 5, 1, 0, true, true)); + cases.push_back(make(4, 90, 4, 20, 10, false, false)); + cases.push_back(make(5, 200, 3, 1000, 5, true, true)); + cases.push_back(make(6, 40, 6, 4, 30, true, false)); + for (auto& c : cases) { + const int n = c.g.num_nodes(); + std::printf("# case n=%d e=%d\n", n, c.g.num_edges()); + // Forward and reverse SPF over the option matrix. + for (NodeId s : {c.src, NodeId(3), NodeId(n - 1)}) for (int mp = 0; mp < 2; ++mp) for (int me = 0; me < 2; ++me) + for (int tb = 0; tb < 2; ++tb) for (int rc = 0; rc < 2; ++rc) for (int ur = 0; ur < 2; ++ur) for (int um = 0; um < 2; ++um) { + EdgeSelection sel; sel.multi_edge = me; sel.require_capacity = rc; + sel.tie_break = tb ? EdgeTieBreak::PreferHigherResidual : EdgeTieBreak::Deterministic; + auto res = ur ? std::span(c.residual) : std::span{}; + auto nm = um ? c.nmask() : std::span{}; + auto em = um ? c.emask() : std::span{}; + for (std::optional dst : {std::optional{}, std::optional{c.dst}, std::optional{NodeId((s + 1) % n)}}) + dump_res(shortest_paths(c.g, s, dst, mp, sel, res, nm, em)); + const auto row = c.g.row_offsets_view(); const auto aei = c.g.adj_edge_index_view(); + std::vector fan(aei.begin() + row[c.src], aei.begin() + row[c.src + 1]); + dump_res(shortest_paths_to(c.g, s, mp, sel, res, nm, em, {})); + if (c.src >= n - 2) dump_res(shortest_paths_to(c.g, c.dst, mp, sel, res, nm, em, fan)); // pseudo source fan-out + } + // Max-flow matrix. + for (int pl = 1; pl <= 3; ++pl) for (int sp = 0; sp < 2; ++sp) for (int rc = 0; rc < 2; ++rc) for (int um = 0; um < 2; ++um) { + auto nm = um ? c.nmask() : std::span{}; + auto em = um ? c.emask() : std::span{}; + auto [total, sm] = calc_max_flow(c.g, c.src, c.dst, static_cast(pl), sp, rc, true, true, true, nm, em); + dump_summary(total, sm); + } + auto gh = algs->build_graph(c.g); + MaxFlowOptions mo; mo.with_edge_flows = true; + std::vector> pairs; + for (int i = 0; i < 12; ++i) pairs.emplace_back(NodeId((i * 7) % n), NodeId((i * 11 + 5) % n)); + for (auto& sm : algs->batch_max_flow(gh, pairs, mo)) dump_summary(sm.total_flow, sm); + for (auto& [e, f] : algs->sensitivity_analysis(gh, c.src, c.dst, mo)) std::printf("sens %d %.17g\n", e, f); + // FlowPolicy sequences. + for (int pl = 1; pl <= 3; ++pl) for (int mp = 0; mp < 2; ++mp) for (int rc = 0; rc < 2; ++rc) { + FlowGraph fg(c.g); + ExecutionContext ctx(algs, gh); + FlowPolicyConfig cfg; + cfg.flow_placement = static_cast(pl); + cfg.multipath = mp; cfg.require_capacity = rc; + cfg.min_flow_count = mp ? 1 : 4; cfg.max_flow_count = mp ? std::optional{} : std::optional{4}; + cfg.node_mask = c.nmask(); cfg.edge_mask = c.emask(); + FlowPolicy pol(ctx, cfg); + auto r1 = pol.place_demand(fg, c.src, c.dst, 0, 25.0); + auto r2 = pol.place_demand(fg, c.src, c.dst, 0, 40.0); + auto r3 = pol.rebalance_demand(fg, c.src, c.dst, 0, 5.0); + std::printf("policy %d %d %d: %.17g %.17g %.17g %.17g %.17g %.17g placed=%.17g flows=%zu\n", pl, mp, rc, + r1.first, r1.second, r2.first, r2.second, r3.first, r3.second, pol.placed_demand(), pol.flows().size()); + std::vector>> recs; + for (auto& kv : pol.flows()) recs.push_back({kv.first.flowId, {(long long)kv.second.cost, kv.second.placed_flow}}); + std::sort(recs.begin(), recs.end()); + for (auto& r : recs) std::printf(" flow %lld cost %lld placed %.17g\n", r.first, r.second.first, r.second.second); + for (auto f : fg.edge_flow_view()) std::printf("%.17g,", f); + std::printf("\n"); + pol.remove_demand(fg); + double left = 0; for (auto f : fg.edge_flow_view()) left += f; + std::printf("after remove %.17g\n", left); + } + // KSP. + for (int k : {1, 3, 6}) for (int uq = 0; uq < 2; ++uq) { + auto paths = k_shortest_paths(c.g, c.src, c.dst, k, std::optional{1.5}, uq, c.nmask(), c.emask()); + std::printf("ksp k=%d unique=%d n=%zu\n", k, uq, paths.size()); + for (auto& p : paths) dump_res(p); + } + } + return 0; +} diff --git a/dev/perf/spf_queue/bitgate/sha256.txt b/dev/perf/spf_queue/bitgate/sha256.txt new file mode 100644 index 0000000..7ae872f --- /dev/null +++ b/dev/perf/spf_queue/bitgate/sha256.txt @@ -0,0 +1,3 @@ +a976f254eced152b14991ba2198351ec7983506f3f1e177c289852ec2bcaab90 dev/perf/spf_queue/bitgate/old.txt +a976f254eced152b14991ba2198351ec7983506f3f1e177c289852ec2bcaab90 dev/perf/spf_queue/bitgate/new.txt +a976f254eced152b14991ba2198351ec7983506f3f1e177c289852ec2bcaab90 dev/perf/spf_queue/bitgate/new-heap.txt diff --git a/dev/perf/spf_queue/bitgate/status.txt b/dev/perf/spf_queue/bitgate/status.txt new file mode 100644 index 0000000..9228bca --- /dev/null +++ b/dev/perf/spf_queue/bitgate/status.txt @@ -0,0 +1 @@ +BITGATE IDENTICAL diff --git a/dev/perf/spf_queue/build.sh b/dev/perf/spf_queue/build.sh new file mode 100755 index 0000000..4c06ad5 --- /dev/null +++ b/dev/perf/spf_queue/build.sh @@ -0,0 +1,31 @@ +#!/usr/bin/env bash +# Plain C++ build of the parity/timing harness (no Objective-C++/Metal; any +# clang/gcc with C++20). +# bash build.sh -> build/perf/cpu-queue (working tree sources) +# bash build.sh sanitize -> build/perf/cpu-queue-sanitize (ASan/UBSan) +# bash build.sh old [REV] -> build/perf/cpu-queue-old (sources of REV, default fbab119, +# extracted with git archive into build/perf/old-src) +set -euo pipefail +cd "$(dirname "$0")/../../.." +mode=${1:-release} +flags=(-std=c++20 -O3 -funroll-loops -fno-math-errno -fno-trapping-math -Wall -Wextra) +src=. +out=build/perf/cpu-queue +case "$mode" in + release) ;; + sanitize) + flags=(-std=c++20 -O1 -g -fsanitize=address,undefined -fno-sanitize-recover=undefined -fno-omit-frame-pointer) + out=build/perf/cpu-queue-sanitize ;; + old) + rev=${2:-fbab119} + src=build/perf/old-src + rm -rf "$src" && mkdir -p "$src" + git archive "$rev" src include | tar -x -C "$src" + out=build/perf/cpu-queue-old ;; + *) echo "usage: build.sh [release|sanitize|old [REV]]" >&2; exit 2 ;; +esac +mkdir -p build/perf +${CXX:-clang++} "${flags[@]}" -I"$src/include" \ + dev/perf/spf_queue/harness.cpp \ + "$src/src/strict_multidigraph.cpp" "$src/src/shortest_paths.cpp" "$src/src/profiling.cpp" -o "$out" +echo "built $out" diff --git a/dev/perf/spf_queue/harness.cpp b/dev/perf/spf_queue/harness.cpp new file mode 100644 index 0000000..1e8b869 --- /dev/null +++ b/dev/perf/spf_queue/harness.cpp @@ -0,0 +1,354 @@ +// Portable CPU harness: bit-exact parity of queue/workspace variants against the +// production shortest_paths, plus sequential single-thread timing. +// +// harness correctness -> parity matrix, exit 1 on mismatch +// harness time [samples] [maxW] -> CSV timing rows on stdout +// harness sweep [samples] [maxW] -> cost-range sweep rows +// +// variant = ref | heap-fresh | heap-full | heap-sparse | bucket-fresh | +// bucket-full | bucket-sparse | bsort-sparse | bsort-fresh +#include "spf_variants.hpp" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace netgraph::core; +using spfx::INF; +using Result = std::pair, PredDAG>; +using Clock = std::chrono::steady_clock; + +static double ms(Clock::time_point start) { + return std::chrono::duration(Clock::now() - start).count(); +} + +struct Case { + std::string name; + StrictMultiDiGraph graph; + std::unique_ptr node_mask, edge_mask; + std::vector residual; + NodeId fixed_src = -1, fixed_dst = -1; + std::span nm() const { return {node_mask.get(), size_t(graph.num_nodes())}; } + std::span em() const { return {edge_mask.get(), size_t(graph.num_edges())}; } +}; + +// Verbatim port of the research generator (same RNG draws), plus new kinds: +// uniform : random topology, every cost == 31 +// wideK : random topology, costs 1..K (K via max_cost argument) +// pseudo : 2-tier fabric with a zero-cost pseudo source/sink attachment, as +// NetGraph's max-flow builds; fixed src/dst = the pseudo nodes +// zerocyc : random graph with a share of zero-cost edges (zero-cost cycles) +static Case make_case(std::string kind, int n, int degree = 8, bool masked = false, + bool large = false, unsigned seed = 1729, Cost max_cost = 31) { + std::vector src, dst; + std::vector costs; + std::vector caps; + std::mt19937 rng(seed); + auto add = [&](int u, int v, Cost c) { + src.push_back(u); dst.push_back(v); + costs.push_back(c + (large ? (Cost(1) << 34) : 0)); + caps.push_back(1.0 + double(rng() % 100) / 7.0); + }; + NodeId fsrc = -1, fdst = -1; + if (kind == "chain") { + for (int i = 0; i < n - 1; ++i) add(i, i + 1, 1 + rng() % 31); + } else if (kind == "grid") { + int side = int(std::sqrt(n)); + if (side * side != n) throw std::runtime_error("grid must be square"); + for (int u = 0; u < n; ++u) { + if (u % side + 1 < side) { add(u, u + 1, 1); add(u + 1, u, 1); } + if (u + side < n) { add(u, u + side, 1); add(u + side, u, 1); } + } + } else if (kind == "fabric" || kind == "clos") { + int spines = kind == "clos" ? n / 2 : 32; + for (int u = 0; u < n - spines; ++u) for (int v = n - spines; v < n; ++v) { + add(u, v, 1); add(v, u, 1); + } + } else if (kind == "uniform") { + for (int u = 0; u < n; ++u) { + add(u, (u + 1) % n, 31); + for (int k = 1; k < degree; ++k) add(u, rng() % n, 31); + } + } else if (kind == "wide") { + for (int u = 0; u < n; ++u) { + add(u, (u + 1) % n, 1 + Cost(rng() % max_cost)); + for (int k = 1; k < degree; ++k) add(u, rng() % n, 1 + Cost(rng() % max_cost)); + } + } else if (kind == "zerocyc") { + for (int u = 0; u < n; ++u) { + add(u, (u + 1) % n, rng() % 4 == 0 ? 0 : 1 + rng() % 31); + for (int k = 1; k < degree; ++k) add(u, rng() % n, rng() % 4 == 0 ? 0 : 1 + rng() % 31); + } + } else if (kind == "pseudo") { + // n real nodes: leaves [0, n/2), spines [n/2, n); then pseudo src n, pseudo dst n+1. + int leaves = n / 2; + for (int u = 0; u < leaves; ++u) for (int v = leaves; v < n; ++v) { add(u, v, 1); add(v, u, 1); } + int k = std::max(1, leaves / 4); + for (int u = 0; u < k; ++u) add(n, u, 0); + for (int u = leaves - k; u < leaves; ++u) add(u, n + 1, 0); + fsrc = n; fdst = n + 1; n += 2; + } else { + for (int u = 0; u < n; ++u) { + add(u, (u + 1) % n, 1 + rng() % 31); + for (int k = 1; k < degree; ++k) add(u, rng() % n, 1 + rng() % 31); + } + } + Case c{kind + (masked ? "_masked" : "") + (large ? "_int64" : ""), + StrictMultiDiGraph::from_arrays(n, src, dst, caps, costs)}; + c.fixed_src = fsrc; c.fixed_dst = fdst; + int e = c.graph.num_edges(); + c.node_mask = std::make_unique(n); + c.edge_mask = std::make_unique(e); + c.residual.assign(c.graph.capacity_view().begin(), c.graph.capacity_view().end()); + for (int i = 0; i < n; ++i) c.node_mask[i] = !masked || rng() % 23 != 0; + for (int i = 0; i < e; ++i) { + c.edge_mask[i] = !masked || rng() % 11 != 0; + if (masked && rng() % 13 == 0) c.residual[i] = 0; + } + if (fsrc >= 0) { c.node_mask[fsrc] = true; c.node_mask[fdst] = true; } + return c; +} + +struct Query { + NodeId src; std::optional dst; bool multipath; EdgeSelection sel; + bool use_residual; bool use_masks; bool reverse = false; +}; + +static Result run_ref(const Case& c, const Query& q) { + auto res = q.use_residual ? std::span(c.residual) : std::span{}; + auto nm = q.use_masks ? c.nm() : std::span{}; + auto em = q.use_masks ? c.em() : std::span{}; + if (q.reverse) return shortest_paths_to(c.graph, q.src, q.multipath, q.sel, res, nm, em, {}); + return shortest_paths(c.graph, q.src, q.dst, q.multipath, q.sel, res, nm, em); +} + +struct Runner { + std::string variant; + spfx::HeapQueue heap; spfx::BucketHeapQueue bucket; spfx::BucketPow2Queue bucket2; spfx::BucketSortQueue bsort; + spfx::Workspace ws; + spfx::CostProfile prof; + std::size_t max_width = 1u << 20; + bool fallback = false; + void prepare(const Case& c) { + prof = spfx::profile_costs(c.graph); + fallback = static_cast(prof.max_cost / prof.stride) + 1 > max_width; + ws = spfx::Workspace{}; + if (variant.find("fresh") != std::string::npos) ws.mode = spfx::WsMode::Fresh; + else if (variant.find("full") != std::string::npos) ws.mode = spfx::WsMode::ReuseFull; + else if (variant.find("hybrid") != std::string::npos) ws.mode = spfx::WsMode::ReuseHybrid; + else ws.mode = spfx::WsMode::ReuseSparse; + } + Result run(const Case& c, const Query& q) { + if (variant == "ref" || q.reverse) return run_ref(c, q); // reverse: production only + spfx::Workspace fresh; fresh.mode = spfx::WsMode::Fresh; + spfx::Workspace& w = (ws.mode == spfx::WsMode::Fresh) ? fresh : ws; + auto res = q.use_residual ? std::span(c.residual) : std::span{}; + auto nm = q.use_masks ? c.nm() : std::span{}; + auto em = q.use_masks ? c.em() : std::span{}; + const bool use_heap = fallback || variant.rfind("heap", 0) == 0; + if (use_heap) return spfx::spf_variant(c.graph, q.src, q.dst, q.multipath, q.sel, res, nm, em, heap, w, prof.max_cost, prof.stride); + if (variant.rfind("bsort", 0) == 0) return spfx::spf_variant(c.graph, q.src, q.dst, q.multipath, q.sel, res, nm, em, bsort, w, prof.max_cost, prof.stride); + if (variant.rfind("bucket2", 0) == 0) return spfx::spf_variant(c.graph, q.src, q.dst, q.multipath, q.sel, res, nm, em, bucket2, w, prof.max_cost, prof.stride); + return spfx::spf_variant(c.graph, q.src, q.dst, q.multipath, q.sel, res, nm, em, bucket, w, prof.max_cost, prof.stride); + } +}; + +static bool same(const Result& a, const Result& b) { + return a.first == b.first && a.second.parent_offsets == b.second.parent_offsets && + a.second.parents == b.second.parents && a.second.via_edges == b.second.via_edges; +} + +static NodeId far_node(const std::vector& d) { + NodeId best = -1; Cost bd = -1; + for (std::size_t v = 0; v < d.size(); ++v) if (d[v] != INF && d[v] > bd) { bd = d[v]; best = NodeId(v); } + return best; +} + +static int correctness() { + const char* variants[] = {"heap-fresh", "heap-full", "heap-sparse", "heap-hybrid", "bucket-fresh", + "bucket-full", "bucket-sparse", "bucket-hybrid", "bucket2-fresh", "bucket2-sparse", + "bucket2-hybrid", "bsort-fresh", "bsort-sparse"}; + std::vector cases; + for (unsigned seed = 1; seed <= 12; ++seed) cases.push_back(make_case("random", 37 + seed * 3, 6, true, false, seed)); + for (unsigned seed = 1; seed <= 6; ++seed) cases.push_back(make_case("zerocyc", 40 + seed * 5, 5, seed % 2, false, seed)); + cases.push_back(make_case("random", 1024)); + cases.push_back(make_case("random", 512, 8, true, true, 7)); + cases.push_back(make_case("grid", 1024)); + cases.push_back(make_case("uniform", 500)); + cases.push_back(make_case("wide", 600, 8, true, false, 3, 100000)); + cases.push_back(make_case("pseudo", 64)); + cases.push_back(make_case("pseudo", 200, 8, true, false, 5)); + cases.push_back(make_case("chain", 300)); + cases.push_back(make_case("fabric", 100)); + // Dense parallel edges and self-loops: a tiny multigraph. + { + std::vector s, d; std::vector c; std::vector k; std::mt19937 r(99); + for (int i = 0; i < 400; ++i) { s.push_back(r() % 12); d.push_back(r() % 12); c.push_back(r() % 3); k.push_back(double(r() % 5)); } + Case mc{"multi", StrictMultiDiGraph::from_arrays(12, s, d, k, c)}; + mc.node_mask = std::make_unique(12); mc.edge_mask = std::make_unique(400); + mc.residual.assign(mc.graph.capacity_view().begin(), mc.graph.capacity_view().end()); + for (int i = 0; i < 12; ++i) mc.node_mask[i] = r() % 9 != 0; + for (int i = 0; i < 400; ++i) { mc.edge_mask[i] = r() % 7 != 0; if (r() % 5 == 0) mc.residual[i] = kMinCap * (r() % 3); } + cases.push_back(std::move(mc)); + } + std::size_t checked = 0, failed = 0; + for (auto& c : cases) { + const int n = c.graph.num_nodes(); + std::vector sources; + if (c.fixed_src >= 0) sources = {c.fixed_src, 0, 3}; + else for (int i = 0; i < 6; ++i) sources.push_back((i * 997 + 1) % n); + for (const char* vname : variants) { + Runner r; r.variant = vname; r.prepare(c); + for (NodeId s : sources) { + for (int mp = 0; mp < 2; ++mp) for (int me = 0; me < 2; ++me) for (int tb = 0; tb < 2; ++tb) + for (int rc = 0; rc < 2; ++rc) for (int ur = 0; ur < 2; ++ur) for (int um = 0; um < 2; ++um) { + Query q; q.src = s; q.multipath = mp; q.sel.multi_edge = me; + q.sel.tie_break = tb ? EdgeTieBreak::PreferHigherResidual : EdgeTieBreak::Deterministic; + q.sel.require_capacity = rc; q.use_residual = ur; q.use_masks = um; + std::vector> dsts = {std::nullopt}; + auto full = run_ref(c, q); + if (c.fixed_dst >= 0) dsts.push_back(c.fixed_dst); + auto row = c.graph.row_offsets_view(); auto col = c.graph.col_indices_view(); + if (row[s + 1] > row[s]) dsts.push_back(col[row[s]]); + NodeId far = far_node(full.first); if (far >= 0) dsts.push_back(far); + dsts.push_back(s); dsts.push_back((s + n / 2) % n); + for (auto& d : dsts) { + q.dst = d; + auto expected = run_ref(c, q); + for (int rep = 0; rep < 2; ++rep) { // second run exercises reuse/reset paths + auto actual = r.run(c, q); + ++checked; + if (!same(expected, actual)) { + ++failed; + if (failed <= 20) + std::cerr << "MISMATCH case=" << c.name << " n=" << n << " variant=" << vname + << " src=" << s << " dst=" << (d ? std::to_string(*d) : "none") + << " mp=" << mp << " me=" << me << " tb=" << tb << " rc=" << rc + << " ur=" << ur << " um=" << um << " rep=" << rep << '\n'; + } + } + } + } + } + } + } + std::cout << "checked=" << checked << " failed=" << failed << '\n'; + return failed ? 1 : 0; +} + +struct Workload { std::string label; Case c; int queries; std::string dst_mode; }; + +static void time_workloads(std::vector& wls, const std::string& variant, int samples, std::size_t maxw) { + std::cout << "case,n,e,queries,dst,variant,fallback,W,median_ms,samples,wall_samples_ms\n"; + for (auto& w : wls) { + auto& c = w.c; const int n = c.graph.num_nodes(); + std::vector qs; + for (int i = 0; i < w.queries; ++i) { + Query q; q.multipath = true; q.sel = EdgeSelection{}; q.use_residual = true; q.use_masks = true; + q.src = c.fixed_src >= 0 ? c.fixed_src : (i * 997) % n; + if (w.dst_mode == "reverse") q.reverse = true; + else if (w.dst_mode == "fixed") q.dst = c.fixed_dst; + else if (w.dst_mode == "near") { + auto row = c.graph.row_offsets_view(); auto col = c.graph.col_indices_view(); + q.dst = col[row[q.src]]; + } else if (w.dst_mode == "far") { + Query f = q; f.dst = std::nullopt; q.dst = far_node(run_ref(c, f).first); + } + qs.push_back(q); + } + std::vector expected; for (auto& q : qs) expected.push_back(run_ref(c, q)); + Runner r; r.variant = variant; r.max_width = maxw; r.prepare(c); + std::vector times; + for (int rep = -2; rep < samples; ++rep) { + std::vector actual(qs.size()); + auto start = Clock::now(); + for (std::size_t i = 0; i < qs.size(); ++i) actual[i] = r.run(c, qs[i]); + double el = ms(start); + for (std::size_t i = 0; i < qs.size(); ++i) if (!same(expected[i], actual[i])) throw std::runtime_error("timed result mismatch in " + w.label); + if (rep >= 0) times.push_back(el); + } + std::vector sorted = times; std::sort(sorted.begin(), sorted.end()); + std::cout << w.label << ',' << n << ',' << c.graph.num_edges() << ',' << w.queries << ',' << w.dst_mode << ',' + << variant << ',' << (r.fallback ? 1 : 0) << ',' << (r.prof.max_cost / r.prof.stride + 1) << ',' + << std::fixed << sorted[sorted.size() / 2] << ',' << samples << ','; + for (std::size_t j = 0; j < times.size(); ++j) std::cout << (j ? ";" : "") << times[j]; + std::cout << '\n' << std::flush; + } +} + +int main(int argc, char** argv) { + try { + std::string mode = argc > 1 ? argv[1] : "correctness"; + if (mode == "correctness") return correctness(); + std::string variant = argc > 2 ? argv[2] : "ref"; + int samples = argc > 3 ? std::stoi(argv[3]) : 7; + std::size_t maxw = argc > 4 ? std::stoull(argv[4]) : (1u << 20); + std::vector wls; + if (mode == "time") { + wls.push_back({"random", make_case("random", 1024), 1, "none"}); + wls.push_back({"random", make_case("random", 4096), 256, "none"}); + wls.push_back({"random", make_case("random", 16384), 64, "none"}); + wls.push_back({"random", make_case("random", 65536), 1, "none"}); + wls.push_back({"random", make_case("random", 4096, 32), 64, "none"}); + wls.push_back({"clos", make_case("clos", 800), 64, "none"}); + wls.push_back({"grid", make_case("grid", 10000), 1, "none"}); + wls.push_back({"chain", make_case("chain", 2048), 1, "none"}); + wls.push_back({"uniform", make_case("uniform", 16384), 64, "none"}); + wls.push_back({"random_masked", make_case("random", 16384, 8, true), 64, "none"}); + wls.push_back({"pseudo", make_case("pseudo", 800), 64, "fixed"}); + wls.push_back({"random", make_case("random", 1024), 64, "far"}); + wls.push_back({"random", make_case("random", 16384), 64, "far"}); + wls.push_back({"random", make_case("random", 65536), 16, "far"}); + wls.push_back({"random", make_case("random", 1024), 64, "near"}); + wls.push_back({"random", make_case("random", 16384), 64, "near"}); + wls.push_back({"random", make_case("random", 65536), 64, "near"}); + wls.push_back({"random", make_case("random", 262144), 16, "near"}); + wls.push_back({"random", make_case("random", 262144), 1, "none"}); + wls.push_back({"random", make_case("random", 4096), 64, "reverse"}); + wls.push_back({"random", make_case("random", 16384), 16, "reverse"}); + wls.push_back({"clos", make_case("clos", 800), 16, "reverse"}); + wls.push_back({"chain", make_case("chain", 2048), 1, "reverse"}); + } else if (mode == "short") { + wls.push_back({"random", make_case("random", 16384), 64, "none"}); + wls.push_back({"random", make_case("random", 65536), 1, "none"}); + wls.push_back({"clos", make_case("clos", 800), 64, "none"}); + wls.push_back({"chain", make_case("chain", 2048), 1, "none"}); + wls.push_back({"random", make_case("random", 16384), 64, "near"}); + wls.push_back({"random", make_case("random", 65536), 64, "near"}); + wls.push_back({"random", make_case("random", 262144), 16, "near"}); + wls.push_back({"random", make_case("random", 262144), 1, "none"}); + wls.push_back({"random", make_case("random", 4096), 64, "reverse"}); + wls.push_back({"clos", make_case("clos", 800), 16, "reverse"}); + } else if (mode == "faults") { + auto c = make_case("random", 262144); + Runner r; r.variant = variant; r.prepare(c); + std::vector qs; + for (int i = 0; i < 16; ++i) { + Query q; q.multipath = true; q.sel = EdgeSelection{}; q.use_residual = true; q.use_masks = true; + q.src = (i * 997) % c.graph.num_nodes(); + auto row = c.graph.row_offsets_view(); auto col = c.graph.col_indices_view(); + q.dst = col[row[q.src]]; qs.push_back(q); + } + std::cout << "variant,sample,ms,minor_faults\n"; + for (int rep = 0; rep < samples; ++rep) { + struct rusage a{}, b{}; getrusage(RUSAGE_SELF, &a); + auto start = Clock::now(); + for (auto& q : qs) { auto res = r.run(c, q); (void)res; } + double el = ms(start); getrusage(RUSAGE_SELF, &b); + std::cout << variant << ',' << rep << ',' << el << ',' << (b.ru_minflt - a.ru_minflt) << '\n'; + } + return 0; + } else if (mode == "sweep") { + for (Cost k : {Cost(1), Cost(31), Cost(1023), Cost(32767), Cost(1048575), Cost(33554431)}) + wls.push_back({"wide" + std::to_string(k), make_case("wide", 16384, 8, false, false, 11, k), 16, "none"}); + } else { std::cerr << "unknown mode\n"; return 2; } + time_workloads(wls, variant, samples, maxw); + return 0; + } catch (const std::exception& e) { std::cerr << "FAIL: " << e.what() << '\n'; return 1; } +} diff --git a/dev/perf/spf_queue/results/core/environment.txt b/dev/perf/spf_queue/results/core/environment.txt new file mode 100644 index 0000000..7e3715f --- /dev/null +++ b/dev/perf/spf_queue/results/core/environment.txt @@ -0,0 +1,5 @@ +date: 2026-10-02T01:55:02Z +commit: fbab119e794c843838f4f3f96d75cb7f32f06845 +398e99a789a55595c2862a1574d5dbb7b79105debd23893e513145331c8ebf20 build/perf/cpu-queue-old +0caa759264760987d39f2e34774fb972e6d906aa30c0ba50b338b630bc2ecb82 build/perf/cpu-queue +32b56468bdbf2aa01cd24f4d49bc32572a4fb3df2cdfbee222919365ddb345ac src/shortest_paths.cpp diff --git a/dev/perf/spf_queue/results/core/load.txt b/dev/perf/spf_queue/results/core/load.txt new file mode 100644 index 0000000..355b2d8 --- /dev/null +++ b/dev/perf/spf_queue/results/core/load.txt @@ -0,0 +1,5 @@ + 2:55 up 52 days, 7:30, 3 users, load averages: 4.90 3.90 3.58 + 2:55 up 52 days, 7:31, 3 users, load averages: 5.87 4.25 3.72 + 2:55 up 52 days, 7:31, 3 users, load averages: 5.55 4.28 3.74 + 2:56 up 52 days, 7:32, 3 users, load averages: 4.78 4.23 3.74 + 2:56 up 52 days, 7:32, 3 users, load averages: 3.81 4.06 3.70 diff --git a/dev/perf/spf_queue/results/core/sweep-a1-old.csv b/dev/perf/spf_queue/results/core/sweep-a1-old.csv new file mode 100644 index 0000000..f9e3244 --- /dev/null +++ b/dev/perf/spf_queue/results/core/sweep-a1-old.csv @@ -0,0 +1,7 @@ +case,n,e,queries,dst,variant,fallback,W,median_ms,samples,wall_samples_ms +wide1,16384,131072,16,none,ref,0,2,44.352291,9,44.086875;44.377000;44.628125;44.352291;44.023541;43.918208;44.219417;44.613792;44.580041 +wide31,16384,131072,16,none,ref,0,32,64.523625,9,65.509584;63.234250;65.116667;65.243042;64.903458;64.523625;63.181459;63.612750;63.286166 +wide1023,16384,131072,16,none,ref,0,1024,59.174417,9,58.785959;58.733333;58.501958;59.025541;59.562083;59.174417;59.679125;61.427416;60.950667 +wide32767,16384,131072,16,none,ref,0,32768,51.340375,9,51.536250;50.769167;51.296250;50.826084;51.254458;51.340375;55.436375;52.199417;51.832375 +wide1048575,16384,131072,16,none,ref,0,1048570,49.692959,9,49.268709;49.916458;49.665333;50.078875;50.071583;49.323417;49.692959;49.539000;50.344708 +wide33554431,16384,131072,16,none,ref,1,33554196,50.979792,9,51.642458;50.843541;51.670125;52.071708;50.979792;49.830125;49.897750;53.102917;50.218000 diff --git a/dev/perf/spf_queue/results/core/sweep-a2-old.csv b/dev/perf/spf_queue/results/core/sweep-a2-old.csv new file mode 100644 index 0000000..481ab09 --- /dev/null +++ b/dev/perf/spf_queue/results/core/sweep-a2-old.csv @@ -0,0 +1,7 @@ +case,n,e,queries,dst,variant,fallback,W,median_ms,samples,wall_samples_ms +wide1,16384,131072,16,none,ref,0,2,45.312333,9,44.464833;44.154500;47.801250;53.494416;50.825042;45.947750;45.312333;44.580125;43.997000 +wide31,16384,131072,16,none,ref,0,32,62.621250,9,62.490250;62.513000;63.224833;65.986583;63.337458;62.931083;62.621250;62.527625;62.346834 +wide1023,16384,131072,16,none,ref,0,1024,58.916208,9,59.217541;58.972542;58.553250;58.374542;58.483916;58.916208;58.997625;59.213500;58.537375 +wide32767,16384,131072,16,none,ref,0,32768,51.218083,9,51.855000;50.652958;51.594542;52.729791;54.058500;50.825625;51.218083;50.761458;50.697500 +wide1048575,16384,131072,16,none,ref,0,1048570,49.482167,9,49.696250;49.551542;50.780459;49.118250;49.691791;49.366750;49.482167;49.194792;49.096834 +wide33554431,16384,131072,16,none,ref,1,33554196,49.570416,9,49.298209;49.703792;49.571917;49.570416;49.748334;49.420875;48.950458;49.058333;49.650792 diff --git a/dev/perf/spf_queue/results/core/sweep-b-new-heap.csv b/dev/perf/spf_queue/results/core/sweep-b-new-heap.csv new file mode 100644 index 0000000..ebdd1c8 --- /dev/null +++ b/dev/perf/spf_queue/results/core/sweep-b-new-heap.csv @@ -0,0 +1,7 @@ +case,n,e,queries,dst,variant,fallback,W,median_ms,samples,wall_samples_ms +wide1,16384,131072,16,none,ref,0,2,44.878208,9,45.642250;44.777125;44.635208;44.826041;44.878208;44.698917;44.906916;45.127375;46.000833 +wide31,16384,131072,16,none,ref,0,32,65.879833,9,65.689708;65.387917;65.879833;65.649000;65.923375;65.449416;71.317416;70.386500;66.445333 +wide1023,16384,131072,16,none,ref,0,1024,64.511417,9,65.141875;64.957542;64.511417;63.439542;63.949875;65.523292;64.848458;62.969292;61.874125 +wide32767,16384,131072,16,none,ref,0,32768,53.333916,9,56.096500;53.301334;53.190750;52.911167;53.580208;53.497084;53.135542;53.689084;53.333916 +wide1048575,16384,131072,16,none,ref,0,1048570,51.609166,9,51.523833;51.587417;51.883958;51.651209;51.836750;51.609166;51.933042;51.236250;51.375834 +wide33554431,16384,131072,16,none,ref,1,33554196,52.825083,9,51.052583;53.398959;52.825083;53.651458;52.462500;53.022917;51.669167;52.227625;52.896750 diff --git a/dev/perf/spf_queue/results/core/sweep-b-new.csv b/dev/perf/spf_queue/results/core/sweep-b-new.csv new file mode 100644 index 0000000..9433c7f --- /dev/null +++ b/dev/perf/spf_queue/results/core/sweep-b-new.csv @@ -0,0 +1,7 @@ +case,n,e,queries,dst,variant,fallback,W,median_ms,samples,wall_samples_ms +wide1,16384,131072,16,none,ref,0,2,36.503458,9,37.167208;36.729708;37.140375;36.533916;36.503458;36.221459;36.294459;36.378834;36.433625 +wide31,16384,131072,16,none,ref,0,32,37.245334,9,37.449375;37.121292;37.245334;37.061000;37.297667;37.611959;37.674375;37.111042;37.001167 +wide1023,16384,131072,16,none,ref,0,1024,35.254125,9,35.443709;34.672542;34.525583;35.358042;35.254125;34.552375;35.635083;35.049750;37.176667 +wide32767,16384,131072,16,none,ref,0,32768,42.723500,9,46.660292;46.680417;43.522792;42.570000;42.480250;42.398000;43.176167;42.561459;42.723500 +wide1048575,16384,131072,16,none,ref,0,1048570,52.842042,9,52.842042;54.554709;52.937625;51.867250;53.022625;53.576167;51.793459;51.445958;51.624084 +wide33554431,16384,131072,16,none,ref,1,33554196,51.172125,9,51.042458;51.125750;51.288833;51.172125;51.396875;51.077375;50.950125;51.360083;51.348583 diff --git a/dev/perf/spf_queue/results/core/time-a1-old.csv b/dev/perf/spf_queue/results/core/time-a1-old.csv new file mode 100644 index 0000000..9fc4aae --- /dev/null +++ b/dev/perf/spf_queue/results/core/time-a1-old.csv @@ -0,0 +1,24 @@ +case,n,e,queries,dst,variant,fallback,W,median_ms,samples,wall_samples_ms +random,1024,8192,1,none,ref,0,32,0.106958,9,0.115667;0.110708;0.106792;0.106958;0.104708;0.109125;0.105583;0.110708;0.105542 +random,4096,32768,256,none,ref,0,32,211.610083,9,212.391417;213.572625;211.610083;212.972792;209.318375;211.922333;211.232708;210.825583;211.031791 +random,16384,131072,64,none,ref,0,32,254.445125,9,255.636625;250.567292;256.788750;255.059291;254.445125;252.375416;252.658750;251.488167;258.346709 +random,65536,524288,1,none,ref,0,32,21.207166,9,22.317625;20.960375;22.085000;21.607833;21.891917;20.436417;21.207166;20.212583;19.644375 +random,4096,131072,64,none,ref,0,32,111.982500,9,111.510291;111.280167;110.260750;114.967625;111.982500;116.551958;115.775541;112.375292;110.651750 +clos,800,320000,64,none,ref,0,2,143.850792,9,144.580583;159.426375;146.935833;144.435542;143.749167;143.498125;143.109583;143.096916;143.850792 +grid,10000,39600,1,none,ref,0,2,0.613667,9,0.626875;0.617250;0.614458;0.608209;0.605041;0.613667;0.602333;0.630500;0.612917 +chain,2048,2047,1,none,ref,0,32,0.021084,9,0.021125;0.023292;0.021250;0.021291;0.021000;0.020833;0.021084;0.021000;0.020833 +uniform,16384,131072,64,none,ref,0,2,181.359417,9,184.075459;184.356917;181.359417;179.613750;176.768791;176.969792;183.551792;185.391208;179.085709 +random_masked,16384,131072,64,none,ref,0,32,229.998916,9,231.366959;229.379667;229.071125;230.344541;229.998916;229.167958;231.250333;229.889500;233.766959 +pseudo,802,320200,64,fixed,ref,0,2,143.435458,9,145.647375;143.648291;143.467333;143.388459;143.066459;143.010917;142.905250;143.435458;144.383417 +random,1024,8192,64,far,ref,0,32,10.809542,9,10.983583;10.809542;10.820083;10.535125;10.627583;11.172125;10.714834;10.797625;10.889416 +random,16384,131072,64,far,ref,0,32,251.559084,9,251.398833;255.170833;249.550292;257.199750;256.924875;251.559084;262.081709;250.485417;250.757833 +random,65536,524288,16,far,ref,0,32,324.283292,9,317.256292;323.378583;317.522917;335.351792;344.360000;328.237084;332.692291;323.432333;324.283292 +random,1024,8192,64,near,ref,0,32,0.115916,9,0.131834;0.116125;0.114917;0.116166;0.114417;0.115916;0.115167;0.115916;0.114916 +random,16384,131072,64,near,ref,0,32,1.160042,9,1.184500;1.160042;1.155458;1.184875;1.169292;1.155208;1.161750;1.149708;1.133042 +random,65536,524288,64,near,ref,0,32,4.350791,9,4.351875;4.369875;4.271042;4.321834;4.495250;4.440125;4.322833;4.295916;4.350791 +random,262144,2097152,16,near,ref,0,32,4.508541,9,4.475417;4.420459;4.466000;4.534375;4.546958;4.508541;4.552375;4.574167;4.442375 +random,262144,2097152,1,none,ref,0,32,136.600542,9,131.104333;132.261833;151.478750;136.600542;153.047334;136.134208;151.398709;138.768875;133.424375 +random,4096,32768,64,reverse,ref,0,32,55.852125,9,56.317833;55.482417;55.200209;55.489792;55.858208;56.313583;55.924292;55.852125;55.504916 +random,16384,131072,16,reverse,ref,0,32,66.552625,9,66.607458;66.686250;66.552625;66.465708;66.405917;66.595375;66.715500;66.423000;66.335334 +clos,800,320000,16,reverse,ref,0,2,45.430417,9,45.366916;46.270000;45.521083;45.523167;45.045208;45.342166;46.058917;45.430417;45.360167 +chain,2048,2047,1,reverse,ref,0,32,0.002459,9,0.002542;0.002500;0.002458;0.002417;0.002458;0.002459;0.002459;0.002417;0.002500 diff --git a/dev/perf/spf_queue/results/core/time-a2-old.csv b/dev/perf/spf_queue/results/core/time-a2-old.csv new file mode 100644 index 0000000..94e8ab2 --- /dev/null +++ b/dev/perf/spf_queue/results/core/time-a2-old.csv @@ -0,0 +1,24 @@ +case,n,e,queries,dst,variant,fallback,W,median_ms,samples,wall_samples_ms +random,1024,8192,1,none,ref,0,32,0.101834,9,0.109500;0.105542;0.101750;0.104625;0.101834;0.100333;0.101167;0.103750;0.100666 +random,4096,32768,256,none,ref,0,32,207.613708,9,207.485375;206.933041;208.212125;207.613708;207.810167;208.212750;210.455416;207.561500;207.319334 +random,16384,131072,64,none,ref,0,32,250.635500,9,248.790875;255.047708;252.925667;250.635500;259.166875;256.407833;249.778542;249.601458;249.926959 +random,65536,524288,1,none,ref,0,32,19.031875,9,19.095375;18.645916;18.997584;19.031875;19.140959;18.780000;18.720708;19.176583;19.497166 +random,4096,131072,64,none,ref,0,32,110.612875,9,109.587375;110.209167;111.275208;110.612875;111.021292;109.861250;109.868792;111.204875;112.800917 +clos,800,320000,64,none,ref,0,2,144.348666,9,144.072417;144.348666;142.863833;144.374250;143.269584;143.490667;145.960250;146.807167;149.376125 +grid,10000,39600,1,none,ref,0,2,0.617875,9,0.702541;0.759916;0.659916;0.617875;0.626667;0.612417;0.608000;0.610875;0.602750 +chain,2048,2047,1,none,ref,0,32,0.021125,9,0.021167;0.021208;0.020917;0.021042;0.021125;0.021042;0.021125;0.021125;0.021083 +uniform,16384,131072,64,none,ref,0,2,177.095166,9,182.894583;177.679000;176.943375;178.067417;177.095166;175.792833;175.764500;177.102125;176.212083 +random_masked,16384,131072,64,none,ref,0,32,229.178375,9,236.057750;234.569458;229.058791;230.634208;228.691667;229.766125;229.178375;228.735667;228.920333 +pseudo,802,320200,64,fixed,ref,0,2,143.852875,9,142.524209;145.574958;144.100459;142.070458;141.723667;142.472459;145.693959;143.852875;144.534584 +random,1024,8192,64,far,ref,0,32,10.644542,9,10.938208;10.673625;10.548000;10.667625;10.833166;10.644542;10.574875;10.554875;10.396333 +random,16384,131072,64,far,ref,0,32,250.480292,9,249.484750;256.099917;256.425250;250.480292;250.175000;252.559959;249.520334;250.489750;249.955709 +random,65536,524288,16,far,ref,0,32,330.221833,9,315.811792;313.175667;318.501292;354.013792;334.924291;358.063459;337.334500;330.221833;325.634834 +random,1024,8192,64,near,ref,0,32,0.115000,9,0.131166;0.120875;0.123250;0.114667;0.115125;0.114500;0.114542;0.115000;0.114458 +random,16384,131072,64,near,ref,0,32,1.158416,9,1.172833;1.157791;1.135833;1.134000;1.149042;1.170666;1.162125;1.159625;1.158416 +random,65536,524288,64,near,ref,0,32,4.254209,9,4.462792;4.332792;4.254209;4.196083;4.119875;4.314084;4.682750;4.132750;4.198625 +random,262144,2097152,16,near,ref,0,32,4.052500,9,4.064917;4.003458;4.176958;3.968500;4.052500;4.077541;4.024875;4.008208;4.084000 +random,262144,2097152,1,none,ref,0,32,133.776042,9,129.185667;137.226125;140.845583;129.927167;138.156834;133.776042;129.648542;129.228250;140.502583 +random,4096,32768,64,reverse,ref,0,32,55.341708,9,55.341708;54.893125;55.288291;55.720083;55.631458;55.147375;55.813000;55.523584;55.047041 +random,16384,131072,16,reverse,ref,0,32,66.335584,9,66.911958;66.478584;66.164500;66.552166;65.950875;66.265667;66.290083;66.454625;66.335584 +clos,800,320000,16,reverse,ref,0,2,45.715584,9,45.088375;45.245375;45.715584;45.252958;45.571917;47.052000;47.791334;48.474250;47.146917 +chain,2048,2047,1,reverse,ref,0,32,0.002500,9,0.002541;0.006000;0.002542;0.002500;0.002500;0.002459;0.002417;0.002417;0.002459 diff --git a/dev/perf/spf_queue/results/core/time-b-new-heap.csv b/dev/perf/spf_queue/results/core/time-b-new-heap.csv new file mode 100644 index 0000000..205909f --- /dev/null +++ b/dev/perf/spf_queue/results/core/time-b-new-heap.csv @@ -0,0 +1,24 @@ +case,n,e,queries,dst,variant,fallback,W,median_ms,samples,wall_samples_ms +random,1024,8192,1,none,ref,0,32,0.088833,9,0.096708;0.091625;0.088833;0.088750;0.090125;0.088541;0.088417;0.089375;0.087750 +random,4096,32768,256,none,ref,0,32,221.265750,9,220.144584;223.817375;220.986583;223.324666;222.115833;219.679500;221.265750;223.397125;220.469791 +random,16384,131072,64,none,ref,0,32,266.067667,9,274.505625;266.067667;267.851333;270.677250;269.163250;264.256125;265.097667;263.502791;263.624708 +random,65536,524288,1,none,ref,0,32,23.134583,9,20.670500;23.134583;24.174791;23.200709;23.227667;24.203375;22.576833;22.547500;22.666666 +random,4096,131072,64,none,ref,0,32,115.415541,9,115.824416;115.139792;115.361583;115.253792;118.206167;115.457125;114.843167;115.415541;115.862542 +clos,800,320000,64,none,ref,0,2,111.078375,9,111.197500;111.471166;110.903000;110.062458;111.763917;111.078375;111.423292;110.355000;109.572500 +grid,10000,39600,1,none,ref,0,2,0.634583,9,0.667334;0.642000;0.634583;0.619208;0.621583;0.626667;0.608708;0.755708;0.666667 +chain,2048,2047,1,none,ref,0,32,0.029416,9,0.029459;0.029416;0.029208;0.029459;0.029083;0.029542;0.029250;0.029125;0.029541 +uniform,16384,131072,64,none,ref,0,2,178.581250,9,195.664541;191.799417;182.415708;177.275333;178.194333;176.856083;178.398166;178.581250;185.570167 +random_masked,16384,131072,64,none,ref,0,32,236.748625,9,236.023250;236.838417;236.574250;236.748625;236.012875;235.968875;237.149583;243.117416;237.379625 +pseudo,802,320200,64,fixed,ref,0,2,110.311166,9,106.727958;108.254041;111.146250;113.320334;111.019083;109.168833;111.504666;110.311166;108.458625 +random,1024,8192,64,far,ref,0,32,11.213583,9,11.372458;11.213583;11.326291;11.234958;11.130166;11.206750;11.241334;11.163084;11.072542 +random,16384,131072,64,far,ref,0,32,264.043167,9,264.706709;261.972584;270.202333;264.043167;261.499958;260.463167;261.026333;272.374125;265.389125 +random,65536,524288,16,far,ref,0,32,336.034334,9,336.034334;332.651584;356.911208;348.736917;331.438584;330.369333;334.507666;361.791000;338.378541 +random,1024,8192,64,near,ref,0,32,0.037709,9,0.049833;0.037750;0.037709;0.038917;0.036584;0.036625;0.041125;0.037125;0.037375 +random,16384,131072,64,near,ref,0,32,0.391916,9,0.401042;0.391125;0.400458;0.387916;0.393584;0.391916;0.391000;0.391417;0.392417 +random,65536,524288,64,near,ref,0,32,1.516667,9,1.524625;1.527166;1.501125;1.529125;1.489458;1.496208;1.504041;1.516667;1.544250 +random,262144,2097152,16,near,ref,0,32,1.470708,9,1.496750;1.484625;1.459750;1.510000;1.470708;1.463125;1.449584;1.478750;1.448833 +random,262144,2097152,1,none,ref,0,32,130.310667,9,130.310667;129.807542;135.604750;131.635916;127.798916;133.017500;130.851417;128.863917;128.407125 +random,4096,32768,64,reverse,ref,0,32,58.814625,9,58.716666;58.974417;58.564417;58.924000;58.719750;58.765125;58.819625;59.099708;58.814625 +random,16384,131072,16,reverse,ref,0,32,69.334166,9,69.079041;70.882875;72.038375;70.165583;69.543625;69.334166;68.577084;68.910917;69.139291 +clos,800,320000,16,reverse,ref,0,2,36.895583,9,36.895583;36.931584;36.731667;36.628208;37.129375;37.363000;36.916333;36.660125;36.753125 +chain,2048,2047,1,reverse,ref,0,32,0.000959,9,0.000959;0.000958;0.000917;0.000958;0.001041;0.000917;0.001000;0.001000;0.001000 diff --git a/dev/perf/spf_queue/results/core/time-b-new.csv b/dev/perf/spf_queue/results/core/time-b-new.csv new file mode 100644 index 0000000..34b6d95 --- /dev/null +++ b/dev/perf/spf_queue/results/core/time-b-new.csv @@ -0,0 +1,24 @@ +case,n,e,queries,dst,variant,fallback,W,median_ms,samples,wall_samples_ms +random,1024,8192,1,none,ref,0,32,0.066833,9,0.069250;0.075792;0.070875;0.068000;0.065625;0.066125;0.066042;0.066833;0.066625 +random,4096,32768,256,none,ref,0,32,132.648459,9,132.505375;132.265375;132.831417;132.648459;132.447625;132.762458;132.147750;133.442458;133.112792 +random,16384,131072,64,none,ref,0,32,150.945333,9,153.656875;164.973750;153.952125;152.398625;150.712417;150.172000;150.945333;148.924042;150.006708 +random,65536,524288,1,none,ref,0,32,11.514416,9,12.729084;11.643750;11.423167;11.514416;11.301959;11.454750;11.378291;11.714166;13.003042 +random,4096,131072,64,none,ref,0,32,77.140875,9,77.841792;76.885000;76.946334;77.022959;77.553333;77.419958;77.140875;77.250500;76.946625 +clos,800,320000,64,none,ref,0,2,110.201250,9,110.201250;110.459333;111.589125;110.316375;110.060292;109.016875;109.324375;111.536917;109.488958 +grid,10000,39600,1,none,ref,0,2,0.458667,9,0.455084;0.457958;0.457750;0.454583;0.525708;0.490208;0.472750;0.473292;0.458667 +chain,2048,2047,1,none,ref,0,32,0.027209,9,0.027667;0.032000;0.027583;0.027167;0.027167;0.027500;0.027209;0.027209;0.026875 +uniform,16384,131072,64,none,ref,0,2,146.318459,9,148.808250;145.343750;145.932500;145.638708;144.796250;146.318459;147.311791;149.775541;151.739708 +random_masked,16384,131072,64,none,ref,0,32,140.926917,9,141.910000;140.926917;140.947875;142.060625;140.763166;140.562292;140.122166;140.942208;140.426417 +pseudo,802,320200,64,fixed,ref,0,2,107.962250,9,107.962250;107.616041;110.084750;111.659083;109.297500;109.965042;107.801958;107.381167;107.513167 +random,1024,8192,64,far,ref,0,32,7.093000,9,7.049625;6.997417;7.093000;6.971875;7.082042;7.106000;7.180791;7.158083;7.143250 +random,16384,131072,64,far,ref,0,32,149.749750,9,149.000292;149.749750;149.729417;154.389250;149.780083;149.536709;149.227542;150.169167;155.094416 +random,65536,524288,16,far,ref,0,32,201.204958,9,198.333625;195.605250;206.026334;204.001458;199.659708;201.204958;196.077834;233.704458;211.461416 +random,1024,8192,64,near,ref,0,32,0.042584,9,0.053208;0.042500;0.042166;0.043625;0.042625;0.042584;0.042667;0.041833;0.042000 +random,16384,131072,64,near,ref,0,32,0.402375,9,0.403084;0.411250;0.396709;0.396209;0.402375;0.405083;0.404750;0.393667;0.394125 +random,65536,524288,64,near,ref,0,32,1.505625,9,1.490084;1.491875;1.527917;1.524792;1.505625;1.635250;1.522292;1.500542;1.498333 +random,262144,2097152,16,near,ref,0,32,1.491458,9,1.448042;1.475334;1.456458;1.498000;1.502959;1.516000;1.550250;1.491458;1.483708 +random,262144,2097152,1,none,ref,0,32,96.220542,9,96.220542;99.851167;96.823708;92.344792;90.409417;89.217250;89.115792;96.658666;97.151708 +random,4096,32768,64,reverse,ref,0,32,34.225416,9,34.518125;34.398250;34.308125;34.140792;34.143125;34.115125;34.155500;34.273000;34.225416 +random,16384,131072,16,reverse,ref,0,32,38.665209,9,38.807916;38.697167;38.897083;38.665209;38.407208;38.855583;38.632208;38.602916;38.591125 +clos,800,320000,16,reverse,ref,0,2,37.150083,9,39.364542;37.592042;37.042417;38.531000;37.150083;37.109750;38.969375;37.142042;36.280792 +chain,2048,2047,1,reverse,ref,0,32,0.000958,9,0.000958;0.000959;0.000917;0.000958;0.000959;0.000958;0.000916;0.000917;0.000916 diff --git a/dev/perf/spf_queue/results/first/correctness-sanitized.txt b/dev/perf/spf_queue/results/first/correctness-sanitized.txt new file mode 100644 index 0000000..347c0ee --- /dev/null +++ b/dev/perf/spf_queue/results/first/correctness-sanitized.txt @@ -0,0 +1,2 @@ +checked=1351168 failed=0 +exit=0 diff --git a/dev/perf/spf_queue/results/first/correctness-teeth.txt b/dev/perf/spf_queue/results/first/correctness-teeth.txt new file mode 100644 index 0000000..d723574 --- /dev/null +++ b/dev/perf/spf_queue/results/first/correctness-teeth.txt @@ -0,0 +1 @@ +checked=1351168 failed=167636 diff --git a/dev/perf/spf_queue/results/first/correctness.txt b/dev/perf/spf_queue/results/first/correctness.txt new file mode 100644 index 0000000..347c0ee --- /dev/null +++ b/dev/perf/spf_queue/results/first/correctness.txt @@ -0,0 +1,2 @@ +checked=1351168 failed=0 +exit=0 diff --git a/dev/perf/spf_queue/results/first/environment.txt b/dev/perf/spf_queue/results/first/environment.txt new file mode 100644 index 0000000..b5c6fa9 --- /dev/null +++ b/dev/perf/spf_queue/results/first/environment.txt @@ -0,0 +1,8 @@ +date: 2026-09-27T13:35:56Z +commit: fbab119e794c843838f4f3f96d75cb7f32f06845 +Apple M4 Max +ae2f8f3b2f2839d6d088e0a938b86cba02c23c285c33cac99df6bf369286f264 dev/perf/spf_queue/spf_variants.hpp +a0ac4290fd6b47bdefcc4bd4cf50257e275406cb34f371e4c0ba30368b0fea45 dev/perf/spf_queue/harness.cpp +9ee6053d38a0b1e44df958e423e12ab93fb54c3d80c8d4bcb623730362b8f441 src/shortest_paths.cpp +12f65bdc8daa9415d118d062bdc897981bde448f5391bed2c711c8c968e9322b src/strict_multidigraph.cpp +Apple clang version 21.0.0 (clang-2100.1.1.101) diff --git a/dev/perf/spf_queue/results/first/load.txt b/dev/perf/spf_queue/results/first/load.txt new file mode 100644 index 0000000..3452f6c --- /dev/null +++ b/dev/perf/spf_queue/results/first/load.txt @@ -0,0 +1,15 @@ +14:35 up 47 days, 19:11, 3 users, load averages: 3.33 3.01 3.05 +14:36 up 47 days, 19:12, 3 users, load averages: 2.94 2.95 3.03 +14:36 up 47 days, 19:12, 3 users, load averages: 4.08 3.21 3.12 +14:37 up 47 days, 19:12, 3 users, load averages: 3.95 3.25 3.14 +14:37 up 47 days, 19:13, 3 users, load averages: 3.41 3.18 3.11 +14:37 up 47 days, 19:13, 3 users, load averages: 3.16 3.14 3.10 +14:38 up 47 days, 19:13, 3 users, load averages: 3.64 3.25 3.14 +14:38 up 47 days, 19:14, 3 users, load averages: 3.28 3.18 3.12 +14:38 up 47 days, 19:14, 3 users, load averages: 3.21 3.17 3.11 +14:39 up 47 days, 19:14, 3 users, load averages: 3.47 3.24 3.14 +14:39 up 47 days, 19:15, 3 users, load averages: 3.59 3.29 3.16 +14:39 up 47 days, 19:15, 3 users, load averages: 3.55 3.28 3.16 +14:39 up 47 days, 19:15, 3 users, load averages: 3.42 3.26 3.15 +14:39 up 47 days, 19:15, 3 users, load averages: 3.63 3.31 3.17 +14:39 up 47 days, 19:15, 3 users, load averages: 3.63 3.31 3.17 diff --git a/dev/perf/spf_queue/results/first/sweep-bsort-sparse.csv b/dev/perf/spf_queue/results/first/sweep-bsort-sparse.csv new file mode 100644 index 0000000..d6524b4 --- /dev/null +++ b/dev/perf/spf_queue/results/first/sweep-bsort-sparse.csv @@ -0,0 +1,7 @@ +case,n,e,queries,dst,variant,fallback,W,median_ms,samples,wall_samples_ms +wide1,16384,131072,16,none,bsort-sparse,0,2,36.213417,9,37.503167;36.411458;36.550708;35.483709;36.001917;36.213417;37.912750;35.776291;36.088458 +wide31,16384,131072,16,none,bsort-sparse,0,32,37.633250,9,37.642292;37.615583;37.526041;37.746125;37.884709;37.733334;37.633250;37.480625;37.275917 +wide1023,16384,131072,16,none,bsort-sparse,0,1024,33.782917,9,33.744125;33.971042;33.692333;33.873166;33.782917;33.827375;33.746500;33.667792;33.785417 +wide32767,16384,131072,16,none,bsort-sparse,0,32768,34.269584,9,34.145166;34.158250;34.001209;34.269584;33.649958;34.406584;34.414625;34.346042;34.283834 +wide1048575,16384,131072,16,none,bsort-sparse,0,1048570,46.217500,9,45.310209;47.594125;46.217500;46.955084;46.440625;46.040500;45.000041;46.189209;47.516000 +wide33554431,16384,131072,16,none,bsort-sparse,1,33554196,56.886334,9,55.632334;57.164750;57.547542;57.042417;56.886334;57.274458;56.415333;56.450250;56.839292 diff --git a/dev/perf/spf_queue/results/first/sweep-bucket-sparse.csv b/dev/perf/spf_queue/results/first/sweep-bucket-sparse.csv new file mode 100644 index 0000000..e172a77 --- /dev/null +++ b/dev/perf/spf_queue/results/first/sweep-bucket-sparse.csv @@ -0,0 +1,7 @@ +case,n,e,queries,dst,variant,fallback,W,median_ms,samples,wall_samples_ms +wide1,16384,131072,16,none,bucket-sparse,0,2,35.220125,9,34.863958;35.220125;35.179708;35.015167;35.218083;35.266916;35.852333;35.964375;35.417875 +wide31,16384,131072,16,none,bucket-sparse,0,32,35.754000,9,35.186583;35.210584;36.171750;36.027334;36.380417;35.901208;35.754000;35.222417;35.417541 +wide1023,16384,131072,16,none,bucket-sparse,0,1024,34.063333,9,34.236000;34.070875;34.083625;33.672625;34.063333;33.680458;33.881833;33.872875;34.160292 +wide32767,16384,131072,16,none,bucket-sparse,0,32768,35.003458,9,35.149750;35.003458;34.967500;35.018583;35.021125;34.919542;34.933209;35.050500;34.908083 +wide1048575,16384,131072,16,none,bucket-sparse,0,1048570,46.844291,9,46.844291;44.614167;46.522541;45.393916;46.223250;47.520584;48.872792;48.944750;46.885625 +wide33554431,16384,131072,16,none,bucket-sparse,1,33554196,56.527708,9,56.282083;56.527708;56.688292;56.450375;58.205833;56.590208;56.040166;56.696125;56.417125 diff --git a/dev/perf/spf_queue/results/first/sweep-heap-sparse.csv b/dev/perf/spf_queue/results/first/sweep-heap-sparse.csv new file mode 100644 index 0000000..7164155 --- /dev/null +++ b/dev/perf/spf_queue/results/first/sweep-heap-sparse.csv @@ -0,0 +1,7 @@ +case,n,e,queries,dst,variant,fallback,W,median_ms,samples,wall_samples_ms +wide1,16384,131072,16,none,heap-sparse,0,2,46.968625,9,47.229292;46.897250;46.189542;46.399666;48.464125;47.555375;46.968625;47.561292;46.556542 +wide31,16384,131072,16,none,heap-sparse,0,32,69.403708,9,69.283542;69.735167;69.185625;69.599000;69.889917;69.209417;69.402167;69.403708;70.222125 +wide1023,16384,131072,16,none,heap-sparse,0,1024,67.032584,9,67.360250;66.871958;67.032584;67.299542;67.001125;67.400292;68.543416;66.935334;66.819000 +wide32767,16384,131072,16,none,heap-sparse,0,32768,58.449708,9,57.046833;58.449708;59.940292;59.077958;59.057333;58.319000;58.592958;58.129917;57.809250 +wide1048575,16384,131072,16,none,heap-sparse,0,1048570,57.236042,9,57.512500;56.372916;57.242875;56.918167;57.274917;57.236042;56.913416;57.412625;57.007750 +wide33554431,16384,131072,16,none,heap-sparse,1,33554196,56.640542,9,56.641292;55.692875;55.862500;55.489417;56.796875;56.640542;56.854500;56.504375;56.956292 diff --git a/dev/perf/spf_queue/results/first/sweep-ref.csv b/dev/perf/spf_queue/results/first/sweep-ref.csv new file mode 100644 index 0000000..0b8390b --- /dev/null +++ b/dev/perf/spf_queue/results/first/sweep-ref.csv @@ -0,0 +1,7 @@ +case,n,e,queries,dst,variant,fallback,W,median_ms,samples,wall_samples_ms +wide1,16384,131072,16,none,ref,0,2,43.727417,9,43.343875;44.084000;43.727417;43.741292;43.888209;43.588916;43.806583;43.654875;43.198666 +wide31,16384,131072,16,none,ref,0,32,62.112375,9,62.803250;61.927958;62.112375;61.957708;61.832417;61.767541;63.810750;68.329792;62.300042 +wide1023,16384,131072,16,none,ref,0,1024,58.154708,9,57.620875;58.266375;58.270167;57.265875;57.078750;59.170875;57.157083;58.154708;63.124917 +wide32767,16384,131072,16,none,ref,0,32768,49.973584,9,50.194417;49.654458;49.866084;49.973584;50.138500;50.410167;49.828167;49.296625;50.260250 +wide1048575,16384,131072,16,none,ref,0,1048570,48.596208,9,47.921292;48.808916;48.395167;48.596208;48.227875;48.645500;48.894667;49.038500;48.373792 +wide33554431,16384,131072,16,none,ref,1,33554196,48.868375,9,48.062459;48.759333;49.000291;48.868375;48.529750;48.639958;49.409125;48.982166;48.976000 diff --git a/dev/perf/spf_queue/results/first/time-bsort-fresh-b.csv b/dev/perf/spf_queue/results/first/time-bsort-fresh-b.csv new file mode 100644 index 0000000..807378f --- /dev/null +++ b/dev/perf/spf_queue/results/first/time-bsort-fresh-b.csv @@ -0,0 +1,20 @@ +case,n,e,queries,dst,variant,fallback,W,median_ms,samples,wall_samples_ms +random,1024,8192,1,none,bsort-fresh,0,32,0.073000,9,0.079958;0.074375;0.074041;0.072541;0.072417;0.072791;0.073250;0.072875;0.073000 +random,4096,32768,256,none,bsort-fresh,0,32,127.398375,9,126.718708;125.971417;126.947417;129.972584;128.232417;128.374958;128.044166;127.398375;127.396167 +random,16384,131072,64,none,bsort-fresh,0,32,144.333333,9,144.555416;147.892875;145.481209;143.996083;144.333333;144.136167;144.596167;144.100209;143.942459 +random,65536,524288,1,none,bsort-fresh,0,32,10.920625,9,10.780291;10.920625;10.930583;10.925833;10.912958;10.827666;10.885833;11.177000;10.983875 +random,4096,131072,64,none,bsort-fresh,0,32,65.595250,9,65.367834;65.363375;64.938292;66.759000;67.187209;68.249708;67.946375;65.595250;64.582250 +clos,800,320000,64,none,bsort-fresh,0,2,126.180125,9,127.017042;126.199333;125.849000;125.754625;125.813333;126.180125;126.682042;126.612375;125.955541 +grid,10000,39600,1,none,bsort-fresh,0,2,0.392833,9,0.435875;0.402709;0.395417;0.394042;0.392833;0.389209;0.389291;0.389250;0.391500 +chain,2048,2047,1,none,bsort-fresh,0,32,0.044875,9,0.065416;0.045250;0.048167;0.045000;0.043750;0.044666;0.044708;0.044875;0.044791 +uniform,16384,131072,64,none,bsort-fresh,0,2,142.049166,9,142.963458;143.555708;140.099292;144.939667;147.514959;141.901334;142.049166;141.335459;141.541834 +random_masked,16384,131072,64,none,bsort-fresh,0,32,140.737542,9,139.656959;139.978542;141.379625;142.474875;140.737542;140.405875;141.147333;139.679375;141.383500 +pseudo,802,320200,64,fixed,bsort-fresh,0,2,130.713667,9,134.616125;131.302333;132.074667;131.003750;130.271167;130.713667;129.811250;128.510167;126.406125 +random,1024,8192,64,far,bsort-fresh,0,32,6.481416,9,6.446375;6.834125;6.495416;6.481416;6.725083;6.711584;6.344709;6.472000;6.272958 +random,16384,131072,64,far,bsort-fresh,0,32,143.584500,9,144.152958;143.569083;143.288000;144.914292;143.919625;143.357792;142.812792;144.227542;143.584500 +random,65536,524288,16,far,bsort-fresh,0,32,177.307125,9,172.243125;178.124000;174.089375;187.898458;194.189167;181.906334;177.307125;173.282583;175.041833 +random,1024,8192,64,near,bsort-fresh,0,32,0.115500,9,0.127708;0.113375;0.112916;0.111750;0.118541;0.116708;0.131792;0.115500;0.112166 +random,16384,131072,64,near,bsort-fresh,0,32,1.114708,9,1.096125;1.098250;1.114708;1.131916;1.203875;1.139833;1.164917;1.066291;1.106917 +random,65536,524288,64,near,bsort-fresh,0,32,4.342334,9,4.342334;4.513791;4.308459;4.539084;4.296958;4.536416;4.332875;4.542125;4.300667 +random,262144,2097152,16,near,bsort-fresh,0,32,4.199250,9,19.132917;19.258458;16.012125;3.874875;4.016334;4.104625;4.215708;4.122584;4.199250 +random,262144,2097152,1,none,bsort-fresh,0,32,82.487666,9,82.487666;82.558167;83.558916;82.006250;80.108042;81.022917;82.437333;87.462667;84.019958 diff --git a/dev/perf/spf_queue/results/first/time-bsort-sparse-b.csv b/dev/perf/spf_queue/results/first/time-bsort-sparse-b.csv new file mode 100644 index 0000000..42185a1 --- /dev/null +++ b/dev/perf/spf_queue/results/first/time-bsort-sparse-b.csv @@ -0,0 +1,20 @@ +case,n,e,queries,dst,variant,fallback,W,median_ms,samples,wall_samples_ms +random,1024,8192,1,none,bsort-sparse,0,32,0.072208,9,0.077833;0.073958;0.074833;0.072125;0.072000;0.072208;0.072333;0.071375;0.071583 +random,4096,32768,256,none,bsort-sparse,0,32,130.563333,9,130.291542;129.928333;129.826125;130.341792;132.589334;130.890375;130.563333;132.631791;133.538958 +random,16384,131072,64,none,bsort-sparse,0,32,154.019875,9,150.272541;149.183208;158.544792;154.019875;152.807500;157.225917;154.544834;152.768542;156.195500 +random,65536,524288,1,none,bsort-sparse,0,32,12.254041,9,11.671833;11.614125;11.664000;12.254041;12.390959;13.516750;12.239416;13.174959;12.510875 +random,4096,131072,64,none,bsort-sparse,0,32,66.531042,9,66.602416;66.531042;67.645250;66.783667;66.124292;66.494833;66.341375;66.474667;66.600375 +clos,800,320000,64,none,bsort-sparse,0,2,128.233625,9,127.980125;127.916459;128.161375;128.233625;128.160375;131.579125;129.286625;131.803792;130.153792 +grid,10000,39600,1,none,bsort-sparse,0,2,0.414875,9,0.424042;0.419708;0.413625;0.414875;0.412208;0.410958;0.410708;0.578292;0.429708 +chain,2048,2047,1,none,bsort-sparse,0,32,0.045375,9,0.047542;0.047834;0.047791;0.047667;0.043625;0.043500;0.043500;0.043416;0.045375 +uniform,16384,131072,64,none,bsort-sparse,0,2,140.927958,9,140.451625;140.927958;140.518625;141.233375;140.714709;146.751417;144.065209;141.193125;140.622750 +random_masked,16384,131072,64,none,bsort-sparse,0,32,147.117084,9,150.706875;160.268500;150.488166;146.747542;146.520458;146.777958;147.836209;147.117084;146.608750 +pseudo,802,320200,64,fixed,bsort-sparse,0,2,126.737125,9,130.360708;126.737125;125.585334;126.883500;126.408666;126.394500;128.847042;127.032125;126.336500 +random,1024,8192,64,far,bsort-sparse,0,32,6.427875,9,6.558666;6.515333;6.526083;6.427875;6.496250;6.376792;6.409709;6.403500;6.394375 +random,16384,131072,64,far,bsort-sparse,0,32,150.673083,9,150.673083;150.674500;151.902042;149.348292;149.884167;150.329125;150.647417;154.169167;153.845334 +random,65536,524288,16,far,bsort-sparse,0,32,185.616042,9,186.573292;184.522542;185.096875;187.703416;185.322625;185.616042;185.213666;193.822083;188.567750 +random,1024,8192,64,near,bsort-sparse,0,32,0.043000,9,0.065917;0.043125;0.043125;0.043167;0.042916;0.042833;0.043000;0.043000;0.043000 +random,16384,131072,64,near,bsort-sparse,0,32,0.393959,9,0.405375;0.395667;0.393333;0.393542;0.393959;0.393208;0.393417;0.394000;0.418083 +random,65536,524288,64,near,bsort-sparse,0,32,1.495875,9,1.513000;1.495875;1.430333;1.527417;1.487333;1.504167;1.507000;1.488542;1.487417 +random,262144,2097152,16,near,bsort-sparse,0,32,1.450708,9,1.420625;1.438834;1.450708;1.506708;1.423125;1.437542;1.453250;1.454167;1.470750 +random,262144,2097152,1,none,bsort-sparse,0,32,86.061459,9,86.686250;86.173459;86.626250;86.437875;84.282875;86.061459;84.945792;84.178333;85.198459 diff --git a/dev/perf/spf_queue/results/first/time-bucket-fresh-b.csv b/dev/perf/spf_queue/results/first/time-bucket-fresh-b.csv new file mode 100644 index 0000000..5059745 --- /dev/null +++ b/dev/perf/spf_queue/results/first/time-bucket-fresh-b.csv @@ -0,0 +1,20 @@ +case,n,e,queries,dst,variant,fallback,W,median_ms,samples,wall_samples_ms +random,1024,8192,1,none,bucket-fresh,0,32,0.078458,9,0.093458;0.084416;0.082417;0.076584;0.078708;0.077917;0.076000;0.078458;0.075917 +random,4096,32768,256,none,bucket-fresh,0,32,117.688709,9,117.763250;117.568541;119.826709;117.148083;116.848875;117.782000;117.688709;117.028166;118.412333 +random,16384,131072,64,none,bucket-fresh,0,32,133.422291,9,133.422291;135.131084;134.927209;134.389375;133.486125;132.716542;132.560333;133.355458;132.436375 +random,65536,524288,1,none,bucket-fresh,0,32,10.957041,9,10.897542;11.583166;10.951750;11.056250;10.957041;10.634750;10.294625;11.157000;11.140709 +random,4096,131072,64,none,bucket-fresh,0,32,64.141542,9,64.153834;64.116459;64.415125;64.283583;64.291917;64.082167;63.974250;64.141542;63.823958 +clos,800,320000,64,none,bucket-fresh,0,2,126.132042,9,126.527125;127.438167;126.097917;126.135291;124.511084;125.285209;127.010417;126.132042;125.727250 +grid,10000,39600,1,none,bucket-fresh,0,2,0.465958,9,0.481958;0.518250;0.500708;0.485542;0.445792;0.465958;0.458459;0.460042;0.458459 +chain,2048,2047,1,none,bucket-fresh,0,32,0.044875,9,0.040125;0.039916;0.039792;0.041417;0.044916;0.047375;0.045000;0.044875;0.044959 +uniform,16384,131072,64,none,bucket-fresh,0,2,142.378625,9,142.732667;142.469708;141.925417;141.230333;141.874083;141.373375;142.378625;144.852500;143.189958 +random_masked,16384,131072,64,none,bucket-fresh,0,32,130.637375,9,130.457042;130.042792;130.783042;130.637375;131.483084;129.935333;130.749792;130.790208;129.892000 +pseudo,802,320200,64,fixed,bucket-fresh,0,2,125.455083,9,126.943167;127.354084;127.369666;125.342417;124.162583;124.628250;126.541666;124.528000;125.455083 +random,1024,8192,64,far,bucket-fresh,0,32,6.255334,9,6.339792;6.285750;6.213042;6.201625;6.179083;6.276625;6.341917;6.255334;6.172750 +random,16384,131072,64,far,bucket-fresh,0,32,134.766458,9,133.359833;134.506208;135.116584;134.766458;133.574917;135.545875;134.077708;135.431416;134.812250 +random,65536,524288,16,far,bucket-fresh,0,32,162.663333,9,161.521083;163.212958;161.964459;162.663333;162.321958;162.549250;176.804958;175.382292;163.466083 +random,1024,8192,64,near,bucket-fresh,0,32,0.111042,9,0.117166;0.110916;0.111334;0.111125;0.103458;0.110916;0.111167;0.111042;0.106584 +random,16384,131072,64,near,bucket-fresh,0,32,1.190333,9,1.202959;1.218000;1.134083;1.148417;1.185709;1.190333;1.194292;1.222500;1.178833 +random,65536,524288,64,near,bucket-fresh,0,32,4.332041,9,4.265875;4.366833;4.247917;4.384917;4.282750;4.491208;4.332041;4.374708;4.267042 +random,262144,2097152,16,near,bucket-fresh,0,32,4.090291,9,3.828583;3.954084;3.899584;4.046292;4.130250;4.090291;4.241917;4.186083;4.144292 +random,262144,2097152,1,none,bucket-fresh,0,32,83.624875,9,91.434167;85.099291;87.027625;80.038375;82.772375;82.189167;89.432791;83.624875;82.109959 diff --git a/dev/perf/spf_queue/results/first/time-bucket-full-b.csv b/dev/perf/spf_queue/results/first/time-bucket-full-b.csv new file mode 100644 index 0000000..538ceb5 --- /dev/null +++ b/dev/perf/spf_queue/results/first/time-bucket-full-b.csv @@ -0,0 +1,20 @@ +case,n,e,queries,dst,variant,fallback,W,median_ms,samples,wall_samples_ms +random,1024,8192,1,none,bucket-full,0,32,0.074792,9,0.077917;0.075750;0.075750;0.074292;0.075417;0.074625;0.074583;0.074792;0.074333 +random,4096,32768,256,none,bucket-full,0,32,119.398208,9,119.398208;120.878167;121.197792;119.620666;119.044750;119.726625;118.877792;119.055292;118.027042 +random,16384,131072,64,none,bucket-full,0,32,133.055000,9,132.952084;133.698125;133.055000;132.576417;132.905875;132.183916;134.968292;134.945500;133.846167 +random,65536,524288,1,none,bucket-full,0,32,10.186875,9,10.190542;10.191834;10.115083;10.186875;10.053959;10.254500;10.136125;10.263666;10.180708 +random,4096,131072,64,none,bucket-full,0,32,64.248666,9,64.910709;65.125209;64.397542;64.248666;64.636667;63.902875;64.126208;64.172666;64.079292 +clos,800,320000,64,none,bucket-full,0,2,126.467500,9,126.599375;125.362625;126.467500;125.210875;126.247625;126.411750;128.020208;127.637875;126.887833 +grid,10000,39600,1,none,bucket-full,0,2,0.472750,9,0.490500;0.472750;0.471250;0.472041;0.469583;0.471792;0.475917;0.481375;0.482125 +chain,2048,2047,1,none,bucket-full,0,32,0.045209,9,0.044459;0.049250;0.044791;0.045209;0.044875;0.045292;0.054958;0.052167;0.044208 +uniform,16384,131072,64,none,bucket-full,0,2,145.564458,9,144.952791;143.328833;147.899167;146.651959;145.564458;144.691208;149.940875;145.752250;145.242666 +random_masked,16384,131072,64,none,bucket-full,0,32,131.274375,9,135.150667;131.974417;131.884375;130.784167;131.197041;132.654042;131.274375;131.134000;131.139709 +pseudo,802,320200,64,fixed,bucket-full,0,2,125.527166,9,126.696875;125.384625;125.527166;124.887125;124.589833;124.728791;128.626125;126.069667;126.432875 +random,1024,8192,64,far,bucket-full,0,32,6.198584,9,6.198584;6.652333;6.384875;6.345208;6.184625;6.220209;6.114625;6.120791;6.145667 +random,16384,131072,64,far,bucket-full,0,32,133.248250,9,132.824000;134.288167;136.456167;134.005667;133.142208;133.248250;133.024458;133.895208;132.927083 +random,65536,524288,16,far,bucket-full,0,32,163.100042,9,167.189291;163.153667;162.840500;163.100042;163.073125;163.641167;165.388459;162.862792;163.054042 +random,1024,8192,64,near,bucket-full,0,32,0.111750,9,0.112333;0.111750;0.112292;0.102667;0.108375;0.112416;0.111000;0.102417;0.111916 +random,16384,131072,64,near,bucket-full,0,32,1.309166,9,1.309166;1.320833;1.325750;1.314833;1.301125;1.302167;1.301375;1.326458;1.305167 +random,65536,524288,64,near,bucket-full,0,32,4.804834,9,4.460792;4.986750;4.804834;5.224542;4.583125;4.763250;4.781834;4.829125;4.814208 +random,262144,2097152,16,near,bucket-full,0,32,5.560917,9,5.646708;5.523042;5.358334;5.583625;5.366417;5.509125;5.560917;5.655583;5.652541 +random,262144,2097152,1,none,bucket-full,0,32,80.930042,9,82.033958;78.861125;81.416959;81.632916;81.707416;80.163083;80.265000;79.492458;80.930042 diff --git a/dev/perf/spf_queue/results/first/time-bucket-sparse-b.csv b/dev/perf/spf_queue/results/first/time-bucket-sparse-b.csv new file mode 100644 index 0000000..e4898a0 --- /dev/null +++ b/dev/perf/spf_queue/results/first/time-bucket-sparse-b.csv @@ -0,0 +1,20 @@ +case,n,e,queries,dst,variant,fallback,W,median_ms,samples,wall_samples_ms +random,1024,8192,1,none,bucket-sparse,0,32,0.069417,9,0.073833;0.070791;0.069417;0.069167;0.068500;0.068208;0.068208;0.072083;0.075166 +random,4096,32768,256,none,bucket-sparse,0,32,122.055459,9,122.239000;121.626000;121.953875;121.374791;123.540416;122.909333;122.823917;121.561042;122.055459 +random,16384,131072,64,none,bucket-sparse,0,32,140.305917,9,140.002792;140.915750;141.959167;139.621583;140.114750;140.479542;140.596666;140.305917;139.659000 +random,65536,524288,1,none,bucket-sparse,0,32,10.681958,9,10.657250;10.608375;10.681958;10.690167;10.477083;10.461584;10.873584;12.338417;11.963750 +random,4096,131072,64,none,bucket-sparse,0,32,65.799209,9,65.799209;65.483625;65.478167;65.776875;66.112542;65.268375;66.647750;67.733209;67.061167 +clos,800,320000,64,none,bucket-sparse,0,2,127.859500,9,127.814458;126.084333;125.578083;127.859500;129.214167;128.186167;127.734041;128.022083;131.675041 +grid,10000,39600,1,none,bucket-sparse,0,2,0.497208,9,0.497417;0.496833;0.535958;0.512917;0.497208;0.490792;0.489250;0.496250;0.501875 +chain,2048,2047,1,none,bucket-sparse,0,32,0.044541,9,0.044166;0.044541;0.044792;0.044875;0.043875;0.040167;0.044000;0.044709;0.044833 +uniform,16384,131072,64,none,bucket-sparse,0,2,140.725750,9,140.679042;140.899333;140.650959;140.534083;143.067333;141.098916;140.725750;140.329209;141.557458 +random_masked,16384,131072,64,none,bucket-sparse,0,32,138.444792,9,137.654583;138.033375;139.399875;137.454083;139.411583;138.656625;140.437916;138.444792;137.928167 +pseudo,802,320200,64,fixed,bucket-sparse,0,2,127.199916,9,127.469500;126.634000;126.764916;127.199916;126.949334;126.892792;127.591084;127.256125;127.498833 +random,1024,8192,64,far,bucket-sparse,0,32,6.545583,9,6.714750;6.495500;6.545583;6.496458;6.496833;6.469416;6.560708;6.591291;6.639250 +random,16384,131072,64,far,bucket-sparse,0,32,140.847709,9,140.817500;144.266000;140.847709;140.950125;140.655417;141.417417;140.807834;140.897667;140.688000 +random,65536,524288,16,far,bucket-sparse,0,32,176.071583,9,174.404500;173.780334;176.126125;175.394916;174.731542;207.892875;177.738708;176.071583;177.683416 +random,1024,8192,64,near,bucket-sparse,0,32,0.043500,9,0.051000;0.044833;0.043958;0.044500;0.043500;0.043167;0.038750;0.043416;0.043208 +random,16384,131072,64,near,bucket-sparse,0,32,0.393292,9,0.393458;0.393208;0.394791;0.393292;0.393250;0.393375;0.395333;0.392917;0.392709 +random,65536,524288,64,near,bucket-sparse,0,32,1.488667,9,1.476667;1.489542;1.501916;1.490959;1.503042;1.488625;1.488667;1.420125;1.457042 +random,262144,2097152,16,near,bucket-sparse,0,32,1.448875,9,1.507625;1.487041;1.448875;1.448041;1.456500;1.461791;1.438708;1.408958;1.411375 +random,262144,2097152,1,none,bucket-sparse,0,32,87.025667,9,88.228625;88.995625;89.278125;86.785542;85.460000;87.117750;87.025000;86.052083;87.025667 diff --git a/dev/perf/spf_queue/results/first/time-heap-fresh-b.csv b/dev/perf/spf_queue/results/first/time-heap-fresh-b.csv new file mode 100644 index 0000000..c7f0a9d --- /dev/null +++ b/dev/perf/spf_queue/results/first/time-heap-fresh-b.csv @@ -0,0 +1,20 @@ +case,n,e,queries,dst,variant,fallback,W,median_ms,samples,wall_samples_ms +random,1024,8192,1,none,heap-fresh,0,32,0.115375,9,0.135375;0.116291;0.120250;0.116500;0.113917;0.110208;0.114250;0.115084;0.115375 +random,4096,32768,256,none,heap-fresh,0,32,223.834916,9,224.898208;224.539834;224.930084;222.888125;222.325041;223.091583;221.774625;224.744125;223.834916 +random,16384,131072,64,none,heap-fresh,0,32,265.681750,9,266.057250;262.723041;265.681750;265.032292;264.191792;271.088500;266.109166;263.244750;269.137166 +random,65536,524288,1,none,heap-fresh,0,32,19.683459,9,19.345209;19.499500;20.155625;20.074083;19.409083;19.608167;19.887625;19.941041;19.683459 +random,4096,131072,64,none,heap-fresh,0,32,113.862791,9,114.006792;113.152833;113.679917;113.862791;115.032583;114.331750;113.343167;114.297083;113.528666 +clos,800,320000,64,none,heap-fresh,0,2,133.167417,9,134.150583;134.728791;135.087416;132.998625;132.928084;134.091042;133.023917;133.167417;132.971333 +grid,10000,39600,1,none,heap-fresh,0,2,0.689458,9,0.712083;0.697250;0.709292;0.689458;0.686583;0.683166;0.679958;0.682000;0.691167 +chain,2048,2047,1,none,heap-fresh,0,32,0.023542,9,0.023708;0.023750;0.023500;0.023792;0.023459;0.023458;0.023500;0.023666;0.023542 +uniform,16384,131072,64,none,heap-fresh,0,2,183.190666,9,181.771166;182.520459;184.364584;181.516292;183.190666;189.134792;183.239958;190.424542;183.068458 +random_masked,16384,131072,64,none,heap-fresh,0,32,242.620042,9,243.224625;251.311000;241.052000;241.867042;242.354042;250.248167;243.503416;241.469541;242.620042 +pseudo,802,320200,64,fixed,heap-fresh,0,2,133.608041,9,134.581458;133.274083;133.141459;132.606250;134.189167;133.608041;132.927208;136.439583;135.795666 +random,1024,8192,64,far,heap-fresh,0,32,11.316167,9,11.444291;11.045375;11.190875;11.316167;11.364459;11.323000;11.470167;11.278541;11.179041 +random,16384,131072,64,far,heap-fresh,0,32,266.656375,9,266.065000;263.982750;266.656375;270.425500;269.786708;266.468000;265.333458;268.683750;271.332375 +random,65536,524288,16,far,heap-fresh,0,32,326.680791,9,329.341125;326.680791;326.758208;321.000542;335.756333;326.244750;323.910042;340.101375;324.130500 +random,1024,8192,64,near,heap-fresh,0,32,0.107708,9,0.149875;0.118667;0.100459;0.107375;0.108125;0.107708;0.102208;0.107541;0.108417 +random,16384,131072,64,near,heap-fresh,0,32,1.120875,9,1.115834;1.116750;1.131292;1.120875;1.117917;1.148708;1.117417;1.132916;1.144584 +random,65536,524288,64,near,heap-fresh,0,32,4.239500,9,4.239500;4.149917;4.355250;4.177916;4.380166;4.192875;4.372500;4.234792;4.392750 +random,262144,2097152,16,near,heap-fresh,0,32,18.921708,9,18.899709;18.846708;19.207000;18.773125;18.921708;18.525292;19.286667;19.227375;19.109542 +random,262144,2097152,1,none,heap-fresh,0,32,128.563542,9,128.563542;129.742458;130.436708;130.550250;129.716083;127.658042;128.143750;127.020417;127.533833 diff --git a/dev/perf/spf_queue/results/first/time-heap-full-b.csv b/dev/perf/spf_queue/results/first/time-heap-full-b.csv new file mode 100644 index 0000000..ff3653c --- /dev/null +++ b/dev/perf/spf_queue/results/first/time-heap-full-b.csv @@ -0,0 +1,20 @@ +case,n,e,queries,dst,variant,fallback,W,median_ms,samples,wall_samples_ms +random,1024,8192,1,none,heap-full,0,32,0.118166,9,0.146458;0.119167;0.118291;0.118166;0.115708;0.110000;0.114708;0.118625;0.114792 +random,4096,32768,256,none,heap-full,0,32,225.395542,9,228.126834;225.598041;226.784417;224.466333;225.105541;223.834291;229.336083;225.395542;224.983000 +random,16384,131072,64,none,heap-full,0,32,265.663667,9,265.335083;264.208125;265.271333;265.663667;270.274833;266.530500;266.512042;265.724917;265.575583 +random,65536,524288,1,none,heap-full,0,32,19.883583,9,20.028709;19.561417;20.049292;19.653542;20.800750;19.901500;19.473959;19.149125;19.883583 +random,4096,131072,64,none,heap-full,0,32,114.433792,9,114.462042;113.903833;114.012792;113.931000;114.783792;113.315125;116.039125;115.399625;114.433792 +clos,800,320000,64,none,heap-full,0,2,135.741666,9,135.116917;134.591250;135.741666;135.747500;137.683500;134.934209;135.111292;136.439125;136.778917 +grid,10000,39600,1,none,heap-full,0,2,0.666084,9,0.686292;0.695459;0.687708;0.668750;0.666084;0.652834;0.655833;0.664750;0.651542 +chain,2048,2047,1,none,heap-full,0,32,0.024042,9,0.024125;0.024000;0.024042;0.024166;0.024000;0.024166;0.024000;0.024042;0.023917 +uniform,16384,131072,64,none,heap-full,0,2,186.434333,9,186.382125;187.959625;187.210125;186.661417;186.400625;186.434333;185.308791;186.939208;186.230500 +random_masked,16384,131072,64,none,heap-full,0,32,242.225833,9,243.238083;241.939542;240.649917;243.730625;242.225833;241.985083;242.513833;242.397167;241.178917 +pseudo,802,320200,64,fixed,heap-full,0,2,135.039292,9,136.127209;133.944250;134.869292;135.412083;135.039292;136.334667;134.849584;135.085750;134.163375 +random,1024,8192,64,far,heap-full,0,32,11.354459,9,11.433541;11.354459;11.310458;11.410833;11.384834;11.358375;11.285875;11.261625;11.155958 +random,16384,131072,64,far,heap-full,0,32,266.233750,9,270.825250;270.773958;265.282750;266.282667;266.233750;265.749042;267.558791;264.842958;266.230209 +random,65536,524288,16,far,heap-full,0,32,326.155042,9,326.112541;326.155042;324.624875;328.796792;338.246416;326.962750;329.384750;325.279000;325.245000 +random,1024,8192,64,near,heap-full,0,32,0.111833,9,0.115042;0.111333;0.112917;0.111833;0.112875;0.108791;0.112125;0.111584;0.100958 +random,16384,131072,64,near,heap-full,0,32,1.321000,9,1.307833;1.309541;1.333500;1.328000;1.316583;1.303833;1.358750;1.322084;1.321000 +random,65536,524288,64,near,heap-full,0,32,4.666167,9,4.680125;4.746792;4.687000;4.710875;4.567125;4.445833;4.520084;4.598542;4.666167 +random,262144,2097152,16,near,heap-full,0,32,4.416333,9,4.437667;4.416333;4.343000;4.427208;4.405584;4.448750;4.410709;4.395916;4.423042 +random,262144,2097152,1,none,heap-full,0,32,133.189250,9,132.078166;154.603666;138.514625;134.731917;133.189250;132.093292;133.728792;132.005875;130.611875 diff --git a/dev/perf/spf_queue/results/first/time-heap-sparse-b.csv b/dev/perf/spf_queue/results/first/time-heap-sparse-b.csv new file mode 100644 index 0000000..e0779bf --- /dev/null +++ b/dev/perf/spf_queue/results/first/time-heap-sparse-b.csv @@ -0,0 +1,20 @@ +case,n,e,queries,dst,variant,fallback,W,median_ms,samples,wall_samples_ms +random,1024,8192,1,none,heap-sparse,0,32,0.117333,9,0.130291;0.124250;0.121584;0.114292;0.117333;0.118042;0.116625;0.116834;0.112292 +random,4096,32768,256,none,heap-sparse,0,32,229.792625,9,229.388833;230.305875;231.628292;230.546042;229.461750;229.950458;228.498667;229.238584;229.792625 +random,16384,131072,64,none,heap-sparse,0,32,276.181541,9,279.428708;277.561000;276.181541;275.323584;278.222333;275.489833;274.415166;276.176833;276.760000 +random,65536,524288,1,none,heap-sparse,0,32,21.996833,9,21.128708;21.069625;20.960500;21.339375;22.240083;22.326084;24.122875;22.688334;21.996833 +random,4096,131072,64,none,heap-sparse,0,32,116.661125,9,117.081084;117.246125;117.409959;116.661125;115.278166;116.601917;115.869209;116.179458;116.846666 +clos,800,320000,64,none,heap-sparse,0,2,136.225542,9,135.596375;134.843917;137.157458;136.865917;138.362334;135.601875;136.225542;136.789542;134.530292 +grid,10000,39600,1,none,heap-sparse,0,2,0.707875,9,0.731333;0.707875;0.691917;0.692833;0.686791;0.682042;0.830041;0.820875;0.843250 +chain,2048,2047,1,none,heap-sparse,0,32,0.027833,9,0.027750;0.032125;0.027833;0.030542;0.028041;0.115791;0.024167;0.023709;0.024167 +uniform,16384,131072,64,none,heap-sparse,0,2,184.445750,9,183.342291;184.445750;184.596791;183.134708;183.946209;182.170375;184.866542;185.646792;186.874458 +random_masked,16384,131072,64,none,heap-sparse,0,32,251.644875,9,250.169625;249.810584;250.236708;252.644666;254.517125;258.871958;254.390125;251.196209;251.644875 +pseudo,802,320200,64,fixed,heap-sparse,0,2,136.496834,9,136.217500;136.784500;137.803792;136.429167;136.496834;135.609042;136.616375;135.702375;138.337834 +random,1024,8192,64,far,heap-sparse,0,32,11.728833,9,11.823709;11.680708;11.769959;11.700625;11.871875;11.755625;11.670667;11.596583;11.728833 +random,16384,131072,64,far,heap-sparse,0,32,276.217541,9,276.196792;276.217541;275.599250;276.902334;277.647209;276.274125;284.605208;275.271625;274.206834 +random,65536,524288,16,far,heap-sparse,0,32,331.986958,9,339.849750;338.197000;329.244917;331.144125;331.986958;329.266792;332.546125;342.616583;330.256208 +random,1024,8192,64,near,heap-sparse,0,32,0.040208,9,0.047250;0.040208;0.040750;0.037333;0.037959;0.040042;0.040209;0.040208;0.040208 +random,16384,131072,64,near,heap-sparse,0,32,0.385916,9,0.386458;0.395208;0.403959;0.385916;0.415292;0.360208;0.351250;0.381875;0.363916 +random,65536,524288,64,near,heap-sparse,0,32,1.486333,9,1.472916;1.488500;1.480625;1.486333;1.494833;1.479833;1.481375;1.495417;1.489333 +random,262144,2097152,16,near,heap-sparse,0,32,1.460417,9,1.436792;1.463291;1.460417;1.442041;1.469333;1.442625;1.458000;1.467083;1.467917 +random,262144,2097152,1,none,heap-sparse,0,32,137.015333,9,134.901125;140.954125;143.564417;137.015333;143.781125;143.934167;136.714000;134.648500;133.846833 diff --git a/dev/perf/spf_queue/results/first/time-ref-a1.csv b/dev/perf/spf_queue/results/first/time-ref-a1.csv new file mode 100644 index 0000000..0b656c2 --- /dev/null +++ b/dev/perf/spf_queue/results/first/time-ref-a1.csv @@ -0,0 +1,20 @@ +case,n,e,queries,dst,variant,fallback,W,median_ms,samples,wall_samples_ms +random,1024,8192,1,none,ref,0,32,0.100625,9,0.100084;0.100625;0.113375;0.094750;0.101875;0.115375;0.109708;0.095333;0.095792 +random,4096,32768,256,none,ref,0,32,198.718250,9,197.933375;197.190208;195.268000;199.687250;205.407833;198.453000;198.718250;199.052333;199.647459 +random,16384,131072,64,none,ref,0,32,238.755083,9,238.755083;235.413583;238.942375;237.525208;235.592584;239.616750;240.090875;240.277500;237.924625 +random,65536,524288,1,none,ref,0,32,18.375666,9,18.342500;18.308292;18.375666;18.354417;17.978417;18.898875;18.709833;21.097667;19.911959 +random,4096,131072,64,none,ref,0,32,106.741584,9,106.072083;106.741584;105.991084;107.077666;107.519958;106.421125;107.008459;107.891375;105.394958 +clos,800,320000,64,none,ref,0,2,142.105167,9,142.505333;142.222834;141.403875;142.105167;140.911792;141.648084;141.805625;142.577541;142.248125 +grid,10000,39600,1,none,ref,0,2,0.614125,9,0.629125;0.630625;0.621958;0.620959;0.614125;0.607250;0.606917;0.602959;0.603291 +chain,2048,2047,1,none,ref,0,32,0.020833,9,0.022250;0.026583;0.045542;0.021500;0.020833;0.020709;0.020750;0.020667;0.020750 +uniform,16384,131072,64,none,ref,0,2,170.249750,9,168.616459;168.656292;170.249750;170.986333;172.660916;172.197834;167.438625;171.170375;168.618917 +random_masked,16384,131072,64,none,ref,0,32,219.464666,9,216.439000;220.720375;219.626583;219.428917;221.002208;220.503125;216.853333;219.464666;219.259125 +pseudo,802,320200,64,fixed,ref,0,2,140.618958,9,140.512042;140.764125;141.042750;138.901291;140.618958;140.345292;139.922334;142.146583;142.305542 +random,1024,8192,64,far,ref,0,32,10.129084,9,10.252625;10.129084;10.263500;10.034291;9.965875;10.187417;9.917250;10.094625;10.151000 +random,16384,131072,64,far,ref,0,32,240.012083,9,239.525250;239.438250;241.082250;240.157208;242.569167;239.640250;240.012083;241.302292;238.371542 +random,65536,524288,16,far,ref,0,32,289.354125,9,292.384500;302.566458;289.184583;290.246875;288.628292;289.354125;285.801458;288.569916;289.974167 +random,1024,8192,64,near,ref,0,32,0.104666,9,0.104666;0.101875;0.102208;0.115333;0.102042;0.113416;0.112625;0.111500;0.099667 +random,16384,131072,64,near,ref,0,32,1.044334,9,0.998958;1.029041;1.039625;1.044334;1.030583;1.056791;1.046792;1.069291;1.064209 +random,65536,524288,64,near,ref,0,32,4.034208,9,3.985625;4.076125;3.991750;4.027791;4.034208;4.034833;4.035667;4.096250;4.005333 +random,262144,2097152,16,near,ref,0,32,3.871542,9,3.840209;3.836792;3.842625;3.912084;3.873375;3.898500;3.871542;3.867917;3.907875 +random,262144,2097152,1,none,ref,0,32,119.703333,9,121.781375;119.108459;118.500666;120.011333;119.737667;122.042291;119.297917;118.898958;119.703333 diff --git a/dev/perf/spf_queue/results/first/time-ref-a2.csv b/dev/perf/spf_queue/results/first/time-ref-a2.csv new file mode 100644 index 0000000..948912b --- /dev/null +++ b/dev/perf/spf_queue/results/first/time-ref-a2.csv @@ -0,0 +1,20 @@ +case,n,e,queries,dst,variant,fallback,W,median_ms,samples,wall_samples_ms +random,1024,8192,1,none,ref,0,32,0.104208,9,0.111125;0.100583;0.110625;0.105583;0.103792;0.100542;0.103708;0.106417;0.104208 +random,4096,32768,256,none,ref,0,32,205.803292,9,207.161417;204.300125;205.676917;205.803292;207.224167;205.854417;206.188916;204.471167;205.455292 +random,16384,131072,64,none,ref,0,32,245.574917,9,246.231958;250.732666;245.339292;245.376208;245.066250;245.574917;247.844667;245.871292;245.273291 +random,65536,524288,1,none,ref,0,32,19.633375,9,19.437083;18.434834;18.742708;19.423083;19.633375;20.104666;20.097833;20.449042;19.730208 +random,4096,131072,64,none,ref,0,32,109.030458,9,109.414000;108.868500;108.683666;109.278042;109.245667;109.650583;109.021959;109.030458;108.857542 +clos,800,320000,64,none,ref,0,2,143.648375,9,143.608167;143.648375;142.897167;141.598667;145.929375;145.318334;145.996750;142.662042;143.719000 +grid,10000,39600,1,none,ref,0,2,0.621917,9,0.638042;0.621250;0.621917;0.629333;0.611333;0.618750;0.617416;0.636459;0.634125 +chain,2048,2047,1,none,ref,0,32,0.020583,9,0.020625;0.020375;0.020542;0.020584;0.020708;0.020583;0.020583;0.020542;0.020584 +uniform,16384,131072,64,none,ref,0,2,175.401208,9,175.401208;174.853709;174.902833;176.983417;175.576708;175.084000;174.032000;177.454708;176.266458 +random_masked,16384,131072,64,none,ref,0,32,225.265708,9,224.450417;225.327166;224.965458;225.131000;224.263917;225.615750;226.301708;227.413958;225.265708 +pseudo,802,320200,64,fixed,ref,0,2,142.151958,9,143.465209;142.830625;142.089583;141.701500;142.102959;142.151958;143.083291;141.934459;142.653250 +random,1024,8192,64,far,ref,0,32,10.432500,9,10.424959;10.307958;10.458000;10.432500;10.516459;10.506750;10.504625;10.343583;10.309125 +random,16384,131072,64,far,ref,0,32,246.256583,9,245.007042;246.015000;246.830125;245.896333;245.123167;246.953958;247.596042;248.142625;246.256583 +random,65536,524288,16,far,ref,0,32,299.940042,9,302.783792;297.925292;312.234125;303.503083;300.796917;297.393250;299.940042;297.575833;299.894000 +random,1024,8192,64,near,ref,0,32,0.120042,9,0.133000;0.118916;0.120667;0.117375;0.129250;0.120042;0.120416;0.119792;0.118791 +random,16384,131072,64,near,ref,0,32,1.170917,9,1.152417;1.192917;1.163625;1.170917;1.172084;1.167875;1.174625;1.188250;1.153333 +random,65536,524288,64,near,ref,0,32,4.207375,9,4.285375;4.206917;4.205583;4.207375;4.201167;4.213958;4.213542;4.165792;4.244750 +random,262144,2097152,16,near,ref,0,32,3.996708,9,3.968250;4.090666;3.967375;4.077625;3.996375;3.976584;3.996708;4.000083;4.050416 +random,262144,2097152,1,none,ref,0,32,125.213500,9,129.476167;123.631583;125.867208;125.910000;125.753333;125.213500;125.165250;124.951542;121.767417 diff --git a/dev/perf/spf_queue/results/netgraph/a1-old.csv b/dev/perf/spf_queue/results/netgraph/a1-old.csv new file mode 100644 index 0000000..ca2a577 --- /dev/null +++ b/dev/perf/spf_queue/results/netgraph/a1-old.csv @@ -0,0 +1,17 @@ +workload,label,median_s,samples,checksum,samples_s +spf_full_clos_200x200,a1-old,0.214242,5,946e7cf8b5a36980,0.215061;0.216031;0.213735;0.214242;0.212930 +spf_full_grid_100x100_weighted,a1-old,0.220778,5,4c2f7751ff9a5057,0.220560;0.220778;0.220257;0.221003;0.221978 +maxflow_clos_200x200_combine,a1-old,0.052564,5,2576c34f1fd9b85e,0.053311;0.053040;0.052564;0.052143;0.051846 +maxflow_failures_clos_100x100_x100,a1-old,0.044261,5,26dc7541b17fd051,0.044064;0.044782;0.044379;0.043525;0.044261 +maxflow_grid_100x100_weighted_combine,a1-old,0.202941,5,b0453b641647871b,0.202895;0.206061;0.205235;0.202941;0.202883 +maxflow_grid_100x100_weighted_pairwise,a1-old,0.203949,5,4fc2486a01221d75,0.205356;0.205253;0.172211;0.203949;0.200981 +placement_backbone_clos,a1-old,0.069218,5,a3bbef71a61656e1,0.069218;0.067452;0.067574;0.070175;0.071420 +placement_mc_backbone_clos_x300,a1-old,0.074473,5,13b9a5f311b911a9,0.077150;0.074793;0.073446;0.074473;0.073984 +maxflow_mc_backbone_clos_x300,a1-old,0.029282,5,ac971ec1b53a4b0a,0.029265;0.029166;0.029931;0.029314;0.029282 +ksp_clos3_pairwise_k8,a1-old,0.054646,5,9bf30f2f50792fe9,0.053493;0.053920;0.056333;0.054646;0.056298 +maxflow_clos3_pod_pairs_combine,a1-old,0.167483,5,2e23a5712f361ff7,0.167694;0.167483;0.197351;0.162379;0.163569 +placement_clos3_wcmp_and_ecmp,a1-old,0.366377,5,14d7ba5534c9ce95,0.370620;0.366377;0.372593;0.365110;0.333473 +placement_clos3_failures_x20,a1-old,7.646194,5,eafa50e144281360,7.614464;7.688954;7.711631;7.610305;7.646194 +scenario_square_mesh_iter100,a1-old,0.010309,5,5046cbe45e195f6e,0.009954;0.010309;0.010277;0.010874;0.010464 +scenario_nsfnet_iter200,a1-old,0.958151,5,d966e67ffac4393c,0.965309;0.958151;0.947347;0.993366;0.944487 +scenario_backbone_clos_iter100,a1-old,0.082340,5,e904ac0839c6cac1,0.082945;0.084257;0.082340;0.081514;0.082249 diff --git a/dev/perf/spf_queue/results/netgraph/a2-old.csv b/dev/perf/spf_queue/results/netgraph/a2-old.csv new file mode 100644 index 0000000..08b21fd --- /dev/null +++ b/dev/perf/spf_queue/results/netgraph/a2-old.csv @@ -0,0 +1,17 @@ +workload,label,median_s,samples,checksum,samples_s +spf_full_clos_200x200,a2-old,0.212650,5,946e7cf8b5a36980,0.213604;0.213158;0.212128;0.212650;0.211883 +spf_full_grid_100x100_weighted,a2-old,0.220314,5,4c2f7751ff9a5057,0.219253;0.221249;0.220314;0.222180;0.219875 +maxflow_clos_200x200_combine,a2-old,0.051853,5,2576c34f1fd9b85e,0.052104;0.051853;0.052154;0.051545;0.051553 +maxflow_failures_clos_100x100_x100,a2-old,0.043021,5,26dc7541b17fd051,0.043132;0.043212;0.042954;0.042811;0.043021 +maxflow_grid_100x100_weighted_combine,a2-old,0.202080,5,b0453b641647871b,0.203003;0.202080;0.202227;0.202046;0.201641 +maxflow_grid_100x100_weighted_pairwise,a2-old,0.200578,5,4fc2486a01221d75,0.202322;0.200159;0.177585;0.204723;0.200578 +placement_backbone_clos,a2-old,0.067439,5,a3bbef71a61656e1,0.067937;0.067139;0.067662;0.067130;0.067439 +placement_mc_backbone_clos_x300,a2-old,0.075278,5,13b9a5f311b911a9,0.075415;0.074549;0.074713;0.075430;0.075278 +maxflow_mc_backbone_clos_x300,a2-old,0.029137,5,ac971ec1b53a4b0a,0.029212;0.029137;0.029388;0.029131;0.029046 +ksp_clos3_pairwise_k8,a2-old,0.053399,5,9bf30f2f50792fe9,0.053732;0.053322;0.054482;0.053399;0.053396 +maxflow_clos3_pod_pairs_combine,a2-old,0.166107,5,2e23a5712f361ff7,0.161893;0.166107;0.198977;0.167306;0.163009 +placement_clos3_wcmp_and_ecmp,a2-old,0.363318,5,14d7ba5534c9ce95,0.362654;0.363394;0.363318;0.363318;0.330417 +placement_clos3_failures_x20,a2-old,7.547826,5,eafa50e144281360,7.463701;7.512790;7.602702;7.609344;7.547826 +scenario_square_mesh_iter100,a2-old,0.010336,5,5046cbe45e195f6e,0.009918;0.010012;0.010376;0.010627;0.010336 +scenario_nsfnet_iter200,a2-old,0.939100,5,d966e67ffac4393c,0.945634;0.934857;0.927139;0.974911;0.939100 +scenario_backbone_clos_iter100,a2-old,0.081112,5,e904ac0839c6cac1,0.082197;0.081385;0.081112;0.080830;0.080991 diff --git a/dev/perf/spf_queue/results/netgraph/b-new-heap.csv b/dev/perf/spf_queue/results/netgraph/b-new-heap.csv new file mode 100644 index 0000000..7345cd3 --- /dev/null +++ b/dev/perf/spf_queue/results/netgraph/b-new-heap.csv @@ -0,0 +1,17 @@ +workload,label,median_s,samples,checksum,samples_s +spf_full_clos_200x200,b-new-heap,0.164632,5,946e7cf8b5a36980,0.171094;0.163302;0.164001;0.164632;0.165386 +spf_full_grid_100x100_weighted,b-new-heap,0.245422,5,4c2f7751ff9a5057,0.245311;0.244615;0.246294;0.245422;0.247913 +maxflow_clos_200x200_combine,b-new-heap,0.046796,5,2576c34f1fd9b85e,0.046604;0.046809;0.046796;0.046520;0.047011 +maxflow_failures_clos_100x100_x100,b-new-heap,0.039282,5,26dc7541b17fd051,0.039282;0.040234;0.038893;0.039675;0.038654 +maxflow_grid_100x100_weighted_combine,b-new-heap,0.219054,5,b0453b641647871b,0.217967;0.219054;0.218718;0.224953;0.221065 +maxflow_grid_100x100_weighted_pairwise,b-new-heap,0.212886,5,4fc2486a01221d75,0.212886;0.220461;0.186507;0.211249;0.216741 +placement_backbone_clos,b-new-heap,0.068715,5,a3bbef71a61656e1,0.068128;0.067605;0.072257;0.071829;0.068715 +placement_mc_backbone_clos_x300,b-new-heap,0.071399,5,13b9a5f311b911a9,0.072645;0.071349;0.071399;0.071738;0.070936 +maxflow_mc_backbone_clos_x300,b-new-heap,0.029019,5,ac971ec1b53a4b0a,0.029019;0.028594;0.028178;0.029278;0.031190 +ksp_clos3_pairwise_k8,b-new-heap,0.046233,5,9bf30f2f50792fe9,0.046716;0.046282;0.046233;0.045945;0.045440 +maxflow_clos3_pod_pairs_combine,b-new-heap,0.171827,5,2e23a5712f361ff7,0.171827;0.174949;0.201334;0.167000;0.164015 +placement_clos3_wcmp_and_ecmp,b-new-heap,0.368871,5,14d7ba5534c9ce95,0.368871;0.363981;0.374026;0.375693;0.334427 +placement_clos3_failures_x20,b-new-heap,7.570639,5,eafa50e144281360,7.638405;7.570639;7.578404;7.479565;7.433718 +scenario_square_mesh_iter100,b-new-heap,0.009861,5,5046cbe45e195f6e,0.009619;0.009698;0.009861;0.009916;0.009878 +scenario_nsfnet_iter200,b-new-heap,0.912169,5,d966e67ffac4393c,0.918451;0.912169;0.909963;0.962305;0.906028 +scenario_backbone_clos_iter100,b-new-heap,0.077625,5,e904ac0839c6cac1,0.077511;0.077981;0.077051;0.078228;0.077625 diff --git a/dev/perf/spf_queue/results/netgraph/b-new.csv b/dev/perf/spf_queue/results/netgraph/b-new.csv new file mode 100644 index 0000000..335acf4 --- /dev/null +++ b/dev/perf/spf_queue/results/netgraph/b-new.csv @@ -0,0 +1,17 @@ +workload,label,median_s,samples,checksum,samples_s +spf_full_clos_200x200,b-new,0.163387,5,946e7cf8b5a36980,0.163696;0.163391;0.163122;0.163197;0.163387 +spf_full_grid_100x100_weighted,b-new,0.181652,5,4c2f7751ff9a5057,0.181652;0.182234;0.180117;0.180609;0.181705 +maxflow_clos_200x200_combine,b-new,0.047118,5,2576c34f1fd9b85e,0.047558;0.046946;0.047023;0.047830;0.047118 +maxflow_failures_clos_100x100_x100,b-new,0.040410,5,26dc7541b17fd051,0.040004;0.040410;0.040879;0.040360;0.040449 +maxflow_grid_100x100_weighted_combine,b-new,0.174551,5,b0453b641647871b,0.177566;0.174597;0.174551;0.170893;0.173684 +maxflow_grid_100x100_weighted_pairwise,b-new,0.208183,5,4fc2486a01221d75,0.211970;0.206165;0.176239;0.208183;0.208189 +placement_backbone_clos,b-new,0.069022,5,a3bbef71a61656e1,0.069022;0.069117;0.067956;0.067765;0.072885 +placement_mc_backbone_clos_x300,b-new,0.067803,5,13b9a5f311b911a9,0.069155;0.067885;0.067111;0.066996;0.067803 +maxflow_mc_backbone_clos_x300,b-new,0.027553,5,ac971ec1b53a4b0a,0.028108;0.027674;0.027451;0.027553;0.027179 +ksp_clos3_pairwise_k8,b-new,0.046303,5,9bf30f2f50792fe9,0.046303;0.045928;0.047188;0.046233;0.046584 +maxflow_clos3_pod_pairs_combine,b-new,0.168243,5,2e23a5712f361ff7,0.167244;0.168132;0.199066;0.168243;0.172598 +placement_clos3_wcmp_and_ecmp,b-new,0.376317,5,14d7ba5534c9ce95,0.378218;0.372257;0.377731;0.376317;0.338946 +placement_clos3_failures_x20,b-new,7.639934,5,eafa50e144281360,7.639045;7.660284;7.732032;7.616304;7.639934 +scenario_square_mesh_iter100,b-new,0.009892,5,5046cbe45e195f6e,0.009892;0.009624;0.009909;0.009814;0.010528 +scenario_nsfnet_iter200,b-new,0.929637,5,d966e67ffac4393c,0.939539;0.929637;0.925644;0.978736;0.926841 +scenario_backbone_clos_iter100,b-new,0.078271,5,e904ac0839c6cac1,0.078327;0.078636;0.078104;0.077679;0.078271 diff --git a/dev/perf/spf_queue/results/netgraph/environment.txt b/dev/perf/spf_queue/results/netgraph/environment.txt new file mode 100644 index 0000000..014b006 --- /dev/null +++ b/dev/perf/spf_queue/results/netgraph/environment.txt @@ -0,0 +1,8 @@ +date: 2026-10-02T01:56:58Z +new: fbab119e794c843838f4f3f96d75cb7f32f06845 (dirty: 14 paths) +old: fbab119e794c843838f4f3f96d75cb7f32f06845 +netgraph: 775530768eec3951b7aec738f7e99d1abb6b7efc +dd3b394c0ba16f7ed0e0e403188f4fcc38dbd9ce2cf594368d2b2a8a19a105a0 dev/perf/spf_queue/bench_netgraph.py +9d684e1280714cd8d4b275c418b34cf936e0b340243612bfab40913bbe60610c /Users/networmix/ws/NetGraph-Core/venv/lib/python3.14/site-packages/_netgraph_core.cpython-314-darwin.so +91dc3b7e2bd3611d54d762e0fb1f875881138d66843866990f019cddfec5cc2c /Users/networmix/ws/NetGraph-Core-main/venv/lib/python3.14/site-packages/_netgraph_core.cpython-314-darwin.so +Apple M4 Max diff --git a/dev/perf/spf_queue/results/netgraph/hashseed-determinism.txt b/dev/perf/spf_queue/results/netgraph/hashseed-determinism.txt new file mode 100644 index 0000000..2f2a1e1 --- /dev/null +++ b/dev/perf/spf_queue/results/netgraph/hashseed-determinism.txt @@ -0,0 +1,9 @@ +new maxflow_mc_backbone_clos_x300 ac971ec1b53a4b0a +old1 maxflow_mc_backbone_clos_x300 ac971ec1b53a4b0a +old2 maxflow_mc_backbone_clos_x300 ac971ec1b53a4b0a +new placement_mc_backbone_clos_x300 13b9a5f311b911a9 +old1 placement_mc_backbone_clos_x300 13b9a5f311b911a9 +old2 placement_mc_backbone_clos_x300 13b9a5f311b911a9 +new scenario_backbone_clos_iter100 e904ac0839c6cac1 +old1 scenario_backbone_clos_iter100 e904ac0839c6cac1 +old2 scenario_backbone_clos_iter100 e904ac0839c6cac1 diff --git a/dev/perf/spf_queue/results/netgraph/load.txt b/dev/perf/spf_queue/results/netgraph/load.txt new file mode 100644 index 0000000..8adfc14 --- /dev/null +++ b/dev/perf/spf_queue/results/netgraph/load.txt @@ -0,0 +1,5 @@ + 2:56 up 52 days, 7:32, 3 users, load averages: 3.81 4.06 3.70 + 2:58 up 52 days, 7:33, 3 users, load averages: 5.32 4.48 3.88 + 2:59 up 52 days, 7:34, 3 users, load averages: 4.18 4.30 3.85 + 3:00 up 52 days, 7:35, 3 users, load averages: 4.64 4.42 3.93 + 3:01 up 52 days, 7:36, 3 users, load averages: 3.82 4.20 3.87 diff --git a/dev/perf/spf_queue/results/short/environment.txt b/dev/perf/spf_queue/results/short/environment.txt new file mode 100644 index 0000000..65f8240 --- /dev/null +++ b/dev/perf/spf_queue/results/short/environment.txt @@ -0,0 +1,3 @@ +date: 2026-09-27T13:41:37Z +30748a1034498f6a2bd05645f72b60750f3ef366c81476fd3f87bbac93c1a381 dev/perf/spf_queue/spf_variants.hpp +cecf8edfd17c19624890ba8c6bc2fa647d7841c25baaebeaaa175712ceebf688 dev/perf/spf_queue/harness.cpp diff --git a/dev/perf/spf_queue/results/short/load.txt b/dev/perf/spf_queue/results/short/load.txt new file mode 100644 index 0000000..0abff49 --- /dev/null +++ b/dev/perf/spf_queue/results/short/load.txt @@ -0,0 +1,8 @@ +14:41 up 47 days, 19:17, 3 users, load averages: 3.46 3.26 3.16 +14:41 up 47 days, 19:17, 3 users, load averages: 3.34 3.23 3.15 +14:41 up 47 days, 19:17, 3 users, load averages: 3.23 3.21 3.14 +14:41 up 47 days, 19:17, 3 users, load averages: 3.06 3.18 3.13 +14:42 up 47 days, 19:17, 3 users, load averages: 2.89 3.14 3.12 +14:42 up 47 days, 19:17, 3 users, load averages: 2.82 3.12 3.11 +14:42 up 47 days, 19:17, 3 users, load averages: 2.93 3.13 3.11 +14:42 up 47 days, 19:18, 3 users, load averages: 3.18 3.18 3.13 diff --git a/dev/perf/spf_queue/results/short/sweep-bucket2-sparse.csv b/dev/perf/spf_queue/results/short/sweep-bucket2-sparse.csv new file mode 100644 index 0000000..04079ec --- /dev/null +++ b/dev/perf/spf_queue/results/short/sweep-bucket2-sparse.csv @@ -0,0 +1,7 @@ +case,n,e,queries,dst,variant,fallback,W,median_ms,samples,wall_samples_ms +wide1,16384,131072,16,none,bucket2-sparse,0,2,37.299375,9,37.058584;37.299375;37.285416;37.232875;37.307000;36.957291;39.781167;38.166292;37.387791 +wide31,16384,131072,16,none,bucket2-sparse,0,32,36.781667,9,36.781667;36.675875;36.531209;36.388875;37.259583;36.938000;36.847333;36.702833;36.799709 +wide1023,16384,131072,16,none,bucket2-sparse,0,1024,34.703667,9,34.732500;34.721584;34.703667;34.777416;34.599666;34.279333;34.665333;34.923625;34.495458 +wide32767,16384,131072,16,none,bucket2-sparse,0,32768,35.819209,9,36.423291;36.809583;35.480750;35.858125;35.819209;35.829750;35.007125;35.601084;35.079583 +wide1048575,16384,131072,16,none,bucket2-sparse,0,1048570,47.752208,9,47.993250;46.520667;47.752208;46.565125;48.841959;47.888041;46.563958;47.450625;48.453833 +wide33554431,16384,131072,16,none,bucket2-sparse,1,33554196,56.532583,9,56.001958;56.304709;57.229250;55.514583;56.225541;56.869458;56.854875;58.679041;56.532583 diff --git a/dev/perf/spf_queue/results/short/time-bucket-hybrid-b.csv b/dev/perf/spf_queue/results/short/time-bucket-hybrid-b.csv new file mode 100644 index 0000000..3840549 --- /dev/null +++ b/dev/perf/spf_queue/results/short/time-bucket-hybrid-b.csv @@ -0,0 +1,9 @@ +case,n,e,queries,dst,variant,fallback,W,median_ms,samples,wall_samples_ms +random,16384,131072,64,none,bucket-hybrid,0,32,142.547666,9,141.814042;142.235333;142.547666;145.159000;142.753125;142.732000;141.346416;141.522875;143.547708 +random,65536,524288,1,none,bucket-hybrid,0,32,10.798875,9,10.798875;10.912625;10.936292;10.787250;10.552875;10.718083;10.778958;11.122250;10.962833 +clos,800,320000,64,none,bucket-hybrid,0,2,142.141958,9,142.959250;140.614458;141.870500;145.317042;141.619250;142.141958;142.838250;141.910292;143.447083 +chain,2048,2047,1,none,bucket-hybrid,0,32,0.040834,9,0.040834;0.041125;0.040458;0.040583;0.040750;0.040875;0.040958;0.041167;0.040792 +random,16384,131072,64,near,bucket-hybrid,0,32,0.389791,9,0.389542;0.412500;0.387250;0.390875;0.394083;0.387292;0.386500;0.389791;0.392209 +random,65536,524288,64,near,bucket-hybrid,0,32,1.484459,9,1.484459;1.473000;1.474459;1.487292;1.477583;1.475709;1.498208;1.484625;1.489750 +random,262144,2097152,16,near,bucket-hybrid,0,32,1.442292,9,1.459500;1.451458;1.432125;1.436708;1.440500;1.442292;1.450166;1.442209;1.446667 +random,262144,2097152,1,none,bucket-hybrid,0,32,84.464083,9,85.850916;89.099833;91.374917;84.464083;85.462917;82.968792;82.194042;83.954375;82.687375 diff --git a/dev/perf/spf_queue/results/short/time-bucket-sparse-b.csv b/dev/perf/spf_queue/results/short/time-bucket-sparse-b.csv new file mode 100644 index 0000000..9af8e2a --- /dev/null +++ b/dev/perf/spf_queue/results/short/time-bucket-sparse-b.csv @@ -0,0 +1,9 @@ +case,n,e,queries,dst,variant,fallback,W,median_ms,samples,wall_samples_ms +random,16384,131072,64,none,bucket-sparse,0,32,146.151375,9,145.365875;146.581375;147.046709;145.907750;145.879916;147.234791;146.151375;147.714292;145.136625 +random,65536,524288,1,none,bucket-sparse,0,32,10.988416,9,11.044125;10.804042;10.830375;10.933083;11.017500;10.988416;11.095125;10.766667;11.091958 +clos,800,320000,64,none,bucket-sparse,0,2,141.707584,9,141.602916;142.928875;141.394458;141.996958;144.307250;141.192500;141.707584;141.517500;141.947458 +chain,2048,2047,1,none,bucket-sparse,0,32,0.041792,9,0.037042;0.038417;0.041917;0.041792;0.041625;0.041625;0.041792;0.042292;0.046542 +random,16384,131072,64,near,bucket-sparse,0,32,0.386666,9,0.386666;0.385417;0.392792;0.381959;0.383250;0.387625;0.390833;0.383792;0.392417 +random,65536,524288,64,near,bucket-sparse,0,32,1.439458,9,1.416958;1.482792;1.507250;1.425667;1.424709;1.541000;1.429417;1.439458;1.523084 +random,262144,2097152,16,near,bucket-sparse,0,32,1.455000,9,1.455000;1.447125;1.366958;1.453084;1.511791;1.458042;1.451667;1.496875;1.467875 +random,262144,2097152,1,none,bucket-sparse,0,32,92.620833,9,93.362750;91.775833;96.660417;93.237000;98.978917;92.009125;92.620833;89.293292;88.834333 diff --git a/dev/perf/spf_queue/results/short/time-bucket2-fresh-b.csv b/dev/perf/spf_queue/results/short/time-bucket2-fresh-b.csv new file mode 100644 index 0000000..e68bded --- /dev/null +++ b/dev/perf/spf_queue/results/short/time-bucket2-fresh-b.csv @@ -0,0 +1,9 @@ +case,n,e,queries,dst,variant,fallback,W,median_ms,samples,wall_samples_ms +random,16384,131072,64,none,bucket2-fresh,0,32,142.163000,9,140.967209;141.247417;142.163000;141.064542;144.924083;142.519750;142.667958;144.079083;141.456417 +random,65536,524288,1,none,bucket2-fresh,0,32,10.603833,9,10.704708;10.602166;10.760750;10.537584;10.620416;10.371667;10.603833;10.354041;10.773959 +clos,800,320000,64,none,bucket2-fresh,0,2,141.902750,9,141.549417;141.541042;144.366500;141.535417;142.107375;141.902167;143.362708;142.260042;141.902750 +chain,2048,2047,1,none,bucket2-fresh,0,32,0.035542,9,0.035083;0.035542;0.035458;0.035625;0.046708;0.035375;0.035708;0.035375;0.035834 +random,16384,131072,64,near,bucket2-fresh,0,32,1.336000,9,1.396750;1.399000;1.436458;1.324125;1.275750;1.291083;1.333292;1.336000;1.380375 +random,65536,524288,64,near,bucket2-fresh,0,32,5.261459,9,5.480084;4.884666;5.216500;5.141875;5.405084;5.249708;5.399750;5.261459;5.417583 +random,262144,2097152,16,near,bucket2-fresh,0,32,5.230458,9,5.177375;5.003542;5.108792;7.128292;5.230458;5.224084;5.279209;5.274916;5.299583 +random,262144,2097152,1,none,bucket2-fresh,0,32,86.550500,9,86.550500;86.679625;84.645666;85.720708;83.300834;85.359417;91.528000;91.843500;89.670625 diff --git a/dev/perf/spf_queue/results/short/time-bucket2-hybrid-b.csv b/dev/perf/spf_queue/results/short/time-bucket2-hybrid-b.csv new file mode 100644 index 0000000..9108b2c --- /dev/null +++ b/dev/perf/spf_queue/results/short/time-bucket2-hybrid-b.csv @@ -0,0 +1,9 @@ +case,n,e,queries,dst,variant,fallback,W,median_ms,samples,wall_samples_ms +random,16384,131072,64,none,bucket2-hybrid,0,32,146.908458,9,149.103333;146.908458;153.407334;151.466584;148.761833;142.588416;143.540292;144.859666;144.793083 +random,65536,524288,1,none,bucket2-hybrid,0,32,11.742542,9,11.742542;12.280833;12.336916;12.553708;11.515250;11.836375;11.498792;11.367084;11.614458 +clos,800,320000,64,none,bucket2-hybrid,0,2,144.050750,9,144.281250;143.780042;142.801334;144.050750;143.585833;145.442250;145.965375;144.048125;146.001791 +chain,2048,2047,1,none,bucket2-hybrid,0,32,0.038334,9,0.038542;0.038042;0.038458;0.038334;0.038291;0.038416;0.038292;0.038291;0.038500 +random,16384,131072,64,near,bucket2-hybrid,0,32,0.393166,9,0.394125;0.401459;0.403000;0.392291;0.392875;0.398375;0.392250;0.393166;0.392334 +random,65536,524288,64,near,bucket2-hybrid,0,32,1.498541,9,1.497833;1.510291;1.492042;1.498541;1.516292;1.486791;1.499625;1.487583;1.511375 +random,262144,2097152,16,near,bucket2-hybrid,0,32,1.411375,9,1.340875;1.415917;1.435625;1.349125;1.366625;1.403875;1.422208;1.411375;1.436292 +random,262144,2097152,1,none,bucket2-hybrid,0,32,84.643541,9,83.597292;84.989084;83.386458;85.441959;83.921208;83.676792;84.643541;86.611042;85.450250 diff --git a/dev/perf/spf_queue/results/short/time-bucket2-sparse-b.csv b/dev/perf/spf_queue/results/short/time-bucket2-sparse-b.csv new file mode 100644 index 0000000..705d100 --- /dev/null +++ b/dev/perf/spf_queue/results/short/time-bucket2-sparse-b.csv @@ -0,0 +1,9 @@ +case,n,e,queries,dst,variant,fallback,W,median_ms,samples,wall_samples_ms +random,16384,131072,64,none,bucket2-sparse,0,32,147.686917,9,147.830750;147.531417;147.372209;147.061958;149.109292;149.496875;147.970583;146.964417;147.686917 +random,65536,524288,1,none,bucket2-sparse,0,32,11.416459,9,11.431292;11.416459;11.210667;11.834542;11.816958;11.380167;11.199083;11.488292;11.214833 +clos,800,320000,64,none,bucket2-sparse,0,2,143.678625,9,144.810291;143.678625;142.837750;142.298541;142.889500;143.704667;143.648000;145.034541;146.672667 +chain,2048,2047,1,none,bucket2-sparse,0,32,0.040916,9,0.037208;0.039334;0.040833;0.040916;0.041000;0.041041;0.041042;0.041083;0.039667 +random,16384,131072,64,near,bucket2-sparse,0,32,0.398333,9,0.403250;0.411209;0.398333;0.395750;0.391458;0.455709;0.478792;0.378000;0.378500 +random,65536,524288,64,near,bucket2-sparse,0,32,1.500166,9,1.500166;1.477167;1.504708;1.495167;1.497542;1.516500;1.489167;1.687291;1.531375 +random,262144,2097152,16,near,bucket2-sparse,0,32,1.450625,9,1.381625;1.413875;1.471417;1.457458;1.450625;1.440000;1.462625;1.466166;1.447083 +random,262144,2097152,1,none,bucket2-sparse,0,32,95.974167,9,100.352250;98.287042;95.974167;94.826000;92.828416;95.038750;93.860083;98.846875;96.269292 diff --git a/dev/perf/spf_queue/results/short/time-heap-hybrid-b.csv b/dev/perf/spf_queue/results/short/time-heap-hybrid-b.csv new file mode 100644 index 0000000..b745303 --- /dev/null +++ b/dev/perf/spf_queue/results/short/time-heap-hybrid-b.csv @@ -0,0 +1,9 @@ +case,n,e,queries,dst,variant,fallback,W,median_ms,samples,wall_samples_ms +random,16384,131072,64,none,heap-hybrid,0,32,273.173042,9,273.535959;273.173042;272.987500;274.413708;272.240708;272.831625;272.374041;273.861250;275.296667 +random,65536,524288,1,none,heap-hybrid,0,32,20.333792,9,20.587500;20.226958;20.591334;20.201833;20.277375;19.883125;20.333792;20.459667;20.590542 +clos,800,320000,64,none,heap-hybrid,0,2,135.961625,9,135.924375;135.899834;138.616000;135.521958;136.078250;136.760792;136.773459;135.961625;135.061542 +chain,2048,2047,1,none,heap-hybrid,0,32,0.024500,9,0.022000;0.023083;0.024500;0.024750;0.025042;0.024750;0.024375;0.024541;0.024500 +random,16384,131072,64,near,heap-hybrid,0,32,0.390458,9,0.387792;0.389541;0.390458;0.390459;0.386875;0.391084;0.392083;0.408167;0.388917 +random,65536,524288,64,near,heap-hybrid,0,32,1.481000,9,1.497167;1.481000;1.481041;1.492750;1.483334;1.396500;1.409125;1.445125;1.464084 +random,262144,2097152,16,near,heap-hybrid,0,32,1.456709,9,1.430542;1.456709;1.462583;1.456834;1.475000;1.445459;1.443833;1.464333;1.447459 +random,262144,2097152,1,none,heap-hybrid,0,32,131.476542,9,131.909875;131.235750;129.497458;131.023292;131.906417;132.037875;132.782167;130.478583;131.476542 diff --git a/dev/perf/spf_queue/results/short/time-ref-a1.csv b/dev/perf/spf_queue/results/short/time-ref-a1.csv new file mode 100644 index 0000000..4a3fb44 --- /dev/null +++ b/dev/perf/spf_queue/results/short/time-ref-a1.csv @@ -0,0 +1,9 @@ +case,n,e,queries,dst,variant,fallback,W,median_ms,samples,wall_samples_ms +random,16384,131072,64,none,ref,0,32,240.574042,9,239.941250;243.446250;243.989666;240.574042;239.140083;241.751209;239.183292;241.564583;239.675084 +random,65536,524288,1,none,ref,0,32,18.512292,9,18.477250;18.512292;18.502583;18.579334;18.885459;18.153333;18.186375;18.595458;18.531083 +clos,800,320000,64,none,ref,0,2,137.762333,9,137.476083;137.589542;141.538542;139.405833;137.762333;136.658917;138.521917;138.898375;137.596916 +chain,2048,2047,1,none,ref,0,32,0.020583,9,0.020583;0.023083;0.019750;0.018500;0.018500;0.020166;0.020708;0.020667;0.020875 +random,16384,131072,64,near,ref,0,32,1.046583,9,1.099292;1.076792;1.031625;1.002583;1.015500;1.046583;1.051792;1.043291;1.053416 +random,65536,524288,64,near,ref,0,32,4.206375,9,4.206375;4.798000;5.190875;4.624958;4.175583;4.034417;4.407375;4.000666;4.178959 +random,262144,2097152,16,near,ref,0,32,3.913459,9,3.901625;3.917291;3.924083;3.913459;3.900458;3.938041;3.915958;3.895375;3.909083 +random,262144,2097152,1,none,ref,0,32,119.533542,9,120.662833;117.989875;119.298416;120.215542;117.608500;119.533542;119.545958;118.972500;129.493667 diff --git a/dev/perf/spf_queue/results/short/time-ref-a2.csv b/dev/perf/spf_queue/results/short/time-ref-a2.csv new file mode 100644 index 0000000..1c7b4be --- /dev/null +++ b/dev/perf/spf_queue/results/short/time-ref-a2.csv @@ -0,0 +1,9 @@ +case,n,e,queries,dst,variant,fallback,W,median_ms,samples,wall_samples_ms +random,16384,131072,64,none,ref,0,32,245.430000,9,248.316125;247.171583;244.164041;245.430000;244.551542;243.334791;244.229459;247.001041;245.512083 +random,65536,524288,1,none,ref,0,32,18.767000,9,18.134292;18.544916;18.387041;18.409583;18.924417;18.847500;18.767000;18.922875;18.988125 +clos,800,320000,64,none,ref,0,2,141.644542,9,141.412958;141.113542;141.644542;140.970292;142.218375;143.736166;140.296792;143.137291;142.293208 +chain,2048,2047,1,none,ref,0,32,0.023334,9,0.020709;0.022041;0.021000;0.023375;0.023334;0.024250;0.024042;0.023875;0.023333 +random,16384,131072,64,near,ref,0,32,1.104167,9,1.087125;1.084917;1.086542;1.119541;1.148958;1.118583;1.104167;1.099708;1.144750 +random,65536,524288,64,near,ref,0,32,4.305042,9,4.331750;4.193667;4.377625;4.208583;4.354542;4.137708;4.409417;4.166125;4.305042 +random,262144,2097152,16,near,ref,0,32,19.192541,9,19.290125;19.192541;19.075667;18.905375;19.081709;19.091959;19.239083;19.242709;19.201542 +random,262144,2097152,1,none,ref,0,32,124.229000,9,122.850416;129.890541;123.901291;123.352166;131.279125;139.409250;136.247250;124.229000;122.618125 diff --git a/dev/perf/spf_queue/review-2026-10/BRIEF.md b/dev/perf/spf_queue/review-2026-10/BRIEF.md new file mode 100644 index 0000000..6c200b5 --- /dev/null +++ b/dev/perf/spf_queue/review-2026-10/BRIEF.md @@ -0,0 +1,79 @@ +# Critical review brief: SPF optimisation in NetGraph-Core + +You are an independent, sceptical performance reviewer. Repository root is the +current directory (NetGraph-Core, C++20 core + pybind11). The working tree has +an UNCOMMITTED change on top of commit `fbab119` that replaces the Dijkstra +frontier in `src/shortest_paths.cpp` with a monotone bucket queue (active bucket +kept as a heap on `(-bottleneck, node)` so pop order is identical to the old +binary heap), plus a thread-local scratch workspace with touched-node tracking +and a hybrid reset. Read, in this order: + +1. `dev/perf/spf_queue/PLAN.md` (the plan: decision, + experiment, implementation status, old/new/old measurements, trade-offs). +2. `dev/perf/spf_queue/review-2026-10/change.diff` + (the exact production + test diff) and the live files `src/shortest_paths.cpp`, + `src/strict_multidigraph.cpp`, `include/netgraph/core/shortest_paths.hpp`. +3. `dev/perf/spf_queue/README.md` and the harness + `spf_variants.hpp` / `harness.cpp` (plain C++; `bash dev/perf/spf_queue/build.sh` + builds `build/perf/cpu-queue`; `build/perf/cpu-queue-old` + is the same harness built from the previous sources; `time ref 7`, + `short ref 7`, `sweep ref 7 2097152`, `correctness` are the modes). +4. Callers: `src/max_flow.cpp`, `src/flow_state.cpp` (place_max_flow), + `src/flow_policy.cpp` (get_path_bundle, memo), `src/k_shortest_paths.cpp` + (its own `dijkstra_single` and spur searches), `src/cpu_backend.cpp`. +5. Context memos: `dev/research/metal_pathfinding/optimization/README.md` (GPU research) + and the measured dead ends listed in CPU_PLAN.md ("do not retry"). + +## Your task + +Think hard and answer: **were all easily achievable and reasonable +optimisations considered and verified?** Specifically: + +- Cheap wins inside the new code that were missed: the bucket queue (bucket + advance, bitmap, per-pop overhead, item layout, the chain-graph regression, + width limit), the heap route (the recorded 5–9% fallback regression and its + real cause), the workspace (reset policy, output materialisation, the O(N) + output floor), predecessor-list construction and the PredDAG conversion, + early-exit handling, the reverse search, the cost/gcd metadata. +- Cheap wins around the search that were not touched: how max-flow, + place_max_flow and FlowPolicy call SPF (repeated full searches, residual + recomputation, memoisation, early termination), KSP's private + `dijkstra_single`, graph construction (CSR layout, edge ordering by cost), + the Python binding path (copies, GIL), batch/thread usage. +- Whether the measurements support the claims: A/B/A design, noise, the + `W_max = 65536` choice, the sweep, the NetGraph-level workloads + (`cpu_queue/bench_netgraph.py`) and whether they represent realistic + NetGraph use; anything the author may have rationalised away. +- Correctness or robustness risks that an optimisation reviewer should flag: + thread_local lifetime and memory bound, exception paths, reentrancy, + int64 overflow in bucket arithmetic, graphs with zero edges, Python threads. + +## Rules + +- Be concrete and sceptical. Cite file paths and line numbers. Do not restate + the plan; find what it misses or gets wrong. +- Verify, don't speculate: build the harness and run experiments where a claim + can be checked in minutes (old binary vs new binary, forced heap via + `NGRAPH_CORE_SPF_QUEUE=heap`, fresh processes, several samples, record load + with `uptime`). Treat differences under ~5% as noise unless reproduced. +- Do NOT modify tracked files. Put every experiment, patch (as `.patch` files) + or script under `dev/perf/spf_queue/review-2026-10/`. + You may build into `build/`. Do not run `git commit`, `git stash`, `git + checkout`, or anything that changes the working tree outside that directory. + The Python venv is `venv/`; NetGraph lives in `/Users/networmix/ws/NetGraph` + (read-only for you). Do not run the full test suites; they already passed. +- Other sessions share this machine; keep runs short and sequential. + +## Report (write it to `dev/perf/spf_queue/review-2026-10/REPORT.md`, in English) + +1. A ranked list of findings. For each: title; what exactly is missed or wrong + (with evidence); expected gain and the workload class it applies to; cost + and risk; verdict as one of VERIFIED-GAIN (you measured it), PLAUSIBLE- + UNTESTED (why you could not verify), REFUTED (you measured no gain), + ALREADY-COVERED (the plan handles it; say where). +2. For every VERIFIED-GAIN: the exact patch (file + diff) and the numbers + (old / new / your variant, samples, load). +3. Measurement critique: what in the recorded A/B/A would you not trust, and + what would you rerun. +4. A short verdict: is the shipped approach the right streamlined choice, and + what (if anything) should be done before committing it. diff --git a/dev/perf/spf_queue/review-2026-10/REPORT.md b/dev/perf/spf_queue/review-2026-10/REPORT.md new file mode 100644 index 0000000..195d4b9 --- /dev/null +++ b/dev/perf/spf_queue/review-2026-10/REPORT.md @@ -0,0 +1,280 @@ +# Independent review of the SPF optimisation + +Reviewed 2 October 2026 against `fbab119e794c843838f4f3f96d75cb7f32f06845` and the supplied uncommitted diff. Line references below refer to the live, unmodified production files, not the experimental copies. + +**No: the main algorithm choice is sensible, but several small, worthwhile changes were neither considered nor verified.** I measured gains in neighbour processing, predecessor output construction, singleton-frontier handling, and fixed-routing callers. More importantly, I reproduced a new exception-safety defect and disproved the stated retained-memory bound. The weighted-graph speedup itself survives independent measurement. + +All experimental sources, patches, scripts and results are in this directory; executables/objects are under `build/perf/`. All 97 tracked files were checked byte-for-byte against the review-start snapshot; none changed ([verification](results/tracked-verification.txt)). No full repository suite, commit, checkout, stash, or downstream source modification was performed. + +## 1. Ranked findings + +### 1. A failed touched-list allocation corrupts the next SPF call + +**Verdict: VERIFIED-GAIN — correctness restoration, not a latency claim. Priority: fix before committing.** + +`src/shortest_paths.cpp:726–728` writes the source distance and bottleneck **before** the potentially allocating `touched.push_back`. Reverse SPF does the same at `:932–934`. If that allocation throws, the lease runs, but sparse cleanup at `:433–436`/`:475–479` has no record of the modified node. The next same-sized search can suppress a valid relaxation against the stale zero distance. Sparse output materialisation then reports the reachable node as unreachable. + +[Reproducer](robustness.cpp), [public old-build reproducer](fault-public.cpp), and [exact fix](exception-fix.patch), affecting those two blocks in `src/shortest_paths.cpp`: + +| Eight-node, one-edge graph; inject one four-byte allocation failure, then search from/to the other endpoint | Old | New | Fix | +|---|---:|---:|---:| +| Forward distance to the reachable node | 1 | `INT64_MAX` | 1 | +| Reverse distance from the reachable node | 1 | `INT64_MAX` | 1 | + +Raw outputs: [old](results/fault-old.txt), [new](results/fault.txt), [fix](results/fault-fixed.txt). The patch records the source/target first, then performs the nonthrowing writes. It does not change successful-call work or outputs. Cost/risk: two statement reorderings; very low. The existing fanout-throw test at `tests/cpp/shortest_paths_tests.cpp:641–668` does not exercise this failure point. The comment claiming restoration on *every* exit at `src/shortest_paths.cpp:497` is presently false. + +### 2. Do not recompute an identical SPF inside fixed-routing max-flow calls + +**Verdict: VERIFIED-GAIN.** + +`src/max_flow.cpp:123–151` and `src/flow_state.cpp:537–552` repeatedly call SPF. With `require_capacity=false`, they pass no residual; graph, masks, endpoints and selection remain identical. The next placement still needs current residuals, but the next SPF does not. This is a particularly simple caller optimisation, independent of the queue. It is unnecessary when `shortest_path=true`, which already stops after one successful tier. + +[Exact patch](fixed-routing.patch) caches the result **within the invocation**, in both files, only re-searching when capacity-aware routing is enabled. It does not cache changing residual-aware routes. On eight weighted 4,096-node/32,768-edge queries, seven samples per fresh process: + +| Workload | Old A1 / A2, ms | New A1 / A2, ms | Reuse variant, ms | Reduction from new | +|---|---:|---:|---:|---:| +| `place_max_flow`, fixed routing | 5.757 / 5.646 | 3.857 / 3.784 | 2.134 | 44–45% | +| Same, node/edge exclusions | 4.255 / 4.150 | 3.090 / 2.951 | 1.693 | 43–45% | +| `calc_max_flow`, exclusions | 6.032 / 6.033 | 4.942 / 4.846 | 3.531 | 27–29% | +| `calc_max_flow`, no exclusions | 7.105 / 6.903 | 5.139 / 4.972 | 4.486 | Unstable samples; do not use for a precise claim | + +The unmasked `calc_max_flow` variant samples span 3.851–5.648 ms; I am explicitly not treating its median as equally strong evidence. The other gains also appeared in the screening pass. The accepted rerun fixes all query endpoints in the masks before warmup; the earlier screening files are retained and labelled `screen-flow-*`. + +Evidence: [driver](flow-driver.cpp), [build/run script](build-flow.sh), [old A1](results/flow-old1.csv), [new A1](results/flow-new1.csv), [variant](results/flow-fixed.csv), [new A2](results/flow-new2.csv), [old A2](results/flow-old2.csv), [load](results/load-flow.txt): 1-minute load 4.46–4.76. Output hashes agree; capacity and conservation checks run outside timing. See section 2 for stronger flow validation. + +Expected applicability: fixed IP/IGP routing through these helpers, with repeated placement enabled. No promised improvement for residual-aware default max-flow or the recommended single-pass IP-ECMP combination. Cost/risk: small local lifetime extension; review the old result's extra lifetime during replacement on the residual-aware route. Keep this as a separate caller patch if the SPF change is to remain narrowly scoped. + +### 3. Skip settled neighbours before collecting their parallel edges + +**Verdict: VERIFIED-GAIN.** + +At `src/shortest_paths.cpp:583–640` and `:832–881`, the code collects eligible edges and computes their bottleneck even when the neighbour is settled. With nonnegative costs, a settled neighbour cannot receive a shorter path; equal-cost predecessor changes and single-path capacity improvements are already prohibited for settled neighbours at `:644–655`/`:884–895`. Skipping its contiguous neighbour run early preserves the existing outputs. + +[Exact patch](settled.patch): two condition changes in `src/shortest_paths.cpp`. This is not a different tie-break, cached eligibility policy, or new queue. + +| Dense unit fabric, 800 nodes / 320,000 edges, 16 full-source queries | Old A1 / A2 | New A1 / A2 | Skip-settled | +|---|---:|---:|---:| +| Pass A, ms | 36.784 / 36.827 | 34.775 / 35.326 | 30.552 | +| Pass B, ms | 36.005 / 36.967 | 35.225 / 36.691 | 29.811 | +| Reverse search, 16 targets, ms | 48.257 / 46.690 | 46.923 | 37.042 | + +Forward improvement is 12–19% against the new code; reverse improvement is 21%. Weighted random graphs do **not** establish a gain: pass B is 36.487 versus 36.437/36.404 ms. Do not advertise this as a universal improvement. The extra branch could be unfavourable in other graph families. + +Evidence: `results/{old-a1,new-a1,settled,new-a2,old-a2}.csv`, the corresponding `*-b*` files, and `results/reverse-*.csv`; [first load log](results/load.txt), [second load log](results/load-second.txt). Loads during these forward phases were 3.53–4.42; reverse phases 4.67. Full forward old-loop comparison: 1,351,168 comparisons, zero failures. Reverse hashes agree with the separately built old implementation; targeted sanitizers and the cross-caller bitgate also pass. + +Cost/risk: very small implementation, low semantic risk after nonnegative-weight proof and parity checks. This directly challenges the suggestion at `CPU_PLAN.md:150–155` that edge-scanning dominance makes unit fabrics merely neutral: some of that edge processing is avoidable. + +### 4. Forward PredDAG conversion need not walk every surviving list twice + +**Verdict: VERIFIED-GAIN.** + +`src/shortest_paths.cpp:679–700` walks each predecessor list to count entries, prefixes the counts, sizes/initialises two output arrays, and walks the same lists again to fill them. On dense equal-cost DAGs this is measurable work, not an irreducible result-size floor. + +[Exact patch](append.patch) keeps the sparse path unchanged. For the dense case it reserves the number of recorded entries as an upper bound, appends surviving entries once in node/list order, and writes each final offset immediately. It preserves parent ordering and all four output arrays. + +| Same dense forward workload as finding 3 | Old A1 / A2, ms | New A1 / A2, ms | One-pass conversion, ms | +|---|---:|---:|---:| +| Pass B | 36.005 / 36.967 | 35.225 / 36.691 | 29.755 | +| Pass C | 37.396 / 37.468 | 35.800 / 35.380 | 31.159 | + +This is a reproduced 12–19% reduction. Random-graph changes remain below the review's significance threshold. Combined with settled-neighbour skipping, the dense row is 26.327 ms versus 35.800/35.380 ms, about 26% lower; that combined timing is one phase, not a separately replicated universal claim. + +Evidence: [patch](append.patch), [combined patch](combined.patch), `results/{append,append-c,combined}.csv`, [pass C load](results/load-third.txt). Pass B load was 3.53; pass C was busier, 7.93–8.46. The individual improvement survives both passes. [Forward comparison](results/correctness-append.txt): 1,351,168 comparisons, zero failures. + +Expected applicability: dense multipath outputs with many live predecessor entries. Cost/risk: small conversion change, but reserving *all* recorded entries can retain excess space in the returned vectors when many predecessors were superseded. This must be weighed against the exact-sized current output; it is not a free memory improvement. Reverse conversion is a scatter by successor and requires ascending-tail order (`:981–1015`), so this exact patch cannot simply be copied there. + +### 5. The chain regression is partly avoidable without another search algorithm + +**Verdict: VERIFIED-GAIN.** + +For a frontier with one item, `BucketQueue` still divides/modulos its key, sets/clears occupancy, advances the cursor and touches a vector/heap (`src/shortest_paths.cpp:329–362`). The plan tried modulo masking and accepted the regression; that does not test avoiding the bucket machinery altogether for an isolated item. + +[Exact patch](inline.patch) stores a lone newly pushed item inline, promoting it into the existing buckets if a second item arrives. After ordinary bucket operation it only re-enters this mode when the frontier empties. Keys, queue selection and pop order are unchanged. This is not retrospective dispatch to a second Dijkstra implementation. + +| Chain: 2,048 nodes, 256 queries with varying sources | Old A1 / A2, ms | New A1 / A2, ms | Inline item, ms | +|---|---:|---:|---:| +| Pass B | 2.929 / 3.114 | 5.232 / 5.462 | 3.541 | +| Pass C | 3.039 / 3.115 | 5.607 / 5.569 | 3.618 | + +Reduction from the new bucket route: 32–35%. It still trails the old implementation by about 14–21% in these passes. These are 256 varying-length chain queries, **not** the plan's single full-chain query; do not quote the whole batch as single-query latency. Other focus rows show no reproduced material gain or regression. + +Evidence: `results/{inline,inline-c}.csv`, the B/C controls above, and [correctness](results/correctness-inline.txt): 1,351,168 comparisons, zero failures. Same load ranges as finding 4. A smaller experiment retaining just a sole item's bucket location ([singleton.patch](singleton.patch)) gave only about 9% in the first chain pass; bypassing the bucket storage is the useful version. + +Cost/risk: modest queue-state complexity; promotion after zero-cost pushes and cyclic cursor transitions deserve explicit tests. Applicability includes narrow-frontier portions of ordinary graphs, not just graphs that are globally chains. There is no workload evidence behind the plan's categorical statement that no production caller runs on a path graph (`CPU_PLAN.md:287–292`). + +### 6. Retained memory is not bounded by one largest-graph workspace + +**Verdict: PLAUSIBLE-UNTESTED for the reclamation optimisation; the counterexample itself is verified. Priority: correct the bound before committing.** + +Only the fixed node arrays go through `ensure_sized` (`src/shortest_paths.cpp:402–405,424–430,465–472`). Entry arrays, touched/selection buffers, heap storage, bucket headers and each individual bucket's item capacity retain their high-water marks. Both directional workspaces coexist per thread (`:494–495`). + +The stronger problem is the **sum of independent bucket high-water marks**. [Memory probe](robustness.cpp), [output](results/memory.txt): with 63 graphs, each having only 1,027 nodes and 1,026 edges and a maximum live frontier of 1,024 items, retained bucket-item capacity rises from **16,400 bytes to 1,032,208 bytes**. A subsequent two-node graph shrinks `dist.capacity()` to two but retains all 1,032,208 bucket bytes. + +Thus `:260–264` is misleading and `CPU_PLAN.md:368–369` accounts only for empty headers/bitmap. A conservative bound is proportional to `W_max × historical maximum queued items`, plus node/entry/heap buffers, **per direction per live thread**, rather than just the largest simultaneous frontier. The multiplier can be much more important than the 1.6 MB header number. Entries and heap capacity also survive a graph-size shrink. + +Expected benefit: memory reclamation after heterogeneous graphs or worker-pool traffic; no measured latency gain. Cost/risk: add a total retained-byte budget or reclaim bucket/item storage on substantial graph-size shrink; avoid destroying hot capacities every query. I did not benchmark such a policy because choosing a memory budget requires a workload trade-off; pretending that `W_max` already supplies it would be incorrect. Thread exit does free the TLS vectors; long-lived Python/executor threads are the relevant retention case. + +### 7. The fallback regression is real in some rows, but its “workspace cost” explanation is not established + +**Verdict: PLAUSIBLE-UNTESTED for the remaining causal attribution. Specific cheap remedies below are REFUTED as material gains.** + +`CPU_PLAN.md:156–162` converts an unresolved difference into “the cost of the reusable workspace.” The new route does extra touched-list work, copies dense distances (`src/shortest_paths.cpp:675`), and resets arrays after copying (`:438–443`); these are candidates, not a measured attribution. The three previously attempted mitigations were not repeated. + +I isolated three other possibilities, using the same production loop: + +| Pass A/B, 16 full queries | New forced heap | Experiment | Outcome | +|---|---:|---:|---| +| Random 16k, remove touched tracking and force dense handling | 65.364 / 66.960 ms | 64.784 ms | Under 5%; no established full-search gain | +| Wide ~2^20 costs, same ablation | 52.299 / 53.113 ms | 51.040 ms | Under 5%; insufficient to attribute the gap | +| Near-target queries, same ablation | 0.399 / 0.408 ms | 1.233 ms | Destroys the intended workspace benefit | +| Wide ~2^20, explicit heap item/comparator | 52.299 / 53.113 ms | 55.679 ms | No gain | +| Wide ~2^20, copy heap front before pop, like old priority_queue | 52.248 ms | 52.007 ms | Noise | + +Patches: [notouch](notouch.patch), [heapitem](heapitem.patch), [frontpop](frontpop.patch). The 24-byte heap item versus 16-byte bucket item is a genuine layout difference; merely replacing the tuple with an explicitly ordered struct did not help. Do not narrow the double bottleneck or int64 distance to pack a key. + +The quarter-touched threshold at `src/shortest_paths.cpp:399` is not established as the crossover: the reported workload matrix mostly samples very sparse or nearly full searches. Reset and output materialisation need not have the same optimal threshold; reverse sparse conversion additionally sorts touched nodes (`:986–987`). Intermediate touched fractions, locality and graph-size churn remain unmeasured. This is a plausible tuning opportunity, not a verified gain, and the no-touch ablation is not a threshold sweep. + +Fresh old/new controls vary: pass B wide ~2^20 is 48.972/50.562 ms old versus 53.175/52.534 ms new; pass A is 50.820/52.036 versus 53.541/53.120. The boundary run at the same broad cost range is 25.107/25.151 versus 27.498 ms for eight queries. These support a workload-dependent penalty, sometimes clearly over 5%, not a fixed universal 5–9% tax. Cost/risk of further attribution: targeted search/finish/reset profiling on a quieter machine. Expected recoverable percentage remains unknown. Neither “noise” nor “inevitable” is an adequate root cause. + +### 8. `W_max=65536` is conservative and useful, not a verified optimal or portable threshold + +**Verdict: PLAUSIBLE-UNTESTED for the remaining bitmap/cleanup refinements.** The bounded-dispatch design and deferred wider-queue alternatives are already covered by the plan. + +The recorded sweep jumps from `W=32768` to approximately `2^20`; it never measures the chosen boundary (`cpu_queue/harness.cpp:339–341`). Passing `2097152` as harness `maxW` does **not** change the production `ref` route's compile-time limit: `Runner::run` immediately calls `run_ref` (`:147`), while `src/shortest_paths.cpp:270,368–393` decides actual dispatch. The CSV's harness `fallback` field therefore is not a production fallback counter. + +I added the missing near-boundary rows, seven samples, 16,384 nodes/131,072 edges: + +| Actual W | Old A1 / A2, ms | New auto, ms | New forced heap, ms | +|---:|---:|---:|---:| +| 32,768; eight full queries | 25.959 / 26.272 | 17.628 | 27.216 | +| 65,535; eight full queries | 25.433 / 25.761 | 18.147 | 26.350 | +| 65,536; eight full queries | 25.641 / 26.609 | 18.499 | 27.175 | +| 65,537; eight full queries | 25.659 / 25.454 | 26.491 | 26.865 | +| 65,535; 64 near queries | 1.131 / 1.123 | 0.455 | 0.390 | +| 65,536; 64 near queries | 1.171 / 1.149 | 0.435 | 0.399 | + +[Raw boundary files](results/boundary-new1.csv), corresponding old/heap controls, and [load](results/load-second.txt), 4.42–4.67. The boundary supports full-search acceleration on this M4; near queries pay a 9–17% bucket overhead relative to the new heap while still beating old substantially. This is evidence against treating W alone as a universal profitability predictor, not a request to add a complex dispatcher immediately. + +The occupancy bitmap is already implemented. However, `settle_active` can scan up to `ceil(W/64)` words (`:349`); `end()` also scans **every word**, including zero ones (`:317`), and `begin()` clears every word (`:312`). “Clear only occupied buckets” does not mean O(number of occupied buckets) total cleanup. A second-level nonempty-word bitmap or touched-word list addresses this overhead; its benefit at small W is unproven. Both workspaces also call both queues' `end()`, so a heap query after a wide bucket query still scans that old bitmap. + +The plan already defers a hierarchical bitmap/radix alternative and x86 verification (`CPU_PLAN.md:367–373,433–438`); these are not omitted discoveries. Do not widen the limit solely from the old full-search sweep, especially before bounding retained item capacity and measuring cold construction, sparse frontiers, masks and graph changes. No second machine was available in this review. + +### 9. An O(N) result floor exists, but the proposed distance-only remedy is misstated; early exit also has a compatibility trap + +**Verdict: PLAUSIBLE-UNTESTED for a target-specific internal result path.** + +`src/shortest_paths.cpp:671–687` necessarily fills N distances and N+1 offsets under the current API. Sparse reset correctly removes scratch initialisation, not these outputs. But a **distance-only vector still has N elements**; it cannot remove the O(N) floor as claimed at `CPU_PLAN.md:454–457`. A scalar target-distance result, compact target subgraph/path, caller-owned output, or a lazy/sparse result contract is needed. The internal callers commonly inspect only `dist[dst]` (`src/max_flow.cpp:142`, `src/flow_policy.cpp:184`), and `place_max_flow` does not use distances at all (`src/flow_state.cpp:543–549`). They are concrete candidates for a narrower internal result interface, without changing Python defaults. Removing the distances alone still leaves the dense DAG offsets. + +Also, the current early-exit code is not simply “process exactly through the target's distance.” Stale-entry `continue` branches at `:566–569` bypass the stop check at `:661`. A stale equal-distance entry behind the target can cause a more expensive node to be expanded. [Six-node reproducer](early-exit.cpp): target cost 1, yet a node reachable only by expanding a distance-2 node gets distance 3. [Old](results/early-old.txt) and [new](results/early-new.txt) both do this. + +Moving the stop test to the loop head would save work, but changes the returned tentative off-target distances/DAG and fails strict old-result parity. Likewise, breaking immediately when the destination is popped or skipping all relaxations beyond its distance is not a drop-in optimisation. Use an explicit narrower internal contract if taking this route. Expected gain: large only when output/unused exploration dominates; not measured. Cost/risk: moderate API/contract work. Bidirectional search/A* and canonical incoming-CSR reconstruction are not equally cheap substitutes under the current ordered-output contract. + +### 10. FlowPolicy already avoids many searches; it still has avoidable copies and post-search rejection + +**Verdict: PLAUSIBLE-UNTESTED for the remaining copy and bounded-search opportunities.** Existing memoisation and shared seeding already cover much of this area. + +Memoisation is not missing: `src/flow_policy.cpp:148–205` matches exact state stamps or residual bytes, and `:434–444` computes the initial bundle once. The header documents a prior 94% repeat rate for the measured EqualBalanced cycle and 0% for Proportional (`include/netgraph/core/flow_policy.hpp:215–228`). This is historical profiling evidence, not a distribution I remeasured here. Residual-aware memoisation must retain exact capacities: unchanged eligibility does not preserve bottleneck ordering or zero-cost DAG choices. + +There is nevertheless a definite redundant copy: after obtaining an owned `dag`, `get_path_bundle` returns `std::make_pair(dag, dst_cost)` at `src/flow_policy.cpp:238`. Moving that local would avoid another full DAG copy on both hit and miss. A hit still needs its own owned result because the cache retains its DAG. Also, `has_min_flow` remains a memo-key discriminator at `:159–160`, although residual awareness now depends solely on `require_capacity_` at `:94–101`, and EB skips the threshold-derived edge mask. Revisit that stale key/comment with a call-count reproducer before changing it. + +Cost ceilings are applied after SPF at `:207–232`; when a bound is already known, an internal bounded-target search could reject earlier. Respect `best_path_cost_` updates and equal-cost/zero-edge behaviour. Expected gain: one DAG copy per bundle return, fewer equivalent-key misses, and less work on rejected high-cost routes; workload speedup unmeasured. Cost/risk: move is trivial; memo-key/ceiling changes require focused semantic tests. Broad new memoisation is not justified by the existing measured Proportional miss rate. I did not build an isolated memo-hit/bundle-return benchmark for this private helper; the source proves the copy, not a measurable end-to-end gain. + +### 11. KSP's main missed cheap cost is not necessarily its private Dijkstra queue + +**Verdict: PLAUSIBLE-UNTESTED for mask/result work.** Deferring private-queue replacement is already justified in the plan. + +`dijkstra_single` is used for the initial path (`src/k_shortest_paths.cpp:204`); its comparator only compares cost (`:61–63`), so substituting SPF's capacity/node key can change first-path selection. Most subsequent spur work calls the newly optimised public SPF (`:283`). Replacing the private queue without profiling may have little impact on k>1. + +Every spur builds byte masks of N/E elements (`:247–267`), then allocates bool arrays and copies them again (`:269–279`). Reuse bool scratch directly, reset only the prefix/edge exclusions that changed, and preserve the base masks. KSP already caps enumeration and rejects candidate families against the cost ceiling (`:289–305`), but the ceiling is checked *after* the complete SPF/DAG result. A bounded internal search could help rejected spurs. Expected benefit: fewer O(N+E) allocations/copies per spur, especially on large graphs and small reachable regions; no percentage established. Cost/risk: moderate scratch-lifetime and ordering work. The one k=8 Clos benchmark does not profile these components or cover long WAN paths and changing k. + +### 12. Graph layout and metadata are not free, but the obvious gcd micro-optimisation is not a demonstrated win + +**Verdict: REFUTED for a material gcd-guard gain in these measurements.** A separate adjacency-local attribute layout remains an untested possibility. + +[One-line gcd patch](gcd.patch) stops calling `std::gcd` once the running gcd reaches 1 (`src/strict_multidigraph.cpp:66`). I timed the **whole constructor**, not just that operation: 16,384 nodes, 131,072 edges, nine samples, old/new/guard/new/old. Random-input construction was 9.060/9.137 ms old, 9.164/9.289 new, 9.122 guarded. Already cost-ordered input was 1.344/1.374 old, 1.430/1.448 new, 1.364 guarded; the repeat was 1.448/1.456 new versus 1.411 guarded. The smaller repeat does not reproduce a >5% gain. Do not sell this as a significant speedup. Output graph hashes agree. Raw files: `results/build-*.csv`, `results/build-repeat-*.csv`; load logs are the B/C logs. + +The graph already has forward and reverse CSR. Global `(cost,src,dst)` edge ordering (`src/strict_multidigraph.cpp:80–108`) means a CSR row gathers cost/capacity through edge IDs, and the comment that *all* parallel edges are consecutive at `src/shortest_paths.cpp:580` is too strong across cost tiers. Cost-first rows are useful, but not the same as CSR-local cost/capacity arrays. Reordering edge IDs or neighbour visitation risks documented edge-ID tie-breaking and predecessor order. An auxiliary CSR-aligned attribute layout could preserve IDs/order but costs memory and still needs edge-ID gathers for residuals/masks. No layout experiment establishes that trade-off here. + +The max/gcd metadata itself is correct and cheap to access, travels with graph copies, handles zero costs, and avoids repeated eligibility scans. A masked-out wide edge can force the whole query onto the heap; computing a tighter per-query profile is not free and needs amortisation over a stable mask. It is not automatically a cheap win. + +### 13. Python copies and threading deserve separate measurements; “release the GIL” is already done + +**Verdict: PLAUSIBLE-UNTESTED for owned-output transfer and worker reuse.** GIL release and bounded existing batches are already implemented. + +`bindings/python/module.cpp:185–206,228–255` copies residuals/masks before releasing the GIL. The copied inputs give the native call a snapshot; blindly borrowing writable NumPy memory would remove that protection while another Python thread runs. The GIL is already released around SPF, reverse SPF, max-flow, KSP and placement. `CpuBackend` forwards spans directly (`src/cpu_backend.cpp:24–37,40–51`); removing its small duplicated validation is not a credible main optimisation. + +Outputs do have extra traffic: the binding allocates/copies or converts the distance vector and passes `res.second` as an lvalue into `py::make_tuple` (`bindings/python/module.cpp:208–217,257–266`). The installed pybind11 caster maps an lvalue under automatic policy to a copy (`venv/lib/python3.14/site-packages/pybind11/include/pybind11/detail/type_caster_base.h:1650–1659`). Move the owned DAG; consider a capsule owning the int64 vector for a zero-copy int64 result. Float64's sentinel conversion still needs a pass. No separately rebuilt pybind extension variant was timed in this review, so the existing-module NetGraph rerun cannot verify these transfer changes. Expected benefit: output-heavy and tiny-search Python calls; not measured, and public ownership/mutability/default-dtype tests are needed. + +`batch_max_flow` already dynamically schedules bounded `std::async` workers (`src/max_flow.cpp:354–379`), and sensitivity has its own bounded workers (`:427–454`). TLS scratch is reusable within those workers but is destroyed when each batch's workers exit. Persistent workers may amortise first-use allocation; nested Python pools plus native batches can oversubscribe the machine. The NetGraph benchmark explicitly uses serial Monte Carlo/scenarios, so it cannot establish throughput or persistent-pool memory behaviour. Sequential augmentations sharing residuals cannot be batched as independent searches. + +### 14. There is another potentially larger dense-placement hotspot outside SPF + +**Verdict: PLAUSIBLE-UNTESTED.** + +`src/flow_state.cpp:174–199` finds unique DAG parents by linear search and then rescans the entire parent list once per unique parent. For a node with P distinct predecessors, this is quadratic parent processing before the placement solve. Preserve first-appearance and edge accumulation order with a reusable indexed grouping/counting structure; do not sort indiscriminately because floating-point accumulation and group order are observable. + +Expected applicability: wide ECMP/Clos DAGs where queue changes hardly move end-to-end placement time. Expected asymptotic improvement is O(P²) to O(P), but I did not measure a latency gain or implement it: maintaining arbitrary caller-supplied PredDAG order and all three placement semantics needs a separate patch and feasibility/conservation/cut checks. Cost/risk: larger than the four small verified performance changes above. This is a concrete profiling target, not evidence that the existing solver can simply be replaced. + +### 15. Arithmetic/empty-graph/Python-thread risks are mostly covered; reentrancy is a separate assumption + +**Verdict: ALREADY-COVERED for ordinary arithmetic, edgeless graphs and independent threads.** Same-thread reentrancy remains a separate, unverified use case. + +The constructor enforces nonnegative costs and total cost below `2^62` (`src/strict_multidigraph.cpp:40–66`). Therefore `max_cost/gcd+1` cannot overflow int64; cursor advancement corresponds to an actual queued nonnegative distance, and its stride step is bounded by an edge-cost window. I found no ordinary signed-overflow counterexample in the bucket arithmetic. All-zero costs give W=1; no-edge graphs need no edge access despite empty residual/mask sizes comparing equal to E=0. + +[Targeted sanitizer probe](safety.cpp) covered exact W=65,535/65,536/65,537, zero costs, costs near the constructor's aggregate bound, N=0 and N>0/E=0, both directions, option combinations, reused workspaces and concurrent C++ threads. It passed under ASan/UBSan. This does not substitute for Python-thread throughput measurements. Independent immutable-graph calls receive independent TLS state; Python input copies and GIL release remain unchanged. + +There is no in-use guard or nested lease stack for `tls_forward`/`tls_reverse` (`src/shortest_paths.cpp:494–501`). A same-direction recursive call on one thread would reset the outer call's workspace. I found no supported callback/reentry path in these synchronous loops; ordinary Python threads are not such a path. Document the non-reentrant assumption or add an in-use fallback if callbacks/custom allocation hooks become supported. Do not present a hypothetical recursive call as a reproduced production failure. + +## 2. Experiments, exact patches and validation coverage + +The reproducible performance patches are linked in findings 2–5; the exception fix is linked in finding 1. Each `.patch` contains the full unified diff against the unmodified live source. Experimental `.cpp` copies let them be built without applying anything to the working tree. + +- [build-review.sh](build-review.sh) creates old sources/headers using read-only `git show fbab119:...` and builds the focused harness variants. Same Apple clang 21, C++20, `-O3 -funroll-loops -fno-math-errno -fno-trapping-math` as the supplied harness. The supplied `build.sh` was also run successfully. +- [driver.cpp](driver.cpp) reuses the supplied generators/query setup and adds focused, reverse and boundary rows. Random16/wide rows contain 16 queries; Clos contains 16; near contains 64; chain contains 256 varying sources. Every phase is a fresh process; two warmups precede seven measured samples. Raw CSVs include all samples. +- [run-review.py](run-review.py), [run-second.py](run-second.py), [run-third.py](run-third.py) record phase order/load and keep old and new controls on both sides of the focus experiments. [environment](results/environment.txt) records compiler/host/source/binary hashes; [final manifest](results/final-sha256.txt) covers later experimental builds and sources. Pass C is deliberately reported as noisier, not quietly substituted for pass B. +- Baseline, skip-settled, inline-item and one-pass-output versions each passed the supplied forward comparison matrix: **1,351,168 comparisons each**, against the preserved old-loop variants, not just distances. These are repeated combinations on a finite set of graphs, not millions of independent graphs. Files: `results/correctness-{baseline,settled,inline,append}.txt`. +- [validate-review.sh](validate-review.sh) builds settled+one-pass output together with the fixed-routing caller patch under **ASan/UBSan**, with sanitizer failures fatal. Its targeted fixture checks nonuniform-cost flow feasibility/conservation, all single-edge exclusions, exhaustive small-graph cut optimality and reported cut capacity, plus FlowPolicy cost factors 1 and 2. [Results](results/validate-flow-variant.txt), the build/run log (not retained). +- The same sanitized combined/caller build passes the existing cross-caller dump: **6,226 lines byte-identical** to the old binary, including forward/reverse/fanout, placement modes, FlowPolicy sequences, batch/sensitivity and KSP. [Hashes](results/bitgate-sha256.txt). Native batch/sensitivity thread budgets were set to 1 for this check to keep load bounded. The inline queue was separately checked by the full forward matrix; it was not included in that combined sanitized build. +- [safety.cpp](safety.cpp) adds the width/int64/edgeless/concurrency probes described above. [Output](results/safety.txt). +- [run-netgraph-review.py](run-netgraph-review.py) reruns four NetGraph workloads with five samples, `PYTHONHASHSEED=0`, bytecode writes disabled, explicitly selected old/new modules. [Module paths/hashes/load](results/netgraph-environment.txt) verify the same extension binaries used by the recorded experiment. No downstream rebuild was needed or performed; these runs measure the existing uncommitted change, **not** my C++ variants. + +NetGraph rerun, medians in ms, identical recorded workload digests in all phases: + +| Workload | Old A1 / A2 | New | New forced heap | +|---|---:|---:|---:| +| Full SPF, Clos 200×200 | 212.167 / 212.584 | 215.551 | 215.680 | +| Full SPF, weighted 100×100 grid | 219.249 / 219.160 | 169.151 | 235.446 | +| Bound-context max-flow, weighted grid combine | 201.715 / 204.482 | 160.344 | 216.545 | +| Backbone Clos placement | 68.333 / 68.736 | 67.171 | 67.445 | + +The weighted benefit is independently reproduced. Sub-5% Clos/placement changes are noise under this review's rule. The broader 16-row scenario suite was read but not rerun. + +## 3. What the measurements do and do not establish + +Already-measured dead ends were not retried: sorting active buckets once, power-of-two masking as a cure for chains, re-hoisting TLS array pointers, re-fixing the function-pointer comparator, and moving growable buffers into locals. None is presented here as a new recommendation. + +1. **The strongest original claims are sound.** A matched old/new/forced-heap/old sequence, result checks and fresh processes are much better than comparing the slower experimental heap copy with its sibling bucket implementation. The weighted Core gain and approximately 1.25–1.30× weighted NetGraph gains survived this review. The small-query workspace gain also survives. GPU ten-worker tables and relaxed canonical-DAG prototypes are not comparable replacements; the plan correctly separates them. + +2. **A/B/A is not machine isolation.** Original Core load ranged 6.5–12.1, and original NetGraph load 3.9–6.5. Medians from consecutive samples within one process do not remove thermal/frequency, scheduler or allocator drift. My own load logs show 3.5–4.7 during the first two passes and roughly 8 during the third. These are useful large-effect confirmations on a shared machine, not the plan's promised quiet-machine acceptance evidence. Do not derive confidence intervals from nine correlated samples as if they were nine isolated process runs. + +3. **The “no unit workload regressed beyond A1/A2 drift” statement is literally too strong.** The recorded backbone placement row is 68.5/67.9 old versus 71.4 new; three-tier placement is 370.7/366.7 versus 381.3 (`CPU_PLAN.md:126–139,150–155`). Both exceed the old bracketing drift while being around the declared noise band. The defensible conclusion is “not a demonstrated regression,” not “within A1/A2 drift.” The first pre-comparator-fix pass is useful context but is not an independent replication of the final binary. + +4. **The sweep samples the wrong dimensions for a universal cutoff.** One positive uniform-random cost distribution, one N/degree and full-source queries cannot establish a universal W limit. Add exact boundary widths, stride>1, all-zero costs, sparse/high-diameter graphs, outlier edges, changing masks, first-query allocation and memory high-water behaviour. This review supplies boundary and some safety rows, not that entire performance matrix. Linux/x86 remains open. A masked wide edge can cause a fallback, rather than “merely wasting empty buckets.” + +5. **All supplied Core timing rows are warmed.** Expected `run_ref` calls occur before timing (`harness.cpp:263`), followed by two warmups (`:266`). This warms the new TLS workspace before its first measured call. All graph construction is outside timing. The timing loop retains the entire batch's output vectors until checking (`:267–271`), unlike callers that immediately consume/discard each result. This matters for allocation/cache pressure and the large-output conversion variant. Add cold first-call and immediate-consumption measurements rather than replacing the warmed numbers. + +6. **The NetGraph workloads are useful software-path coverage, not a representative demand distribution.** They include real APIs, shipped scenarios, pseudo nodes, failures, WCMP/ECMP and KSP. However, the positive result is dominated by a synthetic planar 100×100 grid with costs sampled from 1–20 (`bench_netgraph.py:85–110`). It is not evidence that a typical metric-weighted WAN simulation speeds up 25%; the included NSFNET scenario was already near neutral. Bound contexts are created outside timing (`:174–175,187–188,200–205`), while pairwise grid builds a context inside (`:231–237`); their different gains do not isolate queue effectiveness. Timed Python functions also hash/normalise results and perform NumPy reductions. Serial scenarios/Monte Carlo do not represent parallel worker-pool reuse or oversubscription. + +7. **Digest agreement has limits.** SPF checksums contain only a distance sum and parent count (`bench_netgraph.py:178–196`), so they cannot detect reordered/wrong parents, swapped distances or wrong via-edges. `norm` drops fields named `id` recursively (`:38–51`). Only the last inner repetition's checksum is compared (`:376–381`). Keep the full bitgate/differential evidence separate from these weaker end-to-end digests. Hash-seed pinning is a legitimate correction, but does not turn this into a semantic max-flow certificate. The targeted certificate added here provides a small independent check, not complete application acceptance. + +8. **Reverse P2 was not finished according to its own gate.** `CPU_PLAN.md:426–431` requires a measured reverse result; the plan elsewhere admits none. This review's reverse measurements show 14.188/13.807 → 8.539 ms on random weighted 4k graphs, and 0.402/0.409 → 0.741 ms on chains. Add these to the evidence rather than labelling an unmeasured stage done. + +9. **Rerun priorities:** first the exception reproducer after the production fix; then isolated new/variant/new and old/new/old on dense fabrics, narrow frontiers and wide-cost fallback, with shorter interleaved phase blocks and source hashes. Include cold/warm and immediate-consumption results, realistic caller counts/touched fractions/cost ranges, output size and total per-thread retained bytes. Profile search versus output versus reset to settle the fallback attribution. Finally run the normal project/integration/sanitizer gates after applying any production patches, and CI plus a second CPU architecture. Local measurements and previously passed suites do not replace those checks on the final code. + +## 4. Commit recommendation + +**Keep the ordered bucket queue, exact pop-order contract and sparse workspace strategy. They are a good streamlined baseline. Do not commit this exact tree unchanged.** + +Fix the reproduced allocation-failure contamination first. Correct the memory claim and either bound aggregate retained bucket capacity or explicitly accept and document the actual retention policy. Consider the settled-neighbour skip and one-pass forward output together: their dense-fabric gain is large enough to merit the modest additional review. The inline singleton path and fixed-routing reuse are measured, contained follow-ups; they can be separate commits rather than expanding the queue patch without limit. + +Retain the conservative width limit while documenting that its second-platform and cold/memory acceptance remains open. Record the remaining heap penalty as unexplained rather than an unavoidable workspace tax. There is no justification to block this CPU direction on GPU work, a general batch API, a different KSP algorithm, or a wholesale graph-layout redesign. There is also no evidence for saying that all reasonable cheap wins were exhausted. diff --git a/dev/perf/spf_queue/review-2026-10/append.patch b/dev/perf/spf_queue/review-2026-10/append.patch new file mode 100644 index 0000000..6c1139b --- /dev/null +++ b/dev/perf/spf_queue/review-2026-10/append.patch @@ -0,0 +1,23 @@ +--- a/src/shortest_paths.cpp ++++ b/src/shortest_paths.cpp +@@ -676,6 +676,20 @@ + } + PredDAG dag; + dag.parent_offsets.assign(static_cast(N+1), 0); ++ if (!sparse) { ++ // Upper bound includes obsolete entries, but avoids a second list walk. ++ dag.parents.reserve(ws.ent_parent.size()); ++ dag.via_edges.reserve(ws.ent_edge.size()); ++ for (std::int32_t v = 0; v < N; ++v) { ++ for (auto i = ws.pred_head[static_cast(v)]; i >= 0; ++ i = ws.ent_next[static_cast(i)]) { ++ dag.parents.push_back(ws.ent_parent[static_cast(i)]); ++ dag.via_edges.push_back(ws.ent_edge[static_cast(i)]); ++ } ++ dag.parent_offsets[static_cast(v) + 1] = static_cast(dag.parents.size()); ++ } ++ return {std::move(dist), std::move(dag)}; ++ } + auto count = [&](std::int32_t v) { + std::size_t c = 0; + for (std::int32_t i = ws.pred_head[static_cast(v)]; i >= 0; i = ws.ent_next[static_cast(i)]) ++c; diff --git a/dev/perf/spf_queue/review-2026-10/build-flow.sh b/dev/perf/spf_queue/review-2026-10/build-flow.sh new file mode 100644 index 0000000..5331fb6 --- /dev/null +++ b/dev/perf/spf_queue/review-2026-10/build-flow.sh @@ -0,0 +1,18 @@ +#!/bin/bash +set -eu +r=dev/perf/spf_queue/review-2026-10 +flags=(-std=c++20 -O3 -funroll-loops -fno-math-errno -fno-trapping-math) +for v in old new fixed; do + case $v in + old) inc="$r/old-include"; spf="$r/old-shortest_paths.cpp"; graph="$r/old-strict_multidigraph.cpp"; flow=src/max_flow.cpp; state=src/flow_state.cpp;; + new) inc=include; spf=src/shortest_paths.cpp; graph=src/strict_multidigraph.cpp; flow=src/max_flow.cpp; state=src/flow_state.cpp;; + fixed) inc=include; spf=src/shortest_paths.cpp; graph=src/strict_multidigraph.cpp; flow="$r/max_flow-fixed.cpp"; state="$r/flow_state-fixed.cpp";; + esac + clang++ "${flags[@]}" -I"$inc" -Iinclude "$r/flow-driver.cpp" "$spf" "$graph" "$flow" "$state" src/profiling.cpp -o "build/perf/review-flow-$v" +done +for phase in old1 new1 fixed new2 old2; do + case $phase in old*) v=old;;new*)v=new;;*)v=fixed;;esac + uptime >> "$r/results/load-flow.txt" + build/perf/review-flow-$v > "$r/results/flow-$phase.csv" + echo "$phase done" +done diff --git a/dev/perf/spf_queue/review-2026-10/build-review.sh b/dev/perf/spf_queue/review-2026-10/build-review.sh new file mode 100644 index 0000000..4dc1fe2 --- /dev/null +++ b/dev/perf/spf_queue/review-2026-10/build-review.sh @@ -0,0 +1,15 @@ +#!/bin/bash +set -eu +cd "$(dirname "$0")/../../../../.." +r=dev/perf/spf_queue/review-2026-10 +flags=(-std=c++20 -O3 -funroll-loops -fno-math-errno -fno-trapping-math) +mkdir -p "$r/old-include/netgraph/core" +for f in shortest_paths strict_multidigraph; do + git show "fbab119:include/netgraph/core/$f.hpp" > "$r/old-include/netgraph/core/$f.hpp" + git show "fbab119:src/$f.cpp" > "$r/old-$f.cpp" +done +clang++ "${flags[@]}" -I"$r/old-include" -Iinclude "$r/driver.cpp" "$r/old-shortest_paths.cpp" "$r/old-strict_multidigraph.cpp" src/profiling.cpp -o build/perf/review-old +for v in baseline settled singleton heapitem notouch inline append frontpop combined; do + clang++ "${flags[@]}" -Iinclude "$r/driver.cpp" "$r/$v.cpp" src/strict_multidigraph.cpp src/profiling.cpp -o "build/perf/review-$v" + echo "built $v" +done diff --git a/dev/perf/spf_queue/review-2026-10/check-and-build.sh b/dev/perf/spf_queue/review-2026-10/check-and-build.sh new file mode 100644 index 0000000..9abfc41 --- /dev/null +++ b/dev/perf/spf_queue/review-2026-10/check-and-build.sh @@ -0,0 +1,16 @@ +#!/bin/bash +set -eu +r=dev/perf/spf_queue/review-2026-10 +for v in baseline settled inline; do + build/perf/review-$v correctness > "$r/results/correctness-$v.txt" + echo "correctness $v passed" +done +clang++ -std=c++20 -O3 -funroll-loops -fno-math-errno -fno-trapping-math -Iinclude "$r/driver.cpp" "$r/append.cpp" src/strict_multidigraph.cpp src/profiling.cpp -o build/perf/review-append +for v in old baseline gcd; do + case $v in + old) graph="$r/old-strict_multidigraph.cpp"; inc="$r/old-include";; + baseline) graph=src/strict_multidigraph.cpp; inc=include;; + gcd) graph="$r/gcd.cpp"; inc=include;; + esac + clang++ -std=c++20 -O3 -funroll-loops -fno-math-errno -fno-trapping-math -I"$inc" -Iinclude "$r/construction.cpp" "$graph" -o build/perf/review-build-$v +done diff --git a/dev/perf/spf_queue/review-2026-10/combined.patch b/dev/perf/spf_queue/review-2026-10/combined.patch new file mode 100644 index 0000000..5b645c3 --- /dev/null +++ b/dev/perf/spf_queue/review-2026-10/combined.patch @@ -0,0 +1,41 @@ +--- a/src/shortest_paths.cpp ++++ b/src/shortest_paths.cpp +@@ -580,7 +580,7 @@ + // Process edges grouped by destination node (parallel edges are consecutive in CSR). + while (i < end) { + NodeId v = col[i]; +- if (use_node_mask && !node_mask[static_cast(v)]) { ++ if (settled[static_cast(v)] || (use_node_mask && !node_mask[static_cast(v)])) { + std::size_t j_skip = i; while (j_skip < end && col[j_skip] == v) ++j_skip; i = j_skip; continue; + } + +@@ -676,6 +676,20 @@ + } + PredDAG dag; + dag.parent_offsets.assign(static_cast(N+1), 0); ++ if (!sparse) { ++ // Upper bound includes obsolete entries, but avoids a second list walk. ++ dag.parents.reserve(ws.ent_parent.size()); ++ dag.via_edges.reserve(ws.ent_edge.size()); ++ for (std::int32_t v = 0; v < N; ++v) { ++ for (auto i = ws.pred_head[static_cast(v)]; i >= 0; ++ i = ws.ent_next[static_cast(i)]) { ++ dag.parents.push_back(ws.ent_parent[static_cast(i)]); ++ dag.via_edges.push_back(ws.ent_edge[static_cast(i)]); ++ } ++ dag.parent_offsets[static_cast(v) + 1] = static_cast(dag.parents.size()); ++ } ++ return {std::move(dist), std::move(dag)}; ++ } + auto count = [&](std::int32_t v) { + std::size_t c = 0; + for (std::int32_t i = ws.pred_head[static_cast(v)]; i >= 0; i = ws.ent_next[static_cast(i)]) ++c; +@@ -829,7 +843,7 @@ + std::size_t i = start; + while (i < end) { + NodeId u = icol[i]; +- if (use_node_mask && !node_mask[static_cast(u)]) { ++ if (settled[static_cast(u)] || (use_node_mask && !node_mask[static_cast(u)])) { + std::size_t j_skip = i; while (j_skip < end && icol[j_skip] == u) ++j_skip; i = j_skip; continue; + } + Cost min_edge_cost = kInf; diff --git a/dev/perf/spf_queue/review-2026-10/construction.cpp b/dev/perf/spf_queue/review-2026-10/construction.cpp new file mode 100644 index 0000000..afbeaac --- /dev/null +++ b/dev/perf/spf_queue/review-2026-10/construction.cpp @@ -0,0 +1,28 @@ +#include "netgraph/core/strict_multidigraph.hpp" +#include +#include +#include +#include +#include +using namespace netgraph::core; +int main() { + for (bool ordered: {false,true}) { + const int n=16384,m=131072; + std::vectors(m),d(m);std::vectorw(m);std::vectora(m,1); + std::mt19937 rng(11); + for(int i=0;i samples; + std::uint64_t checksum=0; + for(int rep=-2;rep<9;++rep){ + auto t=std::chrono::steady_clock::now(); + auto g=StrictMultiDiGraph::from_arrays(n,s,d,a,w); + auto ms=std::chrono::duration(std::chrono::steady_clock::now()-t).count(); + std::uint64_t h=0;for(auto c:g.cost_view())h=h*31+c;for(auto c:g.adj_edge_index_view())h=h*31+c; + if(rep==-2)checksum=h;else if(h!=checksum)return 2; + if(rep>=0)samples.push_back(ms); + } + auto sorted=samples;std::sort(sorted.begin(),sorted.end()); + std::cout<<(ordered?"ordered":"random")<<','<(x);h*=1099511628211ULL;} }; + mix(r.first); mix(r.second.parent_offsets);mix(r.second.parents);mix(r.second.via_edges); + return h; +} +int main(int argc,char**argv) { + std::string mode=argc>1?argv[1]:"focus"; + int samples=argc>2?std::stoi(argv[2]):7; + if(mode=="correctness") return correctness(); + if(mode=="reverse") { + std::cout<<"case,median_ms,hash,samples_ms\n"; + for(auto kind:{"random","clos","chain","zerocyc"}) { + auto c=make_case(kind,std::string(kind)=="clos"?800:4096); + std::vector times; + std::uint64_t hash=0; + for(int rep=-2;rep out; + auto start=Clock::now(); + for(int q=0;q<16;++q) out.push_back(shortest_paths_to(c.graph,(q*997)%c.graph.num_nodes(),true,EdgeSelection{},c.residual,c.nm(),c.em())); + auto elapsed=ms(start); + std::uint64_t h=0;for(auto& r:out) h^=hash_result(r); + if(rep==-2) hash=h; else if(hash!=h) throw std::runtime_error("reverse nondeterminism"); + if(rep>=0) times.push_back(elapsed); + } + auto sorted=times;std::sort(sorted.begin(),sorted.end()); + std::cout< w; + if(mode=="boundary") { + for(Cost k:{32767,65534,65535,65536,131071,262143,1048575}) { + w.push_back({"wide"+std::to_string(k),make_case("wide",16384,8,false,false,11,k),8,"none"}); + w.push_back({"near"+std::to_string(k),make_case("wide",16384,8,false,false,11,k),64,"near"}); + } + } else { + w.push_back({"random16",make_case("random",16384),16,"none"}); + w.push_back({"clos800",make_case("clos",800),16,"none"}); + w.push_back({"chain2048",make_case("chain",2048),256,"none"}); + w.push_back({"near16",make_case("random",16384),64,"near"}); + w.push_back({"wide20",make_case("wide",16384,8,false,false,11,1048575),16,"none"}); + w.push_back({"wide25",make_case("wide",16384,8,false,false,11,33554431),16,"none"}); + } + time_workloads(w,"ref",samples,2097152); +} diff --git a/dev/perf/spf_queue/review-2026-10/early-exit.cpp b/dev/perf/spf_queue/review-2026-10/early-exit.cpp new file mode 100644 index 0000000..3e2619e --- /dev/null +++ b/dev/perf/spf_queue/review-2026-10/early-exit.cpp @@ -0,0 +1,8 @@ +#include "netgraph/core/shortest_paths.hpp" +#include +using namespace netgraph::core; +int main(){ + auto g=StrictMultiDiGraph::from_arrays(6,std::vector{0,0,2,0,0,4},std::vector{1,2,1,3,4,5},std::vector{1,10,10,10,10,10},std::vector{1,0,0,1,2,1}); + auto r=shortest_paths(g,0,3,true,EdgeSelection{}); + std::cout<<"target_cost="<(N)); + WorkspaceLease lease{ws}; ++ ws.touched.push_back(src); + ws.dist[static_cast(src)] = static_cast(0); + ws.min_res[static_cast(src)] = std::numeric_limits::max(); +- ws.touched.push_back(src); + BucketPlan plan; + if (use_bucket_queue(g, queue, plan)) { + run_forward(ws.bucket, ws, g, src, dst, multipath, selection, residual, node_mask, edge_mask, plan); +@@ -929,9 +929,9 @@ + WorkspaceLease lease{ws}; + + if (target_allowed) { ++ ws.touched.push_back(target); + ws.dist[static_cast(target)] = static_cast(0); + ws.min_res[static_cast(target)] = std::numeric_limits::max(); +- ws.touched.push_back(target); + BucketPlan plan; + if (use_bucket_queue(g, queue, plan)) { + run_reverse(ws.bucket, ws, g, target, multipath, selection, residual, node_mask, edge_mask, plan); diff --git a/dev/perf/spf_queue/review-2026-10/fault-public.cpp b/dev/perf/spf_queue/review-2026-10/fault-public.cpp new file mode 100644 index 0000000..7a89b53 --- /dev/null +++ b/dev/perf/spf_queue/review-2026-10/fault-public.cpp @@ -0,0 +1,30 @@ +#include +#include +#include +static bool fail_four = false; +void* operator new(std::size_t n) { + if (fail_four && n == 4) { fail_four=false; throw std::bad_alloc(); } + if (void* p=std::malloc(n?n:1)) return p; + throw std::bad_alloc(); +} +void operator delete(void* p) noexcept { std::free(p); } +#include "netgraph/core/shortest_paths.hpp" +using namespace netgraph::core; +int main(int argc,char**argv) { + std::string mode=argc>1?argv[1]:"fault"; + EdgeSelection sel; + if(mode=="fault") { + auto g=StrictMultiDiGraph::from_arrays(8,std::vector{1},std::vector{0},std::vector{1},std::vector{1}); + fail_four=true; + try { (void)shortest_paths(g,0,std::nullopt,true,sel); } + catch(const std::bad_alloc&) { std::cout<<"caught forward bad_alloc\n"; } + auto r=shortest_paths(g,1,std::nullopt,true,sel); + std::cout<<"forward distance[0]="<{0},std::vector{1},std::vector{1},std::vector{1}); + fail_four=true; + try { (void)shortest_paths_to(rev,0,true,sel); } + catch(const std::bad_alloc&) { std::cout<<"caught reverse bad_alloc\n"; } + auto t=shortest_paths_to(rev,1,true,sel); + std::cout<<"reverse distance[0]="<, PredDAG> path_result; ++ bool have_path_result = false; + while (true) { + EdgeSelection sel; + sel.multi_edge = true; + sel.require_capacity = require_capacity; + sel.tie_break = EdgeTieBreak::Deterministic; +- auto [dist, dag] = shortest_paths( ++ if (require_capacity || !have_path_result) { ++ path_result = shortest_paths( + g, src, dst, + /*multipath=*/true, + sel, + require_capacity ? fs.residual_view() : std::span{}, + use_node_mask ? node_mask : std::span{}, + use_edge_mask ? edge_mask : std::span{}); ++ have_path_result = true; ++ } ++ const auto& [dist, dag] = path_result; + + // No path if t has no parents in DAG + if (static_cast(dst) >= dag.parent_offsets.size() - 1 || +--- a/src/flow_state.cpp ++++ b/src/flow_state.cpp +@@ -535,14 +535,20 @@ + } + + Flow total = static_cast(0.0); ++ std::pair, PredDAG> path_result; ++ bool have_path_result = false; + while (true) { + EdgeSelection sel; + sel.multi_edge = true; + sel.require_capacity = require_capacity; + sel.tie_break = EdgeTieBreak::Deterministic; +- auto [dist, dag] = shortest_paths(*g_, src, dst, /*multipath=*/true, sel, ++ if (require_capacity || !have_path_result) { ++ path_result = shortest_paths(*g_, src, dst, /*multipath=*/true, sel, + require_capacity ? residual_ : std::span{}, + node_mask, edge_mask); ++ have_path_result = true; ++ } ++ const auto& [dist, dag] = path_result; + if (static_cast(dst) >= dag.parent_offsets.size()-1 || dag.parent_offsets[static_cast(dst)] == dag.parent_offsets[static_cast(dst)+1]) { + break; + } diff --git a/dev/perf/spf_queue/review-2026-10/flow-driver.cpp b/dev/perf/spf_queue/review-2026-10/flow-driver.cpp new file mode 100644 index 0000000..cf7fcb1 --- /dev/null +++ b/dev/perf/spf_queue/review-2026-10/flow-driver.cpp @@ -0,0 +1,30 @@ +#define main original_harness_main +#include "../harness.cpp" +#undef main +#include "netgraph/core/max_flow.hpp" +#include "netgraph/core/flow_state.hpp" +static void feasible(const StrictMultiDiGraph&g,NodeId s,NodeId t,double f,std::span ef) { + std::vector balance(g.num_nodes());auto src=g.edge_src_view();auto dst=g.edge_dst_view();auto cap=g.capacity_view(); + for(std::size_t e=0;ecap[e]+1e-7)throw std::runtime_error("capacity");balance[src[e]]+=ef[e];balance[dst[e]]-=ef[e];} + for(int v=0;v1e-6)throw std::runtime_error("conservation"); +} +int main() { + std::cout<<"case,median_ms,hash,samples_ms\n"; + for(bool masked:{false,true})for(bool state:{false,true}) { + auto c=make_case("random",4096,8,masked);std::vector samples;std::uint64_t hash=0; + for(int q=0;q<8;++q){c.node_mask[q*17]=true;c.node_mask[2048+q]=true;} + for(int rep=-2;rep<7;++rep){ + std::vector> out;out.reserve(8); + auto start=Clock::now(); + for(int q=0;q<8;++q){ + NodeId s=q*17,t=2048+q; + if(state){FlowState fs(c.graph);double f=fs.place_max_flow(s,t,FlowPlacement::Proportional,false,false,c.nm(),c.em());FlowSummary sm;sm.edge_flows.assign(fs.edge_flow_view().begin(),fs.edge_flow_view().end());out.emplace_back(f,std::move(sm));} + else out.push_back(calc_max_flow(c.graph,s,t,FlowPlacement::Proportional,false,false,true,false,false,c.nm(),c.em())); + } + auto elapsed=ms(start);std::uint64_t h=0; + for(int q=0;q<8;++q){auto&[f,sm]=out[q];feasible(c.graph,q*17,2048+q,f,sm.edge_flows);h=h*31+std::bit_cast(f);for(auto e:sm.edge_flows)h=h*31+std::bit_cast(e);for(auto e:sm.costs)h=h*31+e;for(auto e:sm.flows)h=h*31+std::bit_cast(e);} + if(rep==-2)hash=h;else if(hash!=h)throw std::runtime_error("changed output");if(rep>=0)samples.push_back(elapsed); + } + auto sorted=samples;std::sort(sorted.begin(),sorted.end());std::cout<<(state?"place_max_flow":"calc_max_flow")<<(masked?"_masked":"")<<','<(h.front()); } + QItem pop() { ++ QItem t = h.front(); + std::pop_heap(h.begin(), h.end(), Greater{}); +- QItem t = h.back(); h.pop_back(); return t; ++ h.pop_back(); return t; + } + void push(Cost c, Cap nr, NodeId v) { + h.emplace_back(c, nr, v); diff --git a/dev/perf/spf_queue/review-2026-10/gcd.cpp b/dev/perf/spf_queue/review-2026-10/gcd.cpp new file mode 100644 index 0000000..7c5ba12 --- /dev/null +++ b/dev/perf/spf_queue/review-2026-10/gcd.cpp @@ -0,0 +1,165 @@ +/* + StrictMultiDiGraph — immutable directed multigraph with deterministic layout. + + Construction from arrays validates inputs and builds CSR and reverse CSR + adjacency structures. Edges are reordered by (cost, src, dst) to cluster + equal-cost tiers for deterministic traversal. +*/ +#include "netgraph/core/strict_multidigraph.hpp" + +#include +#include +#include + +namespace netgraph::core { + +StrictMultiDiGraph StrictMultiDiGraph::from_arrays( + std::int32_t num_nodes, + std::span src, + std::span dst, + std::span capacity, + std::span cost, + std::span ext_edge_ids) { + + if (num_nodes < 0) { + throw std::invalid_argument("num_nodes must be >= 0"); + } + if (src.size() != dst.size() || src.size() != capacity.size() || src.size() != cost.size()) { + throw std::invalid_argument("src, dst, capacity, and cost must have the same length"); + } + if (!ext_edge_ids.empty() && ext_edge_ids.size() != src.size()) { + throw std::invalid_argument("ext_edge_ids must be empty or have the same length as src/dst/capacity/cost"); + } + StrictMultiDiGraph g; + g.num_nodes_ = num_nodes; + std::size_t m = src.size(); + if (m > static_cast(std::numeric_limits::max())) { + throw std::invalid_argument("number of edges exceeds INT32_MAX"); + } + + // Invariants: ids within [0, num_nodes), non-negative weights. + // SPF accumulates path costs as int64 without overflow checks and uses + // INT64_MAX as the unreachable sentinel, so the total of all edge costs + // (an upper bound on any simple path, and on one reverse-edge bounce) must + // stay below 2^62 or accumulated costs could wrap negative and silently + // corrupt results. + constexpr std::uint64_t kMaxTotalCost = (std::uint64_t{1} << 62); + std::uint64_t total_cost = 0; + Cost max_cost = 0; + Cost cost_gcd = 0; + for (std::size_t i = 0; i < m; ++i) { + if (src[i] < 0 || dst[i] < 0 || src[i] >= num_nodes || dst[i] >= num_nodes) { + throw std::out_of_range("edge index out of range of num_nodes"); + } + if (capacity[i] < 0.0) { + throw std::invalid_argument("capacity must be >= 0"); + } + if (cost[i] < 0) { throw std::invalid_argument("cost must be >= 0"); } + const auto c = static_cast(cost[i]); + if (c >= kMaxTotalCost - total_cost) { + throw std::invalid_argument( + "total edge cost must stay below 2^62: larger accumulated path costs " + "overflow int64 cost arithmetic and silently corrupt results"); + } + total_cost += c; + if (cost[i] > max_cost) max_cost = cost[i]; + if (cost_gcd != 1) cost_gcd = std::gcd(cost_gcd, cost[i]); + } + g.max_cost_ = max_cost; + g.cost_gcd_ = cost_gcd; + // Gather initial arrays + std::vector src_v(src.begin(), src.end()); + std::vector dst_v(dst.begin(), dst.end()); + std::vector cap_v(capacity.begin(), capacity.end()); + std::vector cost_v(cost.begin(), cost.end()); + std::vector ext_v; + if (!ext_edge_ids.empty()) { + ext_v.assign(ext_edge_ids.begin(), ext_edge_ids.end()); + } + + // Sort edges by (cost, src, dst) to cluster equal-cost tiers for deterministic traversal. + // Create an index array [0, 1, 2, ..., m-1] that we'll permute to define the reordering. + std::vector idx(m); + std::iota(idx.begin(), idx.end(), 0); // iota fills with sequential values + + // Cost-first ordering keeps equal-cost tiers clustered; within the same + // cost, maintain stable source/destination ordering for reproducibility. + // stable_sort preserves relative order of equal elements, ensuring determinism. + // Lambda comparator: [&] captures variables by reference, (a, b) are indices to compare. + std::stable_sort(idx.begin(), idx.end(), [&](std::size_t a, std::size_t b) { + if (cost_v[a] != cost_v[b]) return cost_v[a] < cost_v[b]; + if (src_v[a] != src_v[b]) return src_v[a] < src_v[b]; + return dst_v[a] < dst_v[b]; + }); + + // Reorder all edge arrays using the computed permutation. + // Generic lambda (auto parameters) works with any vector type. + auto apply_perm = [&](auto& out_vec, const auto& in_vec) { + out_vec.resize(m); + for (std::size_t i = 0; i < m; ++i) out_vec[i] = in_vec[idx[i]]; + }; + apply_perm(g.src_, src_v); + apply_perm(g.dst_, dst_v); + apply_perm(g.capacity_, cap_v); + apply_perm(g.cost_, cost_v); + if (!ext_v.empty()) { + apply_perm(g.ext_edge_ids_, ext_v); + } + g.edges_ = m; + + // Build CSR (Compressed Sparse Row) adjacency structure. + // For each node u, row_offsets_[u]:row_offsets_[u+1] gives the range in col_indices_ + // that stores u's outgoing neighbors, and adj_edge_index_ stores the corresponding EdgeIds. + + // Step 1: Count outgoing edges per node (histogram). + g.row_offsets_.assign(static_cast(num_nodes) + 1, 0); + for (std::size_t i = 0; i < m; ++i) { + g.row_offsets_[static_cast(g.src_[i]) + 1]++; + } + + // Step 2: Convert counts to cumulative offsets (prefix sum). + // row_offsets_[u] is the starting index for node u's adjacency list. + for (std::size_t i = 1; i < g.row_offsets_.size(); ++i) { + g.row_offsets_[i] += g.row_offsets_[i - 1]; + } + + // Step 3: Fill col_indices_ and adj_edge_index_ arrays. + g.col_indices_.resize(m); + g.adj_edge_index_.resize(m); + // cursor tracks the current write position for each node's adjacency list. + std::vector cursor = g.row_offsets_; // copy for in-place filling + for (std::size_t e = 0; e < m; ++e) { + auto u = g.src_[e]; + auto pos = static_cast(cursor[static_cast(u)]++); + g.col_indices_[pos] = g.dst_[e]; // neighbor node + g.adj_edge_index_[pos] = static_cast(e); // edge index + } + // Build reverse CSR (incoming adjacency) for predecessor tracking. + // Same CSR construction algorithm, but keyed by destination node instead of source. + // This enables efficient lookup of incoming edges for any node. + + // Step 1: Count incoming edges per node. + g.in_row_offsets_.assign(static_cast(num_nodes) + 1, 0); + for (std::size_t i = 0; i < m; ++i) { + g.in_row_offsets_[static_cast(g.dst_[i]) + 1]++; + } + + // Step 2: Convert counts to cumulative offsets. + for (std::size_t i = 1; i < g.in_row_offsets_.size(); ++i) { + g.in_row_offsets_[i] += g.in_row_offsets_[i - 1]; + } + + // Step 3: Fill reverse adjacency arrays. + g.in_col_indices_.resize(m); + g.in_adj_edge_index_.resize(m); + std::vector rcursor = g.in_row_offsets_; + for (std::size_t e = 0; e < m; ++e) { + auto v = g.dst_[e]; + auto pos = static_cast(rcursor[static_cast(v)]++); + g.in_col_indices_[pos] = g.src_[e]; // predecessor node + g.in_adj_edge_index_[pos] = static_cast(e); + } + return g; +} + +} // namespace netgraph::core diff --git a/dev/perf/spf_queue/review-2026-10/gcd.patch b/dev/perf/spf_queue/review-2026-10/gcd.patch new file mode 100644 index 0000000..44d24db --- /dev/null +++ b/dev/perf/spf_queue/review-2026-10/gcd.patch @@ -0,0 +1,11 @@ +--- a/src/strict_multidigraph.cpp ++++ b/src/strict_multidigraph.cpp +@@ -63,7 +63,7 @@ + } + total_cost += c; + if (cost[i] > max_cost) max_cost = cost[i]; +- cost_gcd = std::gcd(cost_gcd, cost[i]); ++ if (cost_gcd != 1) cost_gcd = std::gcd(cost_gcd, cost[i]); + } + g.max_cost_ = max_cost; + g.cost_gcd_ = cost_gcd; diff --git a/dev/perf/spf_queue/review-2026-10/heapitem.patch b/dev/perf/spf_queue/review-2026-10/heapitem.patch new file mode 100644 index 0000000..65e21b4 --- /dev/null +++ b/dev/perf/spf_queue/review-2026-10/heapitem.patch @@ -0,0 +1,26 @@ +--- a/src/shortest_paths.cpp ++++ b/src/shortest_paths.cpp +@@ -269,19 +269,20 @@ + constexpr Cost kInf = std::numeric_limits::max(); + constexpr std::size_t kMaxBucketWidth = std::size_t{1} << 16; + +-using QItem = std::tuple; ++struct QItem { Cost cost; Cap neg_res; NodeId node; }; ++ + + // Reference queue: binary heap on (cost, -bottleneck, node). Keys are unique per + // push (a node is re-pushed only with a strictly smaller cost or a strictly + // larger bottleneck), so the pop order is fully determined by the key. + struct HeapQueue { + // Functor, not a function pointer: std::push_heap / pop_heap inline it. +- struct Greater { bool operator()(const QItem& a, const QItem& b) const { return a > b; } }; ++ struct Greater { bool operator()(const QItem& a, const QItem& b) const { return a.cost != b.cost ? a.cost > b.cost : (a.neg_res != b.neg_res ? a.neg_res > b.neg_res : a.node > b.node); } }; + std::vector h; + void begin(std::size_t, Cost) { h.clear(); } + void end() { h.clear(); } + bool empty() const { return h.empty(); } +- Cost top_cost() const { return std::get<0>(h.front()); } ++ Cost top_cost() const { return h.front().cost; } + QItem pop() { + std::pop_heap(h.begin(), h.end(), Greater{}); + QItem t = h.back(); h.pop_back(); return t; diff --git a/dev/perf/spf_queue/review-2026-10/inline.patch b/dev/perf/spf_queue/review-2026-10/inline.patch new file mode 100644 index 0000000..11bf039 --- /dev/null +++ b/dev/perf/spf_queue/review-2026-10/inline.patch @@ -0,0 +1,70 @@ +--- a/src/shortest_paths.cpp ++++ b/src/shortest_paths.cpp +@@ -304,13 +304,15 @@ + std::vector occ; // one bit per non-empty bucket + std::size_t W = 0, cur_b = 0, pending = 0; + Cost cur = 0, stride = 1; ++ bool inline_item = false; ++ QItem single; + + void begin(std::size_t width, Cost stride_) { + stride = stride_; + W = width; + if (buckets.size() < W) buckets.resize(W); + occ.assign((W + 63) / 64, 0); +- cur = 0; cur_b = 0; pending = 0; ++ cur = 0; cur_b = 0; pending = 0; inline_item = false; + } + // Early exit can leave items behind; clear only the occupied buckets. + void end() { +@@ -323,20 +325,31 @@ + } + occ[w] = 0; + } +- pending = 0; ++ pending = 0; inline_item = false; + } + bool empty() const { return pending == 0; } + std::size_t bucket_of(Cost c) const { + const Cost q = stride == 1 ? c : c / stride; + return static_cast(q % static_cast(W)); + } +- void push(Cost c, Cap nr, NodeId v) { ++ void push_bucket(Cost c, Cap nr, NodeId v) { + const std::size_t b = bucket_of(c); + auto& vec = buckets[b]; + if (vec.empty()) occ[b >> 6] |= (std::uint64_t{1} << (b & 63)); + vec.push_back({nr, v}); + if (b == cur_b) std::push_heap(vec.begin(), vec.end(), Greater{}); + ++pending; ++ } ++ void push(Cost c, Cap nr, NodeId v) { ++ if (pending == 0) { ++ single = {c, nr, v}; inline_item = true; pending = 1; return; ++ } ++ if (inline_item) { ++ inline_item = false; pending = 0; ++ cur_b = bucket_of(cur); ++ push_bucket(std::get<0>(single), std::get<1>(single), std::get<2>(single)); ++ } ++ push_bucket(c, nr, v); + } + // Advance to the next non-empty bucket when the active one is exhausted. + // Precondition: pending > 0. +@@ -352,8 +365,15 @@ + cur += static_cast(steps) * stride; cur_b = f; + std::make_heap(buckets[f].begin(), buckets[f].end(), Greater{}); + } +- Cost top_cost() { settle_active(); return cur; } ++ Cost top_cost() { if (inline_item) return std::get<0>(single); settle_active(); return cur; } + QItem pop() { ++ if (inline_item) { ++ inline_item = false; pending = 0; ++ // Keep cursor tied to the last bucket activation. A later promotion ++ // must first restore the current absolute cost and cyclic index. ++ cur = std::get<0>(single); ++ return single; ++ } + settle_active(); + auto& vec = buckets[cur_b]; + std::pop_heap(vec.begin(), vec.end(), Greater{}); diff --git a/dev/perf/spf_queue/review-2026-10/notouch.patch b/dev/perf/spf_queue/review-2026-10/notouch.patch new file mode 100644 index 0000000..d89d905 --- /dev/null +++ b/dev/perf/spf_queue/review-2026-10/notouch.patch @@ -0,0 +1,29 @@ +--- a/src/shortest_paths.cpp ++++ b/src/shortest_paths.cpp +@@ -396,7 +396,7 @@ + // Shared reset policy: sparse when few nodes were touched, wholesale otherwise. + // The same predicate decides how outputs are materialised, so the two agree. + template +-bool sparse_reset(const WS& ws) { return ws.touched.size() * 4 < ws.dist.size(); } ++bool sparse_reset(const WS&) { return false; } + + template + void ensure_sized(Vec& v, std::size_t n, typename Vec::value_type init) { +@@ -644,7 +644,7 @@ + if (new_cost < dist[v_idx] || + (!multipath && new_cost == dist[v_idx] && !settled[v_idx] && + path_residual > min_residual_to_node[v_idx] + kEpsilon)) { +- if (dist[v_idx] == kInf) ws.touched.push_back(v); ++ + dist[v_idx] = new_cost; + min_residual_to_node[v_idx] = path_residual; + pred_clear(v_idx); +@@ -884,7 +884,7 @@ + if (new_cost < dist[u_idx] || + (!multipath && new_cost == dist[u_idx] && !settled[u_idx] && + path_residual > min_residual_to_dst[u_idx] + kEpsilon)) { +- if (dist[u_idx] == kInf) ws.touched.push_back(u); ++ + dist[u_idx] = new_cost; + min_residual_to_dst[u_idx] = path_residual; + succ_clear(u_idx); diff --git a/dev/perf/spf_queue/review-2026-10/results/append-c.csv b/dev/perf/spf_queue/review-2026-10/results/append-c.csv new file mode 100644 index 0000000..963e199 --- /dev/null +++ b/dev/perf/spf_queue/review-2026-10/results/append-c.csv @@ -0,0 +1,7 @@ +case,n,e,queries,dst,variant,fallback,W,median_ms,samples,wall_samples_ms +random16,16384,131072,16,none,ref,0,32,37.635792,7,38.207416;37.606375;37.612834;38.542167;37.918750;36.896417;37.635792 +clos800,800,320000,16,none,ref,0,2,31.158875,7,32.008042;31.218041;30.541250;31.576083;30.373084;30.469209;31.158875 +chain2048,2048,2047,256,none,ref,0,32,5.696250,7,5.622625;5.661208;5.606292;5.892458;6.009208;5.816542;5.696250 +near16,16384,131072,64,near,ref,0,32,0.406750,7,0.406542;0.404417;0.408167;0.406750;0.404791;0.409375;0.415750 +wide20,16384,131072,16,none,ref,0,1048570,54.188333,7,54.352083;54.185958;55.721250;54.188333;55.605583;52.820000;53.110667 +wide25,16384,131072,16,none,ref,1,33554196,51.991458,7,51.991458;51.997417;52.447250;52.295000;51.866917;51.883875;51.872750 diff --git a/dev/perf/spf_queue/review-2026-10/results/append.csv b/dev/perf/spf_queue/review-2026-10/results/append.csv new file mode 100644 index 0000000..6c8c744 --- /dev/null +++ b/dev/perf/spf_queue/review-2026-10/results/append.csv @@ -0,0 +1,7 @@ +case,n,e,queries,dst,variant,fallback,W,median_ms,samples,wall_samples_ms +random16,16384,131072,16,none,ref,0,32,35.207541,7,35.238625;35.097416;35.207541;35.161000;35.137917;35.443708;35.211333 +clos800,800,320000,16,none,ref,0,2,29.755084,7,29.659500;29.755084;30.265916;29.593917;29.666625;31.104000;31.114667 +chain2048,2048,2047,256,none,ref,0,32,5.591333,7,5.560791;5.577542;5.731958;5.845959;5.459833;5.591333;5.787625 +near16,16384,131072,64,near,ref,0,32,0.392125,7,0.392125;0.382834;0.387250;0.393375;0.392000;0.400333;0.393125 +wide20,16384,131072,16,none,ref,0,1048570,50.562958,7,50.479000;50.832333;50.819333;50.634875;50.442125;50.358042;50.562958 +wide25,16384,131072,16,none,ref,1,33554196,52.024125,7,53.655625;53.328708;52.807833;51.244209;52.024125;51.598250;50.987958 diff --git a/dev/perf/spf_queue/review-2026-10/results/bitgate-sha256.txt b/dev/perf/spf_queue/review-2026-10/results/bitgate-sha256.txt new file mode 100644 index 0000000..5c7d9c6 --- /dev/null +++ b/dev/perf/spf_queue/review-2026-10/results/bitgate-sha256.txt @@ -0,0 +1,2 @@ +a976f254eced152b14991ba2198351ec7983506f3f1e177c289852ec2bcaab90 dev/perf/spf_queue/review-2026-10/results/bitgate-old.txt +a976f254eced152b14991ba2198351ec7983506f3f1e177c289852ec2bcaab90 dev/perf/spf_queue/review-2026-10/results/bitgate-variant.txt diff --git a/dev/perf/spf_queue/review-2026-10/results/boundary-heap.csv b/dev/perf/spf_queue/review-2026-10/results/boundary-heap.csv new file mode 100644 index 0000000..9a39655 --- /dev/null +++ b/dev/perf/spf_queue/review-2026-10/results/boundary-heap.csv @@ -0,0 +1,15 @@ +case,n,e,queries,dst,variant,fallback,W,median_ms,samples,wall_samples_ms +wide32767,16384,131072,8,none,ref,0,32768,27.216125,7,28.146458;28.266458;27.100084;27.216125;27.213083;26.975083;27.599292 +near32767,16384,131072,64,near,ref,0,32768,0.395458,7,0.395458;0.391791;0.388500;0.389708;0.395542;0.395542;0.430625 +wide65534,16384,131072,8,none,ref,0,65535,26.349792,7,26.349792;26.298375;26.907792;26.210750;27.317625;26.253333;26.499417 +near65534,16384,131072,64,near,ref,0,65535,0.389917,7,0.389917;0.390083;0.388792;0.389791;0.390125;0.389750;0.392041 +wide65535,16384,131072,8,none,ref,0,65536,27.174750,7,27.377917;28.266584;26.928917;27.180500;27.174750;26.481250;26.367625 +near65535,16384,131072,64,near,ref,0,65536,0.398709,7,0.380667;0.395583;0.475958;0.724667;0.407708;0.398709;0.394125 +wide65536,16384,131072,8,none,ref,0,65537,26.865125,7,26.781208;26.649750;26.865125;26.975500;27.283250;26.901583;26.306791 +near65536,16384,131072,64,near,ref,0,65537,0.406292,7,0.406375;0.394000;0.394916;0.406292;0.400000;0.407583;0.407459 +wide131071,16384,131072,8,none,ref,0,131072,27.059250,7,26.298084;27.059250;27.075958;27.368333;26.491750;27.280125;26.502750 +near131071,16384,131072,64,near,ref,0,131072,0.389958,7,0.389833;0.389958;0.389042;0.388833;0.440458;0.397708;0.407625 +wide262143,16384,131072,8,none,ref,0,262144,26.460459,7,27.210333;26.460459;25.910166;26.587958;26.447375;27.095792;26.146417 +near262143,16384,131072,64,near,ref,0,262144,0.394750,7,0.394750;0.388334;0.404417;0.399833;0.397458;0.393167;0.393458 +wide1048575,16384,131072,8,none,ref,0,1048570,27.349042,7,27.048000;26.335291;26.375625;27.913125;29.361833;28.475000;27.349042 +near1048575,16384,131072,64,near,ref,0,1048570,0.441584,7,0.397750;0.396167;0.442500;0.448958;0.426250;0.453333;0.441584 diff --git a/dev/perf/spf_queue/review-2026-10/results/boundary-new1.csv b/dev/perf/spf_queue/review-2026-10/results/boundary-new1.csv new file mode 100644 index 0000000..5e16cdf --- /dev/null +++ b/dev/perf/spf_queue/review-2026-10/results/boundary-new1.csv @@ -0,0 +1,15 @@ +case,n,e,queries,dst,variant,fallback,W,median_ms,samples,wall_samples_ms +wide32767,16384,131072,8,none,ref,0,32768,17.627750,7,17.467708;17.788917;17.774958;17.912958;17.627750;17.498041;17.571250 +near32767,16384,131072,64,near,ref,0,32768,0.420792,7,0.420792;0.418875;0.419792;0.424292;0.422000;0.419125;0.450750 +wide65534,16384,131072,8,none,ref,0,65535,18.146791,7,17.373209;18.146791;17.820625;18.424875;18.379041;19.409584;18.128625 +near65534,16384,131072,64,near,ref,0,65535,0.455083,7,0.485750;0.434000;0.433791;0.455083;0.460917;0.459959;0.449458 +wide65535,16384,131072,8,none,ref,0,65536,18.499458,7,18.164084;21.170541;19.691125;18.580833;18.453917;18.499458;17.288917 +near65535,16384,131072,64,near,ref,0,65536,0.434500,7,0.439750;0.494458;0.464708;0.432375;0.434500;0.431833;0.431417 +wide65536,16384,131072,8,none,ref,0,65537,26.490750,7,26.255750;27.382208;26.490750;26.883292;26.491833;26.317709;26.318292 +near65536,16384,131072,64,near,ref,0,65537,0.413542,7,0.413542;0.412375;0.412042;0.422792;0.530541;0.414708;0.412959 +wide131071,16384,131072,8,none,ref,0,131072,26.303167,7,26.388291;26.303167;26.215125;26.181541;26.688667;26.346208;26.260875 +near131071,16384,131072,64,near,ref,0,131072,0.411958,7,0.412792;0.411958;0.412542;0.411333;0.411958;0.413125;0.411833 +wide262143,16384,131072,8,none,ref,0,262144,27.104375,7,27.291750;28.251584;27.074000;27.684125;26.756209;26.675708;27.104375 +near262143,16384,131072,64,near,ref,0,262144,0.418458,7,0.422875;0.416291;0.412375;0.411208;0.418458;0.418916;0.535708 +wide1048575,16384,131072,8,none,ref,0,1048570,27.498000,7,28.209334;26.654250;27.265667;27.498000;28.699583;27.445416;27.548208 +near1048575,16384,131072,64,near,ref,0,1048570,0.419458,7,0.412292;0.409958;0.438000;0.465000;0.417958;0.419458;0.420875 diff --git a/dev/perf/spf_queue/review-2026-10/results/boundary-old1.csv b/dev/perf/spf_queue/review-2026-10/results/boundary-old1.csv new file mode 100644 index 0000000..cf301c2 --- /dev/null +++ b/dev/perf/spf_queue/review-2026-10/results/boundary-old1.csv @@ -0,0 +1,15 @@ +case,n,e,queries,dst,variant,fallback,W,median_ms,samples,wall_samples_ms +wide32767,16384,131072,8,none,ref,0,32768,25.959000,7,25.920750;25.994708;26.018958;25.959000;25.868584;25.998833;25.945334 +near32767,16384,131072,64,near,ref,0,32768,1.123792,7,1.123792;1.143875;1.312083;1.174542;1.120500;1.118458;1.117542 +wide65534,16384,131072,8,none,ref,0,65535,25.432833,7,25.434417;25.484792;25.432833;25.497625;25.411417;25.386000;25.402792 +near65534,16384,131072,64,near,ref,0,65535,1.131375,7,1.134792;1.131375;1.126750;1.150958;1.130917;1.142292;1.127750 +wide65535,16384,131072,8,none,ref,0,65536,25.641458,7,26.183459;25.641458;25.704083;25.475583;25.608166;26.744875;25.582750 +near65535,16384,131072,64,near,ref,0,65536,1.171208,7,1.171375;1.171208;1.144834;1.162584;1.129458;1.229166;1.239417 +wide65536,16384,131072,8,none,ref,0,65537,25.659250,7,25.589125;25.567500;25.659250;25.878333;25.921041;25.928000;25.645167 +near65536,16384,131072,64,near,ref,0,65537,1.172500,7,1.195500;1.233375;1.134375;1.126542;1.172500;1.192833;1.132958 +wide131071,16384,131072,8,none,ref,0,131072,25.524916,7,25.363959;26.327625;25.538041;25.349375;25.411375;25.524916;25.594667 +near131071,16384,131072,64,near,ref,0,131072,1.128166,7,1.148709;1.154292;1.137500;1.125667;1.128166;1.125709;1.125333 +wide262143,16384,131072,8,none,ref,0,262144,25.191500,7,25.191500;25.104833;25.250792;25.137333;25.226084;25.305292;25.094250 +near262143,16384,131072,64,near,ref,0,262144,1.129625,7,1.129625;1.127042;1.123833;1.136125;1.134375;1.128792;1.140958 +wide1048575,16384,131072,8,none,ref,0,1048570,25.106542,7,25.123750;24.851209;25.116375;25.106542;25.039958;24.997625;25.230250 +near1048575,16384,131072,64,near,ref,0,1048570,1.142375,7,1.179875;1.140000;1.142375;1.240625;1.144541;1.120459;1.122583 diff --git a/dev/perf/spf_queue/review-2026-10/results/boundary-old2.csv b/dev/perf/spf_queue/review-2026-10/results/boundary-old2.csv new file mode 100644 index 0000000..f00beda --- /dev/null +++ b/dev/perf/spf_queue/review-2026-10/results/boundary-old2.csv @@ -0,0 +1,15 @@ +case,n,e,queries,dst,variant,fallback,W,median_ms,samples,wall_samples_ms +wide32767,16384,131072,8,none,ref,0,32768,26.271750,7,26.301167;26.686875;26.371917;26.255292;26.271750;26.190042;26.068333 +near32767,16384,131072,64,near,ref,0,32768,1.136167,7,1.182583;1.136167;1.135125;1.136917;1.135708;1.133125;1.143458 +wide65534,16384,131072,8,none,ref,0,65535,25.761125,7,25.856750;26.884209;26.271416;25.761125;25.596167;25.732250;25.505250 +near65534,16384,131072,64,near,ref,0,65535,1.122666,7,1.153667;1.121250;1.114917;1.114459;1.201875;1.122666;1.176334 +wide65535,16384,131072,8,none,ref,0,65536,26.609084,7,26.609084;26.286708;26.560916;27.546417;26.013458;26.998000;27.639542 +near65535,16384,131072,64,near,ref,0,65536,1.149334,7,1.201292;1.135834;1.149334;1.146417;1.154333;1.138625;1.189833 +wide65536,16384,131072,8,none,ref,0,65537,25.453542,7,25.453542;25.423167;25.036875;25.191000;25.708125;26.894000;26.066042 +near65536,16384,131072,64,near,ref,0,65537,1.156958,7,1.140209;1.261541;1.156958;1.205750;1.184833;1.146458;1.149083 +wide131071,16384,131072,8,none,ref,0,131072,25.179291,7,25.184625;25.557708;25.030125;25.059708;25.179291;25.229375;25.011292 +near131071,16384,131072,64,near,ref,0,131072,1.118291,7,1.117792;1.129750;1.117000;1.118291;1.116959;1.148750;1.128125 +wide262143,16384,131072,8,none,ref,0,262144,25.164583,7,25.164583;24.947750;24.892708;25.117916;25.187125;26.459750;25.999500 +near262143,16384,131072,64,near,ref,0,262144,1.178209,7,1.201500;1.223667;1.178209;1.121833;1.120084;1.119375;1.190333 +wide1048575,16384,131072,8,none,ref,0,1048570,25.150958,7,25.270875;25.395917;25.150958;25.117542;25.158292;24.994500;25.007375 +near1048575,16384,131072,64,near,ref,0,1048570,1.136750,7,1.179000;1.136750;1.121125;1.119167;1.150625;1.138500;1.136375 diff --git a/dev/perf/spf_queue/review-2026-10/results/boundary-settled.csv b/dev/perf/spf_queue/review-2026-10/results/boundary-settled.csv new file mode 100644 index 0000000..b638446 --- /dev/null +++ b/dev/perf/spf_queue/review-2026-10/results/boundary-settled.csv @@ -0,0 +1,15 @@ +case,n,e,queries,dst,variant,fallback,W,median_ms,samples,wall_samples_ms +wide32767,16384,131072,8,none,ref,0,32768,17.436917,7,19.366000;17.364333;17.382625;16.994875;17.436917;19.600291;17.841792 +near32767,16384,131072,64,near,ref,0,32768,0.414458,7,0.420208;0.413459;0.413458;0.414458;0.832042;0.430917;0.412333 +wide65534,16384,131072,8,none,ref,0,65535,18.717125,7,18.717125;17.463917;17.628958;16.499875;19.448833;19.348125;18.993583 +near65534,16384,131072,64,near,ref,0,65535,0.471833,7,0.493834;0.480708;0.470208;0.470625;0.483500;0.471833;0.470708 +wide65535,16384,131072,8,none,ref,0,65536,19.366166,7,19.366166;18.572250;17.788084;20.007792;20.720959;19.390792;18.908375 +near65535,16384,131072,64,near,ref,0,65536,0.465041,7,0.479500;0.518542;0.465041;0.484917;0.464042;0.451834;0.450375 +wide65536,16384,131072,8,none,ref,0,65537,27.207833,7,27.207833;26.963750;27.583833;27.970459;26.963125;26.581584;27.401875 +near65536,16384,131072,64,near,ref,0,65537,0.406500,7,0.407208;0.407375;0.406209;0.406166;0.406500;0.407334;0.406125 +wide131071,16384,131072,8,none,ref,0,131072,26.218208,7,26.337125;26.079042;26.577292;25.786125;26.615584;26.218208;25.834875 +near131071,16384,131072,64,near,ref,0,131072,0.426083,7,0.506875;0.455750;0.429416;0.426083;0.425041;0.424834;0.424500 +wide262143,16384,131072,8,none,ref,0,262144,26.430375,7,26.452084;26.167375;26.274000;26.541625;26.430375;26.457833;25.998250 +near262143,16384,131072,64,near,ref,0,262144,0.431250,7,0.424125;0.431250;0.422500;0.435792;0.450667;0.437833;0.425791 +wide1048575,16384,131072,8,none,ref,0,1048570,26.015250,7,26.626792;26.934209;25.769292;26.277167;25.513209;25.970167;26.015250 +near1048575,16384,131072,64,near,ref,0,1048570,0.428000,7,0.466750;0.462792;0.421166;0.426500;0.419584;0.436417;0.428000 diff --git a/dev/perf/spf_queue/review-2026-10/results/build-gcd.csv b/dev/perf/spf_queue/review-2026-10/results/build-gcd.csv new file mode 100644 index 0000000..c795d2b --- /dev/null +++ b/dev/perf/spf_queue/review-2026-10/results/build-gcd.csv @@ -0,0 +1,2 @@ +random,9.12225,12169309226976897007,9.0255;9.29696;9.24317;8.97583;9.07829;9.15029;9.33504;9.12225;9.08346; +ordered,1.36387,16379939557917917184,1.34192;1.37963;1.37363;1.36387;1.37554;1.36342;1.36637;1.19475;1.25596; diff --git a/dev/perf/spf_queue/review-2026-10/results/build-new1.csv b/dev/perf/spf_queue/review-2026-10/results/build-new1.csv new file mode 100644 index 0000000..b5b70f2 --- /dev/null +++ b/dev/perf/spf_queue/review-2026-10/results/build-new1.csv @@ -0,0 +1,2 @@ +random,9.16392,12169309226976897007,9.23296;9.28317;9.09125;9.15975;9.1805;9.07479;9.11642;9.16392;9.2345; +ordered,1.42971,16379939557917917184,1.42;1.42271;1.45396;1.44892;1.53179;1.43958;1.42463;1.426;1.42971; diff --git a/dev/perf/spf_queue/review-2026-10/results/build-new2.csv b/dev/perf/spf_queue/review-2026-10/results/build-new2.csv new file mode 100644 index 0000000..ace6a92 --- /dev/null +++ b/dev/perf/spf_queue/review-2026-10/results/build-new2.csv @@ -0,0 +1,2 @@ +random,9.28858,12169309226976897007,9.44521;9.57671;9.38425;9.28858;9.21017;9.27567;9.307;9.17375;9.10067; +ordered,1.44796,16379939557917917184,1.57033;1.44246;1.42517;1.44796;1.47513;1.44875;1.70025;1.44121;1.43358; diff --git a/dev/perf/spf_queue/review-2026-10/results/build-old1.csv b/dev/perf/spf_queue/review-2026-10/results/build-old1.csv new file mode 100644 index 0000000..a4b41de --- /dev/null +++ b/dev/perf/spf_queue/review-2026-10/results/build-old1.csv @@ -0,0 +1,2 @@ +random,9.06046,12169309226976897007,9.02929;9.15596;9.06567;9.11125;8.99808;9.17017;9.01704;9.06046;9.05; +ordered,1.34379,16379939557917917184,1.39417;1.32854;1.34379;1.32638;1.35642;1.32892;1.32942;1.44129;1.37017; diff --git a/dev/perf/spf_queue/review-2026-10/results/build-old2.csv b/dev/perf/spf_queue/review-2026-10/results/build-old2.csv new file mode 100644 index 0000000..c1d84c0 --- /dev/null +++ b/dev/perf/spf_queue/review-2026-10/results/build-old2.csv @@ -0,0 +1,2 @@ +random,9.13721,12169309226976897007,9.37308;9.16767;9.17583;9.13721;8.98692;9.06342;9.17796;9.13525;9.11583; +ordered,1.37433,16379939557917917184,1.37433;1.36271;1.41938;1.37692;1.36771;1.36867;1.39604;1.38129;1.36892; diff --git a/dev/perf/spf_queue/review-2026-10/results/build-repeat-gcd.csv b/dev/perf/spf_queue/review-2026-10/results/build-repeat-gcd.csv new file mode 100644 index 0000000..1dabbeb --- /dev/null +++ b/dev/perf/spf_queue/review-2026-10/results/build-repeat-gcd.csv @@ -0,0 +1,2 @@ +random,9.32917,12169309226976897007,9.33104;9.60546;8.98971;9.32917;10.0803;9.30875;9.5125;9.26842;9.25737; +ordered,1.41108,16379939557917917184,1.43392;1.41154;1.40246;1.41108;1.4155;1.43271;1.39921;1.30079;1.30358; diff --git a/dev/perf/spf_queue/review-2026-10/results/build-repeat-new1.csv b/dev/perf/spf_queue/review-2026-10/results/build-repeat-new1.csv new file mode 100644 index 0000000..ed3fe22 --- /dev/null +++ b/dev/perf/spf_queue/review-2026-10/results/build-repeat-new1.csv @@ -0,0 +1,2 @@ +random,9.38404,12169309226976897007,9.69817;9.4765;9.30413;9.89342;9.32408;9.525;9.38404;9.29583;9.32975; +ordered,1.44821,16379939557917917184,1.45875;1.44821;1.47833;1.41417;1.46692;1.45879;1.42346;1.42167;1.43983; diff --git a/dev/perf/spf_queue/review-2026-10/results/build-repeat-new2.csv b/dev/perf/spf_queue/review-2026-10/results/build-repeat-new2.csv new file mode 100644 index 0000000..ab39ff6 --- /dev/null +++ b/dev/perf/spf_queue/review-2026-10/results/build-repeat-new2.csv @@ -0,0 +1,2 @@ +random,9.31475,12169309226976897007,9.33629;9.25583;9.40537;9.58625;9.47825;9.30892;9.31475;9.11708;9.164; +ordered,1.45571,16379939557917917184,1.48362;1.41492;1.42183;1.41204;1.48937;1.45629;1.49546;1.45571;1.42967; diff --git a/dev/perf/spf_queue/review-2026-10/results/combined.csv b/dev/perf/spf_queue/review-2026-10/results/combined.csv new file mode 100644 index 0000000..ff1c4cf --- /dev/null +++ b/dev/perf/spf_queue/review-2026-10/results/combined.csv @@ -0,0 +1,7 @@ +case,n,e,queries,dst,variant,fallback,W,median_ms,samples,wall_samples_ms +random16,16384,131072,16,none,ref,0,32,36.724875,7,36.876459;36.764792;36.888208;36.207875;36.669584;36.724875;36.502542 +clos800,800,320000,16,none,ref,0,2,26.326583,7,26.326583;26.456250;26.174583;26.294958;25.905208;26.594291;26.357125 +chain2048,2048,2047,256,none,ref,0,32,5.749834,7,6.107542;5.749834;5.632792;5.484209;5.450416;6.257625;5.891458 +near16,16384,131072,64,near,ref,0,32,0.392708,7,0.396208;0.393666;0.392583;0.392000;0.393166;0.392708;0.392458 +wide20,16384,131072,16,none,ref,0,1048570,52.384667,7,51.748375;52.904292;52.384667;52.881667;52.289333;52.270334;52.416291 +wide25,16384,131072,16,none,ref,1,33554196,52.605833,7,52.605833;51.553042;52.051292;53.022542;52.452708;57.664459;52.894334 diff --git a/dev/perf/spf_queue/review-2026-10/results/correctness-append.txt b/dev/perf/spf_queue/review-2026-10/results/correctness-append.txt new file mode 100644 index 0000000..24d6ed9 --- /dev/null +++ b/dev/perf/spf_queue/review-2026-10/results/correctness-append.txt @@ -0,0 +1 @@ +checked=1351168 failed=0 diff --git a/dev/perf/spf_queue/review-2026-10/results/correctness-baseline.txt b/dev/perf/spf_queue/review-2026-10/results/correctness-baseline.txt new file mode 100644 index 0000000..24d6ed9 --- /dev/null +++ b/dev/perf/spf_queue/review-2026-10/results/correctness-baseline.txt @@ -0,0 +1 @@ +checked=1351168 failed=0 diff --git a/dev/perf/spf_queue/review-2026-10/results/correctness-inline.txt b/dev/perf/spf_queue/review-2026-10/results/correctness-inline.txt new file mode 100644 index 0000000..24d6ed9 --- /dev/null +++ b/dev/perf/spf_queue/review-2026-10/results/correctness-inline.txt @@ -0,0 +1 @@ +checked=1351168 failed=0 diff --git a/dev/perf/spf_queue/review-2026-10/results/correctness-settled.txt b/dev/perf/spf_queue/review-2026-10/results/correctness-settled.txt new file mode 100644 index 0000000..24d6ed9 --- /dev/null +++ b/dev/perf/spf_queue/review-2026-10/results/correctness-settled.txt @@ -0,0 +1 @@ +checked=1351168 failed=0 diff --git a/dev/perf/spf_queue/review-2026-10/results/early-new.txt b/dev/perf/spf_queue/review-2026-10/results/early-new.txt new file mode 100644 index 0000000..e4ba7ee --- /dev/null +++ b/dev/perf/spf_queue/review-2026-10/results/early-new.txt @@ -0,0 +1 @@ +target_cost=1 beyond_target_cost=3 (node 5 requires expanding distance-2 node 4) diff --git a/dev/perf/spf_queue/review-2026-10/results/early-old.txt b/dev/perf/spf_queue/review-2026-10/results/early-old.txt new file mode 100644 index 0000000..e4ba7ee --- /dev/null +++ b/dev/perf/spf_queue/review-2026-10/results/early-old.txt @@ -0,0 +1 @@ +target_cost=1 beyond_target_cost=3 (node 5 requires expanding distance-2 node 4) diff --git a/dev/perf/spf_queue/review-2026-10/results/environment.txt b/dev/perf/spf_queue/review-2026-10/results/environment.txt new file mode 100644 index 0000000..b12a313 --- /dev/null +++ b/dev/perf/spf_queue/review-2026-10/results/environment.txt @@ -0,0 +1,17 @@ +Fri Oct 2 01:24:25 UTC 2026 +Darwin mbp_andrey.lan 25.6.0 Darwin Kernel Version 25.6.0: Sat Jul 11 15:27:27 PDT 2026; root:xnu-12377.161.13~4/RELEASE_ARM64_T6041 arm64 +Apple M4 Max +fbab119e794c843838f4f3f96d75cb7f32f06845 +Apple clang version 21.0.0 (clang-2100.1.1.101) +Target: arm64-apple-darwin25.6.0 +Thread model: posix +InstalledDir: /Library/Developer/CommandLineTools/usr/bin +08a76164496831181942b976ef2b2034a506df7e530853db315cd6cf956408ac build/perf/review-settled +d7aa874e4b7dfde3ed53eabf644cb8e6a73a0581638f771276ab2c851b5580c3 build/perf/review-old +c27c21e0446c0b07881cd2ab671b3ae46978082571c88a0860e71e7d920fb26d build/perf/review-singleton +493c12c969ecb87fb753796cbae177fb6214db988197fcea5eb72404e38338cc build/perf/review-heapitem +7452d40d922869ca2ea3d1f0e0f46088f57b5a01782f9c5200dd8b5ada71855f build/perf/review-notouch +e48e8976f1a0dea1c4bd6edfdd1a4490b7a5e00b40892871a1580ae5680c5106 build/perf/review-baseline +c0b0cb4d010a706f6c545cfb716fd21e10c3ed0aee4ecec7b346eeb9f9eb7ffc build/perf/cpu-queue +4e717d373d97fd2789b2292529646d4f81353c8ba205e384c818f121d4cbe167 build/perf/cpu-queue-old +aa1437b6e04447662c521979eb68b23a354447f634e777442c2dc72404f5bce7 src/shortest_paths.cpp diff --git a/dev/perf/spf_queue/review-2026-10/results/fault-fixed.txt b/dev/perf/spf_queue/review-2026-10/results/fault-fixed.txt new file mode 100644 index 0000000..4157487 --- /dev/null +++ b/dev/perf/spf_queue/review-2026-10/results/fault-fixed.txt @@ -0,0 +1,4 @@ +caught forward bad_alloc +forward distance[0]=1 expected=1 +caught reverse bad_alloc +reverse distance[0]=1 expected=1 diff --git a/dev/perf/spf_queue/review-2026-10/results/fault-old.txt b/dev/perf/spf_queue/review-2026-10/results/fault-old.txt new file mode 100644 index 0000000..4157487 --- /dev/null +++ b/dev/perf/spf_queue/review-2026-10/results/fault-old.txt @@ -0,0 +1,4 @@ +caught forward bad_alloc +forward distance[0]=1 expected=1 +caught reverse bad_alloc +reverse distance[0]=1 expected=1 diff --git a/dev/perf/spf_queue/review-2026-10/results/fault.txt b/dev/perf/spf_queue/review-2026-10/results/fault.txt new file mode 100644 index 0000000..7043974 --- /dev/null +++ b/dev/perf/spf_queue/review-2026-10/results/fault.txt @@ -0,0 +1,4 @@ +caught forward bad_alloc +forward distance[0]=9223372036854775807 expected=1 +caught reverse bad_alloc +reverse distance[0]=9223372036854775807 expected=1 diff --git a/dev/perf/spf_queue/review-2026-10/results/final-sha256.txt b/dev/perf/spf_queue/review-2026-10/results/final-sha256.txt new file mode 100644 index 0000000..e4b68e8 --- /dev/null +++ b/dev/perf/spf_queue/review-2026-10/results/final-sha256.txt @@ -0,0 +1,68 @@ +2744894b016d205e8c2d27124702b8584a16c01768d0b478e43ddda37133118b build/perf/review-append +e48e8976f1a0dea1c4bd6edfdd1a4490b7a5e00b40892871a1580ae5680c5106 build/perf/review-baseline +f1930794735764cb2d83f93c3cb5fb3cea0bfaaa631cf6b35939054e95a80b87 build/perf/review-build-baseline +aca82c7a96944ea868506171cb3ecceb62d31555b927ab5aae5233fa1bcafea2 build/perf/review-build-gcd +0dbb455ca3bc0d9fc1cc73ee2ddf9ef88f06634b4d138a0dcf242ba778d9f9c4 build/perf/review-build-old +7cb163b801210c385d0b058833a977b09c0ce2061ea2b6755ddd51064fc5869a build/perf/review-combined +a4685d608080bbac1904e2884fc306a9de971129c8d4098691c061d77e50fb76 build/perf/review-early-new +b7f45fc227bc8df3679ba26d210ebb682f219d582296c8af8becc29d671a492d build/perf/review-early-old +35eb0e8a822b977e66c8fb3620c6c5cc15674e5eccee1220d2a46f2a5cd057bc build/perf/review-fault-old +a53a8436f40ec23a1bf1b6e8bd78d6e3536943a534a7d72e445520130f778d77 build/perf/review-flow-fixed +b95d95d88924ec47a404225c80fcc2757759cfdc6c1466612516abb76dbffa93 build/perf/review-flow-new +d556b4d468a45f5334bb27a460368aede0da75ab3d2188b37c851a33a05f8a8f build/perf/review-flow-old +789be1de40247f35ef8303a017a2e7f93c42ac78cfbc17738f4ac16a37837bb8 build/perf/review-frontpop +493c12c969ecb87fb753796cbae177fb6214db988197fcea5eb72404e38338cc build/perf/review-heapitem +e4611d037e1fdc92d5dd837f6cc5226b6c268b6671a2275429fd6f80c35e00e9 build/perf/review-inline +7452d40d922869ca2ea3d1f0e0f46088f57b5a01782f9c5200dd8b5ada71855f build/perf/review-notouch +d7aa874e4b7dfde3ed53eabf644cb8e6a73a0581638f771276ab2c851b5580c3 build/perf/review-old +caa9b636764606a8756cd1c24a4690d70d83d72270fd9c1907b67e94f029b696 build/perf/review-robustness +41f68d6f39296328c681c924ba430805a5a2703deed661f2237687b6bbbd7cd0 build/perf/review-robustness-fixed +41eccdff5c751acb75678bd0981afc84ee3f57666a7f5b733f2816c9a7274a7a build/perf/review-safety +08a76164496831181942b976ef2b2034a506df7e530853db315cd6cf956408ac build/perf/review-settled +c27c21e0446c0b07881cd2ab671b3ae46978082571c88a0860e71e7d920fb26d build/perf/review-singleton +f3aa9f51f195b98adb2d88e5df7cc55f34393b33c455b98e1fb94f2a1787419f dev/perf/spf_queue/review-2026-10/BRIEF.md +2adfec05029ff96cf16f4d286ec29cb81859914712d1a6e4f87a12f6e70f9274 dev/perf/spf_queue/review-2026-10/append.cpp +4a92134cff8baddcbf0eca4193b478d66414a90ac409b943372fb4a46d755e51 dev/perf/spf_queue/review-2026-10/append.patch +aa1437b6e04447662c521979eb68b23a354447f634e777442c2dc72404f5bce7 dev/perf/spf_queue/review-2026-10/baseline.cpp +480fd230f8603af15aa2f9c9ff454806552bd94c7fb88c1395c6f428a666fd54 dev/perf/spf_queue/review-2026-10/build-flow.sh +29b4e6cbdaa87570899c474aed6dad8a20beab19195c8f99a2bcaa28335811b0 dev/perf/spf_queue/review-2026-10/build-review.sh +2a991bae311206a2e4bf48d1fae14c5eebdb15b38cae0e7ed1c5278e09fc24c5 dev/perf/spf_queue/review-2026-10/change.diff +baaa96908abd5cff5dd46e1e3a19d715c7728adedede93e6af5c9cc648f67e0c dev/perf/spf_queue/review-2026-10/check-and-build.sh +1abad31a13aa7bddb492fd9331c42157f98969348773e6898fcc39bce77dd126 dev/perf/spf_queue/review-2026-10/combined.cpp +8a3515790228359aac4a25517843bad6eecf00c6bb5815ed663a3fdbe96bff64 dev/perf/spf_queue/review-2026-10/combined.patch +ef9941c043378591c5a772c7b179fe107fd3c96f64e28939f3741d5fe73f4df4 dev/perf/spf_queue/review-2026-10/construction.cpp +9138f40c0f91b6c8bc769d75aa99d6099639f7798a5373478c09278ccc6c21bf dev/perf/spf_queue/review-2026-10/driver.cpp +edca624df600d7757020c7b73869d1c79469a2c28e75f4e0f59264d401f6e298 dev/perf/spf_queue/review-2026-10/early-exit.cpp +9a57d0e6cb308ff744f6ccfc5adbf7ec96d79304453a34d45db91c1b2dbb7827 dev/perf/spf_queue/review-2026-10/exception-fix.cpp +43f1a4a9f49eaaf4e5a048c554f628110c45c1d80208d1de4b112029ca7886e9 dev/perf/spf_queue/review-2026-10/exception-fix.patch +2ef1bcd3a030c446bb0741ea6a717ec53d1e8ea5ae8da1d6301ef0b97fb7bcd8 dev/perf/spf_queue/review-2026-10/fault-public.cpp +1b29d98b499beddb38a42c9d0629418566e2e170737e6b43d3a3875a49b744e3 dev/perf/spf_queue/review-2026-10/fixed-routing.patch +28fb9c4871b23f802fcf31263743d9d42bedf14e1572e7ccc84310056758b194 dev/perf/spf_queue/review-2026-10/flow-driver.cpp +6b3587eddb0d2400b175a6e202eb76c90eefe18faab7d9e282d0d4f3fa1f52b3 dev/perf/spf_queue/review-2026-10/flow_state-fixed.cpp +ae6027fe3b7ed96e1d2a521049cc477c9a4525c43e2a7f35d7359a3d984a48b0 dev/perf/spf_queue/review-2026-10/frontpop.cpp +01ddb2f04a7a9fe09527ae775922e583a5dc601b93e555390bfbfc4b8d518e5d dev/perf/spf_queue/review-2026-10/frontpop.patch +afbc777de4ffb05584d07e23068af20ac757df393a046d912933547a66a54d11 dev/perf/spf_queue/review-2026-10/gcd.cpp +82c08c66f360d85f1c3fd22d5d025fee9e79b8d8e0c6cddc1694173121c8cc0b dev/perf/spf_queue/review-2026-10/gcd.patch +d24fc5af1fe919e9253d4c04c72f3e47cdcc494053e408d370dbadf1d1154bdc dev/perf/spf_queue/review-2026-10/heapitem.cpp +5773f710a5da67c058d1b6315f239f9f6f7593fafe2c42d5fc21ade73c56b7af dev/perf/spf_queue/review-2026-10/heapitem.patch +aab2c327bcc7312c07b8f8bc2bc02a2f21ec22e8978eb08a3dc9f4464e6518bf dev/perf/spf_queue/review-2026-10/inline.cpp +6e412d05382b923d1a8e8cc82a2ecc9c5e0a4aa6419ba2be4c2df2317ac747c5 dev/perf/spf_queue/review-2026-10/inline.patch +48aea198eac88fbc9e0cfa67192038b82dcdffd13c6e42fcf011455cc83231b4 dev/perf/spf_queue/review-2026-10/max_flow-fixed.cpp +7411f13155b1afc714eb53d14929c4a251f6ea1666eacaf35d166fc674430337 dev/perf/spf_queue/review-2026-10/notouch.cpp +4d8e57e6fb155c47713e98c02ff6f0aeeaf96bfdd9edb1b2f11c2c8d5f7dfdc4 dev/perf/spf_queue/review-2026-10/notouch.patch +9ee6053d38a0b1e44df958e423e12ab93fb54c3d80c8d4bcb623730362b8f441 dev/perf/spf_queue/review-2026-10/old-shortest_paths.cpp +12f65bdc8daa9415d118d062bdc897981bde448f5391bed2c711c8c968e9322b dev/perf/spf_queue/review-2026-10/old-strict_multidigraph.cpp +d24c175f74cf132b695beceb419cadcada130fbd6b90d2d1583ded5676ce4532 dev/perf/spf_queue/review-2026-10/robustness.cpp +bc9620bc27580072f6836f916a6388c4a7da6b17086e4f38a497b59f1a82fbf8 dev/perf/spf_queue/review-2026-10/run-netgraph-review.py +bd8575eb91dbf5e72bac1c490e38fb5a5de39175562d1972843ab940d5c04ebd dev/perf/spf_queue/review-2026-10/run-review.py +e7641bf19905876035df281a69b09819c2ac8a6d044f23cfdfa8fc73e7352673 dev/perf/spf_queue/review-2026-10/run-second.py +2c32450294701cd948f0a093c03df129e0046dcdf2f8a5a27c445f50b78ebac2 dev/perf/spf_queue/review-2026-10/run-third.py +4a0b720c75d3911cfba99caeed4f0ef3a83dd4bd44ef29ef7ef8c04a2f0fec85 dev/perf/spf_queue/review-2026-10/safety.cpp +ec2d5cfe913551b6ae225e2f2576d79a4230dbb55fe95eace34344a591f9801a dev/perf/spf_queue/review-2026-10/session.log +7522cb44d30dbd3a74171ad6ec36b1b463ca7a5b74794e4fd0cd99fa004f6eb0 dev/perf/spf_queue/review-2026-10/settled.cpp +25b8bdcf8620c78c5a16668ddb6c0454cbf5e3acdb656c2bb3c2f3a4135564c5 dev/perf/spf_queue/review-2026-10/settled.patch +56136aa3598672bf39673e55774ace0f4bc32de88406cf78a477a11cc368f93f dev/perf/spf_queue/review-2026-10/singleton.cpp +89f6374be7a2318289daeeb1c5a4d034295fb3856e7dedc15218383fe42bb4c5 dev/perf/spf_queue/review-2026-10/singleton.patch +8c0fb19a0e62d710cfc18d8e000b05e322ae3954aba6f3639358ed513736417f dev/perf/spf_queue/review-2026-10/tracked-before.json +8b106f036839a2de638a340968084bfbd04dba027129062f70c1690f57ac818c dev/perf/spf_queue/review-2026-10/validate-flow.cpp +0028e525aa9503b25a741a04523bd6bb113c4bb96359b251c4e23740baa8fd6f dev/perf/spf_queue/review-2026-10/validate-review.sh diff --git a/dev/perf/spf_queue/review-2026-10/results/flow-fixed.csv b/dev/perf/spf_queue/review-2026-10/results/flow-fixed.csv new file mode 100644 index 0000000..6eb842e --- /dev/null +++ b/dev/perf/spf_queue/review-2026-10/results/flow-fixed.csv @@ -0,0 +1,5 @@ +case,median_ms,hash,samples_ms +calc_max_flow,4.48646,17694640663380043544,5.64775;4.78913;4.61479;4.48646;4.03329;4.01167;3.85121; +place_max_flow,2.13392,7688852859487360956,2.13375;2.13392;2.16279;2.223;2.05733;2.11654;2.21879; +calc_max_flow_masked,3.53092,9889262484581709037,3.53092;3.60033;3.58104;3.63612;3.50758;3.42379;3.39221; +place_max_flow_masked,1.69258,17611571108701524338,1.66437;1.69258;1.68496;1.68037;1.81683;1.83758;1.73129; diff --git a/dev/perf/spf_queue/review-2026-10/results/flow-new1.csv b/dev/perf/spf_queue/review-2026-10/results/flow-new1.csv new file mode 100644 index 0000000..46ed257 --- /dev/null +++ b/dev/perf/spf_queue/review-2026-10/results/flow-new1.csv @@ -0,0 +1,5 @@ +case,median_ms,hash,samples_ms +calc_max_flow,5.13942,17694640663380043544,5.13942;5.10746;5.1655;5.18054;5.18562;5.04467;5.0835; +place_max_flow,3.85738,7688852859487360956,3.99929;3.89029;4.10267;3.83567;3.80596;3.85738;3.74071; +calc_max_flow_masked,4.94221,9889262484581709037,4.97875;4.96592;4.87587;4.852;4.91233;4.94221;4.98758; +place_max_flow_masked,3.09025,17611571108701524338,3.1895;3.08596;3.09504;3.09025;2.93175;2.93383;3.11563; diff --git a/dev/perf/spf_queue/review-2026-10/results/flow-new2.csv b/dev/perf/spf_queue/review-2026-10/results/flow-new2.csv new file mode 100644 index 0000000..da00167 --- /dev/null +++ b/dev/perf/spf_queue/review-2026-10/results/flow-new2.csv @@ -0,0 +1,5 @@ +case,median_ms,hash,samples_ms +calc_max_flow,4.97171,17694640663380043544,12.4792;5.39579;4.84162;4.97171;4.92546;4.85942;5.09742; +place_max_flow,3.78354,7688852859487360956,3.86612;4.03892;3.81296;3.77933;3.77858;3.77338;3.78354; +calc_max_flow_masked,4.84563,9889262484581709037,4.76683;4.93637;4.70108;4.87838;4.74988;4.87417;4.84563; +place_max_flow_masked,2.95096,17611571108701524338,3.04258;2.95096;2.95379;2.94037;2.93587;3.03713;2.88842; diff --git a/dev/perf/spf_queue/review-2026-10/results/flow-old1.csv b/dev/perf/spf_queue/review-2026-10/results/flow-old1.csv new file mode 100644 index 0000000..ab82099 --- /dev/null +++ b/dev/perf/spf_queue/review-2026-10/results/flow-old1.csv @@ -0,0 +1,5 @@ +case,median_ms,hash,samples_ms +calc_max_flow,7.10546,17694640663380043544,7.31242;7.09342;7.04033;7.10546;6.95367;7.22346;7.20029; +place_max_flow,5.75662,7688852859487360956,5.85796;5.75662;6.00521;5.74729;6.26367;5.69708;5.68617; +calc_max_flow_masked,6.03229,9889262484581709037,6.01621;6.01492;6.09821;6.08133;6.05596;6.03229;5.88475; +place_max_flow_masked,4.25525,17611571108701524338,4.16933;4.25525;4.1865;4.20538;4.41496;4.33842;4.36954; diff --git a/dev/perf/spf_queue/review-2026-10/results/flow-old2.csv b/dev/perf/spf_queue/review-2026-10/results/flow-old2.csv new file mode 100644 index 0000000..011041b --- /dev/null +++ b/dev/perf/spf_queue/review-2026-10/results/flow-old2.csv @@ -0,0 +1,5 @@ +case,median_ms,hash,samples_ms +calc_max_flow,6.90321,17694640663380043544,7.05717;7.08817;6.90321;6.98071;6.71904;6.76312;6.74846; +place_max_flow,5.64579,7688852859487360956,5.64337;5.49796;5.64579;5.71962;5.80021;5.50375;5.68417; +calc_max_flow_masked,6.03338,9889262484581709037,6.05592;5.85275;6.01258;5.94246;6.03558;6.03338;6.18562; +place_max_flow_masked,4.1495,17611571108701524338,4.27125;4.15796;4.13183;4.11067;4.1495;4.16883;4.12979; diff --git a/dev/perf/spf_queue/review-2026-10/results/frontpop.csv b/dev/perf/spf_queue/review-2026-10/results/frontpop.csv new file mode 100644 index 0000000..3510c69 --- /dev/null +++ b/dev/perf/spf_queue/review-2026-10/results/frontpop.csv @@ -0,0 +1,7 @@ +case,n,e,queries,dst,variant,fallback,W,median_ms,samples,wall_samples_ms +random16,16384,131072,16,none,ref,0,32,65.101375,7,64.946167;64.845875;65.101375;66.617167;65.057041;65.682500;66.550625 +clos800,800,320000,16,none,ref,0,2,36.453708,7,36.859000;36.501083;36.235875;36.292584;36.453708;36.801833;36.208833 +chain2048,2048,2047,256,none,ref,0,32,3.965958,7,3.979875;3.971083;3.965958;3.944334;3.945583;4.008875;3.904917 +near16,16384,131072,64,near,ref,0,32,0.399084,7,0.401458;0.397583;0.398417;0.399084;0.413459;0.399000;0.400584 +wide20,16384,131072,16,none,ref,0,1048570,52.007125,7,51.567083;51.588583;53.758542;51.699834;52.041208;52.007125;53.121209 +wide25,16384,131072,16,none,ref,1,33554196,52.792000,7,52.439583;52.826333;52.792000;51.533250;53.775917;52.867667;51.741292 diff --git a/dev/perf/spf_queue/review-2026-10/results/heap-a1.csv b/dev/perf/spf_queue/review-2026-10/results/heap-a1.csv new file mode 100644 index 0000000..c17721f --- /dev/null +++ b/dev/perf/spf_queue/review-2026-10/results/heap-a1.csv @@ -0,0 +1,7 @@ +case,n,e,queries,dst,variant,fallback,W,median_ms,samples,wall_samples_ms +random16,16384,131072,16,none,ref,0,32,65.364334,7,64.756958;65.060417;65.364334;65.463167;65.001625;68.270959;66.302125 +clos800,800,320000,16,none,ref,0,2,36.700709,7,36.959416;37.673333;37.636916;36.700709;35.915000;35.896875;35.791000 +chain2048,2048,2047,256,none,ref,0,32,3.833208,7,3.968084;3.818500;3.833208;3.799833;3.817417;3.895208;3.882750 +near16,16384,131072,64,near,ref,0,32,0.398833,7,0.398500;0.405291;0.396542;0.413500;0.398833;0.399917;0.394875 +wide20,16384,131072,16,none,ref,0,1048570,52.299333,7,51.901458;52.139167;51.921916;53.186583;52.547000;52.299333;52.796500 +wide25,16384,131072,16,none,ref,1,33554196,53.495500,7,53.457000;54.495542;53.495500;52.239750;53.158500;60.914167;54.363500 diff --git a/dev/perf/spf_queue/review-2026-10/results/heap-a2.csv b/dev/perf/spf_queue/review-2026-10/results/heap-a2.csv new file mode 100644 index 0000000..fbe8c21 --- /dev/null +++ b/dev/perf/spf_queue/review-2026-10/results/heap-a2.csv @@ -0,0 +1,7 @@ +case,n,e,queries,dst,variant,fallback,W,median_ms,samples,wall_samples_ms +random16,16384,131072,16,none,ref,0,32,66.959792,7,66.386958;67.185125;66.959792;66.987375;67.456792;66.839292;66.192000 +clos800,800,320000,16,none,ref,0,2,38.442333,7,38.359708;38.193083;38.292875;38.442333;38.770833;38.635042;38.761959 +chain2048,2048,2047,256,none,ref,0,32,3.979125,7,4.027625;3.979125;4.017958;3.958625;3.933666;3.968250;4.100041 +near16,16384,131072,64,near,ref,0,32,0.408334,7,0.408334;0.419542;0.399500;0.417125;0.396375;0.395500;0.467042 +wide20,16384,131072,16,none,ref,0,1048570,53.113375,7,55.139833;53.365250;55.346916;52.507042;52.512042;52.528292;53.113375 +wide25,16384,131072,16,none,ref,1,33554196,52.646833,7,52.678042;52.766708;52.343250;52.677500;52.646833;52.270042;52.505291 diff --git a/dev/perf/spf_queue/review-2026-10/results/heap-b.csv b/dev/perf/spf_queue/review-2026-10/results/heap-b.csv new file mode 100644 index 0000000..ab7c51b --- /dev/null +++ b/dev/perf/spf_queue/review-2026-10/results/heap-b.csv @@ -0,0 +1,7 @@ +case,n,e,queries,dst,variant,fallback,W,median_ms,samples,wall_samples_ms +random16,16384,131072,16,none,ref,0,32,64.951416,7,65.302459;65.453125;65.329416;64.659166;64.446250;64.951416;64.798125 +clos800,800,320000,16,none,ref,0,2,36.226458,7,37.005584;36.537167;36.034083;36.226458;36.123375;36.493833;35.697291 +chain2048,2048,2047,256,none,ref,0,32,3.839833,7,3.794083;3.867417;3.791833;3.912125;3.839833;3.788834;3.859667 +near16,16384,131072,64,near,ref,0,32,0.395334,7,0.397834;0.406833;0.417958;0.395334;0.394542;0.395083;0.394875 +wide20,16384,131072,16,none,ref,0,1048570,52.248167,7,51.969083;52.299750;52.537667;53.162542;52.145375;52.248167;52.134541 +wide25,16384,131072,16,none,ref,1,33554196,52.650625,7,56.771042;52.650625;52.413416;53.770875;51.828708;52.274333;52.884625 diff --git a/dev/perf/spf_queue/review-2026-10/results/heapitem.csv b/dev/perf/spf_queue/review-2026-10/results/heapitem.csv new file mode 100644 index 0000000..a8d22f9 --- /dev/null +++ b/dev/perf/spf_queue/review-2026-10/results/heapitem.csv @@ -0,0 +1,7 @@ +case,n,e,queries,dst,variant,fallback,W,median_ms,samples,wall_samples_ms +random16,16384,131072,16,none,ref,0,32,63.692209,7,63.582792;63.341250;63.692209;64.101500;62.794375;63.752166;64.545166 +clos800,800,320000,16,none,ref,0,2,36.740125,7,36.518208;36.507958;37.177708;36.930292;36.740125;36.797583;36.663875 +chain2048,2048,2047,256,none,ref,0,32,3.830709,7,3.828250;3.830709;3.863875;3.904916;3.865083;3.727083;3.738709 +near16,16384,131072,64,near,ref,0,32,0.401250,7,0.401167;0.421708;0.406167;0.398958;0.404458;0.401250;0.394708 +wide20,16384,131072,16,none,ref,0,1048570,55.679208,7,55.679208;54.908417;55.376417;55.983709;55.692125;55.792750;55.223375 +wide25,16384,131072,16,none,ref,1,33554196,55.341667,7,55.341667;54.808333;54.961084;56.034541;58.019625;56.560750;53.575291 diff --git a/dev/perf/spf_queue/review-2026-10/results/inline-c.csv b/dev/perf/spf_queue/review-2026-10/results/inline-c.csv new file mode 100644 index 0000000..eea0177 --- /dev/null +++ b/dev/perf/spf_queue/review-2026-10/results/inline-c.csv @@ -0,0 +1,7 @@ +case,n,e,queries,dst,variant,fallback,W,median_ms,samples,wall_samples_ms +random16,16384,131072,16,none,ref,0,32,37.301584,7,38.150125;36.608291;36.901625;37.301584;37.162167;38.334875;38.687125 +clos800,800,320000,16,none,ref,0,2,36.877125,7,37.527166;36.744125;36.877125;38.040291;37.015458;36.548667;36.728291 +chain2048,2048,2047,256,none,ref,0,32,3.618334,7,3.663250;3.590083;3.618334;3.732833;3.579958;3.576042;3.697333 +near16,16384,131072,64,near,ref,0,32,0.398833,7,0.404917;0.398667;0.398209;0.400166;0.398417;0.398833;0.409833 +wide20,16384,131072,16,none,ref,0,1048570,54.109250,7,53.218667;53.234042;52.633916;54.959083;54.398584;54.646250;54.109250 +wide25,16384,131072,16,none,ref,1,33554196,52.257916,7,51.796250;52.257916;52.638666;51.878834;51.613834;52.369708;52.386042 diff --git a/dev/perf/spf_queue/review-2026-10/results/inline.csv b/dev/perf/spf_queue/review-2026-10/results/inline.csv new file mode 100644 index 0000000..aa86258 --- /dev/null +++ b/dev/perf/spf_queue/review-2026-10/results/inline.csv @@ -0,0 +1,7 @@ +case,n,e,queries,dst,variant,fallback,W,median_ms,samples,wall_samples_ms +random16,16384,131072,16,none,ref,0,32,36.222334,7,36.340209;36.811125;36.222334;36.304458;35.971375;35.917041;36.017125 +clos800,800,320000,16,none,ref,0,2,35.565125,7,35.587916;35.565125;35.683458;35.919167;35.414541;35.554083;35.558292 +chain2048,2048,2047,256,none,ref,0,32,3.540667,7,3.521250;3.546916;3.657333;3.527917;3.520250;3.584084;3.540667 +near16,16384,131072,64,near,ref,0,32,0.398500,7,0.400458;0.393000;0.392417;0.398500;0.401208;0.395834;0.439000 +wide20,16384,131072,16,none,ref,0,1048570,52.062375,7,50.544250;50.945583;52.159042;53.085375;52.836917;52.062375;51.674417 +wide25,16384,131072,16,none,ref,1,33554196,50.749417,7,50.995958;50.749417;50.962750;50.671917;50.935917;50.605375;50.528250 diff --git a/dev/perf/spf_queue/review-2026-10/results/load-flow-screen.txt b/dev/perf/spf_queue/review-2026-10/results/load-flow-screen.txt new file mode 100644 index 0000000..9e06b03 --- /dev/null +++ b/dev/perf/spf_queue/review-2026-10/results/load-flow-screen.txt @@ -0,0 +1,5 @@ + 2:34 up 52 days, 7:10, 3 users, load averages: 3.54 4.58 3.94 + 2:34 up 52 days, 7:10, 3 users, load averages: 3.54 4.58 3.94 + 2:34 up 52 days, 7:10, 3 users, load averages: 3.54 4.58 3.94 + 2:34 up 52 days, 7:10, 3 users, load averages: 3.54 4.58 3.94 + 2:34 up 52 days, 7:10, 3 users, load averages: 3.54 4.58 3.94 diff --git a/dev/perf/spf_queue/review-2026-10/results/load-flow.txt b/dev/perf/spf_queue/review-2026-10/results/load-flow.txt new file mode 100644 index 0000000..f1cb9c1 --- /dev/null +++ b/dev/perf/spf_queue/review-2026-10/results/load-flow.txt @@ -0,0 +1,5 @@ + 2:35 up 52 days, 7:11, 3 users, load averages: 4.76 4.70 4.02 + 2:35 up 52 days, 7:11, 3 users, load averages: 4.76 4.70 4.02 + 2:35 up 52 days, 7:11, 3 users, load averages: 4.76 4.70 4.02 + 2:35 up 52 days, 7:11, 3 users, load averages: 4.46 4.64 4.01 + 2:35 up 52 days, 7:11, 3 users, load averages: 4.46 4.64 4.01 diff --git a/dev/perf/spf_queue/review-2026-10/results/load-second.txt b/dev/perf/spf_queue/review-2026-10/results/load-second.txt new file mode 100644 index 0000000..248ed13 --- /dev/null +++ b/dev/perf/spf_queue/review-2026-10/results/load-second.txt @@ -0,0 +1,24 @@ +old-b1 2:28 up 52 days, 7:04, 3 users, load averages: 3.66 3.48 3.15 +new-b1 2:28 up 52 days, 7:04, 3 users, load averages: 3.66 3.48 3.15 +settled-b 2:28 up 52 days, 7:04, 3 users, load averages: 3.66 3.48 3.15 +inline 2:28 up 52 days, 7:04, 3 users, load averages: 3.53 3.45 3.14 +append 2:28 up 52 days, 7:04, 3 users, load averages: 3.53 3.45 3.14 +frontpop 2:28 up 52 days, 7:04, 3 users, load averages: 3.57 3.46 3.15 +heap-b 2:29 up 52 days, 7:04, 3 users, load averages: 3.57 3.46 3.15 +new-b2 2:29 up 52 days, 7:04, 3 users, load averages: 3.60 3.47 3.15 +old-b2 2:29 up 52 days, 7:04, 3 users, load averages: 3.60 3.47 3.15 +build-old1 2:29 up 52 days, 7:04, 3 users, load averages: 3.60 3.47 3.15 +build-new1 2:29 up 52 days, 7:04, 3 users, load averages: 3.60 3.47 3.15 +build-gcd 2:29 up 52 days, 7:04, 3 users, load averages: 4.67 3.69 3.23 +build-new2 2:29 up 52 days, 7:04, 3 users, load averages: 4.67 3.69 3.23 +build-old2 2:29 up 52 days, 7:04, 3 users, load averages: 4.67 3.69 3.23 +reverse-old1 2:29 up 52 days, 7:04, 3 users, load averages: 4.67 3.69 3.23 +reverse-new1 2:29 up 52 days, 7:04, 3 users, load averages: 4.67 3.69 3.23 +reverse-heap 2:29 up 52 days, 7:04, 3 users, load averages: 4.67 3.69 3.23 +reverse-settled 2:29 up 52 days, 7:04, 3 users, load averages: 4.67 3.69 3.23 +reverse-old2 2:29 up 52 days, 7:04, 3 users, load averages: 4.67 3.69 3.23 +boundary-old1 2:29 up 52 days, 7:04, 3 users, load averages: 4.67 3.69 3.23 +boundary-new1 2:29 up 52 days, 7:04, 3 users, load averages: 4.46 3.67 3.22 +boundary-heap 2:29 up 52 days, 7:04, 3 users, load averages: 4.46 3.67 3.22 +boundary-settled 2:29 up 52 days, 7:05, 3 users, load averages: 4.42 3.67 3.23 +boundary-old2 2:29 up 52 days, 7:05, 3 users, load averages: 4.42 3.67 3.23 diff --git a/dev/perf/spf_queue/review-2026-10/results/load-third.txt b/dev/perf/spf_queue/review-2026-10/results/load-third.txt new file mode 100644 index 0000000..ed7b1df --- /dev/null +++ b/dev/perf/spf_queue/review-2026-10/results/load-third.txt @@ -0,0 +1,10 @@ +old-c1 2:31 up 52 days, 7:07, 3 users, load averages: 8.46 5.42 3.97 +new-c1 2:31 up 52 days, 7:07, 3 users, load averages: 8.19 5.41 3.98 +append-c 2:31 up 52 days, 7:07, 3 users, load averages: 8.19 5.41 3.98 +combined 2:31 up 52 days, 7:07, 3 users, load averages: 8.19 5.41 3.98 +inline-c 2:31 up 52 days, 7:07, 3 users, load averages: 7.93 5.41 3.98 +new-c2 2:31 up 52 days, 7:07, 3 users, load averages: 7.93 5.41 3.98 +old-c2 2:31 up 52 days, 7:07, 3 users, load averages: 8.26 5.51 4.03 +build-repeat-new1 2:31 up 52 days, 7:07, 3 users, load averages: 8.26 5.51 4.03 +build-repeat-gcd 2:31 up 52 days, 7:07, 3 users, load averages: 8.26 5.51 4.03 +build-repeat-new2 2:31 up 52 days, 7:07, 3 users, load averages: 8.26 5.51 4.03 diff --git a/dev/perf/spf_queue/review-2026-10/results/load.txt b/dev/perf/spf_queue/review-2026-10/results/load.txt new file mode 100644 index 0000000..6437b22 --- /dev/null +++ b/dev/perf/spf_queue/review-2026-10/results/load.txt @@ -0,0 +1,12 @@ +old-a1 2:24 up 52 days, 7 hrs, 3 users, load averages: 3.69 3.44 3.03 +new-a1 2:24 up 52 days, 7 hrs, 3 users, load averages: 3.69 3.44 3.03 +heap-a1 2:24 up 52 days, 7 hrs, 3 users, load averages: 4.04 3.52 3.06 +settled 2:24 up 52 days, 7 hrs, 3 users, load averages: 4.04 3.52 3.06 +settled-heap 2:24 up 52 days, 7 hrs, 3 users, load averages: 4.11 3.54 3.07 +singleton 2:24 up 52 days, 7 hrs, 3 users, load averages: 4.11 3.54 3.07 +heapitem 2:24 up 52 days, 7 hrs, 3 users, load averages: 4.42 3.61 3.10 +notouch 2:24 up 52 days, 7 hrs, 3 users, load averages: 4.42 3.61 3.10 +new-a2 2:24 up 52 days, 7 hrs, 3 users, load averages: 4.39 3.62 3.10 +heap-a2 2:24 up 52 days, 7 hrs, 3 users, load averages: 4.39 3.62 3.10 +old-a2 2:24 up 52 days, 7 hrs, 3 users, load averages: 4.39 3.62 3.10 +end 2:24 up 52 days, 7 hrs, 3 users, load averages: 4.28 3.61 3.10 diff --git a/dev/perf/spf_queue/review-2026-10/results/memory.txt b/dev/perf/spf_queue/review-2026-10/results/memory.txt new file mode 100644 index 0000000..5f003a1 --- /dev/null +++ b/dev/perf/spf_queue/review-2026-10/results/memory.txt @@ -0,0 +1,3 @@ +after 1 graphs: bucket item capacity bytes=16400 N=1027 E=1026 peak_queue=1024 +after 63 graphs: bucket item capacity bytes=1032208 N=1027 E=1026 peak_queue=1024 +after N=2 graph: bucket item capacity bytes=1032208 dist_capacity=2 diff --git a/dev/perf/spf_queue/review-2026-10/results/netgraph-environment.txt b/dev/perf/spf_queue/review-2026-10/results/netgraph-environment.txt new file mode 100644 index 0000000..16d68f0 --- /dev/null +++ b/dev/perf/spf_queue/review-2026-10/results/netgraph-environment.txt @@ -0,0 +1,16 @@ +old1 2:32 up 52 days, 7:08, 3 users, load averages: 5.87 5.41 4.09 +91dc3b7e2bd3611d54d762e0fb1f875881138d66843866990f019cddfec5cc2c /Users/networmix/ws/NetGraph-Core-main/venv/lib/python3.14/site-packages/_netgraph_core.cpython-314-darwin.so +/Users/networmix/ws/NetGraph-Core-main/venv/lib/python3.14/site-packages/_netgraph_core.cpython-314-darwin.so +/Users/networmix/ws/NetGraph-Core-main/python/netgraph_core/__init__.py +new 2:32 up 52 days, 7:08, 3 users, load averages: 5.64 5.37 4.08 +996ae1c6aef243b9950c345651c901b155b375da2fc429d00f079de0df67e116 /Users/networmix/ws/NetGraph-Core/venv/lib/python3.14/site-packages/_netgraph_core.cpython-314-darwin.so +/Users/networmix/ws/NetGraph-Core/venv/lib/python3.14/site-packages/_netgraph_core.cpython-314-darwin.so +/Users/networmix/ws/NetGraph-Core/python/netgraph_core/__init__.py +heap 2:32 up 52 days, 7:08, 3 users, load averages: 5.64 5.37 4.08 +996ae1c6aef243b9950c345651c901b155b375da2fc429d00f079de0df67e116 /Users/networmix/ws/NetGraph-Core/venv/lib/python3.14/site-packages/_netgraph_core.cpython-314-darwin.so +/Users/networmix/ws/NetGraph-Core/venv/lib/python3.14/site-packages/_netgraph_core.cpython-314-darwin.so +/Users/networmix/ws/NetGraph-Core/python/netgraph_core/__init__.py +old2 2:32 up 52 days, 7:08, 3 users, load averages: 5.74 5.40 4.10 +91dc3b7e2bd3611d54d762e0fb1f875881138d66843866990f019cddfec5cc2c /Users/networmix/ws/NetGraph-Core-main/venv/lib/python3.14/site-packages/_netgraph_core.cpython-314-darwin.so +/Users/networmix/ws/NetGraph-Core-main/venv/lib/python3.14/site-packages/_netgraph_core.cpython-314-darwin.so +/Users/networmix/ws/NetGraph-Core-main/python/netgraph_core/__init__.py diff --git a/dev/perf/spf_queue/review-2026-10/results/netgraph-heap.csv b/dev/perf/spf_queue/review-2026-10/results/netgraph-heap.csv new file mode 100644 index 0000000..67501d0 --- /dev/null +++ b/dev/perf/spf_queue/review-2026-10/results/netgraph-heap.csv @@ -0,0 +1,5 @@ +workload,label,median_s,samples,checksum,samples_s +spf_full_clos_200x200,heap,0.215680,5,946e7cf8b5a36980,0.215093;0.215680;0.217045;0.214475;0.215709 +spf_full_grid_100x100_weighted,heap,0.235446,5,4c2f7751ff9a5057,0.235446;0.235428;0.234089;0.236250;0.238091 +maxflow_grid_100x100_weighted_combine,heap,0.216545,5,b0453b641647871b,0.216545;0.214937;0.219780;0.215704;0.216563 +placement_backbone_clos,heap,0.067445,5,a3bbef71a61656e1,0.068307;0.068552;0.067445;0.067098;0.066769 diff --git a/dev/perf/spf_queue/review-2026-10/results/netgraph-new.csv b/dev/perf/spf_queue/review-2026-10/results/netgraph-new.csv new file mode 100644 index 0000000..a4840b0 --- /dev/null +++ b/dev/perf/spf_queue/review-2026-10/results/netgraph-new.csv @@ -0,0 +1,5 @@ +workload,label,median_s,samples,checksum,samples_s +spf_full_clos_200x200,new,0.215551,5,946e7cf8b5a36980,0.215551;0.215907;0.218243;0.214622;0.214636 +spf_full_grid_100x100_weighted,new,0.169151,5,4c2f7751ff9a5057,0.171143;0.169339;0.168719;0.169148;0.169151 +maxflow_grid_100x100_weighted_combine,new,0.160344,5,b0453b641647871b,0.160344;0.159538;0.159366;0.161421;0.160476 +placement_backbone_clos,new,0.067171,5,a3bbef71a61656e1,0.067222;0.067171;0.067064;0.066943;0.069957 diff --git a/dev/perf/spf_queue/review-2026-10/results/netgraph-old1.csv b/dev/perf/spf_queue/review-2026-10/results/netgraph-old1.csv new file mode 100644 index 0000000..060b57b --- /dev/null +++ b/dev/perf/spf_queue/review-2026-10/results/netgraph-old1.csv @@ -0,0 +1,5 @@ +workload,label,median_s,samples,checksum,samples_s +spf_full_clos_200x200,old1,0.212167,5,946e7cf8b5a36980,0.212167;0.211826;0.211942;0.215837;0.213694 +spf_full_grid_100x100_weighted,old1,0.219249,5,4c2f7751ff9a5057,0.220500;0.219115;0.219249;0.219192;0.219299 +maxflow_grid_100x100_weighted_combine,old1,0.201715,5,b0453b641647871b,0.201715;0.200953;0.200980;0.201761;0.202154 +placement_backbone_clos,old1,0.068333,5,a3bbef71a61656e1,0.071259;0.069470;0.068333;0.067665;0.067146 diff --git a/dev/perf/spf_queue/review-2026-10/results/netgraph-old2.csv b/dev/perf/spf_queue/review-2026-10/results/netgraph-old2.csv new file mode 100644 index 0000000..8fb46d2 --- /dev/null +++ b/dev/perf/spf_queue/review-2026-10/results/netgraph-old2.csv @@ -0,0 +1,5 @@ +workload,label,median_s,samples,checksum,samples_s +spf_full_clos_200x200,old2,0.212584,5,946e7cf8b5a36980,0.215052;0.213002;0.212584;0.211673;0.211985 +spf_full_grid_100x100_weighted,old2,0.219160,5,4c2f7751ff9a5057,0.219166;0.219314;0.219160;0.218651;0.218967 +maxflow_grid_100x100_weighted_combine,old2,0.204482,5,b0453b641647871b,0.204155;0.205131;0.202814;0.206448;0.204482 +placement_backbone_clos,old2,0.068736,5,a3bbef71a61656e1,0.073860;0.068736;0.069312;0.067899;0.067647 diff --git a/dev/perf/spf_queue/review-2026-10/results/new-a1.csv b/dev/perf/spf_queue/review-2026-10/results/new-a1.csv new file mode 100644 index 0000000..437e0c8 --- /dev/null +++ b/dev/perf/spf_queue/review-2026-10/results/new-a1.csv @@ -0,0 +1,7 @@ +case,n,e,queries,dst,variant,fallback,W,median_ms,samples,wall_samples_ms +random16,16384,131072,16,none,ref,0,32,36.102459,7,35.199334;35.690875;38.373709;38.308667;36.978666;35.956458;36.102459 +clos800,800,320000,16,none,ref,0,2,34.775459,7,34.500583;34.933417;35.096750;34.769667;34.775459;34.758333;34.956375 +chain2048,2048,2047,256,none,ref,0,32,5.474458,7,5.474458;5.427250;5.537375;5.544917;5.404750;5.244750;5.608208 +near16,16384,131072,64,near,ref,0,32,0.399542,7,0.405667;0.398833;0.399542;0.397875;0.397334;0.401334;0.527208 +wide20,16384,131072,16,none,ref,0,1048570,53.540750,7,54.768666;53.546709;53.889500;53.540750;51.955959;51.682333;51.324000 +wide25,16384,131072,16,none,ref,1,33554196,51.896333,7,51.418416;51.288208;51.196500;52.728375;51.896333;52.195541;51.900459 diff --git a/dev/perf/spf_queue/review-2026-10/results/new-a2.csv b/dev/perf/spf_queue/review-2026-10/results/new-a2.csv new file mode 100644 index 0000000..1c162b2 --- /dev/null +++ b/dev/perf/spf_queue/review-2026-10/results/new-a2.csv @@ -0,0 +1,7 @@ +case,n,e,queries,dst,variant,fallback,W,median_ms,samples,wall_samples_ms +random16,16384,131072,16,none,ref,0,32,35.831792,7,36.189667;35.773375;35.695792;35.831792;35.725083;36.297667;36.324250 +clos800,800,320000,16,none,ref,0,2,35.326334,7,35.498916;35.326334;35.124375;35.321917;35.321917;36.149375;35.790500 +chain2048,2048,2047,256,none,ref,0,32,5.512958,7,5.512958;5.298833;5.615125;5.432375;5.915125;5.433833;5.638750 +near16,16384,131072,64,near,ref,0,32,0.400833,7,0.441875;0.400833;0.399042;0.400542;0.401750;0.402708;0.397625 +wide20,16384,131072,16,none,ref,0,1048570,53.120167,7,53.321333;53.068083;53.353167;52.922958;52.360084;53.120167;53.810084 +wide25,16384,131072,16,none,ref,1,33554196,53.291750,7,52.971000;53.298666;53.693958;52.207583;53.393625;53.291750;53.217625 diff --git a/dev/perf/spf_queue/review-2026-10/results/new-b1.csv b/dev/perf/spf_queue/review-2026-10/results/new-b1.csv new file mode 100644 index 0000000..8a65069 --- /dev/null +++ b/dev/perf/spf_queue/review-2026-10/results/new-b1.csv @@ -0,0 +1,7 @@ +case,n,e,queries,dst,variant,fallback,W,median_ms,samples,wall_samples_ms +random16,16384,131072,16,none,ref,0,32,36.437375,7,36.458750;36.437375;38.069833;36.224666;36.010291;36.396042;37.253792 +clos800,800,320000,16,none,ref,0,2,35.225250,7,34.455709;35.475875;35.529291;35.883833;35.225250;35.163875;34.286250 +chain2048,2048,2047,256,none,ref,0,32,5.232375,7,5.232375;5.161833;5.193875;5.241000;5.442209;5.288500;5.128166 +near16,16384,131072,64,near,ref,0,32,0.393208,7,0.393208;0.422042;0.394291;0.392958;0.393208;0.392875;0.528167 +wide20,16384,131072,16,none,ref,0,1048570,53.174917,7,58.161917;55.200583;57.610292;53.174917;52.132458;52.841833;52.854667 +wide25,16384,131072,16,none,ref,1,33554196,51.289500,7,51.586333;51.127750;51.289500;51.351333;51.227667;51.099000;51.490417 diff --git a/dev/perf/spf_queue/review-2026-10/results/new-b2.csv b/dev/perf/spf_queue/review-2026-10/results/new-b2.csv new file mode 100644 index 0000000..39a7f2c --- /dev/null +++ b/dev/perf/spf_queue/review-2026-10/results/new-b2.csv @@ -0,0 +1,7 @@ +case,n,e,queries,dst,variant,fallback,W,median_ms,samples,wall_samples_ms +random16,16384,131072,16,none,ref,0,32,36.404042,7,36.404042;36.566625;36.893834;36.811875;35.520042;35.665875;35.423125 +clos800,800,320000,16,none,ref,0,2,36.691083,7,36.693000;36.691083;36.777375;36.492916;36.721750;36.260792;36.411417 +chain2048,2048,2047,256,none,ref,0,32,5.462458,7,5.488625;5.462458;5.325083;5.346833;5.282000;5.603708;5.615292 +near16,16384,131072,64,near,ref,0,32,0.398292,7,0.402209;0.398041;0.398292;0.403500;0.398208;0.398250;0.398875 +wide20,16384,131072,16,none,ref,0,1048570,52.534209,7,53.152833;52.864875;52.173209;52.534209;51.993000;51.975541;52.824167 +wide25,16384,131072,16,none,ref,1,33554196,51.805792,7,51.580833;51.931458;51.890167;51.724667;51.865584;51.728083;51.805792 diff --git a/dev/perf/spf_queue/review-2026-10/results/new-c1.csv b/dev/perf/spf_queue/review-2026-10/results/new-c1.csv new file mode 100644 index 0000000..b1b8412 --- /dev/null +++ b/dev/perf/spf_queue/review-2026-10/results/new-c1.csv @@ -0,0 +1,7 @@ +case,n,e,queries,dst,variant,fallback,W,median_ms,samples,wall_samples_ms +random16,16384,131072,16,none,ref,0,32,37.139500,7,36.504416;36.802209;37.139500;38.133916;37.465166;37.054833;38.317666 +clos800,800,320000,16,none,ref,0,2,35.800416,7,35.303583;36.024750;36.169166;36.144750;35.518792;35.800416;35.443250 +chain2048,2048,2047,256,none,ref,0,32,5.607416,7,5.607416;5.575208;5.649000;5.624584;5.693125;5.270625;5.536083 +near16,16384,131072,64,near,ref,0,32,0.399667,7,0.399667;0.400375;0.400917;0.394542;0.392208;0.392333;0.568209 +wide20,16384,131072,16,none,ref,0,1048570,54.419250,7,54.419250;54.934584;53.961750;58.652125;55.884458;53.924291;54.415167 +wide25,16384,131072,16,none,ref,1,33554196,53.599334,7,53.390917;53.599334;53.398084;53.811875;54.324917;53.464542;53.836208 diff --git a/dev/perf/spf_queue/review-2026-10/results/new-c2.csv b/dev/perf/spf_queue/review-2026-10/results/new-c2.csv new file mode 100644 index 0000000..ae9d0a6 --- /dev/null +++ b/dev/perf/spf_queue/review-2026-10/results/new-c2.csv @@ -0,0 +1,7 @@ +case,n,e,queries,dst,variant,fallback,W,median_ms,samples,wall_samples_ms +random16,16384,131072,16,none,ref,0,32,35.804375,7,37.196709;36.498875;35.856709;35.804375;35.703334;35.523000;35.752333 +clos800,800,320000,16,none,ref,0,2,35.380250,7,34.909542;34.823166;35.486375;35.805667;35.469875;35.380250;35.227375 +chain2048,2048,2047,256,none,ref,0,32,5.569458,7,5.755125;5.363458;5.786500;5.960208;5.536959;5.553417;5.569458 +near16,16384,131072,64,near,ref,0,32,0.410583,7,0.410583;0.406541;0.480917;0.408208;0.413625;0.412792;0.404583 +wide20,16384,131072,16,none,ref,0,1048570,54.147083,7,55.012958;54.037667;54.147083;54.609250;58.278625;53.827542;52.777916 +wide25,16384,131072,16,none,ref,1,33554196,55.281334,7,55.281334;55.300417;54.891208;55.485083;54.879417;56.778000;54.301083 diff --git a/dev/perf/spf_queue/review-2026-10/results/notouch.csv b/dev/perf/spf_queue/review-2026-10/results/notouch.csv new file mode 100644 index 0000000..02b2e38 --- /dev/null +++ b/dev/perf/spf_queue/review-2026-10/results/notouch.csv @@ -0,0 +1,7 @@ +case,n,e,queries,dst,variant,fallback,W,median_ms,samples,wall_samples_ms +random16,16384,131072,16,none,ref,0,32,64.783708,7,65.583000;64.783708;65.158708;64.282958;63.893125;63.678958;64.801625 +clos800,800,320000,16,none,ref,0,2,35.476459,7,35.412791;35.386666;35.476459;35.508416;36.327584;39.811958;35.461834 +chain2048,2048,2047,256,none,ref,0,32,3.864416,7,3.864416;3.936958;3.750625;3.911541;3.743166;3.722166;3.938917 +near16,16384,131072,64,near,ref,0,32,1.233209,7,1.226250;1.227584;1.253875;1.213750;1.234292;1.233209;1.234292 +wide20,16384,131072,16,none,ref,0,1048570,51.039792,7,51.251833;50.497792;50.554000;50.847667;51.061708;53.260042;51.039792 +wide25,16384,131072,16,none,ref,1,33554196,52.060541,7,52.351833;52.380375;52.677792;51.515375;50.656833;51.244459;52.060541 diff --git a/dev/perf/spf_queue/review-2026-10/results/old-a1.csv b/dev/perf/spf_queue/review-2026-10/results/old-a1.csv new file mode 100644 index 0000000..ccec261 --- /dev/null +++ b/dev/perf/spf_queue/review-2026-10/results/old-a1.csv @@ -0,0 +1,7 @@ +case,n,e,queries,dst,variant,fallback,W,median_ms,samples,wall_samples_ms +random16,16384,131072,16,none,ref,0,32,62.661917,7,63.361167;62.796042;62.371417;61.183166;61.657917;62.661917;63.670791 +clos800,800,320000,16,none,ref,0,2,36.783917,7,37.430625;37.233792;36.468375;36.783917;36.168666;35.968083;37.098833 +chain2048,2048,2047,256,none,ref,0,32,3.057542,7,2.948125;3.260791;3.042750;3.032208;3.165833;3.057542;3.211375 +near16,16384,131072,64,near,ref,0,32,1.092541,7,1.155958;1.279500;1.142084;1.017416;1.051916;1.092042;1.092541 +wide20,16384,131072,16,none,ref,0,1048570,50.820084,7,50.733791;50.221000;50.086750;50.820084;52.921666;52.840042;54.729458 +wide25,16384,131072,16,none,ref,1,33554196,52.896333,7,51.156375;53.299750;53.507959;52.896333;52.904042;51.731917;52.568667 diff --git a/dev/perf/spf_queue/review-2026-10/results/old-a2.csv b/dev/perf/spf_queue/review-2026-10/results/old-a2.csv new file mode 100644 index 0000000..5f08a8f --- /dev/null +++ b/dev/perf/spf_queue/review-2026-10/results/old-a2.csv @@ -0,0 +1,7 @@ +case,n,e,queries,dst,variant,fallback,W,median_ms,samples,wall_samples_ms +random16,16384,131072,16,none,ref,0,32,64.328708,7,65.860417;67.227500;69.844208;63.343917;64.328708;63.977542;63.754750 +clos800,800,320000,16,none,ref,0,2,36.826667,7,37.149125;37.741042;36.605166;36.811375;36.489750;37.581458;36.826667 +chain2048,2048,2047,256,none,ref,0,32,2.990084,7,3.024791;2.990084;3.052875;2.964083;2.980958;3.019750;2.961667 +near16,16384,131072,64,near,ref,0,32,1.199667,7,1.191166;1.206875;1.208292;1.198708;1.190500;1.199667;1.214209 +wide20,16384,131072,16,none,ref,0,1048570,52.035958,7,52.165042;53.316625;52.035958;51.401875;51.295833;52.107750;51.960041 +wide25,16384,131072,16,none,ref,1,33554196,50.975833,7,51.363500;51.186625;50.880625;50.549250;50.549292;50.975833;52.110708 diff --git a/dev/perf/spf_queue/review-2026-10/results/old-b1.csv b/dev/perf/spf_queue/review-2026-10/results/old-b1.csv new file mode 100644 index 0000000..7872b37 --- /dev/null +++ b/dev/perf/spf_queue/review-2026-10/results/old-b1.csv @@ -0,0 +1,7 @@ +case,n,e,queries,dst,variant,fallback,W,median_ms,samples,wall_samples_ms +random16,16384,131072,16,none,ref,0,32,61.637542,7,61.942917;61.538791;61.641750;61.961083;61.442291;61.637542;61.568000 +clos800,800,320000,16,none,ref,0,2,36.004833,7,36.153250;36.197042;36.012833;35.441125;35.771541;35.491000;36.004833 +chain2048,2048,2047,256,none,ref,0,32,2.928958,7,2.928958;2.962292;3.033417;2.922334;2.904750;2.933958;2.916417 +near16,16384,131072,64,near,ref,0,32,1.124750,7,1.148625;1.238209;1.100708;1.092209;1.103667;1.124750;1.146000 +wide20,16384,131072,16,none,ref,0,1048570,48.971583,7,48.840500;48.835708;49.106709;48.960542;49.092709;48.971583;49.089000 +wide25,16384,131072,16,none,ref,1,33554196,50.581042,7,49.251042;48.808875;49.316292;50.581042;52.614792;53.201250;54.016584 diff --git a/dev/perf/spf_queue/review-2026-10/results/old-b2.csv b/dev/perf/spf_queue/review-2026-10/results/old-b2.csv new file mode 100644 index 0000000..fa019c1 --- /dev/null +++ b/dev/perf/spf_queue/review-2026-10/results/old-b2.csv @@ -0,0 +1,7 @@ +case,n,e,queries,dst,variant,fallback,W,median_ms,samples,wall_samples_ms +random16,16384,131072,16,none,ref,0,32,63.736459,7,63.736459;63.137583;63.046959;62.846708;63.976583;65.935500;64.739708 +clos800,800,320000,16,none,ref,0,2,36.966917,7,37.437042;37.236958;36.966917;36.455042;36.567083;37.288084;36.713500 +chain2048,2048,2047,256,none,ref,0,32,3.113500,7,3.200416;3.036708;3.115750;3.069792;3.124292;2.971250;3.113500 +near16,16384,131072,64,near,ref,0,32,1.156625,7,1.156625;1.151708;1.166083;1.200334;1.282791;1.110500;1.146583 +wide20,16384,131072,16,none,ref,0,1048570,50.562250,7,50.748417;50.573167;50.539084;50.234584;50.562250;49.976792;50.625125 +wide25,16384,131072,16,none,ref,1,33554196,50.306625,7,50.242875;50.322416;51.103708;50.099792;50.298542;50.384375;50.306625 diff --git a/dev/perf/spf_queue/review-2026-10/results/old-c1.csv b/dev/perf/spf_queue/review-2026-10/results/old-c1.csv new file mode 100644 index 0000000..1d1ba55 --- /dev/null +++ b/dev/perf/spf_queue/review-2026-10/results/old-c1.csv @@ -0,0 +1,7 @@ +case,n,e,queries,dst,variant,fallback,W,median_ms,samples,wall_samples_ms +random16,16384,131072,16,none,ref,0,32,65.450625,7,65.882125;64.276208;65.260500;67.423833;65.450625;64.917750;66.206416 +clos800,800,320000,16,none,ref,0,2,37.396042,7,37.188167;37.396042;37.494208;37.605083;37.457750;37.083417;37.271541 +chain2048,2048,2047,256,none,ref,0,32,3.038625,7,3.047042;3.021875;3.101083;3.038625;3.018084;3.103375;3.018792 +near16,16384,131072,64,near,ref,0,32,1.172167,7,1.313208;1.183792;1.158750;1.165458;1.171416;1.172167;1.174500 +wide20,16384,131072,16,none,ref,0,1048570,52.389542,7,52.971667;51.957750;52.280500;52.823083;51.671041;52.389542;54.248084 +wide25,16384,131072,16,none,ref,1,33554196,52.215416,7,52.625458;52.215416;52.307000;51.824541;51.515833;51.631542;52.662375 diff --git a/dev/perf/spf_queue/review-2026-10/results/old-c2.csv b/dev/perf/spf_queue/review-2026-10/results/old-c2.csv new file mode 100644 index 0000000..e5b4788 --- /dev/null +++ b/dev/perf/spf_queue/review-2026-10/results/old-c2.csv @@ -0,0 +1,7 @@ +case,n,e,queries,dst,variant,fallback,W,median_ms,samples,wall_samples_ms +random16,16384,131072,16,none,ref,0,32,67.528541,7,66.008416;68.058333;70.523875;65.632458;67.528541;66.204166;69.484250 +clos800,800,320000,16,none,ref,0,2,37.468209,7,37.360667;37.451250;37.468209;37.111125;43.702125;40.555084;37.667917 +chain2048,2048,2047,256,none,ref,0,32,3.115042,7,3.325166;3.384667;3.109333;3.115042;3.085416;3.101334;3.127666 +near16,16384,131072,64,near,ref,0,32,1.226250,7,1.229375;1.227542;1.220333;1.224041;1.234542;1.226250;1.216458 +wide20,16384,131072,16,none,ref,0,1048570,54.983958,7,54.983958;53.121458;52.081750;52.332667;61.260375;55.755916;62.780084 +wide25,16384,131072,16,none,ref,1,33554196,51.311292,7,50.930792;51.031875;51.381208;50.627125;51.311292;52.826625;53.041833 diff --git a/dev/perf/spf_queue/review-2026-10/results/reverse-heap.csv b/dev/perf/spf_queue/review-2026-10/results/reverse-heap.csv new file mode 100644 index 0000000..d6b3e18 --- /dev/null +++ b/dev/perf/spf_queue/review-2026-10/results/reverse-heap.csv @@ -0,0 +1,5 @@ +case,median_ms,hash,samples_ms +random,14.29,4323550201995714722,14.2146;14.2688;14.1871;14.3387;14.3591;14.29;14.2905; +clos,46.6671,16998307955055842784,46.2878;48.1355;46.3228;47.327;46.6671;46.6519;48.5254; +chain,0.519167,6923677047050424156,0.52075;0.515292;0.532917;0.5175;0.516583;0.519167;0.525042; +zerocyc,17.8648,3520531437519771524,18.1898;18.3212;17.6796;17.7299;17.8648;17.9677;17.7341; diff --git a/dev/perf/spf_queue/review-2026-10/results/reverse-new1.csv b/dev/perf/spf_queue/review-2026-10/results/reverse-new1.csv new file mode 100644 index 0000000..8e362a8 --- /dev/null +++ b/dev/perf/spf_queue/review-2026-10/results/reverse-new1.csv @@ -0,0 +1,5 @@ +case,median_ms,hash,samples_ms +random,8.53917,4323550201995714722,8.53917;8.44875;8.4335;8.56229;8.54592;8.52125;8.59829; +clos,46.9226,16998307955055842784,46.9246;46.809;47.0009;46.268;46.7838;46.9226;47.6712; +chain,0.7405,6923677047050424156,0.813791;0.7405;0.70425;0.729833;0.716333;0.742916;0.742958; +zerocyc,11.101,3520531437519771524,11.2392;11.2819;10.9927;11.0575;10.9636;11.2812;11.101; diff --git a/dev/perf/spf_queue/review-2026-10/results/reverse-old1.csv b/dev/perf/spf_queue/review-2026-10/results/reverse-old1.csv new file mode 100644 index 0000000..c151b3d --- /dev/null +++ b/dev/perf/spf_queue/review-2026-10/results/reverse-old1.csv @@ -0,0 +1,5 @@ +case,median_ms,hash,samples_ms +random,14.1883,4323550201995714722,13.9235;13.8795;15.3225;14.1821;14.587;14.1883;14.5707; +clos,48.2569,16998307955055842784,47.954;48.6985;48.2569;47.5812;47.9113;48.4309;49.74; +chain,0.401625,6923677047050424156,0.403;0.403834;0.400166;0.401167;0.400791;0.401625;0.405333; +zerocyc,17.3234,3520531437519771524,18.1433;17.3234;17.294;17.1341;16.9652;17.4247;17.6095; diff --git a/dev/perf/spf_queue/review-2026-10/results/reverse-old2.csv b/dev/perf/spf_queue/review-2026-10/results/reverse-old2.csv new file mode 100644 index 0000000..b917885 --- /dev/null +++ b/dev/perf/spf_queue/review-2026-10/results/reverse-old2.csv @@ -0,0 +1,5 @@ +case,median_ms,hash,samples_ms +random,13.8073,4323550201995714722,13.9139;13.7902;13.8063;13.707;13.8688;13.8073;13.871; +clos,46.6904,16998307955055842784,47.0873;46.4569;46.6064;47.3114;46.4868;46.6904;47.2773; +chain,0.409,6923677047050424156,0.404834;0.408334;0.41;0.41075;0.409;0.405917;0.410666; +zerocyc,17.2142,3520531437519771524,17.2065;17.2142;17.3031;17.17;17.3148;17.2411;17.2045; diff --git a/dev/perf/spf_queue/review-2026-10/results/reverse-settled.csv b/dev/perf/spf_queue/review-2026-10/results/reverse-settled.csv new file mode 100644 index 0000000..808695a --- /dev/null +++ b/dev/perf/spf_queue/review-2026-10/results/reverse-settled.csv @@ -0,0 +1,5 @@ +case,median_ms,hash,samples_ms +random,8.46929,4323550201995714722,8.32779;8.44088;8.74062;8.55787;8.46929;8.53213;8.43412; +clos,37.0421,16998307955055842784,37.0421;36.9092;37.2337;36.9606;36.7457;37.5333;37.2674; +chain,0.712,6923677047050424156,0.703833;0.703125;0.711333;0.715333;0.712;0.719459;0.73825; +zerocyc,10.7184,3520531437519771524,10.7537;10.7373;10.701;10.7016;10.8767;10.7184;10.7129; diff --git a/dev/perf/spf_queue/review-2026-10/results/safety.txt b/dev/perf/spf_queue/review-2026-10/results/safety.txt new file mode 100644 index 0000000..2cd383b --- /dev/null +++ b/dev/perf/spf_queue/review-2026-10/results/safety.txt @@ -0,0 +1 @@ +PASS: boundary widths, near-int64-bound, zero costs, edgeless, forward/reverse, reused and concurrent threads diff --git a/dev/perf/spf_queue/review-2026-10/results/screen-flow-fixed.csv b/dev/perf/spf_queue/review-2026-10/results/screen-flow-fixed.csv new file mode 100644 index 0000000..4a67f8f --- /dev/null +++ b/dev/perf/spf_queue/review-2026-10/results/screen-flow-fixed.csv @@ -0,0 +1,5 @@ +case,median_ms,hash,samples_ms +calc_max_flow,3.49771,17694640663380043544,3.49771;3.44867;3.59746;3.5455;3.50575;3.47817;3.46129; +place_max_flow,2.17654,7688852859487360956,2.19533;2.13963;2.12258;2.17654;2.27933;2.22033;2.16417; +calc_max_flow_masked,3.52533,9889262484581709037,3.65667;3.66458;3.51767;3.585;3.52533;3.47987;3.45167; +place_max_flow_masked,1.74058,17611571108701524338,1.83658;1.77683;1.732;1.76604;1.69054;1.74058;1.72042; diff --git a/dev/perf/spf_queue/review-2026-10/results/screen-flow-new1.csv b/dev/perf/spf_queue/review-2026-10/results/screen-flow-new1.csv new file mode 100644 index 0000000..81f770f --- /dev/null +++ b/dev/perf/spf_queue/review-2026-10/results/screen-flow-new1.csv @@ -0,0 +1,5 @@ +case,median_ms,hash,samples_ms +calc_max_flow,6.30813,17694640663380043544,9.53404;7.89408;6.85742;6.30813;5.85308;5.42833;5.04875; +place_max_flow,3.75046,7688852859487360956,3.74292;3.99771;3.72096;3.729;3.75046;3.83758;3.78788; +calc_max_flow_masked,4.66933,9889262484581709037,4.59392;4.66933;4.66683;4.63588;4.70075;4.6815;4.69033; +place_max_flow_masked,2.88571,17611571108701524338,2.89621;2.88571;2.85225;2.96892;2.94071;2.87242;2.83696; diff --git a/dev/perf/spf_queue/review-2026-10/results/screen-flow-new2.csv b/dev/perf/spf_queue/review-2026-10/results/screen-flow-new2.csv new file mode 100644 index 0000000..c4e6c54 --- /dev/null +++ b/dev/perf/spf_queue/review-2026-10/results/screen-flow-new2.csv @@ -0,0 +1,5 @@ +case,median_ms,hash,samples_ms +calc_max_flow,5.17758,17694640663380043544,5.17758;5.18304;5.10125;5.14938;5.25413;5.22612;5.08204; +place_max_flow,3.74721,7688852859487360956,3.75838;3.76867;3.74721;3.74708;3.81875;3.70783;3.73663; +calc_max_flow_masked,4.81,9889262484581709037,4.72837;5.11983;4.78008;4.89187;4.76479;4.89292;4.81; +place_max_flow_masked,3.03613,17611571108701524338,2.90725;3.02983;3.03613;3.24267;3.35433;3.13017;2.93463; diff --git a/dev/perf/spf_queue/review-2026-10/results/screen-flow-old1.csv b/dev/perf/spf_queue/review-2026-10/results/screen-flow-old1.csv new file mode 100644 index 0000000..8fc2c18 --- /dev/null +++ b/dev/perf/spf_queue/review-2026-10/results/screen-flow-old1.csv @@ -0,0 +1,5 @@ +case,median_ms,hash,samples_ms +calc_max_flow,7.46421,17694640663380043544,10.7697;9.501;8.27529;7.46421;7.01146;6.62575;6.60421; +place_max_flow,5.55046,7688852859487360956,5.59325;5.56725;5.55046;5.51917;5.50913;5.47129;5.66104; +calc_max_flow_masked,5.81396,9889262484581709037,5.84025;5.81396;5.74475;5.87383;5.77688;5.95671;5.79425; +place_max_flow_masked,4.05721,17611571108701524338,4.07908;3.97954;4.06804;4.05721;4.03087;4.07292;4.049; diff --git a/dev/perf/spf_queue/review-2026-10/results/screen-flow-old2.csv b/dev/perf/spf_queue/review-2026-10/results/screen-flow-old2.csv new file mode 100644 index 0000000..858bc08 --- /dev/null +++ b/dev/perf/spf_queue/review-2026-10/results/screen-flow-old2.csv @@ -0,0 +1,5 @@ +case,median_ms,hash,samples_ms +calc_max_flow,6.88671,17694640663380043544,6.84333;7.00104;6.84063;6.88671;6.92425;6.96867;6.83817; +place_max_flow,5.62904,7688852859487360956,5.63633;5.73642;5.73917;5.62904;5.55379;5.56463;5.51196; +calc_max_flow_masked,5.98637,9889262484581709037,6.01696;6.03279;5.98104;6.00467;5.90329;5.98637;5.91071; +place_max_flow_masked,4.12329,17611571108701524338,4.01337;4.18213;4.31404;4.14071;4.12329;4.08954;4.03029; diff --git a/dev/perf/spf_queue/review-2026-10/results/settled-b.csv b/dev/perf/spf_queue/review-2026-10/results/settled-b.csv new file mode 100644 index 0000000..ef1d574 --- /dev/null +++ b/dev/perf/spf_queue/review-2026-10/results/settled-b.csv @@ -0,0 +1,7 @@ +case,n,e,queries,dst,variant,fallback,W,median_ms,samples,wall_samples_ms +random16,16384,131072,16,none,ref,0,32,36.487333,7,36.090542;35.959583;36.007542;36.487333;37.377167;37.102084;37.204959 +clos800,800,320000,16,none,ref,0,2,29.811083,7,30.447334;29.933166;29.725458;29.967459;29.711791;29.811083;29.528292 +chain2048,2048,2047,256,none,ref,0,32,5.354125,7,5.354125;5.338375;5.379333;5.297166;5.476250;5.512584;5.302708 +near16,16384,131072,64,near,ref,0,32,0.395167,7,0.395041;0.398792;0.394875;0.395167;0.424417;0.403875;0.394458 +wide20,16384,131072,16,none,ref,0,1048570,50.286542,7,50.904542;50.359750;50.286542;50.461416;50.228625;49.448917;49.680083 +wide25,16384,131072,16,none,ref,1,33554196,50.049500,7,49.963709;50.266833;49.922667;50.049500;50.208000;50.201000;50.021375 diff --git a/dev/perf/spf_queue/review-2026-10/results/settled-heap.csv b/dev/perf/spf_queue/review-2026-10/results/settled-heap.csv new file mode 100644 index 0000000..1b13e44 --- /dev/null +++ b/dev/perf/spf_queue/review-2026-10/results/settled-heap.csv @@ -0,0 +1,7 @@ +case,n,e,queries,dst,variant,fallback,W,median_ms,samples,wall_samples_ms +random16,16384,131072,16,none,ref,0,32,66.158167,7,65.501291;66.360792;66.991167;66.015583;65.004458;66.158167;66.720208 +clos800,800,320000,16,none,ref,0,2,31.214834,7,30.765625;30.921833;31.332292;31.329458;31.445500;30.828375;31.214834 +chain2048,2048,2047,256,none,ref,0,32,3.968333,7,3.945500;3.968333;3.876041;3.986583;4.052458;3.981292;3.927458 +near16,16384,131072,64,near,ref,0,32,0.414542,7,0.414542;0.408208;0.422417;0.401750;0.511000;0.439917;0.376750 +wide20,16384,131072,16,none,ref,0,1048570,52.167875,7,52.122625;51.577041;51.598167;52.167875;53.366667;54.189042;53.137125 +wide25,16384,131072,16,none,ref,1,33554196,52.316375,7,52.712750;52.543958;52.056167;51.818583;52.316375;52.301791;53.811375 diff --git a/dev/perf/spf_queue/review-2026-10/results/settled.csv b/dev/perf/spf_queue/review-2026-10/results/settled.csv new file mode 100644 index 0000000..6c37d15 --- /dev/null +++ b/dev/perf/spf_queue/review-2026-10/results/settled.csv @@ -0,0 +1,7 @@ +case,n,e,queries,dst,variant,fallback,W,median_ms,samples,wall_samples_ms +random16,16384,131072,16,none,ref,0,32,36.302292,7,36.267083;36.252209;36.461292;36.329834;36.278333;36.428250;36.302292 +clos800,800,320000,16,none,ref,0,2,30.552375,7,30.552375;30.614834;30.552375;30.799083;30.420875;30.354875;30.576750 +chain2048,2048,2047,256,none,ref,0,32,5.646583,7,5.629958;5.646583;5.675459;5.604167;5.825583;5.854708;5.641583 +near16,16384,131072,64,near,ref,0,32,0.399458,7,0.399375;0.400292;0.401459;0.397750;0.398125;0.399625;0.399458 +wide20,16384,131072,16,none,ref,0,1048570,50.866667,7,50.945000;51.409333;50.611417;50.734542;51.366167;50.730708;50.866667 +wide25,16384,131072,16,none,ref,1,33554196,52.316458,7,51.991083;52.700875;52.316458;52.266458;52.743542;52.306916;52.581667 diff --git a/dev/perf/spf_queue/review-2026-10/results/singleton.csv b/dev/perf/spf_queue/review-2026-10/results/singleton.csv new file mode 100644 index 0000000..f904009 --- /dev/null +++ b/dev/perf/spf_queue/review-2026-10/results/singleton.csv @@ -0,0 +1,7 @@ +case,n,e,queries,dst,variant,fallback,W,median_ms,samples,wall_samples_ms +random16,16384,131072,16,none,ref,0,32,37.232584,7,43.237917;46.446917;37.663959;36.975792;37.232584;36.434750;37.170750 +clos800,800,320000,16,none,ref,0,2,35.920375,7,35.833750;36.086250;35.904916;36.143000;36.049708;35.366042;35.920375 +chain2048,2048,2047,256,none,ref,0,32,5.007084,7,5.030291;4.919834;5.007084;4.996291;5.026125;4.996833;5.083959 +near16,16384,131072,64,near,ref,0,32,0.402250,7,0.402958;0.397958;0.470084;0.408875;0.402250;0.398000;0.397250 +wide20,16384,131072,16,none,ref,0,1048570,54.110209,7,53.133625;53.488875;55.287875;54.976625;54.198959;53.358917;54.110209 +wide25,16384,131072,16,none,ref,1,33554196,52.396375,7,52.396375;51.643959;52.706292;52.540000;51.862250;51.330000;53.099542 diff --git a/dev/perf/spf_queue/review-2026-10/results/tracked-verification.txt b/dev/perf/spf_queue/review-2026-10/results/tracked-verification.txt new file mode 100644 index 0000000..424b153 --- /dev/null +++ b/dev/perf/spf_queue/review-2026-10/results/tracked-verification.txt @@ -0,0 +1 @@ +97 tracked files compared; changed since review start: [] diff --git a/dev/perf/spf_queue/review-2026-10/results/validate-flow-variant.txt b/dev/perf/spf_queue/review-2026-10/results/validate-flow-variant.txt new file mode 100644 index 0000000..114a384 --- /dev/null +++ b/dev/perf/spf_queue/review-2026-10/results/validate-flow-variant.txt @@ -0,0 +1,8 @@ +excluded=-1 flow=cut=6 +excluded=0 flow=cut=4 +excluded=1 flow=cut=2 +excluded=2 flow=cut=6 +excluded=3 flow=cut=4 +excluded=4 flow=cut=3 +factor=1 placed=2 +factor=2 placed=6 diff --git a/dev/perf/spf_queue/review-2026-10/robustness.cpp b/dev/perf/spf_queue/review-2026-10/robustness.cpp new file mode 100644 index 0000000..f1cda4a --- /dev/null +++ b/dev/perf/spf_queue/review-2026-10/robustness.cpp @@ -0,0 +1,48 @@ +#include +#include +#include +static bool fail_four = false; +void* operator new(std::size_t n) { + if (fail_four && n == 4) { fail_four=false; throw std::bad_alloc(); } + if (void* p=std::malloc(n?n:1)) return p; + throw std::bad_alloc(); +} +void operator delete(void* p) noexcept { std::free(p); } +#ifndef REVIEW_SOURCE +#define REVIEW_SOURCE "baseline.cpp" +#endif +#include REVIEW_SOURCE +using namespace netgraph::core; +int main(int argc,char**argv) { + std::string mode=argc>1?argv[1]:"fault"; + EdgeSelection sel; + if(mode=="fault") { + auto g=StrictMultiDiGraph::from_arrays(8,std::vector{1},std::vector{0},std::vector{1},std::vector{1}); + fail_four=true; + try { (void)shortest_paths(g,0,std::nullopt,true,sel); } + catch(const std::bad_alloc&) { std::cout<<"caught forward bad_alloc\n"; } + auto r=shortest_paths(g,1,std::nullopt,true,sel); + std::cout<<"forward distance[0]="<{0},std::vector{1},std::vector{1},std::vector{1}); + fail_four=true; + try { (void)shortest_paths_to(rev,0,true,sel); } + catch(const std::bad_alloc&) { std::cout<<"caught reverse bad_alloc\n"; } + auto t=shortest_paths_to(rev,1,true,sel); + std::cout<<"reverse distance[0]="< s,d;std::vector a;std::vector w; + for(int v=1;v<=1024;++v){s.push_back(0);d.push_back(v);a.push_back(1);w.push_back(c);} + s.push_back(1025);d.push_back(1026);a.push_back(1);w.push_back(63); + s.push_back(1025);d.push_back(1026);a.push_back(1);w.push_back(1); + auto g=StrictMultiDiGraph::from_arrays(1027,s,d,a,w); + auto r=shortest_paths(g,0,std::nullopt,true,sel); + if(r.first[1]!=c) return 2; + if(c==1 || c==63)std::cout<<"after "<{0},std::vector{1},std::vector{1},std::vector{1}); + (void)shortest_paths(g,0,std::nullopt,true,sel); + std::cout<<"after N=2 graph: bucket item capacity bytes="< +#include +#include +using namespace netgraph::core; +static bool eq(const auto&a,const auto&b) {return a.first==b.first&&a.second.parent_offsets==b.second.parent_offsets&&a.second.parents==b.second.parents&&a.second.via_edges==b.second.via_edges;} +static void checks() { + for(Cost k: {Cost(0),Cost(1),Cost(65534),Cost(65535),Cost(65536),(Cost(1)<<60)-1}) { + auto g=StrictMultiDiGraph::from_arrays(8,std::vector{0,0,1,2,3,4,6},std::vector{1,2,3,3,4,5,7},std::vector{1,2,4,8,16,32,64},std::vector{k,k,0,0,k,0,1}); + auto nm=std::make_unique(8);auto em=std::make_unique(7); + std::fill_n(nm.get(),8,true);std::fill_n(em.get(),7,true); + std::vector res(g.capacity_view().begin(),g.capacity_view().end()); + for(int mp=0;mp<2;++mp)for(int me=0;me<2;++me)for(int tb=0;tb<2;++tb)for(int rc=0;rc<2;++rc)for(int mask=0;mask<2;++mask) { + EdgeSelection sel;sel.multi_edge=me;sel.require_capacity=rc;sel.tie_break=tb?EdgeTieBreak::PreferHigherResidual:EdgeTieBreak::Deterministic; + em[0]=!mask;nm[2]=!mask; + for(int dest=-1;dest<8;++dest) { + std::optional dst=dest<0?std::nullopt:std::optional(dest); + auto a=shortest_paths(g,0,dst,mp,sel,res,{nm.get(),8},{em.get(),7},SpfQueue::Heap); + auto b=shortest_paths(g,0,dst,mp,sel,res,{nm.get(),8},{em.get(),7},SpfQueue::Bucket); + spfx::HeapQueue h;spfx::Workspace ws;auto c=spfx::spf_variant(g,0,dst,mp,sel,res,{nm.get(),8},{em.get(),7},h,ws,k,1); + if(!eq(a,b)||!eq(a,c))throw std::runtime_error("forward mismatch"); + if(dest>=0){auto x=shortest_paths_to(g,dest,mp,sel,res,{nm.get(),8},{em.get(),7},{},SpfQueue::Heap);auto y=shortest_paths_to(g,dest,mp,sel,res,{nm.get(),8},{em.get(),7},{},SpfQueue::Bucket);if(!eq(x,y))throw std::runtime_error("reverse mismatch");} + } + } + } + for(int n:{0,1,8}){ + auto g=StrictMultiDiGraph::from_arrays(n,{},{},{},{}); + auto a=shortest_paths(g,0,std::nullopt,true,EdgeSelection{}); + auto b=shortest_paths_to(g,0,true,EdgeSelection{}); + if(a.first.size()!=std::size_t(n)||b.first.size()!=std::size_t(n)||a.second.parent_offsets.size()!=std::size_t(n+1))throw std::runtime_error("empty mismatch"); + } +} +int main(){checks();std::thread t(checks);checks();t.join();std::cout<<"PASS: boundary widths, near-int64-bound, zero costs, edgeless, forward/reverse, reused and concurrent threads\n";} diff --git a/dev/perf/spf_queue/review-2026-10/settled.patch b/dev/perf/spf_queue/review-2026-10/settled.patch new file mode 100644 index 0000000..31cfe2b --- /dev/null +++ b/dev/perf/spf_queue/review-2026-10/settled.patch @@ -0,0 +1,20 @@ +--- a/src/shortest_paths.cpp ++++ b/src/shortest_paths.cpp +@@ -580,7 +580,7 @@ + // Process edges grouped by destination node (parallel edges are consecutive in CSR). + while (i < end) { + NodeId v = col[i]; +- if (use_node_mask && !node_mask[static_cast(v)]) { ++ if (settled[static_cast(v)] || (use_node_mask && !node_mask[static_cast(v)])) { + std::size_t j_skip = i; while (j_skip < end && col[j_skip] == v) ++j_skip; i = j_skip; continue; + } + +@@ -829,7 +829,7 @@ + std::size_t i = start; + while (i < end) { + NodeId u = icol[i]; +- if (use_node_mask && !node_mask[static_cast(u)]) { ++ if (settled[static_cast(u)] || (use_node_mask && !node_mask[static_cast(u)])) { + std::size_t j_skip = i; while (j_skip < end && icol[j_skip] == u) ++j_skip; i = j_skip; continue; + } + Cost min_edge_cost = kInf; diff --git a/dev/perf/spf_queue/review-2026-10/singleton.patch b/dev/perf/spf_queue/review-2026-10/singleton.patch new file mode 100644 index 0000000..c01ae87 --- /dev/null +++ b/dev/perf/spf_queue/review-2026-10/singleton.patch @@ -0,0 +1,29 @@ +--- a/src/shortest_paths.cpp ++++ b/src/shortest_paths.cpp +@@ -304,6 +304,9 @@ + std::vector occ; // one bit per non-empty bucket + std::size_t W = 0, cur_b = 0, pending = 0; + Cost cur = 0, stride = 1; ++ Cost sole_cost = 0; ++ std::size_t sole_bucket = 0; ++ bool sole = false; + + void begin(std::size_t width, Cost stride_) { + stride = stride_; +@@ -333,6 +336,8 @@ + void push(Cost c, Cap nr, NodeId v) { + const std::size_t b = bucket_of(c); + auto& vec = buckets[b]; ++ sole = pending == 0; ++ if (sole) { sole_cost = c; sole_bucket = b; } + if (vec.empty()) occ[b >> 6] |= (std::uint64_t{1} << (b & 63)); + vec.push_back({nr, v}); + if (b == cur_b) std::push_heap(vec.begin(), vec.end(), Greater{}); +@@ -341,6 +346,7 @@ + // Advance to the next non-empty bucket when the active one is exhausted. + // Precondition: pending > 0. + void settle_active() { ++ if (sole) { cur = sole_cost; cur_b = sole_bucket; return; } + if (!buckets[cur_b].empty()) return; + std::size_t i = cur_b + 1; if (i == W) i = 0; + std::size_t w = i >> 6; diff --git a/dev/perf/spf_queue/review-2026-10/validate-flow.cpp b/dev/perf/spf_queue/review-2026-10/validate-flow.cpp new file mode 100644 index 0000000..b3412a6 --- /dev/null +++ b/dev/perf/spf_queue/review-2026-10/validate-flow.cpp @@ -0,0 +1,28 @@ +#include "netgraph/core/algorithms.hpp" +#include "netgraph/core/backend.hpp" +#include "netgraph/core/flow_policy.hpp" +#include "netgraph/core/max_flow.hpp" +#include +#include +using namespace netgraph::core; +int main(){ + auto g=StrictMultiDiGraph::from_arrays(4,std::vector{0,0,1,1,2},std::vector{1,2,2,3,3},std::vector{3,4,1,2,4},std::vector{1,4,2,2,1}); + bool em[5];auto s=g.edge_src_view();auto d=g.edge_dst_view();auto cap=g.capacity_view(); + for(int excluded=-1;excluded<5;++excluded){ + for(int e=0;e<5;++e)em[e]=e!=excluded; + auto [total,sm]=calc_max_flow(g,0,3,FlowPlacement::Proportional,false,true,true,true,true,{},em); + double balance[4]={};for(int e=0;e<5;++e){double f=sm.edge_flows[e];if(f<-1e-7||f>cap[e]+1e-7||(!em[e]&&std::abs(f)>1e-7))throw std::runtime_error("capacity/mask");balance[s[e]]+=f;balance[d[e]]-=f;} + for(int v=0;v<4;++v)if(std::abs(balance[v]-(v==0?total:v==3?-total:0))>1e-7)throw std::runtime_error("conservation"); + double cut=1e30;for(int subset=1;subset<8;subset+=2){double k=0;for(int e=0;e<5;++e)if(em[e]&&(subset&(1<1e-7)throw std::runtime_error("optimality"); + double reported=0;for(auto e:sm.min_cut.edges)reported+=cap[e];if(std::abs(reported-total)>1e-7)throw std::runtime_error("reported cut"); + std::cout<<"excluded="<(make_cpu_backend());auto gh=algs->build_graph(g);ExecutionContext ctx(algs,gh); + for(double factor:{1.,2.}){ + FlowPolicyConfig cfg;cfg.max_path_cost_factor=factor;cfg.require_capacity=true;cfg.multipath=true; + FlowPolicy p(ctx,cfg);FlowGraph fg(g);auto res=p.place_demand(fg,0,3,1,100); + double expected=factor==1.?2.:6.;if(std::abs(res.first-expected)>1e-7)throw std::runtime_error("factor cap"); + std::cout<<"factor="< "$r/results/$spec-variant.txt" +done +NGRAPH_CORE_BATCH_THREADS=1 NGRAPH_CORE_SENSITIVITY_THREADS=1 build/perf/bitgate-old > "$r/results/bitgate-old.txt" +cmp "$r/results/bitgate-old.txt" "$r/results/bitgate-variant.txt" +shasum -a 256 "$r/results/bitgate-old.txt" "$r/results/bitgate-variant.txt" > "$r/results/bitgate-sha256.txt" +echo 'targeted flow certificates, cost factors, and bitgate passed under ASan/UBSan' diff --git a/dev/perf/spf_queue/run_aba.sh b/dev/perf/spf_queue/run_aba.sh new file mode 100755 index 0000000..5a4aeff --- /dev/null +++ b/dev/perf/spf_queue/run_aba.sh @@ -0,0 +1,24 @@ +#!/usr/bin/env bash +# Fresh process per variant; production reference first and last (A1 ... A2). +set -euo pipefail +cd "$(dirname "$0")/../../.." +out=${1:-dev/perf/spf_queue/results/first} +samples=${2:-9} +mkdir -p "$out" +bin=build/perf/cpu-queue +{ + echo "date: $(date -u +%Y-%m-%dT%H:%M:%SZ)"; echo "commit: $(git rev-parse HEAD)"; sysctl -n machdep.cpu.brand_string + shasum -a 256 dev/perf/spf_queue/*.hpp dev/perf/spf_queue/*.cpp src/shortest_paths.cpp src/strict_multidigraph.cpp + "${CXX:-clang++}" --version | head -1 +} > "$out/environment.txt" +for phase in ref:a1 heap-fresh:b heap-full:b heap-sparse:b bucket-fresh:b bucket-full:b bucket-sparse:b bsort-fresh:b bsort-sparse:b ref:a2; do + v=${phase%%:*}; tag=${phase##*:} + uptime >> "$out/load.txt" + "$bin" time "$v" "$samples" > "$out/time-$v-$tag.csv" +done +for v in ref heap-sparse bucket-sparse bsort-sparse; do + uptime >> "$out/load.txt" + "$bin" sweep "$v" "$samples" 2097152 > "$out/sweep-$v.csv" +done +uptime >> "$out/load.txt" +echo done diff --git a/dev/perf/spf_queue/run_core_aba.sh b/dev/perf/spf_queue/run_core_aba.sh new file mode 100755 index 0000000..ff1c557 --- /dev/null +++ b/dev/perf/spf_queue/run_core_aba.sh @@ -0,0 +1,26 @@ +#!/usr/bin/env bash +# Core-level old/new/old A/B/A on the harness workloads: the `ref` variant is the +# production shortest_paths of whichever sources the binary was built from. +# cpu-queue-old: previous sources (git archive of the base commit) +# cpu-queue: this worktree; B-heap forces the heap route in the new binary +set -euo pipefail +cd "$(dirname "$0")/../../.." +out=${1:-dev/perf/spf_queue/results/core} +samples=${2:-9} +mkdir -p "$out" +{ + echo "date: $(date -u +%Y-%m-%dT%H:%M:%SZ)"; echo "commit: $(git rev-parse HEAD)" + shasum -a 256 build/perf/cpu-queue-old build/perf/cpu-queue src/shortest_paths.cpp +} > "$out/environment.txt" +for phase in a1-old b-new b-new-heap a2-old; do + uptime >> "$out/load.txt" + case $phase in + *old) bin=build/perf/cpu-queue-old; envs=() ;; + b-new) bin=build/perf/cpu-queue; envs=() ;; + b-new-heap) bin=build/perf/cpu-queue; envs=(NGRAPH_CORE_SPF_QUEUE=heap) ;; + esac + env ${envs[@]+"${envs[@]}"} "$bin" time ref "$samples" > "$out/time-$phase.csv" + env ${envs[@]+"${envs[@]}"} "$bin" sweep ref "$samples" 2097152 > "$out/sweep-$phase.csv" +done +uptime >> "$out/load.txt" +echo done diff --git a/dev/perf/spf_queue/run_netgraph_aba.sh b/dev/perf/spf_queue/run_netgraph_aba.sh new file mode 100755 index 0000000..707a4ca --- /dev/null +++ b/dev/perf/spf_queue/run_netgraph_aba.sh @@ -0,0 +1,35 @@ +#!/usr/bin/env bash +# Old/new/old A/B/A on realistic NetGraph workloads, one fresh process per phase. +# A1: main worktree build (fbab119) B: this worktree B-heap: this worktree with +# NGRAPH_CORE_SPF_QUEUE=heap (in-binary control) A2: main worktree build again. +set -euo pipefail +cd "$(dirname "$0")/../../.." +out=${1:-dev/perf/spf_queue/results/netgraph} +samples=${2:-5} +old=${OLD_CORE:-/Users/networmix/ws/NetGraph-Core-main} +new=$PWD +py=/Users/networmix/ws/NetGraph/venv/bin/python +bench=dev/perf/spf_queue/bench_netgraph.py +mkdir -p "$out" +{ + echo "date: $(date -u +%Y-%m-%dT%H:%M:%SZ)" + echo "new: $(git rev-parse HEAD) (dirty: $(git status --short | wc -l | tr -d ' ') paths)" + echo "old: $(git -C "$old" rev-parse HEAD)" + echo "netgraph: $(git -C /Users/networmix/ws/NetGraph rev-parse HEAD)" + shasum -a 256 "$bench" "$new"/venv/lib/python3.14/site-packages/_netgraph_core*.so "$old"/venv/lib/python3.14/site-packages/_netgraph_core*.so + sysctl -n machdep.cpu.brand_string +} > "$out/environment.txt" +run() { # label core-root extra-env + local label=$1 root=$2; shift 2 + uptime >> "$out/load.txt" + # PYTHONHASHSEED pins NetGraph's set-iteration order so Monte Carlo result + # digests are comparable across processes (verified: with a random seed the + # digests differ between two runs of the same build). + env "$@" PYTHONHASHSEED=0 PYTHONPATH="$root/venv/lib/python3.14/site-packages:$root/python" "$py" "$bench" "$label" "$samples" > "$out/$label.csv" +} +run a1-old "$old" +run b-new "$new" +run b-new-heap "$new" NGRAPH_CORE_SPF_QUEUE=heap +run a2-old "$old" +uptime >> "$out/load.txt" +echo done diff --git a/dev/perf/spf_queue/spf_variants.hpp b/dev/perf/spf_queue/spf_variants.hpp new file mode 100644 index 0000000..653cd58 --- /dev/null +++ b/dev/perf/spf_queue/spf_variants.hpp @@ -0,0 +1,492 @@ +// Experimental copies of the production forward SPF loop (src/shortest_paths.cpp, +// shortest_paths_core) with the priority queue and the scratch workspace made +// pluggable. The relaxation, selection, tie-break and predecessor rules are kept +// verbatim so that any observable difference is attributable to the queue or +// the workspace policy. Research code only; not part of the library. +#pragma once + +#include "netgraph/core/constants.hpp" +#include "netgraph/core/shortest_paths.hpp" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace spfx { + +using namespace netgraph::core; +constexpr Cost INF = std::numeric_limits::max(); +using QItem = std::tuple; + +// Reference queue: a binary heap over (cost, -bottleneck, node), the exact key +// std::priority_queue uses in production. Keys are unique per push (a node is +// re-pushed only with a strictly smaller cost or a strictly larger bottleneck), so +// any correct binary heap pops in the same order as std::priority_queue. +struct HeapQueue { + static constexpr const char* name = "heap"; + std::vector h; + static bool gt(const QItem& a, const QItem& b) { return a > b; } + void begin(Cost, Cost) { h.clear(); } + void end() { h.clear(); } + bool empty() const { return h.empty(); } + Cost top_cost() { return std::get<0>(h.front()); } + QItem pop() { + std::pop_heap(h.begin(), h.end(), gt); + QItem t = h.back(); h.pop_back(); return t; + } + void push(Cost c, Cap nr, NodeId v) { + h.emplace_back(c, nr, v); + std::push_heap(h.begin(), h.end(), gt); + } +}; + +// Monotone bucket queue with ordered buckets. Dijkstra pops keys in +// non-decreasing cost order and every push is >= the cost being popped, so with +// W = max_cost/stride + 1 cyclic buckets each bucket holds exactly one cost value +// at any time. The active bucket is a binary heap on (-bottleneck, node); pushes +// into it (zero-cost edges) keep the heap property. The pop sequence is therefore +// identical to the global heap's (cost, -bottleneck, node) order, including +// stale-entry handling, zero-cost edges, single-path re-pushes and early exit. +template +struct BucketHeapQueueT { + static constexpr const char* name = kPow2 ? "bucket2" : "bucket"; + struct Item { Cap neg_res; NodeId node; }; + static bool gt(const Item& a, const Item& b) { +#ifdef SPFX_BAD_ORDER + return a.node > b.node; // teeth check: ignore bottleneck ordering +#else + return a.neg_res != b.neg_res ? a.neg_res > b.neg_res : a.node > b.node; +#endif + } + std::vector> buckets; + std::vector occ; + std::size_t W = 0, cur_b = 0, pending = 0; + Cost cur = 0, stride = 1; + + void begin(Cost max_cost, Cost stride_) { + stride = stride_ > 0 ? stride_ : 1; + W = static_cast(max_cost / stride) + 1; + if constexpr (kPow2) W = std::bit_ceil(W); // modulo becomes a mask + if (buckets.size() < W) buckets.resize(W); + occ.assign((W + 63) / 64, 0); + cur = 0; cur_b = 0; pending = 0; + } + void end() { + // Early exit can leave items behind; clear only occupied buckets. + for (std::size_t w = 0; w < occ.size(); ++w) { + std::uint64_t word = occ[w]; + while (word) { + const std::size_t b = (w << 6) + static_cast(std::countr_zero(word)); + buckets[b].clear(); + word &= word - 1; + } + occ[w] = 0; + } + pending = 0; + } + bool empty() const { return pending == 0; } + std::size_t bucket_of(Cost c) const { + const Cost q = stride == 1 ? c : c / stride; + if constexpr (kPow2) return static_cast(q) & (W - 1); + else return static_cast(q % static_cast(W)); + } + void push(Cost c, Cap nr, NodeId v) { + const std::size_t b = bucket_of(c); + auto& vec = buckets[b]; + if (vec.empty()) occ[b >> 6] |= (std::uint64_t{1} << (b & 63)); + vec.push_back({nr, v}); + if (b == cur_b) std::push_heap(vec.begin(), vec.end(), gt); + ++pending; + } + void settle_active() { + if (!buckets[cur_b].empty()) return; + std::size_t i = cur_b + 1; if (i == W) i = 0; + std::size_t w = i >> 6; + std::uint64_t word = occ[w] & (~std::uint64_t{0} << (i & 63)); + const std::size_t nwords = occ.size(); + while (!word) { w = (w + 1 == nwords) ? 0 : w + 1; word = occ[w]; } + const std::size_t f = (w << 6) + static_cast(std::countr_zero(word)); + const std::size_t steps = f > cur_b ? f - cur_b : f + W - cur_b; + cur += static_cast(steps) * stride; cur_b = f; + std::make_heap(buckets[f].begin(), buckets[f].end(), gt); + } + Cost top_cost() { settle_active(); return cur; } + QItem pop() { + settle_active(); + auto& vec = buckets[cur_b]; + std::pop_heap(vec.begin(), vec.end(), gt); + const Item it = vec.back(); vec.pop_back(); --pending; + if (vec.empty()) occ[cur_b >> 6] &= ~(std::uint64_t{1} << (cur_b & 63)); + return {cur, it.neg_res, it.node}; + } +}; +using BucketHeapQueue = BucketHeapQueueT; +using BucketPow2Queue = BucketHeapQueueT; + +// Variant of the bucket queue that sorts a bucket once when it becomes active and +// consumes it linearly; same-cost pushes that arrive while the bucket is active +// (zero-cost edges) go to a small side heap, and pop takes the smaller head. +struct BucketSortQueue { + static constexpr const char* name = "bsort"; + using Item = BucketHeapQueue::Item; + static bool lt(const Item& a, const Item& b) { + return a.neg_res != b.neg_res ? a.neg_res < b.neg_res : a.node < b.node; + } + static bool gt(const Item& a, const Item& b) { return lt(b, a); } + std::vector> buckets; + std::vector occ; + std::vector side; // heap of same-cost pushes into the active bucket + std::size_t W = 0, cur_b = 0, pending = 0, head = 0; + Cost cur = 0, stride = 1; + + void begin(Cost max_cost, Cost stride_) { + stride = stride_ > 0 ? stride_ : 1; + W = static_cast(max_cost / stride) + 1; + if (buckets.size() < W) buckets.resize(W); + occ.assign((W + 63) / 64, 0); + side.clear(); cur = 0; cur_b = 0; pending = 0; head = 0; + } + void end() { + for (std::size_t w = 0; w < occ.size(); ++w) { + std::uint64_t word = occ[w]; + while (word) { + const std::size_t b = (w << 6) + static_cast(std::countr_zero(word)); + buckets[b].clear(); + word &= word - 1; + } + occ[w] = 0; + } + buckets[cur_b].clear(); side.clear(); pending = 0; head = 0; + } + bool empty() const { return pending == 0; } + std::size_t bucket_of(Cost c) const { + return static_cast((c / stride) % static_cast(W)); + } + bool active_empty() const { return head >= buckets[cur_b].size() && side.empty(); } + void push(Cost c, Cap nr, NodeId v) { + const std::size_t b = bucket_of(c); + if (b == cur_b) { + side.push_back({nr, v}); + std::push_heap(side.begin(), side.end(), gt); + } else { + auto& vec = buckets[b]; + if (vec.empty()) occ[b >> 6] |= (std::uint64_t{1} << (b & 63)); + vec.push_back({nr, v}); + } + ++pending; + } + void settle_active() { + if (!active_empty()) return; + buckets[cur_b].clear(); head = 0; + std::size_t i = cur_b + 1; if (i == W) i = 0; + std::size_t w = i >> 6; + std::uint64_t word = occ[w] & (~std::uint64_t{0} << (i & 63)); + const std::size_t nwords = occ.size(); + while (!word) { w = (w + 1 == nwords) ? 0 : w + 1; word = occ[w]; } + const std::size_t f = (w << 6) + static_cast(std::countr_zero(word)); + const std::size_t steps = f > cur_b ? f - cur_b : f + W - cur_b; + cur += static_cast(steps) * stride; cur_b = f; + occ[f >> 6] &= ~(std::uint64_t{1} << (f & 63)); // active bucket is tracked by head/side + auto& vec = buckets[f]; + std::sort(vec.begin(), vec.end(), lt); + } + Cost top_cost() { settle_active(); return cur; } + QItem pop() { + settle_active(); + auto& vec = buckets[cur_b]; + Item it; + if (head < vec.size() && (side.empty() || lt(vec[head], side.front()))) { + it = vec[head++]; + } else { + std::pop_heap(side.begin(), side.end(), gt); + it = side.back(); side.pop_back(); + } + --pending; + return {cur, it.neg_res, it.node}; + } +}; + +enum class WsMode { Fresh, ReuseFull, ReuseSparse, ReuseHybrid }; +// ReuseHybrid tracks touched nodes like ReuseSparse but chooses the reset, output +// and DAG-conversion strategy at the end of the query from the touched count. + +// Scratch arrays of the production loop. Fresh: allocate per query as production +// does (including reserve(E) on the entry arrays). ReuseFull: keep the vectors and +// reset all N entries. ReuseSparse: keep the vectors and reset only touched nodes. +struct Workspace { + std::vector dist; + std::vector minres; + std::vector pred_head, pred_tail; + std::vector settled; + std::vector ent_parent; + std::vector ent_edge; + std::vector ent_next; + std::vector touched; + WsMode mode = WsMode::Fresh; + + bool tracking() const { return mode == WsMode::ReuseSparse || mode == WsMode::ReuseHybrid; } + // Decisions taken after the search from the touched fraction (hybrid only). + bool sparse_reset() const { + return mode == WsMode::ReuseSparse || (mode == WsMode::ReuseHybrid && touched.size() * 4 < dist.size()); + } + void begin(std::int32_t n, std::int32_t e) { + const auto N = static_cast(n); + if (tracking()) { + if (dist.size() != N) { + dist.assign(N, INF); minres.assign(N, 0); pred_head.assign(N, -1); + pred_tail.assign(N, -1); settled.assign(N, 0); + } + touched.clear(); + } else { + dist.assign(N, INF); minres.assign(N, 0); pred_head.assign(N, -1); + pred_tail.assign(N, -1); settled.assign(N, 0); + } + ent_parent.clear(); ent_edge.clear(); ent_next.clear(); + if (mode == WsMode::Fresh) { + const auto E = static_cast(e); + ent_parent.reserve(E); ent_edge.reserve(E); ent_next.reserve(E); + } + } + inline void touch(NodeId v) { if (tracking()) touched.push_back(v); } + void end() { + if (!tracking()) return; + if (sparse_reset()) { + for (auto v : touched) { + const auto i = static_cast(v); + dist[i] = INF; minres[i] = 0; pred_head[i] = -1; pred_tail[i] = -1; settled[i] = 0; + } + } else { + std::fill(dist.begin(), dist.end(), INF); std::fill(minres.begin(), minres.end(), 0); + std::fill(pred_head.begin(), pred_head.end(), -1); std::fill(pred_tail.begin(), pred_tail.end(), -1); + std::fill(settled.begin(), settled.end(), 0); + } + touched.clear(); + } +}; + +// Copy of shortest_paths_core with the queue and workspace injected. +template +std::pair, PredDAG> +spf_variant(const StrictMultiDiGraph& g, NodeId src, + std::optional dst, + bool multipath_arg, + const EdgeSelection& selection, + std::span residual, + std::span node_mask, + std::span edge_mask, + Queue& pq, Workspace& ws, Cost max_cost, Cost stride) { + const auto N = g.num_nodes(); + const auto row = g.row_offsets_view(); + const auto col = g.col_indices_view(); + const auto aei = g.adj_edge_index_view(); + const auto cost = g.cost_view(); + const auto cap = g.capacity_view(); + + ws.begin(N, g.num_edges()); + auto& dist = ws.dist; + auto& min_residual_to_node = ws.minres; + auto& pred_head = ws.pred_head; + auto& pred_tail = ws.pred_tail; + auto& ent_parent = ws.ent_parent; + auto& ent_edge = ws.ent_edge; + auto& ent_next = ws.ent_next; + auto& settled = ws.settled; + + auto finish_dist = [&]() { + std::vector out; + if (ws.mode == WsMode::Fresh) { out = std::move(dist); dist.clear(); } + else if (ws.mode == WsMode::ReuseFull || !ws.sparse_reset()) { out = dist; } + else { + out.assign(static_cast(N), INF); + for (auto v : ws.touched) out[static_cast(v)] = dist[static_cast(v)]; + } + return out; + }; + + const bool use_node_mask = (node_mask.size() == static_cast(g.num_nodes())); + const bool use_edge_mask = (edge_mask.size() == static_cast(g.num_edges())); + const bool src_allowed = (src >= 0 && src < N && (!use_node_mask || node_mask[static_cast(src)])); + if (src_allowed) { + dist[static_cast(src)] = static_cast(0); + min_residual_to_node[static_cast(src)] = std::numeric_limits::max(); + ws.touch(src); + } + + auto pred_clear = [&](std::size_t v){ pred_head[v] = -1; pred_tail[v] = -1; }; + auto pred_append = [&](std::size_t v, NodeId p, EdgeId e){ + const auto idx = static_cast(ent_parent.size()); + ent_parent.push_back(p); ent_edge.push_back(e); ent_next.push_back(-1); + if (pred_head[v] < 0) { pred_head[v] = idx; } + else { ent_next[static_cast(pred_tail[v])] = idx; } + pred_tail[v] = idx; + }; + if (!src_allowed) { + PredDAG dag; + dag.parent_offsets.assign(static_cast(N + 1), 0); + auto out = finish_dist(); + ws.end(); + return {std::move(out), std::move(dag)}; + } + + pq.begin(max_cost, stride); + pq.push(static_cast(0), -std::numeric_limits::max(), src); + Cost best_dst_cost = std::numeric_limits::max(); + bool have_best_dst = false; + const bool early_exit = dst.has_value(); + const NodeId dst_node = dst.value_or(-1); + + const bool has_residual = (residual.size() == static_cast(g.num_edges())); + const bool require_cap = selection.require_capacity || has_residual; + const bool multipath = multipath_arg; + + std::vector sel_buf; sel_buf.reserve(16); + while (!pq.empty()) { + auto [d_u, neg_res_u, u] = pq.pop(); + if (u < 0 || u >= N) continue; + if (d_u > dist[static_cast(u)]) continue; + if (!multipath && d_u == dist[static_cast(u)] && + -neg_res_u < min_residual_to_node[static_cast(u)] - kEpsilon) continue; + settled[static_cast(u)] = 1; + + if (early_exit && u == dst_node && !have_best_dst) { best_dst_cost = d_u; have_best_dst = true; } + if (early_exit && u == dst_node) { + if (pq.empty() || pq.top_cost() > best_dst_cost) break; else continue; + } + + auto start = static_cast(row[static_cast(u)]); + auto end = static_cast(row[static_cast(u)+1]); + std::size_t i = start; + while (i < end) { + NodeId v = col[i]; + if (use_node_mask && !node_mask[static_cast(v)]) { + std::size_t j_skip = i; while (j_skip < end && col[j_skip] == v) ++j_skip; i = j_skip; continue; + } + Cost min_edge_cost = std::numeric_limits::max(); + std::vector& selected_edges = sel_buf; selected_edges.clear(); + double best_rem_for_min_cost = -1.0; + std::size_t j = i; + int best_edge_id = -1; + for (; j < end && col[j] == v; ++j) { + auto e = static_cast(aei[j]); + if (use_edge_mask && !edge_mask[e]) continue; + const Cap rem = has_residual ? residual[e] : cap[e]; + if (require_cap && rem < kMinCap) continue; + const Cost ecost = static_cast(cost[e]); + if (ecost < min_edge_cost) { + min_edge_cost = ecost; + selected_edges.clear(); + if (selection.multi_edge) { + selected_edges.push_back(static_cast(aei[j])); + } else { + best_edge_id = static_cast(e); + best_rem_for_min_cost = static_cast(rem); + } + } else if (ecost == min_edge_cost) { + if (selection.multi_edge) { + selected_edges.push_back(static_cast(aei[j])); + } else { + if (selection.tie_break == EdgeTieBreak::PreferHigherResidual) { + if (static_cast(rem) > best_rem_for_min_cost + kEpsilon) { + best_edge_id = static_cast(e); + best_rem_for_min_cost = static_cast(rem); + } else if (std::abs(static_cast(rem) - best_rem_for_min_cost) <= kEpsilon) { + if (best_edge_id < 0 || static_cast(e) < best_edge_id) { + best_edge_id = static_cast(e); + } + } + } else { + if (best_edge_id < 0 || static_cast(e) < best_edge_id) { + best_edge_id = static_cast(e); + } + } + } + } + } + if (!selection.multi_edge && best_edge_id >= 0) { + selected_edges.clear(); + selected_edges.push_back(static_cast(best_edge_id)); + } + if (!selected_edges.empty()) { + Cost new_cost = static_cast(d_u + min_edge_cost); + auto v_idx = static_cast(v); + Cap max_edge_residual = static_cast(0); + for (auto edge_id : selected_edges) { + const Cap rem = has_residual ? residual[static_cast(edge_id)] + : cap[static_cast(edge_id)]; + if (rem > max_edge_residual) max_edge_residual = rem; + } + Cap path_residual = std::min(min_residual_to_node[static_cast(u)], max_edge_residual); + if (new_cost < dist[v_idx] || + (!multipath && new_cost == dist[v_idx] && !settled[v_idx] && + path_residual > min_residual_to_node[v_idx] + kEpsilon)) { + if (dist[v_idx] == INF) ws.touch(v); + dist[v_idx] = new_cost; + min_residual_to_node[v_idx] = path_residual; + pred_clear(v_idx); + for (auto sel_e : selected_edges) pred_append(v_idx, u, sel_e); + pq.push(new_cost, -path_residual, v); + } + else if (multipath && new_cost == dist[v_idx] && !settled[v_idx]) { + for (auto sel_e : selected_edges) pred_append(v_idx, u, sel_e); + } + } + i = j; + } + if (have_best_dst) { if (pq.empty() || pq.top_cost() > best_dst_cost) break; } + } + pq.end(); + + PredDAG dag; + dag.parent_offsets.assign(static_cast(N+1), 0); + if (ws.tracking() && ws.sparse_reset()) { + for (auto v : ws.touched) { + std::size_t c = 0; + for (std::int32_t i = pred_head[static_cast(v)]; i >= 0; i = ent_next[static_cast(i)]) ++c; + dag.parent_offsets[static_cast(v+1)] = static_cast(c); + } + } else { + for (std::int32_t v=0; v(v)]; i >= 0; i = ent_next[static_cast(i)]) ++c; + dag.parent_offsets[static_cast(v+1)] = static_cast(c); + } + } + for (std::size_t k=1; k(dag.parent_offsets.back())); + dag.via_edges.resize(static_cast(dag.parent_offsets.back())); + auto fill = [&](std::int32_t v) { + auto base = static_cast(dag.parent_offsets[static_cast(v)]); + std::size_t k = 0; + for (std::int32_t i = pred_head[static_cast(v)]; i >= 0; i = ent_next[static_cast(i)]) { + dag.parents[base+k] = ent_parent[static_cast(i)]; + dag.via_edges[base+k] = ent_edge[static_cast(i)]; + ++k; + } + }; + if (ws.tracking() && ws.sparse_reset()) { for (auto v : ws.touched) fill(v); } + else { for (std::int32_t v=0; v p.max_cost) p.max_cost = c; + Cost a = gcd, b = c; while (b) { Cost t = a % b; a = b; b = t; } gcd = a; + } + p.stride = gcd > 0 ? gcd : 1; + return p; +} + +} // namespace spfx diff --git a/dev/perf/spf_queue/summarize.py b/dev/perf/spf_queue/summarize.py new file mode 100644 index 0000000..89b4efa --- /dev/null +++ b/dev/perf/spf_queue/summarize.py @@ -0,0 +1,83 @@ +#!/usr/bin/env python3 +"""Tabulate cpu_queue A/B/A results as Markdown (sequential single-thread medians).""" + +import csv +import glob +import os +import sys + +root = ( + sys.argv[1] + if len(sys.argv) > 1 + else os.path.join(os.path.dirname(__file__), "results", "first") +) + + +def load(pattern): + rows = {} + for path in sorted(glob.glob(os.path.join(root, pattern))): + tag = ( + os.path.basename(path)[len("time-") : -4] + if "time-" in path + else os.path.basename(path)[len("sweep-") : -4] + ) + with open(path) as f: + for r in csv.DictReader(f): + key = (r["case"], r["n"], r["e"], r["queries"], r["dst"]) + rows.setdefault(key, {})[tag] = r + return rows + + +def fmt(r): + if r is None: + return "—" + s = f"{float(r['median_ms']):.3f}" + return s + (" (heap fallback)" if r.get("fallback") == "1" else "") + + +time_rows = load("time-*.csv") +order = [ + "ref-a1", + "heap-fresh-b", + "heap-full-b", + "heap-sparse-b", + "bucket-fresh-b", + "bucket-full-b", + "bucket-sparse-b", + "bsort-fresh-b", + "bsort-sparse-b", + "ref-a2", +] +seen = {t for v in time_rows.values() for t in v} +present = [t for t in order if t in seen] + sorted(t for t in seen if t not in order) +present = [t for t in present if t != "ref-a2"] + ( + ["ref-a2"] if "ref-a2" in seen else [] +) +print( + "| Workload: case / nodes / edges / queries / dst | W | " + + " | ".join(present) + + " |" +) +print("|---|---:|" + "---:|" * len(present)) +for key, v in time_rows.items(): + any_row = next(iter(v.values())) + label = f"{key[0]} / {key[1]} / {key[2]} / {key[3]} / {key[4]}" + print( + f"| {label} | {any_row['W']} | " + + " | ".join(fmt(v.get(t)) for t in present) + + " |" + ) + +sweep_rows = load("sweep-*.csv") +if sweep_rows: + tags = sorted({t for v in sweep_rows.values() for t in v}) + print() + print("| Cost sweep: case / nodes / queries | W | " + " | ".join(tags) + " |") + print("|---|---:|" + "---:|" * len(tags)) + for key, v in sweep_rows.items(): + any_row = next(iter(v.values())) + print( + f"| {key[0]} / {key[1]} / {key[3]} | {any_row['W']} | " + + " | ".join(fmt(v.get(t)) for t in tags) + + " |" + ) diff --git a/dev/perf/spf_queue/summarize_core.py b/dev/perf/spf_queue/summarize_core.py new file mode 100644 index 0000000..b409d8d --- /dev/null +++ b/dev/perf/spf_queue/summarize_core.py @@ -0,0 +1,34 @@ +#!/usr/bin/env python3 +"""Tabulate the Core-level old/new/old A/B/A (results-core) as Markdown.""" + +import csv +import os +import sys + +root = ( + sys.argv[1] + if len(sys.argv) > 1 + else os.path.join(os.path.dirname(__file__), "results", "core") +) +phases = ["a1-old", "b-new", "b-new-heap", "a2-old"] +for kind in ("time", "sweep"): + rows = {} + for p in phases: + with open(f"{root}/{kind}-{p}.csv") as f: + for r in csv.DictReader(f): + key = (r["case"], r["n"], r["e"], r["queries"], r["dst"], r["W"]) + rows.setdefault(key, {})[p] = float(r["median_ms"]) + print( + f"| {kind}: case / nodes / edges / queries / destination | W | " + + " | ".join(phases) + + " | old/new | old/new-heap |" + ) + print("|---|---:|" + "---:|" * (len(phases) + 2)) + for k, v in rows.items(): + lo, hi = min(v["a1-old"], v["a2-old"]), max(v["a1-old"], v["a2-old"]) + print( + f"| {' / '.join(k[:5])} | {k[5]} | " + + " | ".join(f"{v[p]:.3f}" for p in phases) + + f" | {lo / v['b-new']:.2f}–{hi / v['b-new']:.2f} | {lo / v['b-new-heap']:.2f}–{hi / v['b-new-heap']:.2f} |" + ) + print() diff --git a/dev/perf/spf_queue/summarize_netgraph.py b/dev/perf/spf_queue/summarize_netgraph.py new file mode 100644 index 0000000..dab8f4a --- /dev/null +++ b/dev/perf/spf_queue/summarize_netgraph.py @@ -0,0 +1,44 @@ +#!/usr/bin/env python3 +"""Tabulate the NetGraph-workload A/B/A (old/new/old, fresh processes) as Markdown.""" + +import csv +import glob +import os +import sys + +root = ( + sys.argv[1] + if len(sys.argv) > 1 + else os.path.join(os.path.dirname(__file__), "results", "netgraph") +) +phases = ["a1-old", "b-new", "b-new-heap", "a2-old"] +rows: dict[str, dict[str, dict]] = {} +for path in sorted(glob.glob(os.path.join(root, "*.csv"))): + tag = os.path.basename(path)[:-4] + with open(path) as f: + for r in csv.DictReader(f): + rows.setdefault(r["workload"], {})[tag] = r +present = [p for p in phases if any(p in v for v in rows.values())] +print( + "| Workload | " + + " | ".join(f"{p} ms" for p in present) + + " | old/new | checksums |" +) +print("|---|" + "---:|" * len(present) + "---:|---|") +mismatch = 0 +for name, v in rows.items(): + med = {p: float(v[p]["median_s"]) * 1000 for p in present if p in v} + ratio = "" + if "a1-old" in med and "a2-old" in med and "b-new" in med: + ratio = f"{min(med['a1-old'], med['a2-old']) / med['b-new']:.2f}–{max(med['a1-old'], med['a2-old']) / med['b-new']:.2f}" + sums = {v[p]["checksum"] for p in present if p in v} + ok = "same" if len(sums) == 1 else "DIFFER" + if ok != "same": + mismatch += 1 + print( + f"| {name} | " + + " | ".join(f"{med[p]:.2f}" if p in med else "—" for p in present) + + f" | {ratio} | {ok} |" + ) +print() +print(f"checksum mismatches: {mismatch}") diff --git a/dev/research/README.md b/dev/research/README.md new file mode 100644 index 0000000..9bc2e5d --- /dev/null +++ b/dev/research/README.md @@ -0,0 +1,11 @@ +# Research record + +Investigations whose outcome informed the code but whose prototypes are not +part of the library. They are kept for the evidence and the dead ends they +document, not as maintained tools. + +- [`metal_pathfinding/`](metal_pathfinding/): Apple Metal GPU shortest-path + prototypes (two phases, with raw measurements and validation audits). Their + conclusion, that a better CPU queue should come first, led to the work in + [`../perf/spf_queue/`](../perf/spf_queue/). Objective-C++ and Metal; builds + only on macOS with Xcode. diff --git a/dev/research/metal_pathfinding/README.md b/dev/research/metal_pathfinding/README.md new file mode 100644 index 0000000..65d7de3 --- /dev/null +++ b/dev/research/metal_pathfinding/README.md @@ -0,0 +1,293 @@ +# Metal pathfinding investigation + +**Follow-up:** the [optimization research](optimization/README.md) tests active +frontiers, buckets, batch layout and improved result construction. It finds +substantially better batch results, so the initial timings below must not be +treated as a GPU performance ceiling. Both rounds remain exploratory because +the desktop was not isolated for measurement. + +The [consolidated CPU optimisation plan](../../perf/spf_queue/PLAN.md) now governs +implementation order and acceptance. The backend integration notes below remain +relevant to a later Metal follow-up. + +Research against NetGraph-Core `fbab119` on 26–27 September 2026, using an +Apple M4 Max (14 CPU cores, 32 GPU cores, 36 GB unified memory). +This directory contains standalone experiments. It does not register a backend, +change the Python API, or modify production algorithms. + +**Answer:** adding a Metal implementation is technically feasible, and the host +integration is fairly small. A useful, compatible replacement for `Backend.cpu()` +is a substantially larger task. The candidate interface is **distances on an +immutable graph, with optional batches**, particularly for large low-hop +full-source searches, and explicit CPU fallback. It is premature +to make Metal the default SPF implementation or promise faster flow simulation. + +**What the current backend gets right.** `StrictMultiDiGraph` already has immutable +forward and reverse CSR, stable internal edge IDs, nonnegative int64 costs, and +a constructor bound on the sum of costs that prevents path-cost overflow. +These are useful GPU inputs. `Backend` and `Algorithms` provide a dispatch seam; +`FlowPolicy` calls that seam. The CPU implementation is native C++ Dijkstra, +with flat predecessor storage and Python GIL release. Its existing memoization +and reverse SPF also avoid computations that a GPU would otherwise repeat. +The appropriate comparison is this implementation, including parallel CPU +queries, not a Python Dijkstra loop. + +**Where the abstraction needs work.** These are verified properties of the +current source, not newly claimed correctness defects: + +| Area | Current behavior | Consequence for Metal | +|---|---|---| +| Graph ownership | `GraphHandle` contains only `shared_ptr`. CPU construction is non-owning; Python separately keeps the graph alive. | No place for a typed device representation or backend identity. Add owned device state and preserve topology lifetime. | +| Query interface | `spf` / `spf_to` are synchronous, single-query calls returning host vectors and a `PredDAG`. There is no batched SPF or distances-only API. | Cannot amortize dispatch across independent queries through the current interface. Every call produces a host DAG even if the caller only needs distances. | +| Cost semantics | Internal distances are int64; Python offers int64 explicitly and defaults to float64 conversion. | A float32 GPU implementation would change path selection. Keep exact integer arithmetic. | +| Predecessors | Positive-cost ECMP keeps all equal alternatives; zero-cost edges use settle order to remain acyclic. Parallel-edge selection and capacity ties are configurable. | A distance kernel plus tight-edge extraction is insufficient to reproduce the full contract. | +| Result order | Predecessor arrays follow CPU discovery order. Path enumeration consumes that order, including when capped by `max_paths`. | The prototype's deterministic edge-ID order has equivalent positive-cost edge sets, but is not byte-identical or necessarily enumeration-identical. | +| Residuals and masks | Borrowed per-call spans; capacities and residuals are double; a residual span forces capacity gating. Python currently copies residual/mask input. | Compute exact eligibility on the CPU or reproduce these semantics explicitly. Static topology upload does not remove changing-mask work. | +| Max-flow | `calc_max_flow` calls the free `shortest_paths` function directly between residual updates. | Overriding `Backend::spf` does not accelerate `Backend::max_flow`, batch max-flow, or sensitivity when those delegate to the existing CPU functions. | +| KSP | Yen-style enumeration has its own Dijkstra helper and directly calls free SPF for spurs. | Overriding backend SPF does not make KSP run on the GPU. It is also sequentially dependent across accepted paths. | +| FlowPolicy | Calls `ctx_.algorithms->spf`, generally with `dst` and changing flow state; caches some SPF results. | It can use a new backend, but single-call latency, early exit, cache hits, and residual invalidation matter. Batching across dependent placements would change semantics. | +| Downstream selection | NetGraph's context builder explicitly constructs `Backend.cpu()`. | Shipping a factory alone would not enable acceleration downstream. | + +Source pointers: [backend.hpp](../../../include/netgraph/core/backend.hpp), +[algorithms.hpp](../../../include/netgraph/core/algorithms.hpp), +[shortest_paths.hpp](../../../include/netgraph/core/shortest_paths.hpp), +[shortest_paths.cpp](../../../src/shortest_paths.cpp), +[flow_policy.cpp](../../../src/flow_policy.cpp), [max_flow.cpp](../../../src/max_flow.cpp), +[k_shortest_paths.cpp](../../../src/k_shortest_paths.cpp), +[bindings](../../../bindings/python/module.cpp). +Downstream inspection was read-only: `ngraph/analysis/context.py`, +`ngraph/analysis/placement.py`, and `dev/perf/profiles.py` in the sibling NetGraph +checkout. No downstream behavior or integration speedup was tested. + +**What the external research establishes.** Apple supplies a direct C++ Metal +interface, so there is no need to introduce Swift or a tensor framework just to +call compute kernels. An isolated Objective-C++ translation unit also works; +that is what this experiment builds using Command Line Tools and the system +Foundation/Metal frameworks. [Apple Metal-cpp](https://developer.apple.com/metal/cpp/) + +The current Metal language specification supports 64-bit `long`/`ulong`, but +does not support `double`. Its 64-bit atomics are limited: void-returning +`atomic_min_explicit` / `atomic_max_explicit` exist; a general 64-bit atomic +fetch-min/load API is not available. This is a reason to choose a suitable +algorithm, not a reason to abandon exact costs. Apple lists 64-bit atomics from +Apple9 hardware, whereas 64-bit integer math has broader availability. Capability +checks must cover the target hardware family. +[MSL specification, sections 2.1 and 6.16.4.6](https://developer.apple.com/metal/Metal-Shading-Language-Specification.pdf), +[Apple feature tables](https://developer.apple.com/metal/Metal-Feature-Set-Tables.pdf). +The [local compiler probes](results/capabilities.txt) confirm all of these +distinctions on this M4 Max, including successful void-returning 64-bit minimum. +Compilation alone is not a performance test of that atomic operation. + +MPSGraph is a graph of tensor operations, not an off-the-shelf implementation of +NetGraph's routing semantics. MLX offers custom Metal kernels, which is useful +for prototyping, but still leaves the graph algorithm and correctness contract +to us. I found no drop-in implementation of this API in these libraries. +[Apple MPSGraph](https://developer.apple.com/documentation/metalperformanceshadersgraph?changes=__5_7), +[MLX custom Metal kernels](https://ml-explore.github.io/mlx/build/html/dev/custom_metal_kernels.html). + +Gunrock provides useful GPU graph-processing designs based on frontiers and +load balancing, but its advertised backends are CUDA and HIP, not Metal. +cuGraph likewise depends on NVIDIA's CUDA stack. Neither is a library switch +for an Apple GPU. Their existence does suggest a more ambitious implementation +direction: frontier compaction and work-efficient SSSP rather than repeatedly +scanning every edge. That direction was researched, not implemented or timed. +[Gunrock](https://github.com/gunrock/gunrock), +[cuGraph installation](https://docs.nvidia.com/cugraph/26.10/installation/getting_cugraph/). + +**The experiments.** All three kernels compute exact int64 distances with +double-buffered Bellman–Ford-style pull relaxation over incoming CSR. Reverse +routing uses outgoing CSR. They do not race on distance writes and do not need +64-bit atomics. Per-edge eligibility is prepared on the host from finite double +residuals, node masks, and edge masks. The cost of this preparation and buffer +allocation is recorded as `upload_ms`; each warm query reuses that snapshot. +All prototypes currently model capacity-gated, multipath, multi-edge, full-source +queries. General selection options and changing eligibility are not benchmarked. +Every query in a batch shares the same mask/residual snapshot; this is not a +benchmark of independent failure scenarios with different masks per query. + +| Method | Execution | Intended experiment | +|---|---|---| +| `metal_pull` | One thread per query/vertex, separate dependent dispatches; up to eight rounds per command buffer before checking convergence. | Spread one large query across the GPU; measure repeated launch/synchronization costs. | +| `metal_group` | One threadgroup per query, convergence inside the kernel, global-memory ping-pong distance arrays. | Amortize dispatch across many independent sources without a grid-wide barrier. | +| `metal_shared` | One threadgroup per query, with distance arrays in threadgroup memory. | Reduce memory/barrier overhead for small graphs; enabled only when runtime scratch-memory limits permit. | + +Each returns host distance vectors. The measured full result then scans edges +on the CPU and constructs a positive-cost ECMP DAG. **That full timing includes +DAG construction**, but its order differs from the current CPU implementation. +`distance_wall_ms` ends before DAG construction; `gpu_ms` contains command-buffer +GPU timestamps, not end-to-end API latency. Neither should be presented as the +speed of a compatible `Algorithms.spf` replacement. + +The pull algorithms perform `O(Q * H * (V + E))` work, where `H` is +the number of relaxation rounds (up to `V`), versus heap Dijkstra's usual +`O((V + E) log V)` per source. This makes hop depth and degree as important as +vertex count. These kernels are feasibility baselines, not an optimized +frontier/delta-stepping implementation or a bound on what Metal can achieve. +Two int64 distance buffers require `16 * V * Q` bytes: 64 MiB at 65,536 vertices +and 64 sources, before host outputs and DAGs. A dense int64 matrix at the same +vertex count would itself require 32 GiB. An all-pairs approach therefore needs +an explicit memory/work analysis and batching on this 36 GB machine. + +The CPU controls use the actual current `shortest_paths` / `shortest_paths_to` +sources, built with `-O3 -flto -funroll-loops`. Controls include serial full SPF, +an independent distances-only Dijkstra, and both full SPF and distances-only +Dijkstra through ten reusable worker threads. Pool startup is outside timing; +task submission and result allocation +are inside. Profiling is disabled. The experiment does not exercise Python +binding overhead or an integrated flow-placement workload. + +The full suite covers 27 graph/batch configurations: 128–65,536 vertices, +up to 524,288 directed edges, batches of 1–256 queries, nonuniform random costs, +parallel edges/self-loops, leaf–spine fabrics, 32x32 / 100x100 / 200x200 grids, +directed chains, and masked reverse queries with costs above 32 bits. The Clos +and grid shapes were selected after inspecting NetGraph's own benchmark catalogue; +these remain generated fixtures, not a replay of a user's production topology. + +**Correctness evidence.** Every timed sample, including warmups, compares every +distance and the canonical `(child, parent, edge-id)` predecessor multiset to the +current C++ result. The independent CPU Dijkstra is also checked against that +result. Timing excludes verification. Twelve seeded small masked multigraphs +exercise all three GPU methods in both normal and sanitizer/Metal validation +runs. Hand-derived witnesses additionally check: + +- Diamond ECMP, equal-cost parallel edges, positive self-loop exclusion, and an isolated node. +- Reverse distances and forward-oriented predecessor edges. +- Masked source, masked transit node, and combined residual/edge masks. +- A residual just below `kMinCap` versus exactly at the threshold. +- Int64 costs above 2^53, including a one-unit difference between candidate paths. + +The witnesses also deliberately reproduce unsupported simplifications: + +- Float32 equates 16,777,216 and 16,777,217 and rounds a residual immediately below + `kMinCap` up to the threshold. It also erases a `1` versus `1 + 1e-8` capacity tie. +- On a zero-cost `0 -> 1 -> 2 -> 1` graph, distances agree but naive tight-edge + reconstruction contains a cycle; the CPU DAG correctly retains only two edges. +- Full-suite CSVs record how many query DAGs retain exactly the CPU's array order. + Canonical equality is not silently reported as byte-for-byte parity. + +An initial long run exposed a convergence-flag race in the research kernels: +after the end-of-round barrier, a fast lane could reset the flag for the next +round before every lane had read it. An additional barrier after the reads +fixes that ordering. The rejected run is retained under +[results/rejected-race](results/rejected-race/), and is excluded from conclusions. +After correction, each of two 64-query stress cases passed 100 timed repetitions +plus two warmups for each of three kernels (39,168 complete query comparisons). +An additional 20 timed repetitions plus two warmups per case/kernel passed with +ASan/UBSan and Metal API/shader validation (8,448 query comparisons). +These checks found and then exercised the fix; they are not a proof of every +possible shader interleaving. See [stress.csv](results/stress.csv), +[stress-sanitized.csv](results/stress-sanitized.csv), +[validation log](results/stress-validation.txt), and +[witnesses](results/witnesses-sanitized.txt). + +**Performance acceptance remains separate from correctness.** The script uses +fresh processes in CPU / GPU / CPU order on this Mac, nine timed samples per row +after two warmups, and records each raw sample, pipeline startup, upload cost, +CPU load, and GPU utilization. Builds and test suites do not overlap those runs. +The desktop has active background work. These observations must be labelled +exploratory; the repository's quiet-machine requirement is not yet satisfied. +No production speedup or universal CPU/GPU crossover is established by them. +See [A/B/A data](results/aba/) and the generated +[timing table](results/aba/summary.md), including CPU-control drift. + +The final run's second CPU-load snapshots were 90.7%, 90.75%, and 73.37% idle +before A1, B, and A2. Some tiny-query CPU controls drifted substantially +(up to 67% between phase medians), so an automatic dispatch threshold cannot +be justified from this run. Selected raw observations below are milliseconds +for distances **plus DAG construction**; CPU batches use ten workers: + +| Generated graph | Queries | CPU A1 | Metal B | CPU A2 | +|---|---:|---:|---:|---:| +| Random, 1,024 vertices / 8,192 edges | 1 | 0.145 | 0.707 | 0.115 | +| Random, 65,536 vertices / 524,288 edges | 1 | 20.762 | 4.922 | 22.345 | +| Random, 16,384 vertices / 131,072 edges | 64 | 28.290 | 54.004 | 28.429 | +| Clos, 800 vertices / 320,000 edges | 64 | 17.462 | 72.452 | 17.634 | +| Grid, 40,000 vertices / 159,200 edges | 1 | 2.913 | 8.408 | 2.937 | + +These observations identify follow-up candidates rather than establish a +validated speedup. Large low-hop full-source searches deserve a quiet repeat; +small graphs and deep grids/chains do not provide a general reason to offload +with these algorithms. Dropping the DAG changes the experiment materially: +at 16,384 random vertices and 64 queries, CPU distances-only controls were +14.898 / 15.059 ms, with 9.176 ms for the GPU distance stage. Conversely, +the 800-vertex Clos batch was 2.672 / 2.661 ms on the CPU versus 5.681 ms for +the GPU distance stage. Batching alone is not a sufficient selection rule. +Pipeline startup in this repeat was 24.135 ms; the shader cache had already +been exercised, so this is not a cold-install startup measurement. + +**Implementation sequence, revised after the CPU experiments.** Follow the +[CPU plan](../../perf/spf_queue/PLAN.md) before selecting a GPU backend. Its +[queue-substitution experiment](../../perf/spf_queue/) showed that an ordered +bucket queue inside the existing search reproduces the native result contract +bit-exactly and runs 1.3–1.9x faster on weighted graphs; BFS and +bounded-integer buckets are its special cases, with a width limit and heap +fallback. It is implemented in the working tree and measured old/new/old at the +Core level and through NetGraph. A batch or distances-only API is conditional +on demonstrated callers. +Reuse reverse SPF and caches before increasing the query count, and measure +representative NetGraph workloads end to end. + +Then, if a quiet benchmark justifies it, add an opt-in `Backend.metal()` or an +explicit batch accelerator. Store owned CSR buffers and a backend identity in +the graph handle; keep the graph immutable and the masks versioned or copied per +request. A macOS-only Objective-C++ file and optional CMake Metal/Foundation +linkage are sufficient for the host layer. Keep per-request scratch state safe +under concurrent GIL-released callers. Runtime device/pipeline failures need a +documented policy, and non-Apple builds must retain the CPU-only path. +A first adapter can hold `make_cpu_backend()` and delegate its unimplemented +virtual methods there; it does not require rewriting every algorithm at once. +That is a straightforward way to add a selectable factory, but it must expose +which operations actually execute on the GPU rather than imply that delegating +max-flow or KSP became accelerated. + +For the first compatible SPF implementation, retain int64 arithmetic and exact +CPU eligibility; keep zero-cost DAGs, single-path capacity tie-breaking, +fanout-edge semantics, and any unimplemented selection modes on CPU. Preserve +existing predecessor order before declaring parity for the existing result API, +as required by the consolidated CPU plan. A new distances-only batch API avoids most DAG-specific compatibility +work. It must still distinguish supported options from silently ignored ones. + +The [follow-up](optimization/README.md) has since tested frontier/bucket methods, +GPU predecessor extraction and guarded 32-bit paths. Production adoption still +requires a compatible result contract and a measured win over the improved CPU. +Directly moving the existing heap-based Dijkstra loop to a GPU is unlikely to +expose useful parallel work. Dense all-pairs tensor formulations change the +memory/work complexity and are not the straightforward default for sparse +network graphs. These are engineering judgments, not measured claims about +unimplemented algorithms. + +Keep max-flow, KSP, and placement on the CPU initially. Accelerating their SPF +internals requires additional dispatch plumbing and end-to-end validation of +flow amounts, feasibility, conservation, cuts, costs, masks, and cost factors; +the present distance experiment provides no such validation. Bindings and +`python/netgraph_core/_docs.py` must change together if public APIs are added. +Metal runtime tests need a real Apple GPU CI runner. Local success does not +replace CI. + +**Reproduction.** Run from the repository root on a Mac with a Metal device: + +```bash +bash dev/research/metal_pathfinding/build.sh +build/metal_pathfinding/capabilities +build/metal_pathfinding/experiment gpu dev/research/metal_pathfinding/sssp.metal witnesses 1 +build/metal_pathfinding/experiment gpu dev/research/metal_pathfinding/sssp.metal correctness 2 +build/metal_pathfinding/experiment gpu dev/research/metal_pathfinding/sssp.metal stress 100 + +# Close out other compute work before making performance claims. +# Use a fresh output directory to preserve the recorded run. +bash dev/research/metal_pathfinding/run_aba.sh /tmp/netgraph-metal-aba +venv/bin/python dev/research/metal_pathfinding/summarize.py /tmp/netgraph-metal-aba + +bash dev/research/metal_pathfinding/build.sh sanitize +MTL_DEBUG_LAYER=1 MTL_SHADER_VALIDATION=1 ASAN_OPTIONS=detect_leaks=0 \ + build/metal_pathfinding/experiment-sanitize gpu \ + dev/research/metal_pathfinding/sssp.metal stress 20 +``` + +Repository validation also ran `bash .superset/workspace.sh check` (extension +rebuilt; lint/types clean; 170 C++ tests and 465 Python tests passed) and +`make sanitize-test` (170 C++ tests passed). No production C++ source, binding, +or downstream code was modified. No CI run, commit, or push was made. +The [workspace check log](results/workspace-check.txt), +[core sanitizer log](results/sanitize-test.txt), and +[prototype CPU sanitizer results](results/cpu-sanitized.csv) are retained. diff --git a/dev/research/metal_pathfinding/build.sh b/dev/research/metal_pathfinding/build.sh new file mode 100644 index 0000000..15f5b24 --- /dev/null +++ b/dev/research/metal_pathfinding/build.sh @@ -0,0 +1,14 @@ +#!/usr/bin/env bash +set -euo pipefail +cd "$(dirname "$0")/../.." +mkdir -p build/metal_pathfinding +flags=(-std=c++20 -O3 -flto -funroll-loops -fno-math-errno -fno-trapping-math) +if [[ ${1:-} == sanitize ]]; then + flags=(-std=c++20 -O1 -g -fsanitize=address,undefined -fno-sanitize-recover=undefined -fno-omit-frame-pointer) +fi +xcrun clang++ "${flags[@]}" -fobjc-arc -Iinclude \ + dev/research/metal_pathfinding/experiment.mm src/strict_multidigraph.cpp \ + src/shortest_paths.cpp src/profiling.cpp -framework Foundation -framework Metal \ + -o "build/metal_pathfinding/experiment${1:+-$1}" +xcrun clang++ -std=c++20 -O3 -fobjc-arc dev/research/metal_pathfinding/capabilities.mm \ + -framework Foundation -framework Metal -o build/metal_pathfinding/capabilities diff --git a/dev/research/metal_pathfinding/capabilities.mm b/dev/research/metal_pathfinding/capabilities.mm new file mode 100644 index 0000000..bbef385 --- /dev/null +++ b/dev/research/metal_pathfinding/capabilities.mm @@ -0,0 +1,28 @@ +#import +#import +#include + +int main() { + @autoreleasepool { + id device = MTLCreateSystemDefaultDevice(); + if (!device) return 1; + std::cout << "device=" << device.name.UTF8String + << " unified=" << device.hasUnifiedMemory + << " max_buffer=" << device.maxBufferLength << '\n'; + NSArray* bodies = @[ + @"kernel void test(device long* x [[buffer(0)]], uint i [[thread_position_in_grid]]) { x[i] += 1; }", + @"kernel void test(device double* x [[buffer(0)]], uint i [[thread_position_in_grid]]) { x[i] += 1.0; }", + @"kernel void test(device atomic_ulong* x [[buffer(0)]]) { atomic_fetch_min_explicit(x, 1ul, memory_order_relaxed); }", + @"kernel void test(device atomic_uint* x [[buffer(0)]]) { atomic_fetch_min_explicit(x, 1u, memory_order_relaxed); }", + @"kernel void test(device atomic_ulong* x [[buffer(0)]]) { atomic_min_explicit(x, 1ul, memory_order_relaxed); }", + @"kernel void test(device atomic_ulong* x [[buffer(0)]], device ulong* y [[buffer(1)]]) { y[0] = atomic_load_explicit(x, memory_order_relaxed); }" + ]; + for (NSUInteger i = 0; i < bodies.count; ++i) { + NSError* error = nil; + NSString* source = [@"#include \nusing namespace metal;\n" stringByAppendingString:bodies[i]]; + id library = [device newLibraryWithSource:source options:nil error:&error]; + std::cout << "probe=" << i << " compiled=" << (library != nil) << '\n'; + if (!library) std::cout << error.localizedDescription.UTF8String << '\n'; + } + } +} diff --git a/dev/research/metal_pathfinding/experiment.mm b/dev/research/metal_pathfinding/experiment.mm new file mode 100644 index 0000000..671cbcb --- /dev/null +++ b/dev/research/metal_pathfinding/experiment.mm @@ -0,0 +1,526 @@ +// Standalone research harness, not a registered NetGraph backend. +#import +#import + +#include "netgraph/core/shortest_paths.hpp" +#include "netgraph/core/constants.hpp" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace netgraph::core; +using Result = std::pair, PredDAG>; +using Clock = std::chrono::steady_clock; +constexpr Cost INF = std::numeric_limits::max(); +double ms(Clock::time_point start) { + return std::chrono::duration(Clock::now() - start).count(); +} + +struct Case { + std::string name; + StrictMultiDiGraph graph; + std::unique_ptr node_mask, edge_mask; + std::vector residual; + bool reverse = false; + std::span nm() const { return {node_mask.get(), size_t(graph.num_nodes())}; } + std::span em() const { return {edge_mask.get(), size_t(graph.num_edges())}; } +}; + +Case make_case(std::string kind, int n, int degree = 8, bool masked = false, + bool large = false, bool reverse = false, unsigned seed = 1729) { + std::vector src, dst; + std::vector costs; + std::vector caps; + std::mt19937 rng(seed); + auto add = [&](int u, int v, Cost c) { + src.push_back(u); dst.push_back(v); + costs.push_back(c + (large ? (Cost(1) << 34) : 0)); + caps.push_back(1.0 + double(rng() % 100) / 7.0); + }; + if (kind == "chain") { + for (int i = 0; i < n - 1; ++i) add(i, i + 1, 1 + rng() % 31); + } else if (kind == "grid") { + int side = int(std::sqrt(n)); + if (side * side != n) throw std::runtime_error("grid must be square"); + for (int u = 0; u < n; ++u) { + if (u % side + 1 < side) { add(u, u + 1, 1); add(u + 1, u, 1); } + if (u + side < n) { add(u, u + side, 1); add(u + side, u, 1); } + } + } else if (kind == "fabric" || kind == "clos") { + int spines = kind == "clos" ? n / 2 : 32; + for (int u = 0; u < n - spines; ++u) for (int v = n - spines; v < n; ++v) { + add(u, v, 1); add(v, u, 1); + } + } else { + for (int u = 0; u < n; ++u) { + add(u, (u + 1) % n, 1 + rng() % 31); + for (int k = 1; k < degree; ++k) add(u, rng() % n, 1 + rng() % 31); + } + } + Case c{kind + (masked ? "_masked" : "") + (large ? "_int64" : "") + + (reverse ? "_reverse" : ""), + StrictMultiDiGraph::from_arrays(n, src, dst, caps, costs)}; + c.reverse = reverse; + int e = c.graph.num_edges(); + c.node_mask = std::make_unique(n); + c.edge_mask = std::make_unique(e); + c.residual.assign(c.graph.capacity_view().begin(), c.graph.capacity_view().end()); + for (int i = 0; i < n; ++i) c.node_mask[i] = !masked || rng() % 23 != 0; + for (int i = 0; i < e; ++i) { + c.edge_mask[i] = !masked || rng() % 11 != 0; + if (masked && rng() % 13 == 0) c.residual[i] = 0; + } + return c; +} + +Result cpu(const Case& c, NodeId source) { + if (c.reverse) + return shortest_paths_to(c.graph, source, true, EdgeSelection{}, c.residual, c.nm(), c.em()); + return shortest_paths(c.graph, source, {}, true, EdgeSelection{}, c.residual, c.nm(), c.em()); +} + +// Stronger CPU comparator: no DAG allocation and no capacity tie-breaking. +std::vector cpu_distance(const Case& c, NodeId source) { + auto& g = c.graph; + auto row = c.reverse ? g.in_row_offsets_view() : g.row_offsets_view(); + auto col = c.reverse ? g.in_col_indices_view() : g.col_indices_view(); + auto ids = c.reverse ? g.in_adj_edge_index_view() : g.adj_edge_index_view(); + auto costs = g.cost_view(); + std::vector dist(g.num_nodes(), INF); + if (!c.node_mask[source]) return dist; + using Item = std::pair; + std::priority_queue, std::greater> queue; + dist[source] = 0; queue.emplace(0, source); + while (!queue.empty()) { + auto [d, u] = queue.top(); queue.pop(); + if (d != dist[u]) continue; + for (int j = row[u]; j < row[u + 1]; ++j) { + int v = col[j], e = ids[j]; + if (!c.node_mask[v] || !c.edge_mask[e] || c.residual[e] < kMinCap) continue; + Cost next = d + costs[e]; + if (next < dist[v]) { dist[v] = next; queue.emplace(next, v); } + } + } + return dist; +} + +// Reusable workers: CPU batch baseline does not pay thread creation per sample. +class Pool { + std::mutex mutex; + std::condition_variable start, done; + std::vector workers; + std::function task; + std::atomic next{0}; + int count = 0, pending = 0, generation = 0; + bool stop = false; +public: + explicit Pool(int n) { + for (int i = 0; i < n; ++i) workers.emplace_back([this] { + int seen = 0; + for (;;) { + std::unique_lock lock(mutex); + start.wait(lock, [&] { return stop || generation != seen; }); + if (stop) return; + seen = generation; + lock.unlock(); + for (int i; (i = next.fetch_add(1)) < count;) task(i); + lock.lock(); + if (--pending == 0) done.notify_one(); + } + }); + } + void run(int n, std::function f) { + std::unique_lock lock(mutex); + task = std::move(f); count = n; next = 0; pending = int(workers.size()); ++generation; + start.notify_all(); + done.wait(lock, [&] { return pending == 0; }); + } + ~Pool() { + { std::lock_guard lock(mutex); stop = true; } + start.notify_all(); + for (auto& t : workers) t.join(); + } +}; + +struct Metal { + id device; + id queue; + id pull, group, shared; + double setup_ms; + Metal(const char* path) { + auto t = Clock::now(); + device = MTLCreateSystemDefaultDevice(); + if (!device) throw std::runtime_error("No Metal device"); + queue = [device newCommandQueue]; + NSError* error = nil; + NSString* code = [NSString stringWithContentsOfFile:[NSString stringWithUTF8String:path] + encoding:NSUTF8StringEncoding error:&error]; + if (!code) throw std::runtime_error(error.localizedDescription.UTF8String); + id library = [device newLibraryWithSource:code options:nil error:&error]; + if (!library) throw std::runtime_error(error.localizedDescription.UTF8String); + pull = [device newComputePipelineStateWithFunction:[library newFunctionWithName:@"relax_pull"] error:&error]; + group = [device newComputePipelineStateWithFunction:[library newFunctionWithName:@"solve_group"] error:&error]; + shared = [device newComputePipelineStateWithFunction:[library newFunctionWithName:@"solve_shared"] error:&error]; + if (!pull || !group || !shared) throw std::runtime_error(error.localizedDescription.UTF8String); + setup_ms = ms(t); + std::cerr << "device=" << device.name.UTF8String << " setup_ms=" << setup_ms + << " execution_width=" << pull.threadExecutionWidth << '\n'; + } + id buffer(const void* ptr, size_t size) { + auto b = [device newBufferWithLength:std::max(size_t(4), size) options:MTLResourceStorageModeShared]; + if (!b) throw std::runtime_error("Metal allocation failed"); + if (ptr && size) std::memcpy(b.contents, ptr, size); + return b; + } +}; + +struct GpuGraph { + const Case& c; + Metal& m; + id row, col, cost, allowed, a, b, changed, sources; + std::vector enabled; + std::vector valid_sources; + size_t n, q; + double upload_ms = 0, gpu_ms = 0, distance_ms = 0; + int rounds = 0; + GpuGraph(const Case& testcase, Metal& metal, const std::vector& query_sources) + : c(testcase), m(metal), n(c.graph.num_nodes()), q(query_sources.size()) { + auto t = Clock::now(); + auto& g = c.graph; + // Reverse SSSP pulls from outgoing CSR. Eligibility uses original edge IDs. + auto rows = c.reverse ? g.row_offsets_view() : g.in_row_offsets_view(); + auto cols = c.reverse ? g.col_indices_view() : g.in_col_indices_view(); + auto ids = c.reverse ? g.adj_edge_index_view() : g.in_adj_edge_index_view(); + std::vector costs(ids.size()); + enabled.resize(ids.size()); + for (size_t j = 0; j < ids.size(); ++j) { + int e = ids[j]; + enabled[j] = c.node_mask[g.edge_src_view()[e]] && c.node_mask[g.edge_dst_view()[e]] && + c.edge_mask[e] && c.residual[e] >= kMinCap; + costs[j] = g.cost_view()[e]; + } + valid_sources = query_sources; + for (auto& source : valid_sources) if (!c.node_mask[source]) source = -1; + row = m.buffer(rows.data(), rows.size_bytes()); + col = m.buffer(cols.data(), cols.size_bytes()); + cost = m.buffer(costs.data(), costs.size() * sizeof(Cost)); + allowed = m.buffer(enabled.data(), enabled.size()); + a = m.buffer(nullptr, n * q * sizeof(Cost)); + b = m.buffer(nullptr, n * q * sizeof(Cost)); + changed = m.buffer(nullptr, std::max(size_t(8), q) * sizeof(uint32_t)); + sources = m.buffer(valid_sources.data(), q * sizeof(int)); + upload_ms = ms(t); + } + + void bind(id encoder, id before, id after) { + [encoder setBuffer:row offset:0 atIndex:0]; + [encoder setBuffer:col offset:0 atIndex:1]; + [encoder setBuffer:cost offset:0 atIndex:2]; + [encoder setBuffer:allowed offset:0 atIndex:3]; + [encoder setBuffer:before offset:0 atIndex:4]; + [encoder setBuffer:after offset:0 atIndex:5]; + [encoder setBuffer:changed offset:0 atIndex:6]; + } + void wait(id command) { + [command commit]; [command waitUntilCompleted]; + if (command.status == MTLCommandBufferStatusError) + throw std::runtime_error(command.error.localizedDescription.UTF8String); + gpu_ms += (command.GPUEndTime - command.GPUStartTime) * 1000; + } + std::vector run(bool persistent, bool materialize = true, bool shared = false) { + auto begin = Clock::now(); + gpu_ms = 0; rounds = 0; + struct Params { uint32_t n, queries, round, unused; } p{uint32_t(n), uint32_t(q), 0, 0}; + std::vector outputs(q); + if (persistent) { + id command = [m.queue commandBuffer]; + auto encoder = [command computeCommandEncoder]; + [encoder setComputePipelineState:shared ? m.shared : m.group]; + bind(encoder, a, b); + [encoder setBytes:&p length:sizeof(p) atIndex:7]; + [encoder setBuffer:sources offset:0 atIndex:8]; + if (shared) { + if (n * 16 + m.shared.staticThreadgroupMemoryLength > m.device.maxThreadgroupMemoryLength) + throw std::runtime_error("threadgroup scratch too large"); + [encoder setThreadgroupMemoryLength:n * 16 atIndex:0]; + } + [encoder dispatchThreadgroups:MTLSizeMake(q, 1, 1) threadsPerThreadgroup:MTLSizeMake(256, 1, 1)]; + [encoder endEncoding]; wait(command); + auto counts = static_cast(changed.contents); + for (size_t i = 0; i < q; ++i) { + rounds = std::max(rounds, int(counts[i])); + outputs[i] = static_cast((!shared && counts[i] % 2 ? b : a).contents) + i * n; + } + } else { + auto initial = static_cast(a.contents); + std::fill(initial, initial + n * q, INF); + for (size_t i = 0; i < q; ++i) if (valid_sources[i] >= 0) initial[i * n + valid_sources[i]] = 0; + id before = a, after = b; + while (rounds < int(n)) { + int steps = std::min(8, int(n) - rounds); + std::memset(changed.contents, 0, 8 * sizeof(uint32_t)); + id command = [m.queue commandBuffer]; + for (int j = 0; j < steps; ++j) { + // Separate encoders with tracked resources establish the round dependency. + auto encoder = [command computeCommandEncoder]; + [encoder setComputePipelineState:m.pull]; bind(encoder, before, after); + p.round = j; + [encoder setBytes:&p length:sizeof(p) atIndex:7]; + [encoder dispatchThreads:MTLSizeMake(n * q, 1, 1) threadsPerThreadgroup:MTLSizeMake(256, 1, 1)]; + [encoder endEncoding]; std::swap(before, after); + } + wait(command); rounds += steps; + if (static_cast(changed.contents)[steps - 1] == 0) break; + } + for (size_t i = 0; i < q; ++i) outputs[i] = static_cast(before.contents) + i * n; + } + std::vector results(q); + for (size_t i = 0; i < q; ++i) results[i].first.assign(outputs[i], outputs[i] + n); + distance_ms = ms(begin); + if (!materialize) return results; + for (size_t query = 0; query < q; ++query) { + auto& d = results[query].first; + auto& dag = results[query].second; + auto& g = c.graph; + // Positive-cost ECMP reconstruction. Zero costs intentionally require fallback. + auto esrc = g.edge_src_view(); auto edst = g.edge_dst_view(); auto costs = g.cost_view(); + auto tight = [&](size_t e) { + int u = esrc[e], v = edst[e]; + return c.node_mask[u] && c.node_mask[v] && c.edge_mask[e] && c.residual[e] >= kMinCap && + (c.reverse ? (d[v] != INF && d[u] == d[v] + costs[e]) : + (d[u] != INF && d[v] == d[u] + costs[e])); + }; + dag.parent_offsets.assign(n + 1, 0); + for (size_t e = 0; e < costs.size(); ++e) if (tight(e)) ++dag.parent_offsets[edst[e] + 1]; + std::partial_sum(dag.parent_offsets.begin(), dag.parent_offsets.end(), dag.parent_offsets.begin()); + dag.parents.resize(dag.parent_offsets.back()); dag.via_edges.resize(dag.parents.size()); + auto cursor = dag.parent_offsets; + for (size_t e = 0; e < costs.size(); ++e) if (tight(e)) { + int pos = cursor[edst[e]]++; dag.parents[pos] = esrc[e]; dag.via_edges[pos] = int(e); + } + } + return results; + } +}; + +std::vector> canonical(const PredDAG& dag) { + std::vector> entries; + for (size_t v = 0; v + 1 < dag.parent_offsets.size(); ++v) + for (int j = dag.parent_offsets[v]; j < dag.parent_offsets[v + 1]; ++j) + entries.emplace_back(v, dag.parents[j], dag.via_edges[j]); + std::sort(entries.begin(), entries.end()); return entries; +} + +void verify(const std::vector& expected, const std::vector& actual) { + if (expected.size() != actual.size()) throw std::runtime_error("query size mismatch"); + for (size_t q = 0; q < expected.size(); ++q) { + if (expected[q].first != actual[q].first) { + auto mismatch = std::mismatch(expected[q].first.begin(), expected[q].first.end(), actual[q].first.begin()); + throw std::runtime_error("distance mismatch at query " + std::to_string(q) + " node " + + std::to_string(mismatch.first - expected[q].first.begin()) + " expected " + + std::to_string(*mismatch.first) + " actual " + std::to_string(*mismatch.second)); + } + if (canonical(expected[q].second) != canonical(actual[q].second)) + throw std::runtime_error("DAG edge set mismatch at query " + std::to_string(q)); + } +} + +double median(std::vector x) { std::sort(x.begin(), x.end()); return x[x.size() / 2]; } + +void witnesses(Metal& metal) { + auto fixture = [](int n, std::vector src, std::vector dst, + std::vector costs, std::vector caps) { + Case c{"witness", StrictMultiDiGraph::from_arrays(n, src, dst, caps, costs)}; + c.node_mask = std::make_unique(n); + c.edge_mask = std::make_unique(costs.size()); + std::fill_n(c.node_mask.get(), n, true); + std::fill_n(c.edge_mask.get(), costs.size(), true); + c.residual.assign(c.graph.capacity_view().begin(), c.graph.capacity_view().end()); + return c; + }; + auto check = [&](Case& c, NodeId source, const std::vector& distances, size_t edges) { + auto expected = cpu(c, source); + if (expected.first != distances || expected.second.via_edges.size() != edges) + throw std::runtime_error("hand-derived witness mismatch"); + GpuGraph gpu(c, metal, {source}); + for (int method = 0; method < 3; ++method) + verify({expected}, gpu.run(method != 0, true, method == 2)); + }; + auto c = fixture(5, {0, 0, 0, 1, 2, 1}, {1, 1, 2, 3, 3, 1}, + {1, 1, 1, 1, 1, 1}, {1, 1, 1, 1, 1, 1}); + check(c, 0, {0, 1, 1, 2, INF}, 5); + std::cout << "PASS diamond: all ECMP alternatives, parallel edges, positive self-loop excluded, isolated node\n"; + c.reverse = true; + check(c, 3, {2, 1, 1, 0, INF}, 5); + c.reverse = false; + std::cout << "PASS reverse diamond: hand-derived distances and forward DAG\n"; + c.node_mask[0] = false; + check(c, 0, {INF, INF, INF, INF, INF}, 0); + c.node_mask[0] = true; + c.node_mask[1] = false; + check(c, 0, {0, INF, 1, 2, INF}, 2); + c.node_mask[1] = true; + std::cout << "PASS masked source and transit node\n"; + // All costs equal, graph order is (src,dst), making edge 0 the first parallel edge. + c.residual[0] = std::nextafter(kMinCap, 0.0); + c.residual[1] = kMinCap; + check(c, 0, {0, 1, 1, 2, INF}, 4); + std::cout << "PASS double capacity threshold: below rejected, exact threshold admitted\n"; + c.edge_mask[1] = false; + check(c, 0, {0, INF, 1, 2, INF}, 2); + std::cout << "PASS edge mask and residual gate combined\n"; + + Cost big = Cost(1) << 54; + auto wide = fixture(5, {0, 0, 1, 2}, {1, 2, 3, 3}, + {big, big, big + 1, big + 2}, {1, 1, 1, 1}); + check(wide, 0, {0, big, big, 2 * big + 1, INF}, 3); + std::cout << "PASS exact int64 costs above 2^53 and one-unit path difference\n"; + + auto zero = fixture(3, {0, 1, 2}, {1, 2, 1}, {0, 0, 0}, {1, 1, 1}); + auto expected = cpu(zero, 0); + GpuGraph zg(zero, metal, {0}); + auto actual = zg.run(true); + if (actual[0].first != expected.first || expected.second.via_edges.size() != 2 || + actual[0].second.via_edges.size() != 3) + throw std::runtime_error("zero-cost gap witness changed"); + std::cout << "PASS expected gap: zero-cost distances agree, tight-edge GPU DAG has 1->2->1 cycle; CPU DAG has 2 edges\n"; + if (float(16777216) != float(16777217) || + float(std::nextafter(kMinCap, 0.0)) != float(kMinCap)) + throw std::runtime_error("precision gap witness changed"); + std::cout << "PASS precision gaps: float32 collapses 16777216/16777217 and admits nextafter(kMinCap,0)\n"; + + auto tie = fixture(2, {0, 0}, {1, 1}, {1, 1}, {1, 1 + 1e-8}); + EdgeSelection sel; + sel.multi_edge = false; sel.tie_break = EdgeTieBreak::PreferHigherResidual; + auto t = shortest_paths(tie.graph, 0, {}, false, sel); + if (t.second.via_edges != std::vector{1} || float(1 + 1e-8) != float(1)) + throw std::runtime_error("capacity tie witness changed"); + std::cout << "PASS capacity tie gap: CPU chooses edge 1 at 1+1e-8; float32 collapses both capacities\n"; +} + +void benchmark(Case& c, int queries, const std::string& mode, Metal* metal, Pool& pool, int samples) { + std::vector sources(queries); + for (int i = 0; i < queries; ++i) sources[i] = (i * 997) % c.graph.num_nodes(); + std::vector expected(queries); + for (int i = 0; i < queries; ++i) expected[i] = cpu(c, sources[i]); + std::unique_ptr gpu; + if (metal) gpu = std::make_unique(c, *metal, sources); + std::vector methods = mode == "cpu" ? + std::vector{"cpu_full", "cpu_distance", "cpu_pool10", "cpu_pool10_distance"} : + std::vector{"metal_pull", "metal_group"}; + if (metal && size_t(c.graph.num_nodes()) * 16 + metal->shared.staticThreadgroupMemoryLength <= metal->device.maxThreadgroupMemoryLength) + methods.push_back("metal_shared"); + for (const auto& method : methods) { + std::vector times, device_times, distance_times; + int exact_order = 0; + for (int rep = -2; rep < samples; ++rep) { + @autoreleasepool { + auto start = Clock::now(); + std::vector actual; + if (method == "cpu_full") { + actual.resize(queries); + for (int i = 0; i < queries; ++i) actual[i] = cpu(c, sources[i]); + } else if (method == "cpu_pool10") { + actual.resize(queries); + pool.run(queries, [&](int i) { actual[i] = cpu(c, sources[i]); }); + } else if (method == "cpu_distance" || method == "cpu_pool10_distance") { + actual.resize(queries); + auto task = [&](int i) { actual[i].first = cpu_distance(c, sources[i]); }; + if (method == "cpu_distance") { + for (int i = 0; i < queries; ++i) task(i); + } else pool.run(queries, task); + } else actual = gpu->run(method != "metal_pull", true, method == "metal_shared"); + double elapsed = ms(start); + // Full validation is outside timing, on every sample, not just warmup. + if (method == "cpu_distance" || method == "cpu_pool10_distance") { + for (int i = 0; i < queries; ++i) if (actual[i].first != expected[i].first) + throw std::runtime_error("CPU distance baseline mismatch"); + } else { + verify(expected, actual); + exact_order = 0; + for (int i = 0; i < queries; ++i) + if (expected[i].second.parents == actual[i].second.parents && + expected[i].second.via_edges == actual[i].second.via_edges) ++exact_order; + } + if (rep >= 0) { + times.push_back(elapsed); + device_times.push_back(gpu ? gpu->gpu_ms : 0); + distance_times.push_back(gpu ? gpu->distance_ms : elapsed); + } + } + } + std::cout << c.name << ',' << c.graph.num_nodes() << ',' << c.graph.num_edges() << ',' << queries + << ',' << method << ',' << std::fixed << std::setprecision(6) << median(times) + << ',' << median(device_times) << ',' << median(distance_times) << ',' + << (gpu ? gpu->upload_ms : 0) << ',' << (gpu ? gpu->rounds : 0) << ',' << samples + << ",pass," << exact_order << ','; + for (size_t i = 0; i < times.size(); ++i) std::cout << (i ? ";" : "") << times[i]; + std::cout << '\n' << std::flush; + } +} + +int main(int argc, char** argv) { + @autoreleasepool { + try { + if (argc < 4) throw std::runtime_error("usage: experiment cpu|gpu kernel-path smoke|full|correctness [samples]"); + std::string mode = argv[1], suite = argv[3]; + if (mode != "cpu" && mode != "gpu") throw std::runtime_error("invalid mode"); + int samples = argc > 4 ? std::stoi(argv[4]) : 7; + if (samples < 1) throw std::runtime_error("samples must be positive"); + Pool pool(10); + std::unique_ptr metal; + if (mode == "gpu") metal = std::make_unique(argv[2]); + if (suite == "witnesses") { + if (!metal) throw std::runtime_error("witnesses require gpu mode"); + witnesses(*metal); return 0; + } + std::cout << "case,n,e,queries,method,wall_ms,gpu_ms,distance_wall_ms,upload_ms,rounds,samples,correct,exact_order_queries,wall_samples_ms\n"; + auto run = [&](Case c, std::initializer_list qs) { + for (int q : qs) benchmark(c, q, mode, metal.get(), pool, samples); + }; + if (suite == "stress") { + run(make_case("grid", 1024), {64}); + run(make_case("random", 1024, 8, true, true, true), {64}); + } else if (suite == "correctness") { + for (unsigned seed = 1; seed <= 12; ++seed) { + run(make_case("random", 37 + seed * 3, 6, true, seed % 2, seed % 3 == 0, seed), {8}); + } + } else { + run(make_case("random", 128), {1, 64}); + run(make_case("random", 1024), {1, 64}); + run(make_case("fabric", 288), {1, 64}); + run(make_case("grid", 1024), {1, 64}); + run(make_case("chain", 256), {1}); + run(make_case("random", 1024, 8, true, true, true), {8}); + if (suite == "full") { + run(make_case("random", 4096), {1, 64, 256}); + run(make_case("random", 16384), {1, 64}); + run(make_case("random", 65536), {1, 64}); + run(make_case("chain", 2048), {1}); + run(make_case("random", 4096, 32), {1, 64}); + run(make_case("clos", 200), {1, 64}); + run(make_case("clos", 800), {1, 64}); + run(make_case("grid", 10000), {1, 8}); + run(make_case("grid", 40000), {1}); + } else if (suite != "smoke") throw std::runtime_error("invalid suite"); + } + } catch (const std::exception& e) { + std::cerr << "FAIL: " << e.what() << '\n'; return 1; + } + } +} diff --git a/dev/research/metal_pathfinding/optimization/README.md b/dev/research/metal_pathfinding/optimization/README.md new file mode 100644 index 0000000..010b28c --- /dev/null +++ b/dev/research/metal_pathfinding/optimization/README.md @@ -0,0 +1,279 @@ +# GPU optimization follow-up + +27 September 2026, NetGraph-Core `fbab119`, Apple M4 Max, 32 GPU cores, +14 CPU cores, 36 GiB unified memory. Standalone research; no backend registration +or production algorithm changes. + +**Yes, the first investigation missed important optimizations.** Its poor batch +results were partly an implementation limitation, especially serial CPU +predecessor construction. They are not evidence of a GPU performance ceiling. +The experiments also show why changing to a frontier or bucket algorithm alone +does not guarantee improvement. Work organization, result construction and the +CPU comparison algorithm matter together. + +**The CPU algorithm comparison also changes the decision.** A follow-up CPU +Dial-style bucket implementation brings the 16k weighted batch from the native +CPU's 27.7 ms to 7.7 ms. GPU results across two passes are 3.9–7.5 ms. On the +65k single-query case the stronger CPU takes 4.4 ms and GPU takes 1.2–1.4 ms. +Improve CPU specialization first; pursue GPU acceleration selectively. + +The consolidated [CPU optimisation plan](../../../perf/spf_queue/PLAN.md) is the implementation +source of truth. After the [ordered bucket queue experiment](../../../perf/spf_queue/) it +specifies one queue substitution inside the existing search (BFS and Dial are +its special cases), verified bit-exact against the production result contract, +with a hybrid-reset workspace, a width-based dispatch rule and fallback, and +downstream acceptance requirements. That change is now implemented in +`src/shortest_paths.cpp`; the plan records its old/new/old measurements at the +Core level and through NetGraph. + +## What changed in the evidence + +Fresh processes ran sequentially: CPU A1, original GPU A1, optimized GPU B, +original GPU A2, CPU A2. Seven measured samples plus two warmups per row; +every result was checked outside the timed interval. CPU batches use ten +reusable workers. Times include host distances and positive-cost predecessor +DAG construction, but exclude graph preparation and pipeline creation. + +| Workload | Native CPU A1 / A2, ms | Original GPU A1 / A2, ms | Best tested optimized GPU, ms | Observation | +|---|---:|---:|---:|---| +| Weighted random, 1,024 nodes / 8,192 edges, one query | 0.086 / 0.097 | 0.915 / 0.972 | 0.599 | CPU still wins small individual queries | +| Weighted random, 4,096 / 32,768, 256 queries | 21.391 / 21.281 | 47.812 / 49.310 | 7.003 | Interleaved 64-bit pull makes batching promising | +| Weighted random, 16,384 / 131,072, 64 queries | 27.693 / 27.721 | 57.748 / 53.106 | 7.473 | Earlier batch pessimism is no longer supported | +| Weighted random, 65,536 / 524,288, one query | 19.316 / 19.240 | 5.184 / 5.854 | 1.373 | Guarded 32-bit pull plus GPU DAG extraction helps | +| Unit-cost fabric, 800 / 320,000, 64 queries | 17.042 / 16.525 | 69.896 / 70.228 | 8.185 | CPU BFS plus optimized DAG is already 8.296 / 7.885 ms | +| Unit-cost grid, 10,000 / 39,600, one query | 0.570 / 0.582 | 3.836 / 5.874 | 3.378 | CPU BFS plus DAG is 0.089 / 0.088 ms | +| Weighted chain, 2,048 / 2,047, one query | 0.017 / 0.017 | 4.834 / 4.908 | 4.847 | Almost no useful parallel work per frontier | + +These are **exploratory measurements, not accepted performance claims**. The +desktop was not isolated: pre-phase CPU idle readings ranged from 73.28% to +87.88%, with nonzero background GPU activity. The original GPU grid result +drifted substantially between A1 and A2. A quiet-machine repeat is still required +by this repository's performance standard. Nothing was stopped or altered in +the user's other sessions to obtain these measurements. + +The best method is selected after measurement, not by a working runtime +dispatcher. Original GPU columns select between the original pull and persistent +group methods; the original shared-memory method was not rerun. The complete +[18-case table and all 216 optimized rows](results/aba/summary.md), +[raw samples](results/aba/optimized-b.csv), and +[environment/source hashes](results/aba/environment.txt) preserve the scope. + +## Stronger CPU comparisons + +The first table compares against the current native backend. A second A/B/A +compares GPU with CPU heap and Dial-style cyclic-bucket searches using cached +eligibility and one-pass DAG assembly. Each CPU worker completes both search and +DAG for a query, retaining locality. This is a comparable experimental contract +to the GPU: exact distances and canonical-equivalent positive-cost DAG edge sets, +without CPU discovery-order parity. Both devices exclude eligibility preparation. +The weighted random graphs have integer costs 1–31; the CPU Dial prototype is +explicitly limited to maximum edge weight at most 1,024, and retains int64 sums. + +| Workload | CPU cached heap + DAG A1 / A2, ms | CPU Dial + DAG A1 / A2, ms | Best GPU first / second B, ms | +|---|---:|---:|---:| +| Random 1,024 / 8,192, one query | 0.053 / 0.059 | 0.028 / 0.030 | 0.599 / 0.634 | +| Random 4,096 / 32,768, 256 queries | 13.030 / 13.024 | 7.056 / 6.925 | 7.003 / 4.001 | +| Random 16,384 / 131,072, 64 queries | 17.500 / 17.268 | 7.696 / 7.677 | 7.473 / 3.851 | +| Random 65,536 / 524,288, one query | 11.474 / 11.530 | 4.384 / 4.372 | 1.373 / 1.244 | +| Random 4,096 / 131,072, 64 queries | 6.672 / 6.662 | 3.854 / 3.865 | 2.051 / 2.215 | +| Unit-cost fabric 800 / 320,000, 64 queries | 5.125 / 5.391 | 5.421 / 5.537 | 8.185 / 8.372 | + +The second B repeated all 216 optimized GPU rows, unchanged binary, between +CPU alternative A1/A2. [All second-pass results](results/cpu-algorithms-aba/summary.md) +and [raw GPU samples](results/cpu-algorithms-aba/b.csv) are retained. The winning +GPU method changed on the 4k/256 and 16k/64 batches: 32-bit pull plus GPU DAG +beat the first pass's winning 64-bit pull. Background CPU idle reached 59.82% +before one phase. We have not attributed this variability to a specific cause; +it prevents a precise crossover rule or a stable speedup claim. + +This strengthens the practical recommendation: CPU optimizations are worthwhile +independently of GPU support. GPU remains promising for large single-source and +some batch workloads, but comparisons only against the existing CPU heap backend +overstate the advantage over a better CPU implementation. On the dense fabric, +the fused cached CPU heap + DAG is faster than either GPU pass. On the grid, +the earlier CPU BFS result remains faster than the heap and Dial alternatives. + +## Optimizations we missed + +1. **Result construction on the CPU.** The first prototype scanned every edge + twice and built every query's DAG serially, while the CPU search comparator + already had ten workers. A cached-eligibility, one-pass incoming-CSR DAG + builder, parallel across queries, reduced the 16k/64-query persistent-group + case from approximately 53–58 ms to 13.239 ms without changing the GPU search + algorithm. This variant bundles three changes; it does not isolate the + contribution of threading from one-pass construction or cached eligibility. +2. **Batch memory layout.** Making query the contiguous dimension reduced the + same workload from 15.959 ms with the query-major 64-bit pull to 7.473 ms. + Device time fell from 10.305 to 1.950 ms. Both versions use the same CPU DAG + builder and identical relaxation counts. This improvement does not require + narrowing distances or a new graph algorithm. +3. **Device-side DAG extraction.** Counting tight incoming edges, host prefix + sums, then GPU filling helped the large single-query and higher-degree batch + cases. It is not universally better: query-major frontier plus GPU DAG took + 15.944 ms on the 800-node fabric batch, versus 9.324 ms with CPU DAG assembly. + Layout and output volume require their own decision, separate from SSSP. +4. **Exact 32-bit specialization.** Narrow distances only when + `max_edge_cost * node_count < UINT32_MAX`; otherwise run the 64-bit pull. + This conservatively proves that the sentinel cannot collide with finite + shortest distances. No floating-point conversion is used. It helped some + cases, but 64-bit pull beat 32-bit pull on the 16k batch, so narrower is not + automatically faster. Eligibility still uses CPU double-precision residuals. +5. **Command and host overhead.** Multiple dispatches share a compute encoder + with explicit buffer barriers; convergence flags are aggregated by SIMD + group. These changes were tested as a bundle. An initial screening defect + repeatedly invoked the Objective-C buffer accessor inside the conversion + loop. Hoisting it removed large batch host overhead before final timings. + The retained [screening notes](results/screen-known-limitations.txt) distinguish + those preliminary measurements from the final matrix. + +Apple's compute documentation supports batching dispatches and respecting +resource synchronization. Its Metal 4 command allocators and reusable command +infrastructure offer another way to reduce encoding overhead. Metal 4 itself +was **not implemented or timed** here. +[Metal calculations](https://developer.apple.com/documentation/metal/performing-calculations-on-a-gpu), +[Metal 4 command management](https://developer.apple.com/videos/play/wwdc2025/254/). + +## Should we change algorithms? + +**Weighted, general graphs: retain both pull and frontier candidates.** +Davidson et al. study Workfront Sweep, Near-Far and Bucketing as different +balances between redundant edge work and scheduling overhead. That is the right +comparison space for this problem; ordinary parallel Dijkstra is not an obvious +GPU default. Their NVIDIA results are not M4 speed predictions. +[2014 SSSP paper](https://escholarship.org/uc/item/8qr166v2). + +The new active-frontier implementation supports one thread or one SIMD group +per active vertex, indirect dispatch and queue deduplication. It reduced the +16k/64-query relaxation work from 201.327 million adjacency entries to about +21–22 million. Yet its best full time was 10.144 ms, versus 7.473 ms for +interleaved pull. On the 10k grid it reduced edge scans from 7.920 million to +39,600, but still took 4.040 ms versus pull's 3.378 ms. It retained 200 rounds +and 25 host waits. Less edge work is real; the latency win is not automatic. + +**Distance buckets remain worth investigating, but our simple version is not a +win.** The delta-4 experiment reduced the 16k batch to 8.451 million edge visits, +but needed 72 rounds and 16.825 ms. Delta-16 and delta-64 were also slower than +the best pull. This implementation scans all pending vertex slots to find and +select each bucket, uses a batch-wide minimum and bulk synchronization, and has +neither a light/heavy edge split nor a sophisticated asynchronous queue. +These results reject this implementation as the default, not delta-stepping. + +ADDS specifically addresses bucket management, asynchronous work scheduling +and dynamic delta selection. It is a plausible next algorithmic investigation, +but a correct Metal port needs a progress-safe queue and synchronization design; +copying CUDA persistent-worker assumptions would not establish correctness. +Its published RTX 2080 Ti speedups do not establish gains on Apple hardware. +[ADDS, PPoPP 2021](https://www.cs.utexas.edu/~lin/papers/ppopp21.pdf). + +**Uniform positive costs: test BFS on the CPU as well as the GPU.** The new CPU +BFS comparator was checked against native Dijkstra and uses the same cached +eligibility and optimized DAG construction as the GPU variants. It is a major +improvement on grids and removes most of the apparent GPU advantage on the +dense fabric. Direction-optimizing BFS can switch between sparse frontiers and +pulling from unvisited vertices. Its early exit after finding one parent applies +to distance discovery; all ECMP predecessors still require extraction. +[Direction-optimizing BFS](https://people.eecs.berkeley.edu/~krste/papers/beamer-sc2012.pdf). + +The CPU plan now preserves predecessor order by construction: the ordered +bucket queue reproduces the heap's pop order exactly, and the unit-cost case is +its `W = 2` instance. Under that full contract the sequential gain on uniform-cost +graphs is 1.1–1.3x and inconclusive on the dense fabric, where edge scanning +dominates; the larger research BFS numbers came from the relaxed contract. + +**Stable, road-like graphs with many repeated queries: consider preprocessing.** +PHAST uses contraction-hierarchy preprocessing followed by an ordered sweep. +The paper explicitly requires enough queries to amortize preprocessing and +focuses on low-highway-dimension graphs. For NetGraph, changing masks, residual +eligibility and weights mean shortcut validity or customization must be handled; +that applicability assessment is our inference, not a measured PHAST result. +It is not the first choice for arbitrary changing network simulations. +[PHAST](https://www.microsoft.com/en-us/research/wp-content/uploads/2011/01/phast_ipdps.pdf). + +**Small or destination-limited searches: keep the CPU path.** These tests are +full-source searches; they do not compare against target-early-exit Dijkstra. +Bidirectional search or A* with a proven admissible lower bound can be relevant +to point-to-point workloads, but neither was implemented or timed here. Likewise, +CPU radix queues for wider integer costs remain an unmeasured stronger comparator; +the bounded-weight Dial alternative is measured above. + +## Recommended implementation order + +Follow the [CPU plan](../../../perf/spf_queue/PLAN.md): add the differential parity test with a +forced heap route, land the ordered bucket queue and hybrid-reset workspace in +the forward search as one change gated on the existing output hashes, extend to +the reverse search, freeze the width limit, then validate downstream. Batching +and a new distance-only API are conditional on actual callers, not prerequisites +for single-query CPU gains. + +After those gates, revisit the GPU candidates against the accepted CPU baseline: +interleaved exact 64-bit pull, guarded 32-bit paths, and separately selected result +construction. Adaptive frontier/pull selection and improved bucket scheduling +remain later GPU research. The existing evidence does not establish full-backend +compatibility or justify automatic CPU/GPU dispatch. + +## Validation and remaining limits + +- Final A/B/A: 384 rows, 124,704 checked query results including warmups. +- Correctness: 12 seeded masked graphs and 12 boundary fixtures, all 14 variants, + 11,760 checked query results. Fixtures exercise forward/reverse traversal, + parallel edges, self-loops, blocked sources, unreachable nodes, residuals just + below and at `kMinCap`, distances near the 32-bit boundary, guarded fallback, + and integer costs greater than `2^53`. +- Normal stress: 39,424 checked results. ASan/UBSan plus Metal API and GPU shader + validation: another 11,760 correctness and 8,960 stress results. No reported + sanitizer or validation errors. These repetitions are not independent graphs. +- The separate CPU comparison repeats masked positive-cost checks against native + Dijkstra, and runs ASan/UBSan over both its masked fixtures and all seven + performance workloads. See the [audit](results/audit.json) for exact counts. +- Across both final timing sequences and the listed correctness/stress runs: + 290,192 checked query results, including CPU comparator rows and warmups. +- Final repository check rebuilt the Python extension and passed lint, types, + 170 C++ tests and 465 Python tests. `make sanitize-test` passed all 170 C++ + tests. An initial formatting failure in the new summarizer was corrected and + both subsequent workspace checks passed. These are local checks; CI was not + run. No production tracked files changed, and no commit or push was made. +- All distances compare exactly. Positive-cost predecessor edge sets compare + canonically to native CPU results; CPU discovery order is not reproduced. +- Graphs are synthetic and modest in size. No realistic demand traces, cold + production latency, concurrent calls, per-query mask batches, cost-factor flows, + zero-cost DAG parity or complete backend compatibility were established. +- GPU buffers and cached eligibility are prepared before timing. `upload_ms` + includes the superset of buffers needed by all experimental variants, not a + minimal production upload. Printed `setup_ms` is inherited phase-one pipeline + setup and excludes the additional optimization library; it is not total cold + initialization. GPU timestamps and distance timing are diagnostic subsets, + not substitutes for full wall time. Do not subtract separate medians to claim + an exact component cost. +- Queue atomics, bucket scans, vertex initialization and DAG extraction are not + included in the `edge_visits` counter. The counter measures SSSP adjacency work. +- The prototype requires SIMD width 32 and 256-thread groups, checked at runtime, + and imposes experimental size limits. It is not a portable library implementation. + +Reproduce from the repository root: + +```sh +bash dev/research/metal_pathfinding/optimization/build.sh +build/metal_pathfinding/optimized all correctness 3 +build/metal_pathfinding/optimized all stress 20 +bash dev/research/metal_pathfinding/optimization/run_aba.sh +python3 dev/research/metal_pathfinding/optimization/summarize.py +bash dev/research/metal_pathfinding/optimization/build.sh sanitize +MTL_DEBUG_LAYER=1 MTL_SHADER_VALIDATION=1 ASAN_OPTIONS=detect_leaks=0 \ + build/metal_pathfinding/optimized-sanitize all correctness 3 +MTL_DEBUG_LAYER=1 MTL_SHADER_VALIDATION=1 ASAN_OPTIONS=detect_leaks=0 \ + build/metal_pathfinding/optimized-sanitize all stress 3 +bash dev/research/metal_pathfinding/optimization/build_cpu.sh +build/metal_pathfinding/cpu-algorithms 3 correctness +bash dev/research/metal_pathfinding/optimization/run_cpu_aba.sh +python3 dev/research/metal_pathfinding/optimization/summarize_cpu.py +bash dev/research/metal_pathfinding/optimization/build_cpu.sh sanitize +ASAN_OPTIONS=detect_leaks=0 build/metal_pathfinding/cpu-algorithms-sanitize 3 correctness +ASAN_OPTIONS=detect_leaks=0 build/metal_pathfinding/cpu-algorithms-sanitize 2 +make sanitize-test +bash .superset/workspace.sh check +``` + +Run timings sequentially without builds or tests in parallel. The compiler emits +one known warning because the reused phase-one `main` is renamed for inclusion; +that unused helper lacks an explicit return after its success path. It is not +called by this harness. The original experiment and shader hashes are unchanged. diff --git a/dev/research/metal_pathfinding/optimization/build.sh b/dev/research/metal_pathfinding/optimization/build.sh new file mode 100644 index 0000000..d3cd00a --- /dev/null +++ b/dev/research/metal_pathfinding/optimization/build.sh @@ -0,0 +1,12 @@ +#!/usr/bin/env bash +set -euo pipefail +cd "$(dirname "$0")/../../.." +mkdir -p build/metal_pathfinding +flags=(-std=c++20 -O3 -flto -funroll-loops -fno-math-errno -fno-trapping-math) +if [[ ${1:-} == sanitize ]]; then + flags=(-std=c++20 -O1 -g -fsanitize=address,undefined -fno-sanitize-recover=undefined -fno-omit-frame-pointer) +fi +xcrun clang++ "${flags[@]}" -fobjc-arc -Iinclude \ + dev/research/metal_pathfinding/optimization/experiment.mm src/strict_multidigraph.cpp \ + src/shortest_paths.cpp src/profiling.cpp -framework Foundation -framework Metal \ + -o "build/metal_pathfinding/optimized${1:+-$1}" diff --git a/dev/research/metal_pathfinding/optimization/build_cpu.sh b/dev/research/metal_pathfinding/optimization/build_cpu.sh new file mode 100644 index 0000000..e8b95a1 --- /dev/null +++ b/dev/research/metal_pathfinding/optimization/build_cpu.sh @@ -0,0 +1,11 @@ +#!/usr/bin/env bash +set -euo pipefail +cd "$(dirname "$0")/../../.." +flags=(-std=c++20 -O3 -flto -funroll-loops -fno-math-errno -fno-trapping-math) +if [[ ${1:-} == sanitize ]]; then + flags=(-std=c++20 -O1 -g -fsanitize=address,undefined -fno-sanitize-recover=undefined -fno-omit-frame-pointer) +fi +xcrun clang++ "${flags[@]}" -fobjc-arc -Iinclude \ + dev/research/metal_pathfinding/optimization/cpu_algorithms.mm src/strict_multidigraph.cpp \ + src/shortest_paths.cpp src/profiling.cpp -framework Foundation -framework Metal \ + -o "build/metal_pathfinding/cpu-algorithms${1:+-$1}" diff --git a/dev/research/metal_pathfinding/optimization/cpu_algorithms.mm b/dev/research/metal_pathfinding/optimization/cpu_algorithms.mm new file mode 100644 index 0000000..58dc6ae --- /dev/null +++ b/dev/research/metal_pathfinding/optimization/cpu_algorithms.mm @@ -0,0 +1,102 @@ +// Stronger CPU algorithm comparators for the same positive-cost result contract. +#define main phase_one_main +#include "../experiment.mm" +#undef main + +struct PreparedCpu { + const Case& c; + std::vector enabled; + Cost max_weight=0; + explicit PreparedCpu(const Case& graph):c(graph),enabled(graph.graph.num_edges()) { + const auto& g=c.graph; + for(int e=0;e=kMinCap; + max_weight=std::max(max_weight,g.cost_view()[e]); + } + } + Result solve(NodeId source,bool dial) const { + const auto& g=c.graph; int n=g.num_nodes(); + auto row=g.row_offsets_view(),col=g.col_indices_view(),ids=g.adj_edge_index_view(); + auto costs=g.cost_view(); + Result result; auto& dist=result.first; auto& dag=result.second; + dist.assign(n,INF); + using Item=std::pair; + auto visit=[&](Cost d,NodeId u,auto&& push) { + if(d!=dist[u]) return; + for(int j=row[u];j1024) throw std::runtime_error("Dial comparison requires max weight <= 1024"); + size_t width=size_t(max_weight)+1,pending=1; + std::vector> buckets(width); + buckets[0].emplace_back(0,source); Cost current=0; + auto push=[&](Item x){buckets[size_t(x.first)%width].push_back(x);++pending;}; + while(pending) { + auto& bucket=buckets[size_t(current)%width]; + if(bucket.empty()) {++current;continue;} + auto [d,u]=bucket.back();bucket.pop_back();--pending; + if(d!=current) throw std::runtime_error("Dial ordering invariant failed"); + visit(d,u,push); + } + } else { + std::priority_queue,std::greater> heap; + heap.emplace(0,source); + auto push=[&](Item x){heap.push(x);}; + while(!heap.empty()) {auto [d,u]=heap.top();heap.pop();visit(d,u,push);} + } + } + auto inrow=g.in_row_offsets_view(),incol=g.in_col_indices_view(),inids=g.in_adj_edge_index_view(); + dag.parent_offsets.resize(n+1);dag.parents.reserve(n);dag.via_edges.reserve(n); + for(int v=0;v1 ? std::stoi(argv[1]) : 7; bool correctness=argc>2; + Pool pool(10); + std::cout<<"case,n,e,queries,method,wall_ms,samples,correct,wall_samples_ms\n"; + auto run=[&](Case c,int q) { + std::vector expected(q); std::vector sources(q); + for(int i=0;i times; + for(int rep=-2;rep actual(q); + auto query=[&](int i){actual[i]=prepared.solve(sources[i],dial);}; + if(q==1) query(0);else pool.run(q,query); + double elapsed=ms(start);verify(expected,actual);if(rep>=0)times.push_back(elapsed); + } + std::cout< + +struct OptimizedMetal : Metal { + std::map> pipelines; + OptimizedMetal() : Metal("dev/research/metal_pathfinding/sssp.metal") { + NSError* error = nil; + NSString* code = [NSString stringWithContentsOfFile:@"dev/research/metal_pathfinding/optimization/kernels.metal" + encoding:NSUTF8StringEncoding error:&error]; + auto lib = [device newLibraryWithSource:code options:nil error:&error]; + if (!lib) throw std::runtime_error(error.localizedDescription.UTF8String); + for (const char* name : {"pull64","pull32","prepare","expand","bucket_reset", + "bucket_min","bucket_select","dag_count64","dag_fill64", + "dag_count32","dag_fill32"}) { + auto fn = [lib newFunctionWithName:[NSString stringWithUTF8String:name]]; + auto pipeline = [device newComputePipelineStateWithFunction:fn error:&error]; + if (!pipeline) throw std::runtime_error(error.localizedDescription.UTF8String); + if (pipeline.threadExecutionWidth != 32 || pipeline.maxTotalThreadsPerThreadgroup < 256) + throw std::runtime_error("this research configuration requires SIMD32 and 256-thread groups"); + pipelines.emplace(name, pipeline); + } + } +}; + +struct Config { + std::string name, solver; + bool layout = false, narrow = false, gpu_dag = false; + int lanes = 1, delta = 0; +}; + +struct OptimizedGraph { + const Case& c; + OptimizedMetal& m; + Pool& pool; + GpuGraph old; + std::vector sources; + std::vector in_costs; + std::vector in_enabled; + id a64,b64,a32,b32,weights32; + id outrow,outcol,outcost,outenabled,queueA,queueB,counts,marks,args,work,minimum; + id inrow,incol,incost,inids,inenabled,offsets,parents,via; + size_t n, q, e; + bool fits32; + double upload_ms=0, distance_ms=0, gpu_ms=0; + uint64_t edge_visits=0; + int rounds=0, waits=0; + bool fallback=false; + struct P { uint32_t n,q,round,layout,current,epoch,lanes,delta; }; + + OptimizedGraph(const Case& testcase, OptimizedMetal& metal, Pool& workers, + std::vector query_sources) + : c(testcase),m(metal),pool(workers),old(c,m,query_sources),sources(std::move(query_sources)), + n(c.graph.num_nodes()),q(sources.size()),e(c.graph.num_edges()) { + auto begin=Clock::now(); + if (!n || n*q>UINT32_MAX/32 || e*q>UINT32_MAX/8) throw std::runtime_error("experiment size limit"); + auto& g=c.graph; + Cost largest=0; + for (Cost cost:g.cost_view()) largest=std::max(largest,cost); + // Strictly less than the sentinel; the multiplication is bounded in uint64. + fits32=largest < Cost(UINT32_MAX) && uint64_t(largest)*n < UINT32_MAX; + a64=m.buffer(nullptr,n*q*8); b64=m.buffer(nullptr,n*q*8); + a32=m.buffer(nullptr,n*q*4); b32=m.buffer(nullptr,n*q*4); + std::vector ws(e); + auto pull_ids=c.reverse ? g.adj_edge_index_view() : g.in_adj_edge_index_view(); + for(size_t j=0;j oe(e); + for(size_t j=0;j=kMinCap; + } + outrow=m.buffer(orow.data(),orow.size_bytes()); outcol=m.buffer(ocol.data(),ocol.size_bytes()); + outcost=m.buffer(ws.data(),e*4); outenabled=m.buffer(oe.data(),e); + queueA=m.buffer(nullptr,n*q*4); queueB=m.buffer(nullptr,n*q*4); + counts=m.buffer(nullptr,8); marks=m.buffer(nullptr,n*q*4); + args=m.buffer(nullptr,12); work=m.buffer(nullptr,32); minimum=m.buffer(nullptr,4); + in_costs.resize(e); in_enabled.resize(e); + auto ids=g.in_adj_edge_index_view(); + for(size_t j=0;j=kMinCap; + } + inrow=m.buffer(g.in_row_offsets_view().data(),g.in_row_offsets_view().size_bytes()); + incol=m.buffer(g.in_col_indices_view().data(),g.in_col_indices_view().size_bytes()); + inids=m.buffer(ids.data(),ids.size_bytes()); incost=m.buffer(in_costs.data(),e*8); + inenabled=m.buffer(in_enabled.data(),e); offsets=m.buffer(nullptr,(n+1)*q*4); + // Reserve output capacity once; only actual DAG entries are copied to host. + parents=m.buffer(nullptr,e*q*4); via=m.buffer(nullptr,e*q*4); + upload_ms=old.upload_ms+ms(begin); + } + + void wait(id cb) { + [cb commit]; [cb waitUntilCompleted]; ++waits; + if(cb.status==MTLCommandBufferStatusError) throw std::runtime_error(cb.error.localizedDescription.UTF8String); + gpu_ms+=(cb.GPUEndTime-cb.GPUStartTime)*1000; + } + void pipeline(id enc,const char* name) { + [enc setComputePipelineState:m.pipelines.at(name)]; + } + void dispatch(id enc,size_t size) { + [enc dispatchThreads:MTLSizeMake(size,1,1) threadsPerThreadgroup:MTLSizeMake(256,1,1)]; + [enc memoryBarrierWithScope:MTLBarrierScopeBuffers]; + } + void one(id enc) { + [enc dispatchThreadgroups:MTLSizeMake(1,1,1) threadsPerThreadgroup:MTLSizeMake(1,1,1)]; + [enc memoryBarrierWithScope:MTLBarrierScopeBuffers]; + } + + void cpu_dags(std::vector& results) { + auto row=c.graph.in_row_offsets_view(); auto col=c.graph.in_col_indices_view(); + auto ids=c.graph.in_adj_edge_index_view(); + auto build=[&](int query) { + auto& d=results[query].first; auto& dag=results[query].second; + dag.parent_offsets.resize(n+1); + // Append in incoming-CSR order in one scan. Eligibility was cached at upload. + dag.parents.reserve(n); dag.via_edges.reserve(n); + for(size_t v=0;v pull(Config cfg) { + id before=cfg.narrow ? a32 : a64, after=cfg.narrow ? b32 : b64; + if(cfg.narrow) std::fill_n(static_cast(before.contents),n*q,UINT32_MAX); + else std::fill_n(static_cast(before.contents),n*q,INF); + for(size_t i=0;i(before.contents)[index]=0; + else static_cast(before.contents)[index]=0; + } + P p{uint32_t(n),uint32_t(q),0,uint32_t(cfg.layout),0,0,1,0}; + while(rounds(old.changed.contents)[steps-1]==0) break; + } + return before; + } + + id frontier(Config cfg) { + std::fill_n(static_cast(a32.contents),n*q,UINT32_MAX); + std::memset(marks.contents,0,n*q*4); std::memset(counts.contents,0,8); + uint32_t active=0; + for(size_t query=0;query(a32.contents)[index]=0; + static_cast(queueA.contents)[active++]=index; + if(cfg.delta) static_cast(marks.contents)[index]=1; + } + static_cast(counts.contents)[0]=active; + uint32_t current=0; + id input=queueA, output=queueB; + P p{uint32_t(n),uint32_t(q),0,0,0,1,uint32_t(cfg.lanes),uint32_t(cfg.delta)}; + // Fail rather than returning unconverged data if an implementation bug or + // pathological scheduler exceeds this research harness's operational limit. + while(rounds<1000000) { + std::memset(work.contents,0,32); + auto cb=[m.queue commandBuffer]; auto enc=[cb computeCommandEncoder]; + for(int j=0;j<8;++j) { + p.round=j; p.current=cfg.delta ? 0 : current; p.epoch=uint32_t(rounds+j+1); + [enc setBytes:&p length:sizeof(p) atIndex:7]; + if(cfg.delta) { + input=queueA; output=queueB; + pipeline(enc,"bucket_reset"); + [enc setBuffer:counts offset:0 atIndex:0]; [enc setBuffer:minimum offset:0 atIndex:1]; one(enc); + pipeline(enc,"bucket_min"); + [enc setBuffer:a32 offset:0 atIndex:0]; [enc setBuffer:marks offset:0 atIndex:1]; + [enc setBuffer:minimum offset:0 atIndex:2]; dispatch(enc,n*q); + pipeline(enc,"bucket_select"); + [enc setBuffer:a32 offset:0 atIndex:0]; [enc setBuffer:marks offset:0 atIndex:1]; + [enc setBuffer:minimum offset:0 atIndex:2]; [enc setBuffer:input offset:0 atIndex:3]; + [enc setBuffer:counts offset:0 atIndex:4]; dispatch(enc,n*q); + } + pipeline(enc,"prepare"); + [enc setBuffer:counts offset:0 atIndex:0]; [enc setBuffer:args offset:0 atIndex:1]; one(enc); + pipeline(enc,"expand"); + [enc setBuffer:outrow offset:0 atIndex:0]; [enc setBuffer:outcol offset:0 atIndex:1]; + [enc setBuffer:outcost offset:0 atIndex:2]; [enc setBuffer:outenabled offset:0 atIndex:3]; + [enc setBuffer:a32 offset:0 atIndex:4]; [enc setBuffer:input offset:0 atIndex:5]; + [enc setBuffer:output offset:0 atIndex:6]; [enc setBuffer:counts offset:0 atIndex:8]; + [enc setBuffer:marks offset:0 atIndex:9]; [enc setBuffer:work offset:0 atIndex:10]; + [enc dispatchThreadgroupsWithIndirectBuffer:args indirectBufferOffset:0 threadsPerThreadgroup:MTLSizeMake(256,1,1)]; + [enc memoryBarrierWithScope:MTLBarrierScopeBuffers]; + if(!cfg.delta) { std::swap(input,output); current=1-current; } + } + [enc endEncoding]; wait(cb); rounds+=8; + for(int j=0;j<8;++j) edge_visits+=static_cast(work.contents)[j]; + if(static_cast(counts.contents)[cfg.delta ? 0 : current]==0) return a32; + } + throw std::runtime_error("frontier failed to converge"); + } + + void gpu_dags(std::vector& results,id distances,bool narrow,bool layout) { + struct DP { uint32_t n,q,e,layout,reverse,a,b,c; } p{uint32_t(n),uint32_t(q),uint32_t(e),uint32_t(layout),uint32_t(c.reverse),0,0,0}; + auto encode=[&](bool fill) { + auto cb=[m.queue commandBuffer]; auto enc=[cb computeCommandEncoder]; + pipeline(enc,fill ? (narrow ? "dag_fill32" : "dag_fill64") : (narrow ? "dag_count32" : "dag_count64")); + [enc setBuffer:inrow offset:0 atIndex:0]; [enc setBuffer:incol offset:0 atIndex:1]; + [enc setBuffer:incost offset:0 atIndex:2]; [enc setBuffer:inids offset:0 atIndex:3]; + [enc setBuffer:inenabled offset:0 atIndex:4]; [enc setBuffer:distances offset:0 atIndex:5]; + [enc setBuffer:offsets offset:0 atIndex:6]; [enc setBytes:&p length:sizeof(p) atIndex:7]; + [enc setBuffer:parents offset:0 atIndex:8]; [enc setBuffer:via offset:0 atIndex:9]; + dispatch(enc,n*q); [enc endEncoding]; wait(cb); + }; + encode(false); + pool.run(int(q),[&](int query) { + auto ptr=static_cast(offsets.contents)+query*(n+1); + ptr[0]=0; std::partial_sum(ptr,ptr+n+1,ptr); + results[query].second.parent_offsets.assign(ptr,ptr+n+1); + }); + encode(true); + pool.run(int(q),[&](int query) { + auto& dag=results[query].second; int size=dag.parent_offsets.back(); + auto ps=static_cast(parents.contents)+query*e; + auto es=static_cast(via.contents)+query*e; + dag.parents.assign(ps,ps+size); dag.via_edges.assign(es,es+size); + }); + } + + std::vector run(Config cfg) { + auto begin=Clock::now(); gpu_ms=0; waits=0; rounds=0; edge_visits=0; fallback=false; + if(cfg.solver=="old_pull" || cfg.solver=="old_group") { + auto results=old.run(cfg.solver=="old_group",cfg.name.ends_with("serial")); + gpu_ms=old.gpu_ms; distance_ms=old.distance_ms; rounds=old.rounds; + waits=cfg.solver=="old_pull" ? (rounds+7)/8 : 1; + // For persistent groups, per-query round counts can differ. + if(cfg.solver=="old_pull") edge_visits=uint64_t(rounds)*e*q; + else for(size_t i=0;i(old.changed.contents)[i])*e; + if(!cfg.name.ends_with("serial")) cpu_dags(results); + return results; + } + if(cfg.narrow && !fits32) { cfg.narrow=false; cfg.solver="pull"; fallback=true; } + if(cfg.solver!="pull") cfg.layout=false; + auto data=cfg.solver=="pull" ? pull(cfg) : frontier(cfg); + std::vector results(q); + // Hoist Objective-C accessors out of the per-distance conversion loop. + // Calling .contents for every element dominated large-batch host time. + auto data32=static_cast(data.contents); + auto data64=static_cast(data.contents); + auto copy=[&](int query) { + auto& dist=results[query].first; dist.resize(n); + if(!cfg.layout && !cfg.narrow) { + auto ptr=data64+query*n; + std::copy_n(ptr,n,dist.begin()); + } else for(size_t v=0;v configurations() { + return { + {"old_pull_serial","old_pull"}, {"old_group_serial","old_group"}, + {"old_pull_parallel_dag","old_pull"}, {"old_group_parallel_dag","old_group"}, + {"pull64_barrier","pull"}, {"pull64_interleaved","pull",true}, + {"pull32_interleaved","pull",true,true}, + {"pull32_gpu_dag","pull",true,true,true}, + {"frontier32_vertex","frontier",false,true,false,1}, + {"frontier32_simd","frontier",false,true,false,32}, + {"frontier32_gpu_dag","frontier",false,true,true,32}, + {"bucket32_d4","frontier",false,true,false,32,4}, + {"bucket32_d16","frontier",false,true,false,32,16}, + {"bucket32_d64","frontier",false,true,false,32,64} + }; +} + +Case hub_case(int n) { + std::vector a,b; std::vector w; std::vector cap; + auto add=[&](int u,int v,int cost) {a.push_back(u);b.push_back(v);w.push_back(cost);cap.push_back(1);}; + for(int i=0;i(w.size()); std::fill_n(c.edge_mask.get(),w.size(),true); + c.residual.assign(w.size(),1); return c; +} + +// A stronger comparator for the uniform positive-weight grid/fabric workloads. +// This uses the same cached eligibility and one-pass parallel DAG builder as +// the optimized GPU variants. All output is checked against native Dijkstra. +std::vector cpu_bfs(const Case& c, const OptimizedGraph& gpu, NodeId source) { + int n=c.graph.num_nodes(); + auto row=c.reverse ? c.graph.in_row_offsets_view() : c.graph.row_offsets_view(); + auto col=c.reverse ? c.graph.in_col_indices_view() : c.graph.col_indices_view(); + auto enabled=static_cast(gpu.outenabled.contents); + Cost weight=c.graph.cost_view()[0]; + std::vector dist(n,INF); + if(!c.node_mask[source]) return dist; + std::vector queue(n); size_t head=0,tail=0; + dist[source]=0; queue[tail++]=source; + while(head a{0,0,1,1,2,3,4,0,1,2},b{1,1,2,2,3,4,5,5,1,5}; + std::vector w(a.size(),weight); + std::vector cap(a.size(),1); + auto c=make_case("random",n); + c.name="boundary_"+std::to_string(weight)+(reverse ? "_reverse" : "")+(blocked ? "_masked" : ""); + c.graph=StrictMultiDiGraph::from_arrays(n,a,b,cap,w); + c.edge_mask=std::make_unique(w.size()); std::fill_n(c.edge_mask.get(),w.size(),true); + c.residual.assign(w.size(),1); c.reverse=reverse; + // Competing direct/parallel edges, a self-loop, threshold-adjacent residuals, + // and blocked sources/unreachable nodes. Eligibility is evaluated in double. + c.residual[1]=std::nextafter(kMinCap,0.0); c.residual[3]=kMinCap; + c.edge_mask[7]=false; c.edge_mask[9]=false; + if(blocked) c.node_mask[2]=false; + return c; +} + +void run_case(Case c,int queries,std::string mode,int samples,OptimizedMetal& metal,Pool& pool) { + std::vector sources(queries); + std::vector expected(queries); + for(int i=0;i0 && std::all_of(costs.begin(),costs.end(),[&](Cost w){return w==costs[0];})) { + configs.push_back({"cpu_bfs_full","cpu"}); configs.push_back({"cpu_bfs_distance","cpu"}); + } + } + else if(mode=="optimized") configs.erase(configs.begin(),configs.begin()+2); + else if(mode!="all") throw std::runtime_error("bad mode"); + for(auto cfg:configs) { + std::vector times,dt,gt,work,rounds,waits; + int fallback=0; + for(int rep=-2;rep result; + if(mode=="cpu") { + result.resize(queries); + auto query=[&](int i) { + if(cfg.name.starts_with("cpu_bfs")) result[i].first=cpu_bfs(c,gpu,sources[i]); + else if(cfg.name=="cpu_full") result[i]=cpu(c,sources[i]); + else result[i].first=cpu_distance(c,sources[i]); + }; + if(queries==1) query(0); else pool.run(queries,query); + if(cfg.name=="cpu_bfs_full") gpu.cpu_dags(result); + } else result=gpu.run(cfg); + double elapsed=ms(begin); + if(cfg.name.ends_with("distance")) { + for(int i=0;i=0) { + times.push_back(elapsed); dt.push_back(mode=="cpu" ? elapsed : gpu.distance_ms); + gt.push_back(mode=="cpu" ? 0 : gpu.gpu_ms); work.push_back(mode=="cpu" ? 0 : double(gpu.edge_visits)); + rounds.push_back(mode=="cpu" ? 0 : gpu.rounds); waits.push_back(mode=="cpu" ? 0 : gpu.waits); + fallback=mode=="cpu" ? 0 : gpu.fallback; + } + } + std::cout<3 ? std::stoi(argv[3]) : 7; + if(samples<1) throw std::runtime_error("invalid samples"); + OptimizedMetal metal; Pool pool(10); + std::cout<<"case,n,e,queries,method,wall_ms,distance_ms,gpu_ms,edge_visits,rounds,waits,fallback64,upload_ms,samples,correct,wall_samples_ms\n"; + auto run=[&](Case c,int q) { run_case(std::move(c),q,mode,samples,metal,pool); }; + if(suite=="correctness") { + for(unsigned seed=1;seed<=12;++seed) run(make_case("random",37+seed*3,6,true,seed%2,seed%3==0,seed),8); + for(Cost weight:{Cost(700000000),Cost(715827883),(Cost(1)<<53)+1}) + for(bool reverse:{false,true}) for(bool blocked:{false,true}) run(boundary_case(weight,reverse,blocked),6); + } else if(suite=="stress") { + run(make_case("grid",1024),64); run(make_case("random",1024,8,true,false,true),64); + } else { + run(make_case("random",1024),1); run(make_case("random",1024),64); + run(make_case("clos",200),64); run(make_case("grid",1024),1); + run(hub_case(1024),1); run(make_case("random",1024,8,true,true,true),8); + if(suite=="full") { + run(make_case("random",4096),256); + run(make_case("random",16384),1); run(make_case("random",16384),64); + run(make_case("random",65536),1); + run(make_case("clos",800),1); run(make_case("clos",800),64); + run(make_case("grid",10000),1); run(make_case("grid",10000),8); + run(make_case("chain",2048),1); run(hub_case(4096),64); + run(make_case("random",4096,32),1); run(make_case("random",4096,32),64); + } else if(suite!="smoke") throw std::runtime_error("bad suite"); + } + } catch(const std::exception& e) {std::cerr<<"FAIL: "< +using namespace metal; + +struct P { + uint n, q, round, layout; + uint current, epoch, lanes, delta; +}; +constant long INF64 = 0x7fffffffffffffffL; +constant uint INF32 = 0xffffffffu; + +// Same relaxation as phase one, with optional query-fast layout and 32-bit +// distances only after the host proves the entire finite-distance domain fits. +template +void pull(device const int* row, device const int* col, + device const T* weight, device const uchar* enabled, + device const T* a, device T* b, device atomic_uint* changed, + constant P& p, uint tid, uint lane, T inf) { + uint total = p.n * p.q; + bool dirty = false; + if (tid < total) { + uint v = p.layout ? tid / p.q : tid % p.n; + uint query = p.layout ? tid % p.q : tid / p.n; + T best = a[tid]; + for (int j = row[v]; j < row[v + 1]; ++j) { + uint index = p.layout ? uint(col[j]) * p.q + query : query * p.n + uint(col[j]); + T d = a[index], w = weight[j]; + if (enabled[j] && d != inf && d <= inf - w) best = min(best, T(d + w)); + } + b[tid] = best; + dirty = best != a[tid]; + } + // One flag operation per SIMD group, instead of per changed vertex. + if (simd_any(dirty) && lane == 0) + atomic_store_explicit(changed + p.round, 1u, memory_order_relaxed); +} + +#define PULL_ARGS(T) device const int* row [[buffer(0)]], device const int* col [[buffer(1)]], \ + device const T* weight [[buffer(2)]], device const uchar* enabled [[buffer(3)]], \ + device const T* a [[buffer(4)]], device T* b [[buffer(5)]], \ + device atomic_uint* changed [[buffer(6)]], constant P& p [[buffer(7)]], \ + uint tid [[thread_position_in_grid]], uint lane [[thread_index_in_simdgroup]] +kernel void pull64(PULL_ARGS(long)) { pull(row,col,weight,enabled,a,b,changed,p,tid,lane,INF64); } +kernel void pull32(PULL_ARGS(uint)) { pull(row,col,weight,enabled,a,b,changed,p,tid,lane,INF32); } + +// Frontier queues contain flattened (query * N + node) IDs. Only 32-bit integer +// atomics are required. All queue consumers run after producer dispatch barriers. +kernel void prepare(device atomic_uint* counts [[buffer(0)]], + device uint* indirect [[buffer(1)]], + constant P& p [[buffer(7)]]) { + uint count = atomic_load_explicit(counts + p.current, memory_order_relaxed); + atomic_store_explicit(counts + (1 - p.current), 0u, memory_order_relaxed); + indirect[0] = max(1u, (count * p.lanes + 255) / 256); + indirect[1] = 1; indirect[2] = 1; +} + +kernel void expand(device const int* row [[buffer(0)]], + device const int* col [[buffer(1)]], + device const uint* weight [[buffer(2)]], + device const uchar* enabled [[buffer(3)]], + device atomic_uint* dist [[buffer(4)]], + device const uint* in_queue [[buffer(5)]], + device uint* out_queue [[buffer(6)]], + constant P& p [[buffer(7)]], + device atomic_uint* counts [[buffer(8)]], + device atomic_uint* marks [[buffer(9)]], + device atomic_uint* work [[buffer(10)]], + uint tid [[thread_position_in_grid]]) { + uint slot = tid / p.lanes, lane = tid % p.lanes; + uint count = atomic_load_explicit(counts + p.current, memory_order_relaxed); + if (slot >= count) return; + uint index = in_queue[slot], u = index % p.n, base = index - u; + uint d = atomic_load_explicit(dist + index, memory_order_relaxed); + if (lane == 0) atomic_fetch_add_explicit(work + p.round, uint(row[u+1]-row[u]), memory_order_relaxed); + for (uint j = uint(row[u]) + lane; j < uint(row[u+1]); j += p.lanes) { + uint w = weight[j]; + if (!enabled[j] || d == INF32 || d > INF32 - w) continue; + uint target = base + uint(col[j]); + uint candidate = d + w; + uint old = atomic_fetch_min_explicit(dist + target, candidate, memory_order_relaxed); + if (candidate < old) { + if (p.delta) { + // Bucket mode: mark pending. Selection and clearing happen in a later + // dispatch, so a late improvement cannot be lost behind an early reset. + atomic_store_explicit(marks + target, 1u, memory_order_relaxed); + } else if (atomic_exchange_explicit(marks + target, p.epoch, memory_order_relaxed) != p.epoch) { + uint pos = atomic_fetch_add_explicit(counts + (1-p.current), 1u, memory_order_relaxed); + out_queue[pos] = target; // Epoch deduplication bounds this queue by N*Q. + } + } + } +} + +// A simple bucketed label-correcting scheduler. This deliberately does not claim +// the optimized light/heavy split or asynchronous scheduler of published ADDS. +kernel void bucket_reset(device atomic_uint* counts [[buffer(0)]], + device atomic_uint* min_distance [[buffer(1)]]) { + atomic_store_explicit(counts, 0u, memory_order_relaxed); + atomic_store_explicit(min_distance, INF32, memory_order_relaxed); +} +kernel void bucket_min(device const atomic_uint* dist [[buffer(0)]], + device const atomic_uint* pending [[buffer(1)]], + device atomic_uint* minimum [[buffer(2)]], + constant P& p [[buffer(7)]], uint tid [[thread_position_in_grid]]) { + if (tid >= p.n*p.q) return; + if (atomic_load_explicit(pending+tid, memory_order_relaxed)) + atomic_fetch_min_explicit(minimum, atomic_load_explicit(dist+tid, memory_order_relaxed), memory_order_relaxed); +} +kernel void bucket_select(device const atomic_uint* dist [[buffer(0)]], + device atomic_uint* pending [[buffer(1)]], + device const atomic_uint* minimum [[buffer(2)]], + device uint* queue [[buffer(3)]], + device atomic_uint* counts [[buffer(4)]], + constant P& p [[buffer(7)]], uint tid [[thread_position_in_grid]]) { + if (tid >= p.n*p.q) return; + uint lowest = atomic_load_explicit(minimum, memory_order_relaxed); + if (lowest == INF32) return; + ulong upper = (ulong(lowest) / p.delta + 1) * p.delta; + if (atomic_load_explicit(pending+tid, memory_order_relaxed) && + ulong(atomic_load_explicit(dist+tid, memory_order_relaxed)) < upper) { + atomic_store_explicit(pending+tid, 0u, memory_order_relaxed); + uint pos = atomic_fetch_add_explicit(counts, 1u, memory_order_relaxed); + queue[pos] = tid; + } +} + +// Counts and fills are deterministic within each node's incoming CSR row. +// The host prefix-sums N+1 counts per query; it never scans edges for GPU DAGs. +struct DP { uint n, q, edges, layout, reverse, unused0, unused1, unused2; }; +template +void dag(device const int* row, device const int* col, device const long* costs, + device const int* ids, device const uchar* enabled, device const T* distances, + device int* offsets, device int* parents, device int* via, + constant DP& p, uint tid, T inf) { + if (tid >= p.n*p.q) return; + // Match distance layout. Query-major frontiers must not be read with a + // query-fast thread layout (which also scatters the output writes). + uint v = p.layout ? tid / p.q : tid % p.n; + uint query = p.layout ? tid % p.q : tid / p.n; + uint index = p.layout ? v*p.q+query : query*p.n+v; + T dv = distances[index]; + uint count = 0; + for (int j=row[v]; j(row,col,costs,ids,enabled,distances,offsets,parents,via,p,tid,INF64);} +kernel void dag_fill64(DAG_ARGS(long)) {dag(row,col,costs,ids,enabled,distances,offsets,parents,via,p,tid,INF64);} +kernel void dag_count32(DAG_ARGS(uint)) {dag(row,col,costs,ids,enabled,distances,offsets,parents,via,p,tid,INF32);} +kernel void dag_fill32(DAG_ARGS(uint)) {dag(row,col,costs,ids,enabled,distances,offsets,parents,via,p,tid,INF32);} diff --git a/dev/research/metal_pathfinding/optimization/results/aba/base-a1-stderr.txt b/dev/research/metal_pathfinding/optimization/results/aba/base-a1-stderr.txt new file mode 100644 index 0000000..7bb0bd9 --- /dev/null +++ b/dev/research/metal_pathfinding/optimization/results/aba/base-a1-stderr.txt @@ -0,0 +1 @@ +device=Apple M4 Max setup_ms=22.61 execution_width=32 diff --git a/dev/research/metal_pathfinding/optimization/results/aba/base-a1.csv b/dev/research/metal_pathfinding/optimization/results/aba/base-a1.csv new file mode 100644 index 0000000..e5ad76f --- /dev/null +++ b/dev/research/metal_pathfinding/optimization/results/aba/base-a1.csv @@ -0,0 +1,37 @@ +case,n,e,queries,method,wall_ms,distance_ms,gpu_ms,edge_visits,rounds,waits,fallback64,upload_ms,samples,correct,wall_samples_ms +random,1024,8192,1,old_pull_serial,1.218542,1.184500,0.434750,131072,16,2,0,0.163666,7,pass,1.000000;1.328541;1.493417;0.990875;1.405333;1.218542;0.689625 +random,1024,8192,1,old_group_serial,0.914792,0.838625,0.680833,106496,13,1,0,0.163666,7,pass,1.091958;1.201000;0.947125;0.901458;0.828708;0.911875;0.914792 +random,1024,8192,64,old_pull_serial,4.582958,2.376417,1.597625,12582912,24,3,0,0.191292,7,pass,4.323625;4.577125;4.633041;4.582291;4.727458;4.582958;4.598000 +random,1024,8192,64,old_group_serial,3.817917,1.374833,0.888208,7217152,17,1,0,0.191292,7,pass,3.695125;3.650917;3.798041;3.875042;3.905208;3.916333;3.817917 +clos,200,20000,64,old_pull_serial,5.426542,1.323042,1.016625,10240000,8,1,0,0.336458,7,pass,5.426542;6.071792;5.522958;5.353000;5.670708;5.278334;5.226583 +clos,200,20000,64,old_group_serial,4.768459,0.824667,0.297875,3840000,3,1,0,0.336458,7,pass,4.593416;4.673916;4.953792;4.768459;4.814791;4.615209;4.778209 +grid,1024,3968,1,old_pull_serial,2.331167,2.316292,0.674458,253952,64,8,0,0.136791,7,pass,2.582333;2.420166;3.165750;1.632958;2.331167;1.751666;2.164334 +grid,1024,3968,1,old_group_serial,1.177083,1.162041,1.011542,249984,63,1,0,0.136791,7,pass,1.177083;1.213291;1.289917;1.256459;0.749750;0.362417;0.363500 +hub,1024,3070,1,old_pull_serial,6.268542,6.232250,5.561125,98240,32,4,0,0.106126,7,pass,6.262917;6.289917;6.268542;6.305542;6.316250;6.211292;6.225167 +hub,1024,3070,1,old_group_serial,4.908083,4.871666,4.720917,95170,31,1,0,0.106126,7,pass,4.920042;4.880292;4.908083;4.920708;4.874500;4.864417;4.935875 +random_masked_int64_reverse,1024,8192,8,old_pull_serial,0.517667,0.177166,0.034542,524288,8,1,0,0.204624,7,pass,0.581375;0.517667;0.506875;0.530667;0.517625;0.515750;0.530000 +random_masked_int64_reverse,1024,8192,8,old_group_serial,0.540875,0.194500,0.053500,368640,8,1,0,0.204624,7,pass,0.528417;0.557417;0.540875;0.509500;0.529500;0.548333;0.542875 +random,4096,32768,256,old_pull_serial,49.824334,11.526875,10.145042,201326592,24,3,0,0.545166,7,pass,49.824334;48.800334;48.571958;50.309667;60.286459;59.534375;48.844875 +random,4096,32768,256,old_group_serial,47.811583,10.256667,9.388917,136544256,20,1,0,0.545166,7,pass,55.883000;48.061916;47.811583;46.029625;52.619583;44.779875;46.107125 +random,16384,131072,1,old_pull_serial,2.098167,1.418667,0.204500,3145728,24,3,0,1.713958,7,pass,2.129833;2.098167;1.690500;1.244875;1.214875;2.128125;2.209500 +random,16384,131072,1,old_group_serial,5.719417,5.032459,4.894625,2359296,18,1,0,1.713958,7,pass,6.076542;6.048834;5.709042;5.723250;5.613625;5.697458;5.719417 +random,16384,131072,64,old_pull_serial,58.904791,13.714458,11.617375,201326592,24,3,0,1.789209,7,pass,58.790875;58.904791;58.887125;59.272084;60.799708;57.959042;60.167875 +random,16384,131072,64,old_group_serial,57.747584,12.236500,11.485375,158203904,22,1,0,1.789209,7,pass,58.655667;57.747584;59.414083;57.772666;56.986792;54.688833;54.776958 +random,65536,524288,1,old_pull_serial,5.184250,2.258042,1.213708,12582912,24,3,0,7.745292,7,pass,4.513042;5.060667;5.293625;4.965250;5.271292;5.197875;5.184250 +random,65536,524288,1,old_group_serial,31.832791,28.881959,28.222000,11534336,22,1,0,7.745292,7,pass,31.485125;32.601083;31.832791;32.451750;31.760709;31.991375;31.556166 +clos,800,320000,1,old_pull_serial,1.914708,0.940584,0.731375,2560000,8,1,0,3.524250,7,pass,2.299041;1.914708;2.434625;1.906125;1.881542;1.843375;2.396875 +clos,800,320000,1,old_group_serial,2.133459,1.204000,0.911125,960000,3,1,0,3.524250,7,pass,2.036042;2.133459;2.484125;2.030542;2.462916;2.034041;2.559167 +clos,800,320000,64,old_pull_serial,80.507125,16.727542,16.177125,163840000,8,1,0,3.424624,7,pass,82.494541;80.253417;77.992667;81.233334;80.507125;79.556875;82.401250 +clos,800,320000,64,old_group_serial,69.896166,5.788917,5.249208,61440000,3,1,0,3.424624,7,pass,69.789625;70.156958;69.876959;69.579166;71.083958;70.201209;69.896166 +grid,10000,39600,1,old_pull_serial,3.836417,3.719583,0.559000,7920000,200,25,0,0.502708,7,pass,5.548333;3.887375;3.836417;3.699709;3.756375;4.001833;3.686625 +grid,10000,39600,1,old_group_serial,7.867833,7.721208,7.582500,7880400,199,1,0,0.502708,7,pass,7.953000;7.827709;7.980666;7.854667;7.867833;7.806167;7.943125 +grid,10000,39600,8,old_pull_serial,5.952708,4.955667,1.338125,63360000,200,25,0,0.507209,7,pass,5.595708;5.952708;6.127416;6.336792;6.075833;5.918666;5.732208 +grid,10000,39600,8,old_group_serial,9.001917,8.070500,7.435958,51480000,199,1,0,0.507209,7,pass,8.705167;8.996542;9.001917;9.232250;9.057666;8.974042;9.170042 +chain,2048,2047,1,old_pull_serial,30.622833,30.613000,4.401709,4192256,2048,256,0,0.106750,7,pass,30.267459;30.836959;30.523334;31.464417;30.622833;29.359666;30.867458 +chain,2048,2047,1,old_group_serial,4.834291,4.825792,4.700625,4192256,2048,1,0,0.106750,7,pass,4.829625;4.934042;4.834042;4.889959;4.834291;4.936625;4.812917 +hub,4096,12286,64,old_pull_serial,35.138250,32.326583,30.902083,31452160,40,5,0,0.252917,7,pass,35.515125;35.051541;35.533042;35.235333;35.138250;35.127750;34.555833 +hub,4096,12286,64,old_group_serial,28.558708,25.740416,24.993833,27176632,38,1,0,0.252917,7,pass,27.957792;28.558708;28.586458;28.663542;28.538000;28.549500;28.668834 +random,4096,131072,1,old_pull_serial,0.906250,0.525417,0.266958,2097152,16,2,0,1.621291,7,pass,0.935750;0.866084;0.857208;0.905250;0.920208;0.915709;0.906250 +random,4096,131072,1,old_group_serial,2.808042,2.361958,2.183542,1572864,12,1,0,1.621291,7,pass,2.680625;2.884875;2.723166;2.877167;2.812500;2.808042;2.712208 +random,4096,131072,64,old_pull_serial,34.709250,7.647459,6.259584,134217728,16,2,0,1.701542,7,pass,34.723375;34.123167;34.742875;34.709250;34.173084;34.822959;34.691500 +random,4096,131072,64,old_group_serial,31.930417,5.221542,4.481375,105644032,15,1,0,1.701542,7,pass,30.898458;31.379041;31.775500;31.930417;34.155750;35.345083;39.651000 diff --git a/dev/research/metal_pathfinding/optimization/results/aba/base-a2-stderr.txt b/dev/research/metal_pathfinding/optimization/results/aba/base-a2-stderr.txt new file mode 100644 index 0000000..cb44dce --- /dev/null +++ b/dev/research/metal_pathfinding/optimization/results/aba/base-a2-stderr.txt @@ -0,0 +1 @@ +device=Apple M4 Max setup_ms=23.7174 execution_width=32 diff --git a/dev/research/metal_pathfinding/optimization/results/aba/base-a2.csv b/dev/research/metal_pathfinding/optimization/results/aba/base-a2.csv new file mode 100644 index 0000000..fd30af0 --- /dev/null +++ b/dev/research/metal_pathfinding/optimization/results/aba/base-a2.csv @@ -0,0 +1,37 @@ +case,n,e,queries,method,wall_ms,distance_ms,gpu_ms,edge_visits,rounds,waits,fallback64,upload_ms,samples,correct,wall_samples_ms +random,1024,8192,1,old_pull_serial,0.994334,0.952458,0.399000,131072,16,2,0,0.171417,7,pass,1.577916;0.994334;0.656417;0.664875;0.658917;1.304083;1.546834 +random,1024,8192,1,old_group_serial,0.971833,0.906041,0.680458,106496,13,1,0,0.171417,7,pass,1.023334;1.103292;0.903125;0.840208;0.971833;1.167083;0.936791 +random,1024,8192,64,old_pull_serial,4.691209,2.347542,1.613625,12582912,24,3,0,0.210375,7,pass,4.444834;4.580166;4.754000;5.102500;4.831000;4.639291;4.691209 +random,1024,8192,64,old_group_serial,3.768791,1.364167,0.890125,7217152,17,1,0,0.210375,7,pass,3.744584;3.776792;3.828208;3.773291;3.758709;3.535167;3.768791 +clos,200,20000,64,old_pull_serial,5.650709,1.616708,1.020042,10240000,8,1,0,0.356209,7,pass,5.676875;5.621667;5.220125;6.236833;5.650709;6.217083;5.466333 +clos,200,20000,64,old_group_serial,4.869958,0.831250,0.297000,3840000,3,1,0,0.356209,7,pass,4.959333;4.867584;4.914292;4.869958;4.947166;4.766166;4.391625 +grid,1024,3968,1,old_pull_serial,1.665000,1.652209,0.655292,253952,64,8,0,0.141624,7,pass,1.644250;1.733125;1.603333;1.672625;1.665000;1.664375;1.721208 +grid,1024,3968,1,old_group_serial,1.165667,1.143208,1.005833,249984,63,1,0,0.141624,7,pass,1.263334;1.182333;1.165667;1.273125;0.885333;0.363959;0.362584 +hub,1024,3070,1,old_pull_serial,6.226792,6.189458,5.559000,98240,32,4,0,0.111583,7,pass,6.469750;6.205875;6.281875;6.313250;6.206291;6.226792;6.218000 +hub,1024,3070,1,old_group_serial,4.938125,4.898500,4.725042,95170,31,1,0,0.111583,7,pass,4.938125;4.984083;4.930291;5.019042;4.921959;4.917917;4.942417 +random_masked_int64_reverse,1024,8192,8,old_pull_serial,0.551250,0.183875,0.034625,524288,8,1,0,0.234124,7,pass,0.562916;0.611584;0.507541;0.584208;0.551250;0.545666;0.529500 +random_masked_int64_reverse,1024,8192,8,old_group_serial,0.545000,0.189625,0.053708,368640,8,1,0,0.234124,7,pass,0.550208;0.545000;0.559584;0.519125;0.599333;0.510333;0.538333 +random,4096,32768,256,old_pull_serial,50.688208,12.960833,11.693708,201326592,24,3,0,0.566458,7,pass,49.485708;50.688208;50.617541;52.575375;52.112584;51.623333;49.864333 +random,4096,32768,256,old_group_serial,49.310208,10.459583,9.632500,136544256,20,1,0,0.566458,7,pass,50.547542;49.310208;50.391084;48.556292;47.586917;48.562834;50.677916 +random,16384,131072,1,old_pull_serial,1.870458,1.257416,0.473583,3145728,24,3,0,1.747834,7,pass,1.870458;1.471084;2.038875;2.288666;2.138458;1.621583;1.435041 +random,16384,131072,1,old_group_serial,5.578000,4.954917,4.794625,2359296,18,1,0,1.747834,7,pass,5.681334;5.572917;5.537625;5.559917;5.578000;5.596708;5.730166 +random,16384,131072,64,old_pull_serial,57.437709,12.714583,11.452709,201326592,24,3,0,1.729083,7,pass,60.324959;56.396250;57.583125;56.772667;57.974125;57.437709;56.800125 +random,16384,131072,64,old_group_serial,53.105750,9.701208,8.881250,158203904,22,1,0,1.729083,7,pass,56.427459;54.848291;53.105750;52.603333;52.648291;53.011417;53.238417 +random,65536,524288,1,old_pull_serial,5.853750,3.010042,1.934167,12582912,24,3,0,7.061209,7,pass,5.853750;6.207166;7.395542;7.228292;4.723625;4.678916;4.148125 +random,65536,524288,1,old_group_serial,31.751625,28.941250,28.602500,11534336,22,1,0,7.061209,7,pass,32.139125;31.751625;31.628667;32.141583;31.560792;32.478667;31.455667 +clos,800,320000,1,old_pull_serial,2.377209,1.431583,0.753875,2560000,8,1,0,3.556167,7,pass,2.377209;1.955250;2.455833;2.367417;2.430083;2.385417;2.145208 +clos,800,320000,1,old_group_serial,2.556458,1.576792,0.968750,960000,3,1,0,3.556167,7,pass,2.589084;2.650250;2.526500;2.137334;2.679083;2.422542;2.556458 +clos,800,320000,64,old_pull_serial,83.521542,17.978958,17.478500,163840000,8,1,0,3.485250,7,pass,81.691167;84.700792;84.167000;81.558666;84.714084;83.126750;83.521542 +clos,800,320000,64,old_group_serial,70.227500,6.031083,5.390125,61440000,3,1,0,3.485250,7,pass,70.227500;70.059209;71.906542;69.788417;69.684208;71.298291;70.334458 +grid,10000,39600,1,old_pull_serial,5.873791,5.752500,2.571416,7920000,200,25,0,0.517166,7,pass,5.931959;5.884000;5.702542;6.143625;5.873791;4.747083;3.651417 +grid,10000,39600,1,old_group_serial,7.900583,7.766667,7.575625,7880400,199,1,0,0.517166,7,pass,7.784292;7.930583;7.900125;7.962542;7.925792;7.900583;7.879125 +grid,10000,39600,8,old_pull_serial,5.979167,5.041833,1.348542,63360000,200,25,0,0.506958,7,pass,5.915125;6.136083;6.013709;6.170083;5.979167;5.367833;5.483750 +grid,10000,39600,8,old_group_serial,8.833417,7.841084,7.497625,51480000,199,1,0,0.506958,7,pass,9.022208;8.728042;9.240834;8.833417;9.221417;8.709959;8.703625 +chain,2048,2047,1,old_pull_serial,28.500458,28.490334,4.103082,4192256,2048,256,0,0.107834,7,pass,28.967458;28.705334;28.500458;28.192459;28.413625;28.474459;29.089833 +chain,2048,2047,1,old_group_serial,4.908333,4.887208,4.718333,4192256,2048,1,0,0.107834,7,pass,4.940458;4.827959;4.908333;4.908542;4.900500;4.872958;4.930334 +hub,4096,12286,64,old_pull_serial,35.024208,32.034125,30.893042,31452160,40,5,0,0.415751,7,pass,35.024208;34.828667;34.493209;35.587167;35.316875;35.020542;35.557792 +hub,4096,12286,64,old_group_serial,28.801291,25.839084,25.138125,27176632,38,1,0,0.415751,7,pass,28.757334;28.801291;29.161167;28.600792;28.971625;29.009417;28.756875 +random,4096,131072,1,old_pull_serial,1.039917,0.523167,0.231750,2097152,16,2,0,1.780084,7,pass,0.989042;1.005208;1.085208;1.040166;1.076500;1.039917;0.952042 +random,4096,131072,1,old_group_serial,2.897000,2.410042,2.244375,1572864,12,1,0,1.780084,7,pass,2.997791;2.892875;2.918125;3.060042;2.897000;2.823458;2.822250 +random,4096,131072,64,old_pull_serial,36.476625,7.182083,6.285833,134217728,16,2,0,1.895875,7,pass,36.498208;36.726250;36.476625;36.892708;36.295291;35.935750;36.099417 +random,4096,131072,64,old_group_serial,37.791458,8.716333,8.064625,105644032,15,1,0,1.895875,7,pass,34.829667;37.791458;38.231041;40.189750;39.685208;34.319125;35.647958 diff --git a/dev/research/metal_pathfinding/optimization/results/aba/cpu-a1-stderr.txt b/dev/research/metal_pathfinding/optimization/results/aba/cpu-a1-stderr.txt new file mode 100644 index 0000000..26cb375 --- /dev/null +++ b/dev/research/metal_pathfinding/optimization/results/aba/cpu-a1-stderr.txt @@ -0,0 +1 @@ +device=Apple M4 Max setup_ms=28.925 execution_width=32 diff --git a/dev/research/metal_pathfinding/optimization/results/aba/cpu-a1.csv b/dev/research/metal_pathfinding/optimization/results/aba/cpu-a1.csv new file mode 100644 index 0000000..c3fa171 --- /dev/null +++ b/dev/research/metal_pathfinding/optimization/results/aba/cpu-a1.csv @@ -0,0 +1,49 @@ +case,n,e,queries,method,wall_ms,distance_ms,gpu_ms,edge_visits,rounds,waits,fallback64,upload_ms,samples,correct,wall_samples_ms +random,1024,8192,1,cpu_full,0.085792,0.085792,0.000000,0,0,0,0,0.156042,7,pass,0.090042;0.086958;0.084917;0.085792;0.085166;0.084084;0.086291 +random,1024,8192,1,cpu_distance,0.050625,0.050625,0.000000,0,0,0,0,0.156042,7,pass,0.053458;0.050625;0.050750;0.050083;0.050833;0.049417;0.049792 +random,1024,8192,64,cpu_full,1.247667,1.247667,0.000000,0,0,0,0,0.179625,7,pass,1.311875;1.253000;1.283916;1.234333;1.247667;1.222625;1.230167 +random,1024,8192,64,cpu_distance,0.637834,0.637834,0.000000,0,0,0,0,0.179625,7,pass,0.659916;0.641583;0.637500;0.636542;0.635000;0.637834;0.673583 +clos,200,20000,64,cpu_full,1.072125,1.072125,0.000000,0,0,0,0,0.341708,7,pass,1.046542;1.066708;1.182333;1.086334;1.083958;1.070209;1.072125 +clos,200,20000,64,cpu_distance,0.236500,0.236500,0.000000,0,0,0,0,0.341708,7,pass,0.340000;0.352417;0.270083;0.211791;0.207666;0.210625;0.236500 +clos,200,20000,64,cpu_bfs_full,0.668917,0.668917,0.000000,0,0,0,0,0.341708,7,pass,0.584625;0.551000;0.668917;0.572917;1.059250;0.709625;0.824917 +clos,200,20000,64,cpu_bfs_distance,0.107959,0.107959,0.000000,0,0,0,0,0.341708,7,pass,0.121083;0.121792;0.125125;0.107959;0.098875;0.106792;0.099500 +grid,1024,3968,1,cpu_full,0.039042,0.039042,0.000000,0,0,0,0,0.131500,7,pass,0.042125;0.040916;0.039708;0.039000;0.039042;0.038708;0.038750 +grid,1024,3968,1,cpu_distance,0.012000,0.012000,0.000000,0,0,0,0,0.131500,7,pass,0.012334;0.012292;0.012000;0.011833;0.011834;0.011750;0.013917 +grid,1024,3968,1,cpu_bfs_full,0.009417,0.009417,0.000000,0,0,0,0,0.131500,7,pass,0.009667;0.009417;0.009333;0.011209;0.009375;0.009459;0.009416 +grid,1024,3968,1,cpu_bfs_distance,0.002250,0.002250,0.000000,0,0,0,0,0.131500,7,pass,0.002208;0.002250;0.002250;0.002250;0.002292;0.002250;0.002167 +hub,1024,3070,1,cpu_full,0.052333,0.052333,0.000000,0,0,0,0,0.088167,7,pass,0.054625;0.053500;0.052458;0.052250;0.051917;0.052250;0.052333 +hub,1024,3070,1,cpu_distance,0.024250,0.024250,0.000000,0,0,0,0,0.088167,7,pass,0.032333;0.027417;0.027333;0.024250;0.023000;0.022833;0.023333 +random_masked_int64_reverse,1024,8192,8,cpu_full,0.160083,0.160083,0.000000,0,0,0,0,0.211583,7,pass,0.160083;0.176334;0.154083;0.136833;0.218792;0.161000;0.148417 +random_masked_int64_reverse,1024,8192,8,cpu_distance,0.097875,0.097875,0.000000,0,0,0,0,0.211583,7,pass,0.104167;0.102375;0.089417;0.097500;0.119042;0.097875;0.091625 +random,4096,32768,256,cpu_full,21.390792,21.390792,0.000000,0,0,0,0,0.522792,7,pass,21.548084;21.431583;21.365709;21.390792;21.338292;21.801750;21.308459 +random,4096,32768,256,cpu_distance,10.971792,10.971792,0.000000,0,0,0,0,0.522792,7,pass,10.941667;10.993375;10.984292;10.964500;10.961292;10.982416;10.971792 +random,16384,131072,1,cpu_full,3.661958,3.661958,0.000000,0,0,0,0,1.746959,7,pass,3.746667;3.661083;3.750292;3.732167;3.661958;3.647583;3.608417 +random,16384,131072,1,cpu_distance,1.892958,1.892958,0.000000,0,0,0,0,1.746959,7,pass,1.928917;1.904500;1.910375;1.871917;1.892958;1.860250;1.857916 +random,16384,131072,64,cpu_full,27.692792,27.692792,0.000000,0,0,0,0,1.649084,7,pass,27.658708;27.723542;27.748375;27.639459;27.587250;27.692792;27.800584 +random,16384,131072,64,cpu_distance,15.163333,15.163333,0.000000,0,0,0,0,1.649084,7,pass,15.208709;15.168833;15.147959;15.182041;15.112375;15.163333;15.138666 +random,65536,524288,1,cpu_full,19.316000,19.316000,0.000000,0,0,0,0,8.086334,7,pass,19.478875;19.102083;19.316000;18.730125;19.269000;19.888458;19.416750 +random,65536,524288,1,cpu_distance,9.973291,9.973291,0.000000,0,0,0,0,8.086334,7,pass,9.973291;9.828167;9.980083;9.915125;10.174167;9.670458;10.011000 +clos,800,320000,1,cpu_full,2.177875,2.177875,0.000000,0,0,0,0,3.236458,7,pass,2.187833;2.149125;2.179167;2.127750;2.174667;2.177875;2.179375 +clos,800,320000,1,cpu_distance,0.353375,0.353375,0.000000,0,0,0,0,3.236458,7,pass,0.349791;0.351583;0.355959;0.350875;0.353375;0.356084;0.358625 +clos,800,320000,1,cpu_bfs_full,0.908000,0.908000,0.000000,0,0,0,0,3.236458,7,pass,0.894250;0.924792;0.909333;0.897084;0.879083;0.908000;0.937042 +clos,800,320000,1,cpu_bfs_distance,0.113125,0.113125,0.000000,0,0,0,0,3.236458,7,pass,0.108000;0.117208;0.118334;0.118125;0.111917;0.113083;0.113125 +clos,800,320000,64,cpu_full,17.041958,17.041958,0.000000,0,0,0,0,3.481041,7,pass,16.388250;16.388000;16.345833;17.041958;17.097833;17.276417;17.355125 +clos,800,320000,64,cpu_distance,2.677875,2.677875,0.000000,0,0,0,0,3.481041,7,pass,2.692500;2.691917;2.692916;2.664458;2.666875;2.677875;2.672917 +clos,800,320000,64,cpu_bfs_full,8.295667,8.295667,0.000000,0,0,0,0,3.481041,7,pass,8.552542;8.295667;8.069958;8.153791;8.517708;9.268417;7.606500 +clos,800,320000,64,cpu_bfs_distance,0.860834,0.860834,0.000000,0,0,0,0,3.481041,7,pass,0.877208;0.856917;0.860834;0.852542;0.853625;0.865167;0.862500 +grid,10000,39600,1,cpu_full,0.570333,0.570333,0.000000,0,0,0,0,0.470375,7,pass,0.594125;0.580542;0.570333;0.581792;0.562917;0.567750;0.565416 +grid,10000,39600,1,cpu_distance,0.195500,0.195500,0.000000,0,0,0,0,0.470375,7,pass,0.196333;0.195500;0.204250;0.205834;0.178250;0.179542;0.178500 +grid,10000,39600,1,cpu_bfs_full,0.089292,0.089292,0.000000,0,0,0,0,0.470375,7,pass,0.096875;0.091833;0.094041;0.089000;0.088291;0.089292;0.088625 +grid,10000,39600,1,cpu_bfs_distance,0.022333,0.022333,0.000000,0,0,0,0,0.470375,7,pass,0.022250;0.022458;0.022375;0.022333;0.022292;0.022333;0.022417 +grid,10000,39600,8,cpu_full,0.834084,0.834084,0.000000,0,0,0,0,0.487875,7,pass,0.822042;0.837667;0.834084;0.824375;0.947250;0.820791;0.905875 +grid,10000,39600,8,cpu_distance,0.247208,0.247208,0.000000,0,0,0,0,0.487875,7,pass,0.312416;0.251083;0.242958;0.247208;0.249833;0.242250;0.241583 +grid,10000,39600,8,cpu_bfs_full,0.286042,0.286042,0.000000,0,0,0,0,0.487875,7,pass,0.208750;0.380291;0.228291;0.305208;0.289917;0.286042;0.280583 +grid,10000,39600,8,cpu_bfs_distance,0.073084,0.073084,0.000000,0,0,0,0,0.487875,7,pass,0.073084;0.080750;0.059917;0.073875;0.061250;0.070417;0.078917 +chain,2048,2047,1,cpu_full,0.017209,0.017209,0.000000,0,0,0,0,0.136084,7,pass,0.017417;0.017042;0.017292;0.017125;0.017209;0.017042;0.017333 +chain,2048,2047,1,cpu_distance,0.003875,0.003875,0.000000,0,0,0,0,0.136084,7,pass,0.004292;0.003791;0.003875;0.003625;0.003834;0.004250;0.004292 +hub,4096,12286,64,cpu_full,2.437875,2.437875,0.000000,0,0,0,0,0.237500,7,pass,2.619125;2.383792;2.399750;2.449375;2.437875;2.494959;2.427084 +hub,4096,12286,64,cpu_distance,1.061875,1.061875,0.000000,0,0,0,0,0.237500,7,pass,1.033625;1.061875;1.169542;1.037792;1.101834;1.179625;1.025375 +random,4096,131072,1,cpu_full,1.589583,1.589583,0.000000,0,0,0,0,1.789499,7,pass,1.588625;1.589583;1.700625;1.634417;1.570459;1.556250;1.602333 +random,4096,131072,1,cpu_distance,0.648334,0.648334,0.000000,0,0,0,0,1.789499,7,pass,0.680583;0.654458;0.646000;0.670125;0.646000;0.631709;0.648334 +random,4096,131072,64,cpu_full,12.301875,12.301875,0.000000,0,0,0,0,1.617916,7,pass,12.273209;12.301875;12.218958;12.418250;12.324125;12.225125;14.931792 +random,4096,131072,64,cpu_distance,6.966334,6.966334,0.000000,0,0,0,0,1.617916,7,pass,7.551125;6.966334;6.212750;7.608792;7.220041;6.408000;6.150125 diff --git a/dev/research/metal_pathfinding/optimization/results/aba/cpu-a2-stderr.txt b/dev/research/metal_pathfinding/optimization/results/aba/cpu-a2-stderr.txt new file mode 100644 index 0000000..6703d2b --- /dev/null +++ b/dev/research/metal_pathfinding/optimization/results/aba/cpu-a2-stderr.txt @@ -0,0 +1 @@ +device=Apple M4 Max setup_ms=27.1879 execution_width=32 diff --git a/dev/research/metal_pathfinding/optimization/results/aba/cpu-a2.csv b/dev/research/metal_pathfinding/optimization/results/aba/cpu-a2.csv new file mode 100644 index 0000000..7a31e8d --- /dev/null +++ b/dev/research/metal_pathfinding/optimization/results/aba/cpu-a2.csv @@ -0,0 +1,49 @@ +case,n,e,queries,method,wall_ms,distance_ms,gpu_ms,edge_visits,rounds,waits,fallback64,upload_ms,samples,correct,wall_samples_ms +random,1024,8192,1,cpu_full,0.096875,0.096875,0.000000,0,0,0,0,0.174083,7,pass,0.102042;0.099000;0.096875;0.108042;0.094084;0.093875;0.095250 +random,1024,8192,1,cpu_distance,0.060958,0.060958,0.000000,0,0,0,0,0.174083,7,pass,0.071208;0.062958;0.064875;0.060958;0.057042;0.058167;0.058333 +random,1024,8192,64,cpu_full,1.340459,1.340459,0.000000,0,0,0,0,0.233833,7,pass,1.339292;1.340459;1.461292;1.366334;1.339458;1.339334;1.369500 +random,1024,8192,64,cpu_distance,0.663584,0.663584,0.000000,0,0,0,0,0.233833,7,pass,0.685834;0.674000;0.727500;0.663250;0.652916;0.639375;0.663584 +clos,200,20000,64,cpu_full,1.075958,1.075958,0.000000,0,0,0,0,0.372958,7,pass,1.282000;1.112375;1.074500;1.068083;1.078375;1.075958;1.045042 +clos,200,20000,64,cpu_distance,0.213417,0.213417,0.000000,0,0,0,0,0.372958,7,pass,0.221042;0.213417;0.207542;0.234416;0.213833;0.205459;0.213333 +clos,200,20000,64,cpu_bfs_full,0.633500,0.633500,0.000000,0,0,0,0,0.372958,7,pass,0.537833;0.574250;0.596792;0.647125;0.669458;0.633500;0.654042 +clos,200,20000,64,cpu_bfs_distance,0.086959,0.086959,0.000000,0,0,0,0,0.372958,7,pass,0.095250;0.097583;0.086166;0.086959;0.086875;0.119708;0.083708 +grid,1024,3968,1,cpu_full,0.038708,0.038708,0.000000,0,0,0,0,0.141166,7,pass,0.041292;0.039500;0.038708;0.038417;0.038209;0.041375;0.038584 +grid,1024,3968,1,cpu_distance,0.011750,0.011750,0.000000,0,0,0,0,0.141166,7,pass,0.012375;0.012125;0.011917;0.011750;0.011625;0.011458;0.011417 +grid,1024,3968,1,cpu_bfs_full,0.009375,0.009375,0.000000,0,0,0,0,0.141166,7,pass,0.011583;0.009375;0.009333;0.009375;0.009375;0.009250;0.009375 +grid,1024,3968,1,cpu_bfs_distance,0.002250,0.002250,0.000000,0,0,0,0,0.141166,7,pass,0.002417;0.002292;0.002209;0.002250;0.002208;0.002250;0.002208 +hub,1024,3070,1,cpu_full,0.052000,0.052000,0.000000,0,0,0,0,0.089875,7,pass,0.054083;0.052791;0.052584;0.052000;0.051250;0.050500;0.049667 +hub,1024,3070,1,cpu_distance,0.021875,0.021875,0.000000,0,0,0,0,0.089875,7,pass,0.023083;0.022209;0.021792;0.021875;0.021792;0.021708;0.021875 +random_masked_int64_reverse,1024,8192,8,cpu_full,0.153250,0.153250,0.000000,0,0,0,0,0.195541,7,pass,0.146583;0.156583;0.153250;0.150208;0.152708;0.154500;0.161333 +random_masked_int64_reverse,1024,8192,8,cpu_distance,0.096792,0.096792,0.000000,0,0,0,0,0.195541,7,pass,0.096792;0.099792;0.098333;0.100208;0.091708;0.095875;0.096000 +random,4096,32768,256,cpu_full,21.281458,21.281458,0.000000,0,0,0,0,0.549125,7,pass,21.277042;21.258375;21.281458;21.314917;21.324333;21.278875;21.311791 +random,4096,32768,256,cpu_distance,11.067666,11.067666,0.000000,0,0,0,0,0.549125,7,pass,10.994334;11.005000;11.026500;11.067666;11.480084;11.362334;11.215292 +random,16384,131072,1,cpu_full,3.885666,3.885666,0.000000,0,0,0,0,1.800708,7,pass,3.967125;3.796625;3.860291;4.262833;3.917000;3.885666;3.851709 +random,16384,131072,1,cpu_distance,1.976417,1.976417,0.000000,0,0,0,0,1.800708,7,pass,2.147667;1.979625;1.973542;1.929709;1.987833;1.976417;1.926417 +random,16384,131072,64,cpu_full,27.721375,27.721375,0.000000,0,0,0,0,1.755499,7,pass,27.835834;27.645166;28.465958;27.722000;27.721375;27.572417;27.613583 +random,16384,131072,64,cpu_distance,15.114541,15.114541,0.000000,0,0,0,0,1.755499,7,pass,15.135625;15.110792;15.146000;15.110208;15.084625;15.162208;15.114541 +random,65536,524288,1,cpu_full,19.240125,19.240125,0.000000,0,0,0,0,7.505250,7,pass,18.942084;19.240125;19.137625;18.829333;23.886875;23.010209;19.430541 +random,65536,524288,1,cpu_distance,11.143334,11.143334,0.000000,0,0,0,0,7.505250,7,pass,11.894666;11.143334;11.423291;11.711209;10.922250;10.678833;10.548333 +clos,800,320000,1,cpu_full,2.226791,2.226791,0.000000,0,0,0,0,3.538083,7,pass,2.209250;2.216750;2.188458;2.298666;2.251083;2.226791;2.260083 +clos,800,320000,1,cpu_distance,0.355500,0.355500,0.000000,0,0,0,0,3.538083,7,pass,0.357458;0.365666;0.355209;0.360042;0.355041;0.355500;0.354166 +clos,800,320000,1,cpu_bfs_full,0.937625,0.937625,0.000000,0,0,0,0,3.538083,7,pass,0.936500;0.937625;0.945042;0.929250;0.915417;0.948750;0.957208 +clos,800,320000,1,cpu_bfs_distance,0.123750,0.123750,0.000000,0,0,0,0,3.538083,7,pass,0.123666;0.123750;0.124541;0.124209;0.123875;0.123708;0.123667 +clos,800,320000,64,cpu_full,16.524625,16.524625,0.000000,0,0,0,0,3.487750,7,pass,16.632500;16.422167;16.362041;16.524625;16.451709;16.538916;17.851792 +clos,800,320000,64,cpu_distance,2.695875,2.695875,0.000000,0,0,0,0,3.487750,7,pass,2.691334;2.695875;2.701042;2.697666;2.720417;2.685208;2.679041 +clos,800,320000,64,cpu_bfs_full,7.884833,7.884833,0.000000,0,0,0,0,3.487750,7,pass,8.302500;7.823334;7.566250;8.220417;8.318000;7.284708;7.884833 +clos,800,320000,64,cpu_bfs_distance,0.852750,0.852750,0.000000,0,0,0,0,3.487750,7,pass,0.852750;0.845167;0.850709;0.855333;0.866959;0.852250;0.856625 +grid,10000,39600,1,cpu_full,0.582250,0.582250,0.000000,0,0,0,0,0.491958,7,pass,0.607667;0.600166;0.618917;0.582250;0.578916;0.577333;0.576292 +grid,10000,39600,1,cpu_distance,0.180667,0.180667,0.000000,0,0,0,0,0.491958,7,pass,0.182792;0.183417;0.180667;0.180958;0.175250;0.180667;0.180458 +grid,10000,39600,1,cpu_bfs_full,0.088459,0.088459,0.000000,0,0,0,0,0.491958,7,pass,0.088291;0.088917;0.090834;0.088459;0.088792;0.088250;0.088458 +grid,10000,39600,1,cpu_bfs_distance,0.022917,0.022917,0.000000,0,0,0,0,0.491958,7,pass,0.023041;0.022958;0.022625;0.022917;0.023000;0.022833;0.022750 +grid,10000,39600,8,cpu_full,0.822667,0.822667,0.000000,0,0,0,0,0.511542,7,pass,0.832125;0.829417;0.827291;0.794500;0.813292;0.776792;0.822667 +grid,10000,39600,8,cpu_distance,0.276209,0.276209,0.000000,0,0,0,0,0.511542,7,pass,0.276209;0.304541;0.321125;0.287250;0.269333;0.243208;0.248250 +grid,10000,39600,8,cpu_bfs_full,0.311708,0.311708,0.000000,0,0,0,0,0.511542,7,pass,0.265791;0.314416;0.360625;0.248334;0.311708;0.313541;0.259708 +grid,10000,39600,8,cpu_bfs_distance,0.066208,0.066208,0.000000,0,0,0,0,0.511542,7,pass,0.067666;0.066208;0.068375;0.060500;0.061917;0.083833;0.063875 +chain,2048,2047,1,cpu_full,0.017375,0.017375,0.000000,0,0,0,0,0.145041,7,pass,0.017333;0.019333;0.019292;0.019292;0.017333;0.017375;0.017208 +chain,2048,2047,1,cpu_distance,0.004250,0.004250,0.000000,0,0,0,0,0.145041,7,pass,0.004292;0.004250;0.004209;0.003667;0.004250;0.004250;0.004208 +hub,4096,12286,64,cpu_full,2.338125,2.338125,0.000000,0,0,0,0,0.253291,7,pass,2.335292;2.332416;2.317459;2.338125;2.381084;2.358125;2.366458 +hub,4096,12286,64,cpu_distance,1.035625,1.035625,0.000000,0,0,0,0,0.253291,7,pass,1.045917;1.049042;1.030417;1.033500;1.035625;1.039625;1.031583 +random,4096,131072,1,cpu_full,1.517583,1.517583,0.000000,0,0,0,0,1.896875,7,pass,1.623958;1.576583;1.545917;1.489375;1.478709;1.517583;1.455083 +random,4096,131072,1,cpu_distance,0.688208,0.688208,0.000000,0,0,0,0,1.896875,7,pass,0.716000;0.710083;0.689833;0.688208;0.669541;0.657958;0.656333 +random,4096,131072,64,cpu_full,12.817167,12.817167,0.000000,0,0,0,0,1.777875,7,pass,12.910500;12.817167;12.927917;12.482625;13.703958;12.457333;12.349375 +random,4096,131072,64,cpu_distance,5.703500,5.703500,0.000000,0,0,0,0,1.777875,7,pass,5.703500;5.924666;5.729834;5.690042;5.765166;5.701958;5.690917 diff --git a/dev/research/metal_pathfinding/optimization/results/aba/environment.txt b/dev/research/metal_pathfinding/optimization/results/aba/environment.txt new file mode 100644 index 0000000..12e4344 --- /dev/null +++ b/dev/research/metal_pathfinding/optimization/results/aba/environment.txt @@ -0,0 +1,20 @@ +2026-09-26T23:29:08Z +fbab119e794c843838f4f3f96d75cb7f32f06845 +ProductName: macOS +ProductVersion: 26.6.1 +BuildVersion: 25G76 +Apple M4 Max +38654705664 +14 +Apple clang version 21.0.0 (clang-2100.1.1.101) +Target: arm64-apple-darwin25.6.0 +Thread model: posix +InstalledDir: /Library/Developer/CommandLineTools/usr/bin +1da9ff77bd2ad97e95e951454821b25005859c6f75c27a3c56d925e5fc99f6fc dev/research/metal_pathfinding/experiment.mm +2e36b1623a3940bf1f19f5d81141bb1def14f5873fe2a98aab0101bbe68618a3 dev/research/metal_pathfinding/sssp.metal +7717db8d791d17f7f0ef0b672461ad82afb2ae99cc2ab6c8cb8b33b35e74dd25 dev/research/metal_pathfinding/optimization/experiment.mm +bed6c9a836e85520101659471c62b7c4c9eb6f4954cb7bb74c971f10c44f37ff dev/research/metal_pathfinding/optimization/kernels.metal +7bb649ffcd34e6be02ab14c35767b816b0b32ce3ee3c2fd91c199e4b37a837ce build/metal_pathfinding/optimized +Note: No thermal warning level has been recorded +Note: No performance warning level has been recorded +Note: No CPU power status has been recorded diff --git a/dev/research/metal_pathfinding/optimization/results/aba/gpu-load-base-a1.txt b/dev/research/metal_pathfinding/optimization/results/aba/gpu-load-base-a1.txt new file mode 100644 index 0000000..e35f762 --- /dev/null +++ b/dev/research/metal_pathfinding/optimization/results/aba/gpu-load-base-a1.txt @@ -0,0 +1 @@ + | "PerformanceStatistics" = {"In use system memory (driver)"=0,"Alloc system memory"=11174330368,"Tiler Utilization %"=5,"recoveryCount"=0,"lastRecoveryTime"=0,"Renderer Utilization %"=8,"TiledSceneBytes"=2228224,"Device Utilization %"=9,"SplitSceneCount"=0,"Allocated PB Size"=194379776,"In use system memory"=1583366144} diff --git a/dev/research/metal_pathfinding/optimization/results/aba/gpu-load-base-a2.txt b/dev/research/metal_pathfinding/optimization/results/aba/gpu-load-base-a2.txt new file mode 100644 index 0000000..3dfce12 --- /dev/null +++ b/dev/research/metal_pathfinding/optimization/results/aba/gpu-load-base-a2.txt @@ -0,0 +1 @@ + | "PerformanceStatistics" = {"In use system memory (driver)"=0,"Alloc system memory"=10970677248,"Tiler Utilization %"=3,"recoveryCount"=0,"lastRecoveryTime"=0,"Renderer Utilization %"=5,"TiledSceneBytes"=1507328,"Device Utilization %"=63,"SplitSceneCount"=0,"Allocated PB Size"=189661184,"In use system memory"=1386561536} diff --git a/dev/research/metal_pathfinding/optimization/results/aba/gpu-load-cpu-a1.txt b/dev/research/metal_pathfinding/optimization/results/aba/gpu-load-cpu-a1.txt new file mode 100644 index 0000000..aff1c2d --- /dev/null +++ b/dev/research/metal_pathfinding/optimization/results/aba/gpu-load-cpu-a1.txt @@ -0,0 +1 @@ + | "PerformanceStatistics" = {"In use system memory (driver)"=0,"Alloc system memory"=10953162752,"Tiler Utilization %"=4,"recoveryCount"=0,"lastRecoveryTime"=0,"Renderer Utilization %"=6,"TiledSceneBytes"=2326528,"Device Utilization %"=30,"SplitSceneCount"=0,"Allocated PB Size"=191889408,"In use system memory"=1362182144} diff --git a/dev/research/metal_pathfinding/optimization/results/aba/gpu-load-cpu-a2.txt b/dev/research/metal_pathfinding/optimization/results/aba/gpu-load-cpu-a2.txt new file mode 100644 index 0000000..191180b --- /dev/null +++ b/dev/research/metal_pathfinding/optimization/results/aba/gpu-load-cpu-a2.txt @@ -0,0 +1 @@ + | "PerformanceStatistics" = {"In use system memory (driver)"=0,"Alloc system memory"=11218386944,"Tiler Utilization %"=3,"recoveryCount"=0,"lastRecoveryTime"=0,"Renderer Utilization %"=5,"TiledSceneBytes"=1441792,"Device Utilization %"=66,"SplitSceneCount"=0,"Allocated PB Size"=193069056,"In use system memory"=1351647232} diff --git a/dev/research/metal_pathfinding/optimization/results/aba/gpu-load-optimized-b.txt b/dev/research/metal_pathfinding/optimization/results/aba/gpu-load-optimized-b.txt new file mode 100644 index 0000000..3a68cce --- /dev/null +++ b/dev/research/metal_pathfinding/optimization/results/aba/gpu-load-optimized-b.txt @@ -0,0 +1 @@ + | "PerformanceStatistics" = {"In use system memory (driver)"=0,"Alloc system memory"=10995400704,"Tiler Utilization %"=2,"recoveryCount"=0,"lastRecoveryTime"=0,"Renderer Utilization %"=3,"TiledSceneBytes"=1474560,"Device Utilization %"=66,"SplitSceneCount"=0,"Allocated PB Size"=192282624,"In use system memory"=1355710464} diff --git a/dev/research/metal_pathfinding/optimization/results/aba/load-base-a1.txt b/dev/research/metal_pathfinding/optimization/results/aba/load-base-a1.txt new file mode 100644 index 0000000..dd02bc0 --- /dev/null +++ b/dev/research/metal_pathfinding/optimization/results/aba/load-base-a1.txt @@ -0,0 +1,40 @@ +Processes: 1024 total, 3 running, 1021 sleeping, 5250 threads +2026/09/27 00:29:21 +Load Avg: 3.21, 3.60, 4.27 +CPU usage: 6.18% user, 11.61% sys, 82.20% idle +SharedLibs: 916M resident, 168M data, 136M linkedit. +MemRegions: 638813 total, 10G resident, 741M private, 4389M shared. +PhysMem: 34G used (4239M wired, 626M compressor), 1115M unused. +VM: 453T vsize, 6144M framework vsize, 2846220(0) swapins, 4729331(0) swapouts. +Networks: packets: 191126338/161G in, 146586979/163G out. +Disks: 97827999/2477G read, 117446770/2100G written. + +PID COMMAND %CPU #TH +99753 mscamerad-xpc 0.0 2 +99752 PlugInLibrarySer 0.0 2 +99750 QuickLookUIServi 0.0 3 +99749 com.apple.appkit 0.0 3 +99710 PlugInLibrarySer 0.0 2 +99709 Preview 0.0 4 +99428 crashpad_handler 0.0 4 +98995 crashpad_handler 0.0 4 +Processes: 1025 total, 4 running, 1021 sleeping, 5258 threads +2026/09/27 00:29:22 +Load Avg: 3.21, 3.60, 4.27 +CPU usage: 6.63% user, 5.47% sys, 87.88% idle +SharedLibs: 916M resident, 168M data, 136M linkedit. +MemRegions: 152 total, 11M resident, 741M private, 4418M shared. +PhysMem: 34G used (4196M wired, 626M compressor), 1089M unused. +VM: 453T vsize, 6144M framework vsize, 2846220(0) swapins, 4729331(0) swapouts. +Networks: packets: 191126514/161G in, 146587155/163G out. +Disks: 97828002/2477G read, 117446910/2100G written. + +PID COMMAND %CPU #TH +590 WindowServer 21.6 28/1 +70968 Superset Helper 15.9 32 +0 kernel_task 14.4 850/15 +7309 top 7.7 1/1 +21666 2.1.283 7.3 27 +70942 Superset Helper 7.2 19 +70934 Superset 5.9 51 +70969 Superset 5.2 21 diff --git a/dev/research/metal_pathfinding/optimization/results/aba/load-base-a2.txt b/dev/research/metal_pathfinding/optimization/results/aba/load-base-a2.txt new file mode 100644 index 0000000..d18990e --- /dev/null +++ b/dev/research/metal_pathfinding/optimization/results/aba/load-base-a2.txt @@ -0,0 +1,40 @@ +Processes: 1019 total, 2 running, 1017 sleeping, 5187 threads +2026/09/27 00:30:29 +Load Avg: 3.19, 3.55, 4.19 +CPU usage: 5.82% user, 8.66% sys, 85.51% idle +SharedLibs: 916M resident, 168M data, 136M linkedit. +MemRegions: 638542 total, 10G resident, 736M private, 4366M shared. +PhysMem: 34G used (3986M wired, 626M compressor), 1354M unused. +VM: 451T vsize, 6144M framework vsize, 2846220(0) swapins, 4729331(0) swapouts. +Networks: packets: 191149845/161G in, 146612635/163G out. +Disks: 97828398/2477G read, 117449998/2100G written. + +PID COMMAND %CPU #TH +99753 mscamerad-xpc 0.0 2 +99752 PlugInLibrarySer 0.0 2 +99750 QuickLookUIServi 0.0 3 +99749 com.apple.appkit 0.0 3 +99710 PlugInLibrarySer 0.0 2 +99709 Preview 0.0 4 +99428 crashpad_handler 0.0 4 +98995 crashpad_handler 0.0 4 +Processes: 1019 total, 4 running, 1015 sleeping, 5180 threads +2026/09/27 00:30:30 +Load Avg: 3.19, 3.55, 4.19 +CPU usage: 6.81% user, 6.18% sys, 86.99% idle +SharedLibs: 916M resident, 168M data, 136M linkedit. +MemRegions: 0 total, 0B resident, 736M private, 4366M shared. +PhysMem: 34G used (4002M wired, 626M compressor), 1357M unused. +VM: 451T vsize, 6144M framework vsize, 2846220(0) swapins, 4729331(0) swapouts. +Networks: packets: 191150177/161G in, 146613141/163G out. +Disks: 97828398/2477G read, 117450254/2100G written. + +PID COMMAND %CPU #TH +590 WindowServer 25.0 29/1 +70968 Superset Helper 21.6 32/1 +0 kernel_task 13.1 850/14 +1 launchd 11.9 3 +15622 top 8.2 1/1 +70942 Superset Helper 7.5 19 +81804 2.1.283 6.7 27 +70969 Superset 3.6 20 diff --git a/dev/research/metal_pathfinding/optimization/results/aba/load-cpu-a1.txt b/dev/research/metal_pathfinding/optimization/results/aba/load-cpu-a1.txt new file mode 100644 index 0000000..1c23bd6 --- /dev/null +++ b/dev/research/metal_pathfinding/optimization/results/aba/load-cpu-a1.txt @@ -0,0 +1,40 @@ +Processes: 1032 total, 3 running, 1029 sleeping, 5281 threads +2026/09/27 00:29:09 +Load Avg: 3.51, 3.67, 4.30 +CPU usage: 10.0% user, 9.68% sys, 80.31% idle +SharedLibs: 916M resident, 168M data, 136M linkedit. +MemRegions: 639248 total, 10G resident, 749M private, 4360M shared. +PhysMem: 34G used (3986M wired, 626M compressor), 1219M unused. +VM: 456T vsize, 6144M framework vsize, 2846220(0) swapins, 4729331(0) swapouts. +Networks: packets: 191122601/161G in, 146582691/163G out. +Disks: 97827926/2477G read, 117446010/2100G written. + +PID COMMAND %CPU #TH +99753 mscamerad-xpc 0.0 2 +99752 PlugInLibrarySer 0.0 2 +99750 QuickLookUIServi 0.0 3 +99749 com.apple.appkit 0.0 3 +99710 PlugInLibrarySer 0.0 2 +99709 Preview 0.0 4 +99553 mdworker_shared 0.0 4 +99428 crashpad_handler 0.0 4 +Processes: 1032 total, 4 running, 1028 sleeping, 5264 threads +2026/09/27 00:29:10 +Load Avg: 3.51, 3.67, 4.30 +CPU usage: 11.73% user, 5.4% sys, 83.21% idle +SharedLibs: 916M resident, 168M data, 136M linkedit. +MemRegions: 0 total, 0B resident, 749M private, 4360M shared. +PhysMem: 34G used (3988M wired, 626M compressor), 1243M unused. +VM: 456T vsize, 6144M framework vsize, 2846220(0) swapins, 4729331(0) swapouts. +Networks: packets: 191123079/161G in, 146583230/163G out. +Disks: 97827926/2477G read, 117446016/2100G written. + +PID COMMAND %CPU #TH +590 WindowServer 20.6 28/1 +70968 Superset Helper 17.5 32 +0 kernel_task 12.2 850/14 +70942 Superset Helper 6.4 19 +6126 top 6.1 1/1 +21666 2.1.283 4.7 27 +70969 Superset 2.5 20 +70934 Superset 2.1 50 diff --git a/dev/research/metal_pathfinding/optimization/results/aba/load-cpu-a2.txt b/dev/research/metal_pathfinding/optimization/results/aba/load-cpu-a2.txt new file mode 100644 index 0000000..f527810 --- /dev/null +++ b/dev/research/metal_pathfinding/optimization/results/aba/load-cpu-a2.txt @@ -0,0 +1,40 @@ +Processes: 1023 total, 6 running, 1017 sleeping, 5244 threads +2026/09/27 00:30:44 +Load Avg: 3.82, 3.67, 4.23 +CPU usage: 13.90% user, 12.81% sys, 73.28% idle +SharedLibs: 916M resident, 168M data, 136M linkedit. +MemRegions: 638887 total, 10G resident, 740M private, 4419M shared. +PhysMem: 34G used (3984M wired, 626M compressor), 992M unused. +VM: 452T vsize, 6144M framework vsize, 2846220(0) swapins, 4729331(0) swapouts. +Networks: packets: 191155920/161G in, 146620711/163G out. +Disks: 97828530/2477G read, 117450792/2100G written. + +PID COMMAND %CPU #TH +99753 mscamerad-xpc 0.0 2 +99752 PlugInLibrarySer 0.0 2 +99750 QuickLookUIServi 0.0 3 +99749 com.apple.appkit 0.0 3 +99710 PlugInLibrarySer 0.0 2 +99709 Preview 0.0 4 +99428 crashpad_handler 0.0 4 +98995 crashpad_handler 0.0 4 +Processes: 1029 total, 5 running, 1 stuck, 1023 sleeping, 5261 threads +2026/09/27 00:30:45 +Load Avg: 3.82, 3.67, 4.23 +CPU usage: 16.69% user, 5.86% sys, 77.44% idle +SharedLibs: 916M resident, 168M data, 136M linkedit. +MemRegions: 282 total, 10M resident, 740M private, 4464M shared. +PhysMem: 34G used (3976M wired, 626M compressor), 1037M unused. +VM: 455T vsize, 6144M framework vsize, 2846220(0) swapins, 4729331(0) swapouts. +Networks: packets: 191156199/161G in, 146620961/163G out. +Disks: 97828530/2477G read, 117450800/2100G written. + +PID COMMAND %CPU #TH +16594 Google Chrome He 55.7 25/1 +1225 mediaanalysisd 36.4 18/2 +590 WindowServer 27.7 29 +70968 Superset Helper 25.0 32/1 +95916 Google Chrome 17.5 46 +0 kernel_task 15.2 850/14 +731 sysmond 10.4 3 +70942 Superset Helper 9.3 19 diff --git a/dev/research/metal_pathfinding/optimization/results/aba/load-optimized-b.txt b/dev/research/metal_pathfinding/optimization/results/aba/load-optimized-b.txt new file mode 100644 index 0000000..744da4d --- /dev/null +++ b/dev/research/metal_pathfinding/optimization/results/aba/load-optimized-b.txt @@ -0,0 +1,40 @@ +Processes: 1023 total, 3 running, 1020 sleeping, 5207 threads +2026/09/27 00:29:35 +Load Avg: 3.30, 3.60, 4.25 +CPU usage: 6.44% user, 8.69% sys, 84.86% idle +SharedLibs: 916M resident, 168M data, 136M linkedit. +MemRegions: 625656 total, 10G resident, 740M private, 4353M shared. +PhysMem: 34G used (3975M wired, 626M compressor), 1426M unused. +VM: 451T vsize, 6144M framework vsize, 2846220(0) swapins, 4729331(0) swapouts. +Networks: packets: 191131577/161G in, 146592177/163G out. +Disks: 97828052/2477G read, 117447547/2100G written. + +PID COMMAND %CPU #TH +99753 mscamerad-xpc 0.0 2 +99752 PlugInLibrarySer 0.0 2 +99750 QuickLookUIServi 0.0 3 +99749 com.apple.appkit 0.0 3 +99710 PlugInLibrarySer 0.0 2 +99709 Preview 0.0 4 +99428 crashpad_handler 0.0 4 +98995 crashpad_handler 0.0 4 +Processes: 1024 total, 4 running, 1020 sleeping, 5206 threads +2026/09/27 00:29:37 +Load Avg: 3.30, 3.60, 4.25 +CPU usage: 7.77% user, 5.29% sys, 86.92% idle +SharedLibs: 916M resident, 168M data, 136M linkedit. +MemRegions: 33 total, 80K resident, 740M private, 4354M shared. +PhysMem: 34G used (3977M wired, 626M compressor), 1411M unused. +VM: 451T vsize, 6144M framework vsize, 2846220(0) swapins, 4729331(0) swapouts. +Networks: packets: 191131879/161G in, 146592477/163G out. +Disks: 97828056/2477G read, 117447556/2100G written. + +PID COMMAND %CPU #TH +590 WindowServer 24.9 28 +70968 Superset Helper 16.7 32 +0 kernel_task 12.6 850/14 +81804 2.1.283 10.9 27 +9966 top 6.7 1/1 +70942 Superset Helper 6.5 19 +39757 codex 4.9 31 +70969 Superset 2.8 20 diff --git a/dev/research/metal_pathfinding/optimization/results/aba/optimized-b-stderr.txt b/dev/research/metal_pathfinding/optimization/results/aba/optimized-b-stderr.txt new file mode 100644 index 0000000..fed94be --- /dev/null +++ b/dev/research/metal_pathfinding/optimization/results/aba/optimized-b-stderr.txt @@ -0,0 +1 @@ +device=Apple M4 Max setup_ms=23.3475 execution_width=32 diff --git a/dev/research/metal_pathfinding/optimization/results/aba/optimized-b.csv b/dev/research/metal_pathfinding/optimization/results/aba/optimized-b.csv new file mode 100644 index 0000000..ceb3e3f --- /dev/null +++ b/dev/research/metal_pathfinding/optimization/results/aba/optimized-b.csv @@ -0,0 +1,217 @@ +case,n,e,queries,method,wall_ms,distance_ms,gpu_ms,edge_visits,rounds,waits,fallback64,upload_ms,samples,correct,wall_samples_ms +random,1024,8192,1,old_pull_parallel_dag,1.422708,1.375584,0.424208,131072,16,2,0,0.152791,7,pass,1.540625;1.013375;1.422708;0.980167;1.441208;1.027458;1.449958 +random,1024,8192,1,old_group_parallel_dag,0.833500,0.818833,0.679958,106496,13,1,0,0.152791,7,pass,0.833500;0.817917;1.119042;0.831833;0.925708;0.827042;0.877000 +random,1024,8192,1,pull64_barrier,0.659084,0.646375,0.390667,131072,16,2,0,0.152791,7,pass,0.644416;0.664875;0.659084;0.643459;0.654750;0.659750;0.671792 +random,1024,8192,1,pull64_interleaved,0.655584,0.643000,0.375208,131072,16,2,0,0.152791,7,pass,0.660167;0.652250;0.655584;0.672125;0.650375;0.629083;0.677083 +random,1024,8192,1,pull32_interleaved,0.599333,0.586041,0.337667,131072,16,2,0,0.152791,7,pass,0.667083;0.607875;0.599333;0.571542;0.736667;0.583833;0.566542 +random,1024,8192,1,pull32_gpu_dag,0.960083,0.603666,0.406125,131072,16,4,0,0.152791,7,pass,1.014709;0.960083;0.982375;0.981250;0.949417;0.928375;0.958334 +random,1024,8192,1,frontier32_vertex,0.923583,0.909625,0.634334,21088,16,2,0,0.152791,7,pass,0.906208;0.964958;0.872292;0.874250;1.228792;0.930208;0.923583 +random,1024,8192,1,frontier32_simd,0.661125,0.647209,0.380375,20272,16,2,0,0.152791,7,pass,0.647583;0.661125;0.686791;0.653458;0.636375;0.679750;0.674833 +random,1024,8192,1,frontier32_gpu_dag,1.002750,0.652084,0.452250,20384,16,4,0,0.152791,7,pass,0.988750;0.968709;0.979666;1.002750;1.115041;1.082875;1.185666 +random,1024,8192,1,bucket32_d4,1.895167,1.880583,1.276084,8232,32,4,0,0.152791,7,pass,2.037416;2.476041;1.853333;1.785791;1.902334;1.888917;1.895167 +random,1024,8192,1,bucket32_d16,1.421542,1.407000,0.920208,9336,24,3,0,0.152791,7,pass,1.421542;1.436167;1.369375;1.347459;1.377084;1.460625;1.463417 +random,1024,8192,1,bucket32_d64,0.953750,0.939042,0.653708,19264,16,2,0,0.152791,7,pass,0.950916;0.940167;0.953750;0.954375;0.977375;1.016334;0.913959 +random,1024,8192,64,old_pull_parallel_dag,1.972792,1.703000,1.236416,12582912,24,3,0,0.238875,7,pass,2.379583;2.263125;1.972792;1.649750;1.554584;1.804167;2.017709 +random,1024,8192,64,old_group_parallel_dag,0.852750,0.566166,0.379500,7217152,17,1,0,0.238875,7,pass,0.972542;0.909042;0.773791;0.876500;0.773208;0.852750;0.821167 +random,1024,8192,64,pull64_barrier,1.223458,0.948625,0.470458,12582912,24,3,0,0.238875,7,pass,1.215166;1.266916;1.459875;1.254708;1.100250;1.223458;1.058542 +random,1024,8192,64,pull64_interleaved,0.940417,0.670542,0.268333,12582912,24,3,0,0.238875,7,pass,1.098459;0.940417;1.008292;1.048209;0.935416;0.862625;0.937292 +random,1024,8192,64,pull32_interleaved,0.863416,0.594792,0.197417,12582912,24,3,0,0.238875,7,pass,0.897167;0.847458;0.843917;0.856791;0.925958;0.885125;0.863416 +random,1024,8192,64,pull32_gpu_dag,0.998000,0.578542,0.199083,12582912,24,5,0,0.238875,7,pass,1.014750;0.831500;0.914292;1.005500;0.940167;0.998000;1.025125 +random,1024,8192,64,frontier32_vertex,0.869625,0.628834,0.239458,1289824,16,2,0,0.238875,7,pass,0.929916;1.029083;0.811167;0.964459;0.869625;0.779625;0.783875 +random,1024,8192,64,frontier32_simd,1.028500,0.795709,0.456417,1202328,16,2,0,0.238875,7,pass,1.156250;1.092875;1.028500;0.996917;0.985625;1.019916;1.121709 +random,1024,8192,64,frontier32_gpu_dag,1.197083,0.889625,0.508875,1201208,16,4,0,0.238875,7,pass,1.042417;1.254542;1.182167;1.197083;1.099917;1.569084;2.684750 +random,1024,8192,64,bucket32_d4,5.929458,5.638042,4.210875,528528,56,7,0,0.238875,7,pass,6.084667;5.929458;5.901834;6.615042;5.929458;2.489625;2.791458 +random,1024,8192,64,bucket32_d16,1.623792,1.347083,0.712083,601456,32,4,0,0.238875,7,pass,1.662291;1.614416;1.657709;1.623792;1.578500;1.475583;1.650417 +random,1024,8192,64,bucket32_d64,1.402750,1.126334,0.671125,1154720,24,3,0,0.238875,7,pass,1.349709;1.441667;1.314791;1.402750;1.365125;1.570500;1.408750 +clos,200,20000,64,old_pull_parallel_dag,2.136750,1.514125,1.015667,10240000,8,1,0,0.322125,7,pass,2.048625;2.183375;2.117792;1.920167;2.160875;2.136750;2.711125 +clos,200,20000,64,old_group_parallel_dag,1.460750,0.833416,0.303250,3840000,3,1,0,0.322125,7,pass,1.479875;1.528583;1.339875;1.338875;1.467208;1.426625;1.460750 +clos,200,20000,64,pull64_barrier,2.071916,1.523875,1.000375,10240000,8,1,0,0.322125,7,pass,2.033375;2.132917;2.115500;2.105750;1.921250;1.814041;2.071916 +clos,200,20000,64,pull64_interleaved,1.903375,1.332458,0.757208,10240000,8,1,0,0.322125,7,pass,1.586917;1.955417;1.903375;2.048458;1.910875;1.876500;1.902250 +clos,200,20000,64,pull32_interleaved,1.893500,1.311208,0.687708,10240000,8,1,0,0.322125,7,pass,1.853250;1.915167;1.809917;1.898334;1.949167;1.893500;1.792167 +clos,200,20000,64,pull32_gpu_dag,2.091666,1.226209,1.012708,10240000,8,3,0,0.322125,7,pass,2.159458;2.626458;1.675041;2.091666;1.743709;2.184375;2.028334 +clos,200,20000,64,frontier32_vertex,2.381875,1.556917,0.961125,1280000,8,1,0,0.322125,7,pass,2.020291;2.766500;2.041667;2.792125;2.084459;2.381875;2.471625 +clos,200,20000,64,frontier32_simd,1.552459,0.924500,0.317875,1280000,8,1,0,0.322125,7,pass,1.552459;1.569875;1.528791;1.653375;1.387708;1.480917;1.568750 +clos,200,20000,64,frontier32_gpu_dag,1.979166,0.982458,0.836500,1280000,8,3,0,0.322125,7,pass,2.080875;1.972042;1.933208;2.108042;1.548334;1.979166;2.014125 +clos,200,20000,64,bucket32_d4,1.572375,1.024583,0.480750,1280000,8,1,0,0.322125,7,pass,2.073625;1.344417;1.663959;1.754875;1.275500;1.452917;1.572375 +clos,200,20000,64,bucket32_d16,1.739292,1.165625,0.491667,1280000,8,1,0,0.322125,7,pass,1.775000;1.796583;1.739292;1.315750;1.685625;1.748541;1.637916 +clos,200,20000,64,bucket32_d64,1.692708,1.072250,0.489542,1280000,8,1,0,0.322125,7,pass,1.629041;1.683584;1.586167;1.839709;1.716250;1.692708;1.699208 +grid,1024,3968,1,old_pull_parallel_dag,1.747333,1.738833,0.651333,253952,64,8,0,0.124084,7,pass,1.754625;1.747333;1.919625;1.635333;1.795750;1.629333;1.627542 +grid,1024,3968,1,old_group_parallel_dag,0.365667,0.358792,0.227375,249984,63,1,0,0.124084,7,pass,1.116750;0.360041;0.365667;0.352625;0.396042;0.372000;0.363209 +grid,1024,3968,1,pull64_barrier,1.119292,1.111458,0.177083,253952,64,8,0,0.124084,7,pass,1.136458;1.122167;1.175458;1.103917;1.119292;1.113042;1.103334 +grid,1024,3968,1,pull64_interleaved,1.144083,1.136125,0.176751,253952,64,8,0,0.124084,7,pass,1.134375;1.313625;1.215166;1.160208;1.096416;1.144083;1.113833 +grid,1024,3968,1,pull32_interleaved,1.088542,1.080667,0.163666,253952,64,8,0,0.124084,7,pass,1.101875;1.104166;1.088542;1.119625;1.051041;0.916541;1.050417 +grid,1024,3968,1,pull32_gpu_dag,1.270833,0.918458,0.173167,253952,64,10,0,0.124084,7,pass,1.277166;1.248125;1.308083;1.206458;1.379875;1.122791;1.270833 +grid,1024,3968,1,frontier32_vertex,1.312625,1.304791,0.528083,3968,64,8,0,0.124084,7,pass,1.312625;1.423958;1.307792;1.312292;1.321584;1.309625;1.349500 +grid,1024,3968,1,frontier32_simd,1.179667,1.171750,0.396291,3968,64,8,0,0.124084,7,pass,1.224375;1.179125;1.179667;1.174000;1.176875;1.186250;1.278792 +grid,1024,3968,1,frontier32_gpu_dag,1.394125,1.178458,0.407416,3968,64,10,0,0.124084,7,pass,1.432250;1.562334;1.460583;1.370833;1.394125;1.385333;1.378958 +grid,1024,3968,1,bucket32_d4,1.450166,1.441333,0.637042,3968,64,8,0,0.124084,7,pass,1.622291;1.445083;1.459416;1.450166;1.399667;1.537458;1.438791 +grid,1024,3968,1,bucket32_d16,1.451125,1.443250,0.635917,3968,64,8,0,0.124084,7,pass,1.444458;1.551500;1.423000;1.435167;1.451125;1.456500;1.464833 +grid,1024,3968,1,bucket32_d64,1.466458,1.458667,0.637167,3968,64,8,0,0.124084,7,pass,1.429375;1.439417;1.466458;1.588042;1.638959;1.476583;1.456791 +hub,1024,3070,1,old_pull_parallel_dag,6.046292,6.030084,5.544375,98240,32,4,0,0.098834,7,pass,5.969208;6.158125;6.087291;6.000167;6.046292;6.013417;6.048458 +hub,1024,3070,1,old_group_parallel_dag,4.888250,4.865667,4.721042,95170,31,1,0,0.098834,7,pass,4.863875;4.938958;4.863792;4.881375;4.888250;5.117750;4.995041 +hub,1024,3070,1,pull64_barrier,5.015916,4.988250,4.313333,98240,32,4,0,0.098834,7,pass,4.957625;5.000166;5.193458;5.034583;5.015916;5.078375;4.889250 +hub,1024,3070,1,pull64_interleaved,4.985584,4.962042,4.320833,98240,32,4,0,0.098834,7,pass,4.985584;5.048916;5.110875;4.910750;4.974542;5.079959;4.959667 +hub,1024,3070,1,pull32_interleaved,4.396791,4.373584,3.683708,98240,32,4,0,0.098834,7,pass,4.324084;4.431084;4.344417;4.461542;4.414375;4.396791;4.393666 +hub,1024,3070,1,pull32_gpu_dag,5.115583,4.357708,4.101125,98240,32,6,0,0.098834,7,pass,5.115583;5.122334;5.007417;5.289875;5.065416;5.077334;5.281125 +hub,1024,3070,1,frontier32_vertex,1.436166,1.428458,0.852042,3128,32,4,0,0.098834,7,pass,1.510208;1.436166;1.386458;1.511958;1.404167;1.438709;1.412875 +hub,1024,3070,1,frontier32_simd,0.784458,0.776500,0.233250,3128,32,4,0,0.098834,7,pass,0.761209;0.730042;0.781167;0.861667;0.786834;0.795166;0.784458 +hub,1024,3070,1,frontier32_gpu_dag,1.467375,0.769666,0.649500,3128,32,6,0,0.098834,7,pass,1.490583;1.610666;1.444583;1.509500;1.438708;1.450458;1.467375 +hub,1024,3070,1,bucket32_d4,0.869375,0.860292,0.344792,3100,32,4,0,0.098834,7,pass,0.868792;0.897709;0.906917;0.852833;0.880541;0.804416;0.869375 +hub,1024,3070,1,bucket32_d16,0.851250,0.843000,0.337292,3124,32,4,0,0.098834,7,pass,0.851250;0.846875;0.847417;0.932916;0.857625;0.875333;0.850125 +hub,1024,3070,1,bucket32_d64,0.885584,0.877625,0.326958,3128,32,4,0,0.098834,7,pass,0.848208;0.818834;0.853667;0.956041;0.885584;0.912042;0.911250 +random_masked_int64_reverse,1024,8192,8,old_pull_parallel_dag,0.231584,0.167417,0.031625,524288,8,1,0,0.225500,7,pass,0.232959;0.231584;0.263750;0.244833;0.228166;0.217625;0.224417 +random_masked_int64_reverse,1024,8192,8,old_group_parallel_dag,0.252833,0.194208,0.053500,368640,8,1,0,0.225500,7,pass,0.235500;0.300042;0.265000;0.252833;0.253417;0.241000;0.235292 +random_masked_int64_reverse,1024,8192,8,pull64_barrier,0.248458,0.190334,0.028750,524288,8,1,0,0.225500,7,pass,0.232375;0.263291;0.248458;0.237625;0.234167;0.248958;0.254792 +random_masked_int64_reverse,1024,8192,8,pull64_interleaved,0.263750,0.196708,0.029083,524288,8,1,0,0.225500,7,pass,0.231750;0.251083;0.263750;0.314917;0.275708;0.277375;0.250750 +random_masked_int64_reverse,1024,8192,8,pull32_interleaved,0.252166,0.197709,0.028833,524288,8,1,1,0.225500,7,pass,0.246500;0.296791;0.377917;0.252166;0.253166;0.239334;0.234209 +random_masked_int64_reverse,1024,8192,8,pull32_gpu_dag,0.499334,0.173875,0.048708,524288,8,3,1,0.225500,7,pass,0.453000;0.509250;0.474667;0.491292;0.499334;0.505583;0.586458 +random_masked_int64_reverse,1024,8192,8,frontier32_vertex,0.238375,0.188375,0.029167,524288,8,1,1,0.225500,7,pass,0.267584;0.267791;0.238375;0.232083;0.255083;0.227250;0.222083 +random_masked_int64_reverse,1024,8192,8,frontier32_simd,0.255750,0.192125,0.028667,524288,8,1,1,0.225500,7,pass,0.203333;0.266166;0.315666;0.257458;0.255750;0.237375;0.245750 +random_masked_int64_reverse,1024,8192,8,frontier32_gpu_dag,0.504333,0.184083,0.047458,524288,8,3,1,0.225500,7,pass,0.528250;0.504458;0.574709;0.504333;0.476834;0.476833;0.454791 +random_masked_int64_reverse,1024,8192,8,bucket32_d4,0.243083,0.197583,0.028750,524288,8,1,1,0.225500,7,pass,0.269416;0.260916;0.267750;0.237458;0.235791;0.241416;0.243083 +random_masked_int64_reverse,1024,8192,8,bucket32_d16,0.223542,0.178000,0.028875,524288,8,1,1,0.225500,7,pass,0.222750;0.232791;0.237375;0.258250;0.223542;0.215333;0.210875 +random_masked_int64_reverse,1024,8192,8,bucket32_d64,0.260750,0.198542,0.028917,524288,8,1,1,0.225500,7,pass,0.229833;0.261834;0.302792;0.260917;0.247000;0.260750;0.247750 +random,4096,32768,256,old_pull_parallel_dag,14.954834,11.144167,9.933083,201326592,24,3,0,0.530167,7,pass,15.227708;14.739917;14.645041;14.434167;15.033875;14.956792;14.954834 +random,4096,32768,256,old_group_parallel_dag,11.269917,7.608250,6.915000,136544256,20,1,0,0.530167,7,pass,11.252208;11.493083;11.614375;11.162459;11.269917;11.043583;11.470666 +random,4096,32768,256,pull64_barrier,13.565209,9.762416,8.500917,201326592,24,3,0,0.530167,7,pass,13.685167;13.552875;13.587709;13.426042;13.565209;12.961916;13.579000 +random,4096,32768,256,pull64_interleaved,7.002542,3.340208,2.080917,201326592,24,3,0,0.530167,7,pass,6.459833;7.002542;6.970958;6.819791;8.010875;7.685500;7.589250 +random,4096,32768,256,pull32_interleaved,9.000125,5.200041,3.525458,201326592,24,3,0,0.530167,7,pass,9.000125;11.030083;8.075542;6.810625;11.745583;6.810833;11.157541 +random,4096,32768,256,pull32_gpu_dag,8.790333,6.949833,7.133875,201326592,24,5,0,0.530167,7,pass,9.671167;3.518834;8.790333;9.206042;3.936125;3.961042;9.220208 +random,4096,32768,256,frontier32_vertex,7.936292,4.093958,2.380125,19766184,24,3,0,0.530167,7,pass,14.160834;7.095291;7.936292;14.078500;6.887042;6.492417;8.011875 +random,4096,32768,256,frontier32_simd,11.324125,7.658917,6.414084,20599968,24,3,0,0.530167,7,pass,11.324125;11.230792;12.628625;10.989958;12.690250;10.503958;11.417833 +random,4096,32768,256,frontier32_gpu_dag,9.247000,7.874000,7.025417,20610776,24,5,0,0.530167,7,pass,9.247000;8.839625;10.159084;8.513125;9.098458;9.902667;12.254458 +random,4096,32768,256,bucket32_d4,16.328042,12.613875,10.131208,8454072,72,9,0,0.530167,7,pass,15.820875;15.743208;17.331208;17.372667;17.149292;16.328042;15.803333 +random,4096,32768,256,bucket32_d16,13.121000,9.300750,7.673208,9728592,48,6,0,0.530167,7,pass,12.592459;12.880667;13.311583;13.121000;12.540334;13.268125;13.189209 +random,4096,32768,256,bucket32_d64,14.196416,9.622542,8.263583,18345256,24,3,0,0.530167,7,pass,13.307666;13.243458;14.604250;14.721292;16.965625;14.196416;11.675209 +random,16384,131072,1,old_pull_parallel_dag,0.963792,0.658875,0.243542,3145728,24,3,0,1.641291,7,pass,1.004958;0.949750;0.963792;0.924292;1.072083;0.879500;0.969417 +random,16384,131072,1,old_group_parallel_dag,5.289583,4.968000,4.819125,2359296,18,1,0,1.641291,7,pass,5.441666;5.132583;5.298584;5.189291;5.167667;5.335500;5.289583 +random,16384,131072,1,pull64_barrier,0.760792,0.570916,0.163584,3145728,24,3,0,1.641291,7,pass,0.754833;0.774750;0.854375;0.782167;0.760792;0.759375;0.723417 +random,16384,131072,1,pull64_interleaved,0.828250,0.564041,0.163917,3145728,24,3,0,1.641291,7,pass,0.838583;0.961166;0.811000;0.853208;0.817333;0.828250;0.752583 +random,16384,131072,1,pull32_interleaved,0.705083,0.520875,0.136959,3145728,24,3,0,1.641291,7,pass,0.692583;0.711333;0.700666;0.706750;0.705083;0.703000;0.878958 +random,16384,131072,1,pull32_gpu_dag,0.880167,0.512875,0.158000,3145728,24,5,0,1.641291,7,pass,0.880167;0.828750;0.869708;0.906792;0.831750;0.944541;0.894834 +random,16384,131072,1,frontier32_vertex,0.831833,0.618959,0.258125,377056,24,3,0,1.641291,7,pass,0.849750;0.831833;0.841916;0.827792;0.873667;0.821125;0.814084 +random,16384,131072,1,frontier32_simd,0.806417,0.593083,0.237208,335680,24,3,0,1.641291,7,pass,0.824166;0.806417;0.694583;0.641750;0.808667;0.799250;0.844083 +random,16384,131072,1,frontier32_gpu_dag,0.982833,0.612417,0.268708,334824,24,5,0,1.641291,7,pass,0.991500;0.973042;1.006625;0.951167;0.982833;1.121125;0.797541 +random,16384,131072,1,bucket32_d4,1.832833,1.546042,0.654208,132016,56,7,0,1.641291,7,pass,1.779834;1.940750;1.879708;1.832833;1.795166;1.849667;1.734208 +random,16384,131072,1,bucket32_d16,1.148208,0.916666,0.397583,148256,32,4,0,1.641291,7,pass,1.118791;1.148208;1.278792;1.143833;1.283750;1.248500;1.113291 +random,16384,131072,1,bucket32_d64,0.936833,0.711500,0.339500,268728,24,3,0,1.641291,7,pass,0.928500;0.936833;0.949541;0.932791;0.940250;0.933167;0.946042 +random,16384,131072,64,old_pull_parallel_dag,16.913292,12.650625,11.412458,201326592,24,3,0,1.869208,7,pass,17.212875;16.913292;17.536708;16.731500;16.199708;16.913375;16.278333 +random,16384,131072,64,old_group_parallel_dag,13.239041,9.052417,8.276375,158203904,22,1,0,1.869208,7,pass,13.094375;13.914166;13.783125;13.407916;13.111125;13.058417;13.239041 +random,16384,131072,64,pull64_barrier,15.959375,11.386000,10.305167,201326592,24,3,0,1.869208,7,pass,15.514584;16.078958;15.892875;15.768500;16.169292;16.315750;15.959375 +random,16384,131072,64,pull64_interleaved,7.473334,3.322042,1.949625,201326592,24,3,0,1.869208,7,pass,7.977375;7.469666;7.993750;7.469959;7.340416;8.069541;7.473334 +random,16384,131072,64,pull32_interleaved,8.709917,3.948375,2.593083,201326592,24,3,0,1.869208,7,pass,7.568334;8.709917;9.042834;8.360834;9.779833;11.890542;7.645000 +random,16384,131072,64,pull32_gpu_dag,8.809875,7.334042,7.226667,201326592,24,5,0,1.869208,7,pass,8.327042;8.982250;9.166375;8.212792;9.129458;8.809875;8.644916 +random,16384,131072,64,frontier32_vertex,10.143542,5.759583,3.640500,21296680,24,3,0,1.869208,7,pass,10.647167;8.829458;10.953250;8.470875;8.924250;11.585834;10.143542 +random,16384,131072,64,frontier32_simd,12.189208,7.940750,6.799000,22006672,24,3,0,1.869208,7,pass,12.189208;17.371042;12.150166;11.824625;17.040958;12.901583;11.954250 +random,16384,131072,64,frontier32_gpu_dag,9.202917,7.809334,7.471417,21985376,24,5,0,1.869208,7,pass,9.202917;9.145375;9.333000;9.321417;8.679416;9.192583;9.217625 +random,16384,131072,64,bucket32_d4,16.825209,12.606541,10.280166,8451400,72,9,0,1.869208,7,pass,15.831792;16.931500;16.825209;16.989583;16.937500;16.726666;16.530875 +random,16384,131072,64,bucket32_d16,13.809292,9.686834,7.926208,9572312,48,6,0,1.869208,7,pass,14.031791;13.417000;13.809292;13.634833;13.956208;12.643542;14.687833 +random,16384,131072,64,bucket32_d64,12.602167,8.439250,7.400083,17413440,24,3,0,1.869208,7,pass,12.249792;12.602167;12.763000;11.981750;12.445291;13.342709;13.471250 +random,65536,524288,1,old_pull_parallel_dag,3.545291,2.038125,1.060917,12582912,24,3,0,7.557667,7,pass,4.174416;3.781042;3.698125;3.545291;3.297792;3.206292;3.322458 +random,65536,524288,1,old_group_parallel_dag,30.358375,28.977917,28.313750,11534336,22,1,0,7.557667,7,pass,30.101000;30.358375;30.286417;30.429125;30.627750;30.470958;30.242042 +random,65536,524288,1,pull64_barrier,3.163417,1.729375,0.758083,12582912,24,3,0,7.557667,7,pass,3.113500;2.616291;3.163417;3.279250;3.173625;3.383583;3.162375 +random,65536,524288,1,pull64_interleaved,3.048417,1.518750,0.702958,12582912,24,3,0,7.557667,7,pass,3.038333;2.940000;3.048417;3.174250;3.017125;3.103000;3.113208 +random,65536,524288,1,pull32_interleaved,2.913209,1.337792,0.501667,12582912,24,3,0,7.557667,7,pass,2.913209;2.430541;3.057667;2.519625;2.842875;2.994208;2.928625 +random,65536,524288,1,pull32_gpu_dag,1.373417,0.881667,0.570875,12582912,24,5,0,7.557667,7,pass,1.391584;1.373417;1.479292;1.291209;1.337833;1.320958;1.406750 +random,65536,524288,1,frontier32_vertex,2.737250,1.259292,0.435458,1734632,24,3,0,7.557667,7,pass,2.715333;2.737250;2.858583;2.871083;2.568667;2.928166;2.330750 +random,65536,524288,1,frontier32_simd,3.045416,1.576083,0.639792,1561768,24,3,0,7.557667,7,pass,3.041292;3.007917;3.045416;3.056084;2.611792;3.060625;3.113833 +random,65536,524288,1,frontier32_gpu_dag,1.461000,1.045334,0.686000,1558160,24,5,0,7.557667,7,pass,1.657208;1.494750;1.429000;1.461000;1.452083;1.487333;1.387208 +random,65536,524288,1,bucket32_d4,4.357292,2.761166,1.174042,528256,64,8,0,7.557667,7,pass,4.461625;4.147542;4.444375;3.817792;4.357292;3.730458;4.480750 +random,65536,524288,1,bucket32_d16,3.480542,2.046791,0.835833,599256,40,5,0,7.557667,7,pass,3.480542;3.618791;3.528458;3.040125;3.475000;2.936333;3.646042 +random,65536,524288,1,bucket32_d64,3.186959,1.681334,0.676709,1050376,24,3,0,7.557667,7,pass,2.972375;3.186959;3.069917;3.187000;3.276667;3.274542;3.125584 +clos,800,320000,1,old_pull_parallel_dag,2.141750,1.366208,0.743750,2560000,8,1,0,3.583584,7,pass,2.117375;2.169292;2.141750;2.208292;2.099459;2.102417;2.219875 +clos,800,320000,1,old_group_parallel_dag,2.325833,1.576542,0.904750,960000,3,1,0,3.583584,7,pass,1.803667;2.325833;2.423834;2.367833;2.283458;2.311875;2.412417 +clos,800,320000,1,pull64_barrier,2.017334,1.252542,0.699375,2560000,8,1,0,3.583584,7,pass,1.540042;1.974542;1.998791;2.017334;2.145250;2.049167;2.183834 +clos,800,320000,1,pull64_interleaved,2.265000,1.493125,0.878292,2560000,8,1,0,3.583584,7,pass,2.248084;2.265000;2.266583;2.184625;2.588416;1.812125;2.474416 +clos,800,320000,1,pull32_interleaved,2.800709,1.979625,1.363375,2560000,8,1,0,3.583584,7,pass,2.800709;2.480667;2.804250;2.902708;2.653584;1.981000;3.096791 +clos,800,320000,1,pull32_gpu_dag,2.132833,1.256042,0.994000,2560000,8,3,0,3.583584,7,pass,2.004875;2.039500;2.228625;2.610667;1.446750;2.132833;2.185042 +clos,800,320000,1,frontier32_vertex,2.375500,1.574833,0.933250,320000,8,1,0,3.583584,7,pass,1.813500;2.375500;1.851291;5.269584;3.758292;2.390250;2.215708 +clos,800,320000,1,frontier32_simd,1.604458,0.852083,0.361417,320000,8,1,0,3.583584,7,pass,1.724958;1.809125;1.589542;1.604458;1.514125;1.668583;1.587916 +clos,800,320000,1,frontier32_gpu_dag,1.714416,0.823959,0.606042,320000,8,3,0,3.583584,7,pass,3.397708;1.759291;2.480875;1.558125;1.714416;1.648958;1.076958 +clos,800,320000,1,bucket32_d4,1.660042,0.872958,0.445875,320000,8,1,0,3.583584,7,pass,1.463167;1.412583;1.748375;1.660042;1.712083;1.768875;1.587750 +clos,800,320000,1,bucket32_d16,1.716125,0.904208,0.443542,320000,8,1,0,3.583584,7,pass,1.814125;1.647500;1.722334;1.690042;1.764750;1.716125;1.629792 +clos,800,320000,1,bucket32_d64,1.697542,0.939166,0.453417,320000,8,1,0,3.583584,7,pass,1.726542;1.697542;1.673041;1.558833;1.790583;1.782500;1.680916 +clos,800,320000,64,old_pull_parallel_dag,26.734584,19.417958,18.854209,163840000,8,1,0,3.568791,7,pass,30.062917;26.734584;27.709875;23.844042;26.751083;24.652083;23.241250 +clos,800,320000,64,old_group_parallel_dag,12.636667,5.914625,5.412125,61440000,3,1,0,3.568791,7,pass,13.336750;12.226458;12.215542;12.019334;12.982541;12.636667;13.245083 +clos,800,320000,64,pull64_barrier,24.737250,18.165041,17.724875,163840000,8,1,0,3.568791,7,pass,26.038667;23.627875;23.828875;24.737250;25.138416;20.098750;25.549208 +clos,800,320000,64,pull64_interleaved,13.270458,6.121834,5.404917,163840000,8,1,0,3.568791,7,pass,13.665208;12.286459;13.418500;13.055084;12.553250;13.305834;13.270458 +clos,800,320000,64,pull32_interleaved,10.982708,4.274208,3.646792,163840000,8,1,0,3.568791,7,pass,10.804708;10.794208;10.982708;11.027542;10.547750;11.347166;11.442166 +clos,800,320000,64,pull32_gpu_dag,8.185208,4.307834,6.163833,163840000,8,3,0,3.568791,7,pass,7.631709;7.941417;8.661667;8.185208;8.311625;8.223667;7.750583 +clos,800,320000,64,frontier32_vertex,14.231292,7.148416,6.877042,20480000,8,1,0,3.568791,7,pass,14.506375;12.344792;13.874083;13.901542;14.231292;14.353875;15.082167 +clos,800,320000,64,frontier32_simd,9.324334,2.064667,1.458000,20480000,8,1,0,3.568791,7,pass,8.174041;8.823334;9.906666;8.897125;9.324334;9.981375;9.356125 +clos,800,320000,64,frontier32_gpu_dag,15.943917,2.088583,14.063458,20480000,8,3,0,3.568791,7,pass,17.334916;15.073292;12.642375;15.943917;12.171250;16.266166;17.346541 +clos,800,320000,64,bucket32_d4,10.000292,2.528500,2.040125,20480000,8,1,0,3.568791,7,pass,10.000292;10.508458;9.561208;8.825292;10.400125;10.141750;9.762250 +clos,800,320000,64,bucket32_d16,9.609833,2.183166,1.863208,20480000,8,1,0,3.568791,7,pass,8.653417;9.125125;8.935750;10.713417;9.609833;9.966375;10.069792 +clos,800,320000,64,bucket32_d64,9.988250,2.683542,2.106250,20480000,8,1,0,3.568791,7,pass,9.028250;9.988250;10.240792;9.182333;10.137083;9.899833;10.287375 +grid,10000,39600,1,old_pull_parallel_dag,4.013208,3.946834,0.706459,7920000,200,25,0,0.518084,7,pass,5.984209;3.982416;4.445583;3.987667;4.117083;3.956167;4.013208 +grid,10000,39600,1,old_group_parallel_dag,8.014000,7.948000,7.803667,7880400,199,1,0,0.518084,7,pass,8.141042;7.945375;8.093000;7.954000;8.046667;7.961459;8.014000 +grid,10000,39600,1,pull64_barrier,4.119917,3.996000,0.681501,7920000,200,25,0,0.518084,7,pass,4.068708;4.193167;3.904375;4.360166;3.813917;4.625583;4.119917 +grid,10000,39600,1,pull64_interleaved,3.962917,3.893959,0.656292,7920000,200,25,0,0.518084,7,pass,4.197584;3.962917;3.456708;3.196333;3.866459;4.134333;4.008166 +grid,10000,39600,1,pull32_interleaved,3.378208,3.313666,0.604292,7920000,200,25,0,0.518084,7,pass,3.861917;4.153500;3.086834;3.378208;3.201917;3.100208;3.562041 +grid,10000,39600,1,pull32_gpu_dag,3.492000,3.086416,0.615749,7920000,200,27,0,0.518084,7,pass,3.126625;3.581209;3.413750;3.492000;3.813209;3.413333;3.648042 +grid,10000,39600,1,frontier32_vertex,4.642292,4.568084,1.859291,39600,200,25,0,0.518084,7,pass,4.756792;4.409125;4.959792;4.430125;4.642292;4.346791;4.889625 +grid,10000,39600,1,frontier32_simd,4.039750,3.931208,1.337458,39600,200,25,0,0.518084,7,pass,3.751375;4.175583;3.843833;4.311875;4.072000;3.882458;4.039750 +grid,10000,39600,1,frontier32_gpu_dag,4.282875,3.993000,1.301917,39600,200,27,0,0.518084,7,pass,4.187125;4.407917;4.301333;4.592167;4.274375;4.282875;4.212167 +grid,10000,39600,1,bucket32_d4,4.910500,4.826209,2.155791,39600,200,25,0,0.518084,7,pass,4.898375;4.900875;4.938208;5.008292;4.910500;4.821916;4.910875 +grid,10000,39600,1,bucket32_d16,5.335708,5.270375,2.374709,39600,200,25,0,0.518084,7,pass,4.793250;5.374833;5.328916;5.439166;5.335708;5.208875;5.532833 +grid,10000,39600,1,bucket32_d64,5.192667,5.129416,2.312959,39600,200,25,0,0.518084,7,pass,4.957750;4.982166;5.317625;5.049916;5.437000;5.192667;5.370000 +grid,10000,39600,8,old_pull_parallel_dag,4.347417,4.145458,1.435583,63360000,200,25,0,0.528251,7,pass,4.347417;4.338417;4.487333;4.302209;4.475167;4.519666;4.080167 +grid,10000,39600,8,old_group_parallel_dag,8.291541,8.082208,7.571833,51480000,199,1,0,0.528251,7,pass,8.734208;8.870542;8.262292;8.272625;8.418083;7.921541;8.291541 +grid,10000,39600,8,pull64_barrier,4.480208,4.280041,1.391291,63360000,200,25,0,0.528251,7,pass,4.360291;4.329084;4.569167;4.219833;5.201625;4.875458;4.480208 +grid,10000,39600,8,pull64_interleaved,4.328209,4.166959,1.330291,63360000,200,25,0,0.528251,7,pass,4.562583;4.513084;4.328209;4.082875;4.086834;4.255666;4.698334 +grid,10000,39600,8,pull32_interleaved,4.287208,4.032167,1.367917,63360000,200,25,0,0.528251,7,pass,4.667750;4.214625;4.673917;4.141542;4.287208;4.964583;4.134417 +grid,10000,39600,8,pull32_gpu_dag,4.435666,4.109125,1.561792,63360000,200,27,0,0.528251,7,pass,4.435666;4.378209;4.491958;4.687208;4.528041;4.315750;4.168042 +grid,10000,39600,8,frontier32_vertex,5.906291,5.656709,2.501667,316800,200,25,0,0.528251,7,pass,5.856292;5.906291;5.931083;5.554916;5.907916;5.993083;5.641541 +grid,10000,39600,8,frontier32_simd,4.525792,4.257083,1.460875,316800,200,25,0,0.528251,7,pass,4.868125;4.279667;4.525792;4.542292;4.091500;4.727041;4.396708 +grid,10000,39600,8,frontier32_gpu_dag,4.150250,3.853458,1.370458,316800,200,27,0,0.528251,7,pass,4.059542;4.118750;4.193708;4.150250;4.252083;4.145625;4.603208 +grid,10000,39600,8,bucket32_d4,7.675750,7.433167,3.707208,316800,200,25,0,0.528251,7,pass,7.743958;7.661667;7.675750;7.370209;7.665250;7.730167;8.130750 +grid,10000,39600,8,bucket32_d16,7.595750,7.402000,3.678000,316800,200,25,0,0.528251,7,pass,7.406666;7.361167;7.621917;7.785791;7.595750;7.516958;8.536167 +grid,10000,39600,8,bucket32_d64,7.603292,7.390542,3.720709,316800,200,25,0,0.528251,7,pass,8.424708;7.603292;7.761958;7.373375;7.541583;7.803750;7.529333 +chain,2048,2047,1,old_pull_parallel_dag,30.065000,30.057834,4.364000,4192256,2048,256,0,0.129708,7,pass,29.512792;30.366375;30.389250;30.065000;30.101458;29.244334;29.885125 +chain,2048,2047,1,old_group_parallel_dag,4.847291,4.824625,4.695541,4192256,2048,1,0,0.129708,7,pass,4.847291;4.859959;4.876125;4.871750;4.808833;4.800125;4.805458 +chain,2048,2047,1,pull64_barrier,28.538917,28.531792,4.712458,4192256,2048,256,0,0.129708,7,pass,30.322167;30.520625;28.461958;28.538917;29.325958;28.512125;28.277875 +chain,2048,2047,1,pull64_interleaved,32.552250,32.545292,6.166164,4192256,2048,256,0,0.129708,7,pass,31.818375;32.998209;35.086208;32.552250;32.620042;31.513041;31.235625 +chain,2048,2047,1,pull32_interleaved,33.313166,33.304166,7.667876,4192256,2048,256,0,0.129708,7,pass,33.313166;43.665625;39.094500;38.145541;32.806958;31.240000;30.591459 +chain,2048,2047,1,pull32_gpu_dag,30.618833,30.342208,4.890750,4192256,2048,258,0,0.129708,7,pass,30.596375;30.812083;30.605458;30.618833;30.346917;30.645541;30.759833 +chain,2048,2047,1,frontier32_vertex,37.678875,37.671167,12.262455,2047,2048,256,0,0.129708,7,pass,36.267542;36.667167;36.211541;37.678875;39.911292;40.296834;39.982541 +chain,2048,2047,1,frontier32_simd,41.049750,41.041042,15.763669,2047,2048,256,0,0.129708,7,pass,39.360750;39.254583;73.469250;74.576250;64.359834;41.049750;36.961291 +chain,2048,2047,1,frontier32_gpu_dag,40.147666,39.758041,13.087249,2047,2048,258,0,0.129708,7,pass,40.656333;40.270834;39.919000;39.728292;41.459084;39.793791;40.147666 +chain,2048,2047,1,bucket32_d4,49.000625,48.994042,21.207666,2047,2056,257,0,0.129708,7,pass,49.068292;48.685000;49.196583;48.832041;49.202708;49.000625;48.010625 +chain,2048,2047,1,bucket32_d16,48.754500,48.747084,21.148585,2047,2056,257,0,0.129708,7,pass,49.436750;48.830625;48.754500;49.006875;47.837792;48.425667;48.685791 +chain,2048,2047,1,bucket32_d64,48.401417,48.394833,21.022250,2047,2056,257,0,0.129708,7,pass,49.229041;48.401417;45.143750;46.486666;48.204875;49.047709;48.606625 +hub,4096,12286,64,old_pull_parallel_dag,32.651875,32.266000,30.924958,31452160,40,5,0,0.293750,7,pass,32.054959;32.157959;31.730416;32.897583;32.651875;32.842042;32.749083 +hub,4096,12286,64,old_group_parallel_dag,26.146583,25.760750,25.031750,27176632,38,1,0,0.293750,7,pass,26.043708;26.014500;26.409292;26.222333;26.138041;26.146583;26.241000 +hub,4096,12286,64,pull64_barrier,25.409625,25.028833,23.755584,31452160,40,5,0,0.293750,7,pass,25.125583;25.728459;25.886083;25.626667;25.204167;25.409625;25.196334 +hub,4096,12286,64,pull64_interleaved,33.829875,33.457333,31.908083,31452160,40,5,0,0.293750,7,pass,33.290584;34.397667;33.919000;34.763459;32.469500;33.829875;33.066583 +hub,4096,12286,64,pull32_interleaved,29.085375,28.621209,27.390333,31452160,40,5,0,0.293750,7,pass,28.808208;29.127459;28.627500;29.358417;29.398125;28.602458;29.085375 +hub,4096,12286,64,pull32_gpu_dag,31.331333,28.777667,29.382458,31452160,40,7,0,0.293750,7,pass,31.544208;31.235792;31.331333;31.250667;31.366500;31.655459;31.235541 +hub,4096,12286,64,frontier32_vertex,20.164250,19.779333,18.439125,1847854,40,5,0,0.293750,7,pass,20.370750;20.164250;20.339500;20.267708;20.128208;17.858625;20.054792 +hub,4096,12286,64,frontier32_simd,3.679709,3.293959,1.977208,1683322,40,5,0,0.293750,7,pass,3.645583;3.193958;3.704875;3.761667;3.484667;3.679709;3.840292 +hub,4096,12286,64,frontier32_gpu_dag,5.438458,3.358500,3.574666,1683332,40,7,0,0.293750,7,pass,5.438458;5.484333;5.077625;5.436834;5.303625;5.554375;5.500500 +hub,4096,12286,64,bucket32_d4,5.120292,4.739584,3.072042,788342,48,6,0,0.293750,7,pass,5.120292;4.625500;4.994666;5.342250;5.237375;5.632667;5.067500 +hub,4096,12286,64,bucket32_d16,4.910875,4.544250,3.014125,1124798,48,6,0,0.293750,7,pass,4.009541;5.038875;5.070750;4.861667;4.542542;4.910875;4.955625 +hub,4096,12286,64,bucket32_d64,4.974250,4.580000,3.350917,1929942,40,5,0,0.293750,7,pass,5.005417;5.049500;4.529125;4.683875;5.371250;4.974250;4.864500 +random,4096,131072,1,old_pull_parallel_dag,0.700083,0.520875,0.268583,2097152,16,2,0,1.684833,7,pass,0.731166;0.711875;0.720916;0.700083;0.684917;0.682334;0.675125 +random,4096,131072,1,old_group_parallel_dag,2.531042,2.326500,2.178083,1572864,12,1,0,1.684833,7,pass,2.523791;2.531042;2.708208;2.518583;2.480875;2.536250;2.532084 +random,4096,131072,1,pull64_barrier,0.670083,0.484084,0.243542,2097152,16,2,0,1.684833,7,pass,0.658292;0.670083;0.670417;0.656458;0.705666;0.666084;0.683333 +random,4096,131072,1,pull64_interleaved,0.708375,0.538000,0.266292,2097152,16,2,0,1.684833,7,pass,0.754209;0.708375;0.727000;0.718875;0.667125;0.700375;0.688541 +random,4096,131072,1,pull32_interleaved,0.602708,0.417917,0.179833,2097152,16,2,0,1.684833,7,pass,0.621042;0.626125;0.591833;0.563875;0.568041;0.602708;0.610584 +random,4096,131072,1,pull32_gpu_dag,0.827708,0.458416,0.236792,2097152,16,4,0,1.684833,7,pass,0.828209;0.781000;0.802875;0.827708;0.820042;0.839417;0.889042 +random,4096,131072,1,frontier32_vertex,0.826666,0.637916,0.358083,421728,16,2,0,1.684833,7,pass,0.752500;0.788541;0.826666;0.793041;0.834708;0.845292;0.849417 +random,4096,131072,1,frontier32_simd,0.546833,0.381416,0.130042,385248,16,2,0,1.684833,7,pass,0.606166;0.614833;0.596666;0.532584;0.506333;0.517209;0.546833 +random,4096,131072,1,frontier32_gpu_dag,0.790125,0.403958,0.187833,385888,16,4,0,1.684833,7,pass,0.839625;0.868666;0.790125;0.731833;0.751625;0.765125;0.799542 +random,4096,131072,1,bucket32_d4,0.877584,0.692667,0.278500,138720,24,3,0,1.684833,7,pass,0.796125;0.814708;0.794500;0.887917;0.897584;0.887250;0.877584 +random,4096,131072,1,bucket32_d16,0.602042,0.418417,0.176083,177024,16,2,0,1.684833,7,pass,0.609792;0.595458;0.627042;0.687000;0.588708;0.600541;0.602042 +random,4096,131072,1,bucket32_d64,0.676292,0.489459,0.213125,379328,16,2,0,1.684833,7,pass,0.630916;0.676292;0.686500;0.650000;0.656292;0.682083;0.803250 +random,4096,131072,64,old_pull_parallel_dag,9.210958,7.184000,6.254250,134217728,16,2,0,1.632958,7,pass,9.210958;8.705500;9.369750;9.924625;9.088334;9.114250;9.439791 +random,4096,131072,64,old_group_parallel_dag,6.357125,3.995125,3.300500,105644032,15,1,0,1.632958,7,pass,5.947458;6.071417;8.561834;7.417583;5.757250;6.357125;6.392709 +random,4096,131072,64,pull64_barrier,11.065500,9.020000,8.131667,134217728,16,2,0,1.632958,7,pass,11.302500;11.148667;11.423375;10.809625;11.065500;10.187500;9.389333 +random,4096,131072,64,pull64_interleaved,4.038875,1.980792,1.106083,134217728,16,2,0,1.632958,7,pass,4.038875;3.599083;4.111542;4.356333;3.584625;3.627292;4.185792 +random,4096,131072,64,pull32_interleaved,3.814209,1.788000,1.030583,134217728,16,2,0,1.632958,7,pass,3.794375;3.316542;3.413625;3.836125;4.096958;4.530583;3.814209 +random,4096,131072,64,pull32_gpu_dag,2.051166,1.481834,0.860875,134217728,16,4,0,1.632958,7,pass,5.183500;1.808125;2.051166;1.508042;2.034416;2.400834;4.045375 +random,4096,131072,64,frontier32_vertex,5.418375,3.314583,2.452125,22442464,16,2,0,1.632958,7,pass,13.355792;5.418375;5.113042;5.392083;5.442250;5.494958;5.207167 +random,4096,131072,64,frontier32_simd,5.078208,2.991333,1.970125,22729248,16,2,0,1.632958,7,pass,4.876333;5.078208;5.086084;5.029666;4.357167;11.632250;5.217792 +random,4096,131072,64,frontier32_gpu_dag,4.086083,2.827833,2.683125,22826080,16,4,0,1.632958,7,pass,4.039375;4.086083;4.209583;4.054667;4.363042;4.104958;3.480333 +random,4096,131072,64,bucket32_d4,4.731500,2.704083,1.614958,8805184,24,3,0,1.632958,7,pass,4.731500;9.958708;4.957541;4.429834;4.167167;4.010625;8.756250 +random,4096,131072,64,bucket32_d16,4.925625,2.956292,1.858750,12113536,24,3,0,1.632958,7,pass,6.896625;5.068917;4.772583;4.428167;4.925625;4.905334;11.198667 +random,4096,131072,64,bucket32_d64,5.329667,3.309542,2.396333,23278880,16,2,0,1.632958,7,pass,5.089042;5.574291;4.751666;5.494875;5.421709;5.329667;5.243667 diff --git a/dev/research/metal_pathfinding/optimization/results/aba/summary.json b/dev/research/metal_pathfinding/optimization/results/aba/summary.json new file mode 100644 index 0000000..b8bc023 --- /dev/null +++ b/dev/research/metal_pathfinding/optimization/results/aba/summary.json @@ -0,0 +1,570 @@ +{ + "phase_rows": { + "cpu-a1": 48, + "base-a1": 36, + "optimized-b": 216, + "base-a2": 36, + "cpu-a2": 48 + }, + "checked_query_results": 124704, + "summary": [ + { + "case": [ + "random", + "1024", + "8192", + "1" + ], + "cpu_a1": 0.085792, + "cpu_a2": 0.096875, + "old_method": "old_group_serial", + "old_a1": 0.914792, + "old_a2": 0.971833, + "best": { + "case": "random", + "n": "1024", + "e": "8192", + "queries": "1", + "method": "pull32_interleaved", + "wall_ms": "0.599333", + "distance_ms": "0.586041", + "gpu_ms": "0.337667", + "edge_visits": "131072", + "rounds": "16", + "waits": "2", + "fallback64": "0", + "upload_ms": "0.152791", + "samples": "7", + "correct": "pass", + "wall_samples_ms": "0.667083;0.607875;0.599333;0.571542;0.736667;0.583833;0.566542" + } + }, + { + "case": [ + "random", + "1024", + "8192", + "64" + ], + "cpu_a1": 1.247667, + "cpu_a2": 1.340459, + "old_method": "old_group_serial", + "old_a1": 3.817917, + "old_a2": 3.768791, + "best": { + "case": "random", + "n": "1024", + "e": "8192", + "queries": "64", + "method": "old_group_parallel_dag", + "wall_ms": "0.852750", + "distance_ms": "0.566166", + "gpu_ms": "0.379500", + "edge_visits": "7217152", + "rounds": "17", + "waits": "1", + "fallback64": "0", + "upload_ms": "0.238875", + "samples": "7", + "correct": "pass", + "wall_samples_ms": "0.972542;0.909042;0.773791;0.876500;0.773208;0.852750;0.821167" + } + }, + { + "case": [ + "clos", + "200", + "20000", + "64" + ], + "cpu_a1": 1.072125, + "cpu_a2": 1.075958, + "old_method": "old_group_serial", + "old_a1": 4.768459, + "old_a2": 4.869958, + "best": { + "case": "clos", + "n": "200", + "e": "20000", + "queries": "64", + "method": "old_group_parallel_dag", + "wall_ms": "1.460750", + "distance_ms": "0.833416", + "gpu_ms": "0.303250", + "edge_visits": "3840000", + "rounds": "3", + "waits": "1", + "fallback64": "0", + "upload_ms": "0.322125", + "samples": "7", + "correct": "pass", + "wall_samples_ms": "1.479875;1.528583;1.339875;1.338875;1.467208;1.426625;1.460750" + } + }, + { + "case": [ + "grid", + "1024", + "3968", + "1" + ], + "cpu_a1": 0.039042, + "cpu_a2": 0.038708, + "old_method": "old_group_serial", + "old_a1": 1.177083, + "old_a2": 1.165667, + "best": { + "case": "grid", + "n": "1024", + "e": "3968", + "queries": "1", + "method": "old_group_parallel_dag", + "wall_ms": "0.365667", + "distance_ms": "0.358792", + "gpu_ms": "0.227375", + "edge_visits": "249984", + "rounds": "63", + "waits": "1", + "fallback64": "0", + "upload_ms": "0.124084", + "samples": "7", + "correct": "pass", + "wall_samples_ms": "1.116750;0.360041;0.365667;0.352625;0.396042;0.372000;0.363209" + } + }, + { + "case": [ + "hub", + "1024", + "3070", + "1" + ], + "cpu_a1": 0.052333, + "cpu_a2": 0.052, + "old_method": "old_group_serial", + "old_a1": 4.908083, + "old_a2": 4.938125, + "best": { + "case": "hub", + "n": "1024", + "e": "3070", + "queries": "1", + "method": "frontier32_simd", + "wall_ms": "0.784458", + "distance_ms": "0.776500", + "gpu_ms": "0.233250", + "edge_visits": "3128", + "rounds": "32", + "waits": "4", + "fallback64": "0", + "upload_ms": "0.098834", + "samples": "7", + "correct": "pass", + "wall_samples_ms": "0.761209;0.730042;0.781167;0.861667;0.786834;0.795166;0.784458" + } + }, + { + "case": [ + "random_masked_int64_reverse", + "1024", + "8192", + "8" + ], + "cpu_a1": 0.160083, + "cpu_a2": 0.15325, + "old_method": "old_pull_serial", + "old_a1": 0.517667, + "old_a2": 0.55125, + "best": { + "case": "random_masked_int64_reverse", + "n": "1024", + "e": "8192", + "queries": "8", + "method": "bucket32_d16", + "wall_ms": "0.223542", + "distance_ms": "0.178000", + "gpu_ms": "0.028875", + "edge_visits": "524288", + "rounds": "8", + "waits": "1", + "fallback64": "1", + "upload_ms": "0.225500", + "samples": "7", + "correct": "pass", + "wall_samples_ms": "0.222750;0.232791;0.237375;0.258250;0.223542;0.215333;0.210875" + } + }, + { + "case": [ + "random", + "4096", + "32768", + "256" + ], + "cpu_a1": 21.390792, + "cpu_a2": 21.281458, + "old_method": "old_group_serial", + "old_a1": 47.811583, + "old_a2": 49.310208, + "best": { + "case": "random", + "n": "4096", + "e": "32768", + "queries": "256", + "method": "pull64_interleaved", + "wall_ms": "7.002542", + "distance_ms": "3.340208", + "gpu_ms": "2.080917", + "edge_visits": "201326592", + "rounds": "24", + "waits": "3", + "fallback64": "0", + "upload_ms": "0.530167", + "samples": "7", + "correct": "pass", + "wall_samples_ms": "6.459833;7.002542;6.970958;6.819791;8.010875;7.685500;7.589250" + } + }, + { + "case": [ + "random", + "16384", + "131072", + "1" + ], + "cpu_a1": 3.661958, + "cpu_a2": 3.885666, + "old_method": "old_pull_serial", + "old_a1": 2.098167, + "old_a2": 1.870458, + "best": { + "case": "random", + "n": "16384", + "e": "131072", + "queries": "1", + "method": "pull32_interleaved", + "wall_ms": "0.705083", + "distance_ms": "0.520875", + "gpu_ms": "0.136959", + "edge_visits": "3145728", + "rounds": "24", + "waits": "3", + "fallback64": "0", + "upload_ms": "1.641291", + "samples": "7", + "correct": "pass", + "wall_samples_ms": "0.692583;0.711333;0.700666;0.706750;0.705083;0.703000;0.878958" + } + }, + { + "case": [ + "random", + "16384", + "131072", + "64" + ], + "cpu_a1": 27.692792, + "cpu_a2": 27.721375, + "old_method": "old_group_serial", + "old_a1": 57.747584, + "old_a2": 53.10575, + "best": { + "case": "random", + "n": "16384", + "e": "131072", + "queries": "64", + "method": "pull64_interleaved", + "wall_ms": "7.473334", + "distance_ms": "3.322042", + "gpu_ms": "1.949625", + "edge_visits": "201326592", + "rounds": "24", + "waits": "3", + "fallback64": "0", + "upload_ms": "1.869208", + "samples": "7", + "correct": "pass", + "wall_samples_ms": "7.977375;7.469666;7.993750;7.469959;7.340416;8.069541;7.473334" + } + }, + { + "case": [ + "random", + "65536", + "524288", + "1" + ], + "cpu_a1": 19.316, + "cpu_a2": 19.240125, + "old_method": "old_pull_serial", + "old_a1": 5.18425, + "old_a2": 5.85375, + "best": { + "case": "random", + "n": "65536", + "e": "524288", + "queries": "1", + "method": "pull32_gpu_dag", + "wall_ms": "1.373417", + "distance_ms": "0.881667", + "gpu_ms": "0.570875", + "edge_visits": "12582912", + "rounds": "24", + "waits": "5", + "fallback64": "0", + "upload_ms": "7.557667", + "samples": "7", + "correct": "pass", + "wall_samples_ms": "1.391584;1.373417;1.479292;1.291209;1.337833;1.320958;1.406750" + } + }, + { + "case": [ + "clos", + "800", + "320000", + "1" + ], + "cpu_a1": 2.177875, + "cpu_a2": 2.226791, + "old_method": "old_pull_serial", + "old_a1": 1.914708, + "old_a2": 2.377209, + "best": { + "case": "clos", + "n": "800", + "e": "320000", + "queries": "1", + "method": "frontier32_simd", + "wall_ms": "1.604458", + "distance_ms": "0.852083", + "gpu_ms": "0.361417", + "edge_visits": "320000", + "rounds": "8", + "waits": "1", + "fallback64": "0", + "upload_ms": "3.583584", + "samples": "7", + "correct": "pass", + "wall_samples_ms": "1.724958;1.809125;1.589542;1.604458;1.514125;1.668583;1.587916" + } + }, + { + "case": [ + "clos", + "800", + "320000", + "64" + ], + "cpu_a1": 17.041958, + "cpu_a2": 16.524625, + "old_method": "old_group_serial", + "old_a1": 69.896166, + "old_a2": 70.2275, + "best": { + "case": "clos", + "n": "800", + "e": "320000", + "queries": "64", + "method": "pull32_gpu_dag", + "wall_ms": "8.185208", + "distance_ms": "4.307834", + "gpu_ms": "6.163833", + "edge_visits": "163840000", + "rounds": "8", + "waits": "3", + "fallback64": "0", + "upload_ms": "3.568791", + "samples": "7", + "correct": "pass", + "wall_samples_ms": "7.631709;7.941417;8.661667;8.185208;8.311625;8.223667;7.750583" + } + }, + { + "case": [ + "grid", + "10000", + "39600", + "1" + ], + "cpu_a1": 0.570333, + "cpu_a2": 0.58225, + "old_method": "old_pull_serial", + "old_a1": 3.836417, + "old_a2": 5.873791, + "best": { + "case": "grid", + "n": "10000", + "e": "39600", + "queries": "1", + "method": "pull32_interleaved", + "wall_ms": "3.378208", + "distance_ms": "3.313666", + "gpu_ms": "0.604292", + "edge_visits": "7920000", + "rounds": "200", + "waits": "25", + "fallback64": "0", + "upload_ms": "0.518084", + "samples": "7", + "correct": "pass", + "wall_samples_ms": "3.861917;4.153500;3.086834;3.378208;3.201917;3.100208;3.562041" + } + }, + { + "case": [ + "grid", + "10000", + "39600", + "8" + ], + "cpu_a1": 0.834084, + "cpu_a2": 0.822667, + "old_method": "old_pull_serial", + "old_a1": 5.952708, + "old_a2": 5.979167, + "best": { + "case": "grid", + "n": "10000", + "e": "39600", + "queries": "8", + "method": "frontier32_gpu_dag", + "wall_ms": "4.150250", + "distance_ms": "3.853458", + "gpu_ms": "1.370458", + "edge_visits": "316800", + "rounds": "200", + "waits": "27", + "fallback64": "0", + "upload_ms": "0.528251", + "samples": "7", + "correct": "pass", + "wall_samples_ms": "4.059542;4.118750;4.193708;4.150250;4.252083;4.145625;4.603208" + } + }, + { + "case": [ + "chain", + "2048", + "2047", + "1" + ], + "cpu_a1": 0.017209, + "cpu_a2": 0.017375, + "old_method": "old_group_serial", + "old_a1": 4.834291, + "old_a2": 4.908333, + "best": { + "case": "chain", + "n": "2048", + "e": "2047", + "queries": "1", + "method": "old_group_parallel_dag", + "wall_ms": "4.847291", + "distance_ms": "4.824625", + "gpu_ms": "4.695541", + "edge_visits": "4192256", + "rounds": "2048", + "waits": "1", + "fallback64": "0", + "upload_ms": "0.129708", + "samples": "7", + "correct": "pass", + "wall_samples_ms": "4.847291;4.859959;4.876125;4.871750;4.808833;4.800125;4.805458" + } + }, + { + "case": [ + "hub", + "4096", + "12286", + "64" + ], + "cpu_a1": 2.437875, + "cpu_a2": 2.338125, + "old_method": "old_group_serial", + "old_a1": 28.558708, + "old_a2": 28.801291, + "best": { + "case": "hub", + "n": "4096", + "e": "12286", + "queries": "64", + "method": "frontier32_simd", + "wall_ms": "3.679709", + "distance_ms": "3.293959", + "gpu_ms": "1.977208", + "edge_visits": "1683322", + "rounds": "40", + "waits": "5", + "fallback64": "0", + "upload_ms": "0.293750", + "samples": "7", + "correct": "pass", + "wall_samples_ms": "3.645583;3.193958;3.704875;3.761667;3.484667;3.679709;3.840292" + } + }, + { + "case": [ + "random", + "4096", + "131072", + "1" + ], + "cpu_a1": 1.589583, + "cpu_a2": 1.517583, + "old_method": "old_pull_serial", + "old_a1": 0.90625, + "old_a2": 1.039917, + "best": { + "case": "random", + "n": "4096", + "e": "131072", + "queries": "1", + "method": "frontier32_simd", + "wall_ms": "0.546833", + "distance_ms": "0.381416", + "gpu_ms": "0.130042", + "edge_visits": "385248", + "rounds": "16", + "waits": "2", + "fallback64": "0", + "upload_ms": "1.684833", + "samples": "7", + "correct": "pass", + "wall_samples_ms": "0.606166;0.614833;0.596666;0.532584;0.506333;0.517209;0.546833" + } + }, + { + "case": [ + "random", + "4096", + "131072", + "64" + ], + "cpu_a1": 12.301875, + "cpu_a2": 12.817167, + "old_method": "old_group_serial", + "old_a1": 31.930417, + "old_a2": 37.791458, + "best": { + "case": "random", + "n": "4096", + "e": "131072", + "queries": "64", + "method": "pull32_gpu_dag", + "wall_ms": "2.051166", + "distance_ms": "1.481834", + "gpu_ms": "0.860875", + "edge_visits": "134217728", + "rounds": "16", + "waits": "4", + "fallback64": "0", + "upload_ms": "1.632958", + "samples": "7", + "correct": "pass", + "wall_samples_ms": "5.183500;1.808125;2.051166;1.508042;2.034416;2.400834;4.045375" + } + } + ] +} diff --git a/dev/research/metal_pathfinding/optimization/results/aba/summary.md b/dev/research/metal_pathfinding/optimization/results/aba/summary.md new file mode 100644 index 0000000..8f1d0b6 --- /dev/null +++ b/dev/research/metal_pathfinding/optimization/results/aba/summary.md @@ -0,0 +1,317 @@ +# Exploratory A/B/A measurements + +Warm full-result latency in ms, including host distances and positive-cost predecessor DAG. Seven measured samples plus two checked warmups per row. CPU batches use 10 reusable workers. Best variant is selected after measurement; this is an oracle comparison, not an implemented dispatcher. Old GPU columns cover the original pull and group variants; the shared-memory variant was not rerun. The machine was not isolated; these are not accepted performance claims. + +| Case | N / E / Q | CPU full A1 / A2 | Old GPU A1 / A2 | Best tested optimized GPU | ms | CPU BFS full A1 / A2 | +|---|---:|---:|---:|---|---:|---:| +| random | 1024 / 8192 / 1 | 0.086 / 0.097 | 0.915 / 0.972 | pull32_interleaved | 0.599 | — | +| random | 1024 / 8192 / 64 | 1.248 / 1.340 | 3.818 / 3.769 | old_group_parallel_dag | 0.853 | — | +| clos | 200 / 20000 / 64 | 1.072 / 1.076 | 4.768 / 4.870 | old_group_parallel_dag | 1.461 | 0.669 / 0.633 | +| grid | 1024 / 3968 / 1 | 0.039 / 0.039 | 1.177 / 1.166 | old_group_parallel_dag | 0.366 | 0.009 / 0.009 | +| hub | 1024 / 3070 / 1 | 0.052 / 0.052 | 4.908 / 4.938 | frontier32_simd | 0.784 | — | +| random_masked_int64_reverse | 1024 / 8192 / 8 | 0.160 / 0.153 | 0.518 / 0.551 | bucket32_d16 (64-bit pull fallback) | 0.224 | — | +| random | 4096 / 32768 / 256 | 21.391 / 21.281 | 47.812 / 49.310 | pull64_interleaved | 7.003 | — | +| random | 16384 / 131072 / 1 | 3.662 / 3.886 | 2.098 / 1.870 | pull32_interleaved | 0.705 | — | +| random | 16384 / 131072 / 64 | 27.693 / 27.721 | 57.748 / 53.106 | pull64_interleaved | 7.473 | — | +| random | 65536 / 524288 / 1 | 19.316 / 19.240 | 5.184 / 5.854 | pull32_gpu_dag | 1.373 | — | +| clos | 800 / 320000 / 1 | 2.178 / 2.227 | 1.915 / 2.377 | frontier32_simd | 1.604 | 0.908 / 0.938 | +| clos | 800 / 320000 / 64 | 17.042 / 16.525 | 69.896 / 70.228 | pull32_gpu_dag | 8.185 | 8.296 / 7.885 | +| grid | 10000 / 39600 / 1 | 0.570 / 0.582 | 3.836 / 5.874 | pull32_interleaved | 3.378 | 0.089 / 0.088 | +| grid | 10000 / 39600 / 8 | 0.834 / 0.823 | 5.953 / 5.979 | frontier32_gpu_dag | 4.150 | 0.286 / 0.312 | +| chain | 2048 / 2047 / 1 | 0.017 / 0.017 | 4.834 / 4.908 | old_group_parallel_dag | 4.847 | — | +| hub | 4096 / 12286 / 64 | 2.438 / 2.338 | 28.559 / 28.801 | frontier32_simd | 3.680 | — | +| random | 4096 / 131072 / 1 | 1.590 / 1.518 | 0.906 / 1.040 | frontier32_simd | 0.547 | — | +| random | 4096 / 131072 / 64 | 12.302 / 12.817 | 31.930 / 37.791 | pull32_gpu_dag | 2.051 | — | + +## All optimized variants + +No variants omitted. Columns: full wall / distance wall / device work, ms. Device work includes DAG kernels where selected. Edge visits count SSSP adjacency entries, excluding bucket vertex scans, queue management and DAG extraction. + +### ('random', '1024', '8192', '1') + +| Variant | Full / distance / device ms | Edge visits | Rounds | Host waits | 64-bit fallback | +|---|---:|---:|---:|---:|---| +| old_pull_parallel_dag | 1.423 / 1.376 / 0.424 | 131072 | 16 | 2 | 0 | +| old_group_parallel_dag | 0.834 / 0.819 / 0.680 | 106496 | 13 | 1 | 0 | +| pull64_barrier | 0.659 / 0.646 / 0.391 | 131072 | 16 | 2 | 0 | +| pull64_interleaved | 0.656 / 0.643 / 0.375 | 131072 | 16 | 2 | 0 | +| pull32_interleaved | 0.599 / 0.586 / 0.338 | 131072 | 16 | 2 | 0 | +| pull32_gpu_dag | 0.960 / 0.604 / 0.406 | 131072 | 16 | 4 | 0 | +| frontier32_vertex | 0.924 / 0.910 / 0.634 | 21088 | 16 | 2 | 0 | +| frontier32_simd | 0.661 / 0.647 / 0.380 | 20272 | 16 | 2 | 0 | +| frontier32_gpu_dag | 1.003 / 0.652 / 0.452 | 20384 | 16 | 4 | 0 | +| bucket32_d4 | 1.895 / 1.881 / 1.276 | 8232 | 32 | 4 | 0 | +| bucket32_d16 | 1.422 / 1.407 / 0.920 | 9336 | 24 | 3 | 0 | +| bucket32_d64 | 0.954 / 0.939 / 0.654 | 19264 | 16 | 2 | 0 | +### ('random', '1024', '8192', '64') + +| Variant | Full / distance / device ms | Edge visits | Rounds | Host waits | 64-bit fallback | +|---|---:|---:|---:|---:|---| +| old_pull_parallel_dag | 1.973 / 1.703 / 1.236 | 12582912 | 24 | 3 | 0 | +| old_group_parallel_dag | 0.853 / 0.566 / 0.380 | 7217152 | 17 | 1 | 0 | +| pull64_barrier | 1.223 / 0.949 / 0.470 | 12582912 | 24 | 3 | 0 | +| pull64_interleaved | 0.940 / 0.671 / 0.268 | 12582912 | 24 | 3 | 0 | +| pull32_interleaved | 0.863 / 0.595 / 0.197 | 12582912 | 24 | 3 | 0 | +| pull32_gpu_dag | 0.998 / 0.579 / 0.199 | 12582912 | 24 | 5 | 0 | +| frontier32_vertex | 0.870 / 0.629 / 0.239 | 1289824 | 16 | 2 | 0 | +| frontier32_simd | 1.028 / 0.796 / 0.456 | 1202328 | 16 | 2 | 0 | +| frontier32_gpu_dag | 1.197 / 0.890 / 0.509 | 1201208 | 16 | 4 | 0 | +| bucket32_d4 | 5.929 / 5.638 / 4.211 | 528528 | 56 | 7 | 0 | +| bucket32_d16 | 1.624 / 1.347 / 0.712 | 601456 | 32 | 4 | 0 | +| bucket32_d64 | 1.403 / 1.126 / 0.671 | 1154720 | 24 | 3 | 0 | +### ('clos', '200', '20000', '64') + +| Variant | Full / distance / device ms | Edge visits | Rounds | Host waits | 64-bit fallback | +|---|---:|---:|---:|---:|---| +| old_pull_parallel_dag | 2.137 / 1.514 / 1.016 | 10240000 | 8 | 1 | 0 | +| old_group_parallel_dag | 1.461 / 0.833 / 0.303 | 3840000 | 3 | 1 | 0 | +| pull64_barrier | 2.072 / 1.524 / 1.000 | 10240000 | 8 | 1 | 0 | +| pull64_interleaved | 1.903 / 1.332 / 0.757 | 10240000 | 8 | 1 | 0 | +| pull32_interleaved | 1.893 / 1.311 / 0.688 | 10240000 | 8 | 1 | 0 | +| pull32_gpu_dag | 2.092 / 1.226 / 1.013 | 10240000 | 8 | 3 | 0 | +| frontier32_vertex | 2.382 / 1.557 / 0.961 | 1280000 | 8 | 1 | 0 | +| frontier32_simd | 1.552 / 0.924 / 0.318 | 1280000 | 8 | 1 | 0 | +| frontier32_gpu_dag | 1.979 / 0.982 / 0.837 | 1280000 | 8 | 3 | 0 | +| bucket32_d4 | 1.572 / 1.025 / 0.481 | 1280000 | 8 | 1 | 0 | +| bucket32_d16 | 1.739 / 1.166 / 0.492 | 1280000 | 8 | 1 | 0 | +| bucket32_d64 | 1.693 / 1.072 / 0.490 | 1280000 | 8 | 1 | 0 | +### ('grid', '1024', '3968', '1') + +| Variant | Full / distance / device ms | Edge visits | Rounds | Host waits | 64-bit fallback | +|---|---:|---:|---:|---:|---| +| old_pull_parallel_dag | 1.747 / 1.739 / 0.651 | 253952 | 64 | 8 | 0 | +| old_group_parallel_dag | 0.366 / 0.359 / 0.227 | 249984 | 63 | 1 | 0 | +| pull64_barrier | 1.119 / 1.111 / 0.177 | 253952 | 64 | 8 | 0 | +| pull64_interleaved | 1.144 / 1.136 / 0.177 | 253952 | 64 | 8 | 0 | +| pull32_interleaved | 1.089 / 1.081 / 0.164 | 253952 | 64 | 8 | 0 | +| pull32_gpu_dag | 1.271 / 0.918 / 0.173 | 253952 | 64 | 10 | 0 | +| frontier32_vertex | 1.313 / 1.305 / 0.528 | 3968 | 64 | 8 | 0 | +| frontier32_simd | 1.180 / 1.172 / 0.396 | 3968 | 64 | 8 | 0 | +| frontier32_gpu_dag | 1.394 / 1.178 / 0.407 | 3968 | 64 | 10 | 0 | +| bucket32_d4 | 1.450 / 1.441 / 0.637 | 3968 | 64 | 8 | 0 | +| bucket32_d16 | 1.451 / 1.443 / 0.636 | 3968 | 64 | 8 | 0 | +| bucket32_d64 | 1.466 / 1.459 / 0.637 | 3968 | 64 | 8 | 0 | +### ('hub', '1024', '3070', '1') + +| Variant | Full / distance / device ms | Edge visits | Rounds | Host waits | 64-bit fallback | +|---|---:|---:|---:|---:|---| +| old_pull_parallel_dag | 6.046 / 6.030 / 5.544 | 98240 | 32 | 4 | 0 | +| old_group_parallel_dag | 4.888 / 4.866 / 4.721 | 95170 | 31 | 1 | 0 | +| pull64_barrier | 5.016 / 4.988 / 4.313 | 98240 | 32 | 4 | 0 | +| pull64_interleaved | 4.986 / 4.962 / 4.321 | 98240 | 32 | 4 | 0 | +| pull32_interleaved | 4.397 / 4.374 / 3.684 | 98240 | 32 | 4 | 0 | +| pull32_gpu_dag | 5.116 / 4.358 / 4.101 | 98240 | 32 | 6 | 0 | +| frontier32_vertex | 1.436 / 1.428 / 0.852 | 3128 | 32 | 4 | 0 | +| frontier32_simd | 0.784 / 0.776 / 0.233 | 3128 | 32 | 4 | 0 | +| frontier32_gpu_dag | 1.467 / 0.770 / 0.649 | 3128 | 32 | 6 | 0 | +| bucket32_d4 | 0.869 / 0.860 / 0.345 | 3100 | 32 | 4 | 0 | +| bucket32_d16 | 0.851 / 0.843 / 0.337 | 3124 | 32 | 4 | 0 | +| bucket32_d64 | 0.886 / 0.878 / 0.327 | 3128 | 32 | 4 | 0 | +### ('random_masked_int64_reverse', '1024', '8192', '8') + +| Variant | Full / distance / device ms | Edge visits | Rounds | Host waits | 64-bit fallback | +|---|---:|---:|---:|---:|---| +| old_pull_parallel_dag | 0.232 / 0.167 / 0.032 | 524288 | 8 | 1 | 0 | +| old_group_parallel_dag | 0.253 / 0.194 / 0.053 | 368640 | 8 | 1 | 0 | +| pull64_barrier | 0.248 / 0.190 / 0.029 | 524288 | 8 | 1 | 0 | +| pull64_interleaved | 0.264 / 0.197 / 0.029 | 524288 | 8 | 1 | 0 | +| pull32_interleaved | 0.252 / 0.198 / 0.029 | 524288 | 8 | 1 | 1 | +| pull32_gpu_dag | 0.499 / 0.174 / 0.049 | 524288 | 8 | 3 | 1 | +| frontier32_vertex | 0.238 / 0.188 / 0.029 | 524288 | 8 | 1 | 1 | +| frontier32_simd | 0.256 / 0.192 / 0.029 | 524288 | 8 | 1 | 1 | +| frontier32_gpu_dag | 0.504 / 0.184 / 0.047 | 524288 | 8 | 3 | 1 | +| bucket32_d4 | 0.243 / 0.198 / 0.029 | 524288 | 8 | 1 | 1 | +| bucket32_d16 | 0.224 / 0.178 / 0.029 | 524288 | 8 | 1 | 1 | +| bucket32_d64 | 0.261 / 0.199 / 0.029 | 524288 | 8 | 1 | 1 | +### ('random', '4096', '32768', '256') + +| Variant | Full / distance / device ms | Edge visits | Rounds | Host waits | 64-bit fallback | +|---|---:|---:|---:|---:|---| +| old_pull_parallel_dag | 14.955 / 11.144 / 9.933 | 201326592 | 24 | 3 | 0 | +| old_group_parallel_dag | 11.270 / 7.608 / 6.915 | 136544256 | 20 | 1 | 0 | +| pull64_barrier | 13.565 / 9.762 / 8.501 | 201326592 | 24 | 3 | 0 | +| pull64_interleaved | 7.003 / 3.340 / 2.081 | 201326592 | 24 | 3 | 0 | +| pull32_interleaved | 9.000 / 5.200 / 3.525 | 201326592 | 24 | 3 | 0 | +| pull32_gpu_dag | 8.790 / 6.950 / 7.134 | 201326592 | 24 | 5 | 0 | +| frontier32_vertex | 7.936 / 4.094 / 2.380 | 19766184 | 24 | 3 | 0 | +| frontier32_simd | 11.324 / 7.659 / 6.414 | 20599968 | 24 | 3 | 0 | +| frontier32_gpu_dag | 9.247 / 7.874 / 7.025 | 20610776 | 24 | 5 | 0 | +| bucket32_d4 | 16.328 / 12.614 / 10.131 | 8454072 | 72 | 9 | 0 | +| bucket32_d16 | 13.121 / 9.301 / 7.673 | 9728592 | 48 | 6 | 0 | +| bucket32_d64 | 14.196 / 9.623 / 8.264 | 18345256 | 24 | 3 | 0 | +### ('random', '16384', '131072', '1') + +| Variant | Full / distance / device ms | Edge visits | Rounds | Host waits | 64-bit fallback | +|---|---:|---:|---:|---:|---| +| old_pull_parallel_dag | 0.964 / 0.659 / 0.244 | 3145728 | 24 | 3 | 0 | +| old_group_parallel_dag | 5.290 / 4.968 / 4.819 | 2359296 | 18 | 1 | 0 | +| pull64_barrier | 0.761 / 0.571 / 0.164 | 3145728 | 24 | 3 | 0 | +| pull64_interleaved | 0.828 / 0.564 / 0.164 | 3145728 | 24 | 3 | 0 | +| pull32_interleaved | 0.705 / 0.521 / 0.137 | 3145728 | 24 | 3 | 0 | +| pull32_gpu_dag | 0.880 / 0.513 / 0.158 | 3145728 | 24 | 5 | 0 | +| frontier32_vertex | 0.832 / 0.619 / 0.258 | 377056 | 24 | 3 | 0 | +| frontier32_simd | 0.806 / 0.593 / 0.237 | 335680 | 24 | 3 | 0 | +| frontier32_gpu_dag | 0.983 / 0.612 / 0.269 | 334824 | 24 | 5 | 0 | +| bucket32_d4 | 1.833 / 1.546 / 0.654 | 132016 | 56 | 7 | 0 | +| bucket32_d16 | 1.148 / 0.917 / 0.398 | 148256 | 32 | 4 | 0 | +| bucket32_d64 | 0.937 / 0.712 / 0.340 | 268728 | 24 | 3 | 0 | +### ('random', '16384', '131072', '64') + +| Variant | Full / distance / device ms | Edge visits | Rounds | Host waits | 64-bit fallback | +|---|---:|---:|---:|---:|---| +| old_pull_parallel_dag | 16.913 / 12.651 / 11.412 | 201326592 | 24 | 3 | 0 | +| old_group_parallel_dag | 13.239 / 9.052 / 8.276 | 158203904 | 22 | 1 | 0 | +| pull64_barrier | 15.959 / 11.386 / 10.305 | 201326592 | 24 | 3 | 0 | +| pull64_interleaved | 7.473 / 3.322 / 1.950 | 201326592 | 24 | 3 | 0 | +| pull32_interleaved | 8.710 / 3.948 / 2.593 | 201326592 | 24 | 3 | 0 | +| pull32_gpu_dag | 8.810 / 7.334 / 7.227 | 201326592 | 24 | 5 | 0 | +| frontier32_vertex | 10.144 / 5.760 / 3.640 | 21296680 | 24 | 3 | 0 | +| frontier32_simd | 12.189 / 7.941 / 6.799 | 22006672 | 24 | 3 | 0 | +| frontier32_gpu_dag | 9.203 / 7.809 / 7.471 | 21985376 | 24 | 5 | 0 | +| bucket32_d4 | 16.825 / 12.607 / 10.280 | 8451400 | 72 | 9 | 0 | +| bucket32_d16 | 13.809 / 9.687 / 7.926 | 9572312 | 48 | 6 | 0 | +| bucket32_d64 | 12.602 / 8.439 / 7.400 | 17413440 | 24 | 3 | 0 | +### ('random', '65536', '524288', '1') + +| Variant | Full / distance / device ms | Edge visits | Rounds | Host waits | 64-bit fallback | +|---|---:|---:|---:|---:|---| +| old_pull_parallel_dag | 3.545 / 2.038 / 1.061 | 12582912 | 24 | 3 | 0 | +| old_group_parallel_dag | 30.358 / 28.978 / 28.314 | 11534336 | 22 | 1 | 0 | +| pull64_barrier | 3.163 / 1.729 / 0.758 | 12582912 | 24 | 3 | 0 | +| pull64_interleaved | 3.048 / 1.519 / 0.703 | 12582912 | 24 | 3 | 0 | +| pull32_interleaved | 2.913 / 1.338 / 0.502 | 12582912 | 24 | 3 | 0 | +| pull32_gpu_dag | 1.373 / 0.882 / 0.571 | 12582912 | 24 | 5 | 0 | +| frontier32_vertex | 2.737 / 1.259 / 0.435 | 1734632 | 24 | 3 | 0 | +| frontier32_simd | 3.045 / 1.576 / 0.640 | 1561768 | 24 | 3 | 0 | +| frontier32_gpu_dag | 1.461 / 1.045 / 0.686 | 1558160 | 24 | 5 | 0 | +| bucket32_d4 | 4.357 / 2.761 / 1.174 | 528256 | 64 | 8 | 0 | +| bucket32_d16 | 3.481 / 2.047 / 0.836 | 599256 | 40 | 5 | 0 | +| bucket32_d64 | 3.187 / 1.681 / 0.677 | 1050376 | 24 | 3 | 0 | +### ('clos', '800', '320000', '1') + +| Variant | Full / distance / device ms | Edge visits | Rounds | Host waits | 64-bit fallback | +|---|---:|---:|---:|---:|---| +| old_pull_parallel_dag | 2.142 / 1.366 / 0.744 | 2560000 | 8 | 1 | 0 | +| old_group_parallel_dag | 2.326 / 1.577 / 0.905 | 960000 | 3 | 1 | 0 | +| pull64_barrier | 2.017 / 1.253 / 0.699 | 2560000 | 8 | 1 | 0 | +| pull64_interleaved | 2.265 / 1.493 / 0.878 | 2560000 | 8 | 1 | 0 | +| pull32_interleaved | 2.801 / 1.980 / 1.363 | 2560000 | 8 | 1 | 0 | +| pull32_gpu_dag | 2.133 / 1.256 / 0.994 | 2560000 | 8 | 3 | 0 | +| frontier32_vertex | 2.376 / 1.575 / 0.933 | 320000 | 8 | 1 | 0 | +| frontier32_simd | 1.604 / 0.852 / 0.361 | 320000 | 8 | 1 | 0 | +| frontier32_gpu_dag | 1.714 / 0.824 / 0.606 | 320000 | 8 | 3 | 0 | +| bucket32_d4 | 1.660 / 0.873 / 0.446 | 320000 | 8 | 1 | 0 | +| bucket32_d16 | 1.716 / 0.904 / 0.444 | 320000 | 8 | 1 | 0 | +| bucket32_d64 | 1.698 / 0.939 / 0.453 | 320000 | 8 | 1 | 0 | +### ('clos', '800', '320000', '64') + +| Variant | Full / distance / device ms | Edge visits | Rounds | Host waits | 64-bit fallback | +|---|---:|---:|---:|---:|---| +| old_pull_parallel_dag | 26.735 / 19.418 / 18.854 | 163840000 | 8 | 1 | 0 | +| old_group_parallel_dag | 12.637 / 5.915 / 5.412 | 61440000 | 3 | 1 | 0 | +| pull64_barrier | 24.737 / 18.165 / 17.725 | 163840000 | 8 | 1 | 0 | +| pull64_interleaved | 13.270 / 6.122 / 5.405 | 163840000 | 8 | 1 | 0 | +| pull32_interleaved | 10.983 / 4.274 / 3.647 | 163840000 | 8 | 1 | 0 | +| pull32_gpu_dag | 8.185 / 4.308 / 6.164 | 163840000 | 8 | 3 | 0 | +| frontier32_vertex | 14.231 / 7.148 / 6.877 | 20480000 | 8 | 1 | 0 | +| frontier32_simd | 9.324 / 2.065 / 1.458 | 20480000 | 8 | 1 | 0 | +| frontier32_gpu_dag | 15.944 / 2.089 / 14.063 | 20480000 | 8 | 3 | 0 | +| bucket32_d4 | 10.000 / 2.529 / 2.040 | 20480000 | 8 | 1 | 0 | +| bucket32_d16 | 9.610 / 2.183 / 1.863 | 20480000 | 8 | 1 | 0 | +| bucket32_d64 | 9.988 / 2.684 / 2.106 | 20480000 | 8 | 1 | 0 | +### ('grid', '10000', '39600', '1') + +| Variant | Full / distance / device ms | Edge visits | Rounds | Host waits | 64-bit fallback | +|---|---:|---:|---:|---:|---| +| old_pull_parallel_dag | 4.013 / 3.947 / 0.706 | 7920000 | 200 | 25 | 0 | +| old_group_parallel_dag | 8.014 / 7.948 / 7.804 | 7880400 | 199 | 1 | 0 | +| pull64_barrier | 4.120 / 3.996 / 0.682 | 7920000 | 200 | 25 | 0 | +| pull64_interleaved | 3.963 / 3.894 / 0.656 | 7920000 | 200 | 25 | 0 | +| pull32_interleaved | 3.378 / 3.314 / 0.604 | 7920000 | 200 | 25 | 0 | +| pull32_gpu_dag | 3.492 / 3.086 / 0.616 | 7920000 | 200 | 27 | 0 | +| frontier32_vertex | 4.642 / 4.568 / 1.859 | 39600 | 200 | 25 | 0 | +| frontier32_simd | 4.040 / 3.931 / 1.337 | 39600 | 200 | 25 | 0 | +| frontier32_gpu_dag | 4.283 / 3.993 / 1.302 | 39600 | 200 | 27 | 0 | +| bucket32_d4 | 4.910 / 4.826 / 2.156 | 39600 | 200 | 25 | 0 | +| bucket32_d16 | 5.336 / 5.270 / 2.375 | 39600 | 200 | 25 | 0 | +| bucket32_d64 | 5.193 / 5.129 / 2.313 | 39600 | 200 | 25 | 0 | +### ('grid', '10000', '39600', '8') + +| Variant | Full / distance / device ms | Edge visits | Rounds | Host waits | 64-bit fallback | +|---|---:|---:|---:|---:|---| +| old_pull_parallel_dag | 4.347 / 4.145 / 1.436 | 63360000 | 200 | 25 | 0 | +| old_group_parallel_dag | 8.292 / 8.082 / 7.572 | 51480000 | 199 | 1 | 0 | +| pull64_barrier | 4.480 / 4.280 / 1.391 | 63360000 | 200 | 25 | 0 | +| pull64_interleaved | 4.328 / 4.167 / 1.330 | 63360000 | 200 | 25 | 0 | +| pull32_interleaved | 4.287 / 4.032 / 1.368 | 63360000 | 200 | 25 | 0 | +| pull32_gpu_dag | 4.436 / 4.109 / 1.562 | 63360000 | 200 | 27 | 0 | +| frontier32_vertex | 5.906 / 5.657 / 2.502 | 316800 | 200 | 25 | 0 | +| frontier32_simd | 4.526 / 4.257 / 1.461 | 316800 | 200 | 25 | 0 | +| frontier32_gpu_dag | 4.150 / 3.853 / 1.370 | 316800 | 200 | 27 | 0 | +| bucket32_d4 | 7.676 / 7.433 / 3.707 | 316800 | 200 | 25 | 0 | +| bucket32_d16 | 7.596 / 7.402 / 3.678 | 316800 | 200 | 25 | 0 | +| bucket32_d64 | 7.603 / 7.391 / 3.721 | 316800 | 200 | 25 | 0 | +### ('chain', '2048', '2047', '1') + +| Variant | Full / distance / device ms | Edge visits | Rounds | Host waits | 64-bit fallback | +|---|---:|---:|---:|---:|---| +| old_pull_parallel_dag | 30.065 / 30.058 / 4.364 | 4192256 | 2048 | 256 | 0 | +| old_group_parallel_dag | 4.847 / 4.825 / 4.696 | 4192256 | 2048 | 1 | 0 | +| pull64_barrier | 28.539 / 28.532 / 4.712 | 4192256 | 2048 | 256 | 0 | +| pull64_interleaved | 32.552 / 32.545 / 6.166 | 4192256 | 2048 | 256 | 0 | +| pull32_interleaved | 33.313 / 33.304 / 7.668 | 4192256 | 2048 | 256 | 0 | +| pull32_gpu_dag | 30.619 / 30.342 / 4.891 | 4192256 | 2048 | 258 | 0 | +| frontier32_vertex | 37.679 / 37.671 / 12.262 | 2047 | 2048 | 256 | 0 | +| frontier32_simd | 41.050 / 41.041 / 15.764 | 2047 | 2048 | 256 | 0 | +| frontier32_gpu_dag | 40.148 / 39.758 / 13.087 | 2047 | 2048 | 258 | 0 | +| bucket32_d4 | 49.001 / 48.994 / 21.208 | 2047 | 2056 | 257 | 0 | +| bucket32_d16 | 48.755 / 48.747 / 21.149 | 2047 | 2056 | 257 | 0 | +| bucket32_d64 | 48.401 / 48.395 / 21.022 | 2047 | 2056 | 257 | 0 | +### ('hub', '4096', '12286', '64') + +| Variant | Full / distance / device ms | Edge visits | Rounds | Host waits | 64-bit fallback | +|---|---:|---:|---:|---:|---| +| old_pull_parallel_dag | 32.652 / 32.266 / 30.925 | 31452160 | 40 | 5 | 0 | +| old_group_parallel_dag | 26.147 / 25.761 / 25.032 | 27176632 | 38 | 1 | 0 | +| pull64_barrier | 25.410 / 25.029 / 23.756 | 31452160 | 40 | 5 | 0 | +| pull64_interleaved | 33.830 / 33.457 / 31.908 | 31452160 | 40 | 5 | 0 | +| pull32_interleaved | 29.085 / 28.621 / 27.390 | 31452160 | 40 | 5 | 0 | +| pull32_gpu_dag | 31.331 / 28.778 / 29.382 | 31452160 | 40 | 7 | 0 | +| frontier32_vertex | 20.164 / 19.779 / 18.439 | 1847854 | 40 | 5 | 0 | +| frontier32_simd | 3.680 / 3.294 / 1.977 | 1683322 | 40 | 5 | 0 | +| frontier32_gpu_dag | 5.438 / 3.358 / 3.575 | 1683332 | 40 | 7 | 0 | +| bucket32_d4 | 5.120 / 4.740 / 3.072 | 788342 | 48 | 6 | 0 | +| bucket32_d16 | 4.911 / 4.544 / 3.014 | 1124798 | 48 | 6 | 0 | +| bucket32_d64 | 4.974 / 4.580 / 3.351 | 1929942 | 40 | 5 | 0 | +### ('random', '4096', '131072', '1') + +| Variant | Full / distance / device ms | Edge visits | Rounds | Host waits | 64-bit fallback | +|---|---:|---:|---:|---:|---| +| old_pull_parallel_dag | 0.700 / 0.521 / 0.269 | 2097152 | 16 | 2 | 0 | +| old_group_parallel_dag | 2.531 / 2.326 / 2.178 | 1572864 | 12 | 1 | 0 | +| pull64_barrier | 0.670 / 0.484 / 0.244 | 2097152 | 16 | 2 | 0 | +| pull64_interleaved | 0.708 / 0.538 / 0.266 | 2097152 | 16 | 2 | 0 | +| pull32_interleaved | 0.603 / 0.418 / 0.180 | 2097152 | 16 | 2 | 0 | +| pull32_gpu_dag | 0.828 / 0.458 / 0.237 | 2097152 | 16 | 4 | 0 | +| frontier32_vertex | 0.827 / 0.638 / 0.358 | 421728 | 16 | 2 | 0 | +| frontier32_simd | 0.547 / 0.381 / 0.130 | 385248 | 16 | 2 | 0 | +| frontier32_gpu_dag | 0.790 / 0.404 / 0.188 | 385888 | 16 | 4 | 0 | +| bucket32_d4 | 0.878 / 0.693 / 0.279 | 138720 | 24 | 3 | 0 | +| bucket32_d16 | 0.602 / 0.418 / 0.176 | 177024 | 16 | 2 | 0 | +| bucket32_d64 | 0.676 / 0.489 / 0.213 | 379328 | 16 | 2 | 0 | +### ('random', '4096', '131072', '64') + +| Variant | Full / distance / device ms | Edge visits | Rounds | Host waits | 64-bit fallback | +|---|---:|---:|---:|---:|---| +| old_pull_parallel_dag | 9.211 / 7.184 / 6.254 | 134217728 | 16 | 2 | 0 | +| old_group_parallel_dag | 6.357 / 3.995 / 3.300 | 105644032 | 15 | 1 | 0 | +| pull64_barrier | 11.066 / 9.020 / 8.132 | 134217728 | 16 | 2 | 0 | +| pull64_interleaved | 4.039 / 1.981 / 1.106 | 134217728 | 16 | 2 | 0 | +| pull32_interleaved | 3.814 / 1.788 / 1.031 | 134217728 | 16 | 2 | 0 | +| pull32_gpu_dag | 2.051 / 1.482 / 0.861 | 134217728 | 16 | 4 | 0 | +| frontier32_vertex | 5.418 / 3.315 / 2.452 | 22442464 | 16 | 2 | 0 | +| frontier32_simd | 5.078 / 2.991 / 1.970 | 22729248 | 16 | 2 | 0 | +| frontier32_gpu_dag | 4.086 / 2.828 / 2.683 | 22826080 | 16 | 4 | 0 | +| bucket32_d4 | 4.731 / 2.704 / 1.615 | 8805184 | 24 | 3 | 0 | +| bucket32_d16 | 4.926 / 2.956 / 1.859 | 12113536 | 24 | 3 | 0 | +| bucket32_d64 | 5.330 / 3.310 / 2.396 | 23278880 | 16 | 2 | 0 | diff --git a/dev/research/metal_pathfinding/optimization/results/aba/time-base-a1.txt b/dev/research/metal_pathfinding/optimization/results/aba/time-base-a1.txt new file mode 100644 index 0000000..a1f056c --- /dev/null +++ b/dev/research/metal_pathfinding/optimization/results/aba/time-base-a1.txt @@ -0,0 +1,2 @@ +2026-09-26T23:29:22Z +2026-09-26T23:29:35Z diff --git a/dev/research/metal_pathfinding/optimization/results/aba/time-base-a2.txt b/dev/research/metal_pathfinding/optimization/results/aba/time-base-a2.txt new file mode 100644 index 0000000..c203e1a --- /dev/null +++ b/dev/research/metal_pathfinding/optimization/results/aba/time-base-a2.txt @@ -0,0 +1,2 @@ +2026-09-26T23:30:30Z +2026-09-26T23:30:43Z diff --git a/dev/research/metal_pathfinding/optimization/results/aba/time-cpu-a1.txt b/dev/research/metal_pathfinding/optimization/results/aba/time-cpu-a1.txt new file mode 100644 index 0000000..96d1d9c --- /dev/null +++ b/dev/research/metal_pathfinding/optimization/results/aba/time-cpu-a1.txt @@ -0,0 +1,2 @@ +2026-09-26T23:29:10Z +2026-09-26T23:29:20Z diff --git a/dev/research/metal_pathfinding/optimization/results/aba/time-cpu-a2.txt b/dev/research/metal_pathfinding/optimization/results/aba/time-cpu-a2.txt new file mode 100644 index 0000000..aa2e187 --- /dev/null +++ b/dev/research/metal_pathfinding/optimization/results/aba/time-cpu-a2.txt @@ -0,0 +1,2 @@ +2026-09-26T23:30:45Z +2026-09-26T23:30:56Z diff --git a/dev/research/metal_pathfinding/optimization/results/aba/time-optimized-b.txt b/dev/research/metal_pathfinding/optimization/results/aba/time-optimized-b.txt new file mode 100644 index 0000000..9700df1 --- /dev/null +++ b/dev/research/metal_pathfinding/optimization/results/aba/time-optimized-b.txt @@ -0,0 +1,2 @@ +2026-09-26T23:29:37Z +2026-09-26T23:30:29Z diff --git a/dev/research/metal_pathfinding/optimization/results/audit.json b/dev/research/metal_pathfinding/optimization/results/audit.json new file mode 100644 index 0000000..99f87b6 --- /dev/null +++ b/dev/research/metal_pathfinding/optimization/results/audit.json @@ -0,0 +1,66 @@ +{ + "correctness-final.csv": { + "rows": 336, + "checked_query_results": 11760 + }, + "stress.csv": { + "rows": 28, + "checked_query_results": 39424 + }, + "correctness-sanitized.csv": { + "rows": 336, + "checked_query_results": 11760 + }, + "stress-sanitized.csv": { + "rows": 28, + "checked_query_results": 8960 + }, + "aba": { + "phase_rows": { + "cpu-a1": 48, + "base-a1": 36, + "optimized-b": 216, + "base-a2": 36, + "cpu-a2": 48 + }, + "checked_query_results": 124704 + }, + "total_checked_query_results": 290192, + "source_sha256": { + "dev/metal_pathfinding/experiment.mm": "1da9ff77bd2ad97e95e951454821b25005859c6f75c27a3c56d925e5fc99f6fc", + "dev/metal_pathfinding/sssp.metal": "2e36b1623a3940bf1f19f5d81141bb1def14f5873fe2a98aab0101bbe68618a3", + "dev/metal_pathfinding/optimization/experiment.mm": "7717db8d791d17f7f0ef0b672461ad82afb2ae99cc2ab6c8cb8b33b35e74dd25", + "dev/metal_pathfinding/optimization/kernels.metal": "bed6c9a836e85520101659471c62b7c4c9eb6f4954cb7bb74c971f10c44f37ff", + "dev/metal_pathfinding/optimization/cpu_algorithms.mm": "44962b5bd1dba6ecfc8d1449e324875e35ebe373e3f33aef779be12d9cb3fd65", + "dev/metal_pathfinding/optimization/summarize.py": "a08a937336abf0c30fbed82ac4cec970868f1d77469d5aca1a84a9407326578a", + "dev/metal_pathfinding/optimization/summarize_cpu.py": "b384cca4832b308694e1642020ef09cc5b0084c27df5ec20bd64ea793ead51a0" + }, + "cpu-algorithms-correctness.csv": { + "rows": 24, + "checked_query_results": 960 + }, + "cpu-algorithms-sanitized.csv": { + "rows": 24, + "checked_query_results": 960 + }, + "cpu-algorithms-full-sanitized.csv": { + "rows": 14, + "checked_query_results": 3608 + }, + "cpu_algorithms_aba": { + "phase_rows": { + "a1": 14, + "b": 216, + "a2": 14 + }, + "checked_query_results": 88056 + }, + "repository_checks": { + "workspace_check": "passed: rebuilt extension, lint, types, 170 C++ and 465 Python tests", + "sanitize_test": "170 C++ tests passed", + "ci": "not run", + "production_tracked_changes": false, + "commit_created": false, + "pushed": false + } +} diff --git a/dev/research/metal_pathfinding/optimization/results/correctness-final-stderr.txt b/dev/research/metal_pathfinding/optimization/results/correctness-final-stderr.txt new file mode 100644 index 0000000..5d79ff7 --- /dev/null +++ b/dev/research/metal_pathfinding/optimization/results/correctness-final-stderr.txt @@ -0,0 +1 @@ +device=Apple M4 Max setup_ms=51.344 execution_width=32 diff --git a/dev/research/metal_pathfinding/optimization/results/correctness-final.csv b/dev/research/metal_pathfinding/optimization/results/correctness-final.csv new file mode 100644 index 0000000..23c8fd2 --- /dev/null +++ b/dev/research/metal_pathfinding/optimization/results/correctness-final.csv @@ -0,0 +1,337 @@ +case,n,e,queries,method,wall_ms,distance_ms,gpu_ms,edge_visits,rounds,waits,fallback64,upload_ms,samples,correct,wall_samples_ms +random_masked_int64,40,240,8,old_pull_serial,0.295542,0.280167,0.122083,15360,8,1,0,0.093124,3,pass,0.295542;0.481375;0.254833 +random_masked_int64,40,240,8,old_group_serial,0.494583,0.487583,0.071625,9600,6,1,0,0.093124,3,pass,0.494583;0.218417;0.495042 +random_masked_int64,40,240,8,old_pull_parallel_dag,0.795000,0.716125,0.145833,15360,8,1,0,0.093124,3,pass,0.615625;0.805625;0.795000 +random_masked_int64,40,240,8,old_group_parallel_dag,0.240042,0.192250,0.068542,9600,6,1,0,0.093124,3,pass,0.227042;0.240042;0.242917 +random_masked_int64,40,240,8,pull64_barrier,0.335500,0.297875,0.112167,15360,8,1,0,0.093124,3,pass,0.354916;0.320250;0.335500 +random_masked_int64,40,240,8,pull64_interleaved,0.544875,0.511792,0.116292,15360,8,1,0,0.093124,3,pass,0.535125;0.544875;0.697958 +random_masked_int64,40,240,8,pull32_interleaved,0.321750,0.275625,0.113792,15360,8,1,1,0.093124,3,pass,0.684625;0.321750;0.294917 +random_masked_int64,40,240,8,pull32_gpu_dag,0.714125,0.310708,0.195750,15360,8,3,1,0.093124,3,pass,0.863417;0.676542;0.714125 +random_masked_int64,40,240,8,frontier32_vertex,0.313500,0.274208,0.112208,15360,8,1,1,0.093124,3,pass,0.313500;0.315958;0.307541 +random_masked_int64,40,240,8,frontier32_simd,0.448917,0.414458,0.134125,15360,8,1,1,0.093124,3,pass,0.622542;0.448917;0.341667 +random_masked_int64,40,240,8,frontier32_gpu_dag,0.730291,0.305292,0.195917,15360,8,3,1,0.093124,3,pass,0.638333;0.737416;0.730291 +random_masked_int64,40,240,8,bucket32_d4,0.335667,0.285709,0.112125,15360,8,1,1,0.093124,3,pass,0.335667;0.338542;0.313417 +random_masked_int64,40,240,8,bucket32_d16,0.346750,0.319792,0.141667,15360,8,1,1,0.093124,3,pass,0.364625;0.343333;0.346750 +random_masked_int64,40,240,8,bucket32_d64,0.295625,0.270000,0.113125,15360,8,1,1,0.093124,3,pass,0.300625;0.295625;0.295209 +random_masked,43,258,8,old_pull_serial,0.553208,0.537875,0.297833,33024,16,2,0,0.058250,3,pass,0.553208;0.532292;1.283709 +random_masked,43,258,8,old_group_serial,0.253708,0.245125,0.106625,14448,9,1,0,0.058250,3,pass,0.253708;0.254417;0.248625 +random_masked,43,258,8,old_pull_parallel_dag,0.659625,0.611375,0.315917,33024,16,2,0,0.058250,3,pass,0.659625;0.763875;0.653084 +random_masked,43,258,8,old_group_parallel_dag,0.264917,0.231916,0.105708,14448,9,1,0,0.058250,3,pass,0.279208;0.264917;0.260500 +random_masked,43,258,8,pull64_barrier,0.598083,0.582250,0.276708,33024,16,2,0,0.058250,3,pass,0.576291;0.598083;0.730833 +random_masked,43,258,8,pull64_interleaved,0.649584,0.619375,0.300167,33024,16,2,0,0.058250,3,pass,0.649584;0.693042;0.621250 +random_masked,43,258,8,pull32_interleaved,0.643791,0.610666,0.280375,33024,16,2,0,0.058250,3,pass,0.616875;1.234375;0.643791 +random_masked,43,258,8,pull32_gpu_dag,0.862916,0.498916,0.270583,33024,16,4,0,0.058250,3,pass,0.862916;0.851875;0.952791 +random_masked,43,258,8,frontier32_vertex,0.788458,0.755458,0.433333,3186,16,2,0,0.058250,3,pass,0.843375;0.745917;0.788458 +random_masked,43,258,8,frontier32_simd,0.648291,0.621291,0.322292,3186,16,2,0,0.058250,3,pass,0.648291;0.637833;0.685875 +random_masked,43,258,8,frontier32_gpu_dag,1.073125,0.610375,0.384208,3186,16,4,0,0.058250,3,pass,1.453292;1.073125;1.037708 +random_masked,43,258,8,bucket32_d4,1.775500,1.724792,1.121667,2016,32,4,0,0.058250,3,pass,1.748708;1.823084;1.775500 +random_masked,43,258,8,bucket32_d16,1.315042,1.288875,0.827166,2142,24,3,0,0.058250,3,pass,1.315042;1.332542;1.310125 +random_masked,43,258,8,bucket32_d64,0.967625,0.920750,0.555500,3096,16,2,0,0.058250,3,pass,0.967625;1.148250;0.876542 +random_masked_int64_reverse,46,276,8,old_pull_serial,0.228500,0.216209,0.095250,17664,8,1,0,0.062209,3,pass,0.227542;0.233708;0.228500 +random_masked_int64_reverse,46,276,8,old_group_serial,0.190666,0.173792,0.044500,9660,5,1,0,0.062209,3,pass,0.190666;0.191250;0.183416 +random_masked_int64_reverse,46,276,8,old_pull_parallel_dag,0.279041,0.234000,0.095750,17664,8,1,0,0.062209,3,pass,0.280542;0.277709;0.279041 +random_masked_int64_reverse,46,276,8,old_group_parallel_dag,0.215084,0.178417,0.044750,9660,5,1,0,0.062209,3,pass,0.223000;0.205708;0.215084 +random_masked_int64_reverse,46,276,8,pull64_barrier,0.297583,0.262625,0.093000,17664,8,1,0,0.062209,3,pass,0.297583;0.295959;0.299708 +random_masked_int64_reverse,46,276,8,pull64_interleaved,0.282500,0.247250,0.094750,17664,8,1,0,0.062209,3,pass,0.285875;0.282500;0.269042 +random_masked_int64_reverse,46,276,8,pull32_interleaved,0.293375,0.256125,0.095333,17664,8,1,1,0.062209,3,pass,0.276583;0.293375;0.723250 +random_masked_int64_reverse,46,276,8,pull32_gpu_dag,0.619291,0.257709,0.144750,17664,8,3,1,0.062209,3,pass,0.693292;0.619291;0.600458 +random_masked_int64_reverse,46,276,8,frontier32_vertex,0.285083,0.250750,0.092833,17664,8,1,1,0.062209,3,pass,0.279625;0.292667;0.285083 +random_masked_int64_reverse,46,276,8,frontier32_simd,0.294167,0.262416,0.094000,17664,8,1,1,0.062209,3,pass,0.294167;0.297875;0.293209 +random_masked_int64_reverse,46,276,8,frontier32_gpu_dag,0.626417,0.252917,0.144000,17664,8,3,1,0.062209,3,pass,0.626417;0.648291;0.621667 +random_masked_int64_reverse,46,276,8,bucket32_d4,0.299416,0.254583,0.092833,17664,8,1,1,0.062209,3,pass,0.299416;0.327750;0.296000 +random_masked_int64_reverse,46,276,8,bucket32_d16,0.298250,0.259125,0.093458,17664,8,1,1,0.062209,3,pass,0.298250;0.315625;0.291042 +random_masked_int64_reverse,46,276,8,bucket32_d64,0.271792,0.249875,0.093125,17664,8,1,1,0.062209,3,pass,0.302208;0.270667;0.271792 +random_masked,49,294,8,old_pull_serial,0.254500,0.245625,0.124375,18816,8,1,0,0.061041,3,pass,0.254500;0.265292;0.249375 +random_masked,49,294,8,old_group_serial,0.238708,0.229917,0.093250,14700,8,1,0,0.061041,3,pass,0.216625;0.239000;0.238708 +random_masked,49,294,8,old_pull_parallel_dag,0.299625,0.260792,0.124042,18816,8,1,0,0.061041,3,pass,0.306959;0.291250;0.299625 +random_masked,49,294,8,old_group_parallel_dag,0.266000,0.227791,0.093250,14700,8,1,0,0.061041,3,pass,0.253208;0.266000;0.305791 +random_masked,49,294,8,pull64_barrier,0.326084,0.287958,0.121875,18816,8,1,0,0.061041,3,pass,0.317208;0.333250;0.326084 +random_masked,49,294,8,pull64_interleaved,0.297000,0.266958,0.121417,18816,8,1,0,0.061041,3,pass,0.297000;0.272667;0.317333 +random_masked,49,294,8,pull32_interleaved,0.313584,0.278125,0.108625,18816,8,1,0,0.061041,3,pass,0.300375;0.947375;0.313584 +random_masked,49,294,8,pull32_gpu_dag,0.638875,0.268333,0.150750,18816,8,3,0,0.061041,3,pass,0.638875;0.636125;0.734292 +random_masked,49,294,8,frontier32_vertex,0.500083,0.467625,0.272750,3162,8,1,0,0.061041,3,pass,0.378791;0.637958;0.500083 +random_masked,49,294,8,frontier32_simd,0.368084,0.336083,0.180250,3162,8,1,0,0.061041,3,pass,0.383958;0.368084;0.357500 +random_masked,49,294,8,frontier32_gpu_dag,0.731333,0.351000,0.229584,3162,8,3,0,0.061041,3,pass,0.729833;0.842292;0.731333 +random_masked,49,294,8,bucket32_d4,1.551542,1.512250,0.792500,2022,40,5,0,0.061041,3,pass,1.533000;1.551542;1.629291 +random_masked,49,294,8,bucket32_d16,0.829375,0.768292,0.443917,2100,16,2,0,0.061041,3,pass,0.829375;0.911083;0.756209 +random_masked,49,294,8,bucket32_d64,0.655000,0.621375,0.319375,3036,16,2,0,0.061041,3,pass,0.654833;0.673291;0.655000 +random_masked_int64,52,312,8,old_pull_serial,0.206500,0.193792,0.074250,19968,8,1,0,0.089792,3,pass,0.206500;0.191000;0.219292 +random_masked_int64,52,312,8,old_group_serial,0.179167,0.169875,0.042417,12168,6,1,0,0.089792,3,pass,0.179167;0.187583;0.178459 +random_masked_int64,52,312,8,old_pull_parallel_dag,0.243125,0.207833,0.074833,19968,8,1,0,0.089792,3,pass,0.266375;0.243125;0.231208 +random_masked_int64,52,312,8,old_group_parallel_dag,0.192375,0.149375,0.033042,12168,6,1,0,0.089792,3,pass,0.201000;0.192375;0.177625 +random_masked_int64,52,312,8,pull64_barrier,0.222042,0.204000,0.054875,19968,8,1,0,0.089792,3,pass,0.222042;0.491792;0.211875 +random_masked_int64,52,312,8,pull64_interleaved,0.222875,0.206875,0.054417,19968,8,1,0,0.089792,3,pass,0.222875;0.212375;0.242667 +random_masked_int64,52,312,8,pull32_interleaved,0.243833,0.214167,0.054583,19968,8,1,1,0.089792,3,pass,0.257250;0.243833;0.235084 +random_masked_int64,52,312,8,pull32_gpu_dag,0.575083,0.218666,0.079208,19968,8,3,1,0.089792,3,pass,0.575083;0.553167;0.713500 +random_masked_int64,52,312,8,frontier32_vertex,0.236000,0.194250,0.055250,19968,8,1,1,0.089792,3,pass,0.254083;0.236000;0.205541 +random_masked_int64,52,312,8,frontier32_simd,0.231542,0.199750,0.055292,19968,8,1,1,0.089792,3,pass,0.245708;0.221708;0.231542 +random_masked_int64,52,312,8,frontier32_gpu_dag,0.565250,0.222584,0.081208,19968,8,3,1,0.089792,3,pass,0.607084;0.543250;0.565250 +random_masked_int64,52,312,8,bucket32_d4,0.274584,0.236750,0.054500,19968,8,1,1,0.089792,3,pass,0.274584;0.309834;0.267250 +random_masked_int64,52,312,8,bucket32_d16,0.244959,0.211750,0.054500,19968,8,1,1,0.089792,3,pass,0.244959;0.343625;0.226541 +random_masked_int64,52,312,8,bucket32_d64,0.229708,0.197500,0.047875,19968,8,1,1,0.089792,3,pass,0.213291;0.245875;0.229708 +random_masked_reverse,55,330,8,old_pull_serial,0.338000,0.329666,0.072125,42240,16,2,0,0.082751,3,pass,0.317459;0.338000;0.355708 +random_masked_reverse,55,330,8,old_group_serial,0.169334,0.160708,0.028000,20130,10,1,0,0.082751,3,pass,0.176292;0.169334;0.167542 +random_masked_reverse,55,330,8,old_pull_parallel_dag,0.372500,0.337959,0.062667,42240,16,2,0,0.082751,3,pass,0.413708;0.344792;0.372500 +random_masked_reverse,55,330,8,old_group_parallel_dag,0.196875,0.169125,0.024583,20130,10,1,0,0.082751,3,pass,0.206500;0.196875;0.193250 +random_masked_reverse,55,330,8,pull64_barrier,0.346083,0.325542,0.070250,42240,16,2,0,0.082751,3,pass,0.388542;0.346083;0.334208 +random_masked_reverse,55,330,8,pull64_interleaved,0.415000,0.376500,0.071708,42240,16,2,0,0.082751,3,pass,0.341334;0.415000;0.416750 +random_masked_reverse,55,330,8,pull32_interleaved,0.405333,0.352750,0.066125,42240,16,2,0,0.082751,3,pass,0.380375;0.405333;0.424959 +random_masked_reverse,55,330,8,pull32_gpu_dag,0.734834,0.375000,0.080750,42240,16,4,0,0.082751,3,pass,0.734834;0.758000;0.605875 +random_masked_reverse,55,330,8,frontier32_vertex,0.431750,0.409208,0.162250,3691,16,2,0,0.082751,3,pass,0.431750;0.427458;0.671500 +random_masked_reverse,55,330,8,frontier32_simd,0.458458,0.428500,0.120208,3691,16,2,0,0.082751,3,pass,0.432041;0.458458;0.473417 +random_masked_reverse,55,330,8,frontier32_gpu_dag,0.739958,0.433042,0.141708,3691,16,4,0,0.082751,3,pass,0.736334;0.961208;0.739958 +random_masked_reverse,55,330,8,bucket32_d4,1.017375,0.993458,0.364375,2455,32,4,0,0.082751,3,pass,0.925125;1.071250;1.017375 +random_masked_reverse,55,330,8,bucket32_d16,0.769625,0.744958,0.284083,2603,24,3,0,0.082751,3,pass,0.842375;0.769625;0.766042 +random_masked_reverse,55,330,8,bucket32_d64,0.488208,0.452667,0.167083,3605,16,2,0,0.082751,3,pass,0.490125;0.477292;0.488208 +random_masked_int64,58,348,8,old_pull_serial,0.186084,0.176958,0.033542,22272,8,1,0,0.072333,3,pass,0.190292;0.174250;0.186084 +random_masked_int64,58,348,8,old_group_serial,0.157625,0.148708,0.015125,13920,5,1,0,0.072333,3,pass,0.157917;0.148042;0.157625 +random_masked_int64,58,348,8,old_pull_parallel_dag,0.212583,0.181000,0.033375,22272,8,1,0,0.072333,3,pass,0.213917;0.209500;0.212583 +random_masked_int64,58,348,8,old_group_parallel_dag,0.189875,0.154458,0.014375,13920,5,1,0,0.072333,3,pass,0.191875;0.189875;0.188333 +random_masked_int64,58,348,8,pull64_barrier,0.226833,0.202958,0.031875,22272,8,1,0,0.072333,3,pass,0.246250;0.226833;0.221792 +random_masked_int64,58,348,8,pull64_interleaved,0.213041,0.177209,0.026792,22272,8,1,0,0.072333,3,pass,0.213041;0.217834;0.200459 +random_masked_int64,58,348,8,pull32_interleaved,0.200709,0.168250,0.027750,22272,8,1,1,0.072333,3,pass,0.200709;0.182541;0.231917 +random_masked_int64,58,348,8,pull32_gpu_dag,0.526250,0.199792,0.040250,22272,8,3,1,0.072333,3,pass,0.526250;0.513500;0.537750 +random_masked_int64,58,348,8,frontier32_vertex,0.257041,0.224708,0.031792,22272,8,1,1,0.072333,3,pass,0.253250;0.403083;0.257041 +random_masked_int64,58,348,8,frontier32_simd,0.213667,0.187792,0.027917,22272,8,1,1,0.072333,3,pass,0.222208;0.213667;0.197166 +random_masked_int64,58,348,8,frontier32_gpu_dag,0.481458,0.177333,0.041917,22272,8,3,1,0.072333,3,pass,0.487875;0.465292;0.481458 +random_masked_int64,58,348,8,bucket32_d4,0.295167,0.220041,0.026875,22272,8,1,1,0.072333,3,pass,0.184125;0.295167;0.303708 +random_masked_int64,58,348,8,bucket32_d16,0.229375,0.204917,0.030375,22272,8,1,1,0.072333,3,pass,0.228000;0.242292;0.229375 +random_masked_int64,58,348,8,bucket32_d64,0.200666,0.176000,0.026750,22272,8,1,1,0.072333,3,pass,0.218250;0.200666;0.199292 +random_masked,61,366,8,old_pull_serial,0.310042,0.300292,0.062833,46848,16,2,0,0.073625,3,pass,0.313791;0.309125;0.310042 +random_masked,61,366,8,old_group_serial,0.150208,0.140417,0.024625,23424,9,1,0,0.073625,3,pass,0.150208;0.148459;0.150875 +random_masked,61,366,8,old_pull_parallel_dag,0.322833,0.293125,0.062792,46848,16,2,0,0.073625,3,pass,0.328042;0.322833;0.313875 +random_masked,61,366,8,old_group_parallel_dag,0.171500,0.134458,0.024500,23424,9,1,0,0.073625,3,pass,0.177917;0.171500;0.163208 +random_masked,61,366,8,pull64_barrier,0.358458,0.323834,0.059333,46848,16,2,0,0.073625,3,pass,0.358667;0.351625;0.358458 +random_masked,61,366,8,pull64_interleaved,0.379750,0.353000,0.059208,46848,16,2,0,0.073625,3,pass,0.348709;0.379750;0.465916 +random_masked,61,366,8,pull32_interleaved,0.335250,0.308541,0.053625,46848,16,2,0,0.073625,3,pass,0.381041;0.330875;0.335250 +random_masked,61,366,8,pull32_gpu_dag,0.624791,0.326000,0.066625,46848,16,4,0,0.073625,3,pass,0.640166;0.619250;0.624791 +random_masked,61,366,8,frontier32_vertex,0.449708,0.419250,0.120375,4776,16,2,0,0.073625,3,pass,0.423417;0.489625;0.449708 +random_masked,61,366,8,frontier32_simd,0.393417,0.365250,0.089542,4776,16,2,0,0.073625,3,pass,0.509167;0.391625;0.393417 +random_masked,61,366,8,frontier32_gpu_dag,0.645000,0.351333,0.103791,4776,16,4,0,0.073625,3,pass,0.630083;0.659083;0.645000 +random_masked,61,366,8,bucket32_d4,1.162167,1.124208,0.384250,2760,40,5,0,0.073625,3,pass,1.162167;1.262625;1.139458 +random_masked,61,366,8,bucket32_d16,0.787250,0.722958,0.258000,2952,24,3,0,0.073625,3,pass,0.778125;0.842833;0.787250 +random_masked,61,366,8,bucket32_d64,0.569916,0.544083,0.182708,4596,16,2,0,0.073625,3,pass,0.532041;0.579167;0.569916 +random_masked_int64_reverse,64,384,8,old_pull_serial,0.166875,0.154833,0.024000,24576,8,1,0,0.073876,3,pass,0.160750;0.168750;0.166875 +random_masked_int64_reverse,64,384,8,old_group_serial,0.143667,0.133167,0.010917,13440,5,1,0,0.073876,3,pass,0.132459;0.143667;0.160542 +random_masked_int64_reverse,64,384,8,old_pull_parallel_dag,0.195500,0.166708,0.025875,24576,8,1,0,0.073876,3,pass,0.195500;0.202250;0.182875 +random_masked_int64_reverse,64,384,8,old_group_parallel_dag,0.197833,0.165125,0.010875,13440,5,1,0,0.073876,3,pass,0.207542;0.197833;0.190083 +random_masked_int64_reverse,64,384,8,pull64_barrier,0.197875,0.171750,0.022333,24576,8,1,0,0.073876,3,pass,0.190333;0.197875;0.244042 +random_masked_int64_reverse,64,384,8,pull64_interleaved,0.210333,0.168459,0.023500,24576,8,1,0,0.073876,3,pass,0.195041;0.229458;0.210333 +random_masked_int64_reverse,64,384,8,pull32_interleaved,0.197958,0.161917,0.023250,24576,8,1,1,0.073876,3,pass,0.197958;0.244083;0.178875 +random_masked_int64_reverse,64,384,8,pull32_gpu_dag,0.470333,0.161750,0.036292,24576,8,3,1,0.073876,3,pass,0.434792;0.470333;0.542959 +random_masked_int64_reverse,64,384,8,frontier32_vertex,0.222916,0.183333,0.022167,24576,8,1,1,0.073876,3,pass,0.210125;0.222916;0.240000 +random_masked_int64_reverse,64,384,8,frontier32_simd,0.227083,0.192000,0.026750,24576,8,1,1,0.073876,3,pass,0.227083;0.206833;0.236125 +random_masked_int64_reverse,64,384,8,frontier32_gpu_dag,0.524542,0.194917,0.041250,24576,8,3,1,0.073876,3,pass,0.537542;0.524542;0.522500 +random_masked_int64_reverse,64,384,8,bucket32_d4,0.219417,0.188417,0.026792,24576,8,1,1,0.073876,3,pass,0.219709;0.209292;0.219417 +random_masked_int64_reverse,64,384,8,bucket32_d16,0.205000,0.173625,0.023542,24576,8,1,1,0.073876,3,pass,0.205958;0.188167;0.205000 +random_masked_int64_reverse,64,384,8,bucket32_d64,0.224459,0.186917,0.024042,24576,8,1,1,0.073876,3,pass,0.224459;0.237625;0.203416 +random_masked,67,402,8,old_pull_serial,0.183167,0.171459,0.031000,25728,8,1,0,0.070917,3,pass,0.183167;0.187583;0.149917 +random_masked,67,402,8,old_group_serial,0.163500,0.152916,0.019458,24522,8,1,0,0.070917,3,pass,0.169500;0.160041;0.163500 +random_masked,67,402,8,old_pull_parallel_dag,0.199125,0.163417,0.028625,25728,8,1,0,0.070917,3,pass,0.224500;0.193625;0.199125 +random_masked,67,402,8,old_group_parallel_dag,0.186667,0.147834,0.019375,24522,8,1,0,0.070917,3,pass,0.186667;0.197125;0.172125 +random_masked,67,402,8,pull64_barrier,0.198917,0.174375,0.028000,25728,8,1,0,0.070917,3,pass,0.191625;0.198917;0.212833 +random_masked,67,402,8,pull64_interleaved,0.232125,0.185708,0.028458,25728,8,1,0,0.070917,3,pass,0.232125;0.275166;0.208959 +random_masked,67,402,8,pull32_interleaved,0.204667,0.174459,0.025583,25728,8,1,0,0.070917,3,pass,0.204667;0.213750;0.193791 +random_masked,67,402,8,pull32_gpu_dag,0.524541,0.201084,0.042500,25728,8,3,0,0.070917,3,pass,0.495500;0.524541;0.547167 +random_masked,67,402,8,frontier32_vertex,0.300584,0.270209,0.085750,5034,8,1,0,0.070917,3,pass,0.279500;0.300584;0.315542 +random_masked,67,402,8,frontier32_simd,0.254167,0.222250,0.057750,5004,8,1,0,0.070917,3,pass,0.214041;0.262958;0.254167 +random_masked,67,402,8,frontier32_gpu_dag,0.585250,0.250708,0.073500,5004,8,3,0,0.070917,3,pass,0.631083;0.585250;0.584417 +random_masked,67,402,8,bucket32_d4,0.964708,0.943833,0.351208,3120,32,4,0,0.070917,3,pass,0.964708;1.042791;0.926875 +random_masked,67,402,8,bucket32_d16,0.701542,0.673792,0.229458,3360,24,3,0,0.070917,3,pass,0.640625;0.701542;0.830541 +random_masked,67,402,8,bucket32_d64,0.527750,0.500917,0.165750,4908,16,2,0,0.070917,3,pass,0.527750;0.535917;0.492334 +random_masked_int64,70,420,8,old_pull_serial,0.163584,0.150708,0.031875,26880,8,1,0,0.089500,3,pass,0.180000;0.163584;0.157584 +random_masked_int64,70,420,8,old_group_serial,0.162792,0.151000,0.017500,15960,6,1,0,0.089500,3,pass,0.163125;0.162792;0.162417 +random_masked_int64,70,420,8,old_pull_parallel_dag,0.171458,0.148125,0.030958,26880,8,1,0,0.089500,3,pass,0.194000;0.171458;0.168500 +random_masked_int64,70,420,8,old_group_parallel_dag,0.167375,0.141542,0.017333,15960,6,1,0,0.089500,3,pass,0.167375;0.164500;0.169584 +random_masked_int64,70,420,8,pull64_barrier,0.247750,0.208084,0.033500,26880,8,1,0,0.089500,3,pass,0.247750;0.268042;0.236500 +random_masked_int64,70,420,8,pull64_interleaved,0.273250,0.241708,0.033458,26880,8,1,0,0.089500,3,pass,0.235541;0.282666;0.273250 +random_masked_int64,70,420,8,pull32_interleaved,0.241916,0.210000,0.033333,26880,8,1,1,0.089500,3,pass,0.234667;0.248334;0.241916 +random_masked_int64,70,420,8,pull32_gpu_dag,0.480542,0.172791,0.044000,26880,8,3,1,0.089500,3,pass,0.473417;0.480542;0.484875 +random_masked_int64,70,420,8,frontier32_vertex,0.243625,0.210542,0.033250,26880,8,1,1,0.089500,3,pass,0.220084;0.243625;0.263000 +random_masked_int64,70,420,8,frontier32_simd,0.219750,0.186459,0.030250,26880,8,1,1,0.089500,3,pass,0.265709;0.219750;0.198250 +random_masked_int64,70,420,8,frontier32_gpu_dag,0.506583,0.176333,0.045000,26880,8,3,1,0.089500,3,pass,0.506583;0.680959;0.472792 +random_masked_int64,70,420,8,bucket32_d4,0.243417,0.209584,0.029958,26880,8,1,1,0.089500,3,pass,0.243417;0.216875;0.244250 +random_masked_int64,70,420,8,bucket32_d16,0.198583,0.181292,0.031042,26880,8,1,1,0.089500,3,pass,0.207375;0.197958;0.198583 +random_masked_int64,70,420,8,bucket32_d64,0.218833,0.186375,0.031000,26880,8,1,1,0.089500,3,pass,0.218833;0.184583;0.227958 +random_masked_reverse,73,438,8,old_pull_serial,0.353750,0.341459,0.049209,56064,16,2,0,0.079167,3,pass,0.334792;0.494625;0.353750 +random_masked_reverse,73,438,8,old_group_serial,0.164125,0.153167,0.016917,30222,10,1,0,0.079167,3,pass,0.164125;0.169250;0.141750 +random_masked_reverse,73,438,8,old_pull_parallel_dag,0.366125,0.336333,0.054167,56064,16,2,0,0.079167,3,pass,0.320625;0.372000;0.366125 +random_masked_reverse,73,438,8,old_group_parallel_dag,0.186167,0.149833,0.017000,30222,10,1,0,0.079167,3,pass,0.196000;0.186167;0.170000 +random_masked_reverse,73,438,8,pull64_barrier,0.349334,0.315625,0.050958,56064,16,2,0,0.079167,3,pass,0.349334;0.371750;0.330417 +random_masked_reverse,73,438,8,pull64_interleaved,0.416208,0.388333,0.053083,56064,16,2,0,0.079167,3,pass,0.417041;0.416208;0.370042 +random_masked_reverse,73,438,8,pull32_interleaved,0.332625,0.313167,0.046292,56064,16,2,0,0.079167,3,pass,0.332625;0.380083;0.331584 +random_masked_reverse,73,438,8,pull32_gpu_dag,0.607125,0.322291,0.059750,56064,16,4,0,0.079167,3,pass,0.662083;0.607125;0.600292 +random_masked_reverse,73,438,8,frontier32_vertex,0.536875,0.491708,0.140375,5335,16,2,0,0.079167,3,pass,0.435709;0.544209;0.536875 +random_masked_reverse,73,438,8,frontier32_simd,0.399875,0.367125,0.093417,5335,16,2,0,0.079167,3,pass,0.417625;0.399875;0.374584 +random_masked_reverse,73,438,8,frontier32_gpu_dag,0.691875,0.401375,0.122375,5335,16,4,0,0.079167,3,pass,0.773583;0.691875;0.684083 +random_masked_reverse,73,438,8,bucket32_d4,0.993583,0.963916,0.359833,3179,32,4,0,0.079167,3,pass,0.953958;1.084750;0.993583 +random_masked_reverse,73,438,8,bucket32_d16,0.700041,0.663333,0.241959,3402,24,3,0,0.079167,3,pass,0.694917;0.700041;0.735375 +random_masked_reverse,73,438,8,bucket32_d64,0.539166,0.510458,0.181750,4984,16,2,0,0.079167,3,pass,0.512000;0.539166;0.542250 +boundary_700000000,6,10,6,old_pull_serial,0.152792,0.151916,0.015792,360,6,1,0,0.054751,3,pass,0.145750;0.152792;0.156417 +boundary_700000000,6,10,6,old_group_serial,0.138625,0.137875,0.007125,160,5,1,0,0.054751,3,pass,0.138625;0.138750;0.136042 +boundary_700000000,6,10,6,old_pull_parallel_dag,0.187500,0.157584,0.015625,360,6,1,0,0.054751,3,pass,0.187500;0.197583;0.167875 +boundary_700000000,6,10,6,old_group_parallel_dag,0.151583,0.121458,0.007083,160,5,1,0,0.054751,3,pass,0.151583;0.139625;0.169125 +boundary_700000000,6,10,6,pull64_barrier,0.184625,0.154042,0.015334,360,6,1,0,0.054751,3,pass,0.184625;0.178167;0.186042 +boundary_700000000,6,10,6,pull64_interleaved,0.189209,0.159333,0.016083,360,6,1,0,0.054751,3,pass,0.196167;0.189209;0.158250 +boundary_700000000,6,10,6,pull32_interleaved,0.219166,0.182416,0.017333,360,6,1,0,0.054751,3,pass,0.219166;0.276250;0.218333 +boundary_700000000,6,10,6,pull32_gpu_dag,0.541500,0.188541,0.028417,360,6,3,0,0.054751,3,pass,0.514666;0.643125;0.541500 +boundary_700000000,6,10,6,frontier32_vertex,0.250125,0.224375,0.052750,24,8,1,0,0.054751,3,pass,0.250125;0.258792;0.241292 +boundary_700000000,6,10,6,frontier32_simd,0.221708,0.195667,0.045625,24,8,1,0,0.054751,3,pass,0.212667;0.221708;0.243708 +boundary_700000000,6,10,6,frontier32_gpu_dag,0.532167,0.232834,0.061667,24,8,3,0,0.054751,3,pass,0.653500;0.532167;0.525250 +boundary_700000000,6,10,6,bucket32_d4,0.293459,0.266959,0.086500,24,8,1,0,0.054751,3,pass,0.289375;0.293459;0.297000 +boundary_700000000,6,10,6,bucket32_d16,0.323750,0.289917,0.087583,24,8,1,0,0.054751,3,pass,0.299417;0.375250;0.323750 +boundary_700000000,6,10,6,bucket32_d64,0.254333,0.230333,0.071125,24,8,1,0,0.054751,3,pass,0.254333;0.283417;0.251959 +boundary_700000000_masked,6,10,6,old_pull_serial,0.124792,0.124250,0.013125,360,6,1,0,0.045292,3,pass,0.122000;0.124792;0.278875 +boundary_700000000_masked,6,10,6,old_group_serial,0.112750,0.112125,0.004875,80,2,1,0,0.045292,3,pass,0.109500;0.112750;0.113500 +boundary_700000000_masked,6,10,6,old_pull_parallel_dag,0.199625,0.166042,0.015417,360,6,1,0,0.045292,3,pass,0.199625;0.252958;0.197333 +boundary_700000000_masked,6,10,6,old_group_parallel_dag,0.175334,0.133792,0.005000,80,2,1,0,0.045292,3,pass,0.175334;0.179041;0.153834 +boundary_700000000_masked,6,10,6,pull64_barrier,0.219209,0.191416,0.018875,360,6,1,0,0.045292,3,pass,0.219209;0.204625;0.222500 +boundary_700000000_masked,6,10,6,pull64_interleaved,0.225750,0.189542,0.018792,360,6,1,0,0.045292,3,pass,0.244375;0.225750;0.214625 +boundary_700000000_masked,6,10,6,pull32_interleaved,0.216959,0.192125,0.017458,360,6,1,0,0.045292,3,pass,0.216959;0.203875;0.235125 +boundary_700000000_masked,6,10,6,pull32_gpu_dag,0.451458,0.157875,0.025000,360,6,3,0,0.045292,3,pass,0.451458;0.471209;0.438125 +boundary_700000000_masked,6,10,6,frontier32_vertex,0.264417,0.223584,0.051167,12,8,1,0,0.045292,3,pass,0.264417;0.269000;0.252000 +boundary_700000000_masked,6,10,6,frontier32_simd,0.247542,0.221250,0.049125,12,8,1,0,0.045292,3,pass,0.253834;0.247542;0.234625 +boundary_700000000_masked,6,10,6,frontier32_gpu_dag,0.555208,0.226250,0.060417,12,8,3,0,0.045292,3,pass,0.555208;0.564708;0.530958 +boundary_700000000_masked,6,10,6,bucket32_d4,0.290042,0.257416,0.076167,12,8,1,0,0.045292,3,pass,0.290042;0.301375;0.262833 +boundary_700000000_masked,6,10,6,bucket32_d16,0.283500,0.245375,0.081125,12,8,1,0,0.045292,3,pass,0.293917;0.283500;0.276709 +boundary_700000000_masked,6,10,6,bucket32_d64,0.258958,0.222125,0.072375,12,8,1,0,0.045292,3,pass,0.263625;0.258958;0.229209 +boundary_700000000_reverse,6,10,6,old_pull_serial,0.143708,0.142041,0.014792,360,6,1,0,0.076417,3,pass,0.145041;0.143708;0.135000 +boundary_700000000_reverse,6,10,6,old_group_serial,0.126375,0.125542,0.007250,170,5,1,0,0.076417,3,pass,0.120667;0.134209;0.126375 +boundary_700000000_reverse,6,10,6,old_pull_parallel_dag,0.196500,0.159708,0.015375,360,6,1,0,0.076417,3,pass,0.231667;0.189625;0.196500 +boundary_700000000_reverse,6,10,6,old_group_parallel_dag,0.166208,0.132709,0.007333,170,5,1,0,0.076417,3,pass,0.164292;0.168125;0.166208 +boundary_700000000_reverse,6,10,6,pull64_barrier,0.246166,0.217583,0.017875,360,6,1,0,0.076417,3,pass,0.246166;0.223709;0.378167 +boundary_700000000_reverse,6,10,6,pull64_interleaved,0.175291,0.138500,0.014750,360,6,1,0,0.076417,3,pass,0.175291;0.158209;0.179625 +boundary_700000000_reverse,6,10,6,pull32_interleaved,0.176000,0.151166,0.014750,360,6,1,0,0.076417,3,pass,0.164792;0.176000;0.199208 +boundary_700000000_reverse,6,10,6,pull32_gpu_dag,0.473250,0.161208,0.024334,360,6,3,0,0.076417,3,pass,0.453500;0.529333;0.473250 +boundary_700000000_reverse,6,10,6,frontier32_vertex,0.244417,0.205125,0.053750,24,8,1,0,0.076417,3,pass,0.228750;0.244417;0.257000 +boundary_700000000_reverse,6,10,6,frontier32_simd,0.226667,0.198792,0.044042,24,8,1,0,0.076417,3,pass,0.268875;0.226667;0.218209 +boundary_700000000_reverse,6,10,6,frontier32_gpu_dag,0.500625,0.202250,0.053417,24,8,3,0,0.076417,3,pass,0.641458;0.500625;0.485167 +boundary_700000000_reverse,6,10,6,bucket32_d4,0.240000,0.218208,0.070667,24,8,1,0,0.076417,3,pass,0.233708;0.243291;0.240000 +boundary_700000000_reverse,6,10,6,bucket32_d16,0.247750,0.214792,0.070625,24,8,1,0,0.076417,3,pass,0.303042;0.247750;0.223167 +boundary_700000000_reverse,6,10,6,bucket32_d64,0.284000,0.258334,0.084417,24,8,1,0,0.076417,3,pass,0.284000;0.295583;0.280750 +boundary_700000000_reverse_masked,6,10,6,old_pull_serial,0.132916,0.132292,0.013125,360,6,1,0,0.047751,3,pass,0.134042;0.128667;0.132916 +boundary_700000000_reverse_masked,6,10,6,old_group_serial,0.121541,0.120916,0.004792,90,2,1,0,0.047751,3,pass,0.121541;0.119292;0.124375 +boundary_700000000_reverse_masked,6,10,6,old_pull_parallel_dag,0.168125,0.138584,0.013250,360,6,1,0,0.047751,3,pass,0.168833;0.168125;0.167500 +boundary_700000000_reverse_masked,6,10,6,old_group_parallel_dag,0.141583,0.111166,0.004458,90,2,1,0,0.047751,3,pass,0.160375;0.138833;0.141583 +boundary_700000000_reverse_masked,6,10,6,pull64_barrier,0.187000,0.158958,0.014708,360,6,1,0,0.047751,3,pass,0.187000;0.173541;0.189250 +boundary_700000000_reverse_masked,6,10,6,pull64_interleaved,0.192166,0.166916,0.015625,360,6,1,0,0.047751,3,pass,0.192166;0.181792;0.203958 +boundary_700000000_reverse_masked,6,10,6,pull32_interleaved,0.225291,0.188458,0.014459,360,6,1,0,0.047751,3,pass,0.263292;0.225291;0.206083 +boundary_700000000_reverse_masked,6,10,6,pull32_gpu_dag,0.485625,0.171291,0.025000,360,6,3,0,0.047751,3,pass,0.469583;0.489458;0.485625 +boundary_700000000_reverse_masked,6,10,6,frontier32_vertex,0.234334,0.204625,0.042500,9,8,1,0,0.047751,3,pass,0.234334;0.221208;0.236292 +boundary_700000000_reverse_masked,6,10,6,frontier32_simd,0.231166,0.199542,0.041958,9,8,1,0,0.047751,3,pass,0.231166;0.192791;0.239542 +boundary_700000000_reverse_masked,6,10,6,frontier32_gpu_dag,0.504916,0.207875,0.051542,9,8,3,0,0.047751,3,pass,0.467459;0.504916;0.528000 +boundary_700000000_reverse_masked,6,10,6,bucket32_d4,0.276167,0.238000,0.070000,9,8,1,0,0.047751,3,pass,0.260375;0.326041;0.276167 +boundary_700000000_reverse_masked,6,10,6,bucket32_d16,0.274875,0.248708,0.072708,9,8,1,0,0.047751,3,pass,0.274875;0.273958;0.310167 +boundary_700000000_reverse_masked,6,10,6,bucket32_d64,0.293083,0.265250,0.082750,9,8,1,0,0.047751,3,pass,0.287000;0.323625;0.293083 +boundary_715827883,6,10,6,old_pull_serial,0.138666,0.137959,0.013250,360,6,1,0,0.040916,3,pass,0.141625;0.138666;0.129000 +boundary_715827883,6,10,6,old_group_serial,0.135083,0.134416,0.007250,160,5,1,0,0.040916,3,pass,0.129958;0.135083;0.136334 +boundary_715827883,6,10,6,old_pull_parallel_dag,0.179750,0.154292,0.015875,360,6,1,0,0.040916,3,pass,0.179750;0.179458;0.269333 +boundary_715827883,6,10,6,old_group_parallel_dag,0.162583,0.132250,0.007125,160,5,1,0,0.040916,3,pass,0.158625;0.163708;0.162583 +boundary_715827883,6,10,6,pull64_barrier,0.206000,0.172750,0.018625,360,6,1,0,0.040916,3,pass,0.206000;0.199083;0.206917 +boundary_715827883,6,10,6,pull64_interleaved,0.175583,0.148791,0.014625,360,6,1,0,0.040916,3,pass,0.175583;0.176667;0.174500 +boundary_715827883,6,10,6,pull32_interleaved,0.213000,0.184167,0.016958,360,6,1,1,0.040916,3,pass,0.187083;0.213000;0.231541 +boundary_715827883,6,10,6,pull32_gpu_dag,0.478041,0.166792,0.025458,360,6,3,1,0.040916,3,pass,0.450334;0.478041;0.480208 +boundary_715827883,6,10,6,frontier32_vertex,0.205750,0.181292,0.015625,360,6,1,1,0.040916,3,pass,0.203667;0.233000;0.205750 +boundary_715827883,6,10,6,frontier32_simd,0.223875,0.177625,0.015375,360,6,1,1,0.040916,3,pass,0.190459;0.290500;0.223875 +boundary_715827883,6,10,6,frontier32_gpu_dag,0.444916,0.157208,0.025250,360,6,3,1,0.040916,3,pass,0.467583;0.444916;0.413292 +boundary_715827883,6,10,6,bucket32_d4,0.196333,0.172958,0.016125,360,6,1,1,0.040916,3,pass,0.184209;0.196333;0.215666 +boundary_715827883,6,10,6,bucket32_d16,0.242209,0.208958,0.018667,360,6,1,1,0.040916,3,pass,0.211667;0.299083;0.242209 +boundary_715827883,6,10,6,bucket32_d64,0.224458,0.195459,0.018375,360,6,1,1,0.040916,3,pass,0.210750;0.236125;0.224458 +boundary_715827883_masked,6,10,6,old_pull_serial,0.151083,0.150542,0.015625,360,6,1,0,0.050708,3,pass,0.148667;0.151083;0.152375 +boundary_715827883_masked,6,10,6,old_group_serial,0.115209,0.114500,0.004500,80,2,1,0,0.050708,3,pass,0.110166;0.115833;0.115209 +boundary_715827883_masked,6,10,6,old_pull_parallel_dag,0.161250,0.135084,0.012375,360,6,1,0,0.050708,3,pass,0.157542;0.161250;0.235291 +boundary_715827883_masked,6,10,6,old_group_parallel_dag,0.151542,0.117459,0.004583,80,2,1,0,0.050708,3,pass,0.151542;0.146416;0.166083 +boundary_715827883_masked,6,10,6,pull64_barrier,0.176667,0.157250,0.015167,360,6,1,0,0.050708,3,pass,0.170500;0.176667;0.180958 +boundary_715827883_masked,6,10,6,pull64_interleaved,0.197708,0.169916,0.018750,360,6,1,0,0.050708,3,pass,0.181917;0.371958;0.197708 +boundary_715827883_masked,6,10,6,pull32_interleaved,0.184625,0.165792,0.016000,360,6,1,1,0.050708,3,pass,0.202458;0.184625;0.152500 +boundary_715827883_masked,6,10,6,pull32_gpu_dag,0.514959,0.175000,0.027000,360,6,3,1,0.050708,3,pass,0.543917;0.514959;0.500959 +boundary_715827883_masked,6,10,6,frontier32_vertex,0.220292,0.190708,0.018667,360,6,1,1,0.050708,3,pass,0.220292;0.219792;0.224542 +boundary_715827883_masked,6,10,6,frontier32_simd,0.208333,0.178292,0.016875,360,6,1,1,0.050708,3,pass,0.208333;0.200000;0.220625 +boundary_715827883_masked,6,10,6,frontier32_gpu_dag,0.477083,0.166209,0.025792,360,6,3,1,0.050708,3,pass,0.452125;0.477083;0.483458 +boundary_715827883_masked,6,10,6,bucket32_d4,0.199750,0.170875,0.014625,360,6,1,1,0.050708,3,pass,0.207709;0.199750;0.194875 +boundary_715827883_masked,6,10,6,bucket32_d16,0.203542,0.176209,0.018458,360,6,1,1,0.050708,3,pass,0.203542;0.215333;0.194583 +boundary_715827883_masked,6,10,6,bucket32_d64,0.214750,0.187459,0.018708,360,6,1,1,0.050708,3,pass,0.214750;0.271042;0.200792 +boundary_715827883_reverse,6,10,6,old_pull_serial,0.142375,0.141583,0.015625,360,6,1,0,0.064542,3,pass,0.142375;0.141959;0.143292 +boundary_715827883_reverse,6,10,6,old_group_serial,0.131792,0.131083,0.007333,170,5,1,0,0.064542,3,pass,0.131875;0.124625;0.131792 +boundary_715827883_reverse,6,10,6,old_pull_parallel_dag,0.171792,0.147708,0.015375,360,6,1,0,0.064542,3,pass,0.171083;0.171792;0.212459 +boundary_715827883_reverse,6,10,6,old_group_parallel_dag,0.138209,0.110458,0.007375,170,5,1,0,0.064542,3,pass,0.138209;0.136042;0.163542 +boundary_715827883_reverse,6,10,6,pull64_barrier,0.197583,0.172958,0.018250,360,6,1,0,0.064542,3,pass,0.197583;0.222125;0.194500 +boundary_715827883_reverse,6,10,6,pull64_interleaved,0.165458,0.147709,0.014417,360,6,1,0,0.064542,3,pass,0.162375;0.165458;0.167875 +boundary_715827883_reverse,6,10,6,pull32_interleaved,0.198666,0.168375,0.014833,360,6,1,1,0.064542,3,pass,0.165500;0.198666;0.215500 +boundary_715827883_reverse,6,10,6,pull32_gpu_dag,0.467417,0.169875,0.025167,360,6,3,1,0.064542,3,pass,0.484209;0.463083;0.467417 +boundary_715827883_reverse,6,10,6,frontier32_vertex,0.191292,0.166917,0.015000,360,6,1,1,0.064542,3,pass,0.186208;0.191292;0.258750 +boundary_715827883_reverse,6,10,6,frontier32_simd,0.211083,0.182709,0.014833,360,6,1,1,0.064542,3,pass,0.188125;0.211083;0.254250 +boundary_715827883_reverse,6,10,6,frontier32_gpu_dag,0.491833,0.177916,0.030208,360,6,3,1,0.064542,3,pass,0.492708;0.471250;0.491833 +boundary_715827883_reverse,6,10,6,bucket32_d4,0.214209,0.183084,0.018250,360,6,1,1,0.064542,3,pass,0.220083;0.214209;0.213000 +boundary_715827883_reverse,6,10,6,bucket32_d16,0.198083,0.168416,0.015750,360,6,1,1,0.064542,3,pass,0.192959;0.201250;0.198083 +boundary_715827883_reverse,6,10,6,bucket32_d64,0.207708,0.171250,0.014625,360,6,1,1,0.064542,3,pass,0.169041;0.213625;0.207708 +boundary_715827883_reverse_masked,6,10,6,old_pull_serial,0.146167,0.145500,0.015542,360,6,1,0,0.050874,3,pass,0.146167;0.151125;0.144083 +boundary_715827883_reverse_masked,6,10,6,old_group_serial,0.121125,0.120500,0.004625,90,2,1,0,0.050874,3,pass,0.113875;0.125375;0.121125 +boundary_715827883_reverse_masked,6,10,6,old_pull_parallel_dag,0.178167,0.142541,0.015375,360,6,1,0,0.050874,3,pass,0.192833;0.178167;0.162709 +boundary_715827883_reverse_masked,6,10,6,old_group_parallel_dag,0.179375,0.116500,0.004750,90,2,1,0,0.050874,3,pass,0.260584;0.147875;0.179375 +boundary_715827883_reverse_masked,6,10,6,pull64_barrier,0.191292,0.164500,0.014750,360,6,1,0,0.050874,3,pass,0.188666;0.193417;0.191292 +boundary_715827883_reverse_masked,6,10,6,pull64_interleaved,0.185625,0.155208,0.014917,360,6,1,0,0.050874,3,pass,0.185625;0.185625;0.199875 +boundary_715827883_reverse_masked,6,10,6,pull32_interleaved,0.205125,0.184083,0.014708,360,6,1,1,0.050874,3,pass,0.205125;0.218167;0.152416 +boundary_715827883_reverse_masked,6,10,6,pull32_gpu_dag,0.456500,0.166667,0.025708,360,6,3,1,0.050874,3,pass,0.448250;0.456500;0.458416 +boundary_715827883_reverse_masked,6,10,6,frontier32_vertex,0.224834,0.192542,0.015500,360,6,1,1,0.050874,3,pass,0.196542;0.224834;0.225916 +boundary_715827883_reverse_masked,6,10,6,frontier32_simd,0.240625,0.216833,0.017708,360,6,1,1,0.050874,3,pass,0.266959;0.216208;0.240625 +boundary_715827883_reverse_masked,6,10,6,frontier32_gpu_dag,0.453500,0.159958,0.024583,360,6,3,1,0.050874,3,pass,0.492083;0.453500;0.440208 +boundary_715827883_reverse_masked,6,10,6,bucket32_d4,0.214875,0.172750,0.014792,360,6,1,1,0.050874,3,pass,0.247000;0.193750;0.214875 +boundary_715827883_reverse_masked,6,10,6,bucket32_d16,0.187625,0.160917,0.015458,360,6,1,1,0.050874,3,pass,0.187625;0.181125;0.195459 +boundary_715827883_reverse_masked,6,10,6,bucket32_d64,0.197041,0.165458,0.014458,360,6,1,1,0.050874,3,pass,0.218791;0.189042;0.197041 +boundary_9007199254740993,6,10,6,old_pull_serial,0.151375,0.150709,0.015500,360,6,1,0,0.076292,3,pass,0.151708;0.151375;0.139125 +boundary_9007199254740993,6,10,6,old_group_serial,0.130667,0.130000,0.007292,160,5,1,0,0.076292,3,pass,0.133083;0.130667;0.128084 +boundary_9007199254740993,6,10,6,old_pull_parallel_dag,0.158459,0.127875,0.013000,360,6,1,0,0.076292,3,pass,0.174083;0.158459;0.155833 +boundary_9007199254740993,6,10,6,old_group_parallel_dag,0.153917,0.114500,0.007250,160,5,1,0,0.076292,3,pass,0.139083;0.153917;0.216042 +boundary_9007199254740993,6,10,6,pull64_barrier,0.212041,0.185541,0.018250,360,6,1,0,0.076292,3,pass,0.222208;0.212041;0.211666 +boundary_9007199254740993,6,10,6,pull64_interleaved,0.220791,0.200791,0.018500,360,6,1,0,0.076292,3,pass,0.213500;0.225792;0.220791 +boundary_9007199254740993,6,10,6,pull32_interleaved,0.217666,0.176209,0.018500,360,6,1,1,0.076292,3,pass,0.219917;0.217666;0.196792 +boundary_9007199254740993,6,10,6,pull32_gpu_dag,0.463208,0.164083,0.025750,360,6,3,1,0.076292,3,pass,0.441750;0.509791;0.463208 +boundary_9007199254740993,6,10,6,frontier32_vertex,0.201125,0.172583,0.015042,360,6,1,1,0.076292,3,pass,0.201125;0.204333;0.196791 +boundary_9007199254740993,6,10,6,frontier32_simd,0.214166,0.189625,0.018167,360,6,1,1,0.076292,3,pass,0.189208;0.214166;0.248125 +boundary_9007199254740993,6,10,6,frontier32_gpu_dag,0.478042,0.168875,0.025083,360,6,3,1,0.076292,3,pass,0.478042;0.488375;0.465625 +boundary_9007199254740993,6,10,6,bucket32_d4,0.173833,0.150083,0.015000,360,6,1,1,0.076292,3,pass,0.178250;0.165500;0.173833 +boundary_9007199254740993,6,10,6,bucket32_d16,0.195291,0.176625,0.015875,360,6,1,1,0.076292,3,pass,0.195291;0.169709;0.214875 +boundary_9007199254740993,6,10,6,bucket32_d64,0.214458,0.185625,0.018375,360,6,1,1,0.076292,3,pass,0.214958;0.214458;0.209167 +boundary_9007199254740993_masked,6,10,6,old_pull_serial,0.134875,0.133917,0.013500,360,6,1,0,0.047375,3,pass,0.135166;0.131916;0.134875 +boundary_9007199254740993_masked,6,10,6,old_group_serial,0.115042,0.114542,0.004500,80,2,1,0,0.047375,3,pass,0.116834;0.115042;0.114791 +boundary_9007199254740993_masked,6,10,6,old_pull_parallel_dag,0.170084,0.138917,0.013500,360,6,1,0,0.047375,3,pass,0.176333;0.167167;0.170084 +boundary_9007199254740993_masked,6,10,6,old_group_parallel_dag,0.145709,0.115500,0.004542,80,2,1,0,0.047375,3,pass,0.150375;0.139542;0.145709 +boundary_9007199254740993_masked,6,10,6,pull64_barrier,0.190417,0.166334,0.015000,360,6,1,0,0.047375,3,pass,0.184792;0.190417;0.223041 +boundary_9007199254740993_masked,6,10,6,pull64_interleaved,0.203709,0.175542,0.015750,360,6,1,0,0.047375,3,pass,0.285042;0.176916;0.203709 +boundary_9007199254740993_masked,6,10,6,pull32_interleaved,0.203958,0.167292,0.015750,360,6,1,1,0.047375,3,pass,0.197000;0.203958;0.214125 +boundary_9007199254740993_masked,6,10,6,pull32_gpu_dag,0.539333,0.189458,0.029250,360,6,3,1,0.047375,3,pass,0.608375;0.518625;0.539333 +boundary_9007199254740993_masked,6,10,6,frontier32_vertex,0.232208,0.197458,0.018208,360,6,1,1,0.047375,3,pass,0.221042;0.240625;0.232208 +boundary_9007199254740993_masked,6,10,6,frontier32_simd,0.233917,0.196458,0.018125,360,6,1,1,0.047375,3,pass,0.223083;0.240792;0.233917 +boundary_9007199254740993_masked,6,10,6,frontier32_gpu_dag,0.422375,0.155167,0.024625,360,6,3,1,0.047375,3,pass,0.490000;0.414500;0.422375 +boundary_9007199254740993_masked,6,10,6,bucket32_d4,0.208042,0.167500,0.015833,360,6,1,1,0.047375,3,pass,0.171542;0.251167;0.208042 +boundary_9007199254740993_masked,6,10,6,bucket32_d16,0.211583,0.184792,0.018250,360,6,1,1,0.047375,3,pass,0.207250;0.211583;0.235791 +boundary_9007199254740993_masked,6,10,6,bucket32_d64,0.208375,0.179584,0.015500,360,6,1,1,0.047375,3,pass,0.218709;0.184000;0.208375 +boundary_9007199254740993_reverse,6,10,6,old_pull_serial,0.154083,0.153375,0.015792,360,6,1,0,0.049749,3,pass,0.153750;0.155167;0.154083 +boundary_9007199254740993_reverse,6,10,6,old_group_serial,0.128625,0.127917,0.007000,170,5,1,0,0.049749,3,pass,0.126834;0.128625;0.135833 +boundary_9007199254740993_reverse,6,10,6,old_pull_parallel_dag,0.193166,0.157292,0.015750,360,6,1,0,0.049749,3,pass,0.174334;0.200000;0.193166 +boundary_9007199254740993_reverse,6,10,6,old_group_parallel_dag,0.188292,0.145041,0.007125,170,5,1,0,0.049749,3,pass,0.188292;0.173708;0.291250 +boundary_9007199254740993_reverse,6,10,6,pull64_barrier,0.170083,0.155208,0.015625,360,6,1,0,0.049749,3,pass,0.170083;0.167583;0.223333 +boundary_9007199254740993_reverse,6,10,6,pull64_interleaved,0.201416,0.168208,0.015750,360,6,1,0,0.049749,3,pass,0.202792;0.188833;0.201416 +boundary_9007199254740993_reverse,6,10,6,pull32_interleaved,0.215625,0.186917,0.014750,360,6,1,1,0.049749,3,pass,0.215625;0.282458;0.209250 +boundary_9007199254740993_reverse,6,10,6,pull32_gpu_dag,0.476417,0.157792,0.024708,360,6,3,1,0.049749,3,pass,0.510917;0.476417;0.447250 +boundary_9007199254740993_reverse,6,10,6,frontier32_vertex,0.199833,0.172042,0.014625,360,6,1,1,0.049749,3,pass,0.199833;0.199333;0.214375 +boundary_9007199254740993_reverse,6,10,6,frontier32_simd,0.214166,0.186291,0.017625,360,6,1,1,0.049749,3,pass,0.214166;0.226250;0.209666 +boundary_9007199254740993_reverse,6,10,6,frontier32_gpu_dag,0.489500,0.175208,0.028917,360,6,3,1,0.049749,3,pass,0.490166;0.489500;0.489458 +boundary_9007199254740993_reverse,6,10,6,bucket32_d4,0.221417,0.177333,0.017583,360,6,1,1,0.049749,3,pass,0.224625;0.221417;0.211750 +boundary_9007199254740993_reverse,6,10,6,bucket32_d16,0.195875,0.165959,0.015583,360,6,1,1,0.049749,3,pass,0.202792;0.195875;0.184833 +boundary_9007199254740993_reverse,6,10,6,bucket32_d64,0.203959,0.175333,0.015542,360,6,1,1,0.049749,3,pass,0.217291;0.203959;0.190542 +boundary_9007199254740993_reverse_masked,6,10,6,old_pull_serial,0.133000,0.132334,0.013000,360,6,1,0,0.041167,3,pass,0.133000;0.133125;0.128958 +boundary_9007199254740993_reverse_masked,6,10,6,old_group_serial,0.119083,0.118500,0.004750,90,2,1,0,0.041167,3,pass,0.119083;0.119792;0.114042 +boundary_9007199254740993_reverse_masked,6,10,6,old_pull_parallel_dag,0.159833,0.137375,0.013125,360,6,1,0,0.041167,3,pass,0.159833;0.146084;0.166167 +boundary_9007199254740993_reverse_masked,6,10,6,old_group_parallel_dag,0.142542,0.113667,0.004625,90,2,1,0,0.041167,3,pass,0.142542;0.134041;0.152000 +boundary_9007199254740993_reverse_masked,6,10,6,pull64_barrier,0.203000,0.176166,0.014958,360,6,1,0,0.041167,3,pass,0.203000;0.223417;0.194500 +boundary_9007199254740993_reverse_masked,6,10,6,pull64_interleaved,0.216167,0.192375,0.018458,360,6,1,0,0.041167,3,pass,0.216167;0.239167;0.214833 +boundary_9007199254740993_reverse_masked,6,10,6,pull32_interleaved,0.228000,0.199625,0.018500,360,6,1,1,0.041167,3,pass,0.212208;0.251917;0.228000 +boundary_9007199254740993_reverse_masked,6,10,6,pull32_gpu_dag,0.477958,0.185875,0.028208,360,6,3,1,0.041167,3,pass,0.513500;0.477958;0.449834 +boundary_9007199254740993_reverse_masked,6,10,6,frontier32_vertex,0.200500,0.164375,0.015625,360,6,1,1,0.041167,3,pass,0.200500;0.201750;0.197334 +boundary_9007199254740993_reverse_masked,6,10,6,frontier32_simd,0.206292,0.181375,0.015500,360,6,1,1,0.041167,3,pass,0.177125;0.209125;0.206292 +boundary_9007199254740993_reverse_masked,6,10,6,frontier32_gpu_dag,0.460708,0.166541,0.024458,360,6,3,1,0.041167,3,pass,0.446750;0.543625;0.460708 +boundary_9007199254740993_reverse_masked,6,10,6,bucket32_d4,0.198792,0.168667,0.015292,360,6,1,1,0.041167,3,pass,0.195500;0.385292;0.198792 +boundary_9007199254740993_reverse_masked,6,10,6,bucket32_d16,0.194750,0.169750,0.018125,360,6,1,1,0.041167,3,pass,0.194750;0.219708;0.190083 +boundary_9007199254740993_reverse_masked,6,10,6,bucket32_d64,0.185584,0.163667,0.015417,360,6,1,1,0.041167,3,pass,0.196542;0.185584;0.179292 diff --git a/dev/research/metal_pathfinding/optimization/results/correctness-sanitized-stderr.txt b/dev/research/metal_pathfinding/optimization/results/correctness-sanitized-stderr.txt new file mode 100644 index 0000000..d582a21 --- /dev/null +++ b/dev/research/metal_pathfinding/optimization/results/correctness-sanitized-stderr.txt @@ -0,0 +1,3 @@ +2026-09-27 00:31:08.125 optimized-sanitize[19832:38715213] Metal API Validation Enabled +2026-09-27 00:31:08.125 optimized-sanitize[19832:38715213] Metal GPU Validation Enabled +device=Apple M4 Max setup_ms=39.7833 execution_width=32 diff --git a/dev/research/metal_pathfinding/optimization/results/correctness-sanitized.csv b/dev/research/metal_pathfinding/optimization/results/correctness-sanitized.csv new file mode 100644 index 0000000..4837679 --- /dev/null +++ b/dev/research/metal_pathfinding/optimization/results/correctness-sanitized.csv @@ -0,0 +1,337 @@ +case,n,e,queries,method,wall_ms,distance_ms,gpu_ms,edge_visits,rounds,waits,fallback64,upload_ms,samples,correct,wall_samples_ms +random_masked_int64,40,240,8,old_pull_serial,1.305000,1.251917,0.388084,15360,8,1,0,0.187500,3,pass,1.305000;1.505917;1.293750 +random_masked_int64,40,240,8,old_group_serial,0.662375,0.612584,0.239000,9600,6,1,0,0.187500,3,pass,0.709584;0.649000;0.662375 +random_masked_int64,40,240,8,old_pull_parallel_dag,1.278583,1.221584,0.392333,15360,8,1,0,0.187500,3,pass,1.278583;1.620833;0.898625 +random_masked_int64,40,240,8,old_group_parallel_dag,0.944375,0.883166,0.242375,9600,6,1,0,0.187500,3,pass,0.684041;0.944375;0.968250 +random_masked_int64,40,240,8,pull64_barrier,0.858417,0.809750,0.387417,15360,8,1,0,0.187500,3,pass,0.840584;0.940000;0.858417 +random_masked_int64,40,240,8,pull64_interleaved,0.916834,0.887542,0.383708,15360,8,1,0,0.187500,3,pass,0.980791;0.914417;0.916834 +random_masked_int64,40,240,8,pull32_interleaved,0.893708,0.818250,0.384458,15360,8,1,1,0.187500,3,pass,0.893708;0.939958;0.780333 +random_masked_int64,40,240,8,pull32_gpu_dag,1.693708,0.810209,0.543750,15360,8,3,1,0.187500,3,pass,1.801291;1.693708;1.610209 +random_masked_int64,40,240,8,frontier32_vertex,0.870416,0.832084,0.388417,15360,8,1,1,0.187500,3,pass,0.866417;0.870416;1.194333 +random_masked_int64,40,240,8,frontier32_simd,0.861208,0.819958,0.387375,15360,8,1,1,0.187500,3,pass,0.861208;0.842833;0.864708 +random_masked_int64,40,240,8,frontier32_gpu_dag,1.861958,0.874417,0.545708,15360,8,3,1,0.187500,3,pass,1.861958;1.889208;1.675625 +random_masked_int64,40,240,8,bucket32_d4,0.833750,0.785333,0.387375,15360,8,1,1,0.187500,3,pass,0.830167;0.833750;0.892917 +random_masked_int64,40,240,8,bucket32_d16,0.863917,0.836792,0.387875,15360,8,1,1,0.187500,3,pass,0.863917;0.800167;1.445083 +random_masked_int64,40,240,8,bucket32_d64,0.807500,0.786333,0.388625,15360,8,1,1,0.187500,3,pass,0.807500;0.789000;0.919250 +random_masked,43,258,8,old_pull_serial,1.816417,1.765916,0.864583,33024,16,2,0,0.134667,3,pass,1.891250;1.752917;1.816417 +random_masked,43,258,8,old_group_serial,0.745500,0.697542,0.388875,14448,9,1,0,0.134667,3,pass,0.798208;0.745500;0.744750 +random_masked,43,258,8,old_pull_parallel_dag,1.871250,1.797750,0.864750,33024,16,2,0,0.134667,3,pass,1.871250;1.811917;1.984583 +random_masked,43,258,8,old_group_parallel_dag,0.810250,0.755792,0.389375,14448,9,1,0,0.134667,3,pass,0.793417;0.927500;0.810250 +random_masked,43,258,8,pull64_barrier,1.677125,1.634167,0.874458,33024,16,2,0,0.134667,3,pass,1.700375;1.677125;1.629541 +random_masked,43,258,8,pull64_interleaved,1.780833,1.706875,0.849500,33024,16,2,0,0.134667,3,pass,1.780833;2.399292;1.724625 +random_masked,43,258,8,pull32_interleaved,1.692917,1.629125,0.832417,33024,16,2,0,0.134667,3,pass,1.668875;1.946625;1.692917 +random_masked,43,258,8,pull32_gpu_dag,2.853875,1.804708,1.005667,33024,16,4,0,0.134667,3,pass,2.853875;2.712750;3.286375 +random_masked,43,258,8,frontier32_vertex,2.068750,2.032708,1.006875,3186,16,2,0,0.134667,3,pass,2.099875;2.068750;2.005750 +random_masked,43,258,8,frontier32_simd,1.752541,1.680541,0.715792,3186,16,2,0,0.134667,3,pass,1.767250;1.705959;1.752541 +random_masked,43,258,8,frontier32_gpu_dag,2.701125,1.739500,0.889792,3186,16,4,0,0.134667,3,pass,2.713208;2.701125;2.674958 +random_masked,43,258,8,bucket32_d4,5.472583,5.439167,2.785792,2016,32,4,0,0.134667,3,pass,5.472583;5.632459;5.401875 +random_masked,43,258,8,bucket32_d16,4.053875,4.000750,1.943625,2142,24,3,0,0.134667,3,pass,4.177917;4.053875;3.912167 +random_masked,43,258,8,bucket32_d64,2.552333,2.496084,1.264875,3096,16,2,0,0.134667,3,pass,2.517542;2.552333;2.737708 +random_masked_int64_reverse,46,276,8,old_pull_serial,0.725666,0.680958,0.277125,17664,8,1,0,0.114291,3,pass,0.725666;0.723708;0.774292 +random_masked_int64_reverse,46,276,8,old_group_serial,0.499333,0.453375,0.139292,9660,5,1,0,0.114291,3,pass,0.503500;0.499333;0.497209 +random_masked_int64_reverse,46,276,8,old_pull_parallel_dag,0.768667,0.727833,0.273125,17664,8,1,0,0.114291,3,pass,0.756125;0.768667;0.845458 +random_masked_int64_reverse,46,276,8,old_group_parallel_dag,0.537541,0.473708,0.139583,9660,5,1,0,0.114291,3,pass,0.488792;0.605750;0.537541 +random_masked_int64_reverse,46,276,8,pull64_barrier,0.699666,0.659833,0.279792,17664,8,1,0,0.114291,3,pass,0.690500;0.699666;0.770750 +random_masked_int64_reverse,46,276,8,pull64_interleaved,0.795000,0.759666,0.276500,17664,8,1,0,0.114291,3,pass,0.673833;0.795000;0.807875 +random_masked_int64_reverse,46,276,8,pull32_interleaved,0.701542,0.669667,0.277500,17664,8,1,1,0.114291,3,pass,0.738458;0.699833;0.701542 +random_masked_int64_reverse,46,276,8,pull32_gpu_dag,1.643583,0.757125,0.432958,17664,8,3,1,0.114291,3,pass,1.528334;1.643583;2.293166 +random_masked_int64_reverse,46,276,8,frontier32_vertex,0.812042,0.783500,0.278917,17664,8,1,1,0.114291,3,pass,0.789375;0.812042;0.827167 +random_masked_int64_reverse,46,276,8,frontier32_simd,0.686250,0.659958,0.278958,17664,8,1,1,0.114291,3,pass,0.769750;0.686250;0.677625 +random_masked_int64_reverse,46,276,8,frontier32_gpu_dag,1.673041,0.716709,0.444458,17664,8,3,1,0.114291,3,pass,1.672209;1.686333;1.673041 +random_masked_int64_reverse,46,276,8,bucket32_d4,0.763750,0.711875,0.279542,17664,8,1,1,0.114291,3,pass,0.850292;0.763750;0.711584 +random_masked_int64_reverse,46,276,8,bucket32_d16,0.714417,0.681666,0.279375,17664,8,1,1,0.114291,3,pass,0.730958;0.714417;0.696417 +random_masked_int64_reverse,46,276,8,bucket32_d64,0.819333,0.792500,0.287583,17664,8,1,1,0.114291,3,pass,0.708167;0.862708;0.819333 +random_masked,49,294,8,old_pull_serial,0.912166,0.849334,0.399792,18816,8,1,0,0.131500,3,pass,0.895625;0.912166;0.972667 +random_masked,49,294,8,old_group_serial,0.707958,0.650833,0.334708,14700,8,1,0,0.131500,3,pass,0.695959;0.707958;0.813875 +random_masked,49,294,8,old_pull_parallel_dag,0.953958,0.891208,0.400417,18816,8,1,0,0.131500,3,pass,0.953958;0.925708;0.999541 +random_masked,49,294,8,old_group_parallel_dag,0.732625,0.681541,0.336041,14700,8,1,0,0.131500,3,pass,0.840042;0.732625;0.710167 +random_masked,49,294,8,pull64_barrier,0.980833,0.928208,0.411917,18816,8,1,0,0.131500,3,pass,0.980833;1.019542;0.956458 +random_masked,49,294,8,pull64_interleaved,0.907834,0.873709,0.406750,18816,8,1,0,0.131500,3,pass,0.907834;0.824334;0.919709 +random_masked,49,294,8,pull32_interleaved,0.880542,0.835917,0.400792,18816,8,1,0,0.131500,3,pass,0.926958;0.865916;0.880542 +random_masked,49,294,8,pull32_gpu_dag,1.848041,0.831584,0.555000,18816,8,3,0,0.131500,3,pass,1.851708;1.848041;1.821375 +random_masked,49,294,8,frontier32_vertex,1.280584,1.250875,0.722167,3162,8,1,0,0.131500,3,pass,1.280584;1.279417;1.340833 +random_masked,49,294,8,frontier32_simd,1.044291,1.005875,0.445125,3162,8,1,0,0.131500,3,pass,1.044291;1.055583;1.007334 +random_masked,49,294,8,frontier32_gpu_dag,1.994708,1.010000,0.611417,3162,8,3,0,0.131500,3,pass,1.994708;1.904583;2.033125 +random_masked,49,294,8,bucket32_d4,6.611250,6.579000,3.411958,2022,40,5,0,0.131500,3,pass,6.611250;6.410583;6.744250 +random_masked,49,294,8,bucket32_d16,2.816417,2.782209,1.379792,2100,16,2,0,0.131500,3,pass,2.816417;2.825666;2.779209 +random_masked,49,294,8,bucket32_d64,2.587125,2.546291,1.261875,3042,16,2,0,0.131500,3,pass,2.662292;2.528083;2.587125 +random_masked_int64,52,312,8,old_pull_serial,1.008375,0.936208,0.431125,19968,8,1,0,0.130084,3,pass,0.977584;1.008375;1.090209 +random_masked_int64,52,312,8,old_group_serial,0.734125,0.678209,0.273083,12168,6,1,0,0.130084,3,pass,0.734125;0.675416;0.818375 +random_masked_int64,52,312,8,old_pull_parallel_dag,1.063833,0.981458,0.435875,19968,8,1,0,0.130084,3,pass,1.069209;1.063833;0.975292 +random_masked_int64,52,312,8,old_group_parallel_dag,0.686000,0.634333,0.273375,12168,6,1,0,0.130084,3,pass,0.686000;0.677208;0.706125 +random_masked_int64,52,312,8,pull64_barrier,0.988333,0.939583,0.442167,19968,8,1,0,0.130084,3,pass,1.042667;0.988333;0.958750 +random_masked_int64,52,312,8,pull64_interleaved,0.941458,0.907416,0.431375,19968,8,1,0,0.130084,3,pass,0.995000;0.941458;0.899333 +random_masked_int64,52,312,8,pull32_interleaved,0.905667,0.842833,0.432833,19968,8,1,1,0.130084,3,pass,0.884083;0.963625;0.905667 +random_masked_int64,52,312,8,pull32_gpu_dag,1.744917,0.859709,0.600709,19968,8,3,1,0.130084,3,pass,1.744917;1.952834;1.730417 +random_masked_int64,52,312,8,frontier32_vertex,0.942875,0.908416,0.443208,19968,8,1,1,0.130084,3,pass,1.126625;0.942875;0.903625 +random_masked_int64,52,312,8,frontier32_simd,0.930000,0.893125,0.444292,19968,8,1,1,0.130084,3,pass,1.035125;0.900375;0.930000 +random_masked_int64,52,312,8,frontier32_gpu_dag,1.817958,0.863041,0.621125,19968,8,3,1,0.130084,3,pass,1.817958;1.958042;1.713334 +random_masked_int64,52,312,8,bucket32_d4,1.009750,0.944959,0.444292,19968,8,1,1,0.130084,3,pass,1.009750;1.031416;0.967042 +random_masked_int64,52,312,8,bucket32_d16,0.990000,0.950875,0.441375,19968,8,1,1,0.130084,3,pass,0.946166;1.003458;0.990000 +random_masked_int64,52,312,8,bucket32_d64,0.956208,0.909084,0.444125,19968,8,1,1,0.130084,3,pass,0.956208;1.163417;0.916875 +random_masked_reverse,55,330,8,old_pull_serial,1.468792,1.411000,0.547750,42240,16,2,0,0.145874,3,pass,1.547333;1.468792;1.416917 +random_masked_reverse,55,330,8,old_group_serial,0.628292,0.555000,0.250792,20130,10,1,0,0.145874,3,pass,0.604167;0.628292;0.647167 +random_masked_reverse,55,330,8,old_pull_parallel_dag,1.589875,1.536666,0.563625,42240,16,2,0,0.145874,3,pass,1.558250;1.589875;1.648709 +random_masked_reverse,55,330,8,old_group_parallel_dag,0.655500,0.609875,0.254042,20130,10,1,0,0.145874,3,pass,0.655500;0.684291;0.620666 +random_masked_reverse,55,330,8,pull64_barrier,1.385209,1.349834,0.555958,42240,16,2,0,0.145874,3,pass,1.370375;1.420375;1.385209 +random_masked_reverse,55,330,8,pull64_interleaved,1.376791,1.336750,0.551458,42240,16,2,0,0.145874,3,pass,1.376791;1.485166;1.334750 +random_masked_reverse,55,330,8,pull32_interleaved,1.521625,1.473958,0.545167,42240,16,2,0,0.145874,3,pass,1.521625;1.556750;1.415291 +random_masked_reverse,55,330,8,pull32_gpu_dag,2.495833,1.471417,0.716917,42240,16,4,0,0.145874,3,pass,2.495833;2.549042;2.468584 +random_masked_reverse,55,330,8,frontier32_vertex,2.342125,2.304500,1.255875,3691,16,2,0,0.145874,3,pass,2.353792;2.315083;2.342125 +random_masked_reverse,55,330,8,frontier32_simd,1.787084,1.743208,0.743833,3691,16,2,0,0.145874,3,pass,1.787084;1.761209;2.490834 +random_masked_reverse,55,330,8,frontier32_gpu_dag,2.778750,1.799208,0.919250,3691,16,4,0,0.145874,3,pass,2.778750;2.952958;2.660834 +random_masked_reverse,55,330,8,bucket32_d4,5.850292,5.799500,2.949250,2455,32,4,0,0.145874,3,pass,5.722000;5.850292;6.357334 +random_masked_reverse,55,330,8,bucket32_d16,4.124625,4.079792,1.998667,2603,24,3,0,0.145874,3,pass,4.202209;3.872583;4.124625 +random_masked_reverse,55,330,8,bucket32_d64,2.865084,2.815584,1.337000,3605,16,2,0,0.145874,3,pass,2.865084;2.912375;2.795334 +random_masked_int64,58,348,8,old_pull_serial,0.872709,0.795709,0.367625,22272,8,1,0,0.140833,3,pass,0.872709;0.911750;0.861792 +random_masked_int64,58,348,8,old_group_serial,0.582042,0.518041,0.195208,13920,5,1,0,0.140833,3,pass,0.600833;0.582042;0.571458 +random_masked_int64,58,348,8,old_pull_parallel_dag,0.925708,0.859042,0.369625,22272,8,1,0,0.140833,3,pass,0.875667;0.925708;0.991000 +random_masked_int64,58,348,8,old_group_parallel_dag,0.591500,0.533333,0.195500,13920,5,1,0,0.140833,3,pass,0.570542;0.615000;0.591500 +random_masked_int64,58,348,8,pull64_barrier,0.888500,0.827500,0.373000,22272,8,1,0,0.140833,3,pass,0.888500;0.842500;0.918833 +random_masked_int64,58,348,8,pull64_interleaved,0.856625,0.803667,0.364000,22272,8,1,0,0.140833,3,pass,0.807459;0.856625;0.887834 +random_masked_int64,58,348,8,pull32_interleaved,0.867709,0.820791,0.365125,22272,8,1,1,0.140833,3,pass,0.867709;0.974041;0.866375 +random_masked_int64,58,348,8,pull32_gpu_dag,1.867583,0.887667,0.521750,22272,8,3,1,0.140833,3,pass,1.941917;1.784875;1.867583 +random_masked_int64,58,348,8,frontier32_vertex,0.856625,0.815334,0.371167,22272,8,1,1,0.140833,3,pass,0.856625;0.830417;0.954167 +random_masked_int64,58,348,8,frontier32_simd,0.849583,0.811958,0.373375,22272,8,1,1,0.140833,3,pass,0.831125;0.855291;0.849583 +random_masked_int64,58,348,8,frontier32_gpu_dag,1.659250,0.743042,0.533083,22272,8,3,1,0.140833,3,pass,1.560875;1.762667;1.659250 +random_masked_int64,58,348,8,bucket32_d4,0.899042,0.835083,0.373625,22272,8,1,1,0.140833,3,pass,0.966625;0.899042;0.873084 +random_masked_int64,58,348,8,bucket32_d16,0.910541,0.856459,0.373750,22272,8,1,1,0.140833,3,pass,0.910541;1.533667;0.883916 +random_masked_int64,58,348,8,bucket32_d64,0.893583,0.853333,0.372958,22272,8,1,1,0.140833,3,pass,0.803375;0.893583;0.899000 +random_masked,61,366,8,old_pull_serial,1.854125,1.769125,0.870042,46848,16,2,0,0.123125,3,pass,1.854125;1.937959;1.735333 +random_masked,61,366,8,old_group_serial,0.791958,0.719834,0.400583,23424,9,1,0,0.123125,3,pass,0.748750;0.791958;0.793584 +random_masked,61,366,8,old_pull_parallel_dag,1.979500,1.922542,0.870375,46848,16,2,0,0.123125,3,pass,1.889000;2.052833;1.979500 +random_masked,61,366,8,old_group_parallel_dag,0.820458,0.764166,0.425292,23424,9,1,0,0.123125,3,pass,0.820458;0.836709;0.781541 +random_masked,61,366,8,pull64_barrier,1.749375,1.692542,0.875958,46848,16,2,0,0.123125,3,pass,1.749375;1.930875;1.732417 +random_masked,61,366,8,pull64_interleaved,2.035125,1.985166,0.864833,46848,16,2,0,0.123125,3,pass,2.035125;2.042292;1.776708 +random_masked,61,366,8,pull32_interleaved,1.778542,1.701709,0.847667,46848,16,2,0,0.123125,3,pass,1.744000;1.778542;1.834250 +random_masked,61,366,8,pull32_gpu_dag,2.837875,1.714542,1.017125,46848,16,4,0,0.123125,3,pass,2.837875;2.750916;2.866750 +random_masked,61,366,8,frontier32_vertex,2.246167,2.191792,1.042292,4776,16,2,0,0.123125,3,pass,2.209041;2.247041;2.246167 +random_masked,61,366,8,frontier32_simd,1.770291,1.724917,0.722583,4776,16,2,0,0.123125,3,pass,1.730292;1.813792;1.770291 +random_masked,61,366,8,frontier32_gpu_dag,2.942834,1.920750,0.893500,4776,16,4,0,0.123125,3,pass,2.942834;3.091875;2.812417 +random_masked,61,366,8,bucket32_d4,6.850750,6.795292,3.736667,2760,40,5,0,0.123125,3,pass,7.512667;6.758334;6.850750 +random_masked,61,366,8,bucket32_d16,4.147667,4.106708,2.052875,2952,24,3,0,0.123125,3,pass,4.100166;4.667291;4.147667 +random_masked,61,366,8,bucket32_d64,2.798166,2.741958,1.319584,4596,16,2,0,0.123125,3,pass,2.756084;3.563709;2.798166 +random_masked_int64_reverse,64,384,8,old_pull_serial,0.886167,0.795042,0.279500,24576,8,1,0,0.147292,3,pass,0.886167;0.924708;0.759458 +random_masked_int64_reverse,64,384,8,old_group_serial,0.507208,0.449959,0.141625,13440,5,1,0,0.147292,3,pass,0.507208;0.502583;0.509542 +random_masked_int64_reverse,64,384,8,old_pull_parallel_dag,0.732416,0.688709,0.281375,24576,8,1,0,0.147292,3,pass,0.732416;1.318458;0.720583 +random_masked_int64_reverse,64,384,8,old_group_parallel_dag,0.466750,0.434750,0.142042,13440,5,1,0,0.147292,3,pass,0.491667;0.466750;0.456500 +random_masked_int64_reverse,64,384,8,pull64_barrier,0.677125,0.645208,0.289000,24576,8,1,0,0.147292,3,pass,0.678833;0.671916;0.677125 +random_masked_int64_reverse,64,384,8,pull64_interleaved,0.685625,0.651416,0.279750,24576,8,1,0,0.147292,3,pass,0.675625;0.718500;0.685625 +random_masked_int64_reverse,64,384,8,pull32_interleaved,0.719459,0.686375,0.279750,24576,8,1,1,0.147292,3,pass,0.718459;0.739583;0.719459 +random_masked_int64_reverse,64,384,8,pull32_gpu_dag,1.532500,0.645084,0.439208,24576,8,3,1,0.147292,3,pass,1.444958;1.578208;1.532500 +random_masked_int64_reverse,64,384,8,frontier32_vertex,1.130167,1.083291,0.283625,24576,8,1,1,0.147292,3,pass,0.664542;3.123333;1.130167 +random_masked_int64_reverse,64,384,8,frontier32_simd,0.741375,0.696458,0.286042,24576,8,1,1,0.147292,3,pass,0.741375;0.843708;0.697667 +random_masked_int64_reverse,64,384,8,frontier32_gpu_dag,1.513292,0.679583,0.447292,24576,8,3,1,0.147292,3,pass,1.513292;1.511542;4.620750 +random_masked_int64_reverse,64,384,8,bucket32_d4,0.714208,0.677750,0.282125,24576,8,1,1,0.147292,3,pass,0.689625;0.714208;1.098000 +random_masked_int64_reverse,64,384,8,bucket32_d16,0.723459,0.685500,0.281542,24576,8,1,1,0.147292,3,pass,0.718500;0.768875;0.723459 +random_masked_int64_reverse,64,384,8,bucket32_d64,0.729791,0.695958,0.284250,24576,8,1,1,0.147292,3,pass,0.796542;0.725416;0.729791 +random_masked,67,402,8,old_pull_serial,0.857292,0.785291,0.370417,25728,8,1,0,0.128293,3,pass,0.837916;0.857292;0.890875 +random_masked,67,402,8,old_group_serial,0.668833,0.594291,0.296083,24522,8,1,0,0.128293,3,pass,0.672292;0.664500;0.668833 +random_masked,67,402,8,old_pull_parallel_dag,0.928375,0.891000,0.373042,25728,8,1,0,0.128293,3,pass,0.888000;0.928375;0.974042 +random_masked,67,402,8,old_group_parallel_dag,0.723875,0.671833,0.297042,24522,8,1,0,0.128293,3,pass,0.723875;0.910833;0.642500 +random_masked,67,402,8,pull64_barrier,0.831834,0.788125,0.378083,25728,8,1,0,0.128293,3,pass,0.817416;0.855125;0.831834 +random_masked,67,402,8,pull64_interleaved,0.829583,0.785417,0.370458,25728,8,1,0,0.128293,3,pass,0.829583;0.820084;0.854083 +random_masked,67,402,8,pull32_interleaved,0.804083,0.767791,0.361458,25728,8,1,0,0.128293,3,pass,0.804083;0.839708;0.797292 +random_masked,67,402,8,pull32_gpu_dag,1.623708,0.745958,0.508833,25728,8,3,0,0.128293,3,pass,1.654500;1.565750;1.623708 +random_masked,67,402,8,frontier32_vertex,1.267000,1.217542,0.746125,5034,8,1,0,0.128293,3,pass,1.245000;1.289917;1.267000 +random_masked,67,402,8,frontier32_simd,1.016708,0.960041,0.448250,5034,8,1,0,0.128293,3,pass,1.627917;1.016708;1.000916 +random_masked,67,402,8,frontier32_gpu_dag,1.809334,0.957875,0.597875,5034,8,3,0,0.128293,3,pass,1.787542;1.809334;1.864500 +random_masked,67,402,8,bucket32_d4,5.585500,5.529125,2.872125,3120,32,4,0,0.128293,3,pass,5.370417;6.061667;5.585500 +random_masked,67,402,8,bucket32_d16,3.892917,3.851583,1.985375,3360,24,3,0,0.128293,3,pass,3.892917;4.481458;3.838959 +random_masked,67,402,8,bucket32_d64,2.534042,2.490375,1.256000,4914,16,2,0,0.128293,3,pass,2.534042;2.637875;2.526750 +random_masked_int64,70,420,8,old_pull_serial,0.912250,0.837084,0.427291,26880,8,1,0,0.124334,3,pass,0.898458;0.912250;0.922583 +random_masked_int64,70,420,8,old_group_serial,0.656833,0.587292,0.267500,15960,6,1,0,0.124334,3,pass,0.656833;0.635209;0.685292 +random_masked_int64,70,420,8,old_pull_parallel_dag,1.011333,0.946708,0.429375,26880,8,1,0,0.124334,3,pass,1.072625;1.011333;0.990667 +random_masked_int64,70,420,8,old_group_parallel_dag,0.727625,0.678417,0.267084,15960,6,1,0,0.124334,3,pass,0.691584;0.727625;0.745875 +random_masked_int64,70,420,8,pull64_barrier,1.078958,1.021458,0.458000,26880,8,1,0,0.124334,3,pass,1.012542;1.103167;1.078958 +random_masked_int64,70,420,8,pull64_interleaved,0.923167,0.876958,0.438125,26880,8,1,0,0.124334,3,pass,1.001875;0.923167;0.846208 +random_masked_int64,70,420,8,pull32_interleaved,1.027959,0.985125,0.443792,26880,8,1,1,0.124334,3,pass,0.960584;1.518167;1.027959 +random_masked_int64,70,420,8,pull32_gpu_dag,1.744000,0.867250,0.607000,26880,8,3,1,0.124334,3,pass,1.803875;1.744000;1.733875 +random_masked_int64,70,420,8,frontier32_vertex,0.913333,0.869584,0.444000,26880,8,1,1,0.124334,3,pass,0.849500;0.913333;1.494042 +random_masked_int64,70,420,8,frontier32_simd,1.054834,1.027084,0.473750,26880,8,1,1,0.124334,3,pass,1.054834;1.143834;0.988292 +random_masked_int64,70,420,8,frontier32_gpu_dag,1.867833,0.975291,0.639917,26880,8,3,1,0.124334,3,pass,1.995833;1.805875;1.867833 +random_masked_int64,70,420,8,bucket32_d4,0.923167,0.887625,0.468917,26880,8,1,1,0.124334,3,pass,0.840583;1.055541;0.923167 +random_masked_int64,70,420,8,bucket32_d16,0.996375,0.960125,0.446250,26880,8,1,1,0.124334,3,pass,1.016292;0.912750;0.996375 +random_masked_int64,70,420,8,bucket32_d64,0.946958,0.915833,0.462458,26880,8,1,1,0.124334,3,pass,0.946958;1.079209;0.843833 +random_masked_reverse,73,438,8,old_pull_serial,1.544708,1.479625,0.626833,56064,16,2,0,0.127917,3,pass,1.593958;1.537750;1.544708 +random_masked_reverse,73,438,8,old_group_serial,0.616500,0.552708,0.252333,30222,10,1,0,0.127917,3,pass,0.664708;0.616500;0.604208 +random_masked_reverse,73,438,8,old_pull_parallel_dag,1.573667,1.535500,0.613583,56064,16,2,0,0.127917,3,pass,1.573667;1.498833;1.613833 +random_masked_reverse,73,438,8,old_group_parallel_dag,0.605708,0.567584,0.256000,30222,10,1,0,0.127917,3,pass,0.636500;0.605708;0.572500 +random_masked_reverse,73,438,8,pull64_barrier,1.501625,1.458875,0.610542,56064,16,2,0,0.127917,3,pass,1.501625;1.509291;1.430958 +random_masked_reverse,73,438,8,pull64_interleaved,1.434334,1.403000,0.619042,56064,16,2,0,0.127917,3,pass,1.453458;1.405166;1.434334 +random_masked_reverse,73,438,8,pull32_interleaved,1.384458,1.352667,0.597333,56064,16,2,0,0.127917,3,pass,1.371959;1.692083;1.384458 +random_masked_reverse,73,438,8,pull32_gpu_dag,2.072333,1.277333,0.753209,56064,16,4,0,0.127917,3,pass,2.072333;1.848416;2.650459 +random_masked_reverse,73,438,8,frontier32_vertex,2.110666,2.066958,1.024083,5335,16,2,0,0.127917,3,pass,2.153834;2.110666;1.736583 +random_masked_reverse,73,438,8,frontier32_simd,1.530708,1.489292,0.361042,5335,16,2,0,0.127917,3,pass,1.555208;1.530708;1.270708 +random_masked_reverse,73,438,8,frontier32_gpu_dag,2.006667,1.291750,0.472458,5335,16,4,0,0.127917,3,pass,2.064667;1.931875;2.006667 +random_masked_reverse,73,438,8,bucket32_d4,3.628500,3.593417,1.164083,3179,32,4,0,0.127917,3,pass,3.628500;3.704042;3.569250 +random_masked_reverse,73,438,8,bucket32_d16,2.702375,2.656292,0.743625,3402,24,3,0,0.127917,3,pass,2.702375;2.782959;2.543667 +random_masked_reverse,73,438,8,bucket32_d64,1.697042,1.630166,0.391417,4984,16,2,0,0.127917,3,pass,1.697791;1.697042;1.622875 +boundary_700000000,6,10,6,old_pull_serial,0.450042,0.446083,0.050917,360,6,1,0,0.105417,3,pass,0.452375;0.431208;0.450042 +boundary_700000000,6,10,6,old_group_serial,0.330833,0.326875,0.025167,160,5,1,0,0.105417,3,pass,0.330833;0.332792;0.302000 +boundary_700000000,6,10,6,old_pull_parallel_dag,0.430000,0.400375,0.045375,360,6,1,0,0.105417,3,pass,0.486917;0.418167;0.430000 +boundary_700000000,6,10,6,old_group_parallel_dag,0.342333,0.314875,0.024750,160,5,1,0,0.105417,3,pass,0.322084;0.372750;0.342333 +boundary_700000000,6,10,6,pull64_barrier,0.689042,0.662291,0.044333,360,6,1,0,0.105417,3,pass,0.689042;0.763417;0.437542 +boundary_700000000,6,10,6,pull64_interleaved,0.395875,0.375292,0.042625,360,6,1,0,0.105417,3,pass,0.442584;0.395875;0.359333 +boundary_700000000,6,10,6,pull32_interleaved,0.455250,0.423209,0.046250,360,6,1,0,0.105417,3,pass,0.455250;0.649666;0.450333 +boundary_700000000,6,10,6,pull32_gpu_dag,1.057541,0.377000,0.075125,360,6,3,0,0.105417,3,pass,1.231958;1.057541;0.958209 +boundary_700000000,6,10,6,frontier32_vertex,0.632458,0.549625,0.107417,24,8,1,0,0.105417,3,pass,0.543541;0.632458;0.826583 +boundary_700000000,6,10,6,frontier32_simd,0.626792,0.597666,0.108833,24,8,1,0,0.105417,3,pass,0.626792;0.647666;0.575416 +boundary_700000000,6,10,6,frontier32_gpu_dag,1.233375,0.530292,0.134750,24,8,3,0,0.105417,3,pass,1.233375;1.230709;1.302791 +boundary_700000000,6,10,6,bucket32_d4,0.807208,0.783417,0.213333,24,8,1,0,0.105417,3,pass,0.840667;0.807208;0.804500 +boundary_700000000,6,10,6,bucket32_d16,0.702917,0.685959,0.179500,24,8,1,0,0.105417,3,pass,0.697541;0.702917;0.755500 +boundary_700000000,6,10,6,bucket32_d64,0.827875,0.783166,0.208208,24,8,1,0,0.105417,3,pass,0.827875;0.772708;0.840750 +boundary_700000000_masked,6,10,6,old_pull_serial,0.421041,0.416459,0.038000,360,6,1,0,0.080167,3,pass,0.421041;0.501542;0.378208 +boundary_700000000_masked,6,10,6,old_group_serial,0.305292,0.301667,0.014292,80,2,1,0,0.080167,3,pass,0.284583;0.305292;0.322459 +boundary_700000000_masked,6,10,6,old_pull_parallel_dag,0.439750,0.403625,0.042625,360,6,1,0,0.080167,3,pass,0.408709;0.439750;0.440084 +boundary_700000000_masked,6,10,6,old_group_parallel_dag,0.330541,0.295834,0.014417,80,2,1,0,0.080167,3,pass,0.343875;0.330541;0.304542 +boundary_700000000_masked,6,10,6,pull64_barrier,0.417709,0.383416,0.040542,360,6,1,0,0.080167,3,pass,0.417709;0.403792;0.528708 +boundary_700000000_masked,6,10,6,pull64_interleaved,0.416667,0.379250,0.040250,360,6,1,0,0.080167,3,pass,0.416667;0.397209;0.430666 +boundary_700000000_masked,6,10,6,pull32_interleaved,0.457500,0.430208,0.045333,360,6,1,0,0.080167,3,pass,0.457500;0.435708;0.598250 +boundary_700000000_masked,6,10,6,pull32_gpu_dag,1.022792,0.371750,0.067875,360,6,3,0,0.080167,3,pass,1.119458;1.022792;1.005625 +boundary_700000000_masked,6,10,6,frontier32_vertex,0.556292,0.530166,0.089250,12,8,1,0,0.080167,3,pass,0.648458;0.551208;0.556292 +boundary_700000000_masked,6,10,6,frontier32_simd,0.617417,0.551458,0.099875,12,8,1,0,0.080167,3,pass,0.628041;0.617417;0.596375 +boundary_700000000_masked,6,10,6,frontier32_gpu_dag,1.224500,0.539875,0.131542,12,8,3,0,0.080167,3,pass,1.226667;1.181042;1.224500 +boundary_700000000_masked,6,10,6,bucket32_d4,1.358083,1.303625,0.614208,12,8,1,0,0.080167,3,pass,1.364000;1.358083;1.184459 +boundary_700000000_masked,6,10,6,bucket32_d16,1.254834,1.239333,0.635208,12,8,1,0,0.080167,3,pass,1.313875;1.195792;1.254834 +boundary_700000000_masked,6,10,6,bucket32_d64,1.308541,1.216041,0.597167,12,8,1,0,0.080167,3,pass,1.308541;1.335791;0.780125 +boundary_700000000_reverse,6,10,6,old_pull_serial,0.387208,0.382958,0.039958,360,6,1,0,0.071958,3,pass,0.381959;0.389167;0.387208 +boundary_700000000_reverse,6,10,6,old_group_serial,0.310750,0.306458,0.023083,170,5,1,0,0.071958,3,pass,0.310750;0.307292;0.317333 +boundary_700000000_reverse,6,10,6,old_pull_parallel_dag,0.400125,0.378125,0.040125,360,6,1,0,0.071958,3,pass,0.406125;0.396292;0.400125 +boundary_700000000_reverse,6,10,6,old_group_parallel_dag,0.342708,0.317875,0.022125,170,5,1,0,0.071958,3,pass,0.342708;0.338833;0.484917 +boundary_700000000_reverse,6,10,6,pull64_barrier,0.374834,0.359541,0.041250,360,6,1,0,0.071958,3,pass,0.374834;0.356500;0.380417 +boundary_700000000_reverse,6,10,6,pull64_interleaved,0.420333,0.395584,0.042375,360,6,1,0,0.071958,3,pass,0.377083;0.420333;0.478541 +boundary_700000000_reverse,6,10,6,pull32_interleaved,0.458500,0.429958,0.045708,360,6,1,0,0.071958,3,pass,0.458500;0.479917;0.441708 +boundary_700000000_reverse,6,10,6,pull32_gpu_dag,1.066333,0.375875,0.073083,360,6,3,0,0.071958,3,pass,1.049834;1.066333;1.158167 +boundary_700000000_reverse,6,10,6,frontier32_vertex,0.626292,0.568834,0.109375,24,8,1,0,0.071958,3,pass,0.626292;0.847417;0.549584 +boundary_700000000_reverse,6,10,6,frontier32_simd,0.783334,0.758833,0.116333,24,8,1,0,0.071958,3,pass,0.598333;0.783334;0.790542 +boundary_700000000_reverse,6,10,6,frontier32_gpu_dag,1.511041,0.563125,0.136625,24,8,3,0,0.071958,3,pass,1.142917;1.753667;1.511041 +boundary_700000000_reverse,6,10,6,bucket32_d4,0.741583,0.723667,0.179625,24,8,1,0,0.071958,3,pass,0.767750;0.741583;0.718625 +boundary_700000000_reverse,6,10,6,bucket32_d16,0.799791,0.729834,0.179083,24,8,1,0,0.071958,3,pass,1.065958;0.799791;0.753792 +boundary_700000000_reverse,6,10,6,bucket32_d64,0.753458,0.731125,0.187875,24,8,1,0,0.071958,3,pass,0.753458;0.758500;0.740000 +boundary_700000000_reverse_masked,6,10,6,old_pull_serial,0.395500,0.391917,0.039583,360,6,1,0,0.085167,3,pass,0.363250;0.483334;0.395500 +boundary_700000000_reverse_masked,6,10,6,old_group_serial,0.307708,0.303958,0.016125,90,2,1,0,0.085167,3,pass,0.312625;0.305042;0.307708 +boundary_700000000_reverse_masked,6,10,6,old_pull_parallel_dag,0.461167,0.414625,0.043375,360,6,1,0,0.085167,3,pass,0.443875;0.461167;0.467666 +boundary_700000000_reverse_masked,6,10,6,old_group_parallel_dag,0.340417,0.297875,0.013750,90,2,1,0,0.085167,3,pass,0.340417;0.343625;0.318000 +boundary_700000000_reverse_masked,6,10,6,pull64_barrier,0.463666,0.419667,0.039750,360,6,1,0,0.085167,3,pass,0.407917;0.517917;0.463666 +boundary_700000000_reverse_masked,6,10,6,pull64_interleaved,0.455541,0.433167,0.045167,360,6,1,0,0.085167,3,pass,0.438958;0.455541;0.508042 +boundary_700000000_reverse_masked,6,10,6,pull32_interleaved,0.391958,0.371541,0.041125,360,6,1,0,0.085167,3,pass,0.426292;0.390334;0.391958 +boundary_700000000_reverse_masked,6,10,6,pull32_gpu_dag,1.347625,0.629500,0.252583,360,6,3,0,0.085167,3,pass,1.347625;1.216666;1.603875 +boundary_700000000_reverse_masked,6,10,6,frontier32_vertex,0.839042,0.817750,0.334250,9,8,1,0,0.085167,3,pass,0.833625;0.901042;0.839042 +boundary_700000000_reverse_masked,6,10,6,frontier32_simd,0.880916,0.857125,0.309667,9,8,1,0,0.085167,3,pass,0.872084;0.943459;0.880916 +boundary_700000000_reverse_masked,6,10,6,frontier32_gpu_dag,1.215042,0.522500,0.136833,9,8,3,0,0.085167,3,pass,1.459334;1.215042;1.182167 +boundary_700000000_reverse_masked,6,10,6,bucket32_d4,0.723666,0.701334,0.162125,9,8,1,0,0.085167,3,pass,0.719166;0.723666;0.868584 +boundary_700000000_reverse_masked,6,10,6,bucket32_d16,0.745666,0.728917,0.163375,9,8,1,0,0.085167,3,pass,0.695708;0.745666;0.770333 +boundary_700000000_reverse_masked,6,10,6,bucket32_d64,0.733333,0.705334,0.166125,9,8,1,0,0.085167,3,pass,0.742666;0.733333;0.720541 +boundary_715827883,6,10,6,old_pull_serial,0.377833,0.373833,0.040333,360,6,1,0,0.070542,3,pass,0.377833;0.414583;0.371959 +boundary_715827883,6,10,6,old_group_serial,0.297000,0.292750,0.022625,160,5,1,0,0.070542,3,pass,0.296334;0.304125;0.297000 +boundary_715827883,6,10,6,old_pull_parallel_dag,0.438208,0.403125,0.041333,360,6,1,0,0.070542,3,pass,0.438208;0.429416;0.459250 +boundary_715827883,6,10,6,old_group_parallel_dag,0.374375,0.335542,0.022667,160,5,1,0,0.070542,3,pass,0.468666;0.374375;0.372667 +boundary_715827883,6,10,6,pull64_barrier,0.379917,0.365583,0.041542,360,6,1,0,0.070542,3,pass,0.392208;0.379917;0.376791 +boundary_715827883,6,10,6,pull64_interleaved,0.393125,0.370625,0.041500,360,6,1,0,0.070542,3,pass,0.367208;0.393125;0.477167 +boundary_715827883,6,10,6,pull32_interleaved,0.612458,0.590750,0.047000,360,6,1,1,0.070542,3,pass,0.743291;0.438958;0.612458 +boundary_715827883,6,10,6,pull32_gpu_dag,1.074208,0.355250,0.068666,360,6,3,1,0.070542,3,pass,1.074208;0.986708;1.341750 +boundary_715827883,6,10,6,frontier32_vertex,0.412583,0.380292,0.042125,360,6,1,1,0.070542,3,pass,0.412583;0.405291;0.423417 +boundary_715827883,6,10,6,frontier32_simd,0.413166,0.384167,0.041625,360,6,1,1,0.070542,3,pass,0.413166;0.377958;0.458166 +boundary_715827883,6,10,6,frontier32_gpu_dag,1.384334,0.569333,0.282083,360,6,3,1,0.070542,3,pass,1.719209;1.384334;1.365250 +boundary_715827883,6,10,6,bucket32_d4,0.600750,0.571042,0.180750,360,6,1,1,0.070542,3,pass,0.642666;0.581958;0.600750 +boundary_715827883,6,10,6,bucket32_d16,0.668834,0.643750,0.181292,360,6,1,1,0.070542,3,pass,0.631583;0.668834;0.742334 +boundary_715827883,6,10,6,bucket32_d64,0.595917,0.559542,0.045292,360,6,1,1,0.070542,3,pass,0.631375;0.595917;0.441041 +boundary_715827883_masked,6,10,6,old_pull_serial,0.404792,0.401333,0.042542,360,6,1,0,0.082292,3,pass,0.392541;0.404792;0.415416 +boundary_715827883_masked,6,10,6,old_group_serial,0.306167,0.301917,0.013833,80,2,1,0,0.082292,3,pass,0.289250;0.306167;0.312125 +boundary_715827883_masked,6,10,6,old_pull_parallel_dag,0.438875,0.405791,0.041792,360,6,1,0,0.082292,3,pass,0.438875;0.413625;0.444334 +boundary_715827883_masked,6,10,6,old_group_parallel_dag,0.332792,0.303459,0.013875,80,2,1,0,0.082292,3,pass,0.348167;0.332792;0.306375 +boundary_715827883_masked,6,10,6,pull64_barrier,0.437084,0.401333,0.041667,360,6,1,0,0.082292,3,pass,0.437084;0.464041;0.417958 +boundary_715827883_masked,6,10,6,pull64_interleaved,0.463666,0.427625,0.045125,360,6,1,0,0.082292,3,pass,0.429875;0.469958;0.463666 +boundary_715827883_masked,6,10,6,pull32_interleaved,0.415291,0.387667,0.041375,360,6,1,1,0.082292,3,pass,0.425458;0.415291;0.401333 +boundary_715827883_masked,6,10,6,pull32_gpu_dag,1.047000,0.389375,0.070792,360,6,3,1,0.082292,3,pass,1.063250;1.047000;0.970833 +boundary_715827883_masked,6,10,6,frontier32_vertex,0.368166,0.350833,0.040250,360,6,1,1,0.082292,3,pass,0.366167;0.368166;0.414125 +boundary_715827883_masked,6,10,6,frontier32_simd,0.491625,0.463958,0.044000,360,6,1,1,0.082292,3,pass,0.436333;0.491625;0.650084 +boundary_715827883_masked,6,10,6,frontier32_gpu_dag,1.137000,0.406209,0.071458,360,6,3,1,0.082292,3,pass,1.277791;1.137000;1.065125 +boundary_715827883_masked,6,10,6,bucket32_d4,0.582667,0.549583,0.178500,360,6,1,1,0.082292,3,pass,0.582667;0.599250;0.575833 +boundary_715827883_masked,6,10,6,bucket32_d16,0.610792,0.579875,0.174542,360,6,1,1,0.082292,3,pass,0.610792;0.736708;0.537292 +boundary_715827883_masked,6,10,6,bucket32_d64,0.571958,0.552042,0.170167,360,6,1,1,0.082292,3,pass,0.579792;0.571958;0.564417 +boundary_715827883_reverse,6,10,6,old_pull_serial,0.564958,0.560750,0.177250,360,6,1,0,0.088167,3,pass,0.541583;0.576375;0.564958 +boundary_715827883_reverse,6,10,6,old_group_serial,0.376250,0.372000,0.091375,170,5,1,0,0.088167,3,pass,0.367375;0.376250;0.382041 +boundary_715827883_reverse,6,10,6,old_pull_parallel_dag,0.567417,0.539208,0.163583,360,6,1,0,0.088167,3,pass,0.573791;0.547458;0.567417 +boundary_715827883_reverse,6,10,6,old_group_parallel_dag,0.305291,0.288583,0.022750,170,5,1,0,0.088167,3,pass,0.305291;0.302125;0.309709 +boundary_715827883_reverse,6,10,6,pull64_barrier,0.460708,0.426208,0.045167,360,6,1,0,0.088167,3,pass,0.492458;0.421625;0.460708 +boundary_715827883_reverse,6,10,6,pull64_interleaved,0.435334,0.412333,0.042250,360,6,1,0,0.088167,3,pass,0.435334;0.454125;0.424500 +boundary_715827883_reverse,6,10,6,pull32_interleaved,0.385625,0.368458,0.040750,360,6,1,1,0.088167,3,pass,0.385625;0.387041;0.383000 +boundary_715827883_reverse,6,10,6,pull32_gpu_dag,1.081250,0.390458,0.075959,360,6,3,1,0.088167,3,pass,1.081250;1.069625;1.083667 +boundary_715827883_reverse,6,10,6,frontier32_vertex,0.425000,0.388166,0.040250,360,6,1,1,0.088167,3,pass,0.425000;0.412125;0.445916 +boundary_715827883_reverse,6,10,6,frontier32_simd,0.431416,0.398958,0.040792,360,6,1,1,0.088167,3,pass,0.405833;0.511792;0.431416 +boundary_715827883_reverse,6,10,6,frontier32_gpu_dag,1.369542,0.508833,0.071875,360,6,3,1,0.088167,3,pass,1.489667;1.369542;1.167458 +boundary_715827883_reverse,6,10,6,bucket32_d4,0.435250,0.395208,0.040750,360,6,1,1,0.088167,3,pass,0.445667;0.427834;0.435250 +boundary_715827883_reverse,6,10,6,bucket32_d16,0.418208,0.394292,0.041917,360,6,1,1,0.088167,3,pass,0.410542;0.448417;0.418208 +boundary_715827883_reverse,6,10,6,bucket32_d64,0.458000,0.432750,0.045125,360,6,1,1,0.088167,3,pass,0.458000;0.467375;0.439291 +boundary_715827883_reverse_masked,6,10,6,old_pull_serial,0.538584,0.534166,0.158500,360,6,1,0,0.078416,3,pass,0.578750;0.521167;0.538584 +boundary_715827883_reverse_masked,6,10,6,old_group_serial,0.358166,0.354541,0.051667,90,2,1,0,0.078416,3,pass,0.359292;0.347167;0.358166 +boundary_715827883_reverse_masked,6,10,6,old_pull_parallel_dag,0.556542,0.537291,0.158750,360,6,1,0,0.078416,3,pass,0.581250;0.556542;0.520875 +boundary_715827883_reverse_masked,6,10,6,old_group_parallel_dag,0.514667,0.475334,0.051458,90,2,1,0,0.078416,3,pass,0.514667;0.364625;0.626750 +boundary_715827883_reverse_masked,6,10,6,pull64_barrier,0.586833,0.558083,0.175083,360,6,1,0,0.078416,3,pass,0.586833;0.782458;0.585709 +boundary_715827883_reverse_masked,6,10,6,pull64_interleaved,0.609958,0.568333,0.172708,360,6,1,0,0.078416,3,pass,0.609958;0.616958;0.574458 +boundary_715827883_reverse_masked,6,10,6,pull32_interleaved,0.403750,0.376458,0.039375,360,6,1,1,0.078416,3,pass,0.393625;0.403750;0.409791 +boundary_715827883_reverse_masked,6,10,6,pull32_gpu_dag,1.112084,0.390542,0.071709,360,6,3,1,0.078416,3,pass,1.112084;1.158333;1.060042 +boundary_715827883_reverse_masked,6,10,6,frontier32_vertex,0.405625,0.376625,0.040125,360,6,1,1,0.078416,3,pass,0.397333;0.405625;0.425875 +boundary_715827883_reverse_masked,6,10,6,frontier32_simd,0.482541,0.449083,0.042833,360,6,1,1,0.078416,3,pass,0.710208;0.482541;0.406000 +boundary_715827883_reverse_masked,6,10,6,frontier32_gpu_dag,1.187208,0.422750,0.072208,360,6,3,1,0.078416,3,pass,1.187208;1.268459;1.112833 +boundary_715827883_reverse_masked,6,10,6,bucket32_d4,0.424709,0.407958,0.039625,360,6,1,1,0.078416,3,pass,0.424709;0.436584;0.367500 +boundary_715827883_reverse_masked,6,10,6,bucket32_d16,0.406375,0.381875,0.040500,360,6,1,1,0.078416,3,pass,0.406375;0.397542;0.432791 +boundary_715827883_reverse_masked,6,10,6,bucket32_d64,0.575792,0.537666,0.144083,360,6,1,1,0.078416,3,pass,0.406917;0.777833;0.575792 +boundary_9007199254740993,6,10,6,old_pull_serial,0.525500,0.521500,0.174542,360,6,1,0,0.096042,3,pass,0.521500;0.541750;0.525500 +boundary_9007199254740993,6,10,6,old_group_serial,0.387625,0.383541,0.094458,160,5,1,0,0.096042,3,pass,0.387625;0.387750;0.386791 +boundary_9007199254740993,6,10,6,old_pull_parallel_dag,0.610333,0.568208,0.175750,360,6,1,0,0.096042,3,pass,0.610333;0.697375;0.547167 +boundary_9007199254740993,6,10,6,old_group_parallel_dag,0.646583,0.606333,0.090667,160,5,1,0,0.096042,3,pass,0.427917;0.646583;1.133583 +boundary_9007199254740993,6,10,6,pull64_barrier,0.687000,0.651916,0.174125,360,6,1,0,0.096042,3,pass,0.730583;0.687000;0.581792 +boundary_9007199254740993,6,10,6,pull64_interleaved,0.377208,0.362625,0.041458,360,6,1,0,0.096042,3,pass,0.416625;0.362875;0.377208 +boundary_9007199254740993,6,10,6,pull32_interleaved,0.593708,0.549000,0.047375,360,6,1,1,0.096042,3,pass,0.413750;0.714334;0.593708 +boundary_9007199254740993,6,10,6,pull32_gpu_dag,1.076000,0.408375,0.081917,360,6,3,1,0.096042,3,pass,1.134958;1.076000;0.964667 +boundary_9007199254740993,6,10,6,frontier32_vertex,0.399500,0.367208,0.040625,360,6,1,1,0.096042,3,pass,0.429292;0.399500;0.399416 +boundary_9007199254740993,6,10,6,frontier32_simd,0.415125,0.372750,0.042375,360,6,1,1,0.096042,3,pass,0.415125;0.420542;0.406208 +boundary_9007199254740993,6,10,6,frontier32_gpu_dag,1.079083,0.393625,0.079042,360,6,3,1,0.096042,3,pass,1.150250;1.067292;1.079083 +boundary_9007199254740993,6,10,6,bucket32_d4,0.431958,0.392167,0.042083,360,6,1,1,0.096042,3,pass,0.394916;0.431958;0.539750 +boundary_9007199254740993,6,10,6,bucket32_d16,0.462542,0.422333,0.043000,360,6,1,1,0.096042,3,pass,0.374084;0.462542;0.531959 +boundary_9007199254740993,6,10,6,bucket32_d64,0.385042,0.363875,0.041333,360,6,1,1,0.096042,3,pass,0.385042;0.377375;0.395583 +boundary_9007199254740993_masked,6,10,6,old_pull_serial,0.394458,0.390833,0.041875,360,6,1,0,0.146083,3,pass,0.401709;0.384500;0.394458 +boundary_9007199254740993_masked,6,10,6,old_group_serial,0.280958,0.277500,0.013667,80,2,1,0,0.146083,3,pass,0.277625;0.280958;0.299125 +boundary_9007199254740993_masked,6,10,6,old_pull_parallel_dag,0.436292,0.417209,0.039917,360,6,1,0,0.146083,3,pass,0.436292;0.506750;0.436208 +boundary_9007199254740993_masked,6,10,6,old_group_parallel_dag,0.307708,0.285209,0.013833,80,2,1,0,0.146083,3,pass,0.387042;0.305416;0.307708 +boundary_9007199254740993_masked,6,10,6,pull64_barrier,0.420208,0.390959,0.042667,360,6,1,0,0.146083,3,pass,0.420208;0.747500;0.416834 +boundary_9007199254740993_masked,6,10,6,pull64_interleaved,0.398000,0.374541,0.040250,360,6,1,0,0.146083,3,pass,0.398000;0.392167;0.552042 +boundary_9007199254740993_masked,6,10,6,pull32_interleaved,0.387375,0.359708,0.040542,360,6,1,1,0.146083,3,pass,0.441042;0.387375;0.370584 +boundary_9007199254740993_masked,6,10,6,pull32_gpu_dag,1.014542,0.372792,0.070917,360,6,3,1,0.146083,3,pass,1.049416;1.014542;0.967250 +boundary_9007199254740993_masked,6,10,6,frontier32_vertex,0.385583,0.370250,0.040625,360,6,1,1,0.146083,3,pass,0.385583;0.359292;0.596291 +boundary_9007199254740993_masked,6,10,6,frontier32_simd,0.573042,0.536541,0.173000,360,6,1,1,0.146083,3,pass,0.611750;0.573042;0.544917 +boundary_9007199254740993_masked,6,10,6,frontier32_gpu_dag,1.241792,0.560958,0.259333,360,6,3,1,0.146083,3,pass,1.353917;1.241792;1.178917 +boundary_9007199254740993_masked,6,10,6,bucket32_d4,0.568167,0.533917,0.167250,360,6,1,1,0.146083,3,pass,0.616792;0.527041;0.568167 +boundary_9007199254740993_masked,6,10,6,bucket32_d16,0.784000,0.761333,0.048500,360,6,1,1,0.146083,3,pass,0.902250;0.784000;0.585834 +boundary_9007199254740993_masked,6,10,6,bucket32_d64,0.413292,0.393958,0.040125,360,6,1,1,0.146083,3,pass,0.459500;0.413292;0.405333 +boundary_9007199254740993_reverse,6,10,6,old_pull_serial,0.408625,0.404208,0.043375,360,6,1,0,0.099791,3,pass,0.408625;0.384708;0.412958 +boundary_9007199254740993_reverse,6,10,6,old_group_serial,0.295500,0.291250,0.022292,170,5,1,0,0.099791,3,pass,0.285750;0.349334;0.295500 +boundary_9007199254740993_reverse,6,10,6,old_pull_parallel_dag,0.406709,0.375333,0.039375,360,6,1,0,0.099791,3,pass,0.406709;0.397625;0.418583 +boundary_9007199254740993_reverse,6,10,6,old_group_parallel_dag,0.310584,0.288791,0.022250,170,5,1,0,0.099791,3,pass,0.307500;0.310584;0.383958 +boundary_9007199254740993_reverse,6,10,6,pull64_barrier,0.402291,0.370333,0.040458,360,6,1,0,0.099791,3,pass,0.402291;0.409167;0.400833 +boundary_9007199254740993_reverse,6,10,6,pull64_interleaved,0.417625,0.389083,0.040750,360,6,1,0,0.099791,3,pass,0.417625;0.407709;0.672666 +boundary_9007199254740993_reverse,6,10,6,pull32_interleaved,0.456750,0.422084,0.040875,360,6,1,1,0.099791,3,pass,0.457500;0.386250;0.456750 +boundary_9007199254740993_reverse,6,10,6,pull32_gpu_dag,1.081708,0.380083,0.074334,360,6,3,1,0.099791,3,pass,1.092959;1.081708;1.069709 +boundary_9007199254740993_reverse,6,10,6,frontier32_vertex,0.416292,0.387500,0.041125,360,6,1,1,0.099791,3,pass,0.422542;0.391916;0.416292 +boundary_9007199254740993_reverse,6,10,6,frontier32_simd,0.427916,0.387125,0.043458,360,6,1,1,0.099791,3,pass,0.427916;0.428250;0.423667 +boundary_9007199254740993_reverse,6,10,6,frontier32_gpu_dag,1.050666,0.410208,0.074458,360,6,3,1,0.099791,3,pass,1.050666;1.040667;1.417584 +boundary_9007199254740993_reverse,6,10,6,bucket32_d4,0.750875,0.705000,0.158292,360,6,1,1,0.099791,3,pass,0.750875;0.755708;0.628666 +boundary_9007199254740993_reverse,6,10,6,bucket32_d16,0.566208,0.532250,0.157958,360,6,1,1,0.099791,3,pass,0.577666;0.566208;0.550167 +boundary_9007199254740993_reverse,6,10,6,bucket32_d64,0.550459,0.522458,0.164792,360,6,1,1,0.099791,3,pass,0.809167;0.550459;0.511958 +boundary_9007199254740993_reverse_masked,6,10,6,old_pull_serial,0.526750,0.523167,0.161208,360,6,1,0,0.101250,3,pass,0.560709;0.508625;0.526750 +boundary_9007199254740993_reverse_masked,6,10,6,old_group_serial,0.320792,0.317041,0.050625,90,2,1,0,0.101250,3,pass,0.347708;0.320792;0.320625 +boundary_9007199254740993_reverse_masked,6,10,6,old_pull_parallel_dag,0.595958,0.553167,0.158750,360,6,1,0,0.101250,3,pass,0.549417;0.595958;0.602375 +boundary_9007199254740993_reverse_masked,6,10,6,old_group_parallel_dag,0.388416,0.357916,0.050125,90,2,1,0,0.101250,3,pass,0.377708;0.390167;0.388416 +boundary_9007199254740993_reverse_masked,6,10,6,pull64_barrier,0.625292,0.599542,0.165167,360,6,1,0,0.101250,3,pass,0.625292;0.691584;0.555959 +boundary_9007199254740993_reverse_masked,6,10,6,pull64_interleaved,0.379375,0.364792,0.039833,360,6,1,0,0.101250,3,pass,0.434708;0.360708;0.379375 +boundary_9007199254740993_reverse_masked,6,10,6,pull32_interleaved,0.415042,0.378542,0.040500,360,6,1,1,0.101250,3,pass,0.396708;0.415042;0.425292 +boundary_9007199254740993_reverse_masked,6,10,6,pull32_gpu_dag,1.095708,0.395375,0.069958,360,6,3,1,0.101250,3,pass,1.095708;1.093708;1.382084 +boundary_9007199254740993_reverse_masked,6,10,6,frontier32_vertex,0.426042,0.403375,0.041375,360,6,1,1,0.101250,3,pass,0.392542;0.553417;0.426042 +boundary_9007199254740993_reverse_masked,6,10,6,frontier32_simd,0.405584,0.383083,0.040500,360,6,1,1,0.101250,3,pass,0.405584;0.412833;0.404500 +boundary_9007199254740993_reverse_masked,6,10,6,frontier32_gpu_dag,1.210709,0.487375,0.256917,360,6,3,1,0.101250,3,pass,1.133708;1.210709;1.338417 +boundary_9007199254740993_reverse_masked,6,10,6,bucket32_d4,0.601500,0.567208,0.175000,360,6,1,1,0.101250,3,pass,0.602167;0.572583;0.601500 +boundary_9007199254740993_reverse_masked,6,10,6,bucket32_d16,0.529917,0.501708,0.154375,360,6,1,1,0.101250,3,pass,0.529917;0.620084;0.496500 +boundary_9007199254740993_reverse_masked,6,10,6,bucket32_d64,0.555667,0.516125,0.155667,360,6,1,1,0.101250,3,pass,0.936292;0.505125;0.555667 diff --git a/dev/research/metal_pathfinding/optimization/results/correctness-stderr.txt b/dev/research/metal_pathfinding/optimization/results/correctness-stderr.txt new file mode 100644 index 0000000..47b95c6 --- /dev/null +++ b/dev/research/metal_pathfinding/optimization/results/correctness-stderr.txt @@ -0,0 +1 @@ +device=Apple M4 Max setup_ms=50.79 execution_width=32 diff --git a/dev/research/metal_pathfinding/optimization/results/correctness.csv b/dev/research/metal_pathfinding/optimization/results/correctness.csv new file mode 100644 index 0000000..6ad6397 --- /dev/null +++ b/dev/research/metal_pathfinding/optimization/results/correctness.csv @@ -0,0 +1,337 @@ +case,n,e,queries,method,wall_ms,distance_ms,gpu_ms,edge_visits,rounds,waits,fallback64,upload_ms,samples,correct,wall_samples_ms +random_masked_int64,40,240,8,old_pull_serial,0.562958,0.541375,0.122875,15360,8,1,0,0.116249,3,pass,0.568167;0.533500;0.562958 +random_masked_int64,40,240,8,old_group_serial,0.513500,0.491542,0.071625,9600,6,1,0,0.116249,3,pass,0.513500;0.487167;0.567333 +random_masked_int64,40,240,8,old_pull_parallel_dag,0.573333,0.491583,0.122958,15360,8,1,0,0.116249,3,pass,0.573333;0.548333;0.592250 +random_masked_int64,40,240,8,old_group_parallel_dag,0.519708,0.462291,0.071125,9600,6,1,0,0.116249,3,pass,0.500084;0.526209;0.519708 +random_masked_int64,40,240,8,pull64_barrier,0.567209,0.524583,0.113625,15360,8,1,0,0.116249,3,pass,0.567209;0.586667;0.326542 +random_masked_int64,40,240,8,pull64_interleaved,0.335166,0.294625,0.113125,15360,8,1,0,0.116249,3,pass,0.326833;0.338791;0.335166 +random_masked_int64,40,240,8,pull32_interleaved,0.329584,0.277209,0.113292,15360,8,1,1,0.116249,3,pass,0.329584;0.341041;0.309250 +random_masked_int64,40,240,8,pull32_gpu_dag,0.758416,0.296667,0.163916,15360,8,3,1,0.116249,3,pass,0.694417;0.758416;0.838375 +random_masked_int64,40,240,8,frontier32_vertex,0.323083,0.273417,0.112375,15360,8,1,1,0.116249,3,pass,0.365583;0.323083;0.298250 +random_masked_int64,40,240,8,frontier32_simd,0.329375,0.284292,0.112167,15360,8,1,1,0.116249,3,pass,0.327875;0.884416;0.329375 +random_masked_int64,40,240,8,frontier32_gpu_dag,0.657125,0.282000,0.160708,15360,8,3,1,0.116249,3,pass,0.657125;0.698167;0.640042 +random_masked_int64,40,240,8,bucket32_d4,0.394209,0.348916,0.129667,15360,8,1,1,0.116249,3,pass,0.467000;0.394209;0.361750 +random_masked_int64,40,240,8,bucket32_d16,0.333709,0.284834,0.112792,15360,8,1,1,0.116249,3,pass,0.333709;0.318917;0.335542 +random_masked_int64,40,240,8,bucket32_d64,0.317500,0.278125,0.112250,15360,8,1,1,0.116249,3,pass,0.323708;0.305125;0.317500 +random_masked,43,258,8,old_pull_serial,0.572584,0.552875,0.270417,33024,16,2,0,0.083291,3,pass,0.572584;0.578375;0.561625 +random_masked,43,258,8,old_group_serial,0.255458,0.243375,0.105375,14448,9,1,0,0.083291,3,pass,0.255458;0.305583;0.231875 +random_masked,43,258,8,old_pull_parallel_dag,0.577625,0.546834,0.273417,33024,16,2,0,0.083291,3,pass,0.577625;0.608875;0.559083 +random_masked,43,258,8,old_group_parallel_dag,0.281833,0.243709,0.105583,14448,9,1,0,0.083291,3,pass,0.269000;0.293583;0.281833 +random_masked,43,258,8,pull64_barrier,0.594875,0.526042,0.244875,33024,16,2,0,0.083291,3,pass,0.594875;0.600542;0.564625 +random_masked,43,258,8,pull64_interleaved,0.686125,0.652417,0.298292,33024,16,2,0,0.083291,3,pass,0.655416;0.730000;0.686125 +random_masked,43,258,8,pull32_interleaved,0.569958,0.533916,0.219208,33024,16,2,0,0.083291,3,pass,0.690500;0.569958;0.534750 +random_masked,43,258,8,pull32_gpu_dag,1.093000,0.672000,0.337000,33024,16,4,0,0.083291,3,pass,1.089750;1.138958;1.093000 +random_masked,43,258,8,frontier32_vertex,0.811167,0.763792,0.443250,3186,16,2,0,0.083291,3,pass,0.811167;0.769541;0.873292 +random_masked,43,258,8,frontier32_simd,0.662417,0.619000,0.325375,3186,16,2,0,0.083291,3,pass,0.653209;0.662417;1.329042 +random_masked,43,258,8,frontier32_gpu_dag,1.094500,0.664041,0.371958,3186,16,4,0,0.083291,3,pass,1.044250;1.094500;1.224167 +random_masked,43,258,8,bucket32_d4,2.167333,2.099083,1.255792,2016,32,4,0,0.083291,3,pass,2.198125;2.167333;2.011750 +random_masked,43,258,8,bucket32_d16,1.541041,1.509916,0.911334,2142,24,3,0,0.083291,3,pass,1.701416;1.541041;1.509917 +random_masked,43,258,8,bucket32_d64,1.098250,1.062792,0.618375,3096,16,2,0,0.083291,3,pass,1.088084;1.098250;1.138375 +random_masked_int64_reverse,46,276,8,old_pull_serial,0.320125,0.287208,0.119125,17664,8,1,0,0.109000,3,pass,0.320125;0.288375;0.330834 +random_masked_int64_reverse,46,276,8,old_group_serial,0.231167,0.215875,0.045500,9660,5,1,0,0.109000,3,pass,0.231709;0.228834;0.231167 +random_masked_int64_reverse,46,276,8,old_pull_parallel_dag,0.284459,0.242500,0.095250,17664,8,1,0,0.109000,3,pass,0.356084;0.284459;0.282208 +random_masked_int64_reverse,46,276,8,old_group_parallel_dag,0.222583,0.169041,0.044625,9660,5,1,0,0.109000,3,pass,0.222583;0.223209;0.213208 +random_masked_int64_reverse,46,276,8,pull64_barrier,0.361209,0.313625,0.109375,17664,8,1,0,0.109000,3,pass,0.361209;0.383542;0.313542 +random_masked_int64_reverse,46,276,8,pull64_interleaved,0.314208,0.274833,0.093750,17664,8,1,0,0.109000,3,pass,0.347709;0.314208;0.300500 +random_masked_int64_reverse,46,276,8,pull32_interleaved,0.370542,0.328166,0.111917,17664,8,1,1,0.109000,3,pass,0.350250;0.943084;0.370542 +random_masked_int64_reverse,46,276,8,pull32_gpu_dag,0.791459,0.327709,0.156083,17664,8,3,1,0.109000,3,pass,0.791459;0.806792;0.742833 +random_masked_int64_reverse,46,276,8,frontier32_vertex,0.369875,0.318917,0.104333,17664,8,1,1,0.109000,3,pass,0.343583;0.369875;0.378291 +random_masked_int64_reverse,46,276,8,frontier32_simd,0.341250,0.304667,0.107625,17664,8,1,1,0.109000,3,pass,0.336959;0.341250;0.354541 +random_masked_int64_reverse,46,276,8,frontier32_gpu_dag,0.782833,0.318333,0.157750,17664,8,3,1,0.109000,3,pass,0.802541;0.772208;0.782833 +random_masked_int64_reverse,46,276,8,bucket32_d4,0.378708,0.321791,0.101500,17664,8,1,1,0.109000,3,pass,0.426667;0.378708;0.349875 +random_masked_int64_reverse,46,276,8,bucket32_d16,0.366875,0.315208,0.105917,17664,8,1,1,0.109000,3,pass,0.376708;0.366875;0.345125 +random_masked_int64_reverse,46,276,8,bucket32_d64,0.375291,0.328750,0.104875,17664,8,1,1,0.109000,3,pass,0.355542;0.375291;0.380708 +random_masked,49,294,8,old_pull_serial,0.349167,0.330875,0.142625,18816,8,1,0,0.098416,3,pass,0.355041;0.349167;0.336417 +random_masked,49,294,8,old_group_serial,0.291625,0.279125,0.094042,14700,8,1,0,0.098416,3,pass,0.274917;0.291625;0.375291 +random_masked,49,294,8,old_pull_parallel_dag,0.394000,0.325875,0.148708,18816,8,1,0,0.098416,3,pass,0.394000;0.414875;0.355791 +random_masked,49,294,8,old_group_parallel_dag,0.321250,0.275959,0.093833,14700,8,1,0,0.098416,3,pass,0.321250;0.317416;0.348875 +random_masked,49,294,8,pull64_barrier,0.371584,0.324792,0.119250,18816,8,1,0,0.098416,3,pass,0.427208;0.371584;0.358792 +random_masked,49,294,8,pull64_interleaved,0.367875,0.317042,0.145625,18816,8,1,0,0.098416,3,pass,0.325000;0.367875;0.427334 +random_masked,49,294,8,pull32_interleaved,0.331500,0.293542,0.104583,18816,8,1,0,0.098416,3,pass,0.331500;0.368292;0.325250 +random_masked,49,294,8,pull32_gpu_dag,0.853708,0.354166,0.178292,18816,8,3,0,0.098416,3,pass,0.865458;0.810500;0.853708 +random_masked,49,294,8,frontier32_vertex,0.595250,0.561125,0.310875,3162,8,1,0,0.098416,3,pass,0.589541;0.595250;0.615666 +random_masked,49,294,8,frontier32_simd,0.426833,0.374167,0.180625,3156,8,1,0,0.098416,3,pass,0.426833;0.468625;0.403334 +random_masked,49,294,8,frontier32_gpu_dag,0.900792,0.407417,0.236917,3162,8,3,0,0.098416,3,pass,0.900792;0.924666;0.781917 +random_masked,49,294,8,bucket32_d4,2.018792,1.964250,0.991125,2022,40,5,0,0.098416,3,pass,2.461125;2.018792;1.864459 +random_masked,49,294,8,bucket32_d16,0.797750,0.762875,0.338708,2100,16,2,0,0.098416,3,pass,0.834750;0.759209;0.797750 +random_masked,49,294,8,bucket32_d64,0.719584,0.669417,0.273375,3042,16,2,0,0.098416,3,pass,0.847958;0.713667;0.719584 +random_masked_int64,52,312,8,old_pull_serial,0.251500,0.230167,0.061875,19968,8,1,0,0.132541,3,pass,0.251500;0.271667;0.246209 +random_masked_int64,52,312,8,old_group_serial,0.234042,0.204916,0.033833,12168,6,1,0,0.132541,3,pass,0.217834;0.234042;0.241666 +random_masked_int64,52,312,8,old_pull_parallel_dag,0.300750,0.252917,0.062500,19968,8,1,0,0.132541,3,pass,0.258250;0.300750;0.307166 +random_masked_int64,52,312,8,old_group_parallel_dag,0.277167,0.205667,0.033958,12168,6,1,0,0.132541,3,pass,0.256584;0.369375;0.277167 +random_masked_int64,52,312,8,pull64_barrier,0.335791,0.302083,0.060083,19968,8,1,0,0.132541,3,pass,0.347916;0.330959;0.335791 +random_masked_int64,52,312,8,pull64_interleaved,0.343042,0.290542,0.057959,19968,8,1,0,0.132541,3,pass,0.326000;0.357292;0.343042 +random_masked_int64,52,312,8,pull32_interleaved,0.349375,0.298750,0.057958,19968,8,1,1,0.132541,3,pass,0.361458;0.349375;0.335000 +random_masked_int64,52,312,8,pull32_gpu_dag,0.854458,0.312000,0.082459,19968,8,3,1,0.132541,3,pass,0.752042;1.220167;0.854458 +random_masked_int64,52,312,8,frontier32_vertex,0.358917,0.321792,0.058792,19968,8,1,1,0.132541,3,pass,0.369084;0.324000;0.358917 +random_masked_int64,52,312,8,frontier32_simd,0.371084,0.329958,0.058542,19968,8,1,1,0.132541,3,pass,0.371084;0.319417;0.386417 +random_masked_int64,52,312,8,frontier32_gpu_dag,0.591750,0.231083,0.061417,19968,8,3,1,0.132541,3,pass,0.534625;0.591750;0.640417 +random_masked_int64,52,312,8,bucket32_d4,0.324334,0.287292,0.053583,19968,8,1,1,0.132541,3,pass,0.296625;0.400583;0.324334 +random_masked_int64,52,312,8,bucket32_d16,0.321666,0.274500,0.051708,19968,8,1,1,0.132541,3,pass,0.321542;0.373166;0.321666 +random_masked_int64,52,312,8,bucket32_d64,0.330334,0.267000,0.048500,19968,8,1,1,0.132541,3,pass,0.330334;0.354292;0.300292 +random_masked_reverse,55,330,8,old_pull_serial,0.381583,0.369958,0.070083,42240,16,2,0,0.136458,3,pass,0.381583;0.404583;0.378750 +random_masked_reverse,55,330,8,old_group_serial,0.165125,0.149959,0.024333,20130,10,1,0,0.136458,3,pass,0.189000;0.157875;0.165125 +random_masked_reverse,55,330,8,old_pull_parallel_dag,0.330250,0.301334,0.058333,42240,16,2,0,0.136458,3,pass,0.364000;0.322041;0.330250 +random_masked_reverse,55,330,8,old_group_parallel_dag,0.188792,0.148584,0.021917,20130,10,1,0,0.136458,3,pass,0.223500;0.188792;0.181417 +random_masked_reverse,55,330,8,pull64_barrier,0.455958,0.432416,0.060250,42240,16,2,0,0.136458,3,pass,0.463333;0.455958;0.419792 +random_masked_reverse,55,330,8,pull64_interleaved,0.477458,0.446000,0.066375,42240,16,2,0,0.136458,3,pass,0.477458;0.438542;0.577083 +random_masked_reverse,55,330,8,pull32_interleaved,0.437209,0.390750,0.059500,42240,16,2,0,0.136458,3,pass,0.437209;0.439667;0.401416 +random_masked_reverse,55,330,8,pull32_gpu_dag,0.788167,0.410958,0.084000,42240,16,4,0,0.136458,3,pass,0.879083;0.780833;0.788167 +random_masked_reverse,55,330,8,frontier32_vertex,0.558375,0.525958,0.173792,3691,16,2,0,0.136458,3,pass,0.841542;0.558375;0.547000 +random_masked_reverse,55,330,8,frontier32_simd,0.471416,0.425250,0.108125,3691,16,2,0,0.136458,3,pass,0.451917;0.471416;0.482083 +random_masked_reverse,55,330,8,frontier32_gpu_dag,0.761666,0.416041,0.127125,3691,16,4,0,0.136458,3,pass,0.819375;0.761666;0.747625 +random_masked_reverse,55,330,8,bucket32_d4,1.046625,1.021750,0.349208,2455,32,4,0,0.136458,3,pass,1.042834;1.046625;1.100042 +random_masked_reverse,55,330,8,bucket32_d16,0.837417,0.805958,0.279000,2603,24,3,0,0.136458,3,pass,0.837417;0.884334;0.757500 +random_masked_reverse,55,330,8,bucket32_d64,0.521625,0.456666,0.159333,3605,16,2,0,0.136458,3,pass,0.453458;0.526417;0.521625 +random_masked_int64,58,348,8,old_pull_serial,0.186041,0.167958,0.030833,22272,8,1,0,0.058459,3,pass,0.189041;0.178792;0.186041 +random_masked_int64,58,348,8,old_group_serial,0.156000,0.139792,0.013250,13920,5,1,0,0.058459,3,pass,0.151125;0.160167;0.156000 +random_masked_int64,58,348,8,old_pull_parallel_dag,0.197250,0.157083,0.027333,22272,8,1,0,0.058459,3,pass,0.197250;0.200458;0.190459 +random_masked_int64,58,348,8,old_group_parallel_dag,0.165625,0.132291,0.013375,13920,5,1,0,0.058459,3,pass,0.167541;0.159458;0.165625 +random_masked_int64,58,348,8,pull64_barrier,0.208458,0.176250,0.026958,22272,8,1,0,0.058459,3,pass,0.283084;0.208458;0.198500 +random_masked_int64,58,348,8,pull64_interleaved,0.194334,0.174708,0.027958,22272,8,1,0,0.058459,3,pass,0.194334;0.191875;0.202292 +random_masked_int64,58,348,8,pull32_interleaved,0.191375,0.165916,0.027875,22272,8,1,1,0.058459,3,pass,0.198125;0.190583;0.191375 +random_masked_int64,58,348,8,pull32_gpu_dag,0.588458,0.211625,0.047000,22272,8,3,1,0.058459,3,pass,0.590250;0.506208;0.588458 +random_masked_int64,58,348,8,frontier32_vertex,0.225708,0.204667,0.030375,22272,8,1,1,0.058459,3,pass,0.245209;0.223583;0.225708 +random_masked_int64,58,348,8,frontier32_simd,0.244375,0.206250,0.030792,22272,8,1,1,0.058459,3,pass,0.226125;0.274500;0.244375 +random_masked_int64,58,348,8,frontier32_gpu_dag,0.520667,0.194583,0.043542,22272,8,3,1,0.058459,3,pass,0.517875;0.520667;0.547625 +random_masked_int64,58,348,8,bucket32_d4,0.217958,0.187000,0.027875,22272,8,1,1,0.058459,3,pass,0.211583;0.220375;0.217958 +random_masked_int64,58,348,8,bucket32_d16,0.230000,0.204833,0.030375,22272,8,1,1,0.058459,3,pass,0.188792;0.270042;0.230000 +random_masked_int64,58,348,8,bucket32_d64,0.209875,0.187709,0.027333,22272,8,1,1,0.058459,3,pass,0.264500;0.209875;0.203958 +random_masked,61,366,8,old_pull_serial,0.309291,0.298834,0.063375,46848,16,2,0,0.052416,3,pass,0.309291;0.308166;0.322417 +random_masked,61,366,8,old_group_serial,0.141500,0.131333,0.024708,23424,9,1,0,0.052416,3,pass,0.150833;0.141500;0.137000 +random_masked,61,366,8,old_pull_parallel_dag,0.342834,0.306125,0.064458,46848,16,2,0,0.052416,3,pass,0.406584;0.342834;0.339459 +random_masked,61,366,8,old_group_parallel_dag,0.177291,0.145333,0.024708,23424,9,1,0,0.052416,3,pass,0.177291;0.163500;0.191833 +random_masked,61,366,8,pull64_barrier,0.422167,0.395792,0.066667,46848,16,2,0,0.052416,3,pass,0.422167;0.390583;0.431209 +random_masked,61,366,8,pull64_interleaved,0.389083,0.365958,0.066667,46848,16,2,0,0.052416,3,pass,0.389083;0.365166;0.401083 +random_masked,61,366,8,pull32_interleaved,0.353250,0.319500,0.053750,46848,16,2,0,0.052416,3,pass,0.350166;0.353250;0.455584 +random_masked,61,366,8,pull32_gpu_dag,0.685375,0.349667,0.070417,46848,16,4,0,0.052416,3,pass,0.650041;0.834458;0.685375 +random_masked,61,366,8,frontier32_vertex,0.496416,0.460000,0.137750,4776,16,2,0,0.052416,3,pass,0.496416;0.497708;0.445875 +random_masked,61,366,8,frontier32_simd,0.431584,0.383167,0.092917,4776,16,2,0,0.052416,3,pass,0.378875;0.431584;0.512042 +random_masked,61,366,8,frontier32_gpu_dag,0.768958,0.425000,0.124625,4776,16,4,0,0.052416,3,pass,0.818959;0.743625;0.768958 +random_masked,61,366,8,bucket32_d4,1.126958,1.098000,0.409250,2760,40,5,0,0.052416,3,pass,1.126958;1.091500;1.168916 +random_masked,61,366,8,bucket32_d16,0.778042,0.751250,0.267750,2952,24,3,0,0.052416,3,pass,0.778042;0.807250;0.666792 +random_masked,61,366,8,bucket32_d64,0.449792,0.426417,0.157708,4590,16,2,0,0.052416,3,pass,0.443667;0.449792;0.465417 +random_masked_int64_reverse,64,384,8,old_pull_serial,0.179208,0.167667,0.026500,24576,8,1,0,0.046333,3,pass,0.171750;0.179208;0.182792 +random_masked_int64_reverse,64,384,8,old_group_serial,0.154708,0.144500,0.011125,13440,5,1,0,0.046333,3,pass,0.151625;0.154708;0.161958 +random_masked_int64_reverse,64,384,8,old_pull_parallel_dag,0.200458,0.170542,0.026167,24576,8,1,0,0.046333,3,pass,0.209667;0.200458;0.200000 +random_masked_int64_reverse,64,384,8,old_group_parallel_dag,0.175792,0.141084,0.011125,13440,5,1,0,0.046333,3,pass,0.179041;0.175792;0.174542 +random_masked_int64_reverse,64,384,8,pull64_barrier,0.228417,0.203125,0.026667,24576,8,1,0,0.046333,3,pass,0.228417;0.234625;0.225042 +random_masked_int64_reverse,64,384,8,pull64_interleaved,0.218542,0.189875,0.024458,24576,8,1,0,0.046333,3,pass,0.198458;0.251667;0.218542 +random_masked_int64_reverse,64,384,8,pull32_interleaved,0.223083,0.188250,0.024000,24576,8,1,1,0.046333,3,pass,0.197291;0.223083;0.267416 +random_masked_int64_reverse,64,384,8,pull32_gpu_dag,0.465292,0.176792,0.035500,24576,8,3,1,0.046333,3,pass,0.465292;0.442125;0.476250 +random_masked_int64_reverse,64,384,8,frontier32_vertex,0.221250,0.186667,0.022625,24576,8,1,1,0.046333,3,pass,0.221250;0.218417;0.378333 +random_masked_int64_reverse,64,384,8,frontier32_simd,0.213667,0.181542,0.022625,24576,8,1,1,0.046333,3,pass,0.197541;0.224833;0.213667 +random_masked_int64_reverse,64,384,8,frontier32_gpu_dag,0.405958,0.149291,0.034417,24576,8,3,1,0.046333,3,pass,0.401500;0.405958;0.486750 +random_masked_int64_reverse,64,384,8,bucket32_d4,0.194334,0.164583,0.023333,24576,8,1,1,0.046333,3,pass,0.190208;0.205375;0.194334 +random_masked_int64_reverse,64,384,8,bucket32_d16,0.227500,0.203625,0.026750,24576,8,1,1,0.046333,3,pass,0.215584;0.227500;0.354667 +random_masked_int64_reverse,64,384,8,bucket32_d64,0.204667,0.171833,0.022792,24576,8,1,1,0.046333,3,pass,0.204667;0.199625;0.216875 +random_masked,67,402,8,old_pull_serial,0.156208,0.145333,0.027917,25728,8,1,0,0.078416,3,pass,0.158250;0.156208;0.154292 +random_masked,67,402,8,old_group_serial,0.157000,0.146292,0.019708,24522,8,1,0,0.078416,3,pass,0.198042;0.153458;0.157000 +random_masked,67,402,8,old_pull_parallel_dag,0.187958,0.160625,0.028542,25728,8,1,0,0.078416,3,pass,0.180917;0.199084;0.187958 +random_masked,67,402,8,old_group_parallel_dag,0.153916,0.135416,0.019375,24522,8,1,0,0.078416,3,pass,0.163708;0.153916;0.144041 +random_masked,67,402,8,pull64_barrier,0.198750,0.171208,0.027625,25728,8,1,0,0.078416,3,pass,0.217750;0.198750;0.175833 +random_masked,67,402,8,pull64_interleaved,0.237833,0.201459,0.030625,25728,8,1,0,0.078416,3,pass,0.237584;0.310625;0.237833 +random_masked,67,402,8,pull32_interleaved,0.249375,0.202667,0.025375,25728,8,1,0,0.078416,3,pass,0.228958;0.315416;0.249375 +random_masked,67,402,8,pull32_gpu_dag,0.488833,0.179459,0.039125,25728,8,3,0,0.078416,3,pass,0.479541;0.488833;0.514375 +random_masked,67,402,8,frontier32_vertex,0.313167,0.276458,0.080125,5034,8,1,0,0.078416,3,pass,0.319041;0.265166;0.313167 +random_masked,67,402,8,frontier32_simd,0.249209,0.218042,0.051417,5034,8,1,0,0.078416,3,pass,0.233792;0.255833;0.249209 +random_masked,67,402,8,frontier32_gpu_dag,0.607250,0.210917,0.064250,4998,8,3,0,0.078416,3,pass,0.607250;0.494000;0.612541 +random_masked,67,402,8,bucket32_d4,0.935291,0.893959,0.331917,3120,32,4,0,0.078416,3,pass,0.935291;0.935666;0.911458 +random_masked,67,402,8,bucket32_d16,0.785333,0.745209,0.263125,3360,24,3,0,0.078416,3,pass,0.785333;0.732792;0.858959 +random_masked,67,402,8,bucket32_d64,0.456333,0.432458,0.151583,4914,16,2,0,0.078416,3,pass,0.446917;0.511209;0.456333 +random_masked_int64,70,420,8,old_pull_serial,0.172833,0.161834,0.033625,26880,8,1,0,0.111875,3,pass,0.152208;0.172833;0.183542 +random_masked_int64,70,420,8,old_group_serial,0.152167,0.141916,0.017417,15960,6,1,0,0.111875,3,pass,0.152167;0.157459;0.140167 +random_masked_int64,70,420,8,old_pull_parallel_dag,0.184084,0.156958,0.031333,26880,8,1,0,0.111875,3,pass,0.184084;0.183667;0.186000 +random_masked_int64,70,420,8,old_group_parallel_dag,0.172209,0.148625,0.017417,15960,6,1,0,0.111875,3,pass,0.165958;0.207458;0.172209 +random_masked_int64,70,420,8,pull64_barrier,0.222541,0.191167,0.032083,26880,8,1,0,0.111875,3,pass,0.299792;0.222541;0.215792 +random_masked_int64,70,420,8,pull64_interleaved,0.263458,0.214125,0.032958,26880,8,1,0,0.111875,3,pass,0.221292;0.263458;0.273541 +random_masked_int64,70,420,8,pull32_interleaved,0.259208,0.212417,0.033292,26880,8,1,1,0.111875,3,pass,0.264333;0.242292;0.259208 +random_masked_int64,70,420,8,pull32_gpu_dag,0.487792,0.185542,0.044083,26880,8,3,1,0.111875,3,pass,0.520042;0.487792;0.476084 +random_masked_int64,70,420,8,frontier32_vertex,0.228167,0.205667,0.033167,26880,8,1,1,0.111875,3,pass,0.228167;0.278209;0.213792 +random_masked_int64,70,420,8,frontier32_simd,0.235917,0.197334,0.029875,26880,8,1,1,0.111875,3,pass,0.249584;0.235917;0.206458 +random_masked_int64,70,420,8,frontier32_gpu_dag,0.552583,0.195792,0.047541,26880,8,3,1,0.111875,3,pass,0.552583;0.514250;0.567208 +random_masked_int64,70,420,8,bucket32_d4,0.213625,0.180917,0.031042,26880,8,1,1,0.111875,3,pass,0.189583;0.229083;0.213625 +random_masked_int64,70,420,8,bucket32_d16,0.200875,0.175083,0.030667,26880,8,1,1,0.111875,3,pass,0.199792;0.212792;0.200875 +random_masked_int64,70,420,8,bucket32_d64,0.226208,0.203666,0.033042,26880,8,1,1,0.111875,3,pass,0.226208;0.289750;0.209208 +random_masked_reverse,73,438,8,old_pull_serial,0.300875,0.279750,0.049167,56064,16,2,0,0.051958,3,pass,0.297583;0.322917;0.300875 +random_masked_reverse,73,438,8,old_group_serial,0.153167,0.131333,0.016917,30222,10,1,0,0.051958,3,pass,0.162833;0.153167;0.143875 +random_masked_reverse,73,438,8,old_pull_parallel_dag,0.357000,0.316083,0.052417,56064,16,2,0,0.051958,3,pass,0.357000;0.347458;0.368750 +random_masked_reverse,73,438,8,old_group_parallel_dag,0.172250,0.133250,0.017000,30222,10,1,0,0.051958,3,pass,0.161416;0.172250;0.179584 +random_masked_reverse,73,438,8,pull64_barrier,0.355208,0.325958,0.051917,56064,16,2,0,0.051958,3,pass,0.361458;0.338917;0.355208 +random_masked_reverse,73,438,8,pull64_interleaved,0.392041,0.358292,0.055250,56064,16,2,0,0.051958,3,pass,0.387334;0.392041;0.393834 +random_masked_reverse,73,438,8,pull32_interleaved,0.431125,0.388250,0.052375,56064,16,2,0,0.051958,3,pass,0.489459;0.376000;0.431125 +random_masked_reverse,73,438,8,pull32_gpu_dag,0.582458,0.309500,0.058208,56064,16,4,0,0.051958,3,pass,0.582458;0.564583;0.654625 +random_masked_reverse,73,438,8,frontier32_vertex,0.492000,0.452417,0.152417,5335,16,2,0,0.051958,3,pass,0.605959;0.474750;0.492000 +random_masked_reverse,73,438,8,frontier32_simd,0.459959,0.426417,0.108125,5335,16,2,0,0.051958,3,pass,0.473959;0.439375;0.459959 +random_masked_reverse,73,438,8,frontier32_gpu_dag,0.697459,0.393625,0.109375,5335,16,4,0,0.051958,3,pass,0.673333;0.697459;0.753833 +random_masked_reverse,73,438,8,bucket32_d4,0.955083,0.933583,0.309833,3179,32,4,0,0.051958,3,pass,1.078375;0.909541;0.955083 +random_masked_reverse,73,438,8,bucket32_d16,0.751875,0.705958,0.260042,3402,24,3,0,0.051958,3,pass,0.647541;0.751875;0.849292 +random_masked_reverse,73,438,8,bucket32_d64,0.562917,0.525875,0.168958,4984,16,2,0,0.051958,3,pass,0.564125;0.562917;0.562417 +boundary_700000000,6,10,6,old_pull_serial,0.153083,0.152292,0.015542,360,6,1,0,0.062626,3,pass,0.153083;0.153167;0.149625 +boundary_700000000,6,10,6,old_group_serial,0.116958,0.116291,0.007083,160,5,1,0,0.062626,3,pass,0.116958;0.116375;0.242875 +boundary_700000000,6,10,6,old_pull_parallel_dag,0.160958,0.133625,0.013250,360,6,1,0,0.062626,3,pass,0.160958;0.163917;0.160375 +boundary_700000000,6,10,6,old_group_parallel_dag,0.128709,0.114500,0.007042,160,5,1,0,0.062626,3,pass,0.132541;0.128666;0.128709 +boundary_700000000,6,10,6,pull64_barrier,0.170584,0.154583,0.015000,360,6,1,0,0.062626,3,pass,0.170584;0.153833;0.171750 +boundary_700000000,6,10,6,pull64_interleaved,0.190334,0.165417,0.015666,360,6,1,0,0.062626,3,pass,0.186125;0.199333;0.190334 +boundary_700000000,6,10,6,pull32_interleaved,0.209125,0.182333,0.017250,360,6,1,0,0.062626,3,pass,0.210917;0.208625;0.209125 +boundary_700000000,6,10,6,pull32_gpu_dag,0.464958,0.162958,0.024458,360,6,3,0,0.062626,3,pass,0.460833;0.464958;0.468666 +boundary_700000000,6,10,6,frontier32_vertex,0.206792,0.182250,0.045667,24,8,1,0,0.062626,3,pass,0.243416;0.187625;0.206792 +boundary_700000000,6,10,6,frontier32_simd,0.193166,0.173584,0.042917,24,8,1,0,0.062626,3,pass,0.192167;0.212625;0.193166 +boundary_700000000,6,10,6,frontier32_gpu_dag,0.534000,0.215708,0.059417,24,8,3,0,0.062626,3,pass,0.534000;0.603250;0.530958 +boundary_700000000,6,10,6,bucket32_d4,0.290250,0.259750,0.085292,24,8,1,0,0.062626,3,pass,0.274625;0.290250;0.293083 +boundary_700000000,6,10,6,bucket32_d16,0.269250,0.236084,0.071083,24,8,1,0,0.062626,3,pass,0.265084;0.269250;0.281958 +boundary_700000000,6,10,6,bucket32_d64,0.271583,0.238833,0.073458,24,8,1,0,0.062626,3,pass,0.271583;0.256542;0.276333 +boundary_700000000_masked,6,10,6,old_pull_serial,0.132750,0.132042,0.013667,360,6,1,0,0.047500,3,pass,0.132750;0.225500;0.121625 +boundary_700000000_masked,6,10,6,old_group_serial,0.111833,0.111250,0.004667,80,2,1,0,0.047500,3,pass,0.111833;0.112875;0.109333 +boundary_700000000_masked,6,10,6,old_pull_parallel_dag,0.168000,0.135250,0.012875,360,6,1,0,0.047500,3,pass,0.168000;0.158167;0.168750 +boundary_700000000_masked,6,10,6,old_group_parallel_dag,0.151708,0.120958,0.004750,80,2,1,0,0.047500,3,pass,0.151708;0.149333;0.182959 +boundary_700000000_masked,6,10,6,pull64_barrier,0.190958,0.166041,0.015125,360,6,1,0,0.047500,3,pass,0.192667;0.190958;0.189958 +boundary_700000000_masked,6,10,6,pull64_interleaved,0.225917,0.194458,0.018250,360,6,1,0,0.047500,3,pass,0.226292;0.225917;0.211375 +boundary_700000000_masked,6,10,6,pull32_interleaved,0.214167,0.182959,0.017125,360,6,1,0,0.047500,3,pass,0.203500;0.214167;0.214666 +boundary_700000000_masked,6,10,6,pull32_gpu_dag,0.430208,0.142292,0.023583,360,6,3,0,0.047500,3,pass,0.430208;0.390208;0.433958 +boundary_700000000_masked,6,10,6,frontier32_vertex,0.235250,0.204875,0.044042,12,8,1,0,0.047500,3,pass,0.200750;0.235250;0.336958 +boundary_700000000_masked,6,10,6,frontier32_simd,0.249875,0.226667,0.048375,12,8,1,0,0.047500,3,pass,0.229167;0.284334;0.249875 +boundary_700000000_masked,6,10,6,frontier32_gpu_dag,0.571417,0.221708,0.060708,12,8,3,0,0.047500,3,pass,0.590542;0.571417;0.537625 +boundary_700000000_masked,6,10,6,bucket32_d4,0.279708,0.235917,0.070375,12,8,1,0,0.047500,3,pass,0.288167;0.279708;0.246584 +boundary_700000000_masked,6,10,6,bucket32_d16,0.228500,0.209750,0.070083,12,8,1,0,0.047500,3,pass,0.230209;0.228500;0.226459 +boundary_700000000_masked,6,10,6,bucket32_d64,0.295334,0.261667,0.068250,12,8,1,0,0.047500,3,pass,0.273459;0.310292;0.295334 +boundary_700000000_reverse,6,10,6,old_pull_serial,0.152542,0.151750,0.015375,360,6,1,0,0.044708,3,pass,0.152542;0.150625;0.153958 +boundary_700000000_reverse,6,10,6,old_group_serial,0.129375,0.128625,0.007375,170,5,1,0,0.044708,3,pass,0.126500;0.129375;0.135750 +boundary_700000000_reverse,6,10,6,old_pull_parallel_dag,0.185333,0.156667,0.015708,360,6,1,0,0.044708,3,pass,0.180541;0.191708;0.185333 +boundary_700000000_reverse,6,10,6,old_group_parallel_dag,0.170542,0.140583,0.007250,170,5,1,0,0.044708,3,pass,0.187292;0.148292;0.170542 +boundary_700000000_reverse,6,10,6,pull64_barrier,0.214917,0.190417,0.017583,360,6,1,0,0.044708,3,pass,0.213458;0.214917;0.243917 +boundary_700000000_reverse,6,10,6,pull64_interleaved,0.220292,0.166458,0.014958,360,6,1,0,0.044708,3,pass,0.222792;0.175083;0.220292 +boundary_700000000_reverse,6,10,6,pull32_interleaved,0.183500,0.156458,0.015083,360,6,1,0,0.044708,3,pass,0.183500;0.189625;0.182834 +boundary_700000000_reverse,6,10,6,pull32_gpu_dag,0.519917,0.169750,0.024042,360,6,3,0,0.044708,3,pass,0.519917;0.465250;0.537625 +boundary_700000000_reverse,6,10,6,frontier32_vertex,0.216000,0.187417,0.045292,24,8,1,0,0.044708,3,pass,0.213500;0.216000;0.237334 +boundary_700000000_reverse,6,10,6,frontier32_simd,0.246041,0.220042,0.043667,24,8,1,0,0.044708,3,pass,0.229209;0.246041;0.273709 +boundary_700000000_reverse,6,10,6,frontier32_gpu_dag,0.523833,0.220750,0.060375,24,8,3,0,0.044708,3,pass,0.523833;0.498833;0.540417 +boundary_700000000_reverse,6,10,6,bucket32_d4,0.240041,0.214875,0.074250,24,8,1,0,0.044708,3,pass,0.240041;0.244500;0.230375 +boundary_700000000_reverse,6,10,6,bucket32_d16,0.362708,0.330541,0.084500,24,8,1,0,0.044708,3,pass,0.397958;0.301208;0.362708 +boundary_700000000_reverse,6,10,6,bucket32_d64,0.333583,0.250791,0.068667,24,8,1,0,0.044708,3,pass,0.347292;0.333583;0.265750 +boundary_700000000_reverse_masked,6,10,6,old_pull_serial,0.137542,0.136750,0.012625,360,6,1,0,0.065000,3,pass,0.137542;0.134292;0.138000 +boundary_700000000_reverse_masked,6,10,6,old_group_serial,0.120291,0.119625,0.004708,90,2,1,0,0.065000,3,pass,0.125916;0.119667;0.120291 +boundary_700000000_reverse_masked,6,10,6,old_pull_parallel_dag,0.176375,0.136833,0.012625,360,6,1,0,0.065000,3,pass,0.158458;0.181459;0.176375 +boundary_700000000_reverse_masked,6,10,6,old_group_parallel_dag,0.151667,0.128583,0.004750,90,2,1,0,0.065000,3,pass,0.167542;0.151667;0.147500 +boundary_700000000_reverse_masked,6,10,6,pull64_barrier,0.200709,0.166916,0.015167,360,6,1,0,0.065000,3,pass,0.200709;0.212041;0.181625 +boundary_700000000_reverse_masked,6,10,6,pull64_interleaved,0.226166,0.190208,0.017125,360,6,1,0,0.065000,3,pass,0.279458;0.226166;0.219291 +boundary_700000000_reverse_masked,6,10,6,pull32_interleaved,0.195708,0.164333,0.014333,360,6,1,0,0.065000,3,pass,0.306500;0.195708;0.174541 +boundary_700000000_reverse_masked,6,10,6,pull32_gpu_dag,0.511625,0.188000,0.027583,360,6,3,0,0.065000,3,pass,0.499792;0.511625;0.520417 +boundary_700000000_reverse_masked,6,10,6,frontier32_vertex,0.249584,0.218250,0.049750,9,8,1,0,0.065000,3,pass,0.260375;0.237958;0.249584 +boundary_700000000_reverse_masked,6,10,6,frontier32_simd,0.192000,0.174375,0.042500,9,8,1,0,0.065000,3,pass,0.222542;0.188917;0.192000 +boundary_700000000_reverse_masked,6,10,6,frontier32_gpu_dag,0.520750,0.196708,0.051583,9,8,3,0,0.065000,3,pass,0.499458;0.557625;0.520750 +boundary_700000000_reverse_masked,6,10,6,bucket32_d4,0.279375,0.251042,0.081875,9,8,1,0,0.065000,3,pass,0.264584;0.296875;0.279375 +boundary_700000000_reverse_masked,6,10,6,bucket32_d16,0.287792,0.265666,0.081750,9,8,1,0,0.065000,3,pass,0.274875;0.287792;0.295458 +boundary_700000000_reverse_masked,6,10,6,bucket32_d64,0.289625,0.255250,0.068125,9,8,1,0,0.065000,3,pass,0.312834;0.289625;0.250416 +boundary_715827883,6,10,6,old_pull_serial,0.120209,0.119500,0.013125,360,6,1,0,0.058791,3,pass,0.127541;0.120209;0.119917 +boundary_715827883,6,10,6,old_group_serial,0.107166,0.106500,0.006875,160,5,1,0,0.058791,3,pass,0.104417;0.107166;0.108041 +boundary_715827883,6,10,6,old_pull_parallel_dag,0.154000,0.125000,0.013250,360,6,1,0,0.058791,3,pass,0.144125;0.154000;0.171916 +boundary_715827883,6,10,6,old_group_parallel_dag,0.149500,0.114125,0.006875,160,5,1,0,0.058791,3,pass,0.149500;0.140417;0.221042 +boundary_715827883,6,10,6,pull64_barrier,0.222166,0.191750,0.018375,360,6,1,0,0.058791,3,pass,0.214458;0.222166;0.228209 +boundary_715827883,6,10,6,pull64_interleaved,0.189958,0.162959,0.015000,360,6,1,0,0.058791,3,pass,0.184833;0.189958;0.197084 +boundary_715827883,6,10,6,pull32_interleaved,0.192500,0.168000,0.015125,360,6,1,1,0.058791,3,pass,0.192500;0.184500;0.219584 +boundary_715827883,6,10,6,pull32_gpu_dag,0.479250,0.158583,0.024750,360,6,3,1,0.058791,3,pass,0.643291;0.422334;0.479250 +boundary_715827883,6,10,6,frontier32_vertex,0.198375,0.168625,0.015708,360,6,1,1,0.058791,3,pass,0.198375;0.200375;0.183875 +boundary_715827883,6,10,6,frontier32_simd,0.195458,0.156708,0.015750,360,6,1,1,0.058791,3,pass,0.195458;0.203875;0.169375 +boundary_715827883,6,10,6,frontier32_gpu_dag,0.538875,0.189083,0.028750,360,6,3,1,0.058791,3,pass,0.538875;0.638625;0.527042 +boundary_715827883,6,10,6,bucket32_d4,0.226209,0.195500,0.018375,360,6,1,1,0.058791,3,pass,0.226209;0.233750;0.219250 +boundary_715827883,6,10,6,bucket32_d16,0.195584,0.172416,0.015000,360,6,1,1,0.058791,3,pass,0.194333;0.195584;0.202875 +boundary_715827883,6,10,6,bucket32_d64,0.167458,0.142375,0.015125,360,6,1,1,0.058791,3,pass,0.156583;0.167458;0.173500 +boundary_715827883_masked,6,10,6,old_pull_serial,0.122709,0.122167,0.012750,360,6,1,0,0.041375,3,pass,0.124458;0.122709;0.118166 +boundary_715827883_masked,6,10,6,old_group_serial,0.114333,0.113750,0.004750,80,2,1,0,0.041375,3,pass,0.105541;0.117458;0.114333 +boundary_715827883_masked,6,10,6,old_pull_parallel_dag,0.189625,0.160583,0.012750,360,6,1,0,0.041375,3,pass,0.239917;0.189625;0.162708 +boundary_715827883_masked,6,10,6,old_group_parallel_dag,0.177833,0.145375,0.004750,80,2,1,0,0.041375,3,pass,0.204292;0.177833;0.157375 +boundary_715827883_masked,6,10,6,pull64_barrier,0.228125,0.197083,0.018375,360,6,1,0,0.041375,3,pass,0.251083;0.210958;0.228125 +boundary_715827883_masked,6,10,6,pull64_interleaved,0.184666,0.154875,0.015125,360,6,1,0,0.041375,3,pass,0.184666;0.182042;0.220166 +boundary_715827883_masked,6,10,6,pull32_interleaved,0.194125,0.165958,0.015375,360,6,1,1,0.041375,3,pass,0.187125;0.194125;0.205083 +boundary_715827883_masked,6,10,6,pull32_gpu_dag,0.492167,0.173541,0.025833,360,6,3,1,0.041375,3,pass,0.472000;0.507250;0.492167 +boundary_715827883_masked,6,10,6,frontier32_vertex,0.177375,0.156958,0.015334,360,6,1,1,0.041375,3,pass,0.177375;0.174542;0.179959 +boundary_715827883_masked,6,10,6,frontier32_simd,0.198167,0.164041,0.016083,360,6,1,1,0.041375,3,pass,0.183417;0.198167;0.200417 +boundary_715827883_masked,6,10,6,frontier32_gpu_dag,0.472833,0.168333,0.023292,360,6,3,1,0.041375,3,pass,0.462959;0.472833;0.561042 +boundary_715827883_masked,6,10,6,bucket32_d4,0.206875,0.162125,0.015000,360,6,1,1,0.041375,3,pass,0.206875;0.183792;0.220083 +boundary_715827883_masked,6,10,6,bucket32_d16,0.220500,0.186875,0.018250,360,6,1,1,0.041375,3,pass,0.223125;0.210041;0.220500 +boundary_715827883_masked,6,10,6,bucket32_d64,0.221208,0.187541,0.018250,360,6,1,1,0.041375,3,pass,0.221208;0.235125;0.213209 +boundary_715827883_reverse,6,10,6,old_pull_serial,0.133417,0.132625,0.012792,360,6,1,0,0.054333,3,pass,0.124125;0.133417;0.135875 +boundary_715827883_reverse,6,10,6,old_group_serial,0.118458,0.117417,0.006833,170,5,1,0,0.054333,3,pass,0.122917;0.118458;0.112583 +boundary_715827883_reverse,6,10,6,old_pull_parallel_dag,0.165083,0.128666,0.013000,360,6,1,0,0.054333,3,pass,0.169708;0.165083;0.153750 +boundary_715827883_reverse,6,10,6,old_group_parallel_dag,0.142916,0.115625,0.006833,170,5,1,0,0.054333,3,pass,0.133959;0.142916;0.147958 +boundary_715827883_reverse,6,10,6,pull64_barrier,0.178375,0.160750,0.014750,360,6,1,0,0.054333,3,pass,0.178208;0.178375;0.178792 +boundary_715827883_reverse,6,10,6,pull64_interleaved,0.158041,0.141666,0.014167,360,6,1,0,0.054333,3,pass,0.156916;0.254833;0.158041 +boundary_715827883_reverse,6,10,6,pull32_interleaved,0.164167,0.149250,0.014958,360,6,1,1,0.054333,3,pass,0.164042;0.189750;0.164167 +boundary_715827883_reverse,6,10,6,pull32_gpu_dag,0.538250,0.199834,0.027083,360,6,3,1,0.054333,3,pass,0.539208;0.538250;0.507209 +boundary_715827883_reverse,6,10,6,frontier32_vertex,0.203375,0.173375,0.014250,360,6,1,1,0.054333,3,pass,0.203375;0.195083;0.226000 +boundary_715827883_reverse,6,10,6,frontier32_simd,0.196125,0.162666,0.014417,360,6,1,1,0.054333,3,pass,0.185291;0.196125;0.244042 +boundary_715827883_reverse,6,10,6,frontier32_gpu_dag,0.488000,0.175500,0.027667,360,6,3,1,0.054333,3,pass,0.488000;0.462750;0.532166 +boundary_715827883_reverse,6,10,6,bucket32_d4,0.164000,0.148625,0.014542,360,6,1,1,0.054333,3,pass,0.164000;0.152834;0.167458 +boundary_715827883_reverse,6,10,6,bucket32_d16,0.195000,0.168500,0.014708,360,6,1,1,0.054333,3,pass,0.188333;0.256042;0.195000 +boundary_715827883_reverse,6,10,6,bucket32_d64,0.212875,0.184917,0.017666,360,6,1,1,0.054333,3,pass,0.208166;0.344916;0.212875 +boundary_715827883_reverse_masked,6,10,6,old_pull_serial,0.150292,0.149625,0.015375,360,6,1,0,0.052417,3,pass,0.126208;0.150458;0.150292 +boundary_715827883_reverse_masked,6,10,6,old_group_serial,0.127916,0.127333,0.004750,90,2,1,0,0.052417,3,pass,0.127916;0.134125;0.119375 +boundary_715827883_reverse_masked,6,10,6,old_pull_parallel_dag,0.164542,0.136541,0.013125,360,6,1,0,0.052417,3,pass,0.181750;0.164542;0.151083 +boundary_715827883_reverse_masked,6,10,6,old_group_parallel_dag,0.154042,0.127375,0.004875,90,2,1,0,0.052417,3,pass,0.154042;0.156250;0.153292 +boundary_715827883_reverse_masked,6,10,6,pull64_barrier,0.200333,0.165125,0.015125,360,6,1,0,0.052417,3,pass,0.200333;0.199875;0.204416 +boundary_715827883_reverse_masked,6,10,6,pull64_interleaved,0.210792,0.185334,0.017625,360,6,1,0,0.052417,3,pass,0.227500;0.210792;0.200375 +boundary_715827883_reverse_masked,6,10,6,pull32_interleaved,0.217375,0.185084,0.017625,360,6,1,1,0.052417,3,pass,0.217833;0.217375;0.195375 +boundary_715827883_reverse_masked,6,10,6,pull32_gpu_dag,0.515250,0.196792,0.027292,360,6,3,1,0.052417,3,pass,0.515250;0.479500;0.549708 +boundary_715827883_reverse_masked,6,10,6,frontier32_vertex,0.219458,0.190250,0.017667,360,6,1,1,0.052417,3,pass,0.219458;0.250125;0.216333 +boundary_715827883_reverse_masked,6,10,6,frontier32_simd,0.212375,0.181250,0.017625,360,6,1,1,0.052417,3,pass,0.194709;0.212375;0.214000 +boundary_715827883_reverse_masked,6,10,6,frontier32_gpu_dag,0.486708,0.177208,0.027583,360,6,3,1,0.052417,3,pass,0.479000;0.493500;0.486708 +boundary_715827883_reverse_masked,6,10,6,bucket32_d4,0.193167,0.156750,0.014750,360,6,1,1,0.052417,3,pass,0.193167;0.200750;0.182042 +boundary_715827883_reverse_masked,6,10,6,bucket32_d16,0.192625,0.164209,0.015333,360,6,1,1,0.052417,3,pass,0.192625;0.185167;0.198417 +boundary_715827883_reverse_masked,6,10,6,bucket32_d64,0.208375,0.186750,0.017542,360,6,1,1,0.052417,3,pass,0.200917;0.218917;0.208375 +boundary_9007199254740993,6,10,6,old_pull_serial,0.148291,0.147583,0.015875,360,6,1,0,0.073999,3,pass,0.148291;0.147667;0.150250 +boundary_9007199254740993,6,10,6,old_group_serial,0.111833,0.111167,0.006917,160,5,1,0,0.073999,3,pass,0.109625;0.111833;0.127792 +boundary_9007199254740993,6,10,6,old_pull_parallel_dag,0.181458,0.154458,0.015750,360,6,1,0,0.073999,3,pass,0.184667;0.181458;0.176167 +boundary_9007199254740993,6,10,6,old_group_parallel_dag,0.149375,0.119625,0.007125,160,5,1,0,0.073999,3,pass,0.164833;0.147291;0.149375 +boundary_9007199254740993,6,10,6,pull64_barrier,0.200917,0.170292,0.015292,360,6,1,0,0.073999,3,pass,0.199125;0.200917;0.205000 +boundary_9007199254740993,6,10,6,pull64_interleaved,0.212291,0.186167,0.015042,360,6,1,0,0.073999,3,pass,0.212291;0.209834;0.279417 +boundary_9007199254740993,6,10,6,pull32_interleaved,0.159792,0.142750,0.014667,360,6,1,1,0.073999,3,pass,0.167709;0.159042;0.159792 +boundary_9007199254740993,6,10,6,pull32_gpu_dag,0.554792,0.159666,0.029250,360,6,3,1,0.073999,3,pass,0.554792;0.493083;0.578709 +boundary_9007199254740993,6,10,6,frontier32_vertex,0.185416,0.153667,0.017792,360,6,1,1,0.073999,3,pass,0.176292;0.185416;0.188042 +boundary_9007199254740993,6,10,6,frontier32_simd,0.187125,0.155875,0.018250,360,6,1,1,0.073999,3,pass,0.174750;0.187125;0.191708 +boundary_9007199254740993,6,10,6,frontier32_gpu_dag,0.415458,0.156042,0.025916,360,6,3,1,0.073999,3,pass,0.415458;0.400750;0.484833 +boundary_9007199254740993,6,10,6,bucket32_d4,0.176666,0.146292,0.014875,360,6,1,1,0.073999,3,pass,0.210084;0.176666;0.135250 +boundary_9007199254740993,6,10,6,bucket32_d16,0.132542,0.115500,0.014917,360,6,1,1,0.073999,3,pass,0.136166;0.132542;0.130709 +boundary_9007199254740993,6,10,6,bucket32_d64,0.137417,0.121500,0.015042,360,6,1,1,0.073999,3,pass,0.137417;0.129125;0.195834 +boundary_9007199254740993_masked,6,10,6,old_pull_serial,0.105291,0.104750,0.012833,360,6,1,0,0.054125,3,pass,0.107125;0.104375;0.105291 +boundary_9007199254740993_masked,6,10,6,old_group_serial,0.095459,0.094708,0.005041,80,2,1,0,0.054125,3,pass,0.093375;0.174292;0.095459 +boundary_9007199254740993_masked,6,10,6,old_pull_parallel_dag,0.215208,0.159625,0.014791,360,6,1,0,0.054125,3,pass,0.219666;0.215208;0.155541 +boundary_9007199254740993_masked,6,10,6,old_group_parallel_dag,0.135333,0.106834,0.004625,80,2,1,0,0.054125,3,pass,0.133708;0.135625;0.135333 +boundary_9007199254740993_masked,6,10,6,pull64_barrier,0.188291,0.151667,0.018125,360,6,1,0,0.054125,3,pass,0.188291;0.192292;0.160167 +boundary_9007199254740993_masked,6,10,6,pull64_interleaved,0.179083,0.156084,0.018250,360,6,1,0,0.054125,3,pass,0.178208;0.197125;0.179083 +boundary_9007199254740993_masked,6,10,6,pull32_interleaved,0.179709,0.150083,0.018125,360,6,1,1,0.054125,3,pass,0.179709;0.174000;0.180917 +boundary_9007199254740993_masked,6,10,6,pull32_gpu_dag,0.349458,0.133792,0.023625,360,6,3,1,0.054125,3,pass,0.546208;0.344834;0.349458 +boundary_9007199254740993_masked,6,10,6,frontier32_vertex,0.131041,0.115417,0.014500,360,6,1,1,0.054125,3,pass,0.136250;0.131041;0.129208 +boundary_9007199254740993_masked,6,10,6,frontier32_simd,0.136125,0.119875,0.015000,360,6,1,1,0.054125,3,pass,0.136125;0.128042;0.141625 +boundary_9007199254740993_masked,6,10,6,frontier32_gpu_dag,0.478416,0.157208,0.027375,360,6,3,1,0.054125,3,pass,0.553709;0.478416;0.475792 +boundary_9007199254740993_masked,6,10,6,bucket32_d4,0.214250,0.193083,0.015500,360,6,1,1,0.054125,3,pass,0.163333;0.214250;0.219959 +boundary_9007199254740993_masked,6,10,6,bucket32_d16,0.168917,0.144875,0.015000,360,6,1,1,0.054125,3,pass,0.181250;0.156250;0.168917 +boundary_9007199254740993_masked,6,10,6,bucket32_d64,0.142958,0.125459,0.015375,360,6,1,1,0.054125,3,pass,0.129083;0.147166;0.142958 +boundary_9007199254740993_reverse,6,10,6,old_pull_serial,0.105875,0.105083,0.013125,360,6,1,0,0.050126,3,pass,0.102041;0.107958;0.105875 +boundary_9007199254740993_reverse,6,10,6,old_group_serial,0.092250,0.091500,0.006917,170,5,1,0,0.050126,3,pass,0.092250;0.097667;0.092209 +boundary_9007199254740993_reverse,6,10,6,old_pull_parallel_dag,0.123375,0.107333,0.013250,360,6,1,0,0.050126,3,pass,0.150458;0.118958;0.123375 +boundary_9007199254740993_reverse,6,10,6,old_group_parallel_dag,0.132916,0.101792,0.007125,170,5,1,0,0.050126,3,pass,0.132916;0.136167;0.130209 +boundary_9007199254740993_reverse,6,10,6,pull64_barrier,0.189875,0.154125,0.017500,360,6,1,0,0.050126,3,pass,0.189209;0.189875;0.196541 +boundary_9007199254740993_reverse,6,10,6,pull64_interleaved,0.183333,0.161208,0.017625,360,6,1,0,0.050126,3,pass,0.192208;0.182208;0.183333 +boundary_9007199254740993_reverse,6,10,6,pull32_interleaved,0.188125,0.153708,0.017625,360,6,1,1,0.050126,3,pass,0.178292;0.188125;0.288375 +boundary_9007199254740993_reverse,6,10,6,pull32_gpu_dag,0.359916,0.136875,0.023292,360,6,3,1,0.050126,3,pass,0.359916;0.428209;0.350042 +boundary_9007199254740993_reverse,6,10,6,frontier32_vertex,0.152250,0.128333,0.014125,360,6,1,1,0.050126,3,pass,0.152250;0.126959;0.154625 +boundary_9007199254740993_reverse,6,10,6,frontier32_simd,0.179542,0.141500,0.014250,360,6,1,1,0.050126,3,pass,0.168500;0.179542;0.238833 +boundary_9007199254740993_reverse,6,10,6,frontier32_gpu_dag,0.379959,0.137208,0.023500,360,6,3,1,0.050126,3,pass,0.380500;0.358625;0.379959 +boundary_9007199254740993_reverse,6,10,6,bucket32_d4,0.196292,0.171875,0.014500,360,6,1,1,0.050126,3,pass,0.163083;0.196292;0.347041 +boundary_9007199254740993_reverse,6,10,6,bucket32_d16,0.175666,0.155333,0.014958,360,6,1,1,0.050126,3,pass,0.157667;0.231708;0.175666 +boundary_9007199254740993_reverse,6,10,6,bucket32_d64,0.190459,0.151084,0.015333,360,6,1,1,0.050126,3,pass,0.240750;0.190459;0.167292 +boundary_9007199254740993_reverse_masked,6,10,6,old_pull_serial,0.124667,0.124083,0.015542,360,6,1,0,0.052000,3,pass,0.124750;0.124667;0.123667 +boundary_9007199254740993_reverse_masked,6,10,6,old_group_serial,0.099584,0.098583,0.004750,90,2,1,0,0.052000,3,pass,0.100834;0.093209;0.099584 +boundary_9007199254740993_reverse_masked,6,10,6,old_pull_parallel_dag,0.153292,0.125583,0.015208,360,6,1,0,0.052000,3,pass,0.153292;0.151333;0.153875 +boundary_9007199254740993_reverse_masked,6,10,6,old_group_parallel_dag,0.127750,0.094666,0.004750,90,2,1,0,0.052000,3,pass,0.120042;0.129625;0.127750 +boundary_9007199254740993_reverse_masked,6,10,6,pull64_barrier,0.219833,0.181916,0.015375,360,6,1,0,0.052000,3,pass,0.148166;0.282542;0.219833 +boundary_9007199254740993_reverse_masked,6,10,6,pull64_interleaved,0.188667,0.157459,0.017625,360,6,1,0,0.052000,3,pass,0.188667;0.161000;0.282667 +boundary_9007199254740993_reverse_masked,6,10,6,pull32_interleaved,0.184958,0.157708,0.017792,360,6,1,1,0.052000,3,pass,0.199709;0.184958;0.184500 +boundary_9007199254740993_reverse_masked,6,10,6,pull32_gpu_dag,0.490041,0.163625,0.027375,360,6,3,1,0.052000,3,pass,0.540292;0.427375;0.490041 +boundary_9007199254740993_reverse_masked,6,10,6,frontier32_vertex,0.221041,0.194458,0.017542,360,6,1,1,0.052000,3,pass,0.221041;0.194292;0.230875 +boundary_9007199254740993_reverse_masked,6,10,6,frontier32_simd,0.172083,0.145625,0.015625,360,6,1,1,0.052000,3,pass,0.174542;0.172083;0.160959 +boundary_9007199254740993_reverse_masked,6,10,6,frontier32_gpu_dag,0.492375,0.153000,0.026167,360,6,3,1,0.052000,3,pass,0.492375;0.613458;0.419833 +boundary_9007199254740993_reverse_masked,6,10,6,bucket32_d4,0.183167,0.154000,0.014375,360,6,1,1,0.052000,3,pass,0.183167;0.158125;0.202250 +boundary_9007199254740993_reverse_masked,6,10,6,bucket32_d16,0.190542,0.156167,0.018000,360,6,1,1,0.052000,3,pass,0.190542;0.196500;0.181542 +boundary_9007199254740993_reverse_masked,6,10,6,bucket32_d64,0.186166,0.161334,0.017917,360,6,1,1,0.052000,3,pass,0.186166;0.183459;0.225917 diff --git a/dev/research/metal_pathfinding/optimization/results/cpu-algorithms-aba/a1-stderr.txt b/dev/research/metal_pathfinding/optimization/results/cpu-algorithms-aba/a1-stderr.txt new file mode 100644 index 0000000..e69de29 diff --git a/dev/research/metal_pathfinding/optimization/results/cpu-algorithms-aba/a1.csv b/dev/research/metal_pathfinding/optimization/results/cpu-algorithms-aba/a1.csv new file mode 100644 index 0000000..fdbf690 --- /dev/null +++ b/dev/research/metal_pathfinding/optimization/results/cpu-algorithms-aba/a1.csv @@ -0,0 +1,15 @@ +case,n,e,queries,method,wall_ms,samples,correct,wall_samples_ms +random,1024,8192,1,cpu_heap_cached_full,0.052958,7,pass,0.055375;0.051625;0.052917;0.051458;0.052958;0.058583;0.058166 +random,1024,8192,1,cpu_dial_full,0.027667,7,pass,0.030167;0.030541;0.028125;0.027667;0.027250;0.026833;0.026375 +random,4096,32768,256,cpu_heap_cached_full,13.029500,7,pass,13.029500;13.040792;13.013792;13.009291;13.009958;13.036750;14.042792 +random,4096,32768,256,cpu_dial_full,7.056208,7,pass,7.469875;7.434375;7.234209;6.965958;6.996125;7.056208;7.033417 +random,16384,131072,64,cpu_heap_cached_full,17.500459,7,pass,17.562542;17.286708;17.264542;17.357083;17.652583;17.583833;17.500459 +random,16384,131072,64,cpu_dial_full,7.696333,7,pass,7.668375;7.706958;7.745167;7.718791;7.696333;7.663042;7.625000 +random,65536,524288,1,cpu_heap_cached_full,11.474125,7,pass,11.148208;11.188916;11.564208;11.558541;11.339750;11.482000;11.474125 +random,65536,524288,1,cpu_dial_full,4.384459,7,pass,4.454542;4.378833;4.385375;4.329667;4.531666;4.312333;4.384459 +random,4096,131072,64,cpu_heap_cached_full,6.672416,7,pass,6.661917;6.739334;6.643583;6.657541;6.681834;6.698125;6.672416 +random,4096,131072,64,cpu_dial_full,3.853958,7,pass,3.851458;3.853958;3.815916;3.857375;3.879833;3.874917;3.831292 +clos,800,320000,64,cpu_heap_cached_full,5.124625,7,pass,5.071875;5.124625;5.096666;5.870542;5.049958;5.355042;5.716333 +clos,800,320000,64,cpu_dial_full,5.421083,7,pass,5.830666;5.848000;5.917417;5.170042;5.150375;5.105084;5.421083 +grid,10000,39600,1,cpu_heap_cached_full,0.200833,7,pass,0.200833;0.257167;0.200416;0.202250;0.192083;0.180000;0.204292 +grid,10000,39600,1,cpu_dial_full,0.126041,7,pass,0.119416;0.116334;0.126041;0.115459;0.129583;0.129291;0.132166 diff --git a/dev/research/metal_pathfinding/optimization/results/cpu-algorithms-aba/a2-stderr.txt b/dev/research/metal_pathfinding/optimization/results/cpu-algorithms-aba/a2-stderr.txt new file mode 100644 index 0000000..e69de29 diff --git a/dev/research/metal_pathfinding/optimization/results/cpu-algorithms-aba/a2.csv b/dev/research/metal_pathfinding/optimization/results/cpu-algorithms-aba/a2.csv new file mode 100644 index 0000000..024e84a --- /dev/null +++ b/dev/research/metal_pathfinding/optimization/results/cpu-algorithms-aba/a2.csv @@ -0,0 +1,15 @@ +case,n,e,queries,method,wall_ms,samples,correct,wall_samples_ms +random,1024,8192,1,cpu_heap_cached_full,0.059333,7,pass,0.061000;0.064709;0.059916;0.058375;0.058000;0.059333;0.052125 +random,1024,8192,1,cpu_dial_full,0.030000,7,pass,0.034542;0.033125;0.031083;0.029209;0.027208;0.027000;0.030000 +random,4096,32768,256,cpu_heap_cached_full,13.024459,7,pass,13.041833;13.021250;13.009584;13.024459;13.033625;13.042542;12.991958 +random,4096,32768,256,cpu_dial_full,6.924667,7,pass,7.101083;6.924792;7.021833;6.864833;6.924667;6.870667;6.819209 +random,16384,131072,64,cpu_heap_cached_full,17.268250,7,pass,17.273042;17.266000;17.288208;17.268250;17.267209;17.275833;17.255375 +random,16384,131072,64,cpu_dial_full,7.677208,7,pass,7.677208;7.706875;7.657458;7.665875;7.719333;7.661292;7.683000 +random,65536,524288,1,cpu_heap_cached_full,11.530166,7,pass,11.564417;11.470750;11.483750;11.310125;11.569583;11.530166;11.626875 +random,65536,524288,1,cpu_dial_full,4.372167,7,pass,4.378333;4.454333;4.364667;4.227000;4.345917;4.372167;4.389167 +random,4096,131072,64,cpu_heap_cached_full,6.661792,7,pass,6.657041;6.646792;6.646166;6.707916;6.693375;6.663542;6.661792 +random,4096,131072,64,cpu_dial_full,3.865375,7,pass,3.805375;3.811917;3.905625;3.897042;3.809458;3.865375;3.871209 +clos,800,320000,64,cpu_heap_cached_full,5.390792,7,pass,5.126500;5.165833;15.349250;5.390792;5.835791;5.412709;5.085000 +clos,800,320000,64,cpu_dial_full,5.537125,7,pass,5.858500;5.165833;5.832709;5.052833;5.651083;5.096667;5.537125 +grid,10000,39600,1,cpu_heap_cached_full,0.193709,7,pass,0.196375;0.197750;0.194000;0.193083;0.193208;0.193500;0.193709 +grid,10000,39600,1,cpu_dial_full,0.128833,7,pass,0.125792;0.133583;0.128833;0.130583;0.127667;0.127958;0.137959 diff --git a/dev/research/metal_pathfinding/optimization/results/cpu-algorithms-aba/b-stderr.txt b/dev/research/metal_pathfinding/optimization/results/cpu-algorithms-aba/b-stderr.txt new file mode 100644 index 0000000..3f8d1ea --- /dev/null +++ b/dev/research/metal_pathfinding/optimization/results/cpu-algorithms-aba/b-stderr.txt @@ -0,0 +1 @@ +device=Apple M4 Max setup_ms=23.7095 execution_width=32 diff --git a/dev/research/metal_pathfinding/optimization/results/cpu-algorithms-aba/b.csv b/dev/research/metal_pathfinding/optimization/results/cpu-algorithms-aba/b.csv new file mode 100644 index 0000000..0abc818 --- /dev/null +++ b/dev/research/metal_pathfinding/optimization/results/cpu-algorithms-aba/b.csv @@ -0,0 +1,217 @@ +case,n,e,queries,method,wall_ms,distance_ms,gpu_ms,edge_visits,rounds,waits,fallback64,upload_ms,samples,correct,wall_samples_ms +random,1024,8192,1,old_pull_parallel_dag,0.735000,0.722250,0.424250,131072,16,2,0,0.152417,7,pass,1.450333;1.486334;0.967291;0.691833;0.685125;0.682417;0.735000 +random,1024,8192,1,old_group_parallel_dag,0.894458,0.850750,0.680500,106496,13,1,0,0.152417,7,pass,0.924500;0.981625;0.889666;0.890459;0.909083;0.894458;0.841666 +random,1024,8192,1,pull64_barrier,0.665000,0.652208,0.384125,131072,16,2,0,0.152417,7,pass,0.679666;0.653042;0.631167;0.737750;0.683292;0.665000;0.658708 +random,1024,8192,1,pull64_interleaved,0.659958,0.647541,0.378167,131072,16,2,0,0.152417,7,pass,0.666709;0.682333;0.666000;0.656667;0.631250;0.628625;0.659958 +random,1024,8192,1,pull32_interleaved,0.633625,0.621125,0.349458,131072,16,2,0,0.152417,7,pass,0.630000;0.633625;0.646917;0.592625;0.621542;0.675042;0.679750 +random,1024,8192,1,pull32_gpu_dag,0.990667,0.586750,0.402625,131072,16,4,0,0.152417,7,pass,0.929750;0.903791;1.223750;1.103542;0.990667;1.068833;0.932250 +random,1024,8192,1,frontier32_vertex,0.956250,0.942417,0.645375,21088,16,2,0,0.152417,7,pass,0.942042;0.919167;0.956250;0.913625;0.964292;0.977375;0.982875 +random,1024,8192,1,frontier32_simd,0.693166,0.679333,0.379875,20552,16,2,0,0.152417,7,pass,0.676959;0.682750;1.409167;0.693166;0.755167;0.726708;0.655709 +random,1024,8192,1,frontier32_gpu_dag,1.101792,0.705875,0.452875,20328,16,4,0,0.152417,7,pass,1.224167;1.188959;1.101708;1.075709;1.073083;1.115791;1.101792 +random,1024,8192,1,bucket32_d4,1.894708,1.866500,1.272125,8232,32,4,0,0.152417,7,pass,1.987625;1.809250;1.931750;1.894708;1.811083;1.865583;1.993666 +random,1024,8192,1,bucket32_d16,1.462625,1.450541,0.908583,9336,24,3,0,0.152417,7,pass,2.104125;1.320875;1.538500;1.462625;1.601084;1.308042;1.351917 +random,1024,8192,1,bucket32_d64,0.952167,0.937292,0.644333,19312,16,2,0,0.152417,7,pass,1.248750;0.942959;0.996125;1.000625;0.952167;0.918417;0.940625 +random,1024,8192,64,old_pull_parallel_dag,1.937417,1.589708,1.084625,12582912,24,3,0,0.208500,7,pass,2.420375;2.350666;1.955666;1.937417;1.594375;1.582541;1.730292 +random,1024,8192,64,old_group_parallel_dag,0.852708,0.603458,0.416792,7217152,17,1,0,0.208500,7,pass,0.899041;0.998958;0.968625;0.852708;0.836250;0.792500;0.839000 +random,1024,8192,64,pull64_barrier,1.220375,0.975833,0.486292,12582912,24,3,0,0.208500,7,pass,1.220375;1.225167;1.314583;1.287208;1.146875;1.154083;1.183792 +random,1024,8192,64,pull64_interleaved,1.019833,0.760458,0.291000,12582912,24,3,0,0.208500,7,pass,1.065083;1.019833;1.055625;1.020583;0.974209;0.890417;0.998166 +random,1024,8192,64,pull32_interleaved,0.898917,0.634625,0.200167,12582912,24,3,0,0.208500,7,pass,0.898917;0.960667;0.884000;0.879625;0.850791;0.908417;0.920541 +random,1024,8192,64,pull32_gpu_dag,0.969041,0.585417,0.211667,12582912,24,5,0,0.208500,7,pass,0.969041;0.922042;1.008667;0.936709;1.172417;0.945333;1.045625 +random,1024,8192,64,frontier32_vertex,0.813125,0.530375,0.237208,1291032,16,2,0,0.208500,7,pass,0.845167;0.832625;0.813125;0.760750;0.796042;0.843375;0.760958 +random,1024,8192,64,frontier32_simd,1.042375,0.767125,0.452000,1202792,16,2,0,0.208500,7,pass,1.040375;1.059958;0.977208;1.055125;1.042375;0.995208;1.095584 +random,1024,8192,64,frontier32_gpu_dag,1.139000,0.779834,0.484125,1201976,16,4,0,0.208500,7,pass,1.239666;1.290666;1.062875;1.191292;1.127000;1.139000;1.046209 +random,1024,8192,64,bucket32_d4,2.241625,1.943125,1.017667,528520,56,7,0,0.208500,7,pass,2.336875;2.171250;2.283750;2.244750;2.202083;2.176583;2.241625 +random,1024,8192,64,bucket32_d16,1.528958,1.240375,0.663416,601288,32,4,0,0.208500,7,pass,1.477458;1.556208;1.529250;1.455791;1.528958;1.506209;1.531625 +random,1024,8192,64,bucket32_d64,1.433209,1.182000,0.675708,1154152,24,3,0,0.208500,7,pass,1.433209;1.409208;1.480083;1.452917;1.396292;1.491125;1.332208 +clos,200,20000,64,old_pull_parallel_dag,1.969833,1.397334,0.992208,10240000,8,1,0,0.332250,7,pass,2.147375;1.969833;1.709542;2.082542;1.738042;1.786209;2.212375 +clos,200,20000,64,old_group_parallel_dag,1.303791,0.804000,0.299042,3840000,3,1,0,0.332250,7,pass,1.323042;1.303791;1.293500;1.411875;1.069792;1.187042;1.491250 +clos,200,20000,64,pull64_barrier,2.484167,1.863542,1.278250,10240000,8,1,0,0.332250,7,pass,1.892958;2.403958;2.889250;2.317666;2.823000;2.484167;2.843584 +clos,200,20000,64,pull64_interleaved,1.915375,1.354625,0.765750,10240000,8,1,0,0.332250,7,pass,2.070042;1.927292;1.970375;1.915375;1.735583;1.896833;1.832083 +clos,200,20000,64,pull32_interleaved,1.882875,1.271375,0.676375,10240000,8,1,0,0.332250,7,pass,1.980333;1.772375;2.333209;2.149583;1.880167;1.809750;1.882875 +clos,200,20000,64,pull32_gpu_dag,2.063542,1.271125,1.000041,10240000,8,3,0,0.332250,7,pass,2.062708;2.111917;1.881792;2.063542;2.313125;2.266500;1.893166 +clos,200,20000,64,frontier32_vertex,2.130125,1.556167,0.945083,1280000,8,1,0,0.332250,7,pass,2.216500;2.130125;2.210583;1.863375;2.020208;2.181958;2.088666 +clos,200,20000,64,frontier32_simd,1.526333,0.956416,0.331917,1280000,8,1,0,0.332250,7,pass,1.383833;1.526333;1.478875;1.852542;1.436500;1.554041;1.578417 +clos,200,20000,64,frontier32_gpu_dag,2.066125,0.959000,0.844250,1280000,8,3,0,0.332250,7,pass,2.224500;1.735458;1.906792;2.066125;2.169666;2.396917;1.847250 +clos,200,20000,64,bucket32_d4,1.608916,1.072709,0.487625,1280000,8,1,0,0.332250,7,pass,1.291333;1.464042;1.642750;1.661542;1.763500;1.594834;1.608916 +clos,200,20000,64,bucket32_d16,1.782834,1.158959,0.500250,1280000,8,1,0,0.332250,7,pass,1.782834;1.714834;1.623458;2.323750;1.886750;2.390166;1.669083 +clos,200,20000,64,bucket32_d64,1.644084,1.123167,0.491375,1280000,8,1,0,0.332250,7,pass,1.536000;1.733125;1.951083;1.288625;1.644084;1.687625;1.508750 +grid,1024,3968,1,old_pull_parallel_dag,1.988666,1.978791,0.655042,253952,64,8,0,0.126000,7,pass,2.192792;1.794083;1.711292;1.642333;2.324041;2.040042;1.988666 +grid,1024,3968,1,old_group_parallel_dag,0.354333,0.344792,0.227083,249984,63,1,0,0.126000,7,pass,0.357958;0.353500;0.348292;0.354667;0.367708;0.354333;0.352458 +grid,1024,3968,1,pull64_barrier,1.101208,1.092375,0.173458,253952,64,8,0,0.126000,7,pass,1.101208;1.075666;1.197417;1.305459;1.066333;1.098666;1.168958 +grid,1024,3968,1,pull64_interleaved,1.102667,1.094791,0.173334,253952,64,8,0,0.126000,7,pass,1.220083;1.096709;1.102667;1.070708;1.101917;1.107459;1.132750 +grid,1024,3968,1,pull32_interleaved,1.116333,1.109458,0.159500,253952,64,8,0,0.126000,7,pass,1.065125;1.116333;1.098625;1.164500;1.273792;1.174125;1.070041 +grid,1024,3968,1,pull32_gpu_dag,1.169000,0.897708,0.169125,253952,64,10,0,0.126000,7,pass,1.129959;1.169000;1.173791;1.234958;1.194917;1.142833;1.136208 +grid,1024,3968,1,frontier32_vertex,1.287959,1.279750,0.518750,3968,64,8,0,0.126000,7,pass,1.275167;1.336000;1.287959;1.266750;1.320542;1.339834;1.279000 +grid,1024,3968,1,frontier32_simd,1.186417,1.178375,0.389875,3968,64,8,0,0.126000,7,pass,1.234375;1.146250;1.186417;1.171416;1.193500;1.268916;1.171458 +grid,1024,3968,1,frontier32_gpu_dag,1.444166,1.178625,0.405291,3968,64,10,0,0.126000,7,pass,1.394750;1.443917;1.570542;1.444166;1.444042;1.468875;1.606291 +grid,1024,3968,1,bucket32_d4,1.458042,1.450000,0.641250,3968,64,8,0,0.126000,7,pass,1.458042;1.446916;1.443291;1.455125;1.572041;1.467250;1.462417 +grid,1024,3968,1,bucket32_d16,1.450417,1.442583,0.646250,3968,64,8,0,0.126000,7,pass,1.568000;1.441375;1.585875;1.439833;1.450417;1.446250;1.577625 +grid,1024,3968,1,bucket32_d64,1.462208,1.454292,0.645042,3968,64,8,0,0.126000,7,pass,1.447292;1.462208;1.581541;1.449167;1.615959;1.469667;1.437709 +hub,1024,3070,1,old_pull_parallel_dag,6.087125,6.074167,5.541583,98240,32,4,0,0.123417,7,pass,6.160125;6.074625;6.215417;6.087125;6.141625;5.971583;6.010708 +hub,1024,3070,1,old_group_parallel_dag,4.883667,4.859875,4.720875,95170,31,1,0,0.123417,7,pass,4.873500;4.835042;4.883667;4.900833;4.866416;5.016625;4.921584 +hub,1024,3070,1,pull64_barrier,5.015958,5.001833,4.312792,98240,32,4,0,0.123417,7,pass,5.015958;4.936375;5.042167;4.957958;5.001875;5.138125;5.110666 +hub,1024,3070,1,pull64_interleaved,4.968459,4.947375,4.313000,98240,32,4,0,0.123417,7,pass,4.968459;4.898000;5.044458;4.967958;5.057375;4.917041;4.992250 +hub,1024,3070,1,pull32_interleaved,4.399625,4.376083,3.663500,98240,32,4,0,0.123417,7,pass,4.327167;4.296584;4.399625;4.441292;4.519125;4.303584;4.557000 +hub,1024,3070,1,pull32_gpu_dag,5.252583,4.408625,4.077750,98240,32,6,0,0.123417,7,pass,5.259250;5.203416;5.021750;5.114791;5.252625;5.269875;5.252583 +hub,1024,3070,1,frontier32_vertex,1.449125,1.441083,0.861666,3128,32,4,0,0.123417,7,pass,1.366833;1.404125;1.549000;1.449125;1.427167;1.498209;1.453542 +hub,1024,3070,1,frontier32_simd,0.749834,0.741250,0.233000,3128,32,4,0,0.123417,7,pass,0.785000;0.743375;0.694084;0.702792;0.814916;0.749834;0.754667 +hub,1024,3070,1,frontier32_gpu_dag,1.518500,0.744417,0.639333,3128,32,6,0,0.123417,7,pass,1.538584;1.435000;1.477375;1.446750;1.518500;1.532209;1.567208 +hub,1024,3070,1,bucket32_d4,0.918084,0.909917,0.356500,3100,32,4,0,0.123417,7,pass,0.928541;0.925042;0.903959;0.880958;1.046625;0.918084;0.916542 +hub,1024,3070,1,bucket32_d16,0.839333,0.831125,0.341583,3124,32,4,0,0.123417,7,pass,1.026333;0.839333;0.839208;0.858334;1.002334;0.813667;0.822250 +hub,1024,3070,1,bucket32_d64,0.842500,0.834542,0.330958,3128,32,4,0,0.123417,7,pass,0.830083;0.836583;0.831417;0.847833;0.842500;0.995291;0.855042 +random_masked_int64_reverse,1024,8192,8,old_pull_parallel_dag,0.231750,0.154542,0.031792,524288,8,1,0,0.204542,7,pass,0.230500;0.220375;0.231750;0.216000;0.233416;0.288916;0.235958 +random_masked_int64_reverse,1024,8192,8,old_group_parallel_dag,0.252542,0.194250,0.053750,368640,8,1,0,0.204542,7,pass,0.236792;0.252542;0.229916;0.264084;0.240167;0.263500;0.261584 +random_masked_int64_reverse,1024,8192,8,pull64_barrier,0.257667,0.187209,0.028792,524288,8,1,0,0.204542,7,pass,0.257667;0.235125;0.238709;0.250959;0.308250;0.266958;0.260000 +random_masked_int64_reverse,1024,8192,8,pull64_interleaved,0.252833,0.195875,0.028875,524288,8,1,0,0.204542,7,pass,0.256500;0.252833;0.247791;0.248542;0.242375;0.336584;0.254375 +random_masked_int64_reverse,1024,8192,8,pull32_interleaved,0.230417,0.174959,0.029333,524288,8,1,1,0.204542,7,pass,0.241708;0.224875;0.227167;0.211125;0.296709;0.230417;0.262209 +random_masked_int64_reverse,1024,8192,8,pull32_gpu_dag,0.494833,0.182667,0.048458,524288,8,3,1,0.204542,7,pass,0.513375;0.494833;0.505500;0.482667;0.659791;0.474833;0.453875 +random_masked_int64_reverse,1024,8192,8,frontier32_vertex,0.261750,0.195208,0.029083,524288,8,1,1,0.204542,7,pass,0.251333;0.233000;0.221584;0.267291;0.300833;0.262417;0.261750 +random_masked_int64_reverse,1024,8192,8,frontier32_simd,0.247209,0.186625,0.028708,524288,8,1,1,0.204542,7,pass,0.251209;0.256500;0.234417;0.247209;0.251708;0.230375;0.246875 +random_masked_int64_reverse,1024,8192,8,frontier32_gpu_dag,0.497708,0.182250,0.047708,524288,8,3,1,0.204542,7,pass,0.480208;0.465209;0.500875;0.497708;0.503250;0.570834;0.482959 +random_masked_int64_reverse,1024,8192,8,bucket32_d4,0.252250,0.196583,0.028667,524288,8,1,1,0.204542,7,pass,0.252250;0.268500;0.232417;0.246125;0.252875;0.344208;0.244583 +random_masked_int64_reverse,1024,8192,8,bucket32_d16,0.249667,0.182000,0.028708,524288,8,1,1,0.204542,7,pass,0.216667;0.223792;0.213625;0.249667;0.295166;0.279000;0.251250 +random_masked_int64_reverse,1024,8192,8,bucket32_d64,0.251083,0.193833,0.029000,524288,8,1,1,0.204542,7,pass,0.252208;0.256959;0.260000;0.228000;0.235541;0.231000;0.251083 +random,4096,32768,256,old_pull_parallel_dag,14.830166,11.111167,9.874250,201326592,24,3,0,0.540417,7,pass,15.178958;14.550500;14.761417;14.979459;14.964792;14.391417;14.830166 +random,4096,32768,256,old_group_parallel_dag,11.281792,7.602458,6.686625,136544256,20,1,0,0.540417,7,pass,10.789875;11.281792;11.619375;11.280333;11.393125;11.590542;11.218959 +random,4096,32768,256,pull64_barrier,13.451167,9.799333,8.501000,201326592,24,3,0,0.540417,7,pass,13.391709;13.451167;13.661333;13.776250;13.298041;13.431167;13.605083 +random,4096,32768,256,pull64_interleaved,7.315959,3.659084,2.253750,201326592,24,3,0,0.540417,7,pass,6.690083;6.816459;6.842416;7.535833;7.315959;7.446084;8.355833 +random,4096,32768,256,pull32_interleaved,10.835792,7.102291,5.947375,201326592,24,3,0,0.540417,7,pass,10.835792;11.572667;6.765709;10.839125;10.506583;6.753209;11.634209 +random,4096,32768,256,pull32_gpu_dag,4.001000,3.291333,2.062708,201326592,24,5,0,0.540417,7,pass,3.925292;8.471750;4.001000;8.828083;3.363250;8.899209;3.259542 +random,4096,32768,256,frontier32_vertex,8.457208,4.745875,3.541042,19765352,24,3,0,0.540417,7,pass,13.252792;7.803167;8.457208;13.944833;6.756042;6.576625;13.206291 +random,4096,32768,256,frontier32_simd,13.882000,10.166542,8.939417,20629696,24,3,0,0.540417,7,pass,14.372958;15.367875;15.384750;13.882000;12.035083;11.831084;11.218875 +random,4096,32768,256,frontier32_gpu_dag,8.543291,7.328250,6.778500,20601952,24,5,0,0.540417,7,pass,8.543291;8.521875;8.733916;8.510375;9.335416;8.605625;8.068333 +random,4096,32768,256,bucket32_d4,15.935000,12.268334,10.134292,8454048,72,9,0,0.540417,7,pass,16.177500;15.780541;15.770917;15.839625;16.023709;15.935000;16.271625 +random,4096,32768,256,bucket32_d16,13.396000,9.696458,7.725625,9728112,48,6,0,0.540417,7,pass,12.596125;13.460833;13.158208;13.458334;13.019125;14.111666;13.396000 +random,4096,32768,256,bucket32_d64,12.571916,8.730500,7.507958,18505456,24,3,0,0.540417,7,pass,11.895375;13.142667;12.700083;12.617083;12.179083;12.571916;12.433042 +random,16384,131072,1,old_pull_parallel_dag,0.994042,0.627000,0.204333,3145728,24,3,0,1.768209,7,pass,0.993208;0.994042;1.341958;0.917791;0.912375;1.503042;1.060459 +random,16384,131072,1,old_group_parallel_dag,5.366000,5.017958,4.840375,2359296,18,1,0,1.768209,7,pass,5.798209;5.530958;5.321334;5.366000;5.353375;5.372917;5.332083 +random,16384,131072,1,pull64_barrier,0.816750,0.565125,0.164167,3145728,24,3,0,1.768209,7,pass,0.865958;0.962083;0.844750;0.816750;0.811042;0.800375;0.796875 +random,16384,131072,1,pull64_interleaved,0.813625,0.564333,0.166833,3145728,24,3,0,1.768209,7,pass,0.863166;0.939584;0.787834;0.795208;0.902917;0.805500;0.813625 +random,16384,131072,1,pull32_interleaved,0.756500,0.546042,0.141500,3145728,24,3,0,1.768209,7,pass,0.923166;0.722875;0.703750;0.756500;0.740125;0.906291;0.899500 +random,16384,131072,1,pull32_gpu_dag,0.942292,0.540000,0.164958,3145728,24,5,0,1.768209,7,pass,0.942292;0.910583;0.936042;0.956041;0.878083;0.976916;0.998791 +random,16384,131072,1,frontier32_vertex,0.931209,0.689375,0.274000,377624,24,3,0,1.768209,7,pass,0.892750;0.957458;0.894000;0.931209;0.942583;1.014958;0.892084 +random,16384,131072,1,frontier32_simd,0.906500,0.677625,0.260042,331880,24,3,0,1.768209,7,pass,0.890291;0.667916;0.906500;0.909291;0.989250;0.915625;0.724500 +random,16384,131072,1,frontier32_gpu_dag,0.965417,0.651792,0.270625,331616,24,5,0,1.768209,7,pass,0.969083;1.029875;0.945167;0.851666;0.873917;1.018416;0.965417 +random,16384,131072,1,bucket32_d4,1.929542,1.695917,0.702167,132008,56,7,0,1.768209,7,pass,1.996375;1.955291;1.796708;1.929542;1.764500;1.932792;1.741583 +random,16384,131072,1,bucket32_d16,1.202042,0.958541,0.418458,148224,32,4,0,1.768209,7,pass,1.134042;1.177041;1.210208;1.158875;1.202042;1.323416;1.255292 +random,16384,131072,1,bucket32_d64,0.969875,0.745333,0.347375,269208,24,3,0,1.768209,7,pass,0.949333;0.936333;0.969875;0.966208;0.995208;1.023459;1.016541 +random,16384,131072,64,old_pull_parallel_dag,16.722292,12.546667,11.352584,201326592,24,3,0,1.742166,7,pass,16.589625;16.782167;17.024875;16.351458;16.722292;16.532333;16.879709 +random,16384,131072,64,old_group_parallel_dag,13.326000,9.159083,8.322458,158203904,22,1,0,1.742166,7,pass,12.850500;13.103292;13.505583;13.326000;13.384959;13.249125;13.521625 +random,16384,131072,64,pull64_barrier,15.921334,11.512833,10.367083,201326592,24,3,0,1.742166,7,pass,16.106709;16.345667;15.252750;15.479000;15.981125;15.515625;15.921334 +random,16384,131072,64,pull64_interleaved,7.341541,2.985875,1.883792,201326592,24,3,0,1.742166,7,pass,7.593083;7.245708;7.427542;7.141041;7.341541;7.639042;7.271500 +random,16384,131072,64,pull32_interleaved,8.727125,4.219375,3.045833,201326592,24,3,0,1.742166,7,pass,7.861333;8.053417;8.727125;10.393375;11.416917;7.248166;11.526125 +random,16384,131072,64,pull32_gpu_dag,3.850875,3.175750,2.039125,201326592,24,5,0,1.742166,7,pass,8.952083;3.619292;3.631417;8.345083;3.803042;8.516625;3.850875 +random,16384,131072,64,frontier32_vertex,10.189167,5.571958,4.471875,21279416,24,3,0,1.742166,7,pass,10.520375;10.189167;9.001250;10.956875;8.920750;12.021917;8.927750 +random,16384,131072,64,frontier32_simd,12.411875,8.079709,7.035667,22001240,24,3,0,1.742166,7,pass,17.322791;12.816041;12.164000;12.411875;11.992167;13.813792;12.047625 +random,16384,131072,64,frontier32_gpu_dag,10.058792,8.398667,8.525333,21937792,24,5,0,1.742166,7,pass,11.663125;11.269959;11.136625;10.058792;9.125875;9.377250;9.200916 +random,16384,131072,64,bucket32_d4,16.470666,11.920958,9.881666,8451432,72,9,0,1.742166,7,pass,16.470666;16.941042;17.234083;16.376958;16.415000;16.823750;15.927083 +random,16384,131072,64,bucket32_d16,14.035834,9.407333,7.796500,9570560,48,6,0,1.742166,7,pass,14.439958;13.796667;14.274833;13.844209;14.089416;14.035834;13.437416 +random,16384,131072,64,bucket32_d64,15.618875,11.154958,10.232875,17319760,24,3,0,1.742166,7,pass,15.651209;15.288208;15.618875;16.924458;15.772500;15.598375;14.522792 +random,65536,524288,1,old_pull_parallel_dag,3.453041,1.911833,1.022000,12582912,24,3,0,7.594209,7,pass,3.374625;3.569542;3.453041;3.795125;3.498709;3.402541;2.875167 +random,65536,524288,1,old_group_parallel_dag,30.640458,28.988333,28.348000,11534336,22,1,0,7.594209,7,pass,30.396166;30.640458;30.423084;30.773792;30.675375;30.724167;30.427041 +random,65536,524288,1,pull64_barrier,3.064792,1.521959,0.700667,12582912,24,3,0,7.594209,7,pass,3.100041;3.064792;3.087541;3.007292;3.161708;2.970083;3.019500 +random,65536,524288,1,pull64_interleaved,3.002250,1.493667,0.701750,12582912,24,3,0,7.594209,7,pass,2.876709;3.019125;3.179917;3.076334;3.002250;2.974625;2.964250 +random,65536,524288,1,pull32_interleaved,2.775333,1.290542,0.500375,12582912,24,3,0,7.594209,7,pass,2.775333;2.718458;2.930792;2.810750;2.709500;2.773875;2.835042 +random,65536,524288,1,pull32_gpu_dag,1.243833,0.853000,0.567083,12582912,24,5,0,7.594209,7,pass,1.223708;1.245875;1.243833;1.338334;1.271584;1.204125;1.242625 +random,65536,524288,1,frontier32_vertex,2.706458,1.262083,0.431792,1731984,24,3,0,7.594209,7,pass,2.705084;2.798542;2.750750;2.287750;2.706458;2.682250;2.832583 +random,65536,524288,1,frontier32_simd,2.935042,1.411333,0.600541,1575616,24,3,0,7.594209,7,pass,2.868750;3.034250;2.883500;2.935042;2.851584;3.144042;3.044166 +random,65536,524288,1,frontier32_gpu_dag,1.353667,0.972709,0.677750,1567736,24,5,0,7.594209,7,pass,1.358833;1.353667;1.310958;1.462708;1.339167;1.294625;1.385500 +random,65536,524288,1,bucket32_d4,4.132292,2.583208,1.160792,528256,64,8,0,7.594209,7,pass,3.686083;4.242917;4.103209;4.106250;4.263250;4.141291;4.132292 +random,65536,524288,1,bucket32_d16,3.380042,1.838417,0.783500,599248,40,5,0,7.594209,7,pass,3.391417;2.991958;3.371750;3.412458;3.380042;3.350000;3.477709 +random,65536,524288,1,bucket32_d64,2.992250,1.473917,0.653375,1050648,24,3,0,7.594209,7,pass,3.033250;2.985792;2.895916;2.992250;3.102916;2.573667;3.099000 +clos,800,320000,1,old_pull_parallel_dag,2.085458,1.267584,0.711750,2560000,8,1,0,3.542958,7,pass,2.085458;2.114708;2.080291;2.062458;2.124833;2.068584;2.087458 +clos,800,320000,1,old_group_parallel_dag,2.281625,1.479250,0.902375,960000,3,1,0,3.542958,7,pass,1.877667;2.281625;2.305042;2.260417;2.320084;1.892458;2.320458 +clos,800,320000,1,pull64_barrier,2.020750,1.233084,0.651125,2560000,8,1,0,3.542958,7,pass,2.054792;2.014333;2.018458;2.080459;2.020750;2.032083;2.017792 +clos,800,320000,1,pull64_interleaved,2.234583,1.436416,0.885583,2560000,8,1,0,3.542958,7,pass,2.068292;2.148167;2.116125;2.469583;2.302792;2.264542;2.234583 +clos,800,320000,1,pull32_interleaved,2.611333,1.797583,1.339500,2560000,8,1,0,3.542958,7,pass,2.385750;2.671625;2.384958;2.611333;2.573208;3.723625;3.674125 +clos,800,320000,1,pull32_gpu_dag,5.207000,2.914291,4.404583,2560000,8,3,0,3.542958,7,pass,5.244041;5.231584;5.207000;5.068292;5.140417;5.302750;5.152917 +clos,800,320000,1,frontier32_vertex,5.258709,4.426625,3.977667,320000,8,1,0,3.542958,7,pass,5.258709;5.398167;5.131167;5.318000;5.253625;5.215083;5.520042 +clos,800,320000,1,frontier32_simd,1.697541,0.807708,0.318125,320000,8,1,0,3.542958,7,pass,1.290916;2.233917;1.697541;1.702208;1.604792;1.668750;2.286250 +clos,800,320000,1,frontier32_gpu_dag,3.076875,0.757875,2.224667,320000,8,3,0,3.542958,7,pass,3.078333;3.015333;3.076875;3.188792;3.013250;3.084209;3.005084 +clos,800,320000,1,bucket32_d4,1.701625,0.885750,0.410333,320000,8,1,0,3.542958,7,pass,1.666500;1.672584;1.763833;1.701625;1.749083;1.658750;1.714833 +clos,800,320000,1,bucket32_d16,1.668083,0.829166,0.417000,320000,8,1,0,3.542958,7,pass,1.432416;1.856250;1.767917;1.306834;1.348000;1.726250;1.668083 +clos,800,320000,1,bucket32_d64,1.683584,0.853250,0.411375,320000,8,1,0,3.542958,7,pass,1.704958;1.451916;1.686084;1.713750;1.683584;1.665166;1.667083 +clos,800,320000,64,old_pull_parallel_dag,27.135625,19.105583,18.632250,163840000,8,1,0,3.559834,7,pass,26.917833;27.135625;27.827833;32.153333;18.959167;27.720583;24.055417 +clos,800,320000,64,old_group_parallel_dag,12.835333,6.027625,5.311750,61440000,3,1,0,3.559834,7,pass,12.958500;12.734958;13.122792;12.778250;13.686958;12.603333;12.835333 +clos,800,320000,64,pull64_barrier,25.325959,18.258292,17.562750,163840000,8,1,0,3.559834,7,pass,24.298917;26.631375;24.368792;26.615584;24.855375;25.325959;25.410042 +clos,800,320000,64,pull64_interleaved,13.125084,6.035417,5.379583,163840000,8,1,0,3.559834,7,pass,13.326458;12.319792;13.903000;13.181250;13.125084;12.508125;12.685500 +clos,800,320000,64,pull32_interleaved,11.445000,4.363917,3.663417,163840000,8,1,0,3.559834,7,pass,12.150625;11.445000;11.930667;11.957709;10.537375;10.746750;11.351500 +clos,800,320000,64,pull32_gpu_dag,8.371875,4.354166,6.133375,163840000,8,3,0,3.559834,7,pass,7.950875;8.814666;8.371875;7.833334;8.577500;8.882584;6.996125 +clos,800,320000,64,frontier32_vertex,13.988541,7.017125,6.391750,20480000,8,1,0,3.559834,7,pass,14.034166;13.531417;13.871125;13.743541;14.692125;14.240292;13.988541 +clos,800,320000,64,frontier32_simd,9.446000,2.085000,1.444208,20480000,8,1,0,3.559834,7,pass,9.797833;9.376500;9.053084;9.446000;9.639584;9.742792;8.711625 +clos,800,320000,64,frontier32_gpu_dag,14.162083,2.178709,11.456334,20480000,8,3,0,3.559834,7,pass,13.846833;14.475709;13.987625;15.439458;13.093208;14.545959;14.162083 +clos,800,320000,64,bucket32_d4,9.695708,2.496041,1.822042,20480000,8,1,0,3.559834,7,pass,9.883500;9.820625;9.538500;9.682750;9.301291;9.897500;9.695708 +clos,800,320000,64,bucket32_d16,9.406167,2.549333,1.826625,20480000,8,1,0,3.559834,7,pass,8.794417;11.469291;9.967792;9.406167;9.324375;9.109042;9.914709 +clos,800,320000,64,bucket32_d64,9.566083,2.444625,1.837625,20480000,8,1,0,3.559834,7,pass,9.548208;10.232833;8.945042;8.924416;9.566083;16.288833;9.696625 +grid,10000,39600,1,old_pull_parallel_dag,4.192542,4.113917,0.597499,7920000,200,25,0,0.515708,7,pass,4.572333;4.194375;4.089208;4.373667;4.192542;4.166459;3.976875 +grid,10000,39600,1,old_group_parallel_dag,7.762375,7.668834,7.506125,7880400,199,1,0,0.515708,7,pass,7.792125;7.704583;7.700541;7.760000;7.817458;7.783375;7.762375 +grid,10000,39600,1,pull64_barrier,4.020833,3.951958,0.658292,7920000,200,25,0,0.515708,7,pass,3.833709;3.945542;3.954459;4.034000;4.020833;4.291834;4.056792 +grid,10000,39600,1,pull64_interleaved,4.062583,3.994833,0.661000,7920000,200,25,0,0.515708,7,pass,4.196833;3.920792;4.062583;3.845292;4.041584;4.162667;4.256709 +grid,10000,39600,1,pull32_interleaved,3.864167,3.799084,0.587875,7920000,200,25,0,0.515708,7,pass,4.174709;4.013875;3.711500;3.864167;3.757584;3.710666;4.065667 +grid,10000,39600,1,pull32_gpu_dag,3.250500,2.965875,0.577125,7920000,200,27,0,0.515708,7,pass,3.552583;3.289542;3.200750;2.978667;3.290000;3.250500;3.223000 +grid,10000,39600,1,frontier32_vertex,4.489625,4.426958,1.793416,39600,200,25,0,0.515708,7,pass,4.489625;4.444250;4.573167;4.792917;4.258459;4.404625;4.750875 +grid,10000,39600,1,frontier32_simd,4.186542,4.123625,1.378167,39600,200,25,0,0.515708,7,pass,4.386417;4.186542;4.302708;4.184458;4.260750;4.070584;4.179833 +grid,10000,39600,1,frontier32_gpu_dag,4.407875,4.018750,1.346292,39600,200,27,0,0.515708,7,pass,4.517459;4.274333;4.451167;4.378334;4.360333;4.407875;4.505625 +grid,10000,39600,1,bucket32_d4,5.179458,5.116791,2.345999,39600,200,25,0,0.515708,7,pass,5.431125;5.479208;5.013167;5.425500;5.179458;5.173708;5.173291 +grid,10000,39600,1,bucket32_d16,5.276833,5.214041,2.415250,39600,200,25,0,0.515708,7,pass,4.927291;5.050083;5.276833;5.366584;5.363833;5.166292;5.303750 +grid,10000,39600,1,bucket32_d64,5.224250,5.149959,2.362208,39600,200,25,0,0.515708,7,pass,4.964708;5.052042;5.710000;5.224250;5.281208;5.245250;4.885583 +grid,10000,39600,8,old_pull_parallel_dag,4.414333,4.189125,1.349916,63360000,200,25,0,0.520832,7,pass,4.465500;4.414333;4.455250;3.975583;4.589792;3.990375;4.386291 +grid,10000,39600,8,old_group_parallel_dag,8.339916,8.078167,7.476500,51480000,199,1,0,0.520832,7,pass,8.339916;8.429834;8.038333;8.367083;8.349417;7.842958;8.191167 +grid,10000,39600,8,pull64_barrier,5.276917,5.101834,1.466624,63360000,200,25,0,0.520832,7,pass,4.816458;5.794209;4.863750;5.935333;5.276917;5.306875;5.029750 +grid,10000,39600,8,pull64_interleaved,5.016375,4.816125,1.365750,63360000,200,25,0,0.520832,7,pass,5.232500;5.447875;5.016375;4.970041;4.848667;5.042666;4.967708 +grid,10000,39600,8,pull32_interleaved,4.915792,4.690125,1.285791,63360000,200,25,0,0.520832,7,pass,4.809417;5.023625;5.557250;4.915792;5.009958;4.751584;4.751125 +grid,10000,39600,8,pull32_gpu_dag,4.954083,4.625375,1.314542,63360000,200,27,0,0.520832,7,pass,4.815084;5.124208;5.269375;4.898458;4.947625;4.954083;5.022583 +grid,10000,39600,8,frontier32_vertex,5.589084,5.445542,1.953459,316800,200,25,0,0.520832,7,pass,5.582708;5.589084;5.674750;5.473625;5.573792;6.400167;5.717125 +grid,10000,39600,8,frontier32_simd,4.779667,4.539916,1.380791,316800,200,25,0,0.520832,7,pass,4.779667;4.719625;5.179417;4.631792;4.733250;5.285917;5.059000 +grid,10000,39600,8,frontier32_gpu_dag,5.082166,4.654750,1.477750,316800,200,27,0,0.520832,7,pass,5.017125;5.101084;5.184792;4.835041;5.082166;5.098625;4.936417 +grid,10000,39600,8,bucket32_d4,7.027917,6.850791,3.498083,316800,200,25,0,0.520832,7,pass,7.218000;7.175916;7.011250;6.907042;7.027917;7.004458;7.400208 +grid,10000,39600,8,bucket32_d16,7.438125,7.228875,3.634041,316800,200,25,0,0.520832,7,pass,7.169458;7.230125;7.647625;7.648666;7.636167;7.171459;7.438125 +grid,10000,39600,8,bucket32_d64,7.147333,6.930583,3.488042,316800,200,25,0,0.520832,7,pass,7.213916;7.047042;7.147458;7.072792;7.147333;7.110667;7.237083 +chain,2048,2047,1,old_pull_parallel_dag,30.552917,30.545834,4.321582,4192256,2048,256,0,0.125625,7,pass,30.441708;30.552917;31.920250;29.640667;30.868458;31.028000;29.277250 +chain,2048,2047,1,old_group_parallel_dag,4.833083,4.826542,4.695250,4192256,2048,1,0,0.125625,7,pass,4.804500;4.824500;4.816250;4.851208;4.856917;4.858541;4.833083 +chain,2048,2047,1,pull64_barrier,30.510625,30.503291,4.811082,4192256,2048,256,0,0.125625,7,pass,30.510625;30.138791;31.022291;31.066500;26.890709;30.860167;28.175541 +chain,2048,2047,1,pull64_interleaved,31.047791,31.040250,4.944002,4192256,2048,256,0,0.125625,7,pass,28.758083;30.971667;31.047791;31.266083;31.732750;31.417208;30.582792 +chain,2048,2047,1,pull32_interleaved,30.664125,30.657666,4.841290,4192256,2048,256,0,0.125625,7,pass,30.888709;30.521792;30.642750;30.218834;30.664125;31.991916;30.833417 +chain,2048,2047,1,pull32_gpu_dag,31.190750,30.903459,4.845919,4192256,2048,258,0,0.125625,7,pass,30.740917;32.332792;30.644417;31.678750;31.051166;31.380667;31.190750 +chain,2048,2047,1,frontier32_vertex,39.637750,39.628292,12.972585,2047,2048,256,0,0.125625,7,pass,38.372083;40.031083;39.313000;39.637750;40.304916;40.453458;39.255125 +chain,2048,2047,1,frontier32_simd,39.789917,39.782625,12.911460,2047,2048,256,0,0.125625,7,pass,39.902750;39.872792;39.987917;39.789917;39.650792;36.553375;36.089750 +chain,2048,2047,1,frontier32_gpu_dag,70.724250,70.461750,44.595246,2047,2048,258,0,0.125625,7,pass,43.906625;58.636625;70.313917;71.726083;70.724250;76.852417;73.861208 +chain,2048,2047,1,bucket32_d4,58.239375,58.233417,21.375416,2047,2056,257,0,0.125625,7,pass,62.646291;58.284083;58.239375;53.150791;53.433666;55.449542;58.410250 +chain,2048,2047,1,bucket32_d16,57.210791,57.204375,20.963166,2047,2056,257,0,0.125625,7,pass,59.173458;58.572625;55.714083;58.005042;56.776000;56.803584;57.210791 +chain,2048,2047,1,bucket32_d64,57.298833,57.291750,20.994749,2047,2056,257,0,0.125625,7,pass,58.199167;57.298833;57.227292;56.298000;57.819334;57.979250;57.193708 +hub,4096,12286,64,old_pull_parallel_dag,32.738459,32.377000,30.834542,31452160,40,5,0,0.298792,7,pass,32.488459;32.939417;32.738459;32.991250;32.959542;32.400500;32.294959 +hub,4096,12286,64,old_group_parallel_dag,26.029167,25.650958,24.950500,27176632,38,1,0,0.298792,7,pass,26.056500;25.595459;25.674875;26.214084;26.029167;25.727042;26.054042 +hub,4096,12286,64,pull64_barrier,25.705500,25.271334,23.640292,31452160,40,5,0,0.298792,7,pass,25.705500;25.445917;25.780125;25.710875;25.734959;25.565792;25.261959 +hub,4096,12286,64,pull64_interleaved,33.502333,33.108584,31.536709,31452160,40,5,0,0.298792,7,pass,33.577666;33.502333;33.523417;32.882208;33.813209;32.886458;32.949750 +hub,4096,12286,64,pull32_interleaved,28.909250,28.554916,26.900000,31452160,40,5,0,0.298792,7,pass,29.039750;29.081500;28.383209;28.651958;29.064083;28.784208;28.909250 +hub,4096,12286,64,pull32_gpu_dag,31.414959,28.520625,29.230000,31452160,40,7,0,0.298792,7,pass,31.416583;31.781542;31.181542;30.931833;30.765958;31.968583;31.414959 +hub,4096,12286,64,frontier32_vertex,20.297708,19.929541,18.721708,1860120,40,5,0,0.298792,7,pass,20.734375;20.408333;20.049834;20.663792;20.297708;20.041916;20.265708 +hub,4096,12286,64,frontier32_simd,3.727542,3.299791,1.927041,1683322,40,5,0,0.298792,7,pass,3.644167;3.743041;3.727542;3.766667;3.927708;3.695166;3.035375 +hub,4096,12286,64,frontier32_gpu_dag,4.851209,2.763917,3.502458,1683264,40,7,0,0.298792,7,pass,5.212083;5.300875;4.645584;5.398958;4.851209;4.829000;4.836417 +hub,4096,12286,64,bucket32_d4,5.104875,4.739583,3.097417,788342,48,6,0,0.298792,7,pass,5.103375;5.319250;4.142667;4.426417;5.111667;5.148000;5.104875 +hub,4096,12286,64,bucket32_d16,4.303667,3.919791,2.909334,1124798,48,6,0,0.298792,7,pass,4.303667;4.285250;4.624542;4.287916;5.023958;4.240125;4.605209 +hub,4096,12286,64,bucket32_d64,5.089709,4.662958,3.317292,1925862,40,5,0,0.298792,7,pass,5.089709;5.218125;4.996917;4.812292;5.010000;5.321542;5.098500 +random,4096,131072,1,old_pull_parallel_dag,0.658209,0.484209,0.253500,2097152,16,2,0,1.704166,7,pass,0.723083;0.796000;0.658209;0.628833;0.644125;0.789625;0.628666 +random,4096,131072,1,old_group_parallel_dag,2.587292,2.399042,2.250625,1572864,12,1,0,1.704166,7,pass,2.567417;2.631125;2.647459;2.869250;2.513167;2.540333;2.587292 +random,4096,131072,1,pull64_barrier,0.643792,0.480417,0.225417,2097152,16,2,0,1.704166,7,pass,0.735542;0.628042;0.658500;0.665917;0.606791;0.634125;0.643792 +random,4096,131072,1,pull64_interleaved,0.650875,0.473000,0.234000,2097152,16,2,0,1.704166,7,pass,0.683042;0.650875;0.649917;0.626042;0.676500;0.636708;0.745083 +random,4096,131072,1,pull32_interleaved,0.611750,0.425333,0.179125,2097152,16,2,0,1.704166,7,pass,0.597042;0.595916;0.700375;0.611750;0.666083;0.629375;0.580167 +random,4096,131072,1,pull32_gpu_dag,0.814708,0.427917,0.224333,2097152,16,4,0,1.704166,7,pass,0.887750;0.819917;0.814708;0.757125;0.782916;0.782916;0.876000 +random,4096,131072,1,frontier32_vertex,0.777709,0.585167,0.335250,421760,16,2,0,1.704166,7,pass,0.777709;0.797958;0.748917;0.738459;0.794458;0.812375;0.721792 +random,4096,131072,1,frontier32_simd,0.561292,0.368875,0.129875,380192,16,2,0,1.704166,7,pass,0.808000;0.621666;0.561292;0.586125;0.541750;0.528000;0.542708 +random,4096,131072,1,frontier32_gpu_dag,0.777250,0.385500,0.168708,383328,16,4,0,1.704166,7,pass,0.674667;0.689959;0.777250;0.722875;0.854583;0.851667;0.782792 +random,4096,131072,1,bucket32_d4,0.824625,0.642167,0.249917,138720,24,3,0,1.704166,7,pass,0.809458;0.865917;0.824625;0.797333;0.853083;0.871667;0.757959 +random,4096,131072,1,bucket32_d16,0.661125,0.483250,0.199875,177408,16,2,0,1.704166,7,pass,0.662167;0.594250;0.638917;0.688375;0.698750;0.661125;0.649625 +random,4096,131072,1,bucket32_d64,0.615709,0.447834,0.194416,379648,16,2,0,1.704166,7,pass,0.572500;0.579000;0.727541;0.596792;0.615709;0.641250;0.683708 +random,4096,131072,64,old_pull_parallel_dag,9.242792,7.142292,6.265125,134217728,16,2,0,1.900000,7,pass,9.382709;9.053834;9.288833;9.441250;9.242792;8.910334;8.492458 +random,4096,131072,64,old_group_parallel_dag,6.136250,4.016875,3.290875,105644032,15,1,0,1.900000,7,pass,6.136250;6.189875;6.174375;6.008625;6.319916;5.805792;6.047625 +random,4096,131072,64,pull64_barrier,9.428125,7.314208,6.387583,134217728,16,2,0,1.900000,7,pass,10.098667;9.488167;9.428125;9.195458;10.087334;9.325500;9.205917 +random,4096,131072,64,pull64_interleaved,4.731458,2.589250,1.742166,134217728,16,2,0,1.900000,7,pass,4.093542;4.623375;4.798500;4.829542;4.576750;4.731458;4.879333 +random,4096,131072,64,pull32_interleaved,4.225208,2.210041,1.545917,134217728,16,2,0,1.900000,7,pass,4.413500;4.056459;4.225208;5.849208;6.273542;3.443458;3.763917 +random,4096,131072,64,pull32_gpu_dag,2.215000,1.628334,0.809417,134217728,16,4,0,1.900000,7,pass,4.834667;2.066875;2.150542;2.482250;2.217375;2.215000;1.987125 +random,4096,131072,64,frontier32_vertex,5.298958,3.305375,2.517000,22687072,16,2,0,1.900000,7,pass,6.278583;5.896708;5.273833;5.298958;5.188625;5.321541;4.794333 +random,4096,131072,64,frontier32_simd,4.818459,2.921834,1.971000,22886848,16,2,0,1.900000,7,pass,4.792250;4.818459;4.646292;5.055042;5.800500;5.912625;4.697458 +random,4096,131072,64,frontier32_gpu_dag,4.070083,2.819250,2.716417,22966880,16,4,0,1.900000,7,pass,4.098292;3.579583;4.282125;4.248541;3.964916;4.070083;3.906708 +random,4096,131072,64,bucket32_d4,5.638750,3.371833,2.416875,8804704,24,3,0,1.900000,7,pass,5.033750;4.330250;5.638750;5.774958;4.382750;6.163708;5.996584 +random,4096,131072,64,bucket32_d16,6.013709,2.810958,1.843083,12114144,24,3,0,1.900000,7,pass,5.143208;6.767583;5.024625;7.537250;8.913666;5.057708;6.013709 +random,4096,131072,64,bucket32_d64,5.196750,3.178125,2.351542,23254592,16,2,0,1.900000,7,pass,4.848708;5.196750;12.365125;5.578958;5.030667;4.926417;5.383084 diff --git a/dev/research/metal_pathfinding/optimization/results/cpu-algorithms-aba/environment.txt b/dev/research/metal_pathfinding/optimization/results/cpu-algorithms-aba/environment.txt new file mode 100644 index 0000000..0a72477 --- /dev/null +++ b/dev/research/metal_pathfinding/optimization/results/cpu-algorithms-aba/environment.txt @@ -0,0 +1,5 @@ +2026-09-26T23:34:36Z +fbab119e794c843838f4f3f96d75cb7f32f06845 +44962b5bd1dba6ecfc8d1449e324875e35ebe373e3f33aef779be12d9cb3fd65 dev/research/metal_pathfinding/optimization/cpu_algorithms.mm +5336a17369edf018c33267e7765d20bffe8beaed3b8fb9f4e23053942cd3b73c build/metal_pathfinding/cpu-algorithms +7bb649ffcd34e6be02ab14c35767b816b0b32ce3ee3c2fd91c199e4b37a837ce build/metal_pathfinding/optimized diff --git a/dev/research/metal_pathfinding/optimization/results/cpu-algorithms-aba/gpu-load-a1.txt b/dev/research/metal_pathfinding/optimization/results/cpu-algorithms-aba/gpu-load-a1.txt new file mode 100644 index 0000000..bb14b8c --- /dev/null +++ b/dev/research/metal_pathfinding/optimization/results/cpu-algorithms-aba/gpu-load-a1.txt @@ -0,0 +1 @@ + | "PerformanceStatistics" = {"In use system memory (driver)"=0,"Alloc system memory"=10962583552,"Tiler Utilization %"=10,"recoveryCount"=0,"lastRecoveryTime"=0,"Renderer Utilization %"=16,"TiledSceneBytes"=1507328,"Device Utilization %"=25,"SplitSceneCount"=0,"Allocated PB Size"=188219392,"In use system memory"=1329561600} diff --git a/dev/research/metal_pathfinding/optimization/results/cpu-algorithms-aba/gpu-load-a2.txt b/dev/research/metal_pathfinding/optimization/results/cpu-algorithms-aba/gpu-load-a2.txt new file mode 100644 index 0000000..75d8bdd --- /dev/null +++ b/dev/research/metal_pathfinding/optimization/results/cpu-algorithms-aba/gpu-load-a2.txt @@ -0,0 +1 @@ + | "PerformanceStatistics" = {"In use system memory (driver)"=0,"Alloc system memory"=11424284672,"Tiler Utilization %"=2,"recoveryCount"=0,"lastRecoveryTime"=0,"Renderer Utilization %"=4,"TiledSceneBytes"=1507328,"Device Utilization %"=63,"SplitSceneCount"=0,"Allocated PB Size"=191889408,"In use system memory"=1508343808} diff --git a/dev/research/metal_pathfinding/optimization/results/cpu-algorithms-aba/gpu-load-b.txt b/dev/research/metal_pathfinding/optimization/results/cpu-algorithms-aba/gpu-load-b.txt new file mode 100644 index 0000000..137719b --- /dev/null +++ b/dev/research/metal_pathfinding/optimization/results/cpu-algorithms-aba/gpu-load-b.txt @@ -0,0 +1 @@ + | "PerformanceStatistics" = {"In use system memory (driver)"=0,"Alloc system memory"=11044798464,"Tiler Utilization %"=0,"recoveryCount"=0,"lastRecoveryTime"=0,"Renderer Utilization %"=0,"TiledSceneBytes"=1507328,"Device Utilization %"=0,"SplitSceneCount"=0,"Allocated PB Size"=191496192,"In use system memory"=1353957376} diff --git a/dev/research/metal_pathfinding/optimization/results/cpu-algorithms-aba/load-a1.txt b/dev/research/metal_pathfinding/optimization/results/cpu-algorithms-aba/load-a1.txt new file mode 100644 index 0000000..087f07d --- /dev/null +++ b/dev/research/metal_pathfinding/optimization/results/cpu-algorithms-aba/load-a1.txt @@ -0,0 +1,40 @@ +Processes: 1028 total, 2 running, 1026 sleeping, 5245 threads +2026/09/27 00:34:36 +Load Avg: 3.83, 3.81, 4.16 +CPU usage: 5.4% user, 9.75% sys, 85.20% idle +SharedLibs: 924M resident, 170M data, 136M linkedit. +MemRegions: 626142 total, 10G resident, 746M private, 4380M shared. +PhysMem: 34G used (3950M wired, 625M compressor), 1287M unused. +VM: 453T vsize, 6144M framework vsize, 2846254(0) swapins, 4729331(0) swapouts. +Networks: packets: 191220681/161G in, 146692457/164G out. +Disks: 97851346/2478G read, 117478369/2101G written. + +PID COMMAND %CPU #TH +99753 mscamerad-xpc 0.0 2 +99752 PlugInLibrarySer 0.0 2 +99750 QuickLookUIServi 0.0 3 +99749 com.apple.appkit 0.0 3 +99710 PlugInLibrarySer 0.0 2 +99709 Preview 0.0 4 +99428 crashpad_handler 0.0 4 +98995 crashpad_handler 0.0 4 +Processes: 1028 total, 2 running, 1026 sleeping, 5225 threads +2026/09/27 00:34:37 +Load Avg: 3.83, 3.81, 4.16 +CPU usage: 6.82% user, 4.74% sys, 88.43% idle +SharedLibs: 924M resident, 170M data, 136M linkedit. +MemRegions: 0 total, 0B resident, 746M private, 4380M shared. +PhysMem: 34G used (3956M wired, 625M compressor), 1290M unused. +VM: 453T vsize, 6144M framework vsize, 2846254(0) swapins, 4729331(0) swapouts. +Networks: packets: 191220845/161G in, 146692617/164G out. +Disks: 97851346/2478G read, 117478371/2101G written. + +PID COMMAND %CPU #TH +590 WindowServer 28.7 28 +70968 Superset Helper 21.6 32 +0 kernel_task 12.1 850/14 +35069 top 9.0 1/1 +21666 2.1.283 7.7 28 +70942 Superset Helper 7.2 19 +81804 2.1.283 5.2 21 +621 airportd 3.7 9 diff --git a/dev/research/metal_pathfinding/optimization/results/cpu-algorithms-aba/load-a2.txt b/dev/research/metal_pathfinding/optimization/results/cpu-algorithms-aba/load-a2.txt new file mode 100644 index 0000000..07d79ae --- /dev/null +++ b/dev/research/metal_pathfinding/optimization/results/cpu-algorithms-aba/load-a2.txt @@ -0,0 +1,40 @@ +Processes: 1021 total, 3 running, 1018 sleeping, 5225 threads +2026/09/27 00:35:39 +Load Avg: 3.30, 3.68, 4.08 +CPU usage: 23.58% user, 16.59% sys, 59.82% idle +SharedLibs: 924M resident, 170M data, 136M linkedit. +MemRegions: 638937 total, 10G resident, 739M private, 4394M shared. +PhysMem: 34G used (4923M wired, 625M compressor), 767M unused. +VM: 451T vsize, 6144M framework vsize, 2846260(0) swapins, 4729331(0) swapouts. +Networks: packets: 191239397/161G in, 146716076/164G out. +Disks: 97852171/2478G read, 117481152/2101G written. + +PID COMMAND %CPU #TH +99753 mscamerad-xpc 0.0 2 +99752 PlugInLibrarySer 0.0 2 +99750 QuickLookUIServi 0.0 3 +99749 com.apple.appkit 0.0 3 +99710 PlugInLibrarySer 0.0 2 +99709 Preview 0.0 4 +99428 crashpad_handler 0.0 4 +98995 crashpad_handler 0.0 4 +Processes: 1020 total, 7 running, 1013 sleeping, 5228 threads +2026/09/27 00:35:40 +Load Avg: 3.30, 3.68, 4.08 +CPU usage: 14.96% user, 7.41% sys, 77.61% idle +SharedLibs: 924M resident, 170M data, 136M linkedit. +MemRegions: 0 total, 0B resident, 739M private, 4394M shared. +PhysMem: 34G used (4111M wired, 625M compressor), 910M unused. +VM: 451T vsize, 6144M framework vsize, 2846260(0) swapins, 4729331(0) swapouts. +Networks: packets: 191239878/161G in, 146716829/164G out. +Disks: 97852524/2478G read, 117481160/2101G written. + +PID COMMAND %CPU #TH +41532 Google Chrome He 54.7 26/1 +590 WindowServer 26.7 28/1 +95916 Google Chrome 17.7 46 +0 kernel_task 17.2 850/14 +70968 Superset Helper 15.2 32 +21666 2.1.283 9.4 27 +41571 top 7.9 1/1 +28991 Muse 6.2 29 diff --git a/dev/research/metal_pathfinding/optimization/results/cpu-algorithms-aba/load-b.txt b/dev/research/metal_pathfinding/optimization/results/cpu-algorithms-aba/load-b.txt new file mode 100644 index 0000000..5461de5 --- /dev/null +++ b/dev/research/metal_pathfinding/optimization/results/cpu-algorithms-aba/load-b.txt @@ -0,0 +1,40 @@ +Processes: 1032 total, 5 running, 1027 sleeping, 5271 threads +2026/09/27 00:34:45 +Load Avg: 3.77, 3.80, 4.15 +CPU usage: 19.63% user, 13.49% sys, 66.87% idle +SharedLibs: 924M resident, 170M data, 136M linkedit. +MemRegions: 639550 total, 10G resident, 748M private, 4376M shared. +PhysMem: 34G used (3953M wired, 625M compressor), 943M unused. +VM: 456T vsize, 6144M framework vsize, 2846254(0) swapins, 4729331(0) swapouts. +Networks: packets: 191222619/161G in, 146695003/164G out. +Disks: 97851375/2478G read, 117478676/2101G written. + +PID COMMAND %CPU #TH +99753 mscamerad-xpc 0.0 2 +99752 PlugInLibrarySer 0.0 2 +99750 QuickLookUIServi 0.0 3 +99749 com.apple.appkit 0.0 3 +99710 PlugInLibrarySer 0.0 2 +99709 Preview 0.0 4 +99428 crashpad_handler 0.0 4 +98995 crashpad_handler 0.0 4 +Processes: 1029 total, 4 running, 1025 sleeping, 5262 threads +2026/09/27 00:34:46 +Load Avg: 3.77, 3.80, 4.15 +CPU usage: 17.4% user, 6.64% sys, 76.30% idle +SharedLibs: 924M resident, 170M data, 136M linkedit. +MemRegions: 0 total, 0B resident, 748M private, 4376M shared. +PhysMem: 34G used (3977M wired, 625M compressor), 1023M unused. +VM: 455T vsize, 6144M framework vsize, 2846254(0) swapins, 4729331(0) swapouts. +Networks: packets: 191223281/161G in, 146696242/164G out. +Disks: 97851377/2478G read, 117478696/2101G written. + +PID COMMAND %CPU #TH +35242 Google Chrome He 59.1 25/1 +590 WindowServer 29.1 27 +95916 Google Chrome 18.9 46 +70968 Superset Helper 15.9 32 +0 kernel_task 15.0 850/15 +81804 2.1.283 7.7 27 +35565 top 7.6 1/1 +21666 2.1.283 7.3 27 diff --git a/dev/research/metal_pathfinding/optimization/results/cpu-algorithms-aba/summary.json b/dev/research/metal_pathfinding/optimization/results/cpu-algorithms-aba/summary.json new file mode 100644 index 0000000..9ab7903 --- /dev/null +++ b/dev/research/metal_pathfinding/optimization/results/cpu-algorithms-aba/summary.json @@ -0,0 +1,248 @@ +{ + "phase_rows": { + "a1": 14, + "b": 216, + "a2": 14 + }, + "checked_query_results": 88056, + "summary": [ + { + "case": [ + "random", + "1024", + "8192", + "1" + ], + "heap_a1_a2": [ + 0.052958, + 0.059333 + ], + "dial_a1_a2": [ + 0.027667, + 0.03 + ], + "best_gpu": { + "case": "random", + "n": "1024", + "e": "8192", + "queries": "1", + "method": "pull32_interleaved", + "wall_ms": "0.633625", + "distance_ms": "0.621125", + "gpu_ms": "0.349458", + "edge_visits": "131072", + "rounds": "16", + "waits": "2", + "fallback64": "0", + "upload_ms": "0.152417", + "samples": "7", + "correct": "pass", + "wall_samples_ms": "0.630000;0.633625;0.646917;0.592625;0.621542;0.675042;0.679750" + } + }, + { + "case": [ + "random", + "4096", + "32768", + "256" + ], + "heap_a1_a2": [ + 13.0295, + 13.024459 + ], + "dial_a1_a2": [ + 7.056208, + 6.924667 + ], + "best_gpu": { + "case": "random", + "n": "4096", + "e": "32768", + "queries": "256", + "method": "pull32_gpu_dag", + "wall_ms": "4.001000", + "distance_ms": "3.291333", + "gpu_ms": "2.062708", + "edge_visits": "201326592", + "rounds": "24", + "waits": "5", + "fallback64": "0", + "upload_ms": "0.540417", + "samples": "7", + "correct": "pass", + "wall_samples_ms": "3.925292;8.471750;4.001000;8.828083;3.363250;8.899209;3.259542" + } + }, + { + "case": [ + "random", + "16384", + "131072", + "64" + ], + "heap_a1_a2": [ + 17.500459, + 17.26825 + ], + "dial_a1_a2": [ + 7.696333, + 7.677208 + ], + "best_gpu": { + "case": "random", + "n": "16384", + "e": "131072", + "queries": "64", + "method": "pull32_gpu_dag", + "wall_ms": "3.850875", + "distance_ms": "3.175750", + "gpu_ms": "2.039125", + "edge_visits": "201326592", + "rounds": "24", + "waits": "5", + "fallback64": "0", + "upload_ms": "1.742166", + "samples": "7", + "correct": "pass", + "wall_samples_ms": "8.952083;3.619292;3.631417;8.345083;3.803042;8.516625;3.850875" + } + }, + { + "case": [ + "random", + "65536", + "524288", + "1" + ], + "heap_a1_a2": [ + 11.474125, + 11.530166 + ], + "dial_a1_a2": [ + 4.384459, + 4.372167 + ], + "best_gpu": { + "case": "random", + "n": "65536", + "e": "524288", + "queries": "1", + "method": "pull32_gpu_dag", + "wall_ms": "1.243833", + "distance_ms": "0.853000", + "gpu_ms": "0.567083", + "edge_visits": "12582912", + "rounds": "24", + "waits": "5", + "fallback64": "0", + "upload_ms": "7.594209", + "samples": "7", + "correct": "pass", + "wall_samples_ms": "1.223708;1.245875;1.243833;1.338334;1.271584;1.204125;1.242625" + } + }, + { + "case": [ + "random", + "4096", + "131072", + "64" + ], + "heap_a1_a2": [ + 6.672416, + 6.661792 + ], + "dial_a1_a2": [ + 3.853958, + 3.865375 + ], + "best_gpu": { + "case": "random", + "n": "4096", + "e": "131072", + "queries": "64", + "method": "pull32_gpu_dag", + "wall_ms": "2.215000", + "distance_ms": "1.628334", + "gpu_ms": "0.809417", + "edge_visits": "134217728", + "rounds": "16", + "waits": "4", + "fallback64": "0", + "upload_ms": "1.900000", + "samples": "7", + "correct": "pass", + "wall_samples_ms": "4.834667;2.066875;2.150542;2.482250;2.217375;2.215000;1.987125" + } + }, + { + "case": [ + "clos", + "800", + "320000", + "64" + ], + "heap_a1_a2": [ + 5.124625, + 5.390792 + ], + "dial_a1_a2": [ + 5.421083, + 5.537125 + ], + "best_gpu": { + "case": "clos", + "n": "800", + "e": "320000", + "queries": "64", + "method": "pull32_gpu_dag", + "wall_ms": "8.371875", + "distance_ms": "4.354166", + "gpu_ms": "6.133375", + "edge_visits": "163840000", + "rounds": "8", + "waits": "3", + "fallback64": "0", + "upload_ms": "3.559834", + "samples": "7", + "correct": "pass", + "wall_samples_ms": "7.950875;8.814666;8.371875;7.833334;8.577500;8.882584;6.996125" + } + }, + { + "case": [ + "grid", + "10000", + "39600", + "1" + ], + "heap_a1_a2": [ + 0.200833, + 0.193709 + ], + "dial_a1_a2": [ + 0.126041, + 0.128833 + ], + "best_gpu": { + "case": "grid", + "n": "10000", + "e": "39600", + "queries": "1", + "method": "pull32_gpu_dag", + "wall_ms": "3.250500", + "distance_ms": "2.965875", + "gpu_ms": "0.577125", + "edge_visits": "7920000", + "rounds": "200", + "waits": "27", + "fallback64": "0", + "upload_ms": "0.515708", + "samples": "7", + "correct": "pass", + "wall_samples_ms": "3.552583;3.289542;3.200750;2.978667;3.290000;3.250500;3.223000" + } + } + ] +} diff --git a/dev/research/metal_pathfinding/optimization/results/cpu-algorithms-aba/summary.md b/dev/research/metal_pathfinding/optimization/results/cpu-algorithms-aba/summary.md new file mode 100644 index 0000000..ae069d3 --- /dev/null +++ b/dev/research/metal_pathfinding/optimization/results/cpu-algorithms-aba/summary.md @@ -0,0 +1,13 @@ +# Stronger CPU algorithm A/B/A + +All methods include exact distances and canonical-equivalent positive-cost DAG edge sets. CPU batches use 10 workers. Eligibility is cached outside timing for both devices. Seven measured samples and two checked warmups. These remain exploratory, non-isolated desktop measurements. GPU choice is an oracle across 12 tested variants. + +| Case / N / E / Q | Cached heap + DAG A1 / A2 ms | Dial + DAG A1 / A2 ms | Best GPU B ms | GPU method | +|---|---:|---:|---:|---| +| random / 1024 / 8192 / 1 | 0.053 / 0.059 | 0.028 / 0.030 | 0.634 | pull32_interleaved | +| random / 4096 / 32768 / 256 | 13.030 / 13.024 | 7.056 / 6.925 | 4.001 | pull32_gpu_dag | +| random / 16384 / 131072 / 64 | 17.500 / 17.268 | 7.696 / 7.677 | 3.851 | pull32_gpu_dag | +| random / 65536 / 524288 / 1 | 11.474 / 11.530 | 4.384 / 4.372 | 1.244 | pull32_gpu_dag | +| random / 4096 / 131072 / 64 | 6.672 / 6.662 | 3.854 / 3.865 | 2.215 | pull32_gpu_dag | +| clos / 800 / 320000 / 64 | 5.125 / 5.391 | 5.421 / 5.537 | 8.372 | pull32_gpu_dag | +| grid / 10000 / 39600 / 1 | 0.201 / 0.194 | 0.126 / 0.129 | 3.251 | pull32_gpu_dag | diff --git a/dev/research/metal_pathfinding/optimization/results/cpu-algorithms-correctness-stderr.txt b/dev/research/metal_pathfinding/optimization/results/cpu-algorithms-correctness-stderr.txt new file mode 100644 index 0000000..e69de29 diff --git a/dev/research/metal_pathfinding/optimization/results/cpu-algorithms-correctness.csv b/dev/research/metal_pathfinding/optimization/results/cpu-algorithms-correctness.csv new file mode 100644 index 0000000..e07f558 --- /dev/null +++ b/dev/research/metal_pathfinding/optimization/results/cpu-algorithms-correctness.csv @@ -0,0 +1,25 @@ +case,n,e,queries,method,wall_ms,samples,correct,wall_samples_ms +random_masked,40,240,8,cpu_heap_cached_full,0.071250,3,pass,0.071250;0.105375;0.068625 +random_masked,40,240,8,cpu_dial_full,0.098166,3,pass,0.098166;0.102000;0.074667 +random_masked,43,258,8,cpu_heap_cached_full,0.055875,3,pass,0.056250;0.055875;0.050292 +random_masked,43,258,8,cpu_dial_full,0.070917,3,pass,0.075584;0.066958;0.070917 +random_masked,46,276,8,cpu_heap_cached_full,0.046125,3,pass,0.046125;0.068375;0.039542 +random_masked,46,276,8,cpu_dial_full,0.047875,3,pass,0.047875;0.046584;0.048292 +random_masked,49,294,8,cpu_heap_cached_full,0.036167,3,pass,0.036792;0.036167;0.035959 +random_masked,49,294,8,cpu_dial_full,0.071708,3,pass,0.076000;0.066041;0.071708 +random_masked,52,312,8,cpu_heap_cached_full,0.043042,3,pass,0.043042;0.038292;0.045834 +random_masked,52,312,8,cpu_dial_full,0.073292,3,pass,0.073292;0.066792;0.132083 +random_masked,55,330,8,cpu_heap_cached_full,0.081459,3,pass,0.081459;0.110833;0.060291 +random_masked,55,330,8,cpu_dial_full,0.073916,3,pass,0.076041;0.072708;0.073916 +random_masked,58,348,8,cpu_heap_cached_full,0.051208,3,pass,0.050000;0.052500;0.051208 +random_masked,58,348,8,cpu_dial_full,0.076958,3,pass,0.072708;0.076958;0.080125 +random_masked,61,366,8,cpu_heap_cached_full,0.058750,3,pass,0.061791;0.058750;0.057625 +random_masked,61,366,8,cpu_dial_full,0.070542,3,pass,0.098166;0.070542;0.065000 +random_masked,64,384,8,cpu_heap_cached_full,0.039000,3,pass,0.042792;0.039000;0.038334 +random_masked,64,384,8,cpu_dial_full,0.050416,3,pass,0.053541;0.049709;0.050416 +random_masked,67,402,8,cpu_heap_cached_full,0.044000,3,pass,0.044000;0.046917;0.041500 +random_masked,67,402,8,cpu_dial_full,0.060459,3,pass,0.060459;0.064542;0.057333 +random_masked,70,420,8,cpu_heap_cached_full,0.042750,3,pass,0.039958;0.042750;0.046542 +random_masked,70,420,8,cpu_dial_full,0.056625,3,pass,0.056958;0.053167;0.056625 +random_masked,73,438,8,cpu_heap_cached_full,0.043666,3,pass,0.046833;0.043666;0.041209 +random_masked,73,438,8,cpu_dial_full,0.067417,3,pass,0.067417;0.065042;0.072167 diff --git a/dev/research/metal_pathfinding/optimization/results/cpu-algorithms-full-sanitized-stderr.txt b/dev/research/metal_pathfinding/optimization/results/cpu-algorithms-full-sanitized-stderr.txt new file mode 100644 index 0000000..e69de29 diff --git a/dev/research/metal_pathfinding/optimization/results/cpu-algorithms-full-sanitized.csv b/dev/research/metal_pathfinding/optimization/results/cpu-algorithms-full-sanitized.csv new file mode 100644 index 0000000..54cbd5e --- /dev/null +++ b/dev/research/metal_pathfinding/optimization/results/cpu-algorithms-full-sanitized.csv @@ -0,0 +1,15 @@ +case,n,e,queries,method,wall_ms,samples,correct,wall_samples_ms +random,1024,8192,1,cpu_heap_cached_full,0.293125,2,pass,0.293125;0.276083 +random,1024,8192,1,cpu_dial_full,0.255416,2,pass,0.230334;0.255416 +random,4096,32768,256,cpu_heap_cached_full,36.254208,2,pass,35.992750;36.254208 +random,4096,32768,256,cpu_dial_full,25.138833,2,pass,25.138833;25.111958 +random,16384,131072,64,cpu_heap_cached_full,40.832542,2,pass,40.832542;40.449167 +random,16384,131072,64,cpu_dial_full,26.089500,2,pass,26.089500;25.896417 +random,65536,524288,1,cpu_heap_cached_full,31.633041,2,pass,31.633041;29.508083 +random,65536,524288,1,cpu_dial_full,18.166167,2,pass,17.720125;18.166167 +random,4096,131072,64,cpu_heap_cached_full,19.184083,2,pass,19.184083;19.154291 +random,4096,131072,64,cpu_dial_full,15.231375,2,pass,15.231375;14.640042 +clos,800,320000,64,cpu_heap_cached_full,43.773750,2,pass,43.773750;43.312208 +clos,800,320000,64,cpu_dial_full,43.499792,2,pass,43.499792;42.404333 +grid,10000,39600,1,cpu_heap_cached_full,1.385875,2,pass,1.385875;1.377625 +grid,10000,39600,1,cpu_dial_full,1.141959,2,pass,1.141959;1.111958 diff --git a/dev/research/metal_pathfinding/optimization/results/cpu-algorithms-sanitized-stderr.txt b/dev/research/metal_pathfinding/optimization/results/cpu-algorithms-sanitized-stderr.txt new file mode 100644 index 0000000..e69de29 diff --git a/dev/research/metal_pathfinding/optimization/results/cpu-algorithms-sanitized.csv b/dev/research/metal_pathfinding/optimization/results/cpu-algorithms-sanitized.csv new file mode 100644 index 0000000..d524588 --- /dev/null +++ b/dev/research/metal_pathfinding/optimization/results/cpu-algorithms-sanitized.csv @@ -0,0 +1,25 @@ +case,n,e,queries,method,wall_ms,samples,correct,wall_samples_ms +random_masked,40,240,8,cpu_heap_cached_full,0.043625,3,pass,0.109250;0.043625;0.035917 +random_masked,40,240,8,cpu_dial_full,0.049208,3,pass,0.049208;0.050166;0.036667 +random_masked,43,258,8,cpu_heap_cached_full,0.038792,3,pass,0.035000;0.038792;0.054958 +random_masked,43,258,8,cpu_dial_full,0.046375,3,pass,0.039625;0.057541;0.046375 +random_masked,46,276,8,cpu_heap_cached_full,0.043917,3,pass,0.046292;0.037916;0.043917 +random_masked,46,276,8,cpu_dial_full,0.041042,3,pass,0.038416;0.042791;0.041042 +random_masked,49,294,8,cpu_heap_cached_full,0.037500,3,pass,0.038541;0.037500;0.035583 +random_masked,49,294,8,cpu_dial_full,0.049791,3,pass,0.049791;0.036833;0.064375 +random_masked,52,312,8,cpu_heap_cached_full,0.042708,3,pass,0.042708;0.046125;0.035916 +random_masked,52,312,8,cpu_dial_full,0.068458,3,pass,0.054041;0.072625;0.068458 +random_masked,55,330,8,cpu_heap_cached_full,0.066625,3,pass,0.057458;0.066625;0.068417 +random_masked,55,330,8,cpu_dial_full,0.065458,3,pass,0.076583;0.064750;0.065458 +random_masked,58,348,8,cpu_heap_cached_full,0.055541,3,pass,0.054750;0.055541;0.057458 +random_masked,58,348,8,cpu_dial_full,0.053125,3,pass,0.078167;0.053125;0.052375 +random_masked,61,366,8,cpu_heap_cached_full,0.050625,3,pass,0.050625;0.052167;0.039917 +random_masked,61,366,8,cpu_dial_full,0.058291,3,pass,0.058291;0.039958;0.058917 +random_masked,64,384,8,cpu_heap_cached_full,0.038958,3,pass,0.038958;0.044500;0.037500 +random_masked,64,384,8,cpu_dial_full,0.050000,3,pass,0.050000;0.058875;0.045875 +random_masked,67,402,8,cpu_heap_cached_full,0.042708,3,pass,0.042708;0.039458;0.051000 +random_masked,67,402,8,cpu_dial_full,0.046167,3,pass,0.050625;0.046167;0.045709 +random_masked,70,420,8,cpu_heap_cached_full,0.044000,3,pass,0.047750;0.040458;0.044000 +random_masked,70,420,8,cpu_dial_full,0.053875,3,pass,0.053875;0.053875;0.050334 +random_masked,73,438,8,cpu_heap_cached_full,0.054250,3,pass,0.056334;0.054250;0.046958 +random_masked,73,438,8,cpu_dial_full,0.065000,3,pass,0.069834;0.065000;0.060791 diff --git a/dev/research/metal_pathfinding/optimization/results/sanitize-test.txt b/dev/research/metal_pathfinding/optimization/results/sanitize-test.txt new file mode 100644 index 0000000..7502c0a --- /dev/null +++ b/dev/research/metal_pathfinding/optimization/results/sanitize-test.txt @@ -0,0 +1,352 @@ +-- pybind11 not found via config; using FetchContent +-- pybind11 v3.0.0 +-- Enabling sanitizers (disables optimizations) +-- Configuring done (0.6s) +-- Generating done (0.0s) +-- Build files have been written to: /Users/networmix/ws/NetGraph-Core/build/cpp-sanitize +ninja: no work to do. +Test project /Users/networmix/ws/NetGraph-Core/build/cpp-sanitize + Start 51: ShortestPathsTo.DistancesMatchForwardDistancesToDst + Start 52: ShortestPathsTo.ForwardSpfFromPseudoSourceKeepsOnlyNearestSource + Start 77: FlowState.EqualBalanced_SaturatedMemberBlocksAdmission + Start 78: FlowState.EqualBalanced_ProgressesOnlyThroughResidualAwareSpf + 1/170 Test #77: FlowState.EqualBalanced_SaturatedMemberBlocksAdmission ............................ Passed 0.08 sec + 2/170 Test #78: FlowState.EqualBalanced_ProgressesOnlyThroughResidualAwareSpf ..................... Passed 0.08 sec + Start 54: ShortestPathsTo.FanoutSkipsUnreachableAndMaskedHeads + Start 53: ShortestPathsTo.FanoutEdgesForceEverySourceIntoTheDag + 3/170 Test #51: ShortestPathsTo.DistancesMatchForwardDistancesToDst ............................... Passed 0.09 sec + 4/170 Test #52: ShortestPathsTo.ForwardSpfFromPseudoSourceKeepsOnlyNearestSource .................. Passed 0.09 sec + Start 55: ShortestPathsTo.FanoutFromInteriorNodeIsRejected + Start 56: ShortestPathsTo.SinglePathModeKeepsOneSuccessorPerNode + 5/170 Test #54: ShortestPathsTo.FanoutSkipsUnreachableAndMaskedHeads .............................. Passed 0.05 sec + Start 80: FlowState.EqualBalancedLossy_DeficitPropagatesDownstream + 6/170 Test #53: ShortestPathsTo.FanoutEdgesForceEverySourceIntoTheDag ............................. Passed 0.05 sec + 7/170 Test #55: ShortestPathsTo.FanoutFromInteriorNodeIsRejected .................................. Passed 0.05 sec + Start 79: FlowState.EqualBalancedLossy_FillAndDropReportsDrops + Start 81: FlowState.EqualBalancedLossy_InfiniteRequestFillsWithoutDrops + 8/170 Test #56: ShortestPathsTo.SinglePathModeKeepsOneSuccessorPerNode ............................ Passed 0.05 sec + Start 82: FlowGraph.LossyPlacementIsReversibleAndDropsStayOutOfLedger + 9/170 Test #80: FlowState.EqualBalancedLossy_DeficitPropagatesDownstream .......................... Passed 0.05 sec + 10/170 Test #79: FlowState.EqualBalancedLossy_FillAndDropReportsDrops .............................. Passed 0.05 sec + 11/170 Test #81: FlowState.EqualBalancedLossy_InfiniteRequestFillsWithoutDrops ..................... Passed 0.05 sec + Start 93: FlowGraphStamp.CopiesAndMovesGetFreshUids + Start 94: FlowGraphStamp.EqualVersionDivergentCopiesCompareUnequal + Start 16: FlowPolicyCostBounds.MaxPathCostFactor_HugeProduct_DropsBoundInsteadOfWrapping + 12/170 Test #82: FlowGraph.LossyPlacementIsReversibleAndDropsStayOutOfLedger ....................... Passed 0.05 sec + Start 15: FlowPolicyCostBounds.MaxPathCostFactor_UnreachableDst_KeepsSentinelOutOfTheCast + 13/170 Test #94: FlowGraphStamp.EqualVersionDivergentCopiesCompareUnequal .......................... Passed 0.06 sec + Start 92: FlowGraph.LedgerMicroFlows_RemovalRestoresResidual + 14/170 Test #93: FlowGraphStamp.CopiesAndMovesGetFreshUids ......................................... Passed 0.06 sec + 15/170 Test #16: FlowPolicyCostBounds.MaxPathCostFactor_HugeProduct_DropsBoundInsteadOfWrapping .... Passed 0.06 sec + 16/170 Test #15: FlowPolicyCostBounds.MaxPathCostFactor_UnreachableDst_KeepsSentinelOutOfTheCast ... Passed 0.06 sec + Start 47: ShortestPaths.ResolveToPathsWithMaxPathsLimit + Start 156: MaskingTests.CombinedNodeAndEdgeMasks + Start 169: MaskingTests.AlgorithmsAPIMaskedSource + 17/170 Test #47: ShortestPaths.ResolveToPathsWithMaxPathsLimit ..................................... Passed 0.06 sec + Start 46: ShortestPaths.ResolveToPathsSplittingParallelEdges + 18/170 Test #156: MaskingTests.CombinedNodeAndEdgeMasks ............................................. Passed 0.06 sec + 19/170 Test #169: MaskingTests.AlgorithmsAPIMaskedSource ............................................ Passed 0.06 sec + Start 48: ShortestPaths.LargeGraphStressTest + Start 86: FlowGraph.RemoveByClassFiltersCorrectly + 20/170 Test #92: FlowGraph.LedgerMicroFlows_RemovalRestoresResidual ................................ Passed 0.07 sec + Start 90: FlowGraph.CoalescesDuplicateEdgeIds + 21/170 Test #46: ShortestPaths.ResolveToPathsSplittingParallelEdges ................................ Passed 0.06 sec + Start 163: MaskingTests.MaxFlowWithEdgeMask + 22/170 Test #86: FlowGraph.RemoveByClassFiltersCorrectly ........................................... Passed 0.06 sec + Start 125: MaxFlow.Clos_3Tier_Topology_EqualBalanced_Shortest + 23/170 Test #48: ShortestPaths.LargeGraphStressTest ................................................ Passed 0.06 sec + Start 164: MaskingTests.MaxFlowAllPathsMasked + 24/170 Test #90: FlowGraph.CoalescesDuplicateEdgeIds ............................................... Passed 0.06 sec + Start 128: MaxFlow.ShortestPath_MustSaturateAllEqualCostPaths + 25/170 Test #125: MaxFlow.Clos_3Tier_Topology_EqualBalanced_Shortest ................................ Passed 0.06 sec + Start 98: MaxFlow.DegenerateCase_SourceEqualsSink + 26/170 Test #163: MaskingTests.MaxFlowWithEdgeMask .................................................. Passed 0.06 sec + Start 118: MaxFlow.OptionalOutputs_ResidualAndReachable + 27/170 Test #164: MaskingTests.MaxFlowAllPathsMasked ................................................ Passed 0.06 sec + Start 69: FlowState.ApplyDeltasClampsWithinCapacityBounds + 28/170 Test #128: MaxFlow.ShortestPath_MustSaturateAllEqualCostPaths ................................ Passed 0.06 sec + Start 26: StrictMultiDiGraph.ZeroCostEdges + 29/170 Test #98: MaxFlow.DegenerateCase_SourceEqualsSink ........................................... Passed 0.06 sec + 30/170 Test #118: MaxFlow.OptionalOutputs_ResidualAndReachable ...................................... Passed 0.06 sec + 31/170 Test #69: FlowState.ApplyDeltasClampsWithinCapacityBounds ................................... Passed 0.06 sec + Start 68: FlowState.ResetWithInvalidResidualThrows + Start 168: MaskingTests.AllEdgesMaskedNoReachability + Start 149: MaskingTests.MaskedSourceInComputeMinCut + 32/170 Test #26: StrictMultiDiGraph.ZeroCostEdges .................................................. Passed 0.06 sec + Start 142: KShortestPaths.LooplessPaths + 33/170 Test #68: FlowState.ResetWithInvalidResidualThrows .......................................... Passed 0.06 sec + Start 122: MaxFlow.GridGraph_3x3_MultipleEqualCostPaths + 34/170 Test #168: MaskingTests.AllEdgesMaskedNoReachability ......................................... Passed 0.06 sec + 35/170 Test #149: MaskingTests.MaskedSourceInComputeMinCut .......................................... Passed 0.06 sec + Start 25: StrictMultiDiGraph.MaxCapacityEdges + Start 106: MaxFlow.AsymmetricCapacity_1to1M_NumericalStability + 36/170 Test #142: KShortestPaths.LooplessPaths ...................................................... Passed 0.06 sec + Start 116: MaxFlow.MinCut_ValidEdgeIdentification + 37/170 Test #122: MaxFlow.GridGraph_3x3_MultipleEqualCostPaths ...................................... Passed 0.06 sec + 38/170 Test #25: StrictMultiDiGraph.MaxCapacityEdges ............................................... Passed 0.06 sec + Start 141: KShortestPaths.DisconnectedReturnsEmpty + Start 29: StrictMultiDiGraph.ExtEdgeIdsWrongLengthThrows + 39/170 Test #106: MaxFlow.AsymmetricCapacity_1to1M_NumericalStability ............................... Passed 0.06 sec + Start 96: MaxFlow.SinglePath_BottleneckConstraint + 40/170 Test #116: MaxFlow.MinCut_ValidEdgeIdentification ............................................ Passed 0.06 sec + Start 60: FlowState.EqualBalancedDistribution + 41/170 Test #29: StrictMultiDiGraph.ExtEdgeIdsWrongLengthThrows .................................... Passed 0.06 sec + 42/170 Test #96: MaxFlow.SinglePath_BottleneckConstraint ........................................... Passed 0.06 sec + Start 154: MaskingTests.MaskedEdgeSelectsAlternativePath + Start 95: MaxFlow.SinglePath_BasicLinear + 43/170 Test #141: KShortestPaths.DisconnectedReturnsEmpty ........................................... Passed 0.06 sec + Start 121: MaxFlow.BatchMaxFlow_IndependentMaskApplication + 44/170 Test #60: FlowState.EqualBalancedDistribution ............................................... Passed 0.06 sec + Start 39: ShortestPaths.ResidualAwareFiltering + 45/170 Test #95: MaxFlow.SinglePath_BasicLinear .................................................... Passed 0.06 sec + 46/170 Test #121: MaxFlow.BatchMaxFlow_IndependentMaskApplication ................................... Passed 0.06 sec + Start 63: FlowState.ApplyDeltasSubtractive + Start 136: KShortestPaths.KEqualsZeroReturnsEmpty + 47/170 Test #154: MaskingTests.MaskedEdgeSelectsAlternativePath ..................................... Passed 0.07 sec + 48/170 Test #39: ShortestPaths.ResidualAwareFiltering .............................................. Passed 0.06 sec + Start 117: MaxFlow.CostDistribution_AccountsForAllFlow + Start 44: ShortestPaths.TieBreakingDeterminism + 49/170 Test #63: FlowState.ApplyDeltasSubtractive .................................................. Passed 0.06 sec + Start 151: MaskingTests.MaskedDestinationUnreachable + 50/170 Test #136: KShortestPaths.KEqualsZeroReturnsEmpty ............................................ Passed 0.06 sec + 51/170 Test #117: MaxFlow.CostDistribution_AccountsForAllFlow ....................................... Passed 0.06 sec + 52/170 Test #44: ShortestPaths.TieBreakingDeterminism .............................................. Passed 0.06 sec + Start 104: MaxFlow.ECMP_TenPaths_ScalabilityValidation + Start 85: FlowGraph.RemovalDeletesEntry + Start 138: KShortestPaths.UniqueModeFiltering + 53/170 Test #104: MaxFlow.ECMP_TenPaths_ScalabilityValidation ....................................... Passed 0.06 sec + 54/170 Test #85: FlowGraph.RemovalDeletesEntry ..................................................... Passed 0.06 sec + Start 111: MaxFlow.TwoCostTiers_FullMaxFlow_AllTiers + Start 14: FlowPolicyStatic.ValidationRejectsForeignAndDisconnectedBundles + 55/170 Test #151: MaskingTests.MaskedDestinationUnreachable ......................................... Passed 0.06 sec + 56/170 Test #138: KShortestPaths.UniqueModeFiltering ................................................ Passed 0.06 sec + Start 165: MaskingTests.EmptyNodeMaskAllowsAllNodes + Start 132: MaxFlow.Sensitivity_ShortestPathVsMaxFlow + 57/170 Test #111: MaxFlow.TwoCostTiers_FullMaxFlow_AllTiers ......................................... Passed 0.06 sec + Start 37: ShortestPaths.DisconnectedComponents + 58/170 Test #14: FlowPolicyStatic.ValidationRejectsForeignAndDisconnectedBundles ................... Passed 0.06 sec + 59/170 Test #165: MaskingTests.EmptyNodeMaskAllowsAllNodes .......................................... Passed 0.06 sec + 60/170 Test #132: MaxFlow.Sensitivity_ShortestPathVsMaxFlow ......................................... Passed 0.06 sec + Start 89: FlowGraph.GetFlowPathForDAGReturnsEmpty + Start 124: MaxFlow.Clos_3Tier_Topology_Proportional_Shortest + Start 129: MaxFlow.Sensitivity_SinglePath + 61/170 Test #124: MaxFlow.Clos_3Tier_Topology_Proportional_Shortest ................................. Passed 0.06 sec + 62/170 Test #129: MaxFlow.Sensitivity_SinglePath .................................................... Passed 0.06 sec + Start 91: FlowGraph.LedgerHistory_RemovalRestoresResidual + Start 75: FlowState.Proportional_ZeroCapacityOnShortestPath_ReturnsZero + 63/170 Test #37: ShortestPaths.DisconnectedComponents .............................................. Passed 0.06 sec + 64/170 Test #89: FlowGraph.GetFlowPathForDAGReturnsEmpty ........................................... Passed 0.06 sec + Start 27: StrictMultiDiGraph.InvalidNumNodesThrows + Start 76: FlowState.RepeatedPlacementAfterResetAndIndependentInstancesStayStable + 65/170 Test #91: FlowGraph.LedgerHistory_RemovalRestoresResidual ................................... Passed 0.07 sec + 66/170 Test #75: FlowState.Proportional_ZeroCapacityOnShortestPath_ReturnsZero ..................... Passed 0.07 sec + Start 153: MaskingTests.MaskedEdgeBlocksPath + Start 99: MaxFlow.ECMP_TwoPaths_Proportional_ShortestPath + 67/170 Test #27: StrictMultiDiGraph.InvalidNumNodesThrows .......................................... Passed 0.07 sec + 68/170 Test #76: FlowState.RepeatedPlacementAfterResetAndIndependentInstancesStayStable ............ Passed 0.07 sec + Start 120: MaxFlow.EdgeMask_SelectiveEdgeFiltering + Start 101: MaxFlow.ECMP_TwoPaths_EqualBalanced_ShortestPath + 69/170 Test #120: MaxFlow.EdgeMask_SelectiveEdgeFiltering ........................................... Passed 0.06 sec + Start 35: StrictMultiDiGraph.MultipleCostTiers + 70/170 Test #153: MaskingTests.MaskedEdgeBlocksPath ................................................. Passed 0.06 sec + 71/170 Test #99: MaxFlow.ECMP_TwoPaths_Proportional_ShortestPath ................................... Passed 0.06 sec + 72/170 Test #101: MaxFlow.ECMP_TwoPaths_EqualBalanced_ShortestPath .................................. Passed 0.06 sec + Start 161: MaskingTests.KSPWithEdgeMask + Start 102: MaxFlow.ECMP_ThreePaths_Proportional_ShortestPath + Start 2: FlowPolicyCore.Proportional_SingleDemand_UsesShortestPath + 73/170 Test #35: StrictMultiDiGraph.MultipleCostTiers .............................................. Passed 0.06 sec + Start 167: MaskingTests.AllNodesMaskedNoReachability + 74/170 Test #161: MaskingTests.KSPWithEdgeMask ...................................................... Passed 0.06 sec + 75/170 Test #102: MaxFlow.ECMP_ThreePaths_Proportional_ShortestPath ................................. Passed 0.06 sec + 76/170 Test #2: FlowPolicyCore.Proportional_SingleDemand_UsesShortestPath ......................... Passed 0.06 sec + Start 64: FlowState.MinCutComputation + Start 139: KShortestPaths.MaxCostFactorLimit + Start 3: FlowPolicyCore.Proportional_SingleDemand_SplitsAcrossTwoEqualCostPaths + 77/170 Test #167: MaskingTests.AllNodesMaskedNoReachability ......................................... Passed 0.06 sec + Start 11: FlowPolicyCore.EqualBalanced_ShortestPath_IgnoresHigherCostTier + 78/170 Test #64: FlowState.MinCutComputation ....................................................... Passed 0.06 sec + 79/170 Test #139: KShortestPaths.MaxCostFactorLimit ................................................. Passed 0.06 sec + 80/170 Test #3: FlowPolicyCore.Proportional_SingleDemand_SplitsAcrossTwoEqualCostPaths ............ Passed 0.06 sec + Start 133: MaxFlow.CompletionPhase_RecoversCancellation + Start 18: StrictMultiDiGraph.SingleNode + Start 49: ShortestPaths.RejectsMaskLengthMismatch + 81/170 Test #133: MaxFlow.CompletionPhase_RecoversCancellation ...................................... Passed 0.07 sec + Start 13: FlowPolicyStatic.MaskedBundleIsDown + 82/170 Test #11: FlowPolicyCore.EqualBalanced_ShortestPath_IgnoresHigherCostTier ................... Passed 0.07 sec + 83/170 Test #18: StrictMultiDiGraph.SingleNode ..................................................... Passed 0.07 sec + 84/170 Test #49: ShortestPaths.RejectsMaskLengthMismatch ........................................... Passed 0.07 sec + Start 110: MaxFlow.TwoCostTiers_ShortestPath_SingleTierOnly + Start 100: MaxFlow.ECMP_TwoPaths_Proportional_FullMaxFlow + Start 23: StrictMultiDiGraph.CSROffsetsMonotonicity + 85/170 Test #13: FlowPolicyStatic.MaskedBundleIsDown ............................................... Passed 0.07 sec + 86/170 Test #110: MaxFlow.TwoCostTiers_ShortestPath_SingleTierOnly .................................. Passed 0.07 sec + 87/170 Test #100: MaxFlow.ECMP_TwoPaths_Proportional_FullMaxFlow .................................... Passed 0.07 sec + Start 22: StrictMultiDiGraph.ExternalEdgeIdsPreserved + Start 7: FlowPolicyCore.EqualBalanced_SingleDemand_FlowCount3_SaturatesBothPaths + Start 145: KSP.MaxCostFactorBelowOne_ReturnsEmptyForAllK + 88/170 Test #23: StrictMultiDiGraph.CSROffsetsMonotonicity ......................................... Passed 0.07 sec + Start 119: MaxFlow.NodeMask_BlocksFlowThroughNode + 89/170 Test #22: StrictMultiDiGraph.ExternalEdgeIdsPreserved ....................................... Passed 0.07 sec + 90/170 Test #145: KSP.MaxCostFactorBelowOne_ReturnsEmptyForAllK ..................................... Passed 0.06 sec + Start 65: FlowState.ResetRestoresCapacity + Start 135: KShortestPaths.FindsKPaths + 91/170 Test #7: FlowPolicyCore.EqualBalanced_SingleDemand_FlowCount3_SaturatesBothPaths ........... Passed 0.07 sec + 92/170 Test #119: MaxFlow.NodeMask_BlocksFlowThroughNode ............................................ Passed 0.07 sec + Start 143: KShortestPaths.OutOfOrderNodePredDAGSemantics + Start 134: MaxFlow.CompletionPhase_RespectsNodeMask + 93/170 Test #143: KShortestPaths.OutOfOrderNodePredDAGSemantics ..................................... Passed 0.06 sec + Start 43: ShortestPaths.PredDAGIntegrity + 94/170 Test #65: FlowState.ResetRestoresCapacity ................................................... Passed 0.06 sec + 95/170 Test #135: KShortestPaths.FindsKPaths ........................................................ Passed 0.06 sec + 96/170 Test #134: MaxFlow.CompletionPhase_RespectsNodeMask .......................................... Passed 0.06 sec + Start 33: StrictMultiDiGraph.SelfLoopAllowed + Start 62: FlowState.ApplyDeltasAdditive + Start 32: StrictMultiDiGraph.NegativeCostThrows + 97/170 Test #43: ShortestPaths.PredDAGIntegrity .................................................... Passed 0.07 sec + 98/170 Test #62: FlowState.ApplyDeltasAdditive ..................................................... Passed 0.07 sec + Start 19: StrictMultiDiGraph.SingleEdge + Start 144: KShortestPaths.LargerOutOfOrderTopology + 99/170 Test #33: StrictMultiDiGraph.SelfLoopAllowed ................................................ Passed 0.07 sec +100/170 Test #32: StrictMultiDiGraph.NegativeCostThrows ............................................. Passed 0.07 sec + Start 97: MaxFlow.SinglePath_ShortestPathEquivalence + Start 114: MaxFlow.PlacementModes_EqualCapacity_IdenticalResult +101/170 Test #19: StrictMultiDiGraph.SingleEdge ..................................................... Passed 0.06 sec + Start 170: MaskingTests.AlgorithmsAPIMaxFlowWithMask +102/170 Test #144: KShortestPaths.LargerOutOfOrderTopology ........................................... Passed 0.06 sec +103/170 Test #97: MaxFlow.SinglePath_ShortestPathEquivalence ........................................ Passed 0.06 sec +104/170 Test #114: MaxFlow.PlacementModes_EqualCapacity_IdenticalResult .............................. Passed 0.06 sec + Start 4: FlowPolicyCore.Proportional_SingleDemand_MaxFlowCount1_UsesSinglePath + Start 131: MaxFlow.Sensitivity_PartialSaturation + Start 61: FlowState.ZeroCapacityHandling +105/170 Test #170: MaskingTests.AlgorithmsAPIMaxFlowWithMask ......................................... Passed 0.07 sec +106/170 Test #131: MaxFlow.Sensitivity_PartialSaturation ............................................. Passed 0.07 sec + Start 159: MaskingTests.ResidualAndNodeMaskCombined + Start 109: MaxFlow.ZeroCapacityPath_CorrectFiltering +107/170 Test #4: FlowPolicyCore.Proportional_SingleDemand_MaxFlowCount1_UsesSinglePath ............. Passed 0.07 sec +108/170 Test #61: FlowState.ZeroCapacityHandling .................................................... Passed 0.07 sec + Start 21: StrictMultiDiGraph.EdgeSortingByCost + Start 20: StrictMultiDiGraph.ParallelEdges +109/170 Test #109: MaxFlow.ZeroCapacityPath_CorrectFiltering ......................................... Passed 0.06 sec + Start 115: MaxFlow.FlowConservation_IntermediateNodes +110/170 Test #159: MaskingTests.ResidualAndNodeMaskCombined .......................................... Passed 0.07 sec +111/170 Test #21: StrictMultiDiGraph.EdgeSortingByCost .............................................. Passed 0.07 sec +112/170 Test #20: StrictMultiDiGraph.ParallelEdges .................................................. Passed 0.07 sec + Start 8: FlowPolicyCore.DiminishingReturnsCutoff + Start 147: MaskingTests.MaskedSourceWithDestination + Start 45: ShortestPaths.PreferHigherResidualTieBreak +113/170 Test #115: MaxFlow.FlowConservation_IntermediateNodes ........................................ Passed 0.07 sec +114/170 Test #147: MaskingTests.MaskedSourceWithDestination .......................................... Passed 0.06 sec +115/170 Test #45: ShortestPaths.PreferHigherResidualTieBreak ........................................ Passed 0.06 sec + Start 160: MaskingTests.KSPWithNodeMask + Start 74: FlowState.EqualBalanced_ZeroCapacityOnShortestPath_ReturnsZero + Start 42: ShortestPaths.EarlyExitOptimization +116/170 Test #8: FlowPolicyCore.DiminishingReturnsCutoff ........................................... Passed 0.07 sec + Start 126: MaxFlow.Triangle_Topology_Combine_Mode +117/170 Test #42: ShortestPaths.EarlyExitOptimization ............................................... Passed 0.06 sec + Start 84: FlowGraph.PlacementCreatesEntry +118/170 Test #160: MaskingTests.KSPWithNodeMask ...................................................... Passed 0.07 sec +119/170 Test #74: FlowState.EqualBalanced_ZeroCapacityOnShortestPath_ReturnsZero .................... Passed 0.07 sec +120/170 Test #126: MaxFlow.Triangle_Topology_Combine_Mode ............................................ Passed 0.06 sec + Start 146: MaskingTests.MaskedSourceReturnsEmptyDAG + Start 88: FlowGraph.GetFlowPathForLinearFlow + Start 72: FlowState.EqualBalanced_MinFlowGating_DoesNotPruneValidParallelEdges +121/170 Test #84: FlowGraph.PlacementCreatesEntry ................................................... Passed 0.07 sec + Start 67: FlowState.InvalidResidualInitThrows +122/170 Test #146: MaskingTests.MaskedSourceReturnsEmptyDAG .......................................... Passed 0.07 sec +123/170 Test #88: FlowGraph.GetFlowPathForLinearFlow ................................................ Passed 0.07 sec +124/170 Test #72: FlowState.EqualBalanced_MinFlowGating_DoesNotPruneValidParallelEdges .............. Passed 0.07 sec + Start 6: FlowPolicyCore.EqualBalanced_SingleDemand_FlowCount2_BalancedDistribution + Start 66: FlowState.CustomInitialResidual + Start 17: StrictMultiDiGraph.EmptyGraph +125/170 Test #66: FlowState.CustomInitialResidual ................................................... Passed 0.07 sec + Start 1: GraphSmoke.ConstructAndRunSPF +126/170 Test #67: FlowState.InvalidResidualInitThrows ............................................... Passed 0.07 sec +127/170 Test #6: FlowPolicyCore.EqualBalanced_SingleDemand_FlowCount2_BalancedDistribution ......... Passed 0.07 sec +128/170 Test #17: StrictMultiDiGraph.EmptyGraph ..................................................... Passed 0.07 sec + Start 150: MaskingTests.OutOfRangeSourceInComputeMinCut + Start 83: FlowGraph.EmptyLedgerInitially + Start 70: FlowState.EqualBalancedReconvergentDAGPlacesAll +129/170 Test #1: GraphSmoke.ConstructAndRunSPF ..................................................... Passed 0.07 sec + Start 107: MaxFlow.AsymmetricCapacity_1to100_EqualBalanced +130/170 Test #150: MaskingTests.OutOfRangeSourceInComputeMinCut ...................................... Passed 0.07 sec +131/170 Test #83: FlowGraph.EmptyLedgerInitially .................................................... Passed 0.07 sec +132/170 Test #70: FlowState.EqualBalancedReconvergentDAGPlacesAll ................................... Passed 0.07 sec + Start 24: StrictMultiDiGraph.CSRReverseAdjacency + Start 34: StrictMultiDiGraph.NegativeNodeIdThrows + Start 162: MaskingTests.MaxFlowWithNodeMask +133/170 Test #34: StrictMultiDiGraph.NegativeNodeIdThrows ........................................... Passed 0.07 sec + Start 87: FlowGraph.GetFlowEdgesReturnsDeltas +134/170 Test #107: MaxFlow.AsymmetricCapacity_1to100_EqualBalanced ................................... Passed 0.07 sec +135/170 Test #24: StrictMultiDiGraph.CSRReverseAdjacency ............................................ Passed 0.07 sec +136/170 Test #162: MaskingTests.MaxFlowWithNodeMask .................................................. Passed 0.07 sec + Start 127: MaxFlow.SimpleParallelPaths_Topology + Start 166: MaskingTests.EmptyEdgeMaskAllowsAllEdges + Start 108: MaxFlow.EqualBalanced_NodeMask_ReducesECMPWidth +137/170 Test #127: MaxFlow.SimpleParallelPaths_Topology .............................................. Passed 0.07 sec + Start 59: FlowState.ProportionalDistribution +138/170 Test #87: FlowGraph.GetFlowEdgesReturnsDeltas ............................................... Passed 0.07 sec +139/170 Test #166: MaskingTests.EmptyEdgeMaskAllowsAllEdges .......................................... Passed 0.07 sec +140/170 Test #108: MaxFlow.EqualBalanced_NodeMask_ReducesECMPWidth ................................... Passed 0.07 sec + Start 155: MaskingTests.MultipleEdgesMasked + Start 140: KShortestPaths.PathsSortedByCost + Start 50: ShortestPaths.ZeroCostEdges_PredDAGIsAcyclic +141/170 Test #59: FlowState.ProportionalDistribution ................................................ Passed 0.07 sec + Start 36: ShortestPaths.SingleSourceAllNodes +142/170 Test #155: MaskingTests.MultipleEdgesMasked .................................................. Passed 0.07 sec +143/170 Test #140: KShortestPaths.PathsSortedByCost .................................................. Passed 0.07 sec +144/170 Test #50: ShortestPaths.ZeroCostEdges_PredDAGIsAcyclic ...................................... Passed 0.07 sec + Start 105: MaxFlow.AsymmetricCapacity_1to100_Proportional + Start 30: StrictMultiDiGraph.OutOfRangeNodeThrows + Start 9: FlowPolicyCore.EqualBalanced_ShortestPath_ECMP3_SaturatesAllEqualCostPaths +145/170 Test #36: ShortestPaths.SingleSourceAllNodes ................................................ Passed 0.07 sec + Start 103: MaxFlow.ECMP_FourPaths_ClosFabric_Simulation +146/170 Test #105: MaxFlow.AsymmetricCapacity_1to100_Proportional .................................... Passed 0.07 sec +147/170 Test #30: StrictMultiDiGraph.OutOfRangeNodeThrows ........................................... Passed 0.07 sec +148/170 Test #9: FlowPolicyCore.EqualBalanced_ShortestPath_ECMP3_SaturatesAllEqualCostPaths ........ Passed 0.07 sec + Start 31: StrictMultiDiGraph.NegativeCapacityThrows + Start 137: KShortestPaths.NodeMaskBlocksPaths + Start 130: MaxFlow.Sensitivity_TwoParallelPaths +149/170 Test #103: MaxFlow.ECMP_FourPaths_ClosFabric_Simulation ...................................... Passed 0.07 sec +150/170 Test #31: StrictMultiDiGraph.NegativeCapacityThrows ......................................... Passed 0.07 sec +151/170 Test #137: KShortestPaths.NodeMaskBlocksPaths ................................................ Passed 0.07 sec + Start 38: ShortestPaths.MultipleEqualCostPaths + Start 41: ShortestPaths.EdgeMaskFiltering + Start 73: FlowState.EqualBalanced_DownstreamSplitEqualization +152/170 Test #130: MaxFlow.Sensitivity_TwoParallelPaths .............................................. Passed 0.07 sec + Start 10: FlowPolicyCore.EqualBalanced_ShortestPath_DownstreamSplit_BalancesBottleneck +153/170 Test #10: FlowPolicyCore.EqualBalanced_ShortestPath_DownstreamSplit_BalancesBottleneck ...... Passed 0.07 sec + Start 123: MaxFlow.SharedBottleneck_MultiplePathsMerge +154/170 Test #38: ShortestPaths.MultipleEqualCostPaths .............................................. Passed 0.07 sec +155/170 Test #41: ShortestPaths.EdgeMaskFiltering ................................................... Passed 0.07 sec +156/170 Test #73: FlowState.EqualBalanced_DownstreamSplitEqualization ............................... Passed 0.07 sec + Start 57: FlowState.InitialResidualEqualsCapacity + Start 40: ShortestPaths.NodeMaskIsolation + Start 71: FlowState.EqualBalanced_ECMP3_FirstHopEqualization +157/170 Test #123: MaxFlow.SharedBottleneck_MultiplePathsMerge ....................................... Passed 0.07 sec +158/170 Test #57: FlowState.InitialResidualEqualsCapacity ........................................... Passed 0.07 sec + Start 28: StrictMultiDiGraph.MismatchedArrayLengthsThrow + Start 158: MaskingTests.MaskWithResidualCapacity +159/170 Test #40: ShortestPaths.NodeMaskIsolation ................................................... Passed 0.07 sec +160/170 Test #71: FlowState.EqualBalanced_ECMP3_FirstHopEqualization ................................ Passed 0.07 sec + Start 148: MaskingTests.MaskedSourceInMaxFlow + Start 58: FlowState.PlacementReducesResidual +161/170 Test #158: MaskingTests.MaskWithResidualCapacity ............................................. Passed 0.07 sec + Start 113: MaxFlow.ThreeCostTiers_ShortestPath_LowestTierOnly +162/170 Test #28: StrictMultiDiGraph.MismatchedArrayLengthsThrow .................................... Passed 0.07 sec +163/170 Test #148: MaskingTests.MaskedSourceInMaxFlow ................................................ Passed 0.07 sec +164/170 Test #58: FlowState.PlacementReducesResidual ................................................ Passed 0.07 sec + Start 152: MaskingTests.MaskedIntermediateNode + Start 157: MaskingTests.NodeMaskOverridesEdgeMask + Start 112: MaxFlow.EqualCost_ShortestVsFull_Equivalent +165/170 Test #113: MaxFlow.ThreeCostTiers_ShortestPath_LowestTierOnly ................................ Passed 0.07 sec + Start 12: FlowPolicyStatic.PerFlowBundleBinding +166/170 Test #152: MaskingTests.MaskedIntermediateNode ............................................... Passed 0.07 sec +167/170 Test #157: MaskingTests.NodeMaskOverridesEdgeMask ............................................ Passed 0.07 sec +168/170 Test #112: MaxFlow.EqualCost_ShortestVsFull_Equivalent ....................................... Passed 0.07 sec + Start 5: FlowPolicyCore.Proportional_SingleDemand_PartialPlacement_InsufficientCapacity +169/170 Test #12: FlowPolicyStatic.PerFlowBundleBinding ............................................. Passed 0.07 sec +170/170 Test #5: FlowPolicyCore.Proportional_SingleDemand_PartialPlacement_InsufficientCapacity .... Passed 0.06 sec + +100% tests passed out of 170 + +Total Test time (real) = 2.80 sec diff --git a/dev/research/metal_pathfinding/optimization/results/screen-known-limitations.txt b/dev/research/metal_pathfinding/optimization/results/screen-known-limitations.txt new file mode 100644 index 0000000..87ae6b9 --- /dev/null +++ b/dev/research/metal_pathfinding/optimization/results/screen-known-limitations.txt @@ -0,0 +1,6 @@ +Exploratory screen only, not the final timing matrix. +The conversion loop invoked the Objective-C .contents accessor once per distance, +inflating host copy/conversion time on large batches. Corrected before final A/B/A. +GPU DAG thread mapping also initially used query-fast threads for query-major data. +All correctness checks passed; these were performance defects, not wrong distances. +Source hashes are in screen-source-sha256.txt. Final hashes are in aba/environment.txt. diff --git a/dev/research/metal_pathfinding/optimization/results/screen-source-sha256.txt b/dev/research/metal_pathfinding/optimization/results/screen-source-sha256.txt new file mode 100644 index 0000000..a3f0393 --- /dev/null +++ b/dev/research/metal_pathfinding/optimization/results/screen-source-sha256.txt @@ -0,0 +1,2 @@ +0dad0787fdcf08c58ed135e27290a8012865aa8b6a369cc679e8bca622f62b78 dev/research/metal_pathfinding/optimization/experiment.mm +2cdeaf23d1f11dfd07c7092824d7e991ecd70c0c597e6e40ab84c663907a3e17 dev/research/metal_pathfinding/optimization/kernels.metal diff --git a/dev/research/metal_pathfinding/optimization/results/screen-stderr.txt b/dev/research/metal_pathfinding/optimization/results/screen-stderr.txt new file mode 100644 index 0000000..b3f2aa5 --- /dev/null +++ b/dev/research/metal_pathfinding/optimization/results/screen-stderr.txt @@ -0,0 +1 @@ +device=Apple M4 Max setup_ms=26.8109 execution_width=32 diff --git a/dev/research/metal_pathfinding/optimization/results/screen.csv b/dev/research/metal_pathfinding/optimization/results/screen.csv new file mode 100644 index 0000000..6e7c168 --- /dev/null +++ b/dev/research/metal_pathfinding/optimization/results/screen.csv @@ -0,0 +1,253 @@ +case,n,e,queries,method,wall_ms,distance_ms,gpu_ms,edge_visits,rounds,waits,fallback64,upload_ms,samples,correct,wall_samples_ms +random,1024,8192,1,old_pull_serial,0.762542,0.722583,0.437500,131072,16,2,0,0.153791,2,pass,0.762542;0.745541 +random,1024,8192,1,old_group_serial,0.964084,0.894000,0.680958,106496,13,1,0,0.153791,2,pass,0.964084;0.849083 +random,1024,8192,1,old_pull_parallel_dag,0.657209,0.643500,0.419875,131072,16,2,0,0.153791,2,pass,0.657209;0.650417 +random,1024,8192,1,old_group_parallel_dag,0.939833,0.895459,0.681833,106496,13,1,0,0.153791,2,pass,0.908916;0.939833 +random,1024,8192,1,pull64_barrier,0.674375,0.661834,0.397458,131072,16,2,0,0.153791,2,pass,0.674375;0.648416 +random,1024,8192,1,pull64_interleaved,0.853959,0.841292,0.252500,131072,16,2,0,0.153791,2,pass,0.853959;0.363292 +random,1024,8192,1,pull32_interleaved,0.315500,0.302917,0.075167,131072,16,2,0,0.153791,2,pass,0.309917;0.315500 +random,1024,8192,1,pull32_gpu_dag,0.881333,0.556833,0.271792,131072,16,4,0,0.153791,2,pass,0.881333;0.724833 +random,1024,8192,1,frontier32_vertex,0.494250,0.481458,0.180125,21088,16,2,0,0.153791,2,pass,0.473500;0.494250 +random,1024,8192,1,frontier32_simd,0.547583,0.534834,0.114833,20192,16,2,0,0.153791,2,pass,0.547583;0.423667 +random,1024,8192,1,frontier32_gpu_dag,0.746000,0.396458,0.128042,20520,16,4,0,0.153791,2,pass,0.746000;0.704541 +random,1024,8192,1,bucket32_d4,0.875292,0.862667,0.336125,8232,32,4,0,0.153791,2,pass,0.875292;0.871333 +random,1024,8192,1,bucket32_d16,0.671459,0.648500,0.262375,9336,24,3,0,0.153791,2,pass,0.647792;0.671459 +random,1024,8192,1,bucket32_d64,0.512667,0.499750,0.194875,19232,16,2,0,0.153791,2,pass,0.512667;0.452000 +random,1024,8192,64,old_pull_serial,3.818625,1.461417,0.483667,12582912,24,3,0,0.240041,2,pass,3.185541;3.818625 +random,1024,8192,64,old_group_serial,3.211083,0.894833,0.200375,7217152,17,1,0,0.240041,2,pass,3.211083;2.918583 +random,1024,8192,64,old_pull_parallel_dag,3.350541,3.060875,2.247542,12582912,24,3,0,0.240041,2,pass,2.083833;3.350541 +random,1024,8192,64,old_group_parallel_dag,1.480583,1.169125,0.894125,7217152,17,1,0,0.240041,2,pass,1.480583;1.419917 +random,1024,8192,64,pull64_barrier,1.122625,0.860000,0.311584,12582912,24,3,0,0.240041,2,pass,1.011750;1.122625 +random,1024,8192,64,pull64_interleaved,6.522000,6.270875,0.893750,12582912,24,3,0,0.240041,2,pass,5.917709;6.522000 +random,1024,8192,64,pull32_interleaved,6.568875,6.294000,1.247000,12582912,24,3,0,0.240041,2,pass,6.010583;6.568875 +random,1024,8192,64,pull32_gpu_dag,6.263042,5.390250,0.853792,12582912,24,5,0,0.240041,2,pass,6.197125;6.263042 +random,1024,8192,64,frontier32_vertex,6.342208,6.096333,1.145750,1294872,24,3,0,0.240041,2,pass,6.061666;6.342208 +random,1024,8192,64,frontier32_simd,7.192625,6.939583,2.005833,1209280,24,3,0,0.240041,2,pass,6.974292;7.192625 +random,1024,8192,64,frontier32_gpu_dag,5.802583,5.041083,0.489583,1206928,16,4,0,0.240041,2,pass,5.443083;5.802583 +random,1024,8192,64,bucket32_d4,9.311792,9.060875,3.431875,528520,56,7,0,0.240041,2,pass,9.311792;7.144291 +random,1024,8192,64,bucket32_d16,6.371083,6.101125,0.695750,601784,32,4,0,0.240041,2,pass,6.371083;5.691750 +random,1024,8192,64,bucket32_d64,7.686834,7.451417,2.572083,1155632,24,3,0,0.240041,2,pass,7.686834;6.262291 +clos,200,20000,64,old_pull_serial,5.877250,1.938875,1.613708,10240000,8,1,0,0.352709,2,pass,5.877250;5.434792 +clos,200,20000,64,old_group_serial,4.889250,0.948583,0.307792,3840000,3,1,0,0.352709,2,pass,4.889250;4.813292 +clos,200,20000,64,old_pull_parallel_dag,2.647292,2.119125,1.659625,10240000,8,1,0,0.352709,2,pass,2.086042;2.647292 +clos,200,20000,64,old_group_parallel_dag,1.495584,0.891459,0.309875,3840000,3,1,0,0.352709,2,pass,1.448458;1.495584 +clos,200,20000,64,pull64_barrier,2.218833,1.683417,1.023042,10240000,8,1,0,0.352709,2,pass,2.176959;2.218833 +clos,200,20000,64,pull64_interleaved,2.864708,2.299625,0.759375,10240000,8,1,0,0.352709,2,pass,2.610125;2.864708 +clos,200,20000,64,pull32_interleaved,2.704166,2.207834,0.698500,10240000,8,1,0,0.352709,2,pass,2.192083;2.704166 +clos,200,20000,64,pull32_gpu_dag,3.827584,2.580125,1.040375,10240000,8,3,0,0.352709,2,pass,3.230459;3.827584 +clos,200,20000,64,frontier32_vertex,2.962125,2.466500,0.986083,1280000,8,1,0,0.352709,2,pass,2.831042;2.962125 +clos,200,20000,64,frontier32_simd,2.346458,1.829250,0.359958,1280000,8,1,0,0.352709,2,pass,2.346458;2.066292 +clos,200,20000,64,frontier32_gpu_dag,4.250750,2.648000,0.788458,1280000,8,3,0,0.352709,2,pass,3.753292;4.250750 +clos,200,20000,64,bucket32_d4,3.090458,2.563208,0.507375,1280000,8,1,0,0.352709,2,pass,3.090458;2.377792 +clos,200,20000,64,bucket32_d16,2.999750,2.475542,1.133083,1280000,8,1,0,0.352709,2,pass,2.999750;2.523084 +clos,200,20000,64,bucket32_d64,2.528875,1.963250,0.468000,1280000,8,1,0,0.352709,2,pass,2.084417;2.528875 +grid,1024,3968,1,old_pull_serial,1.939625,1.920792,0.651750,253952,64,8,0,0.236834,2,pass,1.939625;1.786750 +grid,1024,3968,1,old_group_serial,1.449167,1.431625,1.011500,249984,63,1,0,0.236834,2,pass,1.449167;1.185000 +grid,1024,3968,1,old_pull_parallel_dag,1.785625,1.775542,0.651499,253952,64,8,0,0.236834,2,pass,1.785625;1.649542 +grid,1024,3968,1,old_group_parallel_dag,1.162416,1.153500,1.008625,249984,63,1,0,0.236834,2,pass,1.162416;1.150083 +grid,1024,3968,1,pull64_barrier,1.762958,1.753834,0.694125,253952,64,8,0,0.236834,2,pass,1.686750;1.762958 +grid,1024,3968,1,pull64_interleaved,2.131792,2.124834,1.110167,253952,64,8,0,0.236834,2,pass,1.793583;2.131792 +grid,1024,3968,1,pull32_interleaved,1.673334,1.664458,0.629750,253952,64,8,0,0.236834,2,pass,1.673334;1.599167 +grid,1024,3968,1,pull32_gpu_dag,2.191500,1.854833,0.896833,253952,64,10,0,0.236834,2,pass,2.000917;2.191500 +grid,1024,3968,1,frontier32_vertex,3.608792,3.595083,2.566375,3968,64,8,0,0.236834,2,pass,3.608792;2.936166 +grid,1024,3968,1,frontier32_simd,2.444500,2.435167,1.407542,3968,64,8,0,0.236834,2,pass,2.444500;2.438000 +grid,1024,3968,1,frontier32_gpu_dag,2.885083,2.530792,1.446375,3968,64,10,0,0.236834,2,pass,2.885083;2.840000 +grid,1024,3968,1,bucket32_d4,3.526792,3.517083,2.379750,3968,64,8,0,0.236834,2,pass,3.444875;3.526792 +grid,1024,3968,1,bucket32_d16,4.111792,4.100167,3.000833,3968,64,8,0,0.236834,2,pass,4.111792;3.712666 +grid,1024,3968,1,bucket32_d64,4.321125,4.313125,3.175875,3968,64,8,0,0.236834,2,pass,3.525208;4.321125 +hub,1024,3070,1,old_pull_serial,6.219708,6.202666,5.564083,98240,32,4,0,0.127834,2,pass,6.219708;6.202208 +hub,1024,3070,1,old_group_serial,4.915291,4.884334,4.720250,95170,31,1,0,0.127834,2,pass,4.855542;4.915291 +hub,1024,3070,1,old_pull_parallel_dag,6.068750,6.050375,5.496250,98240,32,4,0,0.127834,2,pass,6.068750;6.043792 +hub,1024,3070,1,old_group_parallel_dag,4.942709,4.928333,4.755875,95170,31,1,0,0.127834,2,pass,4.900708;4.942709 +hub,1024,3070,1,pull64_barrier,4.900083,4.888000,4.318500,98240,32,4,0,0.127834,2,pass,4.900083;4.899708 +hub,1024,3070,1,pull64_interleaved,5.090459,5.077667,4.310625,98240,32,4,0,0.127834,2,pass,5.090459;5.011958 +hub,1024,3070,1,pull32_interleaved,4.329166,4.318959,3.718042,98240,32,4,0,0.127834,2,pass,4.329166;4.298375 +hub,1024,3070,1,pull32_gpu_dag,5.058875,4.330667,4.105667,98240,32,6,0,0.127834,2,pass,5.006209;5.058875 +hub,1024,3070,1,frontier32_vertex,1.372833,1.364084,0.840958,3128,32,4,0,0.127834,2,pass,1.372833;1.322834 +hub,1024,3070,1,frontier32_simd,0.758292,0.751125,0.233125,3128,32,4,0,0.127834,2,pass,0.752542;0.758292 +hub,1024,3070,1,frontier32_gpu_dag,1.443542,0.736125,0.653958,3128,32,6,0,0.127834,2,pass,1.382958;1.443542 +hub,1024,3070,1,bucket32_d4,0.879333,0.871000,0.348375,3100,32,4,0,0.127834,2,pass,0.879333;0.859334 +hub,1024,3070,1,bucket32_d16,0.852333,0.844083,0.342417,3124,32,4,0,0.127834,2,pass,0.843708;0.852333 +hub,1024,3070,1,bucket32_d64,1.001750,0.993250,0.334375,3128,32,4,0,0.127834,2,pass,1.001750;0.857750 +random_masked_int64_reverse,1024,8192,8,old_pull_serial,0.521375,0.157541,0.032000,524288,8,1,0,0.210333,2,pass,0.521375;0.520625 +random_masked_int64_reverse,1024,8192,8,old_group_serial,0.538292,0.183375,0.053583,368640,8,1,0,0.210333,2,pass,0.538292;0.518041 +random_masked_int64_reverse,1024,8192,8,old_pull_parallel_dag,0.232041,0.168375,0.031917,524288,8,1,0,0.210333,2,pass,0.232041;0.227625 +random_masked_int64_reverse,1024,8192,8,old_group_parallel_dag,0.282750,0.205292,0.053625,368640,8,1,0,0.210333,2,pass,0.257500;0.282750 +random_masked_int64_reverse,1024,8192,8,pull64_barrier,0.223709,0.158792,0.028750,524288,8,1,0,0.210333,2,pass,0.223709;0.214000 +random_masked_int64_reverse,1024,8192,8,pull64_interleaved,0.810750,0.752583,0.028875,524288,8,1,0,0.210333,2,pass,0.569833;0.810750 +random_masked_int64_reverse,1024,8192,8,pull32_interleaved,0.775500,0.697875,0.028875,524288,8,1,1,0.210333,2,pass,0.721208;0.775500 +random_masked_int64_reverse,1024,8192,8,pull32_gpu_dag,1.021792,0.675417,0.051667,524288,8,3,1,0.210333,2,pass,0.982083;1.021792 +random_masked_int64_reverse,1024,8192,8,frontier32_vertex,0.277333,0.223500,0.029000,524288,8,1,1,0.210333,2,pass,0.241625;0.277333 +random_masked_int64_reverse,1024,8192,8,frontier32_simd,0.243875,0.179000,0.028583,524288,8,1,1,0.210333,2,pass,0.243875;0.237500 +random_masked_int64_reverse,1024,8192,8,frontier32_gpu_dag,0.500167,0.189583,0.047458,524288,8,3,1,0.210333,2,pass,0.500167;0.488708 +random_masked_int64_reverse,1024,8192,8,bucket32_d4,0.236375,0.177042,0.028750,524288,8,1,1,0.210333,2,pass,0.228500;0.236375 +random_masked_int64_reverse,1024,8192,8,bucket32_d16,0.249125,0.192084,0.028625,524288,8,1,1,0.210333,2,pass,0.218500;0.249125 +random_masked_int64_reverse,1024,8192,8,bucket32_d64,0.335542,0.296125,0.028625,524288,8,1,1,0.210333,2,pass,0.240375;0.335542 +random,4096,32768,256,old_pull_serial,49.337625,12.467292,11.699833,201326592,24,3,0,0.540875,2,pass,48.524667;49.337625 +random,4096,32768,256,old_group_serial,49.802834,11.785459,10.993500,136544256,20,1,0,0.540875,2,pass,47.385167;49.802834 +random,4096,32768,256,old_pull_parallel_dag,19.919000,16.053916,14.734958,201326592,24,3,0,0.540875,2,pass,19.919000;15.861667 +random,4096,32768,256,old_group_parallel_dag,11.645708,7.757000,6.930917,136544256,20,1,0,0.540875,2,pass,11.483584;11.645708 +random,4096,32768,256,pull64_barrier,13.484083,9.335333,8.520750,201326592,24,3,0,0.540875,2,pass,13.484083;12.949500 +random,4096,32768,256,pull64_interleaved,90.054167,86.195000,8.617750,201326592,24,3,0,0.540875,2,pass,90.054167;86.703666 +random,4096,32768,256,pull32_interleaved,79.266000,75.508625,6.636458,201326592,24,3,0,0.540875,2,pass,78.284917;79.266000 +random,4096,32768,256,pull32_gpu_dag,98.656083,96.740417,7.475250,201326592,24,5,0,0.540875,2,pass,80.137083;98.656083 +random,4096,32768,256,frontier32_vertex,79.679042,75.814167,9.683000,19773312,24,3,0,0.540875,2,pass,79.679042;79.543375 +random,4096,32768,256,frontier32_simd,85.882083,82.195666,16.025708,20638048,24,3,0,0.540875,2,pass,85.882083;85.238500 +random,4096,32768,256,frontier32_gpu_dag,83.435958,80.312834,15.618542,20760840,24,5,0,0.540875,2,pass,79.330083;83.435958 +random,4096,32768,256,bucket32_d4,85.800500,82.027500,15.248208,8454032,72,9,0,0.540875,2,pass,85.800500;84.087875 +random,4096,32768,256,bucket32_d16,85.003125,81.021958,9.436334,9715464,48,6,0,0.540875,2,pass,79.442625;85.003125 +random,4096,32768,256,bucket32_d64,88.076375,84.327833,16.212208,18335896,24,3,0,0.540875,2,pass,88.076375;87.845292 +random,16384,131072,1,old_pull_serial,2.306125,1.628750,0.257125,3145728,24,3,0,1.669042,2,pass,2.306125;1.344208 +random,16384,131072,1,old_group_serial,6.196458,5.531125,5.320500,2359296,18,1,0,1.669042,2,pass,6.196458;5.822917 +random,16384,131072,1,old_pull_parallel_dag,0.998041,0.646917,0.200666,3145728,24,3,0,1.669042,2,pass,0.998041;0.985250 +random,16384,131072,1,old_group_parallel_dag,5.391875,5.119750,4.971208,2359296,18,1,0,1.669042,2,pass,5.391875;5.363250 +random,16384,131072,1,pull64_barrier,0.916583,0.623416,0.172917,3145728,24,3,0,1.669042,2,pass,0.916583;0.894583 +random,16384,131072,1,pull64_interleaved,0.941750,0.720250,0.172625,3145728,24,3,0,1.669042,2,pass,0.928459;0.941750 +random,16384,131072,1,pull32_interleaved,0.899875,0.689083,0.147708,3145728,24,3,0,1.669042,2,pass,0.899875;0.875000 +random,16384,131072,1,pull32_gpu_dag,1.075709,0.687333,0.166417,3145728,24,5,0,1.669042,2,pass,1.075709;1.058916 +random,16384,131072,1,frontier32_vertex,1.222458,0.879917,0.244208,377896,24,3,0,1.669042,2,pass,1.222458;1.058459 +random,16384,131072,1,frontier32_simd,1.140625,0.808417,0.237042,336576,24,3,0,1.669042,2,pass,1.036834;1.140625 +random,16384,131072,1,frontier32_gpu_dag,1.208625,0.863958,0.431667,336096,24,5,0,1.669042,2,pass,1.208625;1.090583 +random,16384,131072,1,bucket32_d4,1.975208,1.713916,0.650959,132024,56,7,0,1.669042,2,pass,1.928042;1.975208 +random,16384,131072,1,bucket32_d16,1.444792,1.120375,0.390458,148264,32,4,0,1.669042,2,pass,1.444792;1.338417 +random,16384,131072,1,bucket32_d64,1.217834,0.885958,0.336333,269064,24,3,0,1.669042,2,pass,1.217834;1.050000 +random,16384,131072,64,old_pull_serial,57.334750,14.082292,12.348333,201326592,24,3,0,1.645250,2,pass,57.334750;56.155875 +random,16384,131072,64,old_group_serial,53.978958,11.020083,10.026500,158203904,22,1,0,1.645250,2,pass,53.571042;53.978958 +random,16384,131072,64,old_pull_parallel_dag,16.908459,12.904958,11.456708,201326592,24,3,0,1.645250,2,pass,16.908459;16.703541 +random,16384,131072,64,old_group_parallel_dag,13.650125,9.371084,8.515875,158203904,22,1,0,1.645250,2,pass,13.650125;13.255167 +random,16384,131072,64,pull64_barrier,16.434583,11.461166,10.202375,201326592,24,3,0,1.645250,2,pass,16.434583;15.835125 +random,16384,131072,64,pull64_interleaved,77.366916,73.168167,2.877792,201326592,24,3,0,1.645250,2,pass,75.897916;77.366916 +random,16384,131072,64,pull32_interleaved,83.784041,79.621792,6.788625,201326592,24,3,0,1.645250,2,pass,83.784041;78.639667 +random,16384,131072,64,pull32_gpu_dag,75.935959,73.474041,7.671417,201326592,24,5,0,1.645250,2,pass,75.935959;75.331334 +random,16384,131072,64,frontier32_vertex,93.834292,88.800917,11.524583,21236872,24,3,0,1.645250,2,pass,80.318042;93.834292 +random,16384,131072,64,frontier32_simd,79.992292,75.712584,9.913500,21938424,24,3,0,1.645250,2,pass,79.992292;79.583166 +random,16384,131072,64,frontier32_gpu_dag,87.396667,84.738792,19.360333,21869744,24,5,0,1.645250,2,pass,79.213125;87.396667 +random,16384,131072,64,bucket32_d4,88.988834,84.024250,13.670625,8451432,72,9,0,1.645250,2,pass,88.988834;88.343833 +random,16384,131072,64,bucket32_d16,91.121792,86.761000,16.956541,9562072,48,6,0,1.645250,2,pass,91.121792;87.719000 +random,16384,131072,64,bucket32_d64,87.983750,83.874083,12.879167,17319032,24,3,0,1.645250,2,pass,87.983750;84.451458 +random,65536,524288,1,old_pull_serial,5.670625,2.852084,1.649333,12582912,24,3,0,7.477583,2,pass,5.572667;5.670625 +random,65536,524288,1,old_group_serial,31.835417,29.109750,28.416708,11534336,22,1,0,7.477583,2,pass,31.347666;31.835417 +random,65536,524288,1,old_pull_parallel_dag,3.276042,1.796917,0.846167,12582912,24,3,0,7.477583,2,pass,3.224125;3.276042 +random,65536,524288,1,old_group_parallel_dag,30.395334,28.999000,28.296250,11534336,22,1,0,7.477583,2,pass,30.395334;29.813041 +random,65536,524288,1,pull64_barrier,3.316500,1.854167,0.802250,12582912,24,3,0,7.477583,2,pass,3.150584;3.316500 +random,65536,524288,1,pull64_interleaved,3.792375,2.321250,0.784542,12582912,24,3,0,7.477583,2,pass,3.740834;3.792375 +random,65536,524288,1,pull32_interleaved,3.664250,2.216250,0.642667,12582912,24,3,0,7.477583,2,pass,3.664250;3.619208 +random,65536,524288,1,pull32_gpu_dag,1.946833,1.440542,0.574292,12582912,24,5,0,7.477583,2,pass,1.807458;1.946833 +random,65536,524288,1,frontier32_vertex,3.540500,2.012917,0.603250,1743784,24,3,0,7.477583,2,pass,3.064458;3.540500 +random,65536,524288,1,frontier32_simd,3.527958,2.002208,0.598125,1562256,24,3,0,7.477583,2,pass,3.527958;3.485750 +random,65536,524288,1,frontier32_gpu_dag,2.079917,1.688458,0.682125,1566928,24,5,0,7.477583,2,pass,2.079917;2.025916 +random,65536,524288,1,bucket32_d4,4.803667,3.281125,1.170083,528256,64,8,0,7.477583,2,pass,4.803667;4.388583 +random,65536,524288,1,bucket32_d16,3.979417,2.442791,0.794417,599384,40,5,0,7.477583,2,pass,3.611333;3.979417 +random,65536,524288,1,bucket32_d64,3.852667,2.205292,0.729333,1050680,24,3,0,7.477583,2,pass,3.614333;3.852667 +clos,800,320000,1,old_pull_serial,2.370625,1.339417,0.724000,2560000,8,1,0,3.496583,2,pass,2.324166;2.370625 +clos,800,320000,1,old_group_serial,2.508750,1.566834,0.924167,960000,3,1,0,3.496583,2,pass,2.038208;2.508750 +clos,800,320000,1,old_pull_parallel_dag,2.127417,1.358375,0.732417,2560000,8,1,0,3.496583,2,pass,2.127417;2.063958 +clos,800,320000,1,old_group_parallel_dag,2.450875,1.688250,1.007875,960000,3,1,0,3.496583,2,pass,2.450875;2.436166 +clos,800,320000,1,pull64_barrier,2.201333,1.408125,0.657125,2560000,8,1,0,3.496583,2,pass,2.201333;1.657750 +clos,800,320000,1,pull64_interleaved,2.063084,1.323375,0.640458,2560000,8,1,0,3.496583,2,pass,2.063084;2.047459 +clos,800,320000,1,pull32_interleaved,1.952042,1.171375,0.556000,2560000,8,1,0,3.496583,2,pass,1.952042;1.436667 +clos,800,320000,1,pull32_gpu_dag,2.170625,1.323375,1.010542,2560000,8,3,0,3.496583,2,pass,2.143209;2.170625 +clos,800,320000,1,frontier32_vertex,2.447125,1.644417,0.968083,320000,8,1,0,3.496583,2,pass,2.447125;2.101167 +clos,800,320000,1,frontier32_simd,1.531125,0.705500,0.095500,320000,8,1,0,3.496583,2,pass,1.531125;1.476083 +clos,800,320000,1,frontier32_gpu_dag,1.652708,0.837417,0.614917,320000,8,3,0,3.496583,2,pass,1.652708;1.008292 +clos,800,320000,1,bucket32_d4,1.741958,0.940916,0.191500,320000,8,1,0,3.496583,2,pass,1.622708;1.741958 +clos,800,320000,1,bucket32_d16,1.637250,0.860458,0.177750,320000,8,1,0,3.496583,2,pass,1.618125;1.637250 +clos,800,320000,1,bucket32_d64,1.648416,0.862959,0.200083,320000,8,1,0,3.496583,2,pass,1.648416;1.564459 +clos,800,320000,64,old_pull_serial,84.010917,20.151750,19.591375,163840000,8,1,0,3.460875,2,pass,79.696125;84.010917 +clos,800,320000,64,old_group_serial,70.853292,5.869375,5.387125,61440000,3,1,0,3.460875,2,pass,70.853292;69.814500 +clos,800,320000,64,old_pull_parallel_dag,25.874292,18.861542,18.216250,163840000,8,1,0,3.460875,2,pass,25.874292;23.185041 +clos,800,320000,64,old_group_parallel_dag,12.892292,5.977542,5.445750,61440000,3,1,0,3.460875,2,pass,12.794500;12.892292 +clos,800,320000,64,pull64_barrier,28.435834,21.288833,20.666500,163840000,8,1,0,3.460875,2,pass,23.741583;28.435834 +clos,800,320000,64,pull64_interleaved,17.237125,10.007500,6.063250,163840000,8,1,0,3.460875,2,pass,17.237125;17.069959 +clos,800,320000,64,pull32_interleaved,15.469333,8.212958,3.644584,163840000,8,1,0,3.460875,2,pass,14.657250;15.469333 +clos,800,320000,64,pull32_gpu_dag,12.177917,8.063667,6.185208,163840000,8,3,0,3.460875,2,pass,11.646000;12.177917 +clos,800,320000,64,frontier32_vertex,17.391792,10.431791,6.175083,20480000,8,1,0,3.460875,2,pass,17.200042;17.391792 +clos,800,320000,64,frontier32_simd,13.298500,6.201125,1.491583,20480000,8,1,0,3.460875,2,pass,11.929792;13.298500 +clos,800,320000,64,frontier32_gpu_dag,11.460292,5.960000,5.538625,20480000,8,3,0,3.460875,2,pass,10.272375;11.460292 +clos,800,320000,64,bucket32_d4,13.275834,6.647167,1.969875,20480000,8,1,0,3.460875,2,pass,13.145500;13.275834 +clos,800,320000,64,bucket32_d16,13.277042,5.984208,1.809625,20480000,8,1,0,3.460875,2,pass,13.277042;12.978417 +clos,800,320000,64,bucket32_d64,12.781000,5.587375,1.800917,20480000,8,1,0,3.460875,2,pass,12.781000;11.775459 +grid,10000,39600,1,old_pull_serial,6.308667,6.189375,2.474124,7920000,200,25,0,0.484791,2,pass,6.174667;6.308667 +grid,10000,39600,1,old_group_serial,7.964459,7.841209,7.579834,7880400,199,1,0,0.484791,2,pass,7.915500;7.964459 +grid,10000,39600,1,old_pull_parallel_dag,4.204917,4.140000,0.606917,7920000,200,25,0,0.484791,2,pass,4.204917;4.148666 +grid,10000,39600,1,old_group_parallel_dag,7.780208,7.685250,7.526250,7880400,199,1,0,0.484791,2,pass,7.773042;7.780208 +grid,10000,39600,1,pull64_barrier,3.893333,3.823000,0.630791,7920000,200,25,0,0.484791,2,pass,3.893333;3.591125 +grid,10000,39600,1,pull64_interleaved,4.129958,4.070667,0.852458,7920000,200,25,0,0.484791,2,pass,4.129958;4.114666 +grid,10000,39600,1,pull32_interleaved,4.162917,4.100792,0.642917,7920000,200,25,0,0.484791,2,pass,3.970334;4.162917 +grid,10000,39600,1,pull32_gpu_dag,4.198666,3.912834,0.646082,7920000,200,27,0,0.484791,2,pass,4.198666;3.817750 +grid,10000,39600,1,frontier32_vertex,5.159500,5.099500,1.914417,39600,200,25,0,0.484791,2,pass,5.159500;5.099333 +grid,10000,39600,1,frontier32_simd,4.911583,4.852292,1.346042,39600,200,25,0,0.484791,2,pass,4.688917;4.911583 +grid,10000,39600,1,frontier32_gpu_dag,5.137208,4.800875,1.375291,39600,200,27,0,0.484791,2,pass,5.102334;5.137208 +grid,10000,39600,1,bucket32_d4,6.035708,5.976458,2.449416,39600,200,25,0,0.484791,2,pass,6.035708;5.789417 +grid,10000,39600,1,bucket32_d16,5.723333,5.664083,2.392000,39600,200,25,0,0.484791,2,pass,5.497666;5.723333 +grid,10000,39600,1,bucket32_d64,6.215667,6.141917,2.437126,39600,200,25,0,0.484791,2,pass,5.774834;6.215667 +grid,10000,39600,8,old_pull_serial,6.342000,5.328667,1.417540,63360000,200,25,0,0.487626,2,pass,6.342000;6.058000 +grid,10000,39600,8,old_group_serial,9.010166,8.094333,7.525375,51480000,199,1,0,0.487626,2,pass,8.645000;9.010166 +grid,10000,39600,8,old_pull_parallel_dag,5.092541,4.901084,1.396958,63360000,200,25,0,0.487626,2,pass,5.022958;5.092541 +grid,10000,39600,8,old_group_parallel_dag,7.914250,7.706834,7.497542,51480000,199,1,0,0.487626,2,pass,7.893583;7.914250 +grid,10000,39600,8,pull64_barrier,5.068458,4.899667,1.411666,63360000,200,25,0,0.487626,2,pass,4.946417;5.068458 +grid,10000,39600,8,pull64_interleaved,10.357083,10.106334,1.521750,63360000,200,25,0,0.487626,2,pass,10.357083;10.304375 +grid,10000,39600,8,pull32_interleaved,11.089083,10.845167,1.357125,63360000,200,25,0,0.487626,2,pass,11.089083;10.573500 +grid,10000,39600,8,pull32_gpu_dag,10.887416,10.004708,1.333043,63360000,200,27,0,0.487626,2,pass,9.630375;10.887416 +grid,10000,39600,8,frontier32_vertex,10.730792,10.477209,1.984625,316800,200,25,0,0.487626,2,pass,10.730792;10.719541 +grid,10000,39600,8,frontier32_simd,10.836875,10.634917,1.851000,316800,200,25,0,0.487626,2,pass,10.836875;10.763708 +grid,10000,39600,8,frontier32_gpu_dag,10.641500,9.760208,1.575917,316800,200,27,0,0.487626,2,pass,10.641500;10.630333 +grid,10000,39600,8,bucket32_d4,13.203375,13.062583,3.960125,316800,200,25,0,0.487626,2,pass,13.203375;13.027500 +grid,10000,39600,8,bucket32_d16,12.623292,12.421500,3.885626,316800,200,25,0,0.487626,2,pass,12.198958;12.623292 +grid,10000,39600,8,bucket32_d64,13.461542,13.314167,3.911709,316800,200,25,0,0.487626,2,pass,13.461542;13.151334 +chain,2048,2047,1,old_pull_serial,31.251584,31.241000,4.493376,4192256,2048,256,0,0.124208,2,pass,29.572958;31.251584 +chain,2048,2047,1,old_group_serial,4.872125,4.846917,4.704000,4192256,2048,1,0,0.124208,2,pass,4.872125;4.816000 +chain,2048,2047,1,old_pull_parallel_dag,30.364166,30.357500,4.342086,4192256,2048,256,0,0.124208,2,pass,30.364166;29.797667 +chain,2048,2047,1,old_group_parallel_dag,4.862500,4.841709,4.696458,4192256,2048,1,0,0.124208,2,pass,4.821792;4.862500 +chain,2048,2047,1,pull64_barrier,31.394625,31.387958,5.149665,4192256,2048,256,0,0.124208,2,pass,31.394625;30.564667 +chain,2048,2047,1,pull64_interleaved,30.923291,30.917667,5.045705,4192256,2048,256,0,0.124208,2,pass,30.342292;30.923291 +chain,2048,2047,1,pull32_interleaved,30.950333,30.944750,5.049085,4192256,2048,256,0,0.124208,2,pass,30.950333;29.343292 +chain,2048,2047,1,pull32_gpu_dag,29.144625,28.787459,4.978918,4192256,2048,258,0,0.124208,2,pass,28.863709;29.144625 +chain,2048,2047,1,frontier32_vertex,54.826625,54.820042,27.490289,2047,2048,256,0,0.124208,2,pass,54.826625;43.290458 +chain,2048,2047,1,frontier32_simd,40.021500,40.015625,13.131166,2047,2048,256,0,0.124208,2,pass,40.021500;38.506333 +chain,2048,2047,1,frontier32_gpu_dag,39.300791,38.996459,12.897914,2047,2048,258,0,0.124208,2,pass,39.067750;39.300791 +chain,2048,2047,1,bucket32_d4,49.432875,49.426375,21.049543,2047,2056,257,0,0.124208,2,pass,47.271833;49.432875 +chain,2048,2047,1,bucket32_d16,109.948875,109.939375,79.102456,2047,2056,257,0,0.124208,2,pass,88.977000;109.948875 +chain,2048,2047,1,bucket32_d64,48.930458,48.922542,21.087253,2047,2056,257,0,0.124208,2,pass,48.352792;48.930458 +hub,4096,12286,64,old_pull_serial,35.106833,32.332625,30.932625,31452160,40,5,0,0.332584,2,pass,34.652083;35.106833 +hub,4096,12286,64,old_group_serial,28.499792,25.765708,25.115500,27176632,38,1,0,0.332584,2,pass,28.499792;28.071959 +hub,4096,12286,64,old_pull_parallel_dag,33.417042,32.452917,30.979041,31452160,40,5,0,0.332584,2,pass,33.417042;32.831750 +hub,4096,12286,64,old_group_parallel_dag,26.387625,26.007666,25.172542,27176632,38,1,0,0.332584,2,pass,26.018208;26.387625 +hub,4096,12286,64,pull64_barrier,25.788459,25.342083,23.820209,31452160,40,5,0,0.332584,2,pass,25.166291;25.788459 +hub,4096,12286,64,pull64_interleaved,49.636291,49.303542,31.618167,31452160,40,5,0,0.332584,2,pass,49.126041;49.636291 +hub,4096,12286,64,pull32_interleaved,45.148542,44.768041,27.223375,31452160,40,5,0,0.332584,2,pass,44.485166;45.148542 +hub,4096,12286,64,pull32_gpu_dag,47.747125,44.786709,29.190750,31452160,40,7,0,0.332584,2,pass,47.409125;47.747125 +hub,4096,12286,64,frontier32_vertex,36.510167,36.094917,18.531458,1872372,40,5,0,0.332584,2,pass,35.063875;36.510167 +hub,4096,12286,64,frontier32_simd,22.199209,21.820333,1.906625,1683322,40,5,0,0.332584,2,pass,22.199209;22.001000 +hub,4096,12286,64,frontier32_gpu_dag,25.051625,21.600917,4.480042,1683264,40,7,0,0.332584,2,pass,25.051625;24.298250 +hub,4096,12286,64,bucket32_d4,25.343542,24.950084,2.969750,788342,48,6,0,0.332584,2,pass,23.476292;25.343542 +hub,4096,12286,64,bucket32_d16,26.631250,26.198042,3.176833,1124810,48,6,0,0.332584,2,pass,26.631250;23.371583 +hub,4096,12286,64,bucket32_d64,25.833834,25.465917,5.076166,1913530,40,5,0,0.332584,2,pass,24.307000;25.833834 +random,4096,131072,1,old_pull_serial,1.648541,1.149500,0.571458,2097152,16,2,0,1.680791,2,pass,1.648541;1.249209 +random,4096,131072,1,old_group_serial,6.351458,5.917417,5.756042,1572864,12,1,0,1.680791,2,pass,6.351458;6.022333 +random,4096,131072,1,old_pull_parallel_dag,0.933000,0.714709,0.452875,2097152,16,2,0,1.680791,2,pass,0.933000;0.886000 +random,4096,131072,1,old_group_parallel_dag,4.209167,4.007625,3.836334,1572864,12,1,0,1.680791,2,pass,4.209167;3.968750 +random,4096,131072,1,pull64_barrier,0.788792,0.602917,0.327542,2097152,16,2,0,1.680791,2,pass,0.788792;0.780500 +random,4096,131072,1,pull64_interleaved,0.789375,0.596625,0.286000,2097152,16,2,0,1.680791,2,pass,0.789375;0.764042 +random,4096,131072,1,pull32_interleaved,0.754708,0.581125,0.278500,2097152,16,2,0,1.680791,2,pass,0.754708;0.704625 +random,4096,131072,1,pull32_gpu_dag,0.969125,0.573500,0.317292,2097152,16,4,0,1.680791,2,pass,0.969125;0.835333 +random,4096,131072,1,frontier32_vertex,0.959750,0.784708,0.448417,421824,16,2,0,1.680791,2,pass,0.959750;0.883166 +random,4096,131072,1,frontier32_simd,0.613042,0.433500,0.165208,388160,16,2,0,1.680791,2,pass,0.602375;0.613042 +random,4096,131072,1,frontier32_gpu_dag,0.792875,0.454500,0.215166,392576,16,4,0,1.680791,2,pass,0.792875;0.771708 +random,4096,131072,1,bucket32_d4,0.948833,0.779541,0.322375,138784,24,3,0,1.680791,2,pass,0.907583;0.948833 +random,4096,131072,1,bucket32_d16,0.668875,0.487292,0.205875,177152,16,2,0,1.680791,2,pass,0.668875;0.664958 +random,4096,131072,1,bucket32_d64,0.704125,0.522375,0.236958,387040,16,2,0,1.680791,2,pass,0.704125;0.692375 +random,4096,131072,64,old_pull_serial,39.707625,10.664917,9.875917,134217728,16,2,0,1.785041,2,pass,39.707625;38.615750 +random,4096,131072,64,old_group_serial,34.620125,5.432459,4.809875,105644032,15,1,0,1.785041,2,pass,33.889416;34.620125 +random,4096,131072,64,old_pull_parallel_dag,13.925708,11.805375,11.350958,134217728,16,2,0,1.785041,2,pass,13.718500;13.925708 +random,4096,131072,64,old_group_parallel_dag,6.589500,4.478333,3.871625,105644032,15,1,0,1.785041,2,pass,6.210000;6.589500 +random,4096,131072,64,pull64_barrier,11.746500,9.527458,8.613667,134217728,16,2,0,1.785041,2,pass,11.549875;11.746500 +random,4096,131072,64,pull64_interleaved,23.944917,21.617000,1.407083,134217728,16,2,0,1.785041,2,pass,23.944917;23.816000 +random,4096,131072,64,pull32_interleaved,24.723167,22.521417,2.845166,134217728,16,2,0,1.785041,2,pass,23.098042;24.723167 +random,4096,131072,64,pull32_gpu_dag,23.908541,22.219333,3.848333,134217728,16,4,0,1.785041,2,pass,23.908541;23.375417 +random,4096,131072,64,frontier32_vertex,27.957250,25.638000,4.482417,22831904,16,2,0,1.785041,2,pass,25.895125;27.957250 +random,4096,131072,64,frontier32_simd,30.802708,28.372875,8.748375,23054048,16,2,0,1.785041,2,pass,30.802708;30.681708 +random,4096,131072,64,frontier32_gpu_dag,30.596834,28.276833,5.482458,22947328,16,4,0,1.785041,2,pass,26.060875;30.596834 +random,4096,131072,64,bucket32_d4,28.980292,26.791458,7.614083,8805280,24,3,0,1.785041,2,pass,27.958958;28.980292 +random,4096,131072,64,bucket32_d16,25.097334,22.833958,2.722333,12090432,24,3,0,1.785041,2,pass,24.775834;25.097334 +random,4096,131072,64,bucket32_d64,29.428333,27.258291,7.370167,23020448,16,2,0,1.785041,2,pass,25.965250;29.428333 diff --git a/dev/research/metal_pathfinding/optimization/results/smoke-stderr.txt b/dev/research/metal_pathfinding/optimization/results/smoke-stderr.txt new file mode 100644 index 0000000..4b20dd4 --- /dev/null +++ b/dev/research/metal_pathfinding/optimization/results/smoke-stderr.txt @@ -0,0 +1 @@ +device=Apple M4 Max setup_ms=52.7973 execution_width=32 diff --git a/dev/research/metal_pathfinding/optimization/results/smoke.csv b/dev/research/metal_pathfinding/optimization/results/smoke.csv new file mode 100644 index 0000000..b8c1539 --- /dev/null +++ b/dev/research/metal_pathfinding/optimization/results/smoke.csv @@ -0,0 +1,85 @@ +case,n,e,queries,method,wall_ms,distance_ms,gpu_ms,edge_visits,rounds,waits,fallback64,upload_ms,samples,correct,wall_samples_ms +random,1024,8192,1,old_pull_serial,0.690458,0.660208,0.399041,131072,16,2,0,0.232500,2,pass,0.690458;0.689292 +random,1024,8192,1,old_group_serial,0.918750,0.867792,0.684042,106496,13,1,0,0.232500,2,pass,0.918750;0.902958 +random,1024,8192,1,old_pull_parallel_dag,0.673667,0.658667,0.400125,131072,16,2,0,0.232500,2,pass,0.639000;0.673667 +random,1024,8192,1,old_group_parallel_dag,1.662917,1.644542,1.504458,106496,13,1,0,0.232500,2,pass,0.902583;1.662917 +random,1024,8192,1,pull64_barrier,0.635417,0.619083,0.358833,131072,16,2,0,0.232500,2,pass,0.635417;0.632209 +random,1024,8192,1,pull64_interleaved,0.691458,0.679500,0.358958,131072,16,2,0,0.232500,2,pass,0.662083;0.691458 +random,1024,8192,1,pull32_interleaved,1.027750,1.003250,0.736542,131072,16,2,0,0.232500,2,pass,1.027750;0.623042 +random,1024,8192,1,pull32_gpu_dag,0.965041,0.565708,0.383500,131072,16,4,0,0.232500,2,pass,0.965041;0.958458 +random,1024,8192,1,frontier32_vertex,1.215292,1.191917,0.921042,21088,16,2,0,0.232500,2,pass,1.215292;0.914417 +random,1024,8192,1,frontier32_simd,0.681375,0.663166,0.368917,20584,16,2,0,0.232500,2,pass,0.664417;0.681375 +random,1024,8192,1,frontier32_gpu_dag,1.127209,0.667792,0.435167,20512,16,4,0,0.232500,2,pass,1.127209;1.085459 +random,1024,8192,1,bucket32_d4,1.810625,1.790333,1.195875,8232,32,4,0,0.232500,2,pass,1.810625;1.789042 +random,1024,8192,1,bucket32_d16,1.298167,1.276541,0.864125,9344,24,3,0,0.232500,2,pass,1.281583;1.298167 +random,1024,8192,1,bucket32_d64,1.120875,1.108042,0.831375,19360,16,2,0,0.232500,2,pass,0.931625;1.120875 +random,1024,8192,64,old_pull_serial,4.363541,2.058709,1.582042,12582912,24,3,0,0.201166,2,pass,4.193209;4.363541 +random,1024,8192,64,old_group_serial,3.589666,1.344042,0.896042,7217152,17,1,0,0.201166,2,pass,3.573459;3.589666 +random,1024,8192,64,old_pull_parallel_dag,2.498625,2.249166,1.710833,12582912,24,3,0,0.201166,2,pass,2.332167;2.498625 +random,1024,8192,64,old_group_parallel_dag,1.373667,1.088042,0.889625,7217152,17,1,0,0.201166,2,pass,1.303750;1.373667 +random,1024,8192,64,pull64_barrier,2.200500,1.807125,1.382208,12582912,24,3,0,0.201166,2,pass,2.078292;2.200500 +random,1024,8192,64,pull64_interleaved,7.077875,6.808541,0.838292,12582912,24,3,0,0.201166,2,pass,7.077875;6.882042 +random,1024,8192,64,pull32_interleaved,6.222875,5.941417,0.684333,12582912,24,3,0,0.201166,2,pass,6.222875;6.170417 +random,1024,8192,64,pull32_gpu_dag,6.617083,5.848167,0.776542,12582912,24,5,0,0.201166,2,pass,6.617083;6.270000 +random,1024,8192,64,frontier32_vertex,6.192417,5.928291,0.991125,1294232,16,2,0,0.201166,2,pass,6.192417;5.873375 +random,1024,8192,64,frontier32_simd,7.073209,6.830167,1.888250,1209320,16,2,0,0.201166,2,pass,7.073209;6.179000 +random,1024,8192,64,frontier32_gpu_dag,7.573000,6.650750,2.009833,1200408,24,5,0,0.201166,2,pass,7.079666;7.573000 +random,1024,8192,64,bucket32_d4,7.151083,6.905833,1.128250,528520,56,7,0,0.201166,2,pass,7.096250;7.151083 +random,1024,8192,64,bucket32_d16,8.154791,7.893041,2.916583,601624,32,4,0,0.201166,2,pass,6.179417;8.154791 +random,1024,8192,64,bucket32_d64,8.615208,8.365000,3.017708,1152992,24,3,0,0.201166,2,pass,8.615208;7.997125 +clos,200,20000,64,old_pull_serial,5.706792,1.619292,1.043833,10240000,8,1,0,0.331916,2,pass,5.189416;5.706792 +clos,200,20000,64,old_group_serial,4.762833,0.842625,0.300750,3840000,3,1,0,0.331916,2,pass,4.762833;4.495333 +clos,200,20000,64,old_pull_parallel_dag,2.005375,1.468625,0.997625,10240000,8,1,0,0.331916,2,pass,2.005375;1.994625 +clos,200,20000,64,old_group_parallel_dag,1.347666,0.814917,0.300333,3840000,3,1,0,0.331916,2,pass,1.347666;1.050958 +clos,200,20000,64,pull64_barrier,2.337291,1.777542,1.019500,10240000,8,1,0,0.331916,2,pass,1.953625;2.337291 +clos,200,20000,64,pull64_interleaved,3.083042,2.474250,0.781917,10240000,8,1,0,0.331916,2,pass,3.083042;2.732916 +clos,200,20000,64,pull32_interleaved,3.211083,2.578416,0.691917,10240000,8,1,0,0.331916,2,pass,3.045292;3.211083 +clos,200,20000,64,pull32_gpu_dag,3.605125,2.331708,1.013250,10240000,8,3,0,0.331916,2,pass,3.605125;3.307625 +clos,200,20000,64,frontier32_vertex,3.004000,2.469083,0.974750,1280000,8,1,0,0.331916,2,pass,3.001875;3.004000 +clos,200,20000,64,frontier32_simd,2.437875,1.916541,0.362875,1280000,8,1,0,0.331916,2,pass,2.306875;2.437875 +clos,200,20000,64,frontier32_gpu_dag,2.945625,1.741792,0.670125,1280000,8,3,0,0.331916,2,pass,2.945625;2.463542 +clos,200,20000,64,bucket32_d4,2.549875,1.939375,0.487125,1280000,8,1,0,0.331916,2,pass,2.549875;2.447583 +clos,200,20000,64,bucket32_d16,2.159458,1.592041,0.524500,1280000,8,1,0,0.331916,2,pass,2.159458;2.139791 +clos,200,20000,64,bucket32_d64,3.199500,2.611750,0.527125,1280000,8,1,0,0.331916,2,pass,3.199500;2.366292 +grid,1024,3968,1,old_pull_serial,2.712167,2.696750,0.686625,253952,64,8,0,0.145582,2,pass,1.828792;2.712167 +grid,1024,3968,1,old_group_serial,1.282709,1.231000,1.012083,249984,63,1,0,0.145582,2,pass,1.229667;1.282709 +grid,1024,3968,1,old_pull_parallel_dag,1.768000,1.760166,0.187833,253952,64,8,0,0.145582,2,pass,1.345583;1.768000 +grid,1024,3968,1,old_group_parallel_dag,0.379875,0.371959,0.246208,249984,63,1,0,0.145582,2,pass,0.375625;0.379875 +grid,1024,3968,1,pull64_barrier,1.375250,1.367250,0.203750,253952,64,8,0,0.145582,2,pass,1.375250;1.315375 +grid,1024,3968,1,pull64_interleaved,1.326333,1.318167,0.201750,253952,64,8,0,0.145582,2,pass,1.326333;1.325542 +grid,1024,3968,1,pull32_interleaved,1.246292,1.237417,0.182542,253952,64,8,0,0.145582,2,pass,1.236292;1.246292 +grid,1024,3968,1,pull32_gpu_dag,1.628458,1.292333,0.202959,253952,64,10,0,0.145582,2,pass,1.628458;1.429875 +grid,1024,3968,1,frontier32_vertex,1.779750,1.772042,0.598750,3968,64,8,0,0.145582,2,pass,1.779750;1.696375 +grid,1024,3968,1,frontier32_simd,1.476417,1.468625,0.426625,3968,64,8,0,0.145582,2,pass,1.450834;1.476417 +grid,1024,3968,1,frontier32_gpu_dag,1.915375,1.583917,0.483375,3968,64,10,0,0.145582,2,pass,1.723792;1.915375 +grid,1024,3968,1,bucket32_d4,1.720042,1.711833,0.662750,3968,64,8,0,0.145582,2,pass,1.720042;1.676791 +grid,1024,3968,1,bucket32_d16,1.843500,1.835583,0.718250,3968,64,8,0,0.145582,2,pass,1.821583;1.843500 +grid,1024,3968,1,bucket32_d64,1.747583,1.739750,0.714041,3968,64,8,0,0.145582,2,pass,1.747583;1.700250 +hub,1024,3070,1,old_pull_serial,6.406708,6.369959,5.576208,98240,32,4,0,0.121500,2,pass,6.406708;6.319083 +hub,1024,3070,1,old_group_serial,5.014500,4.975250,4.745417,95170,31,1,0,0.121500,2,pass,5.014500;4.864000 +hub,1024,3070,1,old_pull_parallel_dag,6.516958,6.485750,5.764334,98240,32,4,0,0.121500,2,pass,6.261500;6.516958 +hub,1024,3070,1,old_group_parallel_dag,4.937042,4.912500,4.720833,95170,31,1,0,0.121500,2,pass,4.937042;4.885708 +hub,1024,3070,1,pull64_barrier,5.041500,5.016791,4.333042,98240,32,4,0,0.121500,2,pass,5.041500;5.025125 +hub,1024,3070,1,pull64_interleaved,5.097541,5.075000,4.344125,98240,32,4,0,0.121500,2,pass,5.097541;5.007375 +hub,1024,3070,1,pull32_interleaved,4.423209,4.413792,3.648959,98240,32,4,0,0.121500,2,pass,4.343750;4.423209 +hub,1024,3070,1,pull32_gpu_dag,5.119000,4.303000,4.076750,98240,32,6,0,0.121500,2,pass,4.981959;5.119000 +hub,1024,3070,1,frontier32_vertex,1.454292,1.445750,0.863709,3128,32,4,0,0.121500,2,pass,1.454292;1.402708 +hub,1024,3070,1,frontier32_simd,0.815875,0.807209,0.231791,3128,32,4,0,0.121500,2,pass,0.704792;0.815875 +hub,1024,3070,1,frontier32_gpu_dag,1.425708,0.726500,0.648833,3128,32,6,0,0.121500,2,pass,1.425708;1.421167 +hub,1024,3070,1,bucket32_d4,0.915708,0.906917,0.349667,3100,32,4,0,0.121500,2,pass,0.915708;0.836708 +hub,1024,3070,1,bucket32_d16,0.854042,0.845583,0.341000,3124,32,4,0,0.121500,2,pass,0.854042;0.837125 +hub,1024,3070,1,bucket32_d64,0.919958,0.911708,0.330000,3128,32,4,0,0.121500,2,pass,0.833583;0.919958 +random_masked_int64_reverse,1024,8192,8,old_pull_serial,0.575416,0.149542,0.031709,524288,8,1,0,0.203249,2,pass,0.575416;0.490708 +random_masked_int64_reverse,1024,8192,8,old_group_serial,0.507083,0.169958,0.053625,368640,8,1,0,0.203249,2,pass,0.507083;0.506209 +random_masked_int64_reverse,1024,8192,8,old_pull_parallel_dag,0.247417,0.183833,0.031917,524288,8,1,0,0.203249,2,pass,0.218750;0.247417 +random_masked_int64_reverse,1024,8192,8,old_group_parallel_dag,0.238708,0.178333,0.053625,368640,8,1,0,0.203249,2,pass,0.238708;0.229958 +random_masked_int64_reverse,1024,8192,8,pull64_barrier,0.242750,0.191708,0.028667,524288,8,1,0,0.203249,2,pass,0.242750;0.241417 +random_masked_int64_reverse,1024,8192,8,pull64_interleaved,0.806791,0.743125,0.028792,524288,8,1,0,0.203249,2,pass,0.614583;0.806791 +random_masked_int64_reverse,1024,8192,8,pull32_interleaved,0.789459,0.709250,0.028875,524288,8,1,1,0.203249,2,pass,0.789459;0.766166 +random_masked_int64_reverse,1024,8192,8,pull32_gpu_dag,0.975416,0.636041,0.051958,524288,8,3,1,0.203249,2,pass,0.955750;0.975416 +random_masked_int64_reverse,1024,8192,8,frontier32_vertex,0.243542,0.194917,0.029083,524288,8,1,1,0.203249,2,pass,0.240709;0.243542 +random_masked_int64_reverse,1024,8192,8,frontier32_simd,0.286791,0.227750,0.028625,524288,8,1,1,0.203249,2,pass,0.286791;0.234208 +random_masked_int64_reverse,1024,8192,8,frontier32_gpu_dag,0.494750,0.178541,0.046917,524288,8,3,1,0.203249,2,pass,0.468250;0.494750 +random_masked_int64_reverse,1024,8192,8,bucket32_d4,0.255792,0.205375,0.028875,524288,8,1,1,0.203249,2,pass,0.232625;0.255792 +random_masked_int64_reverse,1024,8192,8,bucket32_d16,0.242333,0.199541,0.028667,524288,8,1,1,0.203249,2,pass,0.242333;0.225833 +random_masked_int64_reverse,1024,8192,8,bucket32_d64,0.244958,0.195000,0.028875,524288,8,1,1,0.203249,2,pass,0.231417;0.244958 diff --git a/dev/research/metal_pathfinding/optimization/results/stress-sanitized-stderr.txt b/dev/research/metal_pathfinding/optimization/results/stress-sanitized-stderr.txt new file mode 100644 index 0000000..ecd2dc4 --- /dev/null +++ b/dev/research/metal_pathfinding/optimization/results/stress-sanitized-stderr.txt @@ -0,0 +1,3 @@ +2026-09-27 00:31:10.901 optimized-sanitize[19987:38715567] Metal API Validation Enabled +2026-09-27 00:31:10.902 optimized-sanitize[19987:38715567] Metal GPU Validation Enabled +device=Apple M4 Max setup_ms=33.4889 execution_width=32 diff --git a/dev/research/metal_pathfinding/optimization/results/stress-sanitized.csv b/dev/research/metal_pathfinding/optimization/results/stress-sanitized.csv new file mode 100644 index 0000000..868411d --- /dev/null +++ b/dev/research/metal_pathfinding/optimization/results/stress-sanitized.csv @@ -0,0 +1,29 @@ +case,n,e,queries,method,wall_ms,distance_ms,gpu_ms,edge_visits,rounds,waits,fallback64,upload_ms,samples,correct,wall_samples_ms +grid,1024,3968,64,old_pull_serial,15.422459,8.780792,4.421000,16252928,64,8,0,0.355707,3,pass,15.767625;12.079667;15.422459 +grid,1024,3968,64,old_group_serial,11.820416,4.917041,3.918292,12066688,63,1,0,0.355707,3,pass,11.266000;11.991708;11.820416 +grid,1024,3968,64,old_pull_parallel_dag,9.401541,8.708916,4.336000,16252928,64,8,0,0.355707,3,pass,5.894791;10.034959;9.401541 +grid,1024,3968,64,old_group_parallel_dag,3.223291,2.277167,1.718958,12066688,63,1,0,0.355707,3,pass,3.223291;6.094583;2.753959 +grid,1024,3968,64,pull64_barrier,9.744500,8.889250,4.838625,16252928,64,8,0,0.355707,3,pass,5.471708;9.744500;9.802958 +grid,1024,3968,64,pull64_interleaved,8.179959,7.435500,3.227125,16252928,64,8,0,0.355707,3,pass,8.179959;9.998542;5.224125 +grid,1024,3968,64,pull32_interleaved,6.581875,4.865416,1.325542,16252928,64,8,0,0.355707,3,pass,5.519000;9.256834;6.581875 +grid,1024,3968,64,pull32_gpu_dag,9.064958,7.880250,4.344791,16252928,64,10,0,0.355707,3,pass,9.542542;5.143375;9.064958 +grid,1024,3968,64,frontier32_vertex,6.553083,5.827417,1.606209,253952,64,8,0,0.355707,3,pass,6.535333;10.212125;6.553083 +grid,1024,3968,64,frontier32_simd,6.107459,5.438333,1.547667,253952,64,8,0,0.355707,3,pass,6.107459;10.554250;5.719167 +grid,1024,3968,64,frontier32_gpu_dag,9.948333,8.881708,4.683959,253952,64,10,0,0.355707,3,pass,5.949833;9.948333;10.264292 +grid,1024,3968,64,bucket32_d4,8.262958,7.353792,2.220125,253952,64,8,0,0.355707,3,pass,11.154000;7.720708;8.262958 +grid,1024,3968,64,bucket32_d16,7.660833,6.970500,2.238875,253952,64,8,0,0.355707,3,pass,8.266375;7.639000;7.660833 +grid,1024,3968,64,bucket32_d64,8.043542,7.205500,2.246292,253952,64,8,0,0.355707,3,pass,8.043542;8.121875;7.920583 +random_masked_reverse,1024,8192,64,old_pull_serial,16.570084,4.646042,2.783208,12582912,24,3,0,0.572584,3,pass,15.608625;16.570084;17.459917 +random_masked_reverse,1024,8192,64,old_group_serial,14.205167,3.149333,2.211167,7053312,19,1,0,0.572584,3,pass,14.687458;14.092833;14.205167 +random_masked_reverse,1024,8192,64,old_pull_parallel_dag,5.958625,5.081458,2.891292,12582912,24,3,0,0.572584,3,pass,5.958625;6.342875;5.587250 +random_masked_reverse,1024,8192,64,old_group_parallel_dag,4.081958,3.046750,2.223625,7053312,19,1,0,0.572584,3,pass,4.123334;4.081958;2.387042 +random_masked_reverse,1024,8192,64,pull64_barrier,3.941667,2.651792,0.613292,12582912,24,3,0,0.572584,3,pass,6.387167;3.941667;3.833542 +random_masked_reverse,1024,8192,64,pull64_interleaved,5.110292,4.362833,2.690750,12582912,24,3,0,0.572584,3,pass,5.082667;5.948709;5.110292 +random_masked_reverse,1024,8192,64,pull32_interleaved,5.086125,4.363625,2.562375,12582912,24,3,0,0.572584,3,pass,5.091459;5.086125;4.956417 +random_masked_reverse,1024,8192,64,pull32_gpu_dag,5.437875,4.244875,3.199833,12582912,24,5,0,0.572584,3,pass,5.315333;5.962417;5.437875 +random_masked_reverse,1024,8192,64,frontier32_vertex,6.363458,5.504500,3.278917,1097250,24,3,0,0.572584,3,pass,6.792125;6.197834;6.363458 +random_masked_reverse,1024,8192,64,frontier32_simd,6.249791,5.481917,3.753459,1014107,24,3,0,0.572584,3,pass,6.805167;6.204208;6.249791 +random_masked_reverse,1024,8192,64,frontier32_gpu_dag,7.568583,5.928750,4.430708,1014586,24,5,0,0.572584,3,pass,6.909084;8.284792;7.568583 +random_masked_reverse,1024,8192,64,bucket32_d4,15.467792,14.422750,8.644958,454224,64,8,0,0.572584,3,pass,15.524417;14.906917;15.467792 +random_masked_reverse,1024,8192,64,bucket32_d16,10.664084,9.545125,5.615625,510827,40,5,0,0.572584,3,pass,10.664084;11.253959;10.204459 +random_masked_reverse,1024,8192,64,bucket32_d64,8.033667,6.966500,4.823583,910477,24,3,0,0.572584,3,pass,8.232083;8.024584;8.033667 diff --git a/dev/research/metal_pathfinding/optimization/results/stress-stderr.txt b/dev/research/metal_pathfinding/optimization/results/stress-stderr.txt new file mode 100644 index 0000000..3cd5381 --- /dev/null +++ b/dev/research/metal_pathfinding/optimization/results/stress-stderr.txt @@ -0,0 +1 @@ +device=Apple M4 Max setup_ms=25.9229 execution_width=32 diff --git a/dev/research/metal_pathfinding/optimization/results/stress.csv b/dev/research/metal_pathfinding/optimization/results/stress.csv new file mode 100644 index 0000000..8354fce --- /dev/null +++ b/dev/research/metal_pathfinding/optimization/results/stress.csv @@ -0,0 +1,29 @@ +case,n,e,queries,method,wall_ms,distance_ms,gpu_ms,edge_visits,rounds,waits,fallback64,upload_ms,samples,correct,wall_samples_ms +grid,1024,3968,64,old_pull_serial,4.089792,3.178458,1.539083,16252928,64,8,0,0.147000,20,pass,4.953459;4.561792;4.111417;3.969375;3.928708;4.098333;3.655541;4.089792;3.828166;4.460042;3.954084;3.793875;4.304750;4.094625;3.848875;3.618375;3.582916;4.091500;4.011042;4.603625 +grid,1024,3968,64,old_group_serial,2.049708,1.149625,0.723458,12066688,63,1,0,0.147000,20,pass,2.268917;2.055167;2.052042;2.374875;2.049708;2.363917;2.175417;2.370125;2.364458;2.134958;1.624000;2.040166;1.945542;1.940709;2.009708;1.442833;1.836541;1.865625;1.853000;1.448875 +grid,1024,3968,64,old_pull_parallel_dag,1.712792,1.547584,0.446167,16252928,64,8,0,0.147000,20,pass,1.840084;1.978375;1.690125;1.772375;1.885000;1.737750;1.577500;2.035459;1.716708;1.632125;1.987708;1.609333;1.494292;1.832333;1.700750;1.517792;1.659833;1.712792;1.610166;1.562125 +grid,1024,3968,64,old_group_parallel_dag,0.526708,0.374084,0.203625,12066688,63,1,0,0.147000,20,pass,0.530583;0.471917;0.559791;0.511625;0.482458;0.492542;0.479416;0.467708;0.482292;0.557958;0.506666;0.526708;0.461833;0.473834;0.789708;1.320042;1.248125;1.289875;1.233875;1.272292 +grid,1024,3968,64,pull64_barrier,1.628084,1.488833,0.407416,16252928,64,8,0,0.147000,20,pass,1.657917;1.549500;1.818042;1.596500;1.505667;1.643792;1.528208;1.576709;1.769042;1.764167;1.589500;1.591333;1.725667;1.624042;1.659500;1.628084;1.735958;1.571042;1.521709;1.657583 +grid,1024,3968,64,pull64_interleaved,1.632666,1.483417,0.382416,16252928,64,8,0,0.147000,20,pass,1.652083;1.606208;1.749042;1.648709;1.524667;1.578875;1.636000;1.632666;1.559583;1.668208;1.614084;1.573125;1.602250;1.683750;1.587083;1.657916;1.560500;1.488709;1.707916;1.844125 +grid,1024,3968,64,pull32_interleaved,1.582875,1.441625,0.362167,16252928,64,8,0,0.147000,20,pass,1.574292;1.582875;1.557667;1.794667;1.637125;1.539209;1.800500;1.498875;1.544625;1.634334;1.693666;1.379208;1.534833;1.592500;1.561708;1.472208;1.619458;1.573417;1.680500;1.666375 +grid,1024,3968,64,pull32_gpu_dag,1.834750,1.444292,0.387333,16252928,64,10,0,0.147000,20,pass,1.755042;1.845917;1.922625;1.923042;1.766792;1.818583;1.785292;1.853708;1.711834;2.019625;1.704416;1.824791;2.007458;1.839667;1.810709;1.881250;1.834750;1.772291;2.008792;1.815833 +grid,1024,3968,64,frontier32_vertex,1.841667,1.684000,0.571125,253952,64,8,0,0.147000,20,pass,1.899750;1.652584;1.945083;1.880250;1.692916;1.859542;1.871833;1.708083;1.917417;1.841667;1.914958;1.776750;1.699541;1.757333;1.975333;1.689292;1.753250;1.786292;1.894167;1.771041 +grid,1024,3968,64,frontier32_simd,1.809708,1.652416,0.558792,253952,64,8,0,0.147000,20,pass,1.804666;1.881291;1.820375;1.716083;2.049500;1.731542;1.742291;1.779792;1.809708;1.796458;1.887417;1.924208;1.640917;1.974542;1.877083;1.752584;1.892459;1.871708;1.649458;1.715084 +grid,1024,3968,64,frontier32_gpu_dag,1.883666,1.521208,0.550501,253952,64,10,0,0.147000,20,pass,1.853542;1.777416;1.955459;1.928625;1.870958;1.831166;1.801875;1.827708;1.883666;1.830833;1.827167;2.068084;1.886583;1.859041;1.891458;1.820416;1.944500;1.943500;1.907459;1.894792 +grid,1024,3968,64,bucket32_d4,2.419833,2.295292,1.195626,253952,64,8,0,0.147000,20,pass,2.394959;2.321208;2.272750;2.353125;2.377708;2.373667;2.402083;2.333958;2.419833;2.584083;2.565083;2.469291;2.569208;2.505083;2.290333;2.444084;2.406042;2.496458;2.426833;2.501042 +grid,1024,3968,64,bucket32_d16,2.418208,2.291250,1.193416,253952,64,8,0,0.147000,20,pass,2.527958;2.444500;2.298791;2.458541;2.418208;2.523250;2.407291;2.397042;2.581292;2.416000;2.600083;2.541709;2.422458;2.627208;2.386500;2.406708;2.318333;2.247709;2.413084;2.342416 +grid,1024,3968,64,bucket32_d64,6.132625,5.953208,4.671833,253952,64,8,0,0.147000,20,pass,2.698791;2.489500;2.409000;5.611875;6.176958;5.938083;6.222125;6.132625;6.057000;5.982167;6.731583;6.025333;5.934458;6.034459;6.339333;6.321000;7.091042;6.698084;7.285709;6.397250 +random_masked_reverse,1024,8192,64,old_pull_serial,5.141583,1.975875,1.167791,12582912,24,3,0,0.220624,20,pass,5.182417;4.845667;5.141583;5.061416;5.216667;5.116000;4.892583;5.019583;5.102292;5.079334;5.188291;5.694791;5.078084;5.269833;5.304208;4.971834;5.720209;5.066291;5.289042;5.186333 +random_masked_reverse,1024,8192,64,old_group_serial,4.292708,1.062416,0.590333,7053312,19,1,0,0.220624,20,pass,4.292708;3.832458;4.279750;4.245458;4.724750;5.119917;4.378208;4.438625;4.340041;4.412083;3.921083;4.287417;4.431000;4.262917;4.251250;4.246083;4.338083;3.993708;4.331333;4.264958 +random_masked_reverse,1024,8192,64,old_pull_parallel_dag,1.451333,1.212208,0.285250,12582912,24,3,0,0.220624,20,pass,1.908167;2.010541;2.503792;2.144875;1.389042;1.398459;1.607791;1.591958;1.266167;1.451333;1.415208;1.304375;1.118792;1.493541;0.874459;1.445292;1.447917;1.309208;1.493250;1.507125 +random_masked_reverse,1024,8192,64,old_group_parallel_dag,0.998083,0.775833,0.132333,7053312,19,1,0,0.220624,20,pass,0.979250;1.060583;0.551041;0.525416;0.971833;1.042917;0.529875;0.502917;0.998083;1.183958;0.959042;1.031166;1.199209;1.177500;0.983750;1.295125;1.232791;1.180709;0.984334;0.951708 +random_masked_reverse,1024,8192,64,pull64_barrier,1.291250,1.063333,0.206125,12582912,24,3,0,0.220624,20,pass,1.291250;1.395750;0.836208;1.290958;0.837125;1.189167;1.304625;1.352625;1.290166;1.416500;0.841333;0.867667;1.524709;1.542166;0.878209;0.886834;1.295416;0.852083;1.404292;1.415375 +random_masked_reverse,1024,8192,64,pull64_interleaved,1.374042,1.137334,0.190542,12582912,24,3,0,0.220624,20,pass,2.149167;1.813167;1.735083;1.695833;1.790167;1.884125;1.365292;1.297458;1.499500;1.288708;1.374042;0.861625;1.312417;0.889291;1.339084;1.458292;1.360417;1.260750;1.390708;0.919458 +random_masked_reverse,1024,8192,64,pull32_interleaved,1.282917,1.042333,0.159666,12582912,24,3,0,0.220624,20,pass,1.556209;1.153875;0.867083;1.373334;0.814375;1.282917;1.373042;1.280083;1.208750;1.409459;1.346167;1.277708;0.868333;1.497959;1.235084;1.431458;1.303000;0.885417;0.799916;1.435958 +random_masked_reverse,1024,8192,64,pull32_gpu_dag,1.035416,0.629125,0.190208,12582912,24,5,0,0.220624,20,pass,1.035416;1.046333;0.902708;0.911875;1.551500;1.599083;1.565958;1.568417;1.539000;1.734750;1.021750;0.998041;1.020667;0.967916;0.982083;0.976292;1.115375;0.888125;1.057042;0.971208 +random_masked_reverse,1024,8192,64,frontier32_vertex,1.570459,1.288500,0.412500,1072481,24,3,0,0.220624,20,pass,1.503792;1.633500;1.898250;1.644250;1.534917;1.365958;1.505667;1.105500;1.069958;1.658958;1.575375;1.457208;1.545750;1.205375;1.844875;1.639709;1.641959;1.533375;1.570459;1.642458 +random_masked_reverse,1024,8192,64,frontier32_simd,1.627334,1.355791,0.482417,997903,24,3,0,0.220624,20,pass,1.170250;1.702958;1.746458;1.552334;1.260917;1.627334;1.685833;1.570667;1.759292;1.580625;1.524500;1.693000;1.713500;1.553334;1.677291;1.241209;1.720833;1.476167;1.204750;1.671500 +random_masked_reverse,1024,8192,64,frontier32_gpu_dag,1.322917,0.915250,0.493250,999274,24,5,0,0.220624,20,pass,1.257667;1.398542;1.338167;1.158791;1.274125;1.322917;1.286250;1.569208;1.349292;1.142209;1.357542;1.414125;1.273791;1.240458;1.400250;1.258584;1.372958;1.232792;1.206208;1.336167 +random_masked_reverse,1024,8192,64,bucket32_d4,3.220708,2.936334,1.273167,454235,64,8,0,0.220624,20,pass,2.729834;3.051750;3.382959;3.244417;3.194125;3.178917;2.538958;3.416334;3.014291;3.245834;3.220708;3.263750;3.250875;3.423042;2.997125;3.231250;3.178459;2.711375;3.318209;3.145541 +random_masked_reverse,1024,8192,64,bucket32_d16,2.395875,2.110375,0.831208,509878,40,5,0,0.220624,20,pass,2.395875;2.372125;2.276792;2.404417;1.823500;2.501584;2.192125;2.579084;2.378500;2.543125;2.488792;2.434875;1.823542;2.254542;1.976667;2.757458;2.678667;2.147125;2.155334;2.437291 +random_masked_reverse,1024,8192,64,bucket32_d64,1.798709,1.538250,0.673417,904016,24,3,0,0.220624,20,pass,1.380583;1.801542;1.360542;1.311166;1.762375;1.827250;1.710291;2.149708;1.875625;1.807667;2.009209;1.820833;1.790875;1.500250;1.798709;1.776791;2.323041;1.768750;1.929041;1.412625 diff --git a/dev/research/metal_pathfinding/optimization/results/workspace-check-final.txt b/dev/research/metal_pathfinding/optimization/results/workspace-check-final.txt new file mode 100644 index 0000000..0e84856 --- /dev/null +++ b/dev/research/metal_pathfinding/optimization/results/workspace-check-final.txt @@ -0,0 +1,391 @@ +📦 Installing package (editable, default optimizations) +Obtaining file:///Users/networmix/ws/NetGraph-Core + Installing build dependencies: started + Installing build dependencies: finished with status 'done' + Checking if build backend supports build_editable: started + Checking if build backend supports build_editable: finished with status 'done' + Getting requirements to build editable: started + Getting requirements to build editable: finished with status 'done' + Installing backend dependencies: started + Installing backend dependencies: finished with status 'done' + Preparing editable metadata (pyproject.toml): started + Preparing editable metadata (pyproject.toml): finished with status 'done' +Requirement already satisfied: numpy>=1.23.2 in ./venv/lib/python3.14/site-packages (from netgraph-core==0.10.0) (2.5.2) +Building wheels for collected packages: netgraph-core + Building editable for netgraph-core (pyproject.toml): started + Building editable for netgraph-core (pyproject.toml): finished with status 'done' + Created wheel for netgraph-core: filename=netgraph_core-0.10.0-cp314-cp314-macosx_15_0_arm64.whl size=314893 sha256=d2510ae66a03f120aa34f71b3181e2c2bc61d37e63e6dee88b14292916e63b4e + Stored in directory: /private/var/folders/8q/438f_q5s0ys8nlnvjqkf953m0000gn/T/pip-ephem-wheel-cache-m73o7_bm/wheels/18/8c/1a/f701a43f4b69f7c794e11f1f5dd0c17e819d2c98bfd1285718 +Successfully built netgraph-core +Installing collected packages: netgraph-core + Attempting uninstall: netgraph-core + Found existing installation: netgraph-core 0.10.0 + Uninstalling netgraph-core-0.10.0: + Successfully uninstalled netgraph-core-0.10.0 +Successfully installed netgraph-core-0.10.0 +47 files already formatted +All checks passed! +0 errors, 0 warnings, 0 informations +WARNING: there is a new pyright version available (v1.1.401 -> v1.1.414). +Please install the new version or set PYRIGHT_PYTHON_FORCE_VERSION to `latest` + +-- pybind11 not found via config; using FetchContent +-- pybind11 v3.0.0 +-- LTO not supported: CMake doesn't support IPO for current C compiler +-- Configuring done (0.6s) +-- Generating done (0.0s) +-- Build files have been written to: /Users/networmix/ws/NetGraph-Core/build/cpp-tests +ninja: no work to do. +Test project /Users/networmix/ws/NetGraph-Core/build/cpp-tests + Start 141: KShortestPaths.DisconnectedReturnsEmpty + Start 132: MaxFlow.Sensitivity_ShortestPathVsMaxFlow + Start 34: StrictMultiDiGraph.NegativeNodeIdThrows + Start 11: FlowPolicyCore.EqualBalanced_ShortestPath_IgnoresHigherCostTier + 1/170 Test #141: KShortestPaths.DisconnectedReturnsEmpty ........................................... Passed 0.00 sec + Start 152: MaskingTests.MaskedIntermediateNode + 2/170 Test #132: MaxFlow.Sensitivity_ShortestPathVsMaxFlow ......................................... Passed 0.00 sec + 3/170 Test #34: StrictMultiDiGraph.NegativeNodeIdThrows ........................................... Passed 0.00 sec + 4/170 Test #11: FlowPolicyCore.EqualBalanced_ShortestPath_IgnoresHigherCostTier ................... Passed 0.00 sec + Start 9: FlowPolicyCore.EqualBalanced_ShortestPath_ECMP3_SaturatesAllEqualCostPaths + Start 10: FlowPolicyCore.EqualBalanced_ShortestPath_DownstreamSplit_BalancesBottleneck + Start 105: MaxFlow.AsymmetricCapacity_1to100_Proportional + 5/170 Test #152: MaskingTests.MaskedIntermediateNode ............................................... Passed 0.00 sec + Start 154: MaskingTests.MaskedEdgeSelectsAlternativePath + 6/170 Test #9: FlowPolicyCore.EqualBalanced_ShortestPath_ECMP3_SaturatesAllEqualCostPaths ........ Passed 0.00 sec + Start 156: MaskingTests.CombinedNodeAndEdgeMasks + 7/170 Test #10: FlowPolicyCore.EqualBalanced_ShortestPath_DownstreamSplit_BalancesBottleneck ...... Passed 0.00 sec + Start 144: KShortestPaths.LargerOutOfOrderTopology + 8/170 Test #105: MaxFlow.AsymmetricCapacity_1to100_Proportional .................................... Passed 0.00 sec + Start 43: ShortestPaths.PredDAGIntegrity + 9/170 Test #154: MaskingTests.MaskedEdgeSelectsAlternativePath ..................................... Passed 0.00 sec + Start 148: MaskingTests.MaskedSourceInMaxFlow + 10/170 Test #156: MaskingTests.CombinedNodeAndEdgeMasks ............................................. Passed 0.00 sec + Start 118: MaxFlow.OptionalOutputs_ResidualAndReachable + 11/170 Test #144: KShortestPaths.LargerOutOfOrderTopology ........................................... Passed 0.00 sec + Start 33: StrictMultiDiGraph.SelfLoopAllowed + 12/170 Test #43: ShortestPaths.PredDAGIntegrity .................................................... Passed 0.00 sec + Start 8: FlowPolicyCore.DiminishingReturnsCutoff + 13/170 Test #148: MaskingTests.MaskedSourceInMaxFlow ................................................ Passed 0.00 sec + Start 138: KShortestPaths.UniqueModeFiltering + 14/170 Test #118: MaxFlow.OptionalOutputs_ResidualAndReachable ...................................... Passed 0.00 sec + Start 92: FlowGraph.LedgerMicroFlows_RemovalRestoresResidual + 15/170 Test #33: StrictMultiDiGraph.SelfLoopAllowed ................................................ Passed 0.00 sec + Start 83: FlowGraph.EmptyLedgerInitially + 16/170 Test #8: FlowPolicyCore.DiminishingReturnsCutoff ........................................... Passed 0.00 sec + Start 47: ShortestPaths.ResolveToPathsWithMaxPathsLimit + 17/170 Test #138: KShortestPaths.UniqueModeFiltering ................................................ Passed 0.00 sec + Start 67: FlowState.InvalidResidualInitThrows + 18/170 Test #92: FlowGraph.LedgerMicroFlows_RemovalRestoresResidual ................................ Passed 0.00 sec + Start 106: MaxFlow.AsymmetricCapacity_1to1M_NumericalStability + 19/170 Test #83: FlowGraph.EmptyLedgerInitially .................................................... Passed 0.00 sec + Start 1: GraphSmoke.ConstructAndRunSPF + 20/170 Test #47: ShortestPaths.ResolveToPathsWithMaxPathsLimit ..................................... Passed 0.00 sec + Start 17: StrictMultiDiGraph.EmptyGraph + 21/170 Test #67: FlowState.InvalidResidualInitThrows ............................................... Passed 0.00 sec + Start 41: ShortestPaths.EdgeMaskFiltering + 22/170 Test #106: MaxFlow.AsymmetricCapacity_1to1M_NumericalStability ............................... Passed 0.00 sec + Start 89: FlowGraph.GetFlowPathForDAGReturnsEmpty + 23/170 Test #1: GraphSmoke.ConstructAndRunSPF ..................................................... Passed 0.00 sec + Start 104: MaxFlow.ECMP_TenPaths_ScalabilityValidation + 24/170 Test #17: StrictMultiDiGraph.EmptyGraph ..................................................... Passed 0.00 sec + Start 61: FlowState.ZeroCapacityHandling + 25/170 Test #41: ShortestPaths.EdgeMaskFiltering ................................................... Passed 0.00 sec + Start 22: StrictMultiDiGraph.ExternalEdgeIdsPreserved + 26/170 Test #89: FlowGraph.GetFlowPathForDAGReturnsEmpty ........................................... Passed 0.00 sec + Start 155: MaskingTests.MultipleEdgesMasked + 27/170 Test #104: MaxFlow.ECMP_TenPaths_ScalabilityValidation ....................................... Passed 0.00 sec + Start 149: MaskingTests.MaskedSourceInComputeMinCut + 28/170 Test #61: FlowState.ZeroCapacityHandling .................................................... Passed 0.00 sec + Start 109: MaxFlow.ZeroCapacityPath_CorrectFiltering + 29/170 Test #22: StrictMultiDiGraph.ExternalEdgeIdsPreserved ....................................... Passed 0.00 sec + Start 126: MaxFlow.Triangle_Topology_Combine_Mode + 30/170 Test #155: MaskingTests.MultipleEdgesMasked .................................................. Passed 0.00 sec + Start 122: MaxFlow.GridGraph_3x3_MultipleEqualCostPaths + 31/170 Test #149: MaskingTests.MaskedSourceInComputeMinCut .......................................... Passed 0.00 sec + Start 103: MaxFlow.ECMP_FourPaths_ClosFabric_Simulation + 32/170 Test #109: MaxFlow.ZeroCapacityPath_CorrectFiltering ......................................... Passed 0.00 sec + Start 107: MaxFlow.AsymmetricCapacity_1to100_EqualBalanced + 33/170 Test #126: MaxFlow.Triangle_Topology_Combine_Mode ............................................ Passed 0.00 sec + Start 42: ShortestPaths.EarlyExitOptimization + 34/170 Test #122: MaxFlow.GridGraph_3x3_MultipleEqualCostPaths ...................................... Passed 0.00 sec + Start 64: FlowState.MinCutComputation + 35/170 Test #103: MaxFlow.ECMP_FourPaths_ClosFabric_Simulation ...................................... Passed 0.00 sec + Start 75: FlowState.Proportional_ZeroCapacityOnShortestPath_ReturnsZero + 36/170 Test #107: MaxFlow.AsymmetricCapacity_1to100_EqualBalanced ................................... Passed 0.00 sec + Start 29: StrictMultiDiGraph.ExtEdgeIdsWrongLengthThrows + 37/170 Test #42: ShortestPaths.EarlyExitOptimization ............................................... Passed 0.00 sec + Start 135: KShortestPaths.FindsKPaths + 38/170 Test #64: FlowState.MinCutComputation ....................................................... Passed 0.00 sec + Start 32: StrictMultiDiGraph.NegativeCostThrows + 39/170 Test #75: FlowState.Proportional_ZeroCapacityOnShortestPath_ReturnsZero ..................... Passed 0.00 sec + Start 99: MaxFlow.ECMP_TwoPaths_Proportional_ShortestPath + 40/170 Test #29: StrictMultiDiGraph.ExtEdgeIdsWrongLengthThrows .................................... Passed 0.00 sec + Start 21: StrictMultiDiGraph.EdgeSortingByCost + 41/170 Test #135: KShortestPaths.FindsKPaths ........................................................ Passed 0.00 sec + Start 7: FlowPolicyCore.EqualBalanced_SingleDemand_FlowCount3_SaturatesBothPaths + 42/170 Test #32: StrictMultiDiGraph.NegativeCostThrows ............................................. Passed 0.00 sec + Start 37: ShortestPaths.DisconnectedComponents + 43/170 Test #99: MaxFlow.ECMP_TwoPaths_Proportional_ShortestPath ................................... Passed 0.00 sec + Start 69: FlowState.ApplyDeltasClampsWithinCapacityBounds + 44/170 Test #21: StrictMultiDiGraph.EdgeSortingByCost .............................................. Passed 0.00 sec + Start 143: KShortestPaths.OutOfOrderNodePredDAGSemantics + 45/170 Test #7: FlowPolicyCore.EqualBalanced_SingleDemand_FlowCount3_SaturatesBothPaths ........... Passed 0.00 sec + Start 134: MaxFlow.CompletionPhase_RespectsNodeMask + 46/170 Test #37: ShortestPaths.DisconnectedComponents .............................................. Passed 0.00 sec + Start 68: FlowState.ResetWithInvalidResidualThrows + 47/170 Test #69: FlowState.ApplyDeltasClampsWithinCapacityBounds ................................... Passed 0.00 sec + Start 46: ShortestPaths.ResolveToPathsSplittingParallelEdges + 48/170 Test #143: KShortestPaths.OutOfOrderNodePredDAGSemantics ..................................... Passed 0.00 sec + Start 112: MaxFlow.EqualCost_ShortestVsFull_Equivalent + 49/170 Test #134: MaxFlow.CompletionPhase_RespectsNodeMask .......................................... Passed 0.00 sec + Start 157: MaskingTests.NodeMaskOverridesEdgeMask + 50/170 Test #68: FlowState.ResetWithInvalidResidualThrows .......................................... Passed 0.00 sec + Start 133: MaxFlow.CompletionPhase_RecoversCancellation + 51/170 Test #46: ShortestPaths.ResolveToPathsSplittingParallelEdges ................................ Passed 0.00 sec + Start 35: StrictMultiDiGraph.MultipleCostTiers + 52/170 Test #112: MaxFlow.EqualCost_ShortestVsFull_Equivalent ....................................... Passed 0.00 sec + Start 153: MaskingTests.MaskedEdgeBlocksPath + 53/170 Test #157: MaskingTests.NodeMaskOverridesEdgeMask ............................................ Passed 0.00 sec + Start 27: StrictMultiDiGraph.InvalidNumNodesThrows + 54/170 Test #133: MaxFlow.CompletionPhase_RecoversCancellation ...................................... Passed 0.00 sec + Start 71: FlowState.EqualBalanced_ECMP3_FirstHopEqualization + 55/170 Test #35: StrictMultiDiGraph.MultipleCostTiers .............................................. Passed 0.00 sec + Start 114: MaxFlow.PlacementModes_EqualCapacity_IdenticalResult + 56/170 Test #153: MaskingTests.MaskedEdgeBlocksPath ................................................. Passed 0.00 sec + Start 91: FlowGraph.LedgerHistory_RemovalRestoresResidual + 57/170 Test #27: StrictMultiDiGraph.InvalidNumNodesThrows .......................................... Passed 0.00 sec + Start 20: StrictMultiDiGraph.ParallelEdges + 58/170 Test #71: FlowState.EqualBalanced_ECMP3_FirstHopEqualization ................................ Passed 0.00 sec + Start 63: FlowState.ApplyDeltasSubtractive + 59/170 Test #114: MaxFlow.PlacementModes_EqualCapacity_IdenticalResult .............................. Passed 0.00 sec + Start 31: StrictMultiDiGraph.NegativeCapacityThrows + 60/170 Test #91: FlowGraph.LedgerHistory_RemovalRestoresResidual ................................... Passed 0.00 sec + Start 5: FlowPolicyCore.Proportional_SingleDemand_PartialPlacement_InsufficientCapacity + 61/170 Test #20: StrictMultiDiGraph.ParallelEdges .................................................. Passed 0.00 sec + Start 2: FlowPolicyCore.Proportional_SingleDemand_UsesShortestPath + 62/170 Test #63: FlowState.ApplyDeltasSubtractive .................................................. Passed 0.00 sec + Start 121: MaxFlow.BatchMaxFlow_IndependentMaskApplication + 63/170 Test #31: StrictMultiDiGraph.NegativeCapacityThrows ......................................... Passed 0.00 sec + Start 150: MaskingTests.OutOfRangeSourceInComputeMinCut + 64/170 Test #5: FlowPolicyCore.Proportional_SingleDemand_PartialPlacement_InsufficientCapacity .... Passed 0.00 sec + Start 117: MaxFlow.CostDistribution_AccountsForAllFlow + 65/170 Test #2: FlowPolicyCore.Proportional_SingleDemand_UsesShortestPath ......................... Passed 0.00 sec + Start 100: MaxFlow.ECMP_TwoPaths_Proportional_FullMaxFlow + 66/170 Test #150: MaskingTests.OutOfRangeSourceInComputeMinCut ...................................... Passed 0.00 sec + Start 113: MaxFlow.ThreeCostTiers_ShortestPath_LowestTierOnly + 67/170 Test #121: MaxFlow.BatchMaxFlow_IndependentMaskApplication ................................... Passed 0.00 sec + Start 76: FlowState.RepeatedPlacementAfterResetAndIndependentInstancesStayStable + 68/170 Test #117: MaxFlow.CostDistribution_AccountsForAllFlow ....................................... Passed 0.00 sec + Start 23: StrictMultiDiGraph.CSROffsetsMonotonicity + 69/170 Test #100: MaxFlow.ECMP_TwoPaths_Proportional_FullMaxFlow .................................... Passed 0.00 sec + Start 4: FlowPolicyCore.Proportional_SingleDemand_MaxFlowCount1_UsesSinglePath + 70/170 Test #113: MaxFlow.ThreeCostTiers_ShortestPath_LowestTierOnly ................................ Passed 0.00 sec + Start 58: FlowState.PlacementReducesResidual + 71/170 Test #76: FlowState.RepeatedPlacementAfterResetAndIndependentInstancesStayStable ............ Passed 0.00 sec + Start 59: FlowState.ProportionalDistribution + 72/170 Test #23: StrictMultiDiGraph.CSROffsetsMonotonicity ......................................... Passed 0.00 sec + Start 48: ShortestPaths.LargeGraphStressTest + 73/170 Test #4: FlowPolicyCore.Proportional_SingleDemand_MaxFlowCount1_UsesSinglePath ............. Passed 0.00 sec + Start 130: MaxFlow.Sensitivity_TwoParallelPaths + 74/170 Test #58: FlowState.PlacementReducesResidual ................................................ Passed 0.00 sec + Start 6: FlowPolicyCore.EqualBalanced_SingleDemand_FlowCount2_BalancedDistribution + 75/170 Test #59: FlowState.ProportionalDistribution ................................................ Passed 0.00 sec + Start 44: ShortestPaths.TieBreakingDeterminism + 76/170 Test #48: ShortestPaths.LargeGraphStressTest ................................................ Passed 0.00 sec + Start 140: KShortestPaths.PathsSortedByCost + 77/170 Test #130: MaxFlow.Sensitivity_TwoParallelPaths .............................................. Passed 0.00 sec + Start 158: MaskingTests.MaskWithResidualCapacity + 78/170 Test #6: FlowPolicyCore.EqualBalanced_SingleDemand_FlowCount2_BalancedDistribution ......... Passed 0.00 sec + Start 39: ShortestPaths.ResidualAwareFiltering + 79/170 Test #44: ShortestPaths.TieBreakingDeterminism .............................................. Passed 0.00 sec + Start 161: MaskingTests.KSPWithEdgeMask + 80/170 Test #140: KShortestPaths.PathsSortedByCost .................................................. Passed 0.00 sec + Start 49: ShortestPaths.RejectsMaskLengthMismatch + 81/170 Test #158: MaskingTests.MaskWithResidualCapacity ............................................. Passed 0.00 sec + Start 127: MaxFlow.SimpleParallelPaths_Topology + 82/170 Test #39: ShortestPaths.ResidualAwareFiltering .............................................. Passed 0.00 sec + Start 162: MaskingTests.MaxFlowWithNodeMask + 83/170 Test #161: MaskingTests.KSPWithEdgeMask ...................................................... Passed 0.00 sec + Start 137: KShortestPaths.NodeMaskBlocksPaths + 84/170 Test #49: ShortestPaths.RejectsMaskLengthMismatch ........................................... Passed 0.00 sec + Start 18: StrictMultiDiGraph.SingleNode + 85/170 Test #127: MaxFlow.SimpleParallelPaths_Topology .............................................. Passed 0.00 sec + Start 108: MaxFlow.EqualBalanced_NodeMask_ReducesECMPWidth + 86/170 Test #162: MaskingTests.MaxFlowWithNodeMask .................................................. Passed 0.00 sec + Start 88: FlowGraph.GetFlowPathForLinearFlow + 87/170 Test #137: KShortestPaths.NodeMaskBlocksPaths ................................................ Passed 0.00 sec + Start 160: MaskingTests.KSPWithNodeMask + 88/170 Test #18: StrictMultiDiGraph.SingleNode ..................................................... Passed 0.00 sec + Start 50: ShortestPaths.ZeroCostEdges_PredDAGIsAcyclic + 89/170 Test #108: MaxFlow.EqualBalanced_NodeMask_ReducesECMPWidth ................................... Passed 0.00 sec + Start 3: FlowPolicyCore.Proportional_SingleDemand_SplitsAcrossTwoEqualCostPaths + 90/170 Test #88: FlowGraph.GetFlowPathForLinearFlow ................................................ Passed 0.00 sec + Start 142: KShortestPaths.LooplessPaths + 91/170 Test #160: MaskingTests.KSPWithNodeMask ...................................................... Passed 0.00 sec + Start 116: MaxFlow.MinCut_ValidEdgeIdentification + 92/170 Test #50: ShortestPaths.ZeroCostEdges_PredDAGIsAcyclic ...................................... Passed 0.00 sec + Start 36: ShortestPaths.SingleSourceAllNodes + 93/170 Test #3: FlowPolicyCore.Proportional_SingleDemand_SplitsAcrossTwoEqualCostPaths ............ Passed 0.00 sec + Start 38: ShortestPaths.MultipleEqualCostPaths + 94/170 Test #142: KShortestPaths.LooplessPaths ...................................................... Passed 0.00 sec + Start 111: MaxFlow.TwoCostTiers_FullMaxFlow_AllTiers + 95/170 Test #116: MaxFlow.MinCut_ValidEdgeIdentification ............................................ Passed 0.00 sec + Start 136: KShortestPaths.KEqualsZeroReturnsEmpty + 96/170 Test #36: ShortestPaths.SingleSourceAllNodes ................................................ Passed 0.00 sec + Start 24: StrictMultiDiGraph.CSRReverseAdjacency + 97/170 Test #38: ShortestPaths.MultipleEqualCostPaths .............................................. Passed 0.00 sec + Start 97: MaxFlow.SinglePath_ShortestPathEquivalence + 98/170 Test #111: MaxFlow.TwoCostTiers_FullMaxFlow_AllTiers ......................................... Passed 0.00 sec + Start 146: MaskingTests.MaskedSourceReturnsEmptyDAG + 99/170 Test #136: KShortestPaths.KEqualsZeroReturnsEmpty ............................................ Passed 0.00 sec + Start 90: FlowGraph.CoalescesDuplicateEdgeIds +100/170 Test #24: StrictMultiDiGraph.CSRReverseAdjacency ............................................ Passed 0.00 sec + Start 28: StrictMultiDiGraph.MismatchedArrayLengthsThrow +101/170 Test #97: MaxFlow.SinglePath_ShortestPathEquivalence ........................................ Passed 0.00 sec + Start 129: MaxFlow.Sensitivity_SinglePath +102/170 Test #146: MaskingTests.MaskedSourceReturnsEmptyDAG .......................................... Passed 0.00 sec + Start 131: MaxFlow.Sensitivity_PartialSaturation +103/170 Test #90: FlowGraph.CoalescesDuplicateEdgeIds ............................................... Passed 0.00 sec + Start 110: MaxFlow.TwoCostTiers_ShortestPath_SingleTierOnly +104/170 Test #28: StrictMultiDiGraph.MismatchedArrayLengthsThrow .................................... Passed 0.00 sec + Start 124: MaxFlow.Clos_3Tier_Topology_Proportional_Shortest +105/170 Test #129: MaxFlow.Sensitivity_SinglePath .................................................... Passed 0.00 sec + Start 120: MaxFlow.EdgeMask_SelectiveEdgeFiltering +106/170 Test #131: MaxFlow.Sensitivity_PartialSaturation ............................................. Passed 0.00 sec + Start 45: ShortestPaths.PreferHigherResidualTieBreak +107/170 Test #124: MaxFlow.Clos_3Tier_Topology_Proportional_Shortest ................................. Passed 0.00 sec + Start 123: MaxFlow.SharedBottleneck_MultiplePathsMerge +108/170 Test #110: MaxFlow.TwoCostTiers_ShortestPath_SingleTierOnly .................................. Passed 0.00 sec + Start 57: FlowState.InitialResidualEqualsCapacity +109/170 Test #120: MaxFlow.EdgeMask_SelectiveEdgeFiltering ........................................... Passed 0.00 sec + Start 25: StrictMultiDiGraph.MaxCapacityEdges +110/170 Test #45: ShortestPaths.PreferHigherResidualTieBreak ........................................ Passed 0.00 sec + Start 40: ShortestPaths.NodeMaskIsolation +111/170 Test #123: MaxFlow.SharedBottleneck_MultiplePathsMerge ....................................... Passed 0.00 sec + Start 125: MaxFlow.Clos_3Tier_Topology_EqualBalanced_Shortest +112/170 Test #57: FlowState.InitialResidualEqualsCapacity ........................................... Passed 0.00 sec + Start 128: MaxFlow.ShortestPath_MustSaturateAllEqualCostPaths +113/170 Test #25: StrictMultiDiGraph.MaxCapacityEdges ............................................... Passed 0.00 sec + Start 74: FlowState.EqualBalanced_ZeroCapacityOnShortestPath_ReturnsZero +114/170 Test #40: ShortestPaths.NodeMaskIsolation ................................................... Passed 0.00 sec + Start 159: MaskingTests.ResidualAndNodeMaskCombined +115/170 Test #125: MaxFlow.Clos_3Tier_Topology_EqualBalanced_Shortest ................................ Passed 0.00 sec + Start 147: MaskingTests.MaskedSourceWithDestination +116/170 Test #128: MaxFlow.ShortestPath_MustSaturateAllEqualCostPaths ................................ Passed 0.00 sec + Start 70: FlowState.EqualBalancedReconvergentDAGPlacesAll +117/170 Test #74: FlowState.EqualBalanced_ZeroCapacityOnShortestPath_ReturnsZero .................... Passed 0.00 sec + Start 84: FlowGraph.PlacementCreatesEntry +118/170 Test #159: MaskingTests.ResidualAndNodeMaskCombined .......................................... Passed 0.00 sec + Start 30: StrictMultiDiGraph.OutOfRangeNodeThrows +119/170 Test #147: MaskingTests.MaskedSourceWithDestination .......................................... Passed 0.00 sec + Start 62: FlowState.ApplyDeltasAdditive +120/170 Test #70: FlowState.EqualBalancedReconvergentDAGPlacesAll ................................... Passed 0.00 sec + Start 65: FlowState.ResetRestoresCapacity +121/170 Test #84: FlowGraph.PlacementCreatesEntry ................................................... Passed 0.00 sec + Start 151: MaskingTests.MaskedDestinationUnreachable +122/170 Test #30: StrictMultiDiGraph.OutOfRangeNodeThrows ........................................... Passed 0.00 sec + Start 60: FlowState.EqualBalancedDistribution +123/170 Test #62: FlowState.ApplyDeltasAdditive ..................................................... Passed 0.00 sec + Start 139: KShortestPaths.MaxCostFactorLimit +124/170 Test #65: FlowState.ResetRestoresCapacity ................................................... Passed 0.00 sec + Start 19: StrictMultiDiGraph.SingleEdge +125/170 Test #151: MaskingTests.MaskedDestinationUnreachable ......................................... Passed 0.00 sec + Start 96: MaxFlow.SinglePath_BottleneckConstraint +126/170 Test #60: FlowState.EqualBalancedDistribution ............................................... Passed 0.00 sec + Start 66: FlowState.CustomInitialResidual +127/170 Test #139: KShortestPaths.MaxCostFactorLimit ................................................. Passed 0.00 sec + Start 115: MaxFlow.FlowConservation_IntermediateNodes +128/170 Test #19: StrictMultiDiGraph.SingleEdge ..................................................... Passed 0.00 sec + Start 101: MaxFlow.ECMP_TwoPaths_EqualBalanced_ShortestPath +129/170 Test #96: MaxFlow.SinglePath_BottleneckConstraint ........................................... Passed 0.00 sec + Start 102: MaxFlow.ECMP_ThreePaths_Proportional_ShortestPath +130/170 Test #66: FlowState.CustomInitialResidual ................................................... Passed 0.00 sec + Start 26: StrictMultiDiGraph.ZeroCostEdges +131/170 Test #115: MaxFlow.FlowConservation_IntermediateNodes ........................................ Passed 0.00 sec + Start 72: FlowState.EqualBalanced_MinFlowGating_DoesNotPruneValidParallelEdges +132/170 Test #101: MaxFlow.ECMP_TwoPaths_EqualBalanced_ShortestPath .................................. Passed 0.00 sec + Start 95: MaxFlow.SinglePath_BasicLinear +133/170 Test #102: MaxFlow.ECMP_ThreePaths_Proportional_ShortestPath ................................. Passed 0.00 sec + Start 98: MaxFlow.DegenerateCase_SourceEqualsSink +134/170 Test #26: StrictMultiDiGraph.ZeroCostEdges .................................................. Passed 0.00 sec + Start 86: FlowGraph.RemoveByClassFiltersCorrectly +135/170 Test #72: FlowState.EqualBalanced_MinFlowGating_DoesNotPruneValidParallelEdges .............. Passed 0.00 sec + Start 73: FlowState.EqualBalanced_DownstreamSplitEqualization +136/170 Test #95: MaxFlow.SinglePath_BasicLinear .................................................... Passed 0.00 sec + Start 119: MaxFlow.NodeMask_BlocksFlowThroughNode +137/170 Test #98: MaxFlow.DegenerateCase_SourceEqualsSink ........................................... Passed 0.00 sec + Start 85: FlowGraph.RemovalDeletesEntry +138/170 Test #86: FlowGraph.RemoveByClassFiltersCorrectly ........................................... Passed 0.00 sec + Start 87: FlowGraph.GetFlowEdgesReturnsDeltas +139/170 Test #73: FlowState.EqualBalanced_DownstreamSplitEqualization ............................... Passed 0.00 sec + Start 163: MaskingTests.MaxFlowWithEdgeMask +140/170 Test #119: MaxFlow.NodeMask_BlocksFlowThroughNode ............................................ Passed 0.00 sec + Start 164: MaskingTests.MaxFlowAllPathsMasked +141/170 Test #85: FlowGraph.RemovalDeletesEntry ..................................................... Passed 0.00 sec + Start 165: MaskingTests.EmptyNodeMaskAllowsAllNodes +142/170 Test #87: FlowGraph.GetFlowEdgesReturnsDeltas ............................................... Passed 0.00 sec + Start 12: FlowPolicyStatic.PerFlowBundleBinding +143/170 Test #163: MaskingTests.MaxFlowWithEdgeMask .................................................. Passed 0.00 sec + Start 169: MaskingTests.AlgorithmsAPIMaskedSource +144/170 Test #164: MaskingTests.MaxFlowAllPathsMasked ................................................ Passed 0.00 sec + Start 13: FlowPolicyStatic.MaskedBundleIsDown +145/170 Test #165: MaskingTests.EmptyNodeMaskAllowsAllNodes .......................................... Passed 0.00 sec + Start 15: FlowPolicyCostBounds.MaxPathCostFactor_UnreachableDst_KeepsSentinelOutOfTheCast +146/170 Test #12: FlowPolicyStatic.PerFlowBundleBinding ............................................. Passed 0.00 sec + Start 14: FlowPolicyStatic.ValidationRejectsForeignAndDisconnectedBundles +147/170 Test #169: MaskingTests.AlgorithmsAPIMaskedSource ............................................ Passed 0.00 sec + Start 55: ShortestPathsTo.FanoutFromInteriorNodeIsRejected +148/170 Test #13: FlowPolicyStatic.MaskedBundleIsDown ............................................... Passed 0.00 sec + Start 52: ShortestPathsTo.ForwardSpfFromPseudoSourceKeepsOnlyNearestSource +149/170 Test #15: FlowPolicyCostBounds.MaxPathCostFactor_UnreachableDst_KeepsSentinelOutOfTheCast ... Passed 0.00 sec + Start 166: MaskingTests.EmptyEdgeMaskAllowsAllEdges +150/170 Test #14: FlowPolicyStatic.ValidationRejectsForeignAndDisconnectedBundles ................... Passed 0.00 sec + Start 16: FlowPolicyCostBounds.MaxPathCostFactor_HugeProduct_DropsBoundInsteadOfWrapping +151/170 Test #55: ShortestPathsTo.FanoutFromInteriorNodeIsRejected .................................. Passed 0.00 sec + Start 51: ShortestPathsTo.DistancesMatchForwardDistancesToDst +152/170 Test #52: ShortestPathsTo.ForwardSpfFromPseudoSourceKeepsOnlyNearestSource .................. Passed 0.00 sec + Start 94: FlowGraphStamp.EqualVersionDivergentCopiesCompareUnequal +153/170 Test #166: MaskingTests.EmptyEdgeMaskAllowsAllEdges .......................................... Passed 0.00 sec + Start 81: FlowState.EqualBalancedLossy_InfiniteRequestFillsWithoutDrops +154/170 Test #16: FlowPolicyCostBounds.MaxPathCostFactor_HugeProduct_DropsBoundInsteadOfWrapping .... Passed 0.00 sec + Start 79: FlowState.EqualBalancedLossy_FillAndDropReportsDrops +155/170 Test #51: ShortestPathsTo.DistancesMatchForwardDistancesToDst ............................... Passed 0.00 sec + Start 170: MaskingTests.AlgorithmsAPIMaxFlowWithMask +156/170 Test #94: FlowGraphStamp.EqualVersionDivergentCopiesCompareUnequal .......................... Passed 0.00 sec + Start 82: FlowGraph.LossyPlacementIsReversibleAndDropsStayOutOfLedger +157/170 Test #81: FlowState.EqualBalancedLossy_InfiniteRequestFillsWithoutDrops ..................... Passed 0.00 sec + Start 167: MaskingTests.AllNodesMaskedNoReachability +158/170 Test #79: FlowState.EqualBalancedLossy_FillAndDropReportsDrops .............................. Passed 0.00 sec + Start 168: MaskingTests.AllEdgesMaskedNoReachability +159/170 Test #170: MaskingTests.AlgorithmsAPIMaxFlowWithMask ......................................... Passed 0.00 sec + Start 80: FlowState.EqualBalancedLossy_DeficitPropagatesDownstream +160/170 Test #82: FlowGraph.LossyPlacementIsReversibleAndDropsStayOutOfLedger ....................... Passed 0.00 sec + Start 53: ShortestPathsTo.FanoutEdgesForceEverySourceIntoTheDag +161/170 Test #167: MaskingTests.AllNodesMaskedNoReachability ......................................... Passed 0.00 sec + Start 93: FlowGraphStamp.CopiesAndMovesGetFreshUids +162/170 Test #168: MaskingTests.AllEdgesMaskedNoReachability ......................................... Passed 0.00 sec + Start 145: KSP.MaxCostFactorBelowOne_ReturnsEmptyForAllK +163/170 Test #80: FlowState.EqualBalancedLossy_DeficitPropagatesDownstream .......................... Passed 0.00 sec + Start 54: ShortestPathsTo.FanoutSkipsUnreachableAndMaskedHeads +164/170 Test #53: ShortestPathsTo.FanoutEdgesForceEverySourceIntoTheDag ............................. Passed 0.00 sec + Start 77: FlowState.EqualBalanced_SaturatedMemberBlocksAdmission +165/170 Test #93: FlowGraphStamp.CopiesAndMovesGetFreshUids ......................................... Passed 0.00 sec + Start 78: FlowState.EqualBalanced_ProgressesOnlyThroughResidualAwareSpf +166/170 Test #145: KSP.MaxCostFactorBelowOne_ReturnsEmptyForAllK ..................................... Passed 0.00 sec + Start 56: ShortestPathsTo.SinglePathModeKeepsOneSuccessorPerNode +167/170 Test #54: ShortestPathsTo.FanoutSkipsUnreachableAndMaskedHeads .............................. Passed 0.00 sec +168/170 Test #77: FlowState.EqualBalanced_SaturatedMemberBlocksAdmission ............................ Passed 0.00 sec +169/170 Test #78: FlowState.EqualBalanced_ProgressesOnlyThroughResidualAwareSpf ..................... Passed 0.00 sec +170/170 Test #56: ShortestPathsTo.SinglePathModeKeepsOneSuccessorPerNode ............................ Passed 0.00 sec + +100% tests passed out of 170 + +Total Test time (real) = 0.10 sec +........................................................................ [ 15%] +........................................................................ [ 30%] +........................................................................ [ 46%] +........................................................................ [ 61%] +........................................................................ [ 77%] +........................................................................ [ 92%] +................................. [100%] +465 passed in 3.88s diff --git a/dev/research/metal_pathfinding/optimization/results/workspace-check-format-failure.txt b/dev/research/metal_pathfinding/optimization/results/workspace-check-format-failure.txt new file mode 100644 index 0000000..5ae98d9 --- /dev/null +++ b/dev/research/metal_pathfinding/optimization/results/workspace-check-format-failure.txt @@ -0,0 +1,29 @@ +📦 Installing package (editable, default optimizations) +Obtaining file:///Users/networmix/ws/NetGraph-Core + Installing build dependencies: started + Installing build dependencies: finished with status 'done' + Checking if build backend supports build_editable: started + Checking if build backend supports build_editable: finished with status 'done' + Getting requirements to build editable: started + Getting requirements to build editable: finished with status 'done' + Installing backend dependencies: started + Installing backend dependencies: finished with status 'done' + Preparing editable metadata (pyproject.toml): started + Preparing editable metadata (pyproject.toml): finished with status 'done' +Requirement already satisfied: numpy>=1.23.2 in ./venv/lib/python3.14/site-packages (from netgraph-core==0.10.0) (2.5.2) +Building wheels for collected packages: netgraph-core + Building editable for netgraph-core (pyproject.toml): started + Building editable for netgraph-core (pyproject.toml): finished with status 'done' + Created wheel for netgraph-core: filename=netgraph_core-0.10.0-cp314-cp314-macosx_15_0_arm64.whl size=314893 sha256=45dc943b94205d14b496b501ddece08674343bf5cd918dad537b691749b3e16c + Stored in directory: /private/var/folders/8q/438f_q5s0ys8nlnvjqkf953m0000gn/T/pip-ephem-wheel-cache-jhm8vyb3/wheels/18/8c/1a/f701a43f4b69f7c794e11f1f5dd0c17e819d2c98bfd1285718 +Successfully built netgraph-core +Installing collected packages: netgraph-core + Attempting uninstall: netgraph-core + Found existing installation: netgraph-core 0.10.0 + Uninstalling netgraph-core-0.10.0: + Successfully uninstalled netgraph-core-0.10.0 +Successfully installed netgraph-core-0.10.0 +Would reformat: dev/research/metal_pathfinding/optimization/summarize.py +1 file would be reformatted, 45 files already formatted +make[1]: *** [lint] Error 1 +make: *** [check-ci] Error 2 diff --git a/dev/research/metal_pathfinding/optimization/results/workspace-check.txt b/dev/research/metal_pathfinding/optimization/results/workspace-check.txt new file mode 100644 index 0000000..63a2578 --- /dev/null +++ b/dev/research/metal_pathfinding/optimization/results/workspace-check.txt @@ -0,0 +1,391 @@ +📦 Installing package (editable, default optimizations) +Obtaining file:///Users/networmix/ws/NetGraph-Core + Installing build dependencies: started + Installing build dependencies: finished with status 'done' + Checking if build backend supports build_editable: started + Checking if build backend supports build_editable: finished with status 'done' + Getting requirements to build editable: started + Getting requirements to build editable: finished with status 'done' + Installing backend dependencies: started + Installing backend dependencies: finished with status 'done' + Preparing editable metadata (pyproject.toml): started + Preparing editable metadata (pyproject.toml): finished with status 'done' +Requirement already satisfied: numpy>=1.23.2 in ./venv/lib/python3.14/site-packages (from netgraph-core==0.10.0) (2.5.2) +Building wheels for collected packages: netgraph-core + Building editable for netgraph-core (pyproject.toml): started + Building editable for netgraph-core (pyproject.toml): finished with status 'done' + Created wheel for netgraph-core: filename=netgraph_core-0.10.0-cp314-cp314-macosx_15_0_arm64.whl size=314893 sha256=d1b60157a21593b4395cd742e5e77836464e64204d8e6696eaad98b9b46fcad9 + Stored in directory: /private/var/folders/8q/438f_q5s0ys8nlnvjqkf953m0000gn/T/pip-ephem-wheel-cache-pakafcm5/wheels/18/8c/1a/f701a43f4b69f7c794e11f1f5dd0c17e819d2c98bfd1285718 +Successfully built netgraph-core +Installing collected packages: netgraph-core + Attempting uninstall: netgraph-core + Found existing installation: netgraph-core 0.10.0 + Uninstalling netgraph-core-0.10.0: + Successfully uninstalled netgraph-core-0.10.0 +Successfully installed netgraph-core-0.10.0 +46 files already formatted +All checks passed! +0 errors, 0 warnings, 0 informations +WARNING: there is a new pyright version available (v1.1.401 -> v1.1.414). +Please install the new version or set PYRIGHT_PYTHON_FORCE_VERSION to `latest` + +-- pybind11 not found via config; using FetchContent +-- pybind11 v3.0.0 +-- LTO not supported: CMake doesn't support IPO for current C compiler +-- Configuring done (0.5s) +-- Generating done (0.0s) +-- Build files have been written to: /Users/networmix/ws/NetGraph-Core/build/cpp-tests +ninja: no work to do. +Test project /Users/networmix/ws/NetGraph-Core/build/cpp-tests + Start 141: KShortestPaths.DisconnectedReturnsEmpty + Start 132: MaxFlow.Sensitivity_ShortestPathVsMaxFlow + Start 34: StrictMultiDiGraph.NegativeNodeIdThrows + Start 11: FlowPolicyCore.EqualBalanced_ShortestPath_IgnoresHigherCostTier + 1/170 Test #141: KShortestPaths.DisconnectedReturnsEmpty ........................................... Passed 0.04 sec + 2/170 Test #34: StrictMultiDiGraph.NegativeNodeIdThrows ........................................... Passed 0.03 sec + Start 152: MaskingTests.MaskedIntermediateNode + Start 9: FlowPolicyCore.EqualBalanced_ShortestPath_ECMP3_SaturatesAllEqualCostPaths + 3/170 Test #132: MaxFlow.Sensitivity_ShortestPathVsMaxFlow ......................................... Passed 0.04 sec + 4/170 Test #11: FlowPolicyCore.EqualBalanced_ShortestPath_IgnoresHigherCostTier ................... Passed 0.04 sec + Start 10: FlowPolicyCore.EqualBalanced_ShortestPath_DownstreamSplit_BalancesBottleneck + Start 105: MaxFlow.AsymmetricCapacity_1to100_Proportional + 5/170 Test #152: MaskingTests.MaskedIntermediateNode ............................................... Passed 0.00 sec + Start 154: MaskingTests.MaskedEdgeSelectsAlternativePath + 6/170 Test #9: FlowPolicyCore.EqualBalanced_ShortestPath_ECMP3_SaturatesAllEqualCostPaths ........ Passed 0.00 sec + Start 156: MaskingTests.CombinedNodeAndEdgeMasks + 7/170 Test #10: FlowPolicyCore.EqualBalanced_ShortestPath_DownstreamSplit_BalancesBottleneck ...... Passed 0.00 sec + Start 144: KShortestPaths.LargerOutOfOrderTopology + 8/170 Test #105: MaxFlow.AsymmetricCapacity_1to100_Proportional .................................... Passed 0.00 sec + Start 43: ShortestPaths.PredDAGIntegrity + 9/170 Test #154: MaskingTests.MaskedEdgeSelectsAlternativePath ..................................... Passed 0.00 sec + Start 148: MaskingTests.MaskedSourceInMaxFlow + 10/170 Test #156: MaskingTests.CombinedNodeAndEdgeMasks ............................................. Passed 0.00 sec + Start 118: MaxFlow.OptionalOutputs_ResidualAndReachable + 11/170 Test #144: KShortestPaths.LargerOutOfOrderTopology ........................................... Passed 0.00 sec + Start 33: StrictMultiDiGraph.SelfLoopAllowed + 12/170 Test #43: ShortestPaths.PredDAGIntegrity .................................................... Passed 0.00 sec + Start 8: FlowPolicyCore.DiminishingReturnsCutoff + 13/170 Test #148: MaskingTests.MaskedSourceInMaxFlow ................................................ Passed 0.00 sec + Start 138: KShortestPaths.UniqueModeFiltering + 14/170 Test #118: MaxFlow.OptionalOutputs_ResidualAndReachable ...................................... Passed 0.00 sec + Start 92: FlowGraph.LedgerMicroFlows_RemovalRestoresResidual + 15/170 Test #33: StrictMultiDiGraph.SelfLoopAllowed ................................................ Passed 0.00 sec + Start 83: FlowGraph.EmptyLedgerInitially + 16/170 Test #8: FlowPolicyCore.DiminishingReturnsCutoff ........................................... Passed 0.00 sec + Start 47: ShortestPaths.ResolveToPathsWithMaxPathsLimit + 17/170 Test #138: KShortestPaths.UniqueModeFiltering ................................................ Passed 0.00 sec + Start 67: FlowState.InvalidResidualInitThrows + 18/170 Test #92: FlowGraph.LedgerMicroFlows_RemovalRestoresResidual ................................ Passed 0.00 sec + Start 106: MaxFlow.AsymmetricCapacity_1to1M_NumericalStability + 19/170 Test #83: FlowGraph.EmptyLedgerInitially .................................................... Passed 0.00 sec + Start 17: StrictMultiDiGraph.EmptyGraph + 20/170 Test #47: ShortestPaths.ResolveToPathsWithMaxPathsLimit ..................................... Passed 0.00 sec + Start 1: GraphSmoke.ConstructAndRunSPF + 21/170 Test #67: FlowState.InvalidResidualInitThrows ............................................... Passed 0.00 sec + Start 41: ShortestPaths.EdgeMaskFiltering + 22/170 Test #106: MaxFlow.AsymmetricCapacity_1to1M_NumericalStability ............................... Passed 0.00 sec + Start 89: FlowGraph.GetFlowPathForDAGReturnsEmpty + 23/170 Test #17: StrictMultiDiGraph.EmptyGraph ..................................................... Passed 0.00 sec + Start 104: MaxFlow.ECMP_TenPaths_ScalabilityValidation + 24/170 Test #1: GraphSmoke.ConstructAndRunSPF ..................................................... Passed 0.00 sec + Start 61: FlowState.ZeroCapacityHandling + 25/170 Test #41: ShortestPaths.EdgeMaskFiltering ................................................... Passed 0.00 sec + Start 22: StrictMultiDiGraph.ExternalEdgeIdsPreserved + 26/170 Test #89: FlowGraph.GetFlowPathForDAGReturnsEmpty ........................................... Passed 0.00 sec + Start 149: MaskingTests.MaskedSourceInComputeMinCut + 27/170 Test #104: MaxFlow.ECMP_TenPaths_ScalabilityValidation ....................................... Passed 0.00 sec + Start 126: MaxFlow.Triangle_Topology_Combine_Mode + 28/170 Test #61: FlowState.ZeroCapacityHandling .................................................... Passed 0.00 sec + Start 103: MaxFlow.ECMP_FourPaths_ClosFabric_Simulation + 29/170 Test #22: StrictMultiDiGraph.ExternalEdgeIdsPreserved ....................................... Passed 0.00 sec + Start 107: MaxFlow.AsymmetricCapacity_1to100_EqualBalanced + 30/170 Test #149: MaskingTests.MaskedSourceInComputeMinCut .......................................... Passed 0.00 sec + Start 109: MaxFlow.ZeroCapacityPath_CorrectFiltering + 31/170 Test #126: MaxFlow.Triangle_Topology_Combine_Mode ............................................ Passed 0.00 sec + Start 155: MaskingTests.MultipleEdgesMasked + 32/170 Test #103: MaxFlow.ECMP_FourPaths_ClosFabric_Simulation ...................................... Passed 0.00 sec + Start 122: MaxFlow.GridGraph_3x3_MultipleEqualCostPaths + 33/170 Test #107: MaxFlow.AsymmetricCapacity_1to100_EqualBalanced ................................... Passed 0.00 sec + Start 42: ShortestPaths.EarlyExitOptimization + 34/170 Test #109: MaxFlow.ZeroCapacityPath_CorrectFiltering ......................................... Passed 0.00 sec + Start 64: FlowState.MinCutComputation + 35/170 Test #155: MaskingTests.MultipleEdgesMasked .................................................. Passed 0.00 sec + 36/170 Test #122: MaxFlow.GridGraph_3x3_MultipleEqualCostPaths ...................................... Passed 0.00 sec + Start 75: FlowState.Proportional_ZeroCapacityOnShortestPath_ReturnsZero + Start 29: StrictMultiDiGraph.ExtEdgeIdsWrongLengthThrows + 37/170 Test #42: ShortestPaths.EarlyExitOptimization ............................................... Passed 0.00 sec + Start 32: StrictMultiDiGraph.NegativeCostThrows + 38/170 Test #64: FlowState.MinCutComputation ....................................................... Passed 0.00 sec + Start 135: KShortestPaths.FindsKPaths + 39/170 Test #75: FlowState.Proportional_ZeroCapacityOnShortestPath_ReturnsZero ..................... Passed 0.00 sec + Start 99: MaxFlow.ECMP_TwoPaths_Proportional_ShortestPath + 40/170 Test #29: StrictMultiDiGraph.ExtEdgeIdsWrongLengthThrows .................................... Passed 0.00 sec + Start 21: StrictMultiDiGraph.EdgeSortingByCost + 41/170 Test #32: StrictMultiDiGraph.NegativeCostThrows ............................................. Passed 0.00 sec + Start 7: FlowPolicyCore.EqualBalanced_SingleDemand_FlowCount3_SaturatesBothPaths + 42/170 Test #135: KShortestPaths.FindsKPaths ........................................................ Passed 0.00 sec + Start 37: ShortestPaths.DisconnectedComponents + 43/170 Test #99: MaxFlow.ECMP_TwoPaths_Proportional_ShortestPath ................................... Passed 0.00 sec + Start 69: FlowState.ApplyDeltasClampsWithinCapacityBounds + 44/170 Test #21: StrictMultiDiGraph.EdgeSortingByCost .............................................. Passed 0.00 sec + Start 143: KShortestPaths.OutOfOrderNodePredDAGSemantics + 45/170 Test #7: FlowPolicyCore.EqualBalanced_SingleDemand_FlowCount3_SaturatesBothPaths ........... Passed 0.00 sec + Start 134: MaxFlow.CompletionPhase_RespectsNodeMask + 46/170 Test #37: ShortestPaths.DisconnectedComponents .............................................. Passed 0.00 sec + Start 68: FlowState.ResetWithInvalidResidualThrows + 47/170 Test #69: FlowState.ApplyDeltasClampsWithinCapacityBounds ................................... Passed 0.00 sec + Start 46: ShortestPaths.ResolveToPathsSplittingParallelEdges + 48/170 Test #143: KShortestPaths.OutOfOrderNodePredDAGSemantics ..................................... Passed 0.00 sec + Start 112: MaxFlow.EqualCost_ShortestVsFull_Equivalent + 49/170 Test #134: MaxFlow.CompletionPhase_RespectsNodeMask .......................................... Passed 0.00 sec + Start 157: MaskingTests.NodeMaskOverridesEdgeMask + 50/170 Test #68: FlowState.ResetWithInvalidResidualThrows .......................................... Passed 0.00 sec + Start 153: MaskingTests.MaskedEdgeBlocksPath + 51/170 Test #46: ShortestPaths.ResolveToPathsSplittingParallelEdges ................................ Passed 0.00 sec + Start 133: MaxFlow.CompletionPhase_RecoversCancellation + 52/170 Test #112: MaxFlow.EqualCost_ShortestVsFull_Equivalent ....................................... Passed 0.00 sec + Start 35: StrictMultiDiGraph.MultipleCostTiers + 53/170 Test #157: MaskingTests.NodeMaskOverridesEdgeMask ............................................ Passed 0.00 sec + Start 71: FlowState.EqualBalanced_ECMP3_FirstHopEqualization + 54/170 Test #153: MaskingTests.MaskedEdgeBlocksPath ................................................. Passed 0.00 sec + Start 27: StrictMultiDiGraph.InvalidNumNodesThrows + 55/170 Test #133: MaxFlow.CompletionPhase_RecoversCancellation ...................................... Passed 0.00 sec + Start 114: MaxFlow.PlacementModes_EqualCapacity_IdenticalResult + 56/170 Test #35: StrictMultiDiGraph.MultipleCostTiers .............................................. Passed 0.00 sec + Start 91: FlowGraph.LedgerHistory_RemovalRestoresResidual + 57/170 Test #71: FlowState.EqualBalanced_ECMP3_FirstHopEqualization ................................ Passed 0.00 sec + Start 20: StrictMultiDiGraph.ParallelEdges + 58/170 Test #27: StrictMultiDiGraph.InvalidNumNodesThrows .......................................... Passed 0.00 sec + Start 63: FlowState.ApplyDeltasSubtractive + 59/170 Test #114: MaxFlow.PlacementModes_EqualCapacity_IdenticalResult .............................. Passed 0.00 sec + Start 31: StrictMultiDiGraph.NegativeCapacityThrows + 60/170 Test #91: FlowGraph.LedgerHistory_RemovalRestoresResidual ................................... Passed 0.00 sec + Start 2: FlowPolicyCore.Proportional_SingleDemand_UsesShortestPath + 61/170 Test #20: StrictMultiDiGraph.ParallelEdges .................................................. Passed 0.00 sec + Start 5: FlowPolicyCore.Proportional_SingleDemand_PartialPlacement_InsufficientCapacity + 62/170 Test #63: FlowState.ApplyDeltasSubtractive .................................................. Passed 0.00 sec + Start 150: MaskingTests.OutOfRangeSourceInComputeMinCut + 63/170 Test #31: StrictMultiDiGraph.NegativeCapacityThrows ......................................... Passed 0.00 sec + Start 100: MaxFlow.ECMP_TwoPaths_Proportional_FullMaxFlow + 64/170 Test #2: FlowPolicyCore.Proportional_SingleDemand_UsesShortestPath ......................... Passed 0.00 sec + Start 76: FlowState.RepeatedPlacementAfterResetAndIndependentInstancesStayStable + 65/170 Test #5: FlowPolicyCore.Proportional_SingleDemand_PartialPlacement_InsufficientCapacity .... Passed 0.00 sec + Start 121: MaxFlow.BatchMaxFlow_IndependentMaskApplication + 66/170 Test #150: MaskingTests.OutOfRangeSourceInComputeMinCut ...................................... Passed 0.00 sec + Start 117: MaxFlow.CostDistribution_AccountsForAllFlow + 67/170 Test #100: MaxFlow.ECMP_TwoPaths_Proportional_FullMaxFlow .................................... Passed 0.00 sec + Start 113: MaxFlow.ThreeCostTiers_ShortestPath_LowestTierOnly + 68/170 Test #76: FlowState.RepeatedPlacementAfterResetAndIndependentInstancesStayStable ............ Passed 0.00 sec + Start 23: StrictMultiDiGraph.CSROffsetsMonotonicity + 69/170 Test #121: MaxFlow.BatchMaxFlow_IndependentMaskApplication ................................... Passed 0.00 sec + Start 48: ShortestPaths.LargeGraphStressTest + 70/170 Test #117: MaxFlow.CostDistribution_AccountsForAllFlow ....................................... Passed 0.00 sec + Start 58: FlowState.PlacementReducesResidual + 71/170 Test #113: MaxFlow.ThreeCostTiers_ShortestPath_LowestTierOnly ................................ Passed 0.00 sec + Start 4: FlowPolicyCore.Proportional_SingleDemand_MaxFlowCount1_UsesSinglePath + 72/170 Test #23: StrictMultiDiGraph.CSROffsetsMonotonicity ......................................... Passed 0.00 sec + Start 59: FlowState.ProportionalDistribution + 73/170 Test #48: ShortestPaths.LargeGraphStressTest ................................................ Passed 0.00 sec + Start 130: MaxFlow.Sensitivity_TwoParallelPaths + 74/170 Test #58: FlowState.PlacementReducesResidual ................................................ Passed 0.00 sec + Start 6: FlowPolicyCore.EqualBalanced_SingleDemand_FlowCount2_BalancedDistribution + 75/170 Test #4: FlowPolicyCore.Proportional_SingleDemand_MaxFlowCount1_UsesSinglePath ............. Passed 0.00 sec + Start 44: ShortestPaths.TieBreakingDeterminism + 76/170 Test #59: FlowState.ProportionalDistribution ................................................ Passed 0.00 sec + Start 140: KShortestPaths.PathsSortedByCost + 77/170 Test #130: MaxFlow.Sensitivity_TwoParallelPaths .............................................. Passed 0.00 sec + Start 158: MaskingTests.MaskWithResidualCapacity + 78/170 Test #6: FlowPolicyCore.EqualBalanced_SingleDemand_FlowCount2_BalancedDistribution ......... Passed 0.00 sec + Start 39: ShortestPaths.ResidualAwareFiltering + 79/170 Test #44: ShortestPaths.TieBreakingDeterminism .............................................. Passed 0.00 sec + Start 161: MaskingTests.KSPWithEdgeMask + 80/170 Test #140: KShortestPaths.PathsSortedByCost .................................................. Passed 0.00 sec + Start 162: MaskingTests.MaxFlowWithNodeMask + 81/170 Test #158: MaskingTests.MaskWithResidualCapacity ............................................. Passed 0.00 sec + Start 127: MaxFlow.SimpleParallelPaths_Topology + 82/170 Test #39: ShortestPaths.ResidualAwareFiltering .............................................. Passed 0.00 sec + Start 49: ShortestPaths.RejectsMaskLengthMismatch + 83/170 Test #161: MaskingTests.KSPWithEdgeMask ...................................................... Passed 0.00 sec + Start 137: KShortestPaths.NodeMaskBlocksPaths + 84/170 Test #162: MaskingTests.MaxFlowWithNodeMask .................................................. Passed 0.00 sec + Start 18: StrictMultiDiGraph.SingleNode + 85/170 Test #127: MaxFlow.SimpleParallelPaths_Topology .............................................. Passed 0.00 sec + Start 108: MaxFlow.EqualBalanced_NodeMask_ReducesECMPWidth + 86/170 Test #49: ShortestPaths.RejectsMaskLengthMismatch ........................................... Passed 0.00 sec + Start 88: FlowGraph.GetFlowPathForLinearFlow + 87/170 Test #137: KShortestPaths.NodeMaskBlocksPaths ................................................ Passed 0.00 sec + Start 160: MaskingTests.KSPWithNodeMask + 88/170 Test #18: StrictMultiDiGraph.SingleNode ..................................................... Passed 0.00 sec + Start 50: ShortestPaths.ZeroCostEdges_PredDAGIsAcyclic + 89/170 Test #108: MaxFlow.EqualBalanced_NodeMask_ReducesECMPWidth ................................... Passed 0.00 sec + Start 3: FlowPolicyCore.Proportional_SingleDemand_SplitsAcrossTwoEqualCostPaths + 90/170 Test #88: FlowGraph.GetFlowPathForLinearFlow ................................................ Passed 0.00 sec + Start 142: KShortestPaths.LooplessPaths + 91/170 Test #160: MaskingTests.KSPWithNodeMask ...................................................... Passed 0.00 sec + Start 116: MaxFlow.MinCut_ValidEdgeIdentification + 92/170 Test #50: ShortestPaths.ZeroCostEdges_PredDAGIsAcyclic ...................................... Passed 0.00 sec + Start 36: ShortestPaths.SingleSourceAllNodes + 93/170 Test #3: FlowPolicyCore.Proportional_SingleDemand_SplitsAcrossTwoEqualCostPaths ............ Passed 0.00 sec + Start 136: KShortestPaths.KEqualsZeroReturnsEmpty + 94/170 Test #142: KShortestPaths.LooplessPaths ...................................................... Passed 0.00 sec + Start 38: ShortestPaths.MultipleEqualCostPaths + 95/170 Test #116: MaxFlow.MinCut_ValidEdgeIdentification ............................................ Passed 0.00 sec + Start 111: MaxFlow.TwoCostTiers_FullMaxFlow_AllTiers + 96/170 Test #36: ShortestPaths.SingleSourceAllNodes ................................................ Passed 0.00 sec + Start 24: StrictMultiDiGraph.CSRReverseAdjacency + 97/170 Test #136: KShortestPaths.KEqualsZeroReturnsEmpty ............................................ Passed 0.00 sec + Start 97: MaxFlow.SinglePath_ShortestPathEquivalence + 98/170 Test #38: ShortestPaths.MultipleEqualCostPaths .............................................. Passed 0.00 sec + Start 90: FlowGraph.CoalescesDuplicateEdgeIds + 99/170 Test #111: MaxFlow.TwoCostTiers_FullMaxFlow_AllTiers ......................................... Passed 0.00 sec + Start 146: MaskingTests.MaskedSourceReturnsEmptyDAG +100/170 Test #24: StrictMultiDiGraph.CSRReverseAdjacency ............................................ Passed 0.00 sec + Start 28: StrictMultiDiGraph.MismatchedArrayLengthsThrow +101/170 Test #97: MaxFlow.SinglePath_ShortestPathEquivalence ........................................ Passed 0.00 sec + Start 124: MaxFlow.Clos_3Tier_Topology_Proportional_Shortest +102/170 Test #90: FlowGraph.CoalescesDuplicateEdgeIds ............................................... Passed 0.00 sec + Start 131: MaxFlow.Sensitivity_PartialSaturation +103/170 Test #146: MaskingTests.MaskedSourceReturnsEmptyDAG .......................................... Passed 0.00 sec + Start 110: MaxFlow.TwoCostTiers_ShortestPath_SingleTierOnly +104/170 Test #28: StrictMultiDiGraph.MismatchedArrayLengthsThrow .................................... Passed 0.00 sec + Start 129: MaxFlow.Sensitivity_SinglePath +105/170 Test #124: MaxFlow.Clos_3Tier_Topology_Proportional_Shortest ................................. Passed 0.00 sec + Start 120: MaxFlow.EdgeMask_SelectiveEdgeFiltering +106/170 Test #131: MaxFlow.Sensitivity_PartialSaturation ............................................. Passed 0.00 sec + Start 45: ShortestPaths.PreferHigherResidualTieBreak +107/170 Test #110: MaxFlow.TwoCostTiers_ShortestPath_SingleTierOnly .................................. Passed 0.00 sec + Start 25: StrictMultiDiGraph.MaxCapacityEdges +108/170 Test #129: MaxFlow.Sensitivity_SinglePath .................................................... Passed 0.00 sec + Start 57: FlowState.InitialResidualEqualsCapacity +109/170 Test #120: MaxFlow.EdgeMask_SelectiveEdgeFiltering ........................................... Passed 0.00 sec + Start 123: MaxFlow.SharedBottleneck_MultiplePathsMerge +110/170 Test #45: ShortestPaths.PreferHigherResidualTieBreak ........................................ Passed 0.00 sec + Start 40: ShortestPaths.NodeMaskIsolation +111/170 Test #25: StrictMultiDiGraph.MaxCapacityEdges ............................................... Passed 0.00 sec + Start 125: MaxFlow.Clos_3Tier_Topology_EqualBalanced_Shortest +112/170 Test #57: FlowState.InitialResidualEqualsCapacity ........................................... Passed 0.00 sec + Start 128: MaxFlow.ShortestPath_MustSaturateAllEqualCostPaths +113/170 Test #123: MaxFlow.SharedBottleneck_MultiplePathsMerge ....................................... Passed 0.00 sec + Start 159: MaskingTests.ResidualAndNodeMaskCombined +114/170 Test #40: ShortestPaths.NodeMaskIsolation ................................................... Passed 0.00 sec + Start 74: FlowState.EqualBalanced_ZeroCapacityOnShortestPath_ReturnsZero +115/170 Test #125: MaxFlow.Clos_3Tier_Topology_EqualBalanced_Shortest ................................ Passed 0.00 sec + Start 147: MaskingTests.MaskedSourceWithDestination +116/170 Test #128: MaxFlow.ShortestPath_MustSaturateAllEqualCostPaths ................................ Passed 0.00 sec + Start 70: FlowState.EqualBalancedReconvergentDAGPlacesAll +117/170 Test #159: MaskingTests.ResidualAndNodeMaskCombined .......................................... Passed 0.00 sec + Start 84: FlowGraph.PlacementCreatesEntry +118/170 Test #74: FlowState.EqualBalanced_ZeroCapacityOnShortestPath_ReturnsZero .................... Passed 0.00 sec + Start 62: FlowState.ApplyDeltasAdditive +119/170 Test #147: MaskingTests.MaskedSourceWithDestination .......................................... Passed 0.00 sec + Start 65: FlowState.ResetRestoresCapacity +120/170 Test #70: FlowState.EqualBalancedReconvergentDAGPlacesAll ................................... Passed 0.00 sec + Start 19: StrictMultiDiGraph.SingleEdge +121/170 Test #84: FlowGraph.PlacementCreatesEntry ................................................... Passed 0.00 sec + Start 139: KShortestPaths.MaxCostFactorLimit +122/170 Test #62: FlowState.ApplyDeltasAdditive ..................................................... Passed 0.00 sec + Start 30: StrictMultiDiGraph.OutOfRangeNodeThrows +123/170 Test #65: FlowState.ResetRestoresCapacity ................................................... Passed 0.00 sec + Start 60: FlowState.EqualBalancedDistribution +124/170 Test #19: StrictMultiDiGraph.SingleEdge ..................................................... Passed 0.00 sec + Start 151: MaskingTests.MaskedDestinationUnreachable +125/170 Test #139: KShortestPaths.MaxCostFactorLimit ................................................. Passed 0.00 sec + Start 96: MaxFlow.SinglePath_BottleneckConstraint +126/170 Test #30: StrictMultiDiGraph.OutOfRangeNodeThrows ........................................... Passed 0.00 sec + Start 66: FlowState.CustomInitialResidual +127/170 Test #60: FlowState.EqualBalancedDistribution ............................................... Passed 0.00 sec + Start 101: MaxFlow.ECMP_TwoPaths_EqualBalanced_ShortestPath +128/170 Test #151: MaskingTests.MaskedDestinationUnreachable ......................................... Passed 0.00 sec + Start 115: MaxFlow.FlowConservation_IntermediateNodes +129/170 Test #96: MaxFlow.SinglePath_BottleneckConstraint ........................................... Passed 0.00 sec + Start 102: MaxFlow.ECMP_ThreePaths_Proportional_ShortestPath +130/170 Test #66: FlowState.CustomInitialResidual ................................................... Passed 0.00 sec + Start 26: StrictMultiDiGraph.ZeroCostEdges +131/170 Test #101: MaxFlow.ECMP_TwoPaths_EqualBalanced_ShortestPath .................................. Passed 0.00 sec + Start 95: MaxFlow.SinglePath_BasicLinear +132/170 Test #115: MaxFlow.FlowConservation_IntermediateNodes ........................................ Passed 0.00 sec + Start 72: FlowState.EqualBalanced_MinFlowGating_DoesNotPruneValidParallelEdges +133/170 Test #102: MaxFlow.ECMP_ThreePaths_Proportional_ShortestPath ................................. Passed 0.00 sec + Start 98: MaxFlow.DegenerateCase_SourceEqualsSink +134/170 Test #26: StrictMultiDiGraph.ZeroCostEdges .................................................. Passed 0.00 sec + Start 86: FlowGraph.RemoveByClassFiltersCorrectly +135/170 Test #95: MaxFlow.SinglePath_BasicLinear .................................................... Passed 0.00 sec + Start 73: FlowState.EqualBalanced_DownstreamSplitEqualization +136/170 Test #72: FlowState.EqualBalanced_MinFlowGating_DoesNotPruneValidParallelEdges .............. Passed 0.00 sec + Start 119: MaxFlow.NodeMask_BlocksFlowThroughNode +137/170 Test #98: MaxFlow.DegenerateCase_SourceEqualsSink ........................................... Passed 0.00 sec + Start 85: FlowGraph.RemovalDeletesEntry +138/170 Test #86: FlowGraph.RemoveByClassFiltersCorrectly ........................................... Passed 0.00 sec + Start 87: FlowGraph.GetFlowEdgesReturnsDeltas +139/170 Test #73: FlowState.EqualBalanced_DownstreamSplitEqualization ............................... Passed 0.00 sec + Start 163: MaskingTests.MaxFlowWithEdgeMask +140/170 Test #119: MaxFlow.NodeMask_BlocksFlowThroughNode ............................................ Passed 0.00 sec + Start 164: MaskingTests.MaxFlowAllPathsMasked +141/170 Test #85: FlowGraph.RemovalDeletesEntry ..................................................... Passed 0.00 sec + Start 165: MaskingTests.EmptyNodeMaskAllowsAllNodes +142/170 Test #87: FlowGraph.GetFlowEdgesReturnsDeltas ............................................... Passed 0.00 sec + Start 12: FlowPolicyStatic.PerFlowBundleBinding +143/170 Test #163: MaskingTests.MaxFlowWithEdgeMask .................................................. Passed 0.00 sec + Start 169: MaskingTests.AlgorithmsAPIMaskedSource +144/170 Test #164: MaskingTests.MaxFlowAllPathsMasked ................................................ Passed 0.00 sec + Start 13: FlowPolicyStatic.MaskedBundleIsDown +145/170 Test #165: MaskingTests.EmptyNodeMaskAllowsAllNodes .......................................... Passed 0.00 sec + Start 15: FlowPolicyCostBounds.MaxPathCostFactor_UnreachableDst_KeepsSentinelOutOfTheCast +146/170 Test #12: FlowPolicyStatic.PerFlowBundleBinding ............................................. Passed 0.00 sec + Start 14: FlowPolicyStatic.ValidationRejectsForeignAndDisconnectedBundles +147/170 Test #169: MaskingTests.AlgorithmsAPIMaskedSource ............................................ Passed 0.00 sec + Start 55: ShortestPathsTo.FanoutFromInteriorNodeIsRejected +148/170 Test #13: FlowPolicyStatic.MaskedBundleIsDown ............................................... Passed 0.00 sec + Start 51: ShortestPathsTo.DistancesMatchForwardDistancesToDst +149/170 Test #15: FlowPolicyCostBounds.MaxPathCostFactor_UnreachableDst_KeepsSentinelOutOfTheCast ... Passed 0.00 sec + Start 166: MaskingTests.EmptyEdgeMaskAllowsAllEdges +150/170 Test #14: FlowPolicyStatic.ValidationRejectsForeignAndDisconnectedBundles ................... Passed 0.00 sec + Start 81: FlowState.EqualBalancedLossy_InfiniteRequestFillsWithoutDrops +151/170 Test #55: ShortestPathsTo.FanoutFromInteriorNodeIsRejected .................................. Passed 0.00 sec + Start 79: FlowState.EqualBalancedLossy_FillAndDropReportsDrops +152/170 Test #51: ShortestPathsTo.DistancesMatchForwardDistancesToDst ............................... Passed 0.00 sec + Start 82: FlowGraph.LossyPlacementIsReversibleAndDropsStayOutOfLedger +153/170 Test #166: MaskingTests.EmptyEdgeMaskAllowsAllEdges .......................................... Passed 0.00 sec + Start 16: FlowPolicyCostBounds.MaxPathCostFactor_HugeProduct_DropsBoundInsteadOfWrapping +154/170 Test #81: FlowState.EqualBalancedLossy_InfiniteRequestFillsWithoutDrops ..................... Passed 0.00 sec + Start 52: ShortestPathsTo.ForwardSpfFromPseudoSourceKeepsOnlyNearestSource +155/170 Test #79: FlowState.EqualBalancedLossy_FillAndDropReportsDrops .............................. Passed 0.00 sec + Start 170: MaskingTests.AlgorithmsAPIMaxFlowWithMask +156/170 Test #82: FlowGraph.LossyPlacementIsReversibleAndDropsStayOutOfLedger ....................... Passed 0.00 sec + Start 94: FlowGraphStamp.EqualVersionDivergentCopiesCompareUnequal +157/170 Test #16: FlowPolicyCostBounds.MaxPathCostFactor_HugeProduct_DropsBoundInsteadOfWrapping .... Passed 0.00 sec + Start 167: MaskingTests.AllNodesMaskedNoReachability +158/170 Test #52: ShortestPathsTo.ForwardSpfFromPseudoSourceKeepsOnlyNearestSource .................. Passed 0.00 sec + Start 168: MaskingTests.AllEdgesMaskedNoReachability +159/170 Test #170: MaskingTests.AlgorithmsAPIMaxFlowWithMask ......................................... Passed 0.00 sec + Start 80: FlowState.EqualBalancedLossy_DeficitPropagatesDownstream +160/170 Test #94: FlowGraphStamp.EqualVersionDivergentCopiesCompareUnequal .......................... Passed 0.00 sec + Start 53: ShortestPathsTo.FanoutEdgesForceEverySourceIntoTheDag +161/170 Test #167: MaskingTests.AllNodesMaskedNoReachability ......................................... Passed 0.00 sec + Start 93: FlowGraphStamp.CopiesAndMovesGetFreshUids +162/170 Test #168: MaskingTests.AllEdgesMaskedNoReachability ......................................... Passed 0.00 sec + Start 145: KSP.MaxCostFactorBelowOne_ReturnsEmptyForAllK +163/170 Test #80: FlowState.EqualBalancedLossy_DeficitPropagatesDownstream .......................... Passed 0.00 sec + Start 77: FlowState.EqualBalanced_SaturatedMemberBlocksAdmission +164/170 Test #53: ShortestPathsTo.FanoutEdgesForceEverySourceIntoTheDag ............................. Passed 0.00 sec + Start 54: ShortestPathsTo.FanoutSkipsUnreachableAndMaskedHeads +165/170 Test #93: FlowGraphStamp.CopiesAndMovesGetFreshUids ......................................... Passed 0.00 sec + Start 78: FlowState.EqualBalanced_ProgressesOnlyThroughResidualAwareSpf +166/170 Test #145: KSP.MaxCostFactorBelowOne_ReturnsEmptyForAllK ..................................... Passed 0.00 sec + Start 56: ShortestPathsTo.SinglePathModeKeepsOneSuccessorPerNode +167/170 Test #77: FlowState.EqualBalanced_SaturatedMemberBlocksAdmission ............................ Passed 0.00 sec +168/170 Test #54: ShortestPathsTo.FanoutSkipsUnreachableAndMaskedHeads .............................. Passed 0.00 sec +169/170 Test #78: FlowState.EqualBalanced_ProgressesOnlyThroughResidualAwareSpf ..................... Passed 0.00 sec +170/170 Test #56: ShortestPathsTo.SinglePathModeKeepsOneSuccessorPerNode ............................ Passed 0.00 sec + +100% tests passed out of 170 + +Total Test time (real) = 0.13 sec +........................................................................ [ 15%] +........................................................................ [ 30%] +........................................................................ [ 46%] +........................................................................ [ 61%] +........................................................................ [ 77%] +........................................................................ [ 92%] +................................. [100%] +465 passed in 3.91s diff --git a/dev/research/metal_pathfinding/optimization/run_aba.sh b/dev/research/metal_pathfinding/optimization/run_aba.sh new file mode 100644 index 0000000..7c041d9 --- /dev/null +++ b/dev/research/metal_pathfinding/optimization/run_aba.sh @@ -0,0 +1,30 @@ +#!/usr/bin/env bash +# Run sequentially on the same machine. Do not overlap with builds or tests. +set -euo pipefail +cd "$(dirname "$0")/../../.." +out=${1:-dev/research/metal_pathfinding/optimization/results/aba} +mkdir -p "$out" +unset NGRAPH_CORE_PROFILE +{ + date -u '+%Y-%m-%dT%H:%M:%SZ' + git rev-parse HEAD + sw_vers + sysctl -n machdep.cpu.brand_string hw.memsize hw.ncpu + xcrun clang++ --version + shasum -a 256 dev/research/metal_pathfinding/experiment.mm dev/research/metal_pathfinding/sssp.metal \ + dev/research/metal_pathfinding/optimization/experiment.mm dev/research/metal_pathfinding/optimization/kernels.metal \ + build/metal_pathfinding/optimized + pmset -g therm +} > "$out/environment.txt" +for phase in cpu-a1 base-a1 optimized-b base-a2 cpu-a2; do + top -l 2 -n 8 -o cpu -stats pid,command,cpu,threads > "$out/load-$phase.txt" + ioreg -r -c AGXAccelerator -l | sed -n '/"PerformanceStatistics"/p' > "$out/gpu-load-$phase.txt" + case "$phase" in + cpu-*) mode=cpu ;; + base-*) mode=base ;; + optimized-b) mode=optimized ;; + esac + date -u '+%Y-%m-%dT%H:%M:%SZ' > "$out/time-$phase.txt" + build/metal_pathfinding/optimized "$mode" full 7 > "$out/$phase.csv" 2> "$out/$phase-stderr.txt" + date -u '+%Y-%m-%dT%H:%M:%SZ' >> "$out/time-$phase.txt" +done diff --git a/dev/research/metal_pathfinding/optimization/run_cpu_aba.sh b/dev/research/metal_pathfinding/optimization/run_cpu_aba.sh new file mode 100644 index 0000000..a15f747 --- /dev/null +++ b/dev/research/metal_pathfinding/optimization/run_cpu_aba.sh @@ -0,0 +1,21 @@ +#!/usr/bin/env bash +set -euo pipefail +cd "$(dirname "$0")/../../.." +out=dev/research/metal_pathfinding/optimization/results/cpu-algorithms-aba +mkdir -p "$out" +unset NGRAPH_CORE_PROFILE +{ + date -u '+%Y-%m-%dT%H:%M:%SZ' + git rev-parse HEAD + shasum -a 256 dev/research/metal_pathfinding/optimization/cpu_algorithms.mm \ + build/metal_pathfinding/cpu-algorithms build/metal_pathfinding/optimized +} > "$out/environment.txt" +for phase in a1 b a2; do + top -l 2 -n 8 -o cpu -stats pid,command,cpu,threads > "$out/load-$phase.txt" + ioreg -r -c AGXAccelerator -l | sed -n '/"PerformanceStatistics"/p' > "$out/gpu-load-$phase.txt" + if [[ $phase == b ]]; then + build/metal_pathfinding/optimized optimized full 7 > "$out/$phase.csv" 2> "$out/$phase-stderr.txt" + else + build/metal_pathfinding/cpu-algorithms 7 > "$out/$phase.csv" 2> "$out/$phase-stderr.txt" + fi +done diff --git a/dev/research/metal_pathfinding/optimization/summarize.py b/dev/research/metal_pathfinding/optimization/summarize.py new file mode 100644 index 0000000..2dd648f --- /dev/null +++ b/dev/research/metal_pathfinding/optimization/summarize.py @@ -0,0 +1,106 @@ +#!/usr/bin/env python3 +"""Produce auditable tables from all five sequential benchmark phases.""" + +import csv +import json +from pathlib import Path + +ROOT = Path(__file__).resolve().parent / "results" / "aba" +PHASES = ("cpu-a1", "base-a1", "optimized-b", "base-a2", "cpu-a2") +rows = {p: list(csv.DictReader((ROOT / f"{p}.csv").open())) for p in PHASES} +assert [len(rows[p]) for p in PHASES] == [48, 36, 216, 36, 48] +assert all(r["correct"] == "pass" for rs in rows.values() for r in rs) + + +def key(r): + return tuple(r[k] for k in ("case", "n", "e", "queries")) + + +def table(phase, case): + return {r["method"]: r for r in rows[phase] if key(r) == case} + + +def elapsed(r): + return float(r["wall_ms"]) + + +keys = list(dict.fromkeys(key(r) for r in rows["optimized-b"])) +lines = [ + "# Exploratory A/B/A measurements", + "", + "Warm full-result latency in ms, including host distances and positive-cost predecessor DAG. " + "Seven measured samples plus two checked warmups per row. CPU batches use 10 reusable workers. " + "Best variant is selected after measurement; this is an oracle comparison, not an implemented dispatcher. " + "Old GPU columns cover the original pull and group variants; the shared-memory variant was not rerun. " + "The machine was not isolated; these are not accepted performance claims.", + "", + "| Case | N / E / Q | CPU full A1 / A2 | Old GPU A1 / A2 | Best tested optimized GPU | ms | CPU BFS full A1 / A2 |", + "|---|---:|---:|---:|---|---:|---:|", +] +summary = [] +for k in keys: + ca, cb, a, b, c = ( + table(p, k) for p in ("cpu-a1", "cpu-a2", "base-a1", "optimized-b", "base-a2") + ) + # Choose one old algorithm by its mean of A1/A2, then show both measurements. + old = min(a, key=lambda name: (elapsed(a[name]) + elapsed(c[name])) / 2) + best = min(b, key=lambda name: elapsed(b[name])) + best_label = best + ( + " (64-bit pull fallback)" if b[best]["fallback64"] == "1" else "" + ) + bfs = ( + f"{elapsed(ca['cpu_bfs_full']):.3f} / {elapsed(cb['cpu_bfs_full']):.3f}" + if "cpu_bfs_full" in ca + else "—" + ) + lines.append( + f"| {k[0]} | {' / '.join(k[1:])} | {elapsed(ca['cpu_full']):.3f} / {elapsed(cb['cpu_full']):.3f} | " + f"{elapsed(a[old]):.3f} / {elapsed(c[old]):.3f} | {best_label} | {elapsed(b[best]):.3f} | {bfs} |" + ) + summary.append( + { + "case": k, + "cpu_a1": elapsed(ca["cpu_full"]), + "cpu_a2": elapsed(cb["cpu_full"]), + "old_method": old, + "old_a1": elapsed(a[old]), + "old_a2": elapsed(c[old]), + "best": b[best], + } + ) + +lines += [ + "", + "## All optimized variants", + "", + "No variants omitted. Columns: full wall / distance wall / device work, ms. " + "Device work includes DAG kernels where selected. Edge visits count SSSP adjacency entries, " + "excluding bucket vertex scans, queue management and DAG extraction.", + "", +] +for k in keys: + lines += [ + f"### {k}", + "", + "| Variant | Full / distance / device ms | Edge visits | Rounds | Host waits | 64-bit fallback |", + "|---|---:|---:|---:|---:|---|", + ] + for r in table("optimized-b", k).values(): + times = " / ".join( + f"{float(r[f]):.3f}" for f in ("wall_ms", "distance_ms", "gpu_ms") + ) + lines.append( + f"| {r['method']} | {times} | {r['edge_visits']} | {r['rounds']} | {r['waits']} | {r['fallback64']} |" + ) + +checks = sum( + (int(r["samples"]) + 2) * int(r["queries"]) for rs in rows.values() for r in rs +) +audit = { + "phase_rows": {p: len(rs) for p, rs in rows.items()}, + "checked_query_results": checks, + "summary": summary, +} +(ROOT / "summary.md").write_text("\n".join(lines) + "\n") +(ROOT / "summary.json").write_text(json.dumps(audit, indent=2) + "\n") +print(json.dumps({k: v for k, v in audit.items() if k != "summary"}, indent=2)) diff --git a/dev/research/metal_pathfinding/optimization/summarize_cpu.py b/dev/research/metal_pathfinding/optimization/summarize_cpu.py new file mode 100644 index 0000000..b815c3d --- /dev/null +++ b/dev/research/metal_pathfinding/optimization/summarize_cpu.py @@ -0,0 +1,54 @@ +#!/usr/bin/env python3 +"""Stronger CPU algorithm comparison; no production-dispatch claim.""" + +import csv +import json +from pathlib import Path + +root = Path(__file__).resolve().parent / "results/cpu-algorithms-aba" +data = {p: list(csv.DictReader((root / f"{p}.csv").open())) for p in ("a1", "b", "a2")} +assert [len(v) for v in data.values()] == [14, 216, 14] +assert all(r["correct"] == "pass" for rs in data.values() for r in rs) + + +def key(row): + return tuple(row[k] for k in ("case", "n", "e", "queries")) + + +lines = [ + "# Stronger CPU algorithm A/B/A", + "", + "All methods include exact distances and canonical-equivalent positive-cost DAG edge sets. " + "CPU batches use 10 workers. Eligibility is cached outside timing for both devices. " + "Seven measured samples and two checked warmups. These remain exploratory, " + "non-isolated desktop measurements. GPU choice is an oracle across 12 tested variants.", + "", + "| Case / N / E / Q | Cached heap + DAG A1 / A2 ms | Dial + DAG A1 / A2 ms | Best GPU B ms | GPU method |", + "|---|---:|---:|---:|---|", +] +summary = [] +for k in dict.fromkeys(key(r) for r in data["a1"]): + phases = [ + {r["method"]: r for r in data[p] if key(r) == k} for p in ("a1", "b", "a2") + ] + a, b, c = phases + best = min(b.values(), key=lambda r: float(r["wall_ms"])) + heap = [float(p["cpu_heap_cached_full"]["wall_ms"]) for p in (a, c)] + dial = [float(p["cpu_dial_full"]["wall_ms"]) for p in (a, c)] + lines.append( + f"| {' / '.join(k)} | {heap[0]:.3f} / {heap[1]:.3f} | {dial[0]:.3f} / {dial[1]:.3f} | " + f"{float(best['wall_ms']):.3f} | {best['method']} |" + ) + summary.append( + {"case": k, "heap_a1_a2": heap, "dial_a1_a2": dial, "best_gpu": best} + ) +audit = { + "phase_rows": {p: len(v) for p, v in data.items()}, + "checked_query_results": sum( + (int(r["samples"]) + 2) * int(r["queries"]) for rs in data.values() for r in rs + ), + "summary": summary, +} +(root / "summary.md").write_text("\n".join(lines) + "\n") +(root / "summary.json").write_text(json.dumps(audit, indent=2) + "\n") +print("\n".join(lines)) diff --git a/dev/research/metal_pathfinding/results/aba-initial/a1-stderr.txt b/dev/research/metal_pathfinding/results/aba-initial/a1-stderr.txt new file mode 100644 index 0000000..e69de29 diff --git a/dev/research/metal_pathfinding/results/aba-initial/a1.csv b/dev/research/metal_pathfinding/results/aba-initial/a1.csv new file mode 100644 index 0000000..f250b80 --- /dev/null +++ b/dev/research/metal_pathfinding/results/aba-initial/a1.csv @@ -0,0 +1,82 @@ +case,n,e,queries,method,wall_ms,gpu_ms,distance_wall_ms,upload_ms,rounds,samples,correct,exact_order_queries,wall_samples_ms +random,128,1024,1,cpu_full,0.009625,0.000000,0.009625,0.000000,0,9,pass,1,0.009625;0.010542;0.010041;0.013500;0.010292;0.009458;0.009291;0.009250;0.009208 +random,128,1024,1,cpu_distance,0.004541,0.000000,0.004541,0.000000,0,9,pass,0,0.004583;0.005666;0.004417;0.004625;0.004250;0.006458;0.004541;0.004208;0.004167 +random,128,1024,1,cpu_pool10,0.029750,0.000000,0.029750,0.000000,0,9,pass,1,0.030792;0.043125;0.032708;0.027000;0.029750;0.026875;0.034250;0.027000;0.026625 +random,128,1024,64,cpu_full,0.955250,0.000000,0.955250,0.000000,0,9,pass,64,0.973292;0.945083;0.904875;0.882041;1.075791;0.956416;0.955250;0.977375;0.870959 +random,128,1024,64,cpu_distance,0.351959,0.000000,0.351959,0.000000,0,9,pass,0,0.401375;0.351959;0.340208;0.476250;0.456208;0.379709;0.338625;0.344334;0.308541 +random,128,1024,64,cpu_pool10,0.182417,0.000000,0.182417,0.000000,0,9,pass,64,0.182417;0.176833;0.174542;0.182917;0.191750;0.184291;0.197500;0.167458;0.162833 +random,1024,8192,1,cpu_full,0.103583,0.000000,0.103583,0.000000,0,9,pass,1,0.109833;0.110000;0.099291;0.105625;0.104000;0.102792;0.099458;0.102125;0.103583 +random,1024,8192,1,cpu_distance,0.055541,0.000000,0.055541,0.000000,0,9,pass,0,0.059083;0.051542;0.055333;0.055208;0.055541;0.055375;0.055625;0.055833;0.056209 +random,1024,8192,1,cpu_pool10,0.193125,0.000000,0.193125,0.000000,0,9,pass,1,0.200667;0.229666;0.191083;0.194792;0.193125;0.195459;0.165708;0.161917;0.173542 +random,1024,8192,64,cpu_full,10.685667,0.000000,10.685667,0.000000,0,9,pass,64,10.749791;10.777292;11.154708;10.834875;10.685667;10.563875;10.571209;10.589625;10.627750 +random,1024,8192,64,cpu_distance,5.053459,0.000000,5.053459,0.000000,0,9,pass,0,5.145083;5.053459;5.062084;4.993875;5.026833;5.019416;5.055542;4.969833;5.108583 +random,1024,8192,64,cpu_pool10,1.342375,0.000000,1.342375,0.000000,0,9,pass,64,1.372375;1.342916;1.342375;1.338708;1.318542;1.342916;1.354417;1.335167;1.315708 +fabric,288,16384,1,cpu_full,0.112333,0.000000,0.112333,0.000000,0,9,pass,1,0.115083;0.119833;0.110375;0.112667;0.112333;0.118125;0.109709;0.109792;0.109708 +fabric,288,16384,1,cpu_distance,0.023291,0.000000,0.023291,0.000000,0,9,pass,0,0.023709;0.023667;0.023291;0.023542;0.023291;0.023042;0.023208;0.023166;0.023166 +fabric,288,16384,1,cpu_pool10,0.137583,0.000000,0.137583,0.000000,0,9,pass,1,0.135875;0.135667;0.144417;0.132500;0.137583;0.156500;0.146000;0.136291;0.141125 +fabric,288,16384,64,cpu_full,7.318958,0.000000,7.318958,0.000000,0,9,pass,64,7.419667;7.295250;7.297250;7.489000;7.299334;7.340666;7.318958;7.284542;7.324916 +fabric,288,16384,64,cpu_distance,1.489125,0.000000,1.489125,0.000000,0,9,pass,0,1.489125;1.524542;1.487041;1.499584;1.499292;1.478625;1.510084;1.482750;1.483875 +fabric,288,16384,64,cpu_pool10,0.972167,0.000000,0.972167,0.000000,0,9,pass,64,1.685792;1.140875;0.951709;0.972167;0.977500;0.942208;0.959334;0.916959;0.985417 +grid,1024,3968,1,cpu_full,0.043667,0.000000,0.043667,0.000000,0,9,pass,1,0.045750;0.044542;0.043792;0.043459;0.043583;0.044042;0.043625;0.043541;0.043667 +grid,1024,3968,1,cpu_distance,0.011666,0.000000,0.011666,0.000000,0,9,pass,0,0.012583;0.012042;0.012041;0.011791;0.011666;0.011625;0.011500;0.011542;0.011542 +grid,1024,3968,1,cpu_pool10,0.077875,0.000000,0.077875,0.000000,0,9,pass,1,0.088542;0.068417;0.079375;0.062125;0.084667;0.065500;0.078959;0.077875;0.073916 +grid,1024,3968,64,cpu_full,4.005584,0.000000,4.005584,0.000000,0,9,pass,64,4.005584;3.977000;3.994834;3.970583;4.010875;3.966208;4.044791;4.030375;4.086625 +grid,1024,3968,64,cpu_distance,0.894833,0.000000,0.894833,0.000000,0,9,pass,0,0.925833;0.907000;0.899000;0.894833;0.883292;0.896833;0.878750;0.873041;0.874166 +grid,1024,3968,64,cpu_pool10,0.543500,0.000000,0.543500,0.000000,0,9,pass,64,0.584208;0.566875;0.534833;0.544125;0.531250;0.543500;0.529166;0.552875;0.524417 +chain,256,255,1,cpu_full,0.002542,0.000000,0.002542,0.000000,0,9,pass,1,0.002583;0.002542;0.002583;0.002542;0.003458;0.002667;0.002542;0.002500;0.002541 +chain,256,255,1,cpu_distance,0.000708,0.000000,0.000708,0.000000,0,9,pass,0,0.000708;0.000750;0.000708;0.000709;0.000708;0.000750;0.000708;0.000750;0.000708 +chain,256,255,1,cpu_pool10,0.033958,0.000000,0.033958,0.000000,0,9,pass,1,0.039125;0.039375;0.037292;0.036167;0.031041;0.033958;0.033625;0.027333;0.029000 +random_masked_int64_reverse,1024,8192,8,cpu_full,0.581833,0.000000,0.581833,0.000000,0,9,pass,8,0.692791;0.630583;0.611625;0.585000;0.571125;0.565667;0.559791;0.581833;0.555459 +random_masked_int64_reverse,1024,8192,8,cpu_distance,0.303917,0.000000,0.303917,0.000000,0,9,pass,0,0.377291;0.438458;0.395125;0.336584;0.303917;0.289917;0.274959;0.279542;0.270875 +random_masked_int64_reverse,1024,8192,8,cpu_pool10,0.155667,0.000000,0.155667,0.000000,0,9,pass,8,0.154292;0.167333;0.155667;0.155042;0.157458;0.156000;0.155875;0.147917;0.152875 +random,4096,32768,1,cpu_full,0.656542,0.000000,0.656542,0.000000,0,9,pass,1,0.689083;0.693500;0.656542;0.645666;0.662417;0.637500;0.638250;0.636042;0.790125 +random,4096,32768,1,cpu_distance,0.308542,0.000000,0.308542,0.000000,0,9,pass,0,0.338750;0.325250;0.317625;0.308542;0.304625;0.309916;0.303500;0.303042;0.303000 +random,4096,32768,1,cpu_pool10,0.814208,0.000000,0.814208,0.000000,0,9,pass,1,0.826042;0.869667;0.814208;0.765917;0.765084;0.855791;0.743833;0.829917;0.749625 +random,4096,32768,64,cpu_full,52.554875,0.000000,52.554875,0.000000,0,9,pass,64,52.386917;53.197958;52.959833;52.357667;52.261083;51.995125;59.360875;52.554875;52.678667 +random,4096,32768,64,cpu_distance,26.269750,0.000000,26.269750,0.000000,0,9,pass,0,25.927500;26.269750;26.294709;26.415583;26.370750;26.258458;26.318584;26.239250;26.028667 +random,4096,32768,64,cpu_pool10,5.992416,0.000000,5.992416,0.000000,0,9,pass,64,6.017250;6.053250;5.905542;5.941042;5.959459;5.969500;6.017750;6.285584;5.992416 +random,4096,32768,256,cpu_full,208.676542,0.000000,208.676542,0.000000,0,9,pass,256,208.676542;208.153584;208.156916;208.801833;208.602375;208.752792;208.467208;209.713875;210.652583 +random,4096,32768,256,cpu_distance,106.272833,0.000000,106.272833,0.000000,0,9,pass,0,107.689542;106.997833;106.701375;106.272833;105.206709;106.373917;105.998542;104.856041;104.854167 +random,4096,32768,256,cpu_pool10,23.000917,0.000000,23.000917,0.000000,0,9,pass,256,23.054250;23.179708;23.387250;23.000917;22.925084;23.250125;22.768375;22.927834;22.826625 +random,16384,131072,1,cpu_full,3.887250,0.000000,3.887250,0.000000,0,9,pass,1,3.887250;3.999084;3.780250;4.507709;3.907583;3.710875;3.958666;3.830917;3.877834 +random,16384,131072,1,cpu_distance,1.934458,0.000000,1.934458,0.000000,0,9,pass,0,1.934458;1.881542;1.868917;1.983458;2.134000;1.985167;1.920750;1.881125;1.985209 +random,16384,131072,1,cpu_pool10,3.823917,0.000000,3.823917,0.000000,0,9,pass,1,3.823917;3.839416;3.736166;3.679167;3.695708;3.719167;4.268541;3.980250;3.967292 +random,16384,131072,64,cpu_full,256.127917,0.000000,256.127917,0.000000,0,9,pass,64,259.340500;260.231959;254.190417;252.847166;253.639917;258.855125;261.257792;256.016375;256.127917 +random,16384,131072,64,cpu_distance,134.498459,0.000000,134.498459,0.000000,0,9,pass,0,135.160625;136.307417;137.394250;133.758792;133.098583;134.069500;135.485167;133.665375;134.498459 +random,16384,131072,64,cpu_pool10,28.586375,0.000000,28.586375,0.000000,0,9,pass,64,30.187666;28.698666;28.505708;28.563916;28.892208;28.586375;28.463583;28.565541;28.662417 +random,65536,524288,1,cpu_full,22.864166,0.000000,22.864166,0.000000,0,9,pass,1,21.392875;21.666875;22.864166;23.888750;23.744625;23.006084;24.381000;22.531041;22.057541 +random,65536,524288,1,cpu_distance,12.154417,0.000000,12.154417,0.000000,0,9,pass,0,12.221916;13.038792;11.681125;11.504500;12.697750;12.154417;11.320417;11.733250;12.544542 +random,65536,524288,1,cpu_pool10,22.800125,0.000000,22.800125,0.000000,0,9,pass,1,21.551917;21.493292;23.056834;25.353791;23.876125;22.366334;22.800125;23.572000;22.615292 +random,65536,524288,64,cpu_full,1421.675417,0.000000,1421.675417,0.000000,0,9,pass,64,1543.694875;1501.052792;1482.006208;1432.981166;1320.893792;1328.868667;1355.810834;1421.675417;1337.125625 +random,65536,524288,64,cpu_distance,703.276375,0.000000,703.276375,0.000000,0,9,pass,0,703.276375;719.258750;726.684250;682.657208;697.282959;699.636458;698.637625;704.775709;735.197208 +random,65536,524288,64,cpu_pool10,181.873958,0.000000,181.873958,0.000000,0,9,pass,64,216.777750;186.447958;180.352792;178.576708;181.873958;181.106500;200.742167;186.728833;179.152250 +chain,2048,2047,1,cpu_full,0.019667,0.000000,0.019667,0.000000,0,9,pass,1,0.020125;0.019708;0.019792;0.019459;0.019666;0.019667;0.019542;0.019792;0.019625 +chain,2048,2047,1,cpu_distance,0.004792,0.000000,0.004792,0.000000,0,9,pass,0,0.004958;0.004958;0.004750;0.004792;0.004750;0.004875;0.004792;0.004750;0.004792 +chain,2048,2047,1,cpu_pool10,0.039333,0.000000,0.039333,0.000000,0,9,pass,1,0.041000;0.039125;0.041083;0.039333;0.040666;0.037292;0.039333;0.046417;0.036500 +random,4096,131072,1,cpu_full,1.539625,0.000000,1.539625,0.000000,0,9,pass,1,1.592417;1.600542;1.556292;1.554000;1.539625;1.523500;1.516333;1.535500;1.528833 +random,4096,131072,1,cpu_distance,0.666250,0.000000,0.666250,0.000000,0,9,pass,0,0.706750;0.693500;0.686750;0.677958;0.666250;0.652625;0.647209;0.664459;0.643875 +random,4096,131072,1,cpu_pool10,1.721000,0.000000,1.721000,0.000000,0,9,pass,1,1.796875;1.732167;1.728875;1.721000;1.672791;1.717584;1.651584;1.774958;1.618333 +random,4096,131072,64,cpu_full,112.114083,0.000000,112.114083,0.000000,0,9,pass,64,111.754667;111.104792;111.502500;113.248167;112.114083;112.117750;111.657959;114.661000;112.451209 +random,4096,131072,64,cpu_distance,51.198125,0.000000,51.198125,0.000000,0,9,pass,0,49.981584;50.728417;51.871583;51.198125;51.291833;51.193459;51.875625;51.237041;50.593625 +random,4096,131072,64,cpu_pool10,12.856917,0.000000,12.856917,0.000000,0,9,pass,64,12.974625;12.898958;12.780333;12.824459;12.889000;12.811291;12.853333;12.886750;12.856917 +clos,200,20000,1,cpu_full,0.138708,0.000000,0.138708,0.000000,0,9,pass,1,0.138708;0.149834;0.137584;0.154875;0.147750;0.136250;0.147416;0.135417;0.138166 +clos,200,20000,1,cpu_distance,0.026292,0.000000,0.026292,0.000000,0,9,pass,0,0.026792;0.026375;0.026500;0.026292;0.026500;0.026167;0.026084;0.026042;0.026041 +clos,200,20000,1,cpu_pool10,0.178667,0.000000,0.178667,0.000000,0,9,pass,1,0.177917;0.182833;0.184334;0.175625;0.177000;0.183333;0.175875;0.190459;0.178667 +clos,200,20000,64,cpu_full,9.340000,0.000000,9.340000,0.000000,0,9,pass,64,9.371333;9.260542;9.368500;9.340000;9.502042;9.128083;9.156166;9.015542;9.563584 +clos,200,20000,64,cpu_distance,1.710250,0.000000,1.710250,0.000000,0,9,pass,0,1.794083;1.683042;1.691042;1.641416;1.694916;1.710250;1.843750;1.870708;1.763125 +clos,200,20000,64,cpu_pool10,1.167167,0.000000,1.167167,0.000000,0,9,pass,64,1.182834;1.245250;1.187375;1.099833;1.137916;1.167167;1.148208;1.165625;1.731666 +clos,800,320000,1,cpu_full,2.314167,0.000000,2.314167,0.000000,0,9,pass,1,2.304125;2.335583;2.282750;2.279792;2.288334;2.317416;2.326666;2.346875;2.314167 +clos,800,320000,1,cpu_distance,0.390042,0.000000,0.390042,0.000000,0,9,pass,0,0.390083;0.390042;0.398333;0.388583;0.392167;0.391667;0.388792;0.388875;0.388125 +clos,800,320000,1,cpu_pool10,2.355708,0.000000,2.355708,0.000000,0,9,pass,1,2.373750;2.368833;2.333166;2.329875;2.329166;2.355708;2.335834;2.391833;2.362042 +clos,800,320000,64,cpu_full,148.903625,0.000000,148.903625,0.000000,0,9,pass,64,149.844708;148.332833;150.863708;148.481791;151.271416;148.695625;148.903625;152.917459;148.691292 +clos,800,320000,64,cpu_distance,25.264916,0.000000,25.264916,0.000000,0,9,pass,0,25.148333;25.201625;25.167250;25.264916;25.292417;25.266916;25.295417;25.364708;25.206833 +clos,800,320000,64,cpu_pool10,17.328375,0.000000,17.328375,0.000000,0,9,pass,64,18.354167;17.193458;17.347083;17.145083;17.328375;17.167541;19.327292;17.145500;18.241875 +grid,10000,39600,1,cpu_full,0.631166,0.000000,0.631166,0.000000,0,9,pass,1,0.641042;0.623083;0.630083;0.616125;0.680375;0.640584;0.621459;0.631166;0.754208 +grid,10000,39600,1,cpu_distance,0.182417,0.000000,0.182417,0.000000,0,9,pass,0,0.188542;0.196792;0.183292;0.181959;0.179708;0.177833;0.181458;0.182417;0.195750 +grid,10000,39600,1,cpu_pool10,0.714292,0.000000,0.714292,0.000000,0,9,pass,1,0.722417;0.714292;0.669083;0.710083;0.645125;0.737000;0.663958;0.759166;0.755875 +grid,10000,39600,8,cpu_full,5.696250,0.000000,5.696250,0.000000,0,9,pass,8,5.774709;5.671333;5.712750;5.640375;5.724584;5.615833;5.616584;5.876000;5.696250 +grid,10000,39600,8,cpu_distance,1.624167,0.000000,1.624167,0.000000,0,9,pass,0,1.595875;1.640416;1.586875;1.601542;1.711625;1.624167;1.673875;1.597875;1.698792 +grid,10000,39600,8,cpu_pool10,0.852250,0.000000,0.852250,0.000000,0,9,pass,8,0.852250;1.229500;0.813333;0.819625;1.231458;0.918666;1.240458;0.833500;0.845583 +grid,40000,159200,1,cpu_full,2.919000,0.000000,2.919000,0.000000,0,9,pass,1,3.025375;2.919000;2.934042;2.914209;2.914000;2.943083;2.907625;2.919334;2.887459 +grid,40000,159200,1,cpu_distance,0.868708,0.000000,0.868708,0.000000,0,9,pass,0,0.874583;0.868708;0.870375;0.888666;0.860333;0.874084;0.859917;0.863583;0.862333 +grid,40000,159200,1,cpu_pool10,2.959542,0.000000,2.959542,0.000000,0,9,pass,1,2.970542;2.959542;2.984000;2.926583;2.999500;2.947292;2.928833;2.920292;2.966541 diff --git a/dev/research/metal_pathfinding/results/aba-initial/a2-stderr.txt b/dev/research/metal_pathfinding/results/aba-initial/a2-stderr.txt new file mode 100644 index 0000000..e69de29 diff --git a/dev/research/metal_pathfinding/results/aba-initial/a2.csv b/dev/research/metal_pathfinding/results/aba-initial/a2.csv new file mode 100644 index 0000000..a32d157 --- /dev/null +++ b/dev/research/metal_pathfinding/results/aba-initial/a2.csv @@ -0,0 +1,82 @@ +case,n,e,queries,method,wall_ms,gpu_ms,distance_wall_ms,upload_ms,rounds,samples,correct,exact_order_queries,wall_samples_ms +random,128,1024,1,cpu_full,0.010833,0.000000,0.010833,0.000000,0,9,pass,1,0.010250;0.011834;0.009916;0.012334;0.010833;0.011042;0.011292;0.009750;0.009667 +random,128,1024,1,cpu_distance,0.004750,0.000000,0.004750,0.000000,0,9,pass,0,0.004958;0.004750;0.005959;0.004750;0.005458;0.004542;0.005750;0.004500;0.004291 +random,128,1024,1,cpu_pool10,0.028584,0.000000,0.028584,0.000000,0,9,pass,1,0.031333;0.026833;0.030334;0.026333;0.028584;0.026792;0.027500;0.053792;0.048500 +random,128,1024,64,cpu_full,0.821042,0.000000,0.821042,0.000000,0,9,pass,64,0.943291;0.913167;0.870250;0.846167;0.815083;0.821042;0.783792;0.781375;0.776500 +random,128,1024,64,cpu_distance,0.354125,0.000000,0.354125,0.000000,0,9,pass,0,0.433667;0.409125;0.553959;0.420167;0.354125;0.328792;0.306791;0.305459;0.314708 +random,128,1024,64,cpu_pool10,0.156750,0.000000,0.156750,0.000000,0,9,pass,64,0.168125;0.150292;0.156750;0.161125;0.158459;0.150417;0.157667;0.151417;0.146792 +random,1024,8192,1,cpu_full,0.108875,0.000000,0.108875,0.000000,0,9,pass,1,0.111291;0.108875;0.119667;0.111750;0.112375;0.106750;0.103709;0.102334;0.103500 +random,1024,8192,1,cpu_distance,0.057209,0.000000,0.057209,0.000000,0,9,pass,0,0.063500;0.057542;0.057209;0.059500;0.056084;0.059375;0.056875;0.056375;0.055542 +random,1024,8192,1,cpu_pool10,0.179500,0.000000,0.179500,0.000000,0,9,pass,1,0.228584;0.179500;0.216458;0.193375;0.191875;0.167125;0.155417;0.147375;0.160541 +random,1024,8192,64,cpu_full,10.334500,0.000000,10.334500,0.000000,0,9,pass,64,10.415083;10.460125;10.626542;10.342084;10.307166;10.334500;10.297541;10.276292;10.295166 +random,1024,8192,64,cpu_distance,5.089208,0.000000,5.089208,0.000000,0,9,pass,0,5.206541;5.264583;5.280083;5.034667;5.027584;5.015459;5.023583;5.089208;5.108458 +random,1024,8192,64,cpu_pool10,1.276542,0.000000,1.276542,0.000000,0,9,pass,64,1.276542;1.276583;1.278167;1.277375;1.272875;1.242417;1.238208;1.255791;1.294458 +fabric,288,16384,1,cpu_full,0.109542,0.000000,0.109542,0.000000,0,9,pass,1,0.109333;0.108167;0.114042;0.109875;0.109542;0.108625;0.111084;0.108625;0.109834 +fabric,288,16384,1,cpu_distance,0.023459,0.000000,0.023459,0.000000,0,9,pass,0,0.023958;0.024042;0.023708;0.023750;0.023459;0.023125;0.023334;0.023375;0.023083 +fabric,288,16384,1,cpu_pool10,0.140417,0.000000,0.140417,0.000000,0,9,pass,1,0.138917;0.130916;0.142334;0.134833;0.157834;0.160833;0.144708;0.139833;0.140417 +fabric,288,16384,64,cpu_full,7.335417,0.000000,7.335417,0.000000,0,9,pass,64,7.348833;7.351291;7.497708;7.468834;7.281000;7.286833;7.261375;7.335417;7.292000 +fabric,288,16384,64,cpu_distance,1.490792,0.000000,1.490792,0.000000,0,9,pass,0,1.497667;1.484791;1.556166;1.481334;1.489250;1.496291;1.471959;1.490792;1.500042 +fabric,288,16384,64,cpu_pool10,0.994500,0.000000,0.994500,0.000000,0,9,pass,64,1.310167;0.994500;0.885167;1.440208;0.924667;1.369250;0.911375;0.882166;1.262000 +grid,1024,3968,1,cpu_full,0.042708,0.000000,0.042708,0.000000,0,9,pass,1,0.045042;0.043250;0.042667;0.042667;0.042708;0.042834;0.042583;0.042500;0.042750 +grid,1024,3968,1,cpu_distance,0.011792,0.000000,0.011792,0.000000,0,9,pass,0,0.012125;0.011875;0.011917;0.011792;0.011708;0.011709;0.011792;0.011709;0.011750 +grid,1024,3968,1,cpu_pool10,0.078000,0.000000,0.078000,0.000000,0,9,pass,1,0.104375;0.078000;0.062959;0.081000;0.077959;0.069292;0.080084;0.099417;0.067792 +grid,1024,3968,64,cpu_full,3.969708,0.000000,3.969708,0.000000,0,9,pass,64,3.927417;3.982416;4.061667;3.961958;4.054167;3.911708;3.969708;3.937333;3.989291 +grid,1024,3968,64,cpu_distance,0.919125,0.000000,0.919125,0.000000,0,9,pass,0,0.962375;0.942292;0.919125;0.895500;0.881917;1.024958;0.925625;0.898084;0.872708 +grid,1024,3968,64,cpu_pool10,0.545958,0.000000,0.545958,0.000000,0,9,pass,64,0.597417;0.661041;0.519917;0.521167;0.677583;0.545958;0.507708;0.515125;0.678208 +chain,256,255,1,cpu_full,0.002541,0.000000,0.002541,0.000000,0,9,pass,1,0.002542;0.002458;0.002541;0.002583;0.002667;0.002500;0.002708;0.002500;0.002500 +chain,256,255,1,cpu_distance,0.000667,0.000000,0.000667,0.000000,0,9,pass,0,0.000708;0.000708;0.000667;0.000667;0.000667;0.000625;0.000667;0.000667;0.000625 +chain,256,255,1,cpu_pool10,0.030291,0.000000,0.030291,0.000000,0,9,pass,1,0.040666;0.027042;0.030291;0.020500;0.027792;0.025250;0.030375;0.035666;0.036166 +random_masked_int64_reverse,1024,8192,8,cpu_full,0.597541,0.000000,0.597541,0.000000,0,9,pass,8,0.664167;0.636250;0.607958;0.597541;0.581709;0.579417;0.597958;0.566125;0.567250 +random_masked_int64_reverse,1024,8192,8,cpu_distance,0.289750,0.000000,0.289750,0.000000,0,9,pass,0,0.364125;0.346917;0.320291;0.304583;0.289750;0.277959;0.269708;0.270709;0.269083 +random_masked_int64_reverse,1024,8192,8,cpu_pool10,0.203375,0.000000,0.203375,0.000000,0,9,pass,8,0.154459;0.156792;0.230833;0.214083;0.201875;0.203375;0.201375;0.214167;0.273875 +random,4096,32768,1,cpu_full,0.712917,0.000000,0.712917,0.000000,0,9,pass,1,0.681042;0.659792;0.821583;0.779833;0.756666;0.737833;0.712917;0.691500;0.686209 +random,4096,32768,1,cpu_distance,0.309000,0.000000,0.309000,0.000000,0,9,pass,0,0.337875;0.318042;0.305958;0.309000;0.298542;0.341459;0.311000;0.303333;0.301958 +random,4096,32768,1,cpu_pool10,0.785625,0.000000,0.785625,0.000000,0,9,pass,1,0.844916;0.802291;0.791417;0.789125;0.785625;0.780541;0.729375;0.745541;0.746208 +random,4096,32768,64,cpu_full,52.727708,0.000000,52.727708,0.000000,0,9,pass,64,52.664666;52.541958;52.493167;52.884583;53.811209;55.433792;52.673542;53.223542;52.727708 +random,4096,32768,64,cpu_distance,25.830208,0.000000,25.830208,0.000000,0,9,pass,0,26.109875;26.458750;26.554584;25.830208;25.906208;25.789167;25.734000;25.723875;25.792500 +random,4096,32768,64,cpu_pool10,5.860083,0.000000,5.860083,0.000000,0,9,pass,64,5.935000;5.859958;5.821042;5.833000;5.901000;5.850250;5.860083;5.966084;5.929959 +random,4096,32768,256,cpu_full,207.992250,0.000000,207.992250,0.000000,0,9,pass,256,206.724000;208.200708;207.499625;206.872708;210.280083;213.188875;208.143708;206.021542;207.992250 +random,4096,32768,256,cpu_distance,104.051583,0.000000,104.051583,0.000000,0,9,pass,0,104.128959;105.184459;103.591917;103.345583;104.051583;104.073125;103.631084;103.562375;106.041209 +random,4096,32768,256,cpu_pool10,22.650792,0.000000,22.650792,0.000000,0,9,pass,256,23.191209;22.046667;33.122375;23.513166;22.648375;22.679792;22.127083;22.033000;22.650792 +random,16384,131072,1,cpu_full,3.929417,0.000000,3.929417,0.000000,0,9,pass,1,4.274125;3.899833;3.929417;4.422709;3.847792;4.645000;3.848333;4.002333;3.903083 +random,16384,131072,1,cpu_distance,2.171583,0.000000,2.171583,0.000000,0,9,pass,0,2.268166;2.171583;2.203000;2.184500;2.164416;2.150791;2.200750;1.966792;1.933916 +random,16384,131072,1,cpu_pool10,4.152458,0.000000,4.152458,0.000000,0,9,pass,1,4.705584;4.494792;4.191875;4.127666;4.152458;4.026250;3.900041;4.111959;4.444541 +random,16384,131072,64,cpu_full,247.691375,0.000000,247.691375,0.000000,0,9,pass,64,247.384417;248.870041;247.608084;247.486917;246.857833;247.691375;257.440917;250.836500;248.646583 +random,16384,131072,64,cpu_distance,131.827250,0.000000,131.827250,0.000000,0,9,pass,0,131.827250;132.225917;131.814417;131.767875;132.610542;131.409583;130.953708;135.935042;133.253334 +random,16384,131072,64,cpu_pool10,28.359041,0.000000,28.359041,0.000000,0,9,pass,64,28.115292;28.119084;28.112792;28.127334;28.368166;29.834500;29.085750;28.359041;30.483792 +random,65536,524288,1,cpu_full,22.647375,0.000000,22.647375,0.000000,0,9,pass,1,20.932000;23.518000;20.834416;24.593625;22.648875;22.647375;21.936583;22.682208;22.441333 +random,65536,524288,1,cpu_distance,11.794042,0.000000,11.794042,0.000000,0,9,pass,0,11.654459;12.429667;11.794042;11.909250;12.420542;12.983708;11.474417;10.956250;10.923417 +random,65536,524288,1,cpu_pool10,20.695417,0.000000,20.695417,0.000000,0,9,pass,1,20.689834;23.461167;20.695417;24.155625;22.147958;20.718083;20.171959;20.259875;19.568000 +random,65536,524288,64,cpu_full,1320.231250,0.000000,1320.231250,0.000000,0,9,pass,64,1342.003417;1308.543208;1329.705792;1330.231416;1315.563250;1302.226667;1320.231250;1351.369583;1294.068167 +random,65536,524288,64,cpu_distance,703.172916,0.000000,703.172916,0.000000,0,9,pass,0,696.462167;703.172916;729.499542;686.473125;723.540625;727.089417;694.442000;684.076291;730.469000 +random,65536,524288,64,cpu_pool10,190.623000,0.000000,190.623000,0.000000,0,9,pass,64,182.424666;192.549833;182.596875;191.734167;182.435666;193.379583;190.623000;178.277209;193.851375 +chain,2048,2047,1,cpu_full,0.019416,0.000000,0.019416,0.000000,0,9,pass,1,0.019625;0.019500;0.019458;0.019333;0.019375;0.019375;0.019542;0.019375;0.019416 +chain,2048,2047,1,cpu_distance,0.004792,0.000000,0.004792,0.000000,0,9,pass,0,0.004917;0.004750;0.004833;0.004792;0.004750;0.004792;0.004792;0.004708;0.004708 +chain,2048,2047,1,cpu_pool10,0.036834,0.000000,0.036834,0.000000,0,9,pass,1,0.036125;0.037875;0.036834;0.037875;0.037375;0.037583;0.035667;0.034875;0.035000 +random,4096,131072,1,cpu_full,1.679541,0.000000,1.679541,0.000000,0,9,pass,1,1.679541;1.643167;1.592084;1.694542;1.711875;1.677125;1.824875;1.698875;1.639500 +random,4096,131072,1,cpu_distance,0.691209,0.000000,0.691209,0.000000,0,9,pass,0,0.691209;0.674375;0.664250;0.662916;0.655750;0.889125;0.861542;0.732416;0.701209 +random,4096,131072,1,cpu_pool10,1.669292,0.000000,1.669292,0.000000,0,9,pass,1,1.698375;1.669292;1.648959;1.632208;1.717542;1.666333;1.649166;1.786166;1.750334 +random,4096,131072,64,cpu_full,111.530709,0.000000,111.530709,0.000000,0,9,pass,64,111.036208;111.092000;111.208375;111.335500;111.607834;111.530709;111.897333;123.337000;115.064042 +random,4096,131072,64,cpu_distance,49.874000,0.000000,49.874000,0.000000,0,9,pass,0,49.730958;49.667250;50.174584;49.874000;49.732041;49.854875;50.297125;51.777667;50.203834 +random,4096,131072,64,cpu_pool10,12.770500,0.000000,12.770500,0.000000,0,9,pass,64,12.853708;12.836916;12.777666;12.832250;12.754167;12.754208;12.725750;12.692792;12.770500 +clos,200,20000,1,cpu_full,0.144458,0.000000,0.144458,0.000000,0,9,pass,1,0.147125;0.149083;0.159583;0.143958;0.144000;0.144458;0.145500;0.143250;0.143833 +clos,200,20000,1,cpu_distance,0.029417,0.000000,0.029417,0.000000,0,9,pass,0,0.029500;0.029417;0.040209;0.026291;0.026250;0.027125;0.032500;0.032459;0.026417 +clos,200,20000,1,cpu_pool10,0.172209,0.000000,0.172209,0.000000,0,9,pass,1,0.177833;0.169000;0.184208;0.170542;0.170958;0.182333;0.172209;0.176916;0.169833 +clos,200,20000,64,cpu_full,9.344917,0.000000,9.344917,0.000000,0,9,pass,64,9.405083;9.327375;9.344917;9.256375;9.225166;9.460750;9.049167;9.419000;9.451500 +clos,200,20000,64,cpu_distance,1.703708,0.000000,1.703708,0.000000,0,9,pass,0,1.703708;1.771625;1.681083;1.686333;1.807333;1.656834;1.673250;1.711208;1.817500 +clos,200,20000,64,cpu_pool10,1.280458,0.000000,1.280458,0.000000,0,9,pass,64,1.468250;1.114291;1.538709;1.113000;1.129417;1.671500;1.280458;1.133958;1.785375 +clos,800,320000,1,cpu_full,2.456709,0.000000,2.456709,0.000000,0,9,pass,1,2.517875;2.386333;2.496791;2.554583;2.397208;2.427000;2.356875;2.456709;2.576250 +clos,800,320000,1,cpu_distance,0.394584,0.000000,0.394584,0.000000,0,9,pass,0,0.401958;0.389458;0.390875;0.397500;0.394584;0.393417;0.394917;0.397875;0.394500 +clos,800,320000,1,cpu_pool10,2.421333,0.000000,2.421333,0.000000,0,9,pass,1,2.361458;2.418500;2.669208;2.568208;2.395041;2.423167;2.493458;2.421333;2.412875 +clos,800,320000,64,cpu_full,150.211750,0.000000,150.211750,0.000000,0,9,pass,64,150.774000;149.614458;151.205917;149.062583;154.468125;149.091542;150.351875;149.293875;150.211750 +clos,800,320000,64,cpu_distance,25.404750,0.000000,25.404750,0.000000,0,9,pass,0,25.297542;25.404750;25.432334;25.347625;25.474333;25.363375;25.391333;25.542125;25.405834 +clos,800,320000,64,cpu_pool10,17.443042,0.000000,17.443042,0.000000,0,9,pass,64,17.723500;17.432708;18.498708;17.201500;17.314417;18.956917;17.443042;17.232667;18.136750 +grid,10000,39600,1,cpu_full,0.617416,0.000000,0.617416,0.000000,0,9,pass,1,0.637833;0.636542;0.617875;0.618792;0.617416;0.616791;0.612584;0.616750;0.611334 +grid,10000,39600,1,cpu_distance,0.179916,0.000000,0.179916,0.000000,0,9,pass,0,0.182250;0.179167;0.179000;0.179916;0.188250;0.185375;0.177833;0.179375;0.179958 +grid,10000,39600,1,cpu_pool10,0.686959,0.000000,0.686959,0.000000,0,9,pass,1,0.734417;0.711292;0.691458;0.686959;0.706042;0.685584;0.680833;0.677750;0.675167 +grid,10000,39600,8,cpu_full,5.587958,0.000000,5.587958,0.000000,0,9,pass,8,5.609542;5.540458;5.564500;5.599791;5.587958;5.604417;5.595583;5.556542;5.536167 +grid,10000,39600,8,cpu_distance,1.579834,0.000000,1.579834,0.000000,0,9,pass,0,1.598125;1.579834;1.561709;1.566750;1.563667;1.595083;1.588584;1.592917;1.559584 +grid,10000,39600,8,cpu_pool10,0.874125,0.000000,0.874125,0.000000,0,9,pass,8,1.307167;0.874125;0.840250;1.379708;0.871708;1.267542;0.834500;0.831583;1.212583 +grid,40000,159200,1,cpu_full,2.918042,0.000000,2.918042,0.000000,0,9,pass,1,2.908458;2.902584;2.863542;2.918042;2.936250;2.902583;2.953000;3.064666;3.009292 +grid,40000,159200,1,cpu_distance,0.900709,0.000000,0.900709,0.000000,0,9,pass,0,0.889459;0.930333;0.906083;0.909250;0.916958;0.887542;0.876750;0.878583;0.900709 +grid,40000,159200,1,cpu_pool10,3.041500,0.000000,3.041500,0.000000,0,9,pass,1,3.047042;3.043250;3.013167;3.027833;3.012417;3.099708;3.140125;3.041500;3.038209 diff --git a/dev/research/metal_pathfinding/results/aba-initial/b-stderr.txt b/dev/research/metal_pathfinding/results/aba-initial/b-stderr.txt new file mode 100644 index 0000000..ac7eefb --- /dev/null +++ b/dev/research/metal_pathfinding/results/aba-initial/b-stderr.txt @@ -0,0 +1 @@ +device=Apple M4 Max setup_ms=29.7193 execution_width=32 diff --git a/dev/research/metal_pathfinding/results/aba-initial/b.csv b/dev/research/metal_pathfinding/results/aba-initial/b.csv new file mode 100644 index 0000000..3f62dd7 --- /dev/null +++ b/dev/research/metal_pathfinding/results/aba-initial/b.csv @@ -0,0 +1,69 @@ +case,n,e,queries,method,wall_ms,gpu_ms,distance_wall_ms,upload_ms,rounds,samples,correct,exact_order_queries,wall_samples_ms +random,128,1024,1,metal_pull,0.694333,0.305875,0.688416,0.040542,16,9,pass,0,0.824625;0.880667;0.672541;0.714917;0.599375;0.591625;0.694333;0.808792;0.585333 +random,128,1024,1,metal_group,0.272125,0.130750,0.267833,0.040542,9,9,pass,0,0.753375;0.279375;0.267000;0.271958;0.271667;0.272125;0.500250;0.279209;0.263250 +random,128,1024,1,metal_shared,0.264750,0.123500,0.259625,0.040542,9,9,pass,0,0.267167;0.253583;0.264750;0.258417;0.246916;0.258500;0.287166;0.325875;0.362208 +random,128,1024,64,metal_pull,0.898834,0.346917,0.615667,0.060333,16,9,pass,0,1.087958;0.891333;0.974625;0.898834;0.940333;0.880416;0.842291;0.879875;0.907375 +random,128,1024,64,metal_group,0.597708,0.179375,0.323167,0.060333,13,9,pass,0,0.614250;0.678208;0.597708;0.597000;0.625875;0.600250;0.578042;0.571208;0.577208 +random,128,1024,64,metal_shared,0.598917,0.168542,0.314542,0.060333,13,9,pass,0,0.610708;0.607666;0.602542;0.608167;0.598917;0.583041;0.574083;0.558667;0.559542 +random,1024,8192,1,metal_pull,0.751708,0.398583,0.708791,0.082709,16,9,pass,0,0.788250;0.716333;0.715667;0.831709;0.762541;0.751708;0.716250;1.371375;0.701542 +random,1024,8192,1,metal_group,0.857958,0.678792,0.820333,0.082709,13,9,pass,0,0.861750;0.857458;0.853125;0.854958;0.857958;0.869708;0.900250;0.862750;0.851250 +random,1024,8192,1,metal_shared,0.822459,0.639208,0.780792,0.082709,13,9,pass,0,0.916292;0.802667;0.815750;0.840333;0.820834;0.838583;0.819125;0.822459;0.845916 +random,1024,8192,64,metal_pull,4.666000,1.543917,2.176875,0.114500,24,9,pass,0,4.584042;4.518958;5.016250;5.419500;4.748625;4.529042;4.565292;4.666000;4.892125 +random,1024,8192,64,metal_group,3.842875,0.893625,1.354458,0.114500,17,9,pass,0,3.842875;3.535417;3.878875;3.977333;3.835958;3.829125;3.878708;3.709792;3.910750 +random,1024,8192,64,metal_shared,3.773791,0.828458,1.284917,0.114500,17,9,pass,0,3.734166;3.713583;3.813542;3.809833;3.755083;3.695125;3.798167;3.937292;3.773791 +fabric,288,16384,1,metal_pull,1.859625,1.648625,1.806375,0.116000,8,9,pass,0,1.839917;1.864375;1.995041;1.859625;1.868375;1.937417;1.834584;1.844208;1.766292 +fabric,288,16384,1,metal_group,0.776375,0.576500,0.716917,0.116000,3,9,pass,0,0.786958;0.764250;0.845375;0.818083;0.774375;0.777167;0.776375;0.510167;0.555875 +fabric,288,16384,1,metal_shared,0.733292,0.546875,0.674250,0.116000,3,9,pass,0,0.730417;0.733292;0.786042;0.810708;0.739416;0.695333;0.488541;0.478875;0.892958 +fabric,288,16384,64,metal_pull,5.846791,1.800375,2.335667,0.145292,8,9,pass,0,5.086083;5.870000;5.846791;5.543417;5.846542;6.396292;5.965208;5.897375;5.826000 +fabric,288,16384,64,metal_group,4.629250,0.644375,1.190291,0.145292,3,9,pass,0,4.395458;4.694042;4.700083;4.629250;4.676292;4.376625;4.693042;4.293042;4.586375 +fabric,288,16384,64,metal_shared,4.801458,0.622000,1.157084,0.145292,3,9,pass,0,4.661208;4.952084;4.857542;4.645917;4.805500;4.682250;4.801458;6.446500;4.696791 +grid,1024,3968,1,metal_pull,1.846125,0.651292,1.827084,0.065416,64,9,pass,0,2.019292;1.846125;2.021708;1.716792;1.929959;1.710000;1.883416;1.696250;1.706834 +grid,1024,3968,1,metal_group,1.176292,1.008250,1.158542,0.065416,63,9,pass,0,1.164791;1.182625;1.161584;1.162708;1.213208;1.260084;1.171792;1.179334;1.176292 +grid,1024,3968,1,metal_shared,0.487541,0.348875,0.471292,0.065416,63,9,pass,0,0.505459;0.487541;0.486458;0.504208;0.512792;0.488416;0.461667;0.456291;0.466333 +grid,1024,3968,64,metal_pull,3.045875,0.567583,2.132125,0.080500,64,9,pass,0,2.971500;2.829791;3.048500;2.852875;3.045875;2.905750;3.125083;3.216166;3.372708 +grid,1024,3968,64,metal_group,1.864042,0.405958,0.949125,0.080500,63,9,pass,0,1.852166;1.796541;1.882167;1.836917;1.864042;1.955917;1.558459;1.924375;1.948792 +grid,1024,3968,64,metal_shared,1.958083,0.487208,1.013500,0.080500,63,9,pass,0,1.963458;1.958083;1.495541;2.055667;1.936667;1.975791;1.935166;1.944042;2.318917 +chain,256,255,1,metal_pull,5.824792,1.927375,5.822250,0.052833,256,9,pass,1,6.102125;5.943208;6.338167;5.852500;5.273083;5.824792;5.505208;5.067875;5.153459 +chain,256,255,1,metal_group,0.714667,0.608625,0.713083,0.052833,256,9,pass,1,0.711209;0.720959;0.709417;0.711916;0.716583;0.714667;0.708125;0.717959;0.815000 +chain,256,255,1,metal_shared,0.658709,0.552125,0.657209,0.052833,256,9,pass,1,0.658709;0.654916;0.653791;0.739209;0.801459;0.673667;0.663959;0.653000;0.649500 +random_masked_int64_reverse,1024,8192,8,metal_pull,0.682125,0.133708,0.245708,0.085083,8,9,pass,1,0.740958;0.668292;0.736208;0.661167;0.692542;0.682125;0.667625;0.685750;0.660917 +random_masked_int64_reverse,1024,8192,8,metal_group,0.749041,0.241083,0.338250,0.085083,8,9,pass,1,0.767500;0.754917;0.756750;0.745125;0.749041;0.626875;0.746833;0.751167;0.732333 +random_masked_int64_reverse,1024,8192,8,metal_shared,0.741709,0.224625,0.328917,0.085083,8,9,pass,1,0.723625;0.720375;0.715209;0.741709;0.728000;0.803041;0.774625;0.753041;0.768542 +random,4096,32768,1,metal_pull,0.812833,0.413625,0.660625,0.196375,16,9,pass,0,0.801458;0.806833;0.811333;0.814834;0.816083;0.812833;0.793167;0.860833;0.816417 +random,4096,32768,1,metal_group,1.505875,1.226583,1.358042,0.196375,16,9,pass,0,2.224875;1.505875;1.510208;1.338542;1.329209;1.352791;1.476209;1.584875;1.555541 +random,4096,32768,64,metal_pull,14.598084,3.937250,4.753209,0.208583,24,9,pass,0,14.252500;14.598084;15.751167;17.473250;14.592417;13.591042;17.424500;14.417500;18.520500 +random,4096,32768,64,metal_group,14.066250,4.080833,4.463417,0.208583,19,9,pass,0,14.129583;14.038459;11.394417;14.478125;14.066250;13.967625;14.229542;14.124334;11.212583 +random,4096,32768,256,metal_pull,52.239208,11.306291,13.131667,0.215541,24,9,pass,0,49.794333;49.768167;52.239208;51.144625;52.841292;51.508875;53.434292;53.943542;53.808208 +random,4096,32768,256,metal_group,49.850250,9.712792,10.485541,0.215541,20,9,pass,0,47.301833;48.041792;48.523375;51.754625;52.943792;51.925625;49.809875;49.850250;51.073500 +random,16384,131072,1,metal_pull,1.386041,0.270917,0.696084,0.583583,24,9,pass,0,1.349833;1.344791;1.398750;1.883167;1.773000;1.312167;1.368083;1.459333;1.386041 +random,16384,131072,1,metal_group,5.660333,4.802667,4.988333,0.583583,18,9,pass,0,5.774875;5.682834;5.790833;5.646959;5.583334;5.649250;5.620167;5.790166;5.660333 +random,16384,131072,64,metal_pull,57.259666,11.632292,12.902417,0.623375,24,9,pass,0,57.422542;57.092416;57.618708;57.291917;57.259666;56.624625;56.584416;57.963625;56.911000 +random,16384,131072,64,metal_group,54.493208,9.480500,10.270834,0.623375,22,9,pass,0,53.254667;53.490625;54.070542;54.493208;56.920459;56.394708;54.439875;54.946792;55.627125 +random,65536,524288,1,metal_pull,5.859042,1.942875,2.819833,2.711292,24,9,pass,0,5.889208;5.976292;6.990375;6.082208;5.859042;4.821625;4.951208;4.638042;4.792333 +random,65536,524288,1,metal_group,32.303250,28.469375,29.047916,2.711292,22,9,pass,0,31.766250;31.845500;31.635042;31.586375;32.434666;32.359458;32.305917;32.303250;32.318417 +random,65536,524288,64,metal_pull,269.299583,69.087833,71.201500,2.622333,32,9,pass,0,268.115458;271.970875;269.941292;268.528541;269.299583;269.076750;268.627791;269.599125;272.598000 +random,65536,524288,64,metal_group,274.914833,75.469958,76.650542,2.622333,25,9,pass,0,273.356208;272.365000;274.351291;274.330250;274.914833;277.346917;277.881250;276.976584;276.145209 +chain,2048,2047,1,metal_pull,29.862084,4.310752,29.851875,0.070834,2048,9,pass,1,29.859000;28.595000;29.774000;29.862084;30.292084;29.960708;30.157125;29.597333;30.245000 +chain,2048,2047,1,metal_group,4.815750,4.698792,4.806500,0.070834,2048,9,pass,1,4.798125;4.865583;4.803041;4.799208;4.910500;4.826875;4.881500;4.815625;4.815750 +random,4096,131072,1,metal_pull,0.896667,0.267792,0.483708,0.588333,16,9,pass,0,0.875625;0.890458;0.899750;0.896667;0.916875;0.904833;0.877958;0.906667;0.853708 +random,4096,131072,1,metal_group,2.694958,2.174167,2.280334,0.588333,12,9,pass,0,2.671709;2.646250;2.697916;2.805750;2.669416;2.684459;2.925000;2.738292;2.694958 +random,4096,131072,64,metal_pull,37.135333,8.692458,9.196958,0.675541,16,9,pass,0,35.238334;36.093709;35.691375;35.662584;37.135333;39.312250;39.152625;38.276667;38.420625 +random,4096,131072,64,metal_group,36.557458,7.510292,7.880583,0.675541,15,9,pass,0,34.011792;34.412958;38.154083;41.139291;34.516083;35.256750;36.557458;37.278875;36.584917 +clos,200,20000,1,metal_pull,0.669667,0.443375,0.599625,0.127375,8,9,pass,0,0.991167;0.672042;0.669667;0.674875;0.879750;0.652208;0.656792;0.666916;0.640167 +clos,200,20000,1,metal_group,0.366875,0.151917,0.297084,0.127375,3,9,pass,0,0.366875;0.384750;0.342125;0.357500;0.366042;0.383125;0.485541;0.479500;0.342416 +clos,200,20000,1,metal_shared,0.352542,0.142750,0.281125,0.127375,3,9,pass,0,0.407584;0.346917;0.357959;0.352542;0.342917;0.347167;0.347292;0.403458;0.358833 +clos,200,20000,64,metal_pull,5.845584,1.017542,1.578750,0.162000,8,9,pass,0,5.916459;5.769833;5.835500;5.656750;5.845959;5.728583;6.488792;5.845584;5.853792 +clos,200,20000,64,metal_group,5.049667,0.309625,0.890291,0.162000,3,9,pass,0,5.133958;4.883875;5.132000;5.048208;5.071291;5.049667;5.043708;5.150125;4.778417 +clos,200,20000,64,metal_shared,5.062500,0.293833,0.850083,0.162000,3,9,pass,0,5.062500;5.012500;4.969167;4.868250;5.078416;5.152583;5.033167;5.128291;5.161792 +clos,800,320000,1,metal_pull,4.467084,3.168541,3.390333,1.307417,8,9,pass,0,4.739125;4.467084;4.451583;4.742625;4.750208;4.833000;2.988708;1.954417;2.435167 +clos,800,320000,1,metal_group,2.647917,0.946375,1.618458,1.307417,3,9,pass,0,2.143583;5.294334;3.724166;2.616750;2.647917;5.521750;4.269459;2.507334;2.601250 +clos,800,320000,1,metal_shared,2.639667,0.905000,1.565042,1.307417,3,9,pass,0,2.636542;2.500625;2.630250;2.660500;4.998333;5.397416;4.654375;2.564250;2.639667 +clos,800,320000,64,metal_pull,84.884084,16.348833,16.846000,1.254500,8,9,pass,0,84.918625;83.551292;84.269958;83.793166;85.337916;88.659791;83.283542;88.303542;84.884084 +clos,800,320000,64,metal_group,73.596917,5.233958,5.823625,1.254500,3,9,pass,0,73.978875;73.856000;73.987333;73.942958;73.596917;73.378708;73.150542;73.522083;72.589416 +clos,800,320000,64,metal_shared,73.488333,5.098667,5.715750,1.254500,3,9,pass,0,73.912000;73.938666;72.677167;73.085209;72.850625;75.111209;74.153959;72.633250;73.488333 +grid,10000,39600,1,metal_pull,4.066792,0.588250,3.935042,0.170583,200,9,pass,0,5.971916;4.407667;3.591625;4.066792;4.094125;3.673125;3.720167;4.068667;3.871167 +grid,10000,39600,1,metal_group,7.897958,7.570500,7.738625,0.170583,199,9,pass,0,7.841042;7.899084;7.943167;7.855458;7.873667;7.914667;7.897958;7.891959;8.008416 +grid,10000,39600,8,metal_pull,6.015875,1.397917,5.012500,0.167167,200,9,pass,0,6.379375;5.981750;6.565208;5.743083;6.015875;5.603667;6.220792;5.636583;6.580167 +grid,10000,39600,8,metal_group,9.084958,7.487958,8.109417,0.167167,199,9,pass,0,8.986459;9.386500;9.080083;9.138000;9.178042;9.223667;8.955833;9.082250;9.084958 +grid,40000,159200,1,metal_pull,8.366125,1.756501,7.870792,0.498500,400,9,pass,0,8.677875;9.271667;8.710083;8.543291;8.366125;7.339959;7.248500;7.223375;7.600666 +grid,40000,159200,1,metal_group,65.593041,64.849167,65.113958,0.498500,399,9,pass,0,65.552584;65.564333;65.593041;65.452333;66.461167;66.104959;65.226667;65.833166;65.986167 diff --git a/dev/research/metal_pathfinding/results/aba-initial/environment.txt b/dev/research/metal_pathfinding/results/aba-initial/environment.txt new file mode 100644 index 0000000..a449a5e --- /dev/null +++ b/dev/research/metal_pathfinding/results/aba-initial/environment.txt @@ -0,0 +1,17 @@ +2026-09-26T23:02:54Z +fbab119e794c843838f4f3f96d75cb7f32f06845 +ProductName: macOS +ProductVersion: 26.6.1 +BuildVersion: 25G76 +Apple M4 Max +38654705664 +14 +Apple clang version 21.0.0 (clang-2100.1.1.101) +Target: arm64-apple-darwin25.6.0 +Thread model: posix +InstalledDir: /Library/Developer/CommandLineTools/usr/bin +0ea7d865d0d979f1ed79612cff1270bbf2d45425a7548cf7c7fa9595f5f1463b dev/research/metal_pathfinding/experiment.mm +2e36b1623a3940bf1f19f5d81141bb1def14f5873fe2a98aab0101bbe68618a3 dev/research/metal_pathfinding/sssp.metal +Note: No thermal warning level has been recorded +Note: No performance warning level has been recorded +Note: No CPU power status has been recorded diff --git a/dev/research/metal_pathfinding/results/aba-initial/gpu-load-a1.txt b/dev/research/metal_pathfinding/results/aba-initial/gpu-load-a1.txt new file mode 100644 index 0000000..2a9fdd8 --- /dev/null +++ b/dev/research/metal_pathfinding/results/aba-initial/gpu-load-a1.txt @@ -0,0 +1 @@ + | "PerformanceStatistics" = {"In use system memory (driver)"=0,"Alloc system memory"=10844422144,"Tiler Utilization %"=5,"recoveryCount"=0,"lastRecoveryTime"=0,"Renderer Utilization %"=8,"TiledSceneBytes"=1441792,"Device Utilization %"=23,"SplitSceneCount"=0,"Allocated PB Size"=187301888,"In use system memory"=1340784640} diff --git a/dev/research/metal_pathfinding/results/aba-initial/gpu-load-a2.txt b/dev/research/metal_pathfinding/results/aba-initial/gpu-load-a2.txt new file mode 100644 index 0000000..fb2f6fe --- /dev/null +++ b/dev/research/metal_pathfinding/results/aba-initial/gpu-load-a2.txt @@ -0,0 +1 @@ + | "PerformanceStatistics" = {"In use system memory (driver)"=0,"Alloc system memory"=10848157696,"Tiler Utilization %"=2,"recoveryCount"=0,"lastRecoveryTime"=0,"Renderer Utilization %"=5,"TiledSceneBytes"=1441792,"Device Utilization %"=75,"SplitSceneCount"=0,"Allocated PB Size"=187301888,"In use system memory"=1341440000} diff --git a/dev/research/metal_pathfinding/results/aba-initial/gpu-load-b.txt b/dev/research/metal_pathfinding/results/aba-initial/gpu-load-b.txt new file mode 100644 index 0000000..67b7835 --- /dev/null +++ b/dev/research/metal_pathfinding/results/aba-initial/gpu-load-b.txt @@ -0,0 +1 @@ + | "PerformanceStatistics" = {"In use system memory (driver)"=0,"Alloc system memory"=10846322688,"Tiler Utilization %"=6,"recoveryCount"=0,"lastRecoveryTime"=0,"Renderer Utilization %"=10,"TiledSceneBytes"=1441792,"Device Utilization %"=10,"SplitSceneCount"=0,"Allocated PB Size"=187301888,"In use system memory"=1391755264} diff --git a/dev/research/metal_pathfinding/results/aba-initial/load-a1.txt b/dev/research/metal_pathfinding/results/aba-initial/load-a1.txt new file mode 100644 index 0000000..afe6af8 --- /dev/null +++ b/dev/research/metal_pathfinding/results/aba-initial/load-a1.txt @@ -0,0 +1,40 @@ +Processes: 1029 total, 3 running, 1026 sleeping, 5267 threads +2026/09/27 00:02:55 +Load Avg: 3.44, 4.22, 4.55 +CPU usage: 12.78% user, 9.58% sys, 77.62% idle +SharedLibs: 914M resident, 168M data, 135M linkedit. +MemRegions: 640562 total, 10G resident, 741M private, 4397M shared. +PhysMem: 34G used (3993M wired, 633M compressor), 1623M unused. +VM: 455T vsize, 6144M framework vsize, 2843901(0) swapins, 4729331(0) swapouts. +Networks: packets: 190112204/161G in, 145523736/163G out. +Disks: 97543153/2475G read, 117275070/2097G written. + +PID COMMAND %CPU #TH +99753 mscamerad-xpc 0.0 2 +99752 PlugInLibrarySer 0.0 2 +99750 QuickLookUIServi 0.0 3 +99749 com.apple.appkit 0.0 3 +99710 PlugInLibrarySer 0.0 2 +99709 Preview 0.0 4 +99428 crashpad_handler 0.0 4 +98995 crashpad_handler 0.0 4 +Processes: 1030 total, 4 running, 1026 sleeping, 5290 threads +2026/09/27 00:02:56 +Load Avg: 3.56, 4.24, 4.55 +CPU usage: 16.1% user, 6.20% sys, 77.77% idle +SharedLibs: 914M resident, 168M data, 135M linkedit. +MemRegions: 1440 total, 222M resident, 741M private, 4390M shared. +PhysMem: 34G used (3993M wired, 633M compressor), 1565M unused. +VM: 455T vsize, 6144M framework vsize, 2843901(0) swapins, 4729331(0) swapouts. +Networks: packets: 190112459/161G in, 145523987/163G out. +Disks: 97543153/2475G read, 117275092/2097G written. + +PID COMMAND %CPU #TH +1225 mediaanalysisd 33.3 18/2 +590 WindowServer 30.9 28 +70968 Superset Helper 20.4 32 +0 kernel_task 13.0 850/14 +70942 Superset Helper 7.2 19 +59318 top 5.9 1/1 +65401 codex 3.4 38 +70934 Superset 3.1 50 diff --git a/dev/research/metal_pathfinding/results/aba-initial/load-a2.txt b/dev/research/metal_pathfinding/results/aba-initial/load-a2.txt new file mode 100644 index 0000000..7d011ae --- /dev/null +++ b/dev/research/metal_pathfinding/results/aba-initial/load-a2.txt @@ -0,0 +1,40 @@ +Processes: 1029 total, 3 running, 1026 sleeping, 5318 threads +2026/09/27 00:04:25 +Load Avg: 4.06, 4.30, 4.55 +CPU usage: 11.52% user, 15.65% sys, 72.82% idle +SharedLibs: 914M resident, 168M data, 135M linkedit. +MemRegions: 638423 total, 10G resident, 742M private, 4205M shared. +PhysMem: 33G used (4028M wired, 633M compressor), 1920M unused. +VM: 455T vsize, 6144M framework vsize, 2843901(0) swapins, 4729331(0) swapouts. +Networks: packets: 190145627/161G in, 145557848/163G out. +Disks: 97548223/2475G read, 117280135/2097G written. + +PID COMMAND %CPU #TH +99753 mscamerad-xpc 0.0 2 +99752 PlugInLibrarySer 0.0 2 +99750 QuickLookUIServi 0.0 3 +99749 com.apple.appkit 0.0 3 +99710 PlugInLibrarySer 0.0 2 +99709 Preview 0.0 4 +99428 crashpad_handler 0.0 4 +98995 crashpad_handler 0.0 4 +Processes: 1029 total, 2 running, 1027 sleeping, 5313 threads +2026/09/27 00:04:27 +Load Avg: 4.70, 4.43, 4.59 +CPU usage: 7.48% user, 5.9% sys, 87.41% idle +SharedLibs: 914M resident, 168M data, 135M linkedit. +MemRegions: 0 total, 0B resident, 742M private, 4205M shared. +PhysMem: 33G used (3992M wired, 633M compressor), 1918M unused. +VM: 455T vsize, 6144M framework vsize, 2843901(0) swapins, 4729331(0) swapouts. +Networks: packets: 190145997/161G in, 145558207/163G out. +Disks: 97548250/2475G read, 117280139/2097G written. + +PID COMMAND %CPU #TH +590 WindowServer 36.6 28 +70968 Superset Helper 23.2 33 +594 runningboardd 21.0 7 +0 kernel_task 15.7 850/14 +66135 top 8.9 1/1 +70942 Superset Helper 7.7 18 +21666 2.1.283 6.3 27 +39196 PerfPowerService 5.7 13 diff --git a/dev/research/metal_pathfinding/results/aba-initial/load-b.txt b/dev/research/metal_pathfinding/results/aba-initial/load-b.txt new file mode 100644 index 0000000..a06f45c --- /dev/null +++ b/dev/research/metal_pathfinding/results/aba-initial/load-b.txt @@ -0,0 +1,40 @@ +Processes: 1038 total, 4 running, 1034 sleeping, 5297 threads +2026/09/27 00:03:54 +Load Avg: 4.38, 4.36, 4.57 +CPU usage: 6.7% user, 9.19% sys, 84.73% idle +SharedLibs: 914M resident, 168M data, 135M linkedit. +MemRegions: 638679 total, 10G resident, 752M private, 4206M shared. +PhysMem: 33G used (3994M wired, 633M compressor), 1786M unused. +VM: 458T vsize, 6144M framework vsize, 2843901(0) swapins, 4729331(0) swapouts. +Networks: packets: 190133303/161G in, 145544526/163G out. +Disks: 97547513/2475G read, 117278580/2097G written. + +PID COMMAND %CPU #TH +99753 mscamerad-xpc 0.0 2 +99752 PlugInLibrarySer 0.0 2 +99750 QuickLookUIServi 0.0 3 +99749 com.apple.appkit 0.0 3 +99710 PlugInLibrarySer 0.0 2 +99709 Preview 0.0 4 +99428 crashpad_handler 0.0 4 +98995 crashpad_handler 0.0 4 +Processes: 1044 total, 4 running, 1040 sleeping, 5315 threads +2026/09/27 00:03:55 +Load Avg: 4.38, 4.36, 4.57 +CPU usage: 15.9% user, 8.23% sys, 76.66% idle +SharedLibs: 914M resident, 168M data, 135M linkedit. +MemRegions: 1073 total, 191M resident, 752M private, 4208M shared. +PhysMem: 34G used (4060M wired, 633M compressor), 1564M unused. +VM: 461T vsize, 6144M framework vsize, 2843901(0) swapins, 4729331(0) swapouts. +Networks: packets: 190134081/161G in, 145545447/163G out. +Disks: 97547534/2475G read, 117278594/2097G written. + +PID COMMAND %CPU #TH +590 WindowServer 29.1 28 +70968 Superset Helper 24.8 32/1 +1225 mediaanalysisd 24.0 18 +0 kernel_task 14.2 850/14 +517 fseventsd 10.7 16 +81804 2.1.283 9.4 27 +70942 Superset Helper 8.5 18 +63750 top 6.4 1/1 diff --git a/dev/research/metal_pathfinding/results/aba-initial/summary.md b/dev/research/metal_pathfinding/results/aba-initial/summary.md new file mode 100644 index 0000000..09724ff --- /dev/null +++ b/dev/research/metal_pathfinding/results/aba-initial/summary.md @@ -0,0 +1,38 @@ +All times are medians in milliseconds per batch, with nine timed samples. +CPU A columns use serial SPF for Q=1 and the 10-worker pool otherwise. +GPU includes host distance copies and serial CPU ECMP DAG reconstruction. +Upload and pipeline setup are excluded and recorded separately in raw data. +The table picks the fastest measured GPU method for each case. + +| Case | V / E | Q | CPU A1 | GPU B | CPU A2 | GPU method | Distance-only B | CPU drift | +|---|---:|---:|---:|---:|---:|---|---:|---:| +| random | 128 / 1,024 | 1 | 0.010 | 0.265 | 0.011 | metal_shared | 0.260 | +12.6% | +| random | 128 / 1,024 | 64 | 0.182 | 0.598 | 0.157 | metal_group | 0.323 | -14.1% | +| random | 1,024 / 8,192 | 1 | 0.104 | 0.752 | 0.109 | metal_pull | 0.709 | +5.1% | +| random | 1,024 / 8,192 | 64 | 1.342 | 3.774 | 1.277 | metal_shared | 1.285 | -4.9% | +| fabric | 288 / 16,384 | 1 | 0.112 | 0.733 | 0.110 | metal_shared | 0.674 | -2.5% | +| fabric | 288 / 16,384 | 64 | 0.972 | 4.629 | 0.995 | metal_group | 1.190 | +2.3% | +| grid | 1,024 / 3,968 | 1 | 0.044 | 0.488 | 0.043 | metal_shared | 0.471 | -2.2% | +| grid | 1,024 / 3,968 | 64 | 0.543 | 1.864 | 0.546 | metal_group | 0.949 | +0.5% | +| chain | 256 / 255 | 1 | 0.003 | 0.659 | 0.003 | metal_shared | 0.657 | -0.0% | +| random_masked_int64_reverse | 1,024 / 8,192 | 8 | 0.156 | 0.682 | 0.203 | metal_pull | 0.246 | +30.6% | +| random | 4,096 / 32,768 | 1 | 0.657 | 0.813 | 0.713 | metal_pull | 0.661 | +8.6% | +| random | 4,096 / 32,768 | 64 | 5.992 | 14.066 | 5.860 | metal_group | 4.463 | -2.2% | +| random | 4,096 / 32,768 | 256 | 23.001 | 49.850 | 22.651 | metal_group | 10.486 | -1.5% | +| random | 16,384 / 131,072 | 1 | 3.887 | 1.386 | 3.929 | metal_pull | 0.696 | +1.1% | +| random | 16,384 / 131,072 | 64 | 28.586 | 54.493 | 28.359 | metal_group | 10.271 | -0.8% | +| random | 65,536 / 524,288 | 1 | 22.864 | 5.859 | 22.647 | metal_pull | 2.820 | -0.9% | +| random | 65,536 / 524,288 | 64 | 181.874 | 269.300 | 190.623 | metal_pull | 71.201 | +4.8% | +| chain | 2,048 / 2,047 | 1 | 0.020 | 4.816 | 0.019 | metal_group | 4.806 | -1.3% | +| random | 4,096 / 131,072 | 1 | 1.540 | 0.897 | 1.680 | metal_pull | 0.484 | +9.1% | +| random | 4,096 / 131,072 | 64 | 12.857 | 36.557 | 12.771 | metal_group | 7.881 | -0.7% | +| clos | 200 / 20,000 | 1 | 0.139 | 0.353 | 0.144 | metal_shared | 0.281 | +4.1% | +| clos | 200 / 20,000 | 64 | 1.167 | 5.050 | 1.280 | metal_group | 0.890 | +9.7% | +| clos | 800 / 320,000 | 1 | 2.314 | 2.640 | 2.457 | metal_shared | 1.565 | +6.2% | +| clos | 800 / 320,000 | 64 | 17.328 | 73.488 | 17.443 | metal_shared | 5.716 | +0.7% | +| grid | 10,000 / 39,600 | 1 | 0.631 | 4.067 | 0.617 | metal_pull | 3.935 | -2.2% | +| grid | 10,000 / 39,600 | 8 | 0.852 | 6.016 | 0.874 | metal_pull | 5.013 | +2.6% | +| grid | 40,000 / 159,200 | 1 | 2.919 | 8.366 | 2.918 | metal_pull | 7.871 | -0.0% | + +Distance-only timings stop before DAG reconstruction; they are not SPF API timings. +CPU distance-only and serial full-batch controls are also available in a1/a2.csv. diff --git a/dev/research/metal_pathfinding/results/aba/a1-stderr.txt b/dev/research/metal_pathfinding/results/aba/a1-stderr.txt new file mode 100644 index 0000000..e69de29 diff --git a/dev/research/metal_pathfinding/results/aba/a1.csv b/dev/research/metal_pathfinding/results/aba/a1.csv new file mode 100644 index 0000000..85a75b7 --- /dev/null +++ b/dev/research/metal_pathfinding/results/aba/a1.csv @@ -0,0 +1,109 @@ +case,n,e,queries,method,wall_ms,gpu_ms,distance_wall_ms,upload_ms,rounds,samples,correct,exact_order_queries,wall_samples_ms +random,128,1024,1,cpu_full,0.031083,0.000000,0.031083,0.000000,0,9,pass,1,0.025959;0.047458;0.031083;0.025458;0.089375;0.046875;0.027416;0.042458;0.027167 +random,128,1024,1,cpu_distance,0.010625,0.000000,0.010625,0.000000,0,9,pass,0,0.010625;0.010083;0.053000;0.028416;0.012625;0.010750;0.010250;0.009917;0.009917 +random,128,1024,1,cpu_pool10,0.065334,0.000000,0.065334,0.000000,0,9,pass,1,0.072125;0.134959;0.047291;0.041166;0.047625;0.065334;0.108833;0.065334;0.039959 +random,128,1024,1,cpu_pool10_distance,0.031291,0.000000,0.031291,0.000000,0,9,pass,0,0.069500;0.029708;0.031500;0.034125;0.031291;0.036583;0.029125;0.026166;0.027500 +random,128,1024,64,cpu_full,2.259334,0.000000,2.259334,0.000000,0,9,pass,64,2.880125;2.602792;2.582041;2.345583;2.175084;2.259334;2.142166;1.871250;1.849166 +random,128,1024,64,cpu_distance,0.604334,0.000000,0.604334,0.000000,0,9,pass,0,0.777792;0.734917;0.664542;0.613875;0.604334;0.593916;0.557875;0.527708;0.496709 +random,128,1024,64,cpu_pool10,0.234125,0.000000,0.234125,0.000000,0,9,pass,64,0.336750;0.342667;0.316625;0.254000;0.223584;0.234125;0.198583;0.190167;0.206083 +random,128,1024,64,cpu_pool10_distance,0.126417,0.000000,0.126417,0.000000,0,9,pass,0,0.131541;0.137000;0.126417;0.129334;0.111583;0.122541;0.128042;0.108500;0.113791 +random,1024,8192,1,cpu_full,0.145417,0.000000,0.145417,0.000000,0,9,pass,1,0.168083;0.164667;0.152583;0.147458;0.144750;0.145417;0.145333;0.144000;0.144834 +random,1024,8192,1,cpu_distance,0.080125,0.000000,0.080125,0.000000,0,9,pass,0,0.083250;0.080750;0.079959;0.080333;0.079334;0.079584;0.079541;0.081667;0.080125 +random,1024,8192,1,cpu_pool10,0.228792,0.000000,0.228792,0.000000,0,9,pass,1,0.265000;0.228792;0.263084;0.261959;0.227500;0.220083;0.220208;0.195542;0.237208 +random,1024,8192,1,cpu_pool10_distance,0.134708,0.000000,0.134708,0.000000,0,9,pass,0,0.140625;0.138291;0.116250;0.142541;0.134708;0.110167;0.100417;0.150417;0.111000 +random,1024,8192,64,cpu_full,10.256834,0.000000,10.256834,0.000000,0,9,pass,64,10.220708;10.174458;10.082500;10.185167;10.265750;10.277833;10.256834;10.274708;10.452625 +random,1024,8192,64,cpu_distance,5.040292,0.000000,5.040292,0.000000,0,9,pass,0,5.296791;5.411084;5.040292;5.061084;5.073833;4.945042;4.947209;5.020833;4.953291 +random,1024,8192,64,cpu_pool10,1.273334,0.000000,1.273334,0.000000,0,9,pass,64,1.261917;1.254709;1.264208;1.274875;1.273334;1.289083;1.297209;1.288209;1.251541 +random,1024,8192,64,cpu_pool10_distance,0.633542,0.000000,0.633542,0.000000,0,9,pass,0,0.646750;0.634292;0.633542;0.642042;0.639000;0.627834;0.626209;0.630625;0.617000 +fabric,288,16384,1,cpu_full,0.106625,0.000000,0.106625,0.000000,0,9,pass,1,0.103000;0.111958;0.103875;0.109167;0.103208;0.109958;0.103458;0.108709;0.106625 +fabric,288,16384,1,cpu_distance,0.022209,0.000000,0.022209,0.000000,0,9,pass,0,0.022542;0.022375;0.022292;0.022209;0.022042;0.022125;0.022083;0.022041;0.022209 +fabric,288,16384,1,cpu_pool10,0.136416,0.000000,0.136416,0.000000,0,9,pass,1,0.144084;0.130041;0.140500;0.131666;0.137458;0.136416;0.133250;0.129459;0.141334 +fabric,288,16384,1,cpu_pool10_distance,0.051583,0.000000,0.051583,0.000000,0,9,pass,0,0.043250;0.040625;0.052750;0.044667;0.058000;0.053625;0.047084;0.063917;0.051583 +fabric,288,16384,64,cpu_full,7.037208,0.000000,7.037208,0.000000,0,9,pass,64,7.154417;7.377959;7.160000;6.919500;7.004708;7.303625;7.037208;6.997208;7.035792 +fabric,288,16384,64,cpu_distance,1.361708,0.000000,1.361708,0.000000,0,9,pass,0,1.336542;1.394208;1.345500;1.334958;1.364208;1.410250;1.361000;1.369667;1.361708 +fabric,288,16384,64,cpu_pool10,1.010542,0.000000,1.010542,0.000000,0,9,pass,64,0.891250;1.371208;1.054042;0.880958;1.157417;1.010542;0.909041;1.264625;0.965167 +fabric,288,16384,64,cpu_pool10_distance,0.194375,0.000000,0.194375,0.000000,0,9,pass,0,0.209667;0.195750;0.213708;0.207041;0.194250;0.193041;0.188792;0.190834;0.194375 +grid,1024,3968,1,cpu_full,0.037042,0.000000,0.037042,0.000000,0,9,pass,1,0.038875;0.037542;0.037042;0.037250;0.037209;0.036791;0.036917;0.036875;0.036916 +grid,1024,3968,1,cpu_distance,0.010250,0.000000,0.010250,0.000000,0,9,pass,0,0.010792;0.010500;0.010375;0.010375;0.010167;0.010250;0.010125;0.009917;0.010000 +grid,1024,3968,1,cpu_pool10,0.072834,0.000000,0.072834,0.000000,0,9,pass,1,0.082750;0.064583;0.077709;0.063250;0.082875;0.072834;0.070625;0.063208;0.078708 +grid,1024,3968,1,cpu_pool10_distance,0.029667,0.000000,0.029667,0.000000,0,9,pass,0,0.031583;0.028041;0.028125;0.035917;0.029667;0.030750;0.029500;0.026959;0.031833 +grid,1024,3968,64,cpu_full,3.824709,0.000000,3.824709,0.000000,0,9,pass,64,3.806875;3.924791;3.797833;3.863083;3.824709;3.822500;3.807833;3.827250;3.879416 +grid,1024,3968,64,cpu_distance,0.853125,0.000000,0.853125,0.000000,0,9,pass,0,0.887958;0.871792;0.859042;0.873250;0.842917;0.853125;0.849041;0.839958;0.845458 +grid,1024,3968,64,cpu_pool10,0.498458,0.000000,0.498458,0.000000,0,9,pass,64,0.486167;0.522625;0.487375;0.493542;0.521041;0.498458;0.512292;0.498917;0.481625 +grid,1024,3968,64,cpu_pool10_distance,0.146458,0.000000,0.146458,0.000000,0,9,pass,0,0.148833;0.140667;0.145375;0.160292;0.149875;0.139458;0.172917;0.146458;0.141541 +chain,256,255,1,cpu_full,0.002250,0.000000,0.002250,0.000000,0,9,pass,1,0.003500;0.002292;0.002250;0.002291;0.002250;0.002208;0.002250;0.002291;0.002209 +chain,256,255,1,cpu_distance,0.000500,0.000000,0.000500,0.000000,0,9,pass,0,0.000583;0.000459;0.000542;0.000500;0.000458;0.000459;0.000500;0.000459;0.000583 +chain,256,255,1,cpu_pool10,0.033416,0.000000,0.033416,0.000000,0,9,pass,1,0.031625;0.035916;0.026833;0.033416;0.027625;0.024667;0.033708;0.034708;0.036959 +chain,256,255,1,cpu_pool10_distance,0.032375,0.000000,0.032375,0.000000,0,9,pass,0,0.033750;0.033000;0.030500;0.024583;0.043792;0.019459;0.032375;0.032750;0.026333 +random_masked_int64_reverse,1024,8192,8,cpu_full,0.585459,0.000000,0.585459,0.000000,0,9,pass,8,0.634625;0.620333;0.607833;0.610125;0.585459;0.575459;0.583375;0.570917;0.562458 +random_masked_int64_reverse,1024,8192,8,cpu_distance,0.279667,0.000000,0.279667,0.000000,0,9,pass,0,0.336250;0.315000;0.279667;0.277041;0.278250;0.280958;0.286333;0.267625;0.273000 +random_masked_int64_reverse,1024,8192,8,cpu_pool10,0.149667,0.000000,0.149667,0.000000,0,9,pass,8,0.147333;0.155041;0.152666;0.154875;0.149667;0.143208;0.138250;0.151125;0.131666 +random_masked_int64_reverse,1024,8192,8,cpu_pool10_distance,0.092750,0.000000,0.092750,0.000000,0,9,pass,0,0.093708;0.096667;0.091667;0.088125;0.092083;0.090250;0.097916;0.099708;0.092750 +random,4096,32768,1,cpu_full,0.640750,0.000000,0.640750,0.000000,0,9,pass,1,0.654125;0.672584;0.635750;0.640750;0.630541;0.715625;0.663917;0.620958;0.638875 +random,4096,32768,1,cpu_distance,0.305042,0.000000,0.305042,0.000000,0,9,pass,0,0.318834;0.383000;0.356625;0.305042;0.285792;0.279584;0.276209;0.281125;0.308542 +random,4096,32768,1,cpu_pool10,0.750792,0.000000,0.750792,0.000000,0,9,pass,1,0.732959;0.763292;0.765875;0.765083;0.750291;0.750792;0.697250;0.738625;0.866042 +random,4096,32768,1,cpu_pool10_distance,0.396125,0.000000,0.396125,0.000000,0,9,pass,0,0.391083;0.399042;0.400041;0.445875;0.352625;0.396125;0.416417;0.368375;0.364292 +random,4096,32768,64,cpu_full,50.551959,0.000000,50.551959,0.000000,0,9,pass,64,50.982291;50.381667;51.224250;50.245000;49.884125;50.077625;50.921250;50.551959;51.063625 +random,4096,32768,64,cpu_distance,25.068208,0.000000,25.068208,0.000000,0,9,pass,0,24.892083;25.225875;25.305542;24.956250;25.502416;25.652625;24.782041;25.068208;24.635917 +random,4096,32768,64,cpu_pool10,5.984083,0.000000,5.984083,0.000000,0,9,pass,64,6.019500;6.024709;5.952959;5.948666;5.984083;6.007625;5.921583;5.963333;6.381042 +random,4096,32768,64,cpu_pool10_distance,2.967750,0.000000,2.967750,0.000000,0,9,pass,0,2.974166;2.993208;2.954208;2.951584;2.963167;2.988542;2.967750;2.972125;2.958500 +random,4096,32768,256,cpu_full,203.524291,0.000000,203.524291,0.000000,0,9,pass,256,201.889458;203.077667;202.445916;205.140292;207.688792;203.452125;204.337834;203.558833;203.524291 +random,4096,32768,256,cpu_distance,100.870916,0.000000,100.870916,0.000000,0,9,pass,0,102.179417;100.391417;99.621458;99.962083;100.870916;100.120167;102.712666;103.321958;103.868375 +random,4096,32768,256,cpu_pool10,23.461417,0.000000,23.461417,0.000000,0,9,pass,256,23.404958;23.153542;23.566042;22.393541;23.576000;23.669625;28.794875;23.461417;23.088458 +random,4096,32768,256,cpu_pool10_distance,12.019459,0.000000,12.019459,0.000000,0,9,pass,0,11.456875;11.726541;12.966375;12.238042;12.717875;12.019459;11.796125;12.376375;11.948333 +random,16384,131072,1,cpu_full,4.095417,0.000000,4.095417,0.000000,0,9,pass,1,4.290250;3.940416;4.150417;3.954583;3.887333;4.095417;3.985083;4.162667;4.295334 +random,16384,131072,1,cpu_distance,2.076458,0.000000,2.076458,0.000000,0,9,pass,0,2.369584;2.076458;1.996792;2.022250;2.259167;2.148209;2.015833;2.012167;2.160583 +random,16384,131072,1,cpu_pool10,3.907000,0.000000,3.907000,0.000000,0,9,pass,1,3.736125;3.756166;4.311583;4.175125;3.876833;3.907000;4.442625;3.681041;4.181042 +random,16384,131072,1,cpu_pool10_distance,1.988250,0.000000,1.988250,0.000000,0,9,pass,0,1.939375;1.947750;1.892166;1.988250;1.939125;1.997125;2.016583;2.086959;2.044542 +random,16384,131072,64,cpu_full,246.791250,0.000000,246.791250,0.000000,0,9,pass,64,247.174041;257.095833;248.073500;242.532542;244.690333;241.950875;242.319083;246.791250;248.494458 +random,16384,131072,64,cpu_distance,128.259375,0.000000,128.259375,0.000000,0,9,pass,0,128.418500;127.874875;128.259375;128.375083;129.444958;127.964208;128.118000;128.115125;128.568334 +random,16384,131072,64,cpu_pool10,28.289500,0.000000,28.289500,0.000000,0,9,pass,64,28.152417;28.391750;28.205000;28.321167;28.289500;28.210041;28.201417;28.320125;28.388750 +random,16384,131072,64,cpu_pool10_distance,14.897583,0.000000,14.897583,0.000000,0,9,pass,0,14.930292;14.903167;14.878917;14.855125;14.861167;14.889166;14.897583;14.933375;14.931750 +random,65536,524288,1,cpu_full,20.761667,0.000000,20.761667,0.000000,0,9,pass,1,20.893041;20.761667;21.248417;22.771708;19.348959;21.047583;20.342500;19.837625;20.622167 +random,65536,524288,1,cpu_distance,10.450375,0.000000,10.450375,0.000000,0,9,pass,0,10.685375;10.484542;10.293209;10.711500;10.304833;10.450375;10.329542;10.734417;10.264709 +random,65536,524288,1,cpu_pool10,21.484917,0.000000,21.484917,0.000000,0,9,pass,1,18.160875;18.542833;18.610750;19.389750;22.475417;22.478750;21.749084;21.484917;21.888666 +random,65536,524288,1,cpu_pool10_distance,10.246625,0.000000,10.246625,0.000000,0,9,pass,0,11.192042;10.267166;9.973292;10.866416;10.246625;10.542208;10.197125;10.197459;9.896917 +random,65536,524288,64,cpu_full,1257.924209,0.000000,1257.924209,0.000000,0,9,pass,64,1282.247375;1223.090292;1257.924209;1239.818375;1313.894125;1432.189959;1278.728875;1241.412875;1243.033125 +random,65536,524288,64,cpu_distance,665.201250,0.000000,665.201250,0.000000,0,9,pass,0,662.326750;666.337417;657.751459;704.184958;697.644750;659.886125;673.242417;661.982917;665.201250 +random,65536,524288,64,cpu_pool10,174.081708,0.000000,174.081708,0.000000,0,9,pass,64,172.784166;174.081708;191.587583;188.869292;171.705625;172.985750;174.222334;173.790417;176.710000 +random,65536,524288,64,cpu_pool10_distance,85.845625,0.000000,85.845625,0.000000,0,9,pass,0,85.845625;85.446458;85.561875;85.000792;84.927542;86.648500;86.624791;86.942667;86.348917 +chain,2048,2047,1,cpu_full,0.019875,0.000000,0.019875,0.000000,0,9,pass,1,0.020458;0.019959;0.019875;0.019583;0.020208;0.019667;0.019459;0.019625;0.020042 +chain,2048,2047,1,cpu_distance,0.004125,0.000000,0.004125,0.000000,0,9,pass,0,0.004125;0.004084;0.004791;0.006167;0.004167;0.004125;0.004208;0.004125;0.004125 +chain,2048,2047,1,cpu_pool10,0.047125,0.000000,0.047125,0.000000,0,9,pass,1,0.046833;0.050542;0.047125;0.052875;0.048833;0.043500;0.047750;0.046042;0.045958 +chain,2048,2047,1,cpu_pool10_distance,0.038333,0.000000,0.038333,0.000000,0,9,pass,0,0.040375;0.035459;0.067417;0.054459;0.036875;0.033208;0.037333;0.039625;0.038333 +random,4096,131072,1,cpu_full,1.762250,0.000000,1.762250,0.000000,0,9,pass,1,1.806584;1.750208;1.770750;1.810833;1.762250;1.677250;1.621583;1.615750;1.778292 +random,4096,131072,1,cpu_distance,0.664917,0.000000,0.664917,0.000000,0,9,pass,0,0.857084;0.738708;0.715458;0.683333;0.664917;0.663708;0.659416;0.646792;0.643541 +random,4096,131072,1,cpu_pool10,1.889833,0.000000,1.889833,0.000000,0,9,pass,1,2.152625;1.844084;1.923250;1.834959;3.235375;1.889833;1.780667;1.750917;1.954125 +random,4096,131072,1,cpu_pool10_distance,0.804916,0.000000,0.804916,0.000000,0,9,pass,0,0.804916;0.831125;0.772208;0.863541;0.727250;0.842625;0.810208;0.785750;0.799167 +random,4096,131072,64,cpu_full,111.141125,0.000000,111.141125,0.000000,0,9,pass,64,110.630292;111.750125;111.395709;110.963250;112.158667;110.807166;115.478417;111.141125;110.905125 +random,4096,131072,64,cpu_distance,49.129500,0.000000,49.129500,0.000000,0,9,pass,0,49.369208;49.268292;49.148708;48.819417;48.989750;49.011250;49.129500;49.123375;49.282917 +random,4096,131072,64,cpu_pool10,12.773541,0.000000,12.773541,0.000000,0,9,pass,64,12.743708;12.746417;12.784667;12.899042;12.785000;12.787333;12.773541;12.744042;12.745292 +random,4096,131072,64,cpu_pool10_distance,5.610042,0.000000,5.610042,0.000000,0,9,pass,0,5.610042;5.667416;5.604791;5.622333;5.622292;5.609708;5.594958;5.616958;5.591208 +clos,200,20000,1,cpu_full,0.146333,0.000000,0.146333,0.000000,0,9,pass,1,0.155084;0.150416;0.158791;0.145667;0.143875;0.146333;0.147833;0.145000;0.145083 +clos,200,20000,1,cpu_distance,0.024083,0.000000,0.024083,0.000000,0,9,pass,0,0.024459;0.024500;0.024459;0.024292;0.024083;0.023958;0.023916;0.023916;0.023833 +clos,200,20000,1,cpu_pool10,0.170166,0.000000,0.170166,0.000000,0,9,pass,1,0.180250;0.168541;0.179459;0.169875;0.181375;0.166083;0.172709;0.170166;0.163959 +clos,200,20000,1,cpu_pool10_distance,0.049459,0.000000,0.049459,0.000000,0,9,pass,0,0.049458;0.054750;0.042083;0.050958;0.047250;0.049792;0.043166;0.049459;0.050333 +clos,200,20000,64,cpu_full,9.367041,0.000000,9.367041,0.000000,0,9,pass,64,9.367041;9.242792;9.226125;9.416416;9.313959;9.471959;9.546000;9.554458;9.346500 +clos,200,20000,64,cpu_distance,1.571458,0.000000,1.571458,0.000000,0,9,pass,0,1.547375;1.586542;1.571458;1.591250;1.581791;1.544750;1.563000;1.727667;1.547708 +clos,200,20000,64,cpu_pool10,1.180583,0.000000,1.180583,0.000000,0,9,pass,64,1.180583;1.425375;1.678916;1.141583;1.178625;1.772750;1.123250;1.115709;1.238625 +clos,200,20000,64,cpu_pool10_distance,0.210666,0.000000,0.210666,0.000000,0,9,pass,0,0.210666;0.210167;0.210791;0.213917;0.212750;0.209541;0.208833;0.222125;0.209959 +clos,800,320000,1,cpu_full,2.329667,0.000000,2.329667,0.000000,0,9,pass,1,2.286500;2.305791;2.298750;2.346875;2.329667;2.382750;2.380916;2.264417;2.339750 +clos,800,320000,1,cpu_distance,0.356042,0.000000,0.356042,0.000000,0,9,pass,0,0.355584;0.363375;0.355792;0.355042;0.358042;0.354375;0.369792;0.356042;0.356083 +clos,800,320000,1,cpu_pool10,2.282875,0.000000,2.282875,0.000000,0,9,pass,1,2.323791;2.271917;2.281042;2.342584;2.281667;2.282875;2.308708;2.378000;2.273750 +clos,800,320000,1,cpu_pool10_distance,0.353625,0.000000,0.353625,0.000000,0,9,pass,0,0.352834;0.357209;0.353625;0.343166;0.347125;0.376250;0.361042;0.350583;0.377083 +clos,800,320000,64,cpu_full,149.821292,0.000000,149.821292,0.000000,0,9,pass,64,153.024458;148.259167;148.473541;147.598584;150.283417;149.821292;152.691250;151.819917;149.421125 +clos,800,320000,64,cpu_distance,23.226250,0.000000,23.226250,0.000000,0,9,pass,0,23.181583;23.269459;23.226250;23.155542;23.227333;23.171541;23.268875;23.184708;23.296417 +clos,800,320000,64,cpu_pool10,17.461541,0.000000,17.461541,0.000000,0,9,pass,64,17.357208;17.461541;17.265958;18.456042;17.167833;18.505625;18.100083;17.112291;17.978709 +clos,800,320000,64,cpu_pool10_distance,2.672125,0.000000,2.672125,0.000000,0,9,pass,0,2.659791;2.670333;2.681541;2.679541;2.675000;2.728833;2.665083;2.668416;2.672125 +grid,10000,39600,1,cpu_full,0.613750,0.000000,0.613750,0.000000,0,9,pass,1,0.622750;0.618000;0.613750;0.612417;0.615000;0.608000;0.611792;0.607708;0.645042 +grid,10000,39600,1,cpu_distance,0.175083,0.000000,0.175083,0.000000,0,9,pass,0,0.182917;0.172292;0.174584;0.178042;0.175083;0.177042;0.174958;0.176834;0.173000 +grid,10000,39600,1,cpu_pool10,0.669667,0.000000,0.669667,0.000000,0,9,pass,1,0.701208;0.654875;0.704833;0.664958;0.683667;0.685791;0.669667;0.635500;0.627875 +grid,10000,39600,1,cpu_pool10_distance,0.198375,0.000000,0.198375,0.000000,0,9,pass,0,0.198375;0.200542;0.189542;0.197417;0.203625;0.207292;0.197625;0.185166;0.207542 +grid,10000,39600,8,cpu_full,5.544583,0.000000,5.544583,0.000000,0,9,pass,8,5.634791;5.632250;5.544583;5.519792;5.581667;5.498625;5.532291;5.510583;5.655459 +grid,10000,39600,8,cpu_distance,1.551083,0.000000,1.551083,0.000000,0,9,pass,0,1.551083;1.545959;1.550084;1.538041;1.562667;1.553583;1.550583;1.559500;1.551958 +grid,10000,39600,8,cpu_pool10,0.828792,0.000000,0.828792,0.000000,0,9,pass,8,0.829458;0.826417;0.816667;0.841541;0.828792;0.840833;0.818709;0.849666;0.807209 +grid,10000,39600,8,cpu_pool10_distance,0.246709,0.000000,0.246709,0.000000,0,9,pass,0,0.252792;0.247292;0.246709;0.250959;0.243625;0.241375;0.250417;0.245958;0.237708 +grid,40000,159200,1,cpu_full,2.912625,0.000000,2.912625,0.000000,0,9,pass,1,2.956292;2.945167;2.898708;2.920250;2.897166;2.912625;2.900000;2.877417;2.937083 +grid,40000,159200,1,cpu_distance,0.862709,0.000000,0.862709,0.000000,0,9,pass,0,0.866083;0.862709;0.859791;0.868292;0.861792;0.854458;0.858000;0.891958;0.880750 +grid,40000,159200,1,cpu_pool10,2.922000,0.000000,2.922000,0.000000,0,9,pass,1,2.913416;3.005208;2.922000;2.959416;2.880500;2.921209;2.976625;2.863500;2.943000 +grid,40000,159200,1,cpu_pool10_distance,0.859875,0.000000,0.859875,0.000000,0,9,pass,0,0.871416;0.871500;0.890875;0.859875;0.857583;0.859875;0.851917;0.858750;0.884625 diff --git a/dev/research/metal_pathfinding/results/aba/a2-stderr.txt b/dev/research/metal_pathfinding/results/aba/a2-stderr.txt new file mode 100644 index 0000000..e69de29 diff --git a/dev/research/metal_pathfinding/results/aba/a2.csv b/dev/research/metal_pathfinding/results/aba/a2.csv new file mode 100644 index 0000000..c09febd --- /dev/null +++ b/dev/research/metal_pathfinding/results/aba/a2.csv @@ -0,0 +1,109 @@ +case,n,e,queries,method,wall_ms,gpu_ms,distance_wall_ms,upload_ms,rounds,samples,correct,exact_order_queries,wall_samples_ms +random,128,1024,1,cpu_full,0.010125,0.000000,0.010125,0.000000,0,9,pass,1,0.011291;0.010208;0.009417;0.009834;0.010125;0.010667;0.009375;0.010708;0.009500 +random,128,1024,1,cpu_distance,0.004542,0.000000,0.004542,0.000000,0,9,pass,0,0.007583;0.004542;0.004209;0.006084;0.005083;0.004250;0.005041;0.004125;0.004083 +random,128,1024,1,cpu_pool10,0.038500,0.000000,0.038500,0.000000,0,9,pass,1,0.043292;0.032917;0.043125;0.028500;0.041667;0.029708;0.027125;0.045875;0.038500 +random,128,1024,1,cpu_pool10_distance,0.032458,0.000000,0.032458,0.000000,0,9,pass,0,0.028416;0.034125;0.028625;0.040542;0.036459;0.031792;0.032458;0.046292;0.029625 +random,128,1024,64,cpu_full,0.882084,0.000000,0.882084,0.000000,0,9,pass,64,0.943708;0.939166;0.898167;0.865625;0.835250;0.817583;0.808000;0.981042;0.882084 +random,128,1024,64,cpu_distance,0.352750,0.000000,0.352750,0.000000,0,9,pass,0,0.396292;0.383500;0.370208;0.364500;0.352750;0.319208;0.299125;0.288833;0.281458 +random,128,1024,64,cpu_pool10,0.162250,0.000000,0.162250,0.000000,0,9,pass,64,0.186542;0.160833;0.162250;0.166667;0.178041;0.168500;0.157208;0.155042;0.145833 +random,128,1024,64,cpu_pool10_distance,0.101625,0.000000,0.101625,0.000000,0,9,pass,0,0.120959;0.109750;0.105459;0.100958;0.101625;0.098250;0.090542;0.097292;0.111625 +random,1024,8192,1,cpu_full,0.114917,0.000000,0.114917,0.000000,0,9,pass,1,0.115166;0.182417;0.159666;0.129625;0.114917;0.104542;0.107958;0.114625;0.109583 +random,1024,8192,1,cpu_distance,0.056041,0.000000,0.056041,0.000000,0,9,pass,0,0.059250;0.057125;0.056875;0.056292;0.055458;0.055625;0.055584;0.055750;0.056041 +random,1024,8192,1,cpu_pool10,0.176208,0.000000,0.176208,0.000000,0,9,pass,1,0.226166;0.199125;0.176375;0.176208;0.186917;0.144625;0.122041;0.161459;0.117833 +random,1024,8192,1,cpu_pool10_distance,0.081084,0.000000,0.081084,0.000000,0,9,pass,0,0.093458;0.083833;0.079416;0.075917;0.089958;0.077500;0.081084;0.077875;0.102834 +random,1024,8192,64,cpu_full,10.597708,0.000000,10.597708,0.000000,0,9,pass,64,10.453250;10.597708;10.592875;10.643083;10.582625;10.578917;10.603500;10.599333;10.665834 +random,1024,8192,64,cpu_distance,5.116292,0.000000,5.116292,0.000000,0,9,pass,0,5.129709;5.086792;5.078084;5.113291;4.995542;5.247625;5.135333;5.178792;5.116292 +random,1024,8192,64,cpu_pool10,1.330416,0.000000,1.330416,0.000000,0,9,pass,64,1.344375;1.330416;1.368250;1.355459;1.320791;1.322667;1.316250;1.328917;1.334500 +random,1024,8192,64,cpu_pool10_distance,0.657208,0.000000,0.657208,0.000000,0,9,pass,0,0.699125;0.687958;0.645250;0.685584;0.656208;0.638084;0.657792;0.654250;0.657208 +fabric,288,16384,1,cpu_full,0.109875,0.000000,0.109875,0.000000,0,9,pass,1,0.110875;0.110875;0.109834;0.109708;0.109875;0.109500;0.109541;0.113917;0.116625 +fabric,288,16384,1,cpu_distance,0.021542,0.000000,0.021542,0.000000,0,9,pass,0,0.022208;0.021625;0.021750;0.021667;0.021542;0.021500;0.021458;0.021375;0.021375 +fabric,288,16384,1,cpu_pool10,0.135458,0.000000,0.135458,0.000000,0,9,pass,1,0.133584;0.135666;0.133667;0.133542;0.137292;0.141667;0.135458;0.136208;0.130291 +fabric,288,16384,1,cpu_pool10_distance,0.039583,0.000000,0.039583,0.000000,0,9,pass,0,0.036625;0.038750;0.036875;0.041333;0.040791;0.041500;0.039583;0.040666;0.037458 +fabric,288,16384,64,cpu_full,7.310750,0.000000,7.310750,0.000000,0,9,pass,64,7.344708;7.291375;7.259292;7.500875;7.443000;7.251542;7.310750;7.236333;7.320583 +fabric,288,16384,64,cpu_distance,1.393958,0.000000,1.393958,0.000000,0,9,pass,0,1.388542;1.386750;1.402250;1.364583;1.427250;1.416834;1.427416;1.393917;1.393958 +fabric,288,16384,64,cpu_pool10,0.991791,0.000000,0.991791,0.000000,0,9,pass,64,1.373958;0.994750;0.972667;0.947500;1.129792;1.035750;0.958875;0.953333;0.991791 +fabric,288,16384,64,cpu_pool10_distance,0.219167,0.000000,0.219167,0.000000,0,9,pass,0,0.218291;0.221500;0.250875;0.233959;0.234083;0.219167;0.216541;0.212542;0.204333 +grid,1024,3968,1,cpu_full,0.045500,0.000000,0.045500,0.000000,0,9,pass,1,0.047542;0.044041;0.042958;0.044708;0.045500;0.045750;0.045042;0.045583;0.045833 +grid,1024,3968,1,cpu_distance,0.011750,0.000000,0.011750,0.000000,0,9,pass,0,0.012250;0.012083;0.012000;0.011834;0.011750;0.011708;0.011750;0.011750;0.011750 +grid,1024,3968,1,cpu_pool10,0.084417,0.000000,0.084417,0.000000,0,9,pass,1,0.094708;0.087625;0.076625;0.061000;0.084417;0.067833;0.096875;0.117792;0.078792 +grid,1024,3968,1,cpu_pool10_distance,0.045500,0.000000,0.045500,0.000000,0,9,pass,0,0.064333;0.045667;0.031125;0.033708;0.035250;0.053875;0.045500;0.041792;0.057500 +grid,1024,3968,64,cpu_full,4.000542,0.000000,4.000542,0.000000,0,9,pass,64,3.861917;4.025167;3.945917;3.903083;3.850167;4.000542;4.054667;4.033458;4.074458 +grid,1024,3968,64,cpu_distance,0.911416,0.000000,0.911416,0.000000,0,9,pass,0,0.911416;0.948042;1.001584;0.923792;0.934333;0.881667;0.869666;0.863375;0.878458 +grid,1024,3968,64,cpu_pool10,0.556209,0.000000,0.556209,0.000000,0,9,pass,64,0.582292;0.556209;0.572125;0.576792;0.514250;0.520333;0.565041;0.535541;0.523625 +grid,1024,3968,64,cpu_pool10_distance,0.157333,0.000000,0.157333,0.000000,0,9,pass,0,0.159250;0.156500;0.148250;0.157333;0.149000;0.169417;0.172209;0.159416;0.156792 +chain,256,255,1,cpu_full,0.002542,0.000000,0.002542,0.000000,0,9,pass,1,0.002667;0.002542;0.002584;0.002542;0.002542;0.002541;0.002583;0.002500;0.002500 +chain,256,255,1,cpu_distance,0.000958,0.000000,0.000958,0.000000,0,9,pass,0,0.000875;0.000958;0.000917;0.000958;0.001000;0.001000;0.000917;0.000959;0.000667 +chain,256,255,1,cpu_pool10,0.038084,0.000000,0.038084,0.000000,0,9,pass,1,0.049917;0.022958;0.059167;0.026500;0.041958;0.038084;0.036959;0.032916;0.039875 +chain,256,255,1,cpu_pool10_distance,0.032084,0.000000,0.032084,0.000000,0,9,pass,0,0.034417;0.027541;0.024833;0.059083;0.032084;0.036416;0.031375;0.035792;0.031709 +random_masked_int64_reverse,1024,8192,8,cpu_full,0.622542,0.000000,0.622542,0.000000,0,9,pass,8,0.656083;0.637375;0.623500;0.618166;0.612250;0.638208;0.621334;0.622542;0.615333 +random_masked_int64_reverse,1024,8192,8,cpu_distance,0.313375,0.000000,0.313375,0.000000,0,9,pass,0,0.455750;0.416334;0.353042;0.336416;0.311333;0.313375;0.298417;0.294709;0.274708 +random_masked_int64_reverse,1024,8192,8,cpu_pool10,0.149333,0.000000,0.149333,0.000000,0,9,pass,8,0.161500;0.170125;0.149333;0.148958;0.164959;0.147667;0.152334;0.145125;0.147209 +random_masked_int64_reverse,1024,8192,8,cpu_pool10_distance,0.094875,0.000000,0.094875,0.000000,0,9,pass,0,0.098500;0.094875;0.090916;0.093625;0.098708;0.092167;0.097417;0.095833;0.086709 +random,4096,32768,1,cpu_full,0.665250,0.000000,0.665250,0.000000,0,9,pass,1,0.705917;0.685375;0.671708;0.665250;0.653375;0.651750;0.648125;0.643875;0.835666 +random,4096,32768,1,cpu_distance,0.321708,0.000000,0.321708,0.000000,0,9,pass,0,0.410750;0.405125;0.388500;0.354875;0.321708;0.306916;0.311333;0.304709;0.306125 +random,4096,32768,1,cpu_pool10,0.846916,0.000000,0.846916,0.000000,0,9,pass,1,0.846916;0.862333;0.751875;0.909917;0.887167;0.744667;0.925958;0.837833;0.797042 +random,4096,32768,1,cpu_pool10_distance,0.419167,0.000000,0.419167,0.000000,0,9,pass,0,0.497750;0.422541;0.426500;0.419167;0.427625;0.391417;0.366791;0.368958;0.339334 +random,4096,32768,64,cpu_full,52.102750,0.000000,52.102750,0.000000,0,9,pass,64,54.203292;52.887375;53.023041;52.102750;52.049958;52.098542;51.865416;52.029500;52.275167 +random,4096,32768,64,cpu_distance,25.658708,0.000000,25.658708,0.000000,0,9,pass,0,25.682333;25.592583;25.472083;25.676084;25.588542;25.605833;25.926083;25.931125;25.658708 +random,4096,32768,64,cpu_pool10,5.952500,0.000000,5.952500,0.000000,0,9,pass,64,5.960083;5.958084;5.952500;5.969125;5.916334;5.945459;5.953625;5.943708;5.924416 +random,4096,32768,64,cpu_pool10_distance,2.946417,0.000000,2.946417,0.000000,0,9,pass,0,2.963708;2.961416;2.946417;2.949209;2.940333;2.938209;2.953708;2.929417;2.940166 +random,4096,32768,256,cpu_full,207.033042,0.000000,207.033042,0.000000,0,9,pass,256,208.565333;207.732417;206.951125;206.977250;206.746375;206.994000;207.033042;207.599666;207.870500 +random,4096,32768,256,cpu_distance,104.569458,0.000000,104.569458,0.000000,0,9,pass,0,105.489166;105.644292;104.210667;102.589875;104.569458;105.916375;103.105292;102.977125;107.510125 +random,4096,32768,256,cpu_pool10,23.386500,0.000000,23.386500,0.000000,0,9,pass,256,40.046458;23.359125;23.306292;23.386500;24.774417;23.782250;22.939459;22.685208;23.506417 +random,4096,32768,256,cpu_pool10_distance,11.367917,0.000000,11.367917,0.000000,0,9,pass,0,11.047292;10.975666;11.068375;11.096125;11.459875;11.367917;11.371333;11.403250;11.463708 +random,16384,131072,1,cpu_full,3.915167,0.000000,3.915167,0.000000,0,9,pass,1,3.871459;4.099250;4.174833;3.915167;4.067542;3.926667;3.831250;3.879667;3.870000 +random,16384,131072,1,cpu_distance,1.960417,0.000000,1.960417,0.000000,0,9,pass,0,2.021875;1.960417;1.889875;1.857792;2.170125;2.063458;2.063166;1.951458;1.904583 +random,16384,131072,1,cpu_pool10,3.940500,0.000000,3.940500,0.000000,0,9,pass,1,3.966375;3.874167;3.981292;4.094000;3.940500;4.023542;3.924041;3.918916;3.782834 +random,16384,131072,1,cpu_pool10_distance,2.005583,0.000000,2.005583,0.000000,0,9,pass,0,2.005583;2.140833;2.080500;2.099291;1.932666;2.019334;1.991167;1.966417;1.891875 +random,16384,131072,64,cpu_full,249.146417,0.000000,249.146417,0.000000,0,9,pass,64,252.116875;249.126041;248.933209;249.146417;248.897333;248.611000;260.195000;253.889292;251.157125 +random,16384,131072,64,cpu_distance,132.024792,0.000000,132.024792,0.000000,0,9,pass,0,131.589042;132.093459;131.786375;132.343417;132.024792;131.772916;131.826667;132.098333;135.958042 +random,16384,131072,64,cpu_pool10,28.429458,0.000000,28.429458,0.000000,0,9,pass,64,28.800875;29.234250;28.369500;28.398458;28.653125;28.380084;28.296458;29.236500;28.429458 +random,16384,131072,64,cpu_pool10_distance,15.058709,0.000000,15.058709,0.000000,0,9,pass,0,15.146458;15.097000;15.004334;15.058709;15.114167;15.033833;15.072750;14.995417;14.993083 +random,65536,524288,1,cpu_full,22.344958,0.000000,22.344958,0.000000,0,9,pass,1,20.957625;24.492167;21.762292;22.567791;23.338708;23.546042;22.344958;20.185500;20.875542 +random,65536,524288,1,cpu_distance,11.777084,0.000000,11.777084,0.000000,0,9,pass,0,10.724750;10.590250;10.794833;11.777084;12.048833;13.794083;19.637375;12.146958;11.220417 +random,65536,524288,1,cpu_pool10,21.763875,0.000000,21.763875,0.000000,0,9,pass,1,20.818541;20.408583;21.249875;21.763875;22.344583;21.183208;22.291542;22.923167;22.071500 +random,65536,524288,1,cpu_pool10_distance,10.599042,0.000000,10.599042,0.000000,0,9,pass,0,11.239875;11.393583;10.554125;10.913917;10.701125;10.246333;10.511791;10.435750;10.599042 +random,65536,524288,64,cpu_full,1286.349583,0.000000,1286.349583,0.000000,0,9,pass,64,1436.236750;1242.607958;1309.405000;1284.448917;1317.436833;1286.349583;1280.854542;1304.641916;1262.528792 +random,65536,524288,64,cpu_distance,687.072041,0.000000,687.072041,0.000000,0,9,pass,0,684.747959;695.653708;779.019209;761.691542;753.222334;687.072041;685.139583;682.279667;676.369750 +random,65536,524288,64,cpu_pool10,189.990250,0.000000,189.990250,0.000000,0,9,pass,64,185.822458;179.728458;185.915209;182.268708;189.990250;192.153125;192.239500;198.405625;190.860042 +random,65536,524288,64,cpu_pool10_distance,93.937500,0.000000,93.937500,0.000000,0,9,pass,0,99.322250;93.374583;93.937500;94.460250;87.558167;89.512333;88.269208;104.313125;95.677000 +chain,2048,2047,1,cpu_full,0.019666,0.000000,0.019666,0.000000,0,9,pass,1,0.019541;0.019542;0.019666;0.019791;0.019708;0.019791;0.019625;0.019625;0.019666 +chain,2048,2047,1,cpu_distance,0.004042,0.000000,0.004042,0.000000,0,9,pass,0,0.004209;0.004083;0.004042;0.004083;0.004042;0.004000;0.004042;0.004041;0.004209 +chain,2048,2047,1,cpu_pool10,0.048500,0.000000,0.048500,0.000000,0,9,pass,1,0.050000;0.044166;0.051875;0.049250;0.048500;0.044291;0.041708;0.047042;0.072375 +chain,2048,2047,1,cpu_pool10_distance,0.042333,0.000000,0.042333,0.000000,0,9,pass,0,0.062625;0.052375;0.035417;0.041667;0.042333;0.039750;0.045375;0.040334;0.063042 +random,4096,131072,1,cpu_full,1.762667,0.000000,1.762667,0.000000,0,9,pass,1,1.783083;1.739791;1.677667;1.630625;1.836959;1.791583;1.798959;1.762667;1.697500 +random,4096,131072,1,cpu_distance,0.680958,0.000000,0.680958,0.000000,0,9,pass,0,0.821875;0.748750;0.696833;0.677666;0.680958;0.664792;0.675959;0.692125;0.670458 +random,4096,131072,1,cpu_pool10,1.771417,0.000000,1.771417,0.000000,0,9,pass,1,1.784500;1.758750;1.775333;1.712750;1.894250;1.771417;1.747083;1.638625;1.985833 +random,4096,131072,1,cpu_pool10_distance,0.768625,0.000000,0.768625,0.000000,0,9,pass,0,0.760541;0.750709;0.868917;0.747375;0.830375;0.832375;0.811041;0.748417;0.768625 +random,4096,131072,64,cpu_full,114.166208,0.000000,114.166208,0.000000,0,9,pass,64,114.166208;116.409167;117.530542;116.397459;113.341167;114.552042;112.884375;113.846000;112.957667 +random,4096,131072,64,cpu_distance,50.983000,0.000000,50.983000,0.000000,0,9,pass,0,49.911458;52.691959;51.868542;51.245250;50.838875;50.500250;51.579291;50.983000;49.495584 +random,4096,131072,64,cpu_pool10,12.922583,0.000000,12.922583,0.000000,0,9,pass,64,12.922583;13.513000;12.838000;12.768708;12.765625;12.907458;12.986166;13.330500;12.955583 +random,4096,131072,64,cpu_pool10_distance,5.637750,0.000000,5.637750,0.000000,0,9,pass,0,5.667166;5.637750;5.624833;5.653125;5.619750;5.603500;5.658417;5.609250;5.802792 +clos,200,20000,1,cpu_full,0.144333,0.000000,0.144333,0.000000,0,9,pass,1,0.148333;0.146667;0.143875;0.144333;0.143083;0.142916;0.145292;0.143083;0.144583 +clos,200,20000,1,cpu_distance,0.023875,0.000000,0.023875,0.000000,0,9,pass,0,0.024500;0.024583;0.025375;0.023916;0.023875;0.023625;0.023709;0.023833;0.023708 +clos,200,20000,1,cpu_pool10,0.181708,0.000000,0.181708,0.000000,0,9,pass,1,0.195084;0.181834;0.174416;0.181708;0.185958;0.175625;0.172917;0.182959;0.177958 +clos,200,20000,1,cpu_pool10_distance,0.045791,0.000000,0.045791,0.000000,0,9,pass,0,0.045125;0.044042;0.045959;0.044208;0.044125;0.045791;0.051208;0.053792;0.047958 +clos,200,20000,64,cpu_full,9.353375,0.000000,9.353375,0.000000,0,9,pass,64,9.553375;9.510625;9.461208;9.351667;9.505875;9.271583;9.353375;9.296625;9.265625 +clos,200,20000,64,cpu_distance,1.548583,0.000000,1.548583,0.000000,0,9,pass,0,1.557625;1.542666;1.548583;1.566084;1.550334;1.554500;1.535959;1.540042;1.542584 +clos,200,20000,64,cpu_pool10,1.698750,0.000000,1.698750,0.000000,0,9,pass,64,1.173084;2.027625;1.917583;1.160792;1.453625;1.748917;1.155959;1.698750;1.717292 +clos,200,20000,64,cpu_pool10_distance,0.208292,0.000000,0.208292,0.000000,0,9,pass,0,0.202125;0.205000;0.210625;0.208292;0.209000;0.211875;0.209833;0.204000;0.205084 +clos,800,320000,1,cpu_full,2.367500,0.000000,2.367500,0.000000,0,9,pass,1,2.290667;2.292958;2.367500;2.330167;2.377042;2.379000;2.437042;2.441333;2.338166 +clos,800,320000,1,cpu_distance,0.354709,0.000000,0.354709,0.000000,0,9,pass,0,0.354416;0.354709;0.368084;0.354375;0.354916;0.354459;0.355250;0.354125;0.354833 +clos,800,320000,1,cpu_pool10,2.355459,0.000000,2.355459,0.000000,0,9,pass,1,2.333708;2.340416;2.323208;2.343625;2.355459;2.450958;2.476583;2.390417;2.366000 +clos,800,320000,1,cpu_pool10_distance,0.384625,0.000000,0.384625,0.000000,0,9,pass,0,0.390750;0.377542;0.374417;0.393666;0.384625;0.371542;0.365750;0.433833;0.465958 +clos,800,320000,64,cpu_full,150.499083,0.000000,150.499083,0.000000,0,9,pass,64,150.015333;149.947166;150.499083;156.703375;152.934333;149.782625;148.341584;150.854583;152.985292 +clos,800,320000,64,cpu_distance,23.215333,0.000000,23.215333,0.000000,0,9,pass,0,23.143708;23.199416;23.217792;23.347208;23.196417;23.255250;23.228292;23.215333;23.190166 +clos,800,320000,64,cpu_pool10,17.633500,0.000000,17.633500,0.000000,0,9,pass,64,18.064708;17.153916;17.209292;17.633500;18.146959;17.173000;17.843000;17.199125;18.153375 +clos,800,320000,64,cpu_pool10_distance,2.661125,0.000000,2.661125,0.000000,0,9,pass,0,2.661792;2.661125;2.652542;2.656709;2.671125;2.672625;2.656959;2.663500;2.651500 +grid,10000,39600,1,cpu_full,0.616459,0.000000,0.616459,0.000000,0,9,pass,1,0.626625;0.616459;0.613167;0.613625;0.625416;0.613000;0.608542;0.639750;0.714666 +grid,10000,39600,1,cpu_distance,0.183167,0.000000,0.183167,0.000000,0,9,pass,0,0.196583;0.182042;0.193041;0.183167;0.183584;0.199417;0.177208;0.178875;0.180833 +grid,10000,39600,1,cpu_pool10,0.698583,0.000000,0.698583,0.000000,0,9,pass,1,0.721334;0.700833;0.734208;0.698333;0.704459;0.686333;0.682375;0.698583;0.695333 +grid,10000,39600,1,cpu_pool10_distance,0.203416,0.000000,0.203416,0.000000,0,9,pass,0,0.205958;0.199667;0.214250;0.198750;0.205666;0.203416;0.192709;0.208667;0.193792 +grid,10000,39600,8,cpu_full,5.581208,0.000000,5.581208,0.000000,0,9,pass,8,5.578792;5.599916;5.618333;5.582417;5.581208;5.543958;5.535083;5.537709;5.587084 +grid,10000,39600,8,cpu_distance,1.567875,0.000000,1.567875,0.000000,0,9,pass,0,1.580000;1.576542;1.555958;1.555125;1.567875;1.579667;1.546834;1.552584;1.587292 +grid,10000,39600,8,cpu_pool10,0.817917,0.000000,0.817917,0.000000,0,9,pass,8,0.801417;0.817917;0.823250;0.824500;0.808833;0.838833;0.810916;0.840542;0.804375 +grid,10000,39600,8,cpu_pool10_distance,0.246125,0.000000,0.246125,0.000000,0,9,pass,0,0.253875;0.246125;0.244458;0.240583;0.246709;0.250500;0.241417;0.254875;0.241833 +grid,40000,159200,1,cpu_full,2.937459,0.000000,2.937459,0.000000,0,9,pass,1,2.965208;2.922333;2.901166;2.931000;2.937459;2.923958;2.956375;2.958417;3.028584 +grid,40000,159200,1,cpu_distance,0.877667,0.000000,0.877667,0.000000,0,9,pass,0,0.877667;0.871375;0.900625;0.874333;0.858875;0.877792;0.873958;0.895041;0.924417 +grid,40000,159200,1,cpu_pool10,3.069875,0.000000,3.069875,0.000000,0,9,pass,1,3.066875;3.098083;3.105208;3.176875;3.069875;3.004583;3.026041;3.023792;3.222750 +grid,40000,159200,1,cpu_pool10_distance,0.924708,0.000000,0.924708,0.000000,0,9,pass,0,0.936292;0.924708;0.929125;0.915334;0.884375;0.945375;0.927125;0.899667;0.890125 diff --git a/dev/research/metal_pathfinding/results/aba/b-stderr.txt b/dev/research/metal_pathfinding/results/aba/b-stderr.txt new file mode 100644 index 0000000..5985671 --- /dev/null +++ b/dev/research/metal_pathfinding/results/aba/b-stderr.txt @@ -0,0 +1 @@ +device=Apple M4 Max setup_ms=24.1354 execution_width=32 diff --git a/dev/research/metal_pathfinding/results/aba/b.csv b/dev/research/metal_pathfinding/results/aba/b.csv new file mode 100644 index 0000000..9be0375 --- /dev/null +++ b/dev/research/metal_pathfinding/results/aba/b.csv @@ -0,0 +1,69 @@ +case,n,e,queries,method,wall_ms,gpu_ms,distance_wall_ms,upload_ms,rounds,samples,correct,exact_order_queries,wall_samples_ms +random,128,1024,1,metal_pull,0.567417,0.322166,0.563459,0.019916,16,9,pass,0,0.602750;0.587458;0.567417;0.556208;0.548792;0.569833;0.601416;0.558500;0.566750 +random,128,1024,1,metal_group,0.251042,0.130875,0.247458,0.019916,9,9,pass,0,0.252625;0.251042;0.251041;0.251083;0.250791;0.250458;0.267250;0.280500;0.243125 +random,128,1024,1,metal_shared,0.242250,0.123542,0.238708,0.019916,9,9,pass,0,0.244125;0.240792;0.243250;0.242209;0.247542;0.370625;0.242250;0.240250;0.242042 +random,128,1024,64,metal_pull,0.857625,0.380292,0.638500,0.031459,16,9,pass,0,0.866750;0.833917;0.866208;0.857625;0.854625;0.869375;0.850458;0.844500;0.870542 +random,128,1024,64,metal_group,0.585250,0.179333,0.323750,0.031459,13,9,pass,0,0.516250;0.630916;0.534417;0.511167;0.585250;0.585291;0.586250;0.577042;1.320875 +random,128,1024,64,metal_shared,0.526625,0.168792,0.290916,0.031459,13,9,pass,0,0.526625;0.530375;0.533208;0.516334;0.532167;0.540000;0.520250;0.520958;0.524625 +random,1024,8192,1,metal_pull,0.706541,0.431458,0.672833,0.063792,16,9,pass,0,0.708958;0.706541;0.683500;0.696333;0.716708;0.703208;0.702042;0.706542;0.709250 +random,1024,8192,1,metal_group,0.898959,0.679542,0.828542,0.063792,13,9,pass,0,0.874041;0.952625;0.835417;0.958875;0.956334;0.957792;0.836917;0.834667;0.898959 +random,1024,8192,1,metal_shared,0.855917,0.640000,0.787083,0.063792,13,9,pass,0,0.795708;0.898333;0.792708;0.855917;0.934083;0.924583;0.848958;0.892709;0.798875 +random,1024,8192,64,metal_pull,4.632416,1.600792,2.329459,0.066041,24,9,pass,0,4.332500;4.367000;4.657500;4.592333;4.674958;4.290750;4.916542;4.632416;4.770708 +random,1024,8192,64,metal_group,3.383708,0.822625,1.053875,0.066041,17,9,pass,0,3.680667;3.598500;3.752959;3.733166;3.379375;3.383708;3.346375;3.052459;3.109458 +random,1024,8192,64,metal_shared,3.647125,0.827375,1.293500,0.066041,17,9,pass,0,2.843375;3.248042;3.677583;3.657959;3.652542;3.647125;3.590833;3.698167;3.128125 +fabric,288,16384,1,metal_pull,0.584500,0.408625,0.523791,0.100625,8,9,pass,0,0.611375;0.592875;0.576625;0.585417;0.584500;0.579167;0.918042;0.567042;0.565459 +fabric,288,16384,1,metal_group,0.773084,0.583125,0.709625,0.100625,3,9,pass,0,0.327667;0.503125;0.767875;0.773084;0.791375;0.774750;0.777583;0.780084;0.761833 +fabric,288,16384,1,metal_shared,0.737875,0.555167,0.679958,0.100625,3,9,pass,0,0.739417;0.739875;0.736542;0.761292;0.918042;0.733042;0.737875;0.731083;0.726666 +fabric,288,16384,64,metal_pull,5.875333,1.801583,2.368750,0.132416,8,9,pass,0,6.109209;5.987041;5.790292;5.954583;5.768875;5.917583;5.761416;5.875333;5.816042 +fabric,288,16384,64,metal_group,4.538083,0.652000,1.189125,0.132416,3,9,pass,0,4.560458;4.799042;4.693917;4.400916;4.460208;4.538083;4.538041;4.492500;4.595333 +fabric,288,16384,64,metal_shared,4.551917,0.631000,1.168166,0.132416,3,9,pass,0,4.407250;4.394208;4.624959;4.553750;4.580375;4.241083;4.558125;4.551917;4.439542 +grid,1024,3968,1,metal_pull,1.681000,0.651333,1.668041,0.069500,64,9,pass,0,3.145792;1.681000;1.832667;1.848833;1.864125;1.546333;1.373083;1.407792;1.178375 +grid,1024,3968,1,metal_group,0.388208,0.227000,0.373083,0.069500,63,9,pass,0,0.387292;0.388208;0.388583;0.388750;0.385500;0.440667;0.387792;0.388583;0.387209 +grid,1024,3968,1,metal_shared,0.374459,0.213375,0.359417,0.069500,63,9,pass,0,0.365709;0.375708;0.376375;0.374459;0.374375;0.369500;0.375667;0.372625;0.378083 +grid,1024,3968,64,metal_pull,2.805208,0.405750,1.965292,0.049083,64,9,pass,0,3.028000;3.075959;2.952958;2.663000;2.846458;2.737833;2.370708;2.250000;2.805208 +grid,1024,3968,64,metal_group,1.723750,0.206625,0.854125,0.049083,63,9,pass,0,1.723750;1.217917;1.237792;1.618083;1.954292;1.625958;1.766209;1.758125;1.827375 +grid,1024,3968,64,metal_shared,1.775500,0.195250,0.870750,0.049083,63,9,pass,0,1.726416;1.202875;1.847292;1.667541;1.777375;1.775500;1.795250;1.679000;1.792250 +chain,256,255,1,metal_pull,4.188292,0.508375,4.186625,0.062958,256,9,pass,1,4.498417;4.636458;4.241791;4.533875;4.188292;3.823209;3.755125;3.775666;3.508791 +chain,256,255,1,metal_group,0.225292,0.132750,0.224000,0.062958,256,9,pass,1,0.224542;0.229375;0.228458;0.227375;0.225292;0.223292;0.222709;0.224208;0.324750 +chain,256,255,1,metal_shared,0.229792,0.122250,0.228458,0.062958,256,9,pass,1,0.230500;0.227917;0.228000;0.218333;0.235750;0.229792;0.231167;0.230375;0.222041 +random_masked_int64_reverse,1024,8192,8,metal_pull,0.522875,0.032125,0.135209,0.090500,8,9,pass,1,0.511834;0.544083;0.563459;0.534917;0.562042;0.507209;0.522875;0.520583;0.507917 +random_masked_int64_reverse,1024,8192,8,metal_group,0.531875,0.053625,0.158542,0.090500,8,9,pass,1,0.527416;0.562709;0.514000;0.537875;0.531875;0.519292;0.523708;0.546541;0.538459 +random_masked_int64_reverse,1024,8192,8,metal_shared,0.526041,0.049917,0.159333,0.090500,8,9,pass,1,0.514334;0.539375;0.533833;0.518833;0.512709;0.557000;0.524750;0.526041;0.547541 +random,4096,32768,1,metal_pull,0.458167,0.106292,0.325875,0.184875,16,9,pass,0,0.458042;0.453625;0.463291;0.451416;0.457791;0.462958;0.458167;0.465000;0.529708 +random,4096,32768,1,metal_group,1.031083,0.737750,0.873125,0.184875,16,9,pass,0,1.038458;1.004667;0.969208;0.976291;1.031083;1.036333;1.075125;0.979417;1.085459 +random,4096,32768,64,metal_pull,13.708083,2.607750,3.892709,0.228209,24,9,pass,0,19.328916;12.469084;12.552083;18.668167;13.211458;18.690625;13.948333;13.708083;12.846250 +random,4096,32768,64,metal_group,12.983292,2.521375,3.123333,0.228209,19,9,pass,0,11.323000;11.705708;12.151083;12.648958;12.983292;13.544500;13.467916;14.265500;14.300583 +random,4096,32768,256,metal_pull,49.690584,9.834250,11.281292,0.220667,24,9,pass,0,49.880458;49.319875;49.208292;49.690584;50.530375;49.900583;49.381000;49.333916;50.406125 +random,4096,32768,256,metal_group,47.235458,8.198500,8.931625,0.220667,20,9,pass,0,48.244833;48.005541;46.817625;46.219417;46.147375;46.081250;47.235458;56.480959;51.777709 +random,16384,131072,1,metal_pull,1.529042,0.427750,0.892000,0.595375,24,9,pass,0,2.015375;1.495250;1.529042;1.527875;1.600917;1.563125;1.599542;1.528292;1.519417 +random,16384,131072,1,metal_group,5.643083,4.789500,4.978750,0.595375,18,9,pass,0,5.749875;5.666792;5.650041;5.599667;5.643083;5.604333;5.611708;5.601166;5.683917 +random,16384,131072,64,metal_pull,58.410458,11.548458,13.326750,0.663209,24,9,pass,0,67.121166;57.667833;58.470167;57.913459;58.156250;58.410458;59.990625;61.279500;58.239084 +random,16384,131072,64,metal_group,54.004166,8.331625,9.176375,0.663209,22,9,pass,0,54.397292;54.004166;53.502291;53.214125;52.934375;66.739042;54.280541;54.790833;53.420042 +random,65536,524288,1,metal_pull,4.921875,0.846833,1.920917,2.726125,24,9,pass,0,6.001291;5.252834;4.935458;4.593417;4.787125;4.773958;4.849458;4.921875;5.000417 +random,65536,524288,1,metal_group,31.772208,28.237500,28.881750,2.726125,22,9,pass,0,31.775041;31.772208;31.570917;31.932708;31.588333;31.742625;32.067125;31.611333;32.124917 +random,65536,524288,64,metal_pull,278.466208,78.681083,80.713958,2.758750,32,9,pass,0,281.715833;280.435583;278.466208;281.948125;277.973000;277.116458;281.096833;266.919750;276.584625 +random,65536,524288,64,metal_group,277.240041,77.399292,78.233042,2.758750,25,9,pass,0,278.460875;277.240041;273.348500;274.964750;277.577750;281.394417;273.737042;273.665000;280.961666 +chain,2048,2047,1,metal_pull,28.527166,4.077999,28.517125,0.065792,2048,9,pass,1,29.465125;29.033125;28.804292;28.516417;28.424041;28.197667;28.328708;28.647750;28.527166 +chain,2048,2047,1,metal_group,4.803792,4.693375,4.793333,0.065792,2048,9,pass,1,4.799833;4.803792;4.848750;4.903459;4.850958;4.797625;4.800458;4.854666;4.799416 +random,4096,131072,1,metal_pull,0.842792,0.254458,0.451708,0.581791,16,9,pass,0,0.838875;0.832625;0.823042;0.842792;0.843417;0.834083;0.854458;0.886917;0.861834 +random,4096,131072,1,metal_group,2.677375,2.169000,2.272500,0.581791,12,9,pass,0,2.698875;2.772292;2.643875;2.677375;2.720708;2.809459;2.660750;2.642417;2.643792 +random,4096,131072,64,metal_pull,35.841000,6.486458,8.086625,0.641875,16,9,pass,0,35.841000;35.529625;35.501708;35.851209;34.786084;35.420083;37.314042;38.495375;38.841625 +random,4096,131072,64,metal_group,35.625625,7.266500,7.957042,0.641875,15,9,pass,0,32.706541;33.508083;33.932792;37.469041;35.970166;35.835375;35.625625;35.057250;35.728792 +clos,200,20000,1,metal_pull,0.928583,0.457833,0.859500,0.122584,8,9,pass,0,1.622417;1.091250;0.843625;1.078542;1.037583;0.765958;0.783041;0.928583;0.390333 +clos,200,20000,1,metal_group,0.260833,0.063333,0.197625,0.122584,3,9,pass,0,0.234208;0.237334;0.251208;0.250708;0.282042;0.268625;0.260833;0.291875;0.268208 +clos,200,20000,1,metal_shared,0.253875,0.059500,0.190000,0.122584,3,9,pass,0,0.254834;0.253083;0.253125;0.252833;0.255250;0.253875;0.257084;0.253667;0.256458 +clos,200,20000,64,metal_pull,5.757625,1.018167,1.556333,0.129209,8,9,pass,0,5.767959;5.609834;5.724250;5.673250;5.757625;5.656250;5.840625;5.759333;5.932584 +clos,200,20000,64,metal_group,5.121500,0.300292,0.831667,0.129209,3,9,pass,0,5.121500;5.192666;5.247041;5.146750;5.005208;4.946208;5.251791;5.036250;4.973417 +clos,200,20000,64,metal_shared,5.014750,0.294792,0.884542,0.129209,3,9,pass,0,5.155125;5.007708;5.014750;5.007417;5.045417;5.119459;5.008125;5.027000;4.946958 +clos,800,320000,1,metal_pull,2.688750,1.320875,1.690291,1.198250,8,9,pass,0,5.262625;4.836667;2.426042;1.908625;2.955417;4.635917;2.688750;1.943125;2.464041 +clos,800,320000,1,metal_group,3.609042,2.091917,2.558959,1.198250,3,9,pass,0,2.589541;5.534292;5.195666;3.609042;2.121750;2.612750;2.684584;5.583500;4.444583 +clos,800,320000,1,metal_shared,2.589500,0.886333,1.607250,1.198250,3,9,pass,0,2.055708;2.589500;5.415708;5.412917;2.020792;2.759542;2.584042;2.544167;3.905959 +clos,800,320000,64,metal_pull,84.243334,17.155875,17.769125,1.222459,8,9,pass,0,85.693292;82.820583;84.810666;85.224834;85.088417;84.171083;83.663167;82.692000;84.243334 +clos,800,320000,64,metal_group,72.947292,5.246625,5.806292,1.222459,3,9,pass,0,73.739000;72.666209;72.213333;73.495000;73.113167;72.947292;72.646917;72.817208;73.371959 +clos,800,320000,64,metal_shared,72.451792,5.047375,5.681500,1.222459,3,9,pass,0,72.509583;73.012750;72.451792;71.838583;72.226000;71.746875;72.920042;71.717500;73.992291 +grid,10000,39600,1,metal_pull,5.348750,2.243750,5.217083,0.188000,200,9,pass,0,5.705000;5.633250;5.483041;5.417042;5.337041;5.326500;5.348750;5.246000;5.313625 +grid,10000,39600,1,metal_group,7.826000,7.551000,7.692791,0.188000,199,9,pass,0,7.837625;7.825416;7.803542;7.800167;7.832833;7.832208;7.836458;7.812709;7.826000 +grid,10000,39600,8,metal_pull,6.016250,1.352667,4.932792,0.180625,200,9,pass,0,6.059625;5.488791;5.902791;6.103208;5.938250;6.325250;6.016250;5.983042;6.140208 +grid,10000,39600,8,metal_group,9.135500,7.427292,8.073792,0.180625,199,9,pass,0,8.722000;8.678750;9.158917;9.133459;9.125792;9.135500;9.266750;9.217875;9.343875 +grid,40000,159200,1,metal_pull,8.408041,1.743417,7.867500,0.554416,400,9,pass,0,9.057583;9.127500;8.940416;8.546416;8.408041;7.482041;7.682875;7.581166;7.693792 +grid,40000,159200,1,metal_group,65.239125,64.260458,64.756208,0.554416,399,9,pass,0,64.734541;65.239125;65.375083;64.894917;65.609625;66.268041;65.783375;64.778250;64.975083 diff --git a/dev/research/metal_pathfinding/results/aba/environment.txt b/dev/research/metal_pathfinding/results/aba/environment.txt new file mode 100644 index 0000000..b039362 --- /dev/null +++ b/dev/research/metal_pathfinding/results/aba/environment.txt @@ -0,0 +1,17 @@ +2026-09-26T23:07:34Z +fbab119e794c843838f4f3f96d75cb7f32f06845 +ProductName: macOS +ProductVersion: 26.6.1 +BuildVersion: 25G76 +Apple M4 Max +38654705664 +14 +Apple clang version 21.0.0 (clang-2100.1.1.101) +Target: arm64-apple-darwin25.6.0 +Thread model: posix +InstalledDir: /Library/Developer/CommandLineTools/usr/bin +1da9ff77bd2ad97e95e951454821b25005859c6f75c27a3c56d925e5fc99f6fc dev/research/metal_pathfinding/experiment.mm +2e36b1623a3940bf1f19f5d81141bb1def14f5873fe2a98aab0101bbe68618a3 dev/research/metal_pathfinding/sssp.metal +Note: No thermal warning level has been recorded +Note: No performance warning level has been recorded +Note: No CPU power status has been recorded diff --git a/dev/research/metal_pathfinding/results/aba/gpu-load-a1.txt b/dev/research/metal_pathfinding/results/aba/gpu-load-a1.txt new file mode 100644 index 0000000..7b19971 --- /dev/null +++ b/dev/research/metal_pathfinding/results/aba/gpu-load-a1.txt @@ -0,0 +1 @@ + | "PerformanceStatistics" = {"In use system memory (driver)"=0,"Alloc system memory"=11028365312,"Tiler Utilization %"=5,"recoveryCount"=0,"lastRecoveryTime"=0,"Renderer Utilization %"=8,"TiledSceneBytes"=2326528,"Device Utilization %"=8,"SplitSceneCount"=0,"Allocated PB Size"=190316544,"In use system memory"=1562312704} diff --git a/dev/research/metal_pathfinding/results/aba/gpu-load-a2.txt b/dev/research/metal_pathfinding/results/aba/gpu-load-a2.txt new file mode 100644 index 0000000..63385cb --- /dev/null +++ b/dev/research/metal_pathfinding/results/aba/gpu-load-a2.txt @@ -0,0 +1 @@ + | "PerformanceStatistics" = {"In use system memory (driver)"=0,"Alloc system memory"=11064967168,"Tiler Utilization %"=1,"recoveryCount"=0,"lastRecoveryTime"=0,"Renderer Utilization %"=3,"TiledSceneBytes"=1736704,"Device Utilization %"=75,"SplitSceneCount"=0,"Allocated PB Size"=192806912,"In use system memory"=1753808896} diff --git a/dev/research/metal_pathfinding/results/aba/gpu-load-b.txt b/dev/research/metal_pathfinding/results/aba/gpu-load-b.txt new file mode 100644 index 0000000..7edec31 --- /dev/null +++ b/dev/research/metal_pathfinding/results/aba/gpu-load-b.txt @@ -0,0 +1 @@ + | "PerformanceStatistics" = {"In use system memory (driver)"=0,"Alloc system memory"=11040063488,"Tiler Utilization %"=3,"recoveryCount"=0,"lastRecoveryTime"=0,"Renderer Utilization %"=5,"TiledSceneBytes"=2326528,"Device Utilization %"=5,"SplitSceneCount"=0,"Allocated PB Size"=191889408,"In use system memory"=1626095616} diff --git a/dev/research/metal_pathfinding/results/aba/load-a1.txt b/dev/research/metal_pathfinding/results/aba/load-a1.txt new file mode 100644 index 0000000..dad8c67 --- /dev/null +++ b/dev/research/metal_pathfinding/results/aba/load-a1.txt @@ -0,0 +1,40 @@ +Processes: 1026 total, 3 running, 1023 sleeping, 5227 threads +2026/09/27 00:07:35 +Load Avg: 2.50, 3.63, 4.23 +CPU usage: 3.63% user, 8.76% sys, 87.60% idle +SharedLibs: 914M resident, 168M data, 135M linkedit. +MemRegions: 625179 total, 9927M resident, 739M private, 4203M shared. +PhysMem: 33G used (4233M wired, 633M compressor), 1868M unused. +VM: 452T vsize, 6144M framework vsize, 2843905(0) swapins, 4729331(0) swapouts. +Networks: packets: 190194634/161G in, 145611011/163G out. +Disks: 97549297/2475G read, 117292342/2098G written. + +PID COMMAND %CPU #TH +99753 mscamerad-xpc 0.0 2 +99752 PlugInLibrarySer 0.0 2 +99750 QuickLookUIServi 0.0 3 +99749 com.apple.appkit 0.0 3 +99710 PlugInLibrarySer 0.0 2 +99709 Preview 0.0 4 +99428 crashpad_handler 0.0 4 +98995 crashpad_handler 0.0 4 +Processes: 1026 total, 2 running, 1024 sleeping, 5225 threads +2026/09/27 00:07:36 +Load Avg: 2.54, 3.62, 4.22 +CPU usage: 5.65% user, 4.27% sys, 90.7% idle +SharedLibs: 914M resident, 168M data, 135M linkedit. +MemRegions: 0 total, 0B resident, 739M private, 4203M shared. +PhysMem: 33G used (4198M wired, 633M compressor), 1875M unused. +VM: 452T vsize, 6144M framework vsize, 2843905(0) swapins, 4729331(0) swapouts. +Networks: packets: 190194809/161G in, 145611193/163G out. +Disks: 97549297/2475G read, 117292347/2098G written. + +PID COMMAND %CPU #TH +70968 Superset Helper 22.2 32 +590 WindowServer 16.0 30 +0 kernel_task 10.7 850/14 +80307 top 8.9 1/1 +65401 codex 6.0 38 +70942 Superset Helper 5.4 18 +21666 2.1.283 4.7 28 +70934 Superset 4.3 51 diff --git a/dev/research/metal_pathfinding/results/aba/load-a2.txt b/dev/research/metal_pathfinding/results/aba/load-a2.txt new file mode 100644 index 0000000..153a0a0 --- /dev/null +++ b/dev/research/metal_pathfinding/results/aba/load-a2.txt @@ -0,0 +1,40 @@ +Processes: 1028 total, 2 running, 1026 sleeping, 5254 threads +2026/09/27 00:09:05 +Load Avg: 2.84, 3.47, 4.10 +CPU usage: 11.34% user, 14.82% sys, 73.82% idle +SharedLibs: 914M resident, 168M data, 135M linkedit. +MemRegions: 638481 total, 10G resident, 741M private, 4225M shared. +PhysMem: 34G used (4167M wired, 632M compressor), 1555M unused. +VM: 454T vsize, 6144M framework vsize, 2843921(0) swapins, 4729331(0) swapouts. +Networks: packets: 190245179/161G in, 145633207/163G out. +Disks: 97561084/2475G read, 117298099/2098G written. + +PID COMMAND %CPU #TH +99753 mscamerad-xpc 0.0 2 +99752 PlugInLibrarySer 0.0 2 +99750 QuickLookUIServi 0.0 3 +99749 com.apple.appkit 0.0 3 +99710 PlugInLibrarySer 0.0 2 +99709 Preview 0.0 4 +99428 crashpad_handler 0.0 4 +98995 crashpad_handler 0.0 4 +Processes: 1029 total, 9 running, 1020 sleeping, 5311 threads +2026/09/27 00:09:06 +Load Avg: 2.84, 3.47, 4.10 +CPU usage: 15.54% user, 11.8% sys, 73.37% idle +SharedLibs: 914M resident, 168M data, 135M linkedit. +MemRegions: 33 total, 80K resident, 741M private, 4226M shared. +PhysMem: 34G used (4371M wired, 632M compressor), 1526M unused. +VM: 455T vsize, 6144M framework vsize, 2843921(0) swapins, 4729331(0) swapouts. +Networks: packets: 190245522/161G in, 145633548/163G out. +Disks: 97561090/2475G read, 117298104/2098G written. + +PID COMMAND %CPU #TH +70968 Superset Helper 33.8 32 +590 WindowServer 31.2 29/1 +0 kernel_task 15.1 850/14 +70969 Superset 14.9 23 +70942 Superset Helper 9.4 18 +70934 Superset 7.9 51 +89777 top 6.0 1/1 +554 opendirectoryd 4.5 9/1 diff --git a/dev/research/metal_pathfinding/results/aba/load-b.txt b/dev/research/metal_pathfinding/results/aba/load-b.txt new file mode 100644 index 0000000..c761959 --- /dev/null +++ b/dev/research/metal_pathfinding/results/aba/load-b.txt @@ -0,0 +1,40 @@ +Processes: 1028 total, 2 running, 1026 sleeping, 5258 threads +2026/09/27 00:08:33 +Load Avg: 2.69, 3.51, 4.14 +CPU usage: 4.4% user, 9.48% sys, 86.46% idle +SharedLibs: 914M resident, 168M data, 135M linkedit. +MemRegions: 638285 total, 10G resident, 741M private, 4228M shared. +PhysMem: 34G used (4218M wired, 632M compressor), 1622M unused. +VM: 454T vsize, 6144M framework vsize, 2843921(0) swapins, 4729331(0) swapouts. +Networks: packets: 190237774/161G in, 145624667/163G out. +Disks: 97549658/2475G read, 117296556/2098G written. + +PID COMMAND %CPU #TH +99753 mscamerad-xpc 0.0 2 +99752 PlugInLibrarySer 0.0 2 +99750 QuickLookUIServi 0.0 3 +99749 com.apple.appkit 0.0 3 +99710 PlugInLibrarySer 0.0 2 +99709 Preview 0.0 4 +99428 crashpad_handler 0.0 4 +98995 crashpad_handler 0.0 4 +Processes: 1027 total, 2 running, 1025 sleeping, 5243 threads +2026/09/27 00:08:34 +Load Avg: 2.69, 3.51, 4.14 +CPU usage: 5.44% user, 3.79% sys, 90.75% idle +SharedLibs: 914M resident, 168M data, 135M linkedit. +MemRegions: 0 total, 0B resident, 741M private, 4228M shared. +PhysMem: 33G used (4259M wired, 632M compressor), 1761M unused. +VM: 452T vsize, 6144M framework vsize, 2843921(0) swapins, 4729331(0) swapouts. +Networks: packets: 190237907/161G in, 145624794/163G out. +Disks: 97549658/2475G read, 117296557/2098G written. + +PID COMMAND %CPU #TH +70968 Superset Helper 18.0 32 +590 WindowServer 17.7 29 +0 kernel_task 11.5 850/14 +81804 2.1.283 8.8 27 +84786 top 8.5 1/1 +70942 Superset Helper 7.0 19 +39757 codex 4.0 36 +21666 2.1.283 3.5 28 diff --git a/dev/research/metal_pathfinding/results/aba/summary.md b/dev/research/metal_pathfinding/results/aba/summary.md new file mode 100644 index 0000000..3f5a20f --- /dev/null +++ b/dev/research/metal_pathfinding/results/aba/summary.md @@ -0,0 +1,74 @@ +Exploratory observations, not a production performance acceptance result. +Inspect load-*.txt and gpu-load-*.txt; speedup claims require a quiet machine. +The prototype matches supported DAG edge sets, not CPU predecessor order. + +All times are medians in milliseconds per batch, with nine timed samples. +CPU A columns use serial SPF for Q=1 and the 10-worker pool otherwise. +GPU includes host distance copies and serial CPU ECMP DAG reconstruction. +Upload and pipeline setup are excluded and recorded separately in raw data. +The table picks the fastest measured GPU method for each case. + +| Case | V / E | Q | CPU A1 | GPU B | CPU A2 | GPU method | Distance-only B | CPU drift | +|---|---:|---:|---:|---:|---:|---|---:|---:| +| random | 128 / 1,024 | 1 | 0.031 | 0.242 | 0.010 | metal_shared | 0.239 | -67.4% | +| random | 128 / 1,024 | 64 | 0.234 | 0.527 | 0.162 | metal_shared | 0.291 | -30.7% | +| random | 1,024 / 8,192 | 1 | 0.145 | 0.707 | 0.115 | metal_pull | 0.673 | -21.0% | +| random | 1,024 / 8,192 | 64 | 1.273 | 3.384 | 1.330 | metal_group | 1.054 | +4.5% | +| fabric | 288 / 16,384 | 1 | 0.107 | 0.585 | 0.110 | metal_pull | 0.524 | +3.0% | +| fabric | 288 / 16,384 | 64 | 1.011 | 4.538 | 0.992 | metal_group | 1.189 | -1.9% | +| grid | 1,024 / 3,968 | 1 | 0.037 | 0.374 | 0.045 | metal_shared | 0.359 | +22.8% | +| grid | 1,024 / 3,968 | 64 | 0.498 | 1.724 | 0.556 | metal_group | 0.854 | +11.6% | +| chain | 256 / 255 | 1 | 0.002 | 0.225 | 0.003 | metal_group | 0.224 | +13.0% | +| random_masked_int64_reverse | 1,024 / 8,192 | 8 | 0.150 | 0.523 | 0.149 | metal_pull | 0.135 | -0.2% | +| random | 4,096 / 32,768 | 1 | 0.641 | 0.458 | 0.665 | metal_pull | 0.326 | +3.8% | +| random | 4,096 / 32,768 | 64 | 5.984 | 12.983 | 5.952 | metal_group | 3.123 | -0.5% | +| random | 4,096 / 32,768 | 256 | 23.461 | 47.235 | 23.387 | metal_group | 8.932 | -0.3% | +| random | 16,384 / 131,072 | 1 | 4.095 | 1.529 | 3.915 | metal_pull | 0.892 | -4.4% | +| random | 16,384 / 131,072 | 64 | 28.290 | 54.004 | 28.429 | metal_group | 9.176 | +0.5% | +| random | 65,536 / 524,288 | 1 | 20.762 | 4.922 | 22.345 | metal_pull | 1.921 | +7.6% | +| random | 65,536 / 524,288 | 64 | 174.082 | 277.240 | 189.990 | metal_group | 78.233 | +9.1% | +| chain | 2,048 / 2,047 | 1 | 0.020 | 4.804 | 0.020 | metal_group | 4.793 | -1.1% | +| random | 4,096 / 131,072 | 1 | 1.762 | 0.843 | 1.763 | metal_pull | 0.452 | +0.0% | +| random | 4,096 / 131,072 | 64 | 12.774 | 35.626 | 12.923 | metal_group | 7.957 | +1.2% | +| clos | 200 / 20,000 | 1 | 0.146 | 0.254 | 0.144 | metal_shared | 0.190 | -1.4% | +| clos | 200 / 20,000 | 64 | 1.181 | 5.015 | 1.699 | metal_shared | 0.885 | +43.9% | +| clos | 800 / 320,000 | 1 | 2.330 | 2.590 | 2.368 | metal_shared | 1.607 | +1.6% | +| clos | 800 / 320,000 | 64 | 17.462 | 72.452 | 17.634 | metal_shared | 5.681 | +1.0% | +| grid | 10,000 / 39,600 | 1 | 0.614 | 5.349 | 0.616 | metal_pull | 5.217 | +0.4% | +| grid | 10,000 / 39,600 | 8 | 0.829 | 6.016 | 0.818 | metal_pull | 4.933 | -1.3% | +| grid | 40,000 / 159,200 | 1 | 2.913 | 8.408 | 2.937 | metal_pull | 7.867 | +0.9% | + +Distance-only timings stop before DAG reconstruction; they are not SPF API timings. +CPU distance-only and serial full-batch controls are also available in a1/a2.csv. + +Distances-only comparison (both sides omit DAG construction): + +| Case | V / E | Q | CPU A1 | GPU B | CPU A2 | GPU method | +|---|---:|---:|---:|---:|---:|---| +| random | 128 / 1,024 | 1 | 0.011 | 0.239 | 0.005 | metal_shared | +| random | 128 / 1,024 | 64 | 0.126 | 0.291 | 0.102 | metal_shared | +| random | 1,024 / 8,192 | 1 | 0.080 | 0.673 | 0.056 | metal_pull | +| random | 1,024 / 8,192 | 64 | 0.634 | 1.054 | 0.657 | metal_group | +| fabric | 288 / 16,384 | 1 | 0.022 | 0.524 | 0.022 | metal_pull | +| fabric | 288 / 16,384 | 64 | 0.194 | 1.168 | 0.219 | metal_shared | +| grid | 1,024 / 3,968 | 1 | 0.010 | 0.359 | 0.012 | metal_shared | +| grid | 1,024 / 3,968 | 64 | 0.146 | 0.854 | 0.157 | metal_group | +| chain | 256 / 255 | 1 | 0.001 | 0.224 | 0.001 | metal_group | +| random_masked_int64_reverse | 1,024 / 8,192 | 8 | 0.093 | 0.135 | 0.095 | metal_pull | +| random | 4,096 / 32,768 | 1 | 0.305 | 0.326 | 0.322 | metal_pull | +| random | 4,096 / 32,768 | 64 | 2.968 | 3.123 | 2.946 | metal_group | +| random | 4,096 / 32,768 | 256 | 12.019 | 8.932 | 11.368 | metal_group | +| random | 16,384 / 131,072 | 1 | 2.076 | 0.892 | 1.960 | metal_pull | +| random | 16,384 / 131,072 | 64 | 14.898 | 9.176 | 15.059 | metal_group | +| random | 65,536 / 524,288 | 1 | 10.450 | 1.921 | 11.777 | metal_pull | +| random | 65,536 / 524,288 | 64 | 85.846 | 78.233 | 93.938 | metal_group | +| chain | 2,048 / 2,047 | 1 | 0.004 | 4.793 | 0.004 | metal_group | +| random | 4,096 / 131,072 | 1 | 0.665 | 0.452 | 0.681 | metal_pull | +| random | 4,096 / 131,072 | 64 | 5.610 | 7.957 | 5.638 | metal_group | +| clos | 200 / 20,000 | 1 | 0.024 | 0.190 | 0.024 | metal_shared | +| clos | 200 / 20,000 | 64 | 0.211 | 0.832 | 0.208 | metal_group | +| clos | 800 / 320,000 | 1 | 0.356 | 1.607 | 0.355 | metal_shared | +| clos | 800 / 320,000 | 64 | 2.672 | 5.681 | 2.661 | metal_shared | +| grid | 10,000 / 39,600 | 1 | 0.175 | 5.217 | 0.183 | metal_pull | +| grid | 10,000 / 39,600 | 8 | 0.247 | 4.933 | 0.246 | metal_pull | +| grid | 40,000 / 159,200 | 1 | 0.863 | 7.867 | 0.878 | metal_pull | diff --git a/dev/research/metal_pathfinding/results/audit.json b/dev/research/metal_pathfinding/results/audit.json new file mode 100644 index 0000000..a218315 --- /dev/null +++ b/dev/research/metal_pathfinding/results/audit.json @@ -0,0 +1,44 @@ +{ + "a1": { + "rows": 108, + "queries_checked_including_warmups": 40744 + }, + "b": { + "rows": 68, + "queries_checked_including_warmups": 24761 + }, + "a2": { + "rows": 108, + "queries_checked_including_warmups": 40744 + }, + "correctness.csv": { + "rows": 36, + "queries_checked_including_warmups": 1152 + }, + "correctness-sanitized.csv": { + "rows": 36, + "queries_checked_including_warmups": 1152 + }, + "stress.csv": { + "rows": 6, + "queries_checked_including_warmups": 39168 + }, + "stress-sanitized.csv": { + "rows": 6, + "queries_checked_including_warmups": 8448 + }, + "cpu-sanitized.csv": { + "rows": 40, + "queries_checked_including_warmups": 3228 + }, + "experiment.mm_sha256": "1da9ff77bd2ad97e95e951454821b25005859c6f75c27a3c56d925e5fc99f6fc", + "sssp.metal_sha256": "2e36b1623a3940bf1f19f5d81141bb1def14f5873fe2a98aab0101bbe68618a3", + "core_commit": "fbab119e794c843838f4f3f96d75cb7f32f06845", + "quiet_machine_gate_passed": false, + "performance_claim_approved": false, + "ci_run": false, + "production_backend_added": false, + "core_cpp_tests": 170, + "core_python_tests": 465, + "core_sanitizer_tests": 170 +} diff --git a/dev/research/metal_pathfinding/results/capabilities.txt b/dev/research/metal_pathfinding/results/capabilities.txt new file mode 100644 index 0000000..95b9ad1 --- /dev/null +++ b/dev/research/metal_pathfinding/results/capabilities.txt @@ -0,0 +1,31 @@ +device=Apple M4 Max unified=1 max_buffer=22613000192 +probe=0 compiled=1 +probe=1 compiled=0 +program_source:3:25: error: 'double' is not supported in Metal +kernel void test(device double* x [[buffer(0)]], uint i [[thread_position_in_grid]]) { x[i] += 1.0; } + ^ + +probe=2 compiled=0 +program_source:3:58: error: no matching function for call to 'atomic_fetch_min_explicit' +kernel void test(device atomic_ulong* x [[buffer(0)]]) { atomic_fetch_min_explicit(x, 1ul, memory_order_relaxed); } + ^~~~~~~~~~~~~~~~~~~~~~~~~ +/System/Library/PrivateFrameworks/GPUCompiler.framework/Versions/32023/Libraries/lib/clang/32023.886/include/metal/metal_atomic:552:14: note: candidate template ignored: requirement '_valid_fetch_min_type::value' was not satisfied [with T = unsigned long, U = unsigned long] +METAL_FUNC T atomic_fetch_min_explicit( + ^ +/System/Library/PrivateFrameworks/GPUCompiler.framework/Versions/32023/Libraries/lib/clang/32023.886/include/metal/metal_atomic:560:14: note: candidate template ignored: requirement '_valid_fetch_min_type::value' was not satisfied [with T = unsigned long, U = unsigned long] +METAL_FUNC T atomic_fetch_min_explicit( + ^ + +probe=3 compiled=1 +probe=4 compiled=1 +probe=5 compiled=0 +program_source:3:96: error: no matching function for call to 'atomic_load_explicit' +kernel void test(device atomic_ulong* x [[buffer(0)]], device ulong* y [[buffer(1)]]) { y[0] = atomic_load_explicit(x, memory_order_relaxed); } + ^~~~~~~~~~~~~~~~~~~~ +/System/Library/PrivateFrameworks/GPUCompiler.framework/Versions/32023/Libraries/lib/clang/32023.886/include/metal/metal_atomic:240:14: note: candidate template ignored: requirement '_valid_load_type::value' was not satisfied [with T = unsigned long] +METAL_FUNC T atomic_load_explicit( + ^ +/System/Library/PrivateFrameworks/GPUCompiler.framework/Versions/32023/Libraries/lib/clang/32023.886/include/metal/metal_atomic:247:14: note: candidate template ignored: requirement '_valid_load_type::value' was not satisfied [with T = unsigned long] +METAL_FUNC T atomic_load_explicit( + ^ + diff --git a/dev/research/metal_pathfinding/results/correctness-sanitized.csv b/dev/research/metal_pathfinding/results/correctness-sanitized.csv new file mode 100644 index 0000000..a77e150 --- /dev/null +++ b/dev/research/metal_pathfinding/results/correctness-sanitized.csv @@ -0,0 +1,37 @@ +case,n,e,queries,method,wall_ms,gpu_ms,distance_wall_ms,upload_ms,rounds,samples,correct,exact_order_queries,wall_samples_ms +random_masked_int64,40,240,8,metal_pull,1.263750,0.395000,1.205458,0.053958,8,2,pass,7,1.263750;0.901542 +random_masked_int64,40,240,8,metal_group,0.652583,0.283916,0.607084,0.053958,6,2,pass,7,0.617708;0.652583 +random_masked_int64,40,240,8,metal_shared,0.951500,0.198250,0.906541,0.053958,6,2,pass,7,0.860042;0.951500 +random_masked,43,258,8,metal_pull,1.944458,0.886917,1.892250,0.033375,16,2,pass,0,1.755792;1.944458 +random_masked,43,258,8,metal_group,0.756125,0.419417,0.707625,0.033375,9,2,pass,0,0.756125;0.754584 +random_masked,43,258,8,metal_shared,0.661750,0.313667,0.615750,0.033375,9,2,pass,0,0.661750;0.640542 +random_masked_int64_reverse,46,276,8,metal_pull,0.567792,0.068875,0.519583,0.023333,8,2,pass,1,0.567792;0.486209 +random_masked_int64_reverse,46,276,8,metal_group,0.468083,0.033042,0.422375,0.023333,5,2,pass,1,0.393167;0.468083 +random_masked_int64_reverse,46,276,8,metal_shared,0.370541,0.027708,0.323542,0.023333,5,2,pass,1,0.363958;0.370541 +random_masked,49,294,8,metal_pull,0.528250,0.096292,0.480834,0.022084,8,2,pass,2,0.528250;0.518416 +random_masked,49,294,8,metal_group,0.450542,0.078042,0.397875,0.022084,8,2,pass,2,0.430209;0.450542 +random_masked,49,294,8,metal_shared,0.382750,0.060834,0.333750,0.022084,8,2,pass,2,0.382750;0.373667 +random_masked_int64,52,312,8,metal_pull,0.583250,0.108417,0.531208,0.024708,8,2,pass,7,0.583250;0.549291 +random_masked_int64,52,312,8,metal_group,0.568667,0.062125,0.516500,0.024708,6,2,pass,7,0.568667;0.434666 +random_masked_int64,52,312,8,metal_shared,0.390209,0.050000,0.336334,0.024708,6,2,pass,7,0.390209;0.381666 +random_masked_reverse,55,330,8,metal_pull,0.955500,0.137167,0.904750,0.024250,16,2,pass,0,0.932875;0.955500 +random_masked_reverse,55,330,8,metal_group,0.400375,0.056750,0.342417,0.024250,10,2,pass,0,0.388125;0.400375 +random_masked_reverse,55,330,8,metal_shared,0.516750,0.046250,0.459417,0.024250,10,2,pass,0,0.498875;0.516750 +random_masked_int64,58,348,8,metal_pull,0.521208,0.088875,0.463542,0.028666,8,2,pass,7,0.521208;0.514292 +random_masked_int64,58,348,8,metal_group,0.375292,0.045500,0.314708,0.028666,5,2,pass,7,0.375292;0.371792 +random_masked_int64,58,348,8,metal_shared,0.372625,0.039250,0.314083,0.028666,5,2,pass,7,0.369333;0.372625 +random_masked,61,366,8,metal_pull,1.079708,0.210875,1.013334,0.021459,16,2,pass,1,1.034542;1.079708 +random_masked,61,366,8,metal_group,0.427291,0.089750,0.367750,0.021459,9,2,pass,1,0.427291;0.422917 +random_masked,61,366,8,metal_shared,0.399166,0.071916,0.342667,0.021459,9,2,pass,1,0.399166;0.389709 +random_masked_int64_reverse,64,384,8,metal_pull,0.487667,0.070375,0.426917,0.023333,8,2,pass,1,0.483333;0.487667 +random_masked_int64_reverse,64,384,8,metal_group,0.373917,0.033750,0.314708,0.023333,5,2,pass,1,0.364750;0.373917 +random_masked_int64_reverse,64,384,8,metal_shared,0.374791,0.027750,0.315333,0.023333,5,2,pass,1,0.374791;0.344833 +random_masked,67,402,8,metal_pull,0.648583,0.089542,0.517833,0.027542,8,2,pass,0,0.523500;0.648583 +random_masked,67,402,8,metal_group,0.459166,0.066708,0.391292,0.027542,8,2,pass,0,0.459166;0.427208 +random_masked,67,402,8,metal_shared,0.461292,0.123750,0.397750,0.027542,8,2,pass,0,0.441083;0.461292 +random_masked_int64,70,420,8,metal_pull,0.568167,0.100208,0.484084,0.023667,8,2,pass,3,0.568167;0.519291 +random_masked_int64,70,420,8,metal_group,0.412083,0.060250,0.350416,0.023667,6,2,pass,3,0.400500;0.412083 +random_masked_int64,70,420,8,metal_shared,0.675834,0.206875,0.605291,0.023667,6,2,pass,3,0.675834;0.557083 +random_masked_reverse,73,438,8,metal_pull,1.424125,0.585833,1.358291,0.028083,16,2,pass,0,1.424125;1.365500 +random_masked_reverse,73,438,8,metal_group,0.718042,0.249750,0.652875,0.028083,10,2,pass,0,0.623667;0.718042 +random_masked_reverse,73,438,8,metal_shared,0.596708,0.202250,0.526333,0.028083,10,2,pass,0,0.596708;0.561417 diff --git a/dev/research/metal_pathfinding/results/correctness-stderr.txt b/dev/research/metal_pathfinding/results/correctness-stderr.txt new file mode 100644 index 0000000..0c58358 --- /dev/null +++ b/dev/research/metal_pathfinding/results/correctness-stderr.txt @@ -0,0 +1 @@ +device=Apple M4 Max setup_ms=23.9988 execution_width=32 diff --git a/dev/research/metal_pathfinding/results/correctness.csv b/dev/research/metal_pathfinding/results/correctness.csv new file mode 100644 index 0000000..ab8100c --- /dev/null +++ b/dev/research/metal_pathfinding/results/correctness.csv @@ -0,0 +1,37 @@ +case,n,e,queries,method,wall_ms,gpu_ms,distance_wall_ms,upload_ms,rounds,samples,correct,exact_order_queries,wall_samples_ms +random_masked_int64,40,240,8,metal_pull,0.295708,0.129833,0.277459,0.016125,8,2,pass,7,0.295708;0.284042 +random_masked_int64,40,240,8,metal_group,0.210458,0.068708,0.203291,0.016125,6,2,pass,7,0.191750;0.210458 +random_masked_int64,40,240,8,metal_shared,0.587333,0.074583,0.580834,0.016125,6,2,pass,7,0.495125;0.587333 +random_masked,43,258,8,metal_pull,0.841500,0.289833,0.833625,0.023083,16,2,pass,0,0.841500;0.760584 +random_masked,43,258,8,metal_group,0.232041,0.105375,0.223667,0.023083,9,2,pass,0,0.232041;0.230958 +random_masked,43,258,8,metal_shared,0.225208,0.099375,0.218333,0.023083,9,2,pass,0,0.223292;0.225208 +random_masked_int64_reverse,46,276,8,metal_pull,0.547208,0.104125,0.527583,0.027750,8,2,pass,1,0.232750;0.547208 +random_masked_int64_reverse,46,276,8,metal_group,0.175709,0.044708,0.168125,0.027750,5,2,pass,1,0.172292;0.175709 +random_masked_int64_reverse,46,276,8,metal_shared,0.180708,0.042125,0.173916,0.027750,5,2,pass,1,0.180708;0.180334 +random_masked,49,294,8,metal_pull,0.273208,0.125083,0.253625,0.018125,8,2,pass,2,0.261041;0.273208 +random_masked,49,294,8,metal_group,0.236250,0.093750,0.227083,0.018125,8,2,pass,2,0.226666;0.236250 +random_masked,49,294,8,metal_shared,0.222125,0.088000,0.213500,0.018125,8,2,pass,2,0.222125;0.222125 +random_masked_int64,52,312,8,metal_pull,0.289833,0.150542,0.280541,0.017708,8,2,pass,7,0.276834;0.289833 +random_masked_int64,52,312,8,metal_group,0.212750,0.077125,0.194041,0.017708,6,2,pass,7,0.212750;0.205125 +random_masked_int64,52,312,8,metal_shared,0.204459,0.072667,0.196167,0.017708,6,2,pass,7,0.203125;0.204459 +random_masked_reverse,55,330,8,metal_pull,0.457667,0.212375,0.447292,0.017084,16,2,pass,0,0.457667;0.437583 +random_masked_reverse,55,330,8,metal_group,0.200458,0.074208,0.192000,0.017084,10,2,pass,0,0.200458;0.193541 +random_masked_reverse,55,330,8,metal_shared,0.184667,0.069417,0.176000,0.017084,10,2,pass,0,0.184667;0.183125 +random_masked_int64,58,348,8,metal_pull,0.266375,0.117667,0.256625,0.013333,8,2,pass,7,0.250167;0.266375 +random_masked_int64,58,348,8,metal_group,0.180209,0.057667,0.170667,0.013333,5,2,pass,7,0.180209;0.177625 +random_masked_int64,58,348,8,metal_shared,0.248583,0.142375,0.239083,0.013333,5,2,pass,7,0.248583;0.183667 +random_masked,61,366,8,metal_pull,0.525791,0.273333,0.515166,0.015292,16,2,pass,1,0.525791;0.515458 +random_masked,61,366,8,metal_group,0.236833,0.110000,0.226958,0.015292,9,2,pass,1,0.233750;0.236833 +random_masked,61,366,8,metal_shared,0.227042,0.103208,0.217375,0.015292,9,2,pass,1,0.227042;0.225792 +random_masked_int64_reverse,64,384,8,metal_pull,0.374125,0.102208,0.359166,0.012708,8,2,pass,1,0.374125;0.239125 +random_masked_int64_reverse,64,384,8,metal_group,0.222541,0.045000,0.167750,0.012708,5,2,pass,1,0.222541;0.190041 +random_masked_int64_reverse,64,384,8,metal_shared,0.187667,0.042625,0.173541,0.012708,5,2,pass,1,0.183959;0.187667 +random_masked,67,402,8,metal_pull,0.260875,0.118875,0.248459,0.019167,8,2,pass,0,0.248834;0.260875 +random_masked,67,402,8,metal_group,0.250791,0.084792,0.227666,0.019167,8,2,pass,0,0.223333;0.250791 +random_masked,67,402,8,metal_shared,0.267833,0.079750,0.256333,0.019167,8,2,pass,0,0.267833;0.215541 +random_masked_int64,70,420,8,metal_pull,0.397708,0.232000,0.379083,0.020375,8,2,pass,3,0.390583;0.397708 +random_masked_int64,70,420,8,metal_group,0.253125,0.075250,0.220625,0.020375,6,2,pass,3,0.242750;0.253125 +random_masked_int64,70,420,8,metal_shared,0.242166,0.071083,0.213625,0.020375,6,2,pass,3,0.221834;0.242166 +random_masked_reverse,73,438,8,metal_pull,1.053542,0.734042,1.034042,0.031625,16,2,pass,0,1.053542;0.504542 +random_masked_reverse,73,438,8,metal_group,0.240750,0.073791,0.227708,0.031625,10,2,pass,0,0.240750;0.221834 +random_masked_reverse,73,438,8,metal_shared,0.269792,0.069167,0.226000,0.031625,10,2,pass,0,0.269792;0.250833 diff --git a/dev/research/metal_pathfinding/results/cpu-sanitized.csv b/dev/research/metal_pathfinding/results/cpu-sanitized.csv new file mode 100644 index 0000000..84f0bcf --- /dev/null +++ b/dev/research/metal_pathfinding/results/cpu-sanitized.csv @@ -0,0 +1,41 @@ +case,n,e,queries,method,wall_ms,gpu_ms,distance_wall_ms,upload_ms,rounds,samples,correct,exact_order_queries,wall_samples_ms +random,128,1024,1,cpu_full,0.097375,0.000000,0.097375,0.000000,0,1,pass,1,0.097375 +random,128,1024,1,cpu_distance,0.030375,0.000000,0.030375,0.000000,0,1,pass,0,0.030375 +random,128,1024,1,cpu_pool10,0.166000,0.000000,0.166000,0.000000,0,1,pass,1,0.166000 +random,128,1024,1,cpu_pool10_distance,0.077291,0.000000,0.077291,0.000000,0,1,pass,0,0.077291 +random,128,1024,64,cpu_full,4.778583,0.000000,4.778583,0.000000,0,1,pass,64,4.778583 +random,128,1024,64,cpu_distance,1.507292,0.000000,1.507292,0.000000,0,1,pass,0,1.507292 +random,128,1024,64,cpu_pool10,0.686542,0.000000,0.686542,0.000000,0,1,pass,64,0.686542 +random,128,1024,64,cpu_pool10_distance,0.330625,0.000000,0.330625,0.000000,0,1,pass,0,0.330625 +random,1024,8192,1,cpu_full,0.539375,0.000000,0.539375,0.000000,0,1,pass,1,0.539375 +random,1024,8192,1,cpu_distance,0.188375,0.000000,0.188375,0.000000,0,1,pass,0,0.188375 +random,1024,8192,1,cpu_pool10,0.586917,0.000000,0.586917,0.000000,0,1,pass,1,0.586917 +random,1024,8192,1,cpu_pool10_distance,0.240834,0.000000,0.240834,0.000000,0,1,pass,0,0.240834 +random,1024,8192,64,cpu_full,34.944792,0.000000,34.944792,0.000000,0,1,pass,64,34.944792 +random,1024,8192,64,cpu_distance,13.138375,0.000000,13.138375,0.000000,0,1,pass,0,13.138375 +random,1024,8192,64,cpu_pool10,4.126666,0.000000,4.126666,0.000000,0,1,pass,64,4.126666 +random,1024,8192,64,cpu_pool10_distance,1.569333,0.000000,1.569333,0.000000,0,1,pass,0,1.569333 +fabric,288,16384,1,cpu_full,0.859542,0.000000,0.859542,0.000000,0,1,pass,1,0.859542 +fabric,288,16384,1,cpu_distance,0.116792,0.000000,0.116792,0.000000,0,1,pass,0,0.116792 +fabric,288,16384,1,cpu_pool10,0.838292,0.000000,0.838292,0.000000,0,1,pass,1,0.838292 +fabric,288,16384,1,cpu_pool10_distance,0.132208,0.000000,0.132208,0.000000,0,1,pass,0,0.132208 +fabric,288,16384,64,cpu_full,55.711541,0.000000,55.711541,0.000000,0,1,pass,64,55.711541 +fabric,288,16384,64,cpu_distance,8.051041,0.000000,8.051041,0.000000,0,1,pass,0,8.051041 +fabric,288,16384,64,cpu_pool10,6.186542,0.000000,6.186542,0.000000,0,1,pass,64,6.186542 +fabric,288,16384,64,cpu_pool10_distance,0.728208,0.000000,0.728208,0.000000,0,1,pass,0,0.728208 +grid,1024,3968,1,cpu_full,0.292625,0.000000,0.292625,0.000000,0,1,pass,1,0.292625 +grid,1024,3968,1,cpu_distance,0.067333,0.000000,0.067333,0.000000,0,1,pass,0,0.067333 +grid,1024,3968,1,cpu_pool10,0.291583,0.000000,0.291583,0.000000,0,1,pass,1,0.291583 +grid,1024,3968,1,cpu_pool10_distance,0.096125,0.000000,0.096125,0.000000,0,1,pass,0,0.096125 +grid,1024,3968,64,cpu_full,18.959167,0.000000,18.959167,0.000000,0,1,pass,64,18.959167 +grid,1024,3968,64,cpu_distance,4.468167,0.000000,4.468167,0.000000,0,1,pass,0,4.468167 +grid,1024,3968,64,cpu_pool10,2.241042,0.000000,2.241042,0.000000,0,1,pass,64,2.241042 +grid,1024,3968,64,cpu_pool10_distance,0.553875,0.000000,0.553875,0.000000,0,1,pass,0,0.553875 +chain,256,255,1,cpu_full,0.026584,0.000000,0.026584,0.000000,0,1,pass,1,0.026584 +chain,256,255,1,cpu_distance,0.007542,0.000000,0.007542,0.000000,0,1,pass,0,0.007542 +chain,256,255,1,cpu_pool10,0.055416,0.000000,0.055416,0.000000,0,1,pass,1,0.055416 +chain,256,255,1,cpu_pool10_distance,0.031166,0.000000,0.031166,0.000000,0,1,pass,0,0.031166 +random_masked_int64_reverse,1024,8192,8,cpu_full,2.706625,0.000000,2.706625,0.000000,0,1,pass,8,2.706625 +random_masked_int64_reverse,1024,8192,8,cpu_distance,0.929791,0.000000,0.929791,0.000000,0,1,pass,0,0.929791 +random_masked_int64_reverse,1024,8192,8,cpu_pool10,0.434375,0.000000,0.434375,0.000000,0,1,pass,8,0.434375 +random_masked_int64_reverse,1024,8192,8,cpu_pool10_distance,0.197500,0.000000,0.197500,0.000000,0,1,pass,0,0.197500 diff --git a/dev/research/metal_pathfinding/results/cpu-validation.txt b/dev/research/metal_pathfinding/results/cpu-validation.txt new file mode 100644 index 0000000..e69de29 diff --git a/dev/research/metal_pathfinding/results/rejected-race/a1-stderr.txt b/dev/research/metal_pathfinding/results/rejected-race/a1-stderr.txt new file mode 100644 index 0000000..e69de29 diff --git a/dev/research/metal_pathfinding/results/rejected-race/a1.csv b/dev/research/metal_pathfinding/results/rejected-race/a1.csv new file mode 100644 index 0000000..40a48a5 --- /dev/null +++ b/dev/research/metal_pathfinding/results/rejected-race/a1.csv @@ -0,0 +1,82 @@ +case,n,e,queries,method,wall_ms,gpu_ms,distance_wall_ms,upload_ms,rounds,samples,correct,exact_order_queries,wall_samples_ms +random,128,1024,1,cpu_full,0.009666,0.000000,0.009666,0.000000,0,9,pass,1,0.010500;0.011750;0.010709;0.009666;0.009375;0.010292;0.009458;0.009292;0.009375 +random,128,1024,1,cpu_distance,0.004750,0.000000,0.004750,0.000000,0,9,pass,0,0.004750;0.004875;0.006167;0.004583;0.004333;0.006292;0.005542;0.004583;0.004458 +random,128,1024,1,cpu_pool10,0.038167,0.000000,0.038167,0.000000,0,9,pass,1,0.062375;0.040667;0.050667;0.038167;0.043250;0.036875;0.035292;0.028667;0.034958 +random,128,1024,64,cpu_full,0.800000,0.000000,0.800000,0.000000,0,9,pass,64,0.907541;0.878042;0.845291;0.835625;0.800000;0.788042;0.781792;0.784208;0.773458 +random,128,1024,64,cpu_distance,0.396125,0.000000,0.396125,0.000000,0,9,pass,0,0.442208;0.424833;0.404792;0.394959;0.390000;0.399083;0.396125;0.387125;0.386542 +random,128,1024,64,cpu_pool10,0.170208,0.000000,0.170208,0.000000,0,9,pass,64,0.172209;0.167500;0.174958;0.158834;0.170208;0.166500;0.161167;0.198625;0.181000 +random,1024,8192,1,cpu_full,0.099084,0.000000,0.099084,0.000000,0,9,pass,1,0.103500;0.101375;0.098542;0.099209;0.097667;0.099417;0.099041;0.097583;0.099084 +random,1024,8192,1,cpu_distance,0.058041,0.000000,0.058041,0.000000,0,9,pass,0,0.060750;0.058041;0.056750;0.057167;0.056333;0.059542;0.062833;0.059875;0.056875 +random,1024,8192,1,cpu_pool10,0.165833,0.000000,0.165833,0.000000,0,9,pass,1,0.172125;0.203542;0.148416;0.124917;0.191000;0.166625;0.143292;0.165833;0.137583 +random,1024,8192,64,cpu_full,10.543584,0.000000,10.543584,0.000000,0,9,pass,64,10.571083;10.583583;10.586917;10.594250;10.498959;10.348333;10.482750;10.392041;10.543584 +random,1024,8192,64,cpu_distance,5.130416,0.000000,5.130416,0.000000,0,9,pass,0,5.130416;5.089708;5.094791;5.078417;5.263458;5.194500;5.156167;5.122708;5.251958 +random,1024,8192,64,cpu_pool10,1.302667,0.000000,1.302667,0.000000,0,9,pass,64,1.297875;1.289334;1.334458;1.313875;1.291750;1.302667;1.320209;1.273375;1.380250 +fabric,288,16384,1,cpu_full,0.111042,0.000000,0.111042,0.000000,0,9,pass,1,0.116416;0.114041;0.111042;0.115458;0.110375;0.110000;0.110709;0.111708;0.109916 +fabric,288,16384,1,cpu_distance,0.023375,0.000000,0.023375,0.000000,0,9,pass,0,0.023833;0.023792;0.023375;0.023459;0.023416;0.023167;0.023333;0.023250;0.023250 +fabric,288,16384,1,cpu_pool10,0.136584,0.000000,0.136584,0.000000,0,9,pass,1,0.139375;0.149417;0.133875;0.134542;0.136584;0.132542;0.150708;0.135167;0.144917 +fabric,288,16384,64,cpu_full,7.296542,0.000000,7.296542,0.000000,0,9,pass,64,7.296542;7.249084;7.306250;7.259250;7.382000;7.404750;7.204834;7.289084;7.365292 +fabric,288,16384,64,cpu_distance,1.513458,0.000000,1.513458,0.000000,0,9,pass,0,1.482000;1.522833;1.501708;1.522166;1.513458;1.513333;1.503958;1.553209;1.569583 +fabric,288,16384,64,cpu_pool10,0.958250,0.000000,0.958250,0.000000,0,9,pass,64,1.064625;0.943042;0.958250;0.963417;0.960708;0.981125;0.951500;0.927750;0.946458 +grid,1024,3968,1,cpu_full,0.042166,0.000000,0.042166,0.000000,0,9,pass,1,0.047375;0.045667;0.044083;0.042166;0.041458;0.043333;0.041167;0.041292;0.040875 +grid,1024,3968,1,cpu_distance,0.011958,0.000000,0.011958,0.000000,0,9,pass,0,0.012584;0.012167;0.012125;0.012167;0.011792;0.011792;0.011958;0.011750;0.011709 +grid,1024,3968,1,cpu_pool10,0.073917,0.000000,0.073917,0.000000,0,9,pass,1,0.086125;0.073917;0.087500;0.077750;0.067458;0.074667;0.070042;0.068750;0.066125 +grid,1024,3968,64,cpu_full,3.898167,0.000000,3.898167,0.000000,0,9,pass,64,3.895625;3.931583;3.898167;3.892791;3.934375;3.910291;3.882542;3.895417;3.907417 +grid,1024,3968,64,cpu_distance,0.937667,0.000000,0.937667,0.000000,0,9,pass,0,0.953584;0.920083;0.906583;0.896791;1.014416;0.992750;0.958250;0.937667;0.928916 +grid,1024,3968,64,cpu_pool10,0.528625,0.000000,0.528625,0.000000,0,9,pass,64,0.520500;0.554000;0.528625;0.520209;0.517667;0.490542;0.536000;0.590291;0.531209 +chain,256,255,1,cpu_full,0.002750,0.000000,0.002750,0.000000,0,9,pass,1,0.004250;0.002792;0.002708;0.002708;0.002750;0.002792;0.002709;0.002750;0.002667 +chain,256,255,1,cpu_distance,0.000666,0.000000,0.000666,0.000000,0,9,pass,0,0.000625;0.000583;0.000583;0.000542;0.000666;0.000708;0.000709;0.000709;0.000667 +chain,256,255,1,cpu_pool10,0.036333,0.000000,0.036333,0.000000,0,9,pass,1,0.022791;0.036333;0.039916;0.033958;0.034875;0.039209;0.040292;0.026375;0.037625 +random_masked_int64_reverse,1024,8192,8,cpu_full,0.637292,0.000000,0.637292,0.000000,0,9,pass,8,0.667833;0.637292;0.610000;0.586250;0.574125;0.568834;0.684500;0.703167;0.666542 +random_masked_int64_reverse,1024,8192,8,cpu_distance,0.300208,0.000000,0.300208,0.000000,0,9,pass,0,0.459750;0.389292;0.344250;0.303167;0.300208;0.288250;0.285292;0.279416;0.282959 +random_masked_int64_reverse,1024,8192,8,cpu_pool10,0.156000,0.000000,0.156000,0.000000,0,9,pass,8,0.159459;0.161625;0.149458;0.158792;0.152625;0.156000;0.159417;0.151959;0.150167 +random,4096,32768,1,cpu_full,0.631667,0.000000,0.631667,0.000000,0,9,pass,1,0.706459;0.669375;0.644166;0.631667;0.620542;0.617000;0.617833;0.601292;0.727000 +random,4096,32768,1,cpu_distance,0.329750,0.000000,0.329750,0.000000,0,9,pass,0,0.329750;0.340834;0.336292;0.338250;0.327792;0.317375;0.330875;0.304542;0.304708 +random,4096,32768,1,cpu_pool10,0.817667,0.000000,0.817667,0.000000,0,9,pass,1,0.845333;0.823416;0.817667;0.842500;0.807292;0.770000;0.722583;0.818916;0.761541 +random,4096,32768,64,cpu_full,52.210125,0.000000,52.210125,0.000000,0,9,pass,64,52.438458;52.412625;52.033666;52.333375;52.210125;51.993958;52.123292;52.159083;52.419041 +random,4096,32768,64,cpu_distance,26.296916,0.000000,26.296916,0.000000,0,9,pass,0,26.418875;26.417792;26.296916;26.482583;26.288958;26.609667;26.009667;26.031875;26.104125 +random,4096,32768,64,cpu_pool10,6.491792,0.000000,6.491792,0.000000,0,9,pass,64,6.491792;6.342875;6.799208;6.762459;6.705875;6.170292;6.229750;6.722625;6.462917 +random,4096,32768,256,cpu_full,209.806250,0.000000,209.806250,0.000000,0,9,pass,256,209.554292;211.988208;210.116500;209.288583;209.680917;209.828375;209.806250;209.382167;217.385875 +random,4096,32768,256,cpu_distance,105.298583,0.000000,105.298583,0.000000,0,9,pass,0,105.078250;105.298583;105.704542;105.054000;105.176084;105.098709;105.568833;105.914917;106.202334 +random,4096,32768,256,cpu_pool10,22.902917,0.000000,22.902917,0.000000,0,9,pass,256,22.643541;22.909667;22.902917;22.651667;23.214542;22.817000;23.036292;22.723583;22.937291 +random,16384,131072,1,cpu_full,3.829959,0.000000,3.829959,0.000000,0,9,pass,1,3.758083;4.336333;3.799417;3.741708;3.829959;3.751625;3.870791;3.908833;3.859792 +random,16384,131072,1,cpu_distance,1.911000,0.000000,1.911000,0.000000,0,9,pass,0,2.010083;1.909125;1.899250;1.850917;2.113667;2.056375;1.960000;1.911000;1.884875 +random,16384,131072,1,cpu_pool10,3.920375,0.000000,3.920375,0.000000,0,9,pass,1,3.819708;3.773125;4.272791;3.939208;3.692208;4.034500;3.920375;4.013833;3.866792 +random,16384,131072,64,cpu_full,251.553583,0.000000,251.553583,0.000000,0,9,pass,64,252.180500;251.192875;246.819666;251.553583;248.245708;246.188208;252.333084;252.777417;257.578000 +random,16384,131072,64,cpu_distance,132.990000,0.000000,132.990000,0.000000,0,9,pass,0,132.707583;134.917958;133.056834;132.915500;132.990000;132.365792;133.342708;133.048167;132.554875 +random,16384,131072,64,cpu_pool10,28.447375,0.000000,28.447375,0.000000,0,9,pass,64,28.610000;28.458042;28.357791;28.447375;28.609708;28.349416;28.265208;28.702541;28.418541 +random,65536,524288,1,cpu_full,20.940041,0.000000,20.940041,0.000000,0,9,pass,1,21.304334;20.860834;21.335416;20.838250;21.789875;20.292334;21.301250;20.940041;20.917500 +random,65536,524288,1,cpu_distance,11.158625,0.000000,11.158625,0.000000,0,9,pass,0,11.319166;10.996000;10.906125;11.023625;11.190708;10.960709;11.158625;11.208667;11.261834 +random,65536,524288,1,cpu_pool10,23.570334,0.000000,23.570334,0.000000,0,9,pass,1,21.283542;20.398708;22.447709;24.142625;24.654791;24.214250;23.570334;24.476750;22.815583 +random,65536,524288,64,cpu_full,1475.197459,0.000000,1475.197459,0.000000,0,9,pass,64,1384.978917;1475.197459;1464.451459;1485.729083;1612.075042;1686.816042;1673.231417;1429.034000;1386.365083 +random,65536,524288,64,cpu_distance,758.485125,0.000000,758.485125,0.000000,0,9,pass,0,762.178042;763.873042;766.125500;780.269292;758.485125;737.577708;741.359667;744.495709;755.063458 +random,65536,524288,64,cpu_pool10,199.161041,0.000000,199.161041,0.000000,0,9,pass,64,203.127916;199.161041;200.671042;200.809458;198.845500;198.417584;195.237833;199.019000;200.340792 +chain,2048,2047,1,cpu_full,0.019667,0.000000,0.019667,0.000000,0,9,pass,1,0.019459;0.019750;0.020000;0.019584;0.019542;0.019584;0.019708;0.019791;0.019667 +chain,2048,2047,1,cpu_distance,0.004042,0.000000,0.004042,0.000000,0,9,pass,0,0.004958;0.004917;0.004042;0.004416;0.003917;0.004000;0.003958;0.004875;0.004000 +chain,2048,2047,1,cpu_pool10,0.039084,0.000000,0.039084,0.000000,0,9,pass,1,0.043542;0.043291;0.037541;0.039084;0.037917;0.041167;0.033708;0.040000;0.036666 +random,4096,131072,1,cpu_full,1.723084,0.000000,1.723084,0.000000,0,9,pass,1,1.723084;1.816458;1.822000;1.715708;2.010917;1.749500;1.692459;1.691292;1.674250 +random,4096,131072,1,cpu_distance,0.712000,0.000000,0.712000,0.000000,0,9,pass,0,0.738875;0.716959;0.712000;0.700250;0.676166;0.678875;0.682958;0.762375;0.823833 +random,4096,131072,1,cpu_pool10,1.769500,0.000000,1.769500,0.000000,0,9,pass,1,1.757375;1.769500;1.803625;1.661250;1.808917;1.693666;1.652417;1.815417;2.108958 +random,4096,131072,64,cpu_full,114.542416,0.000000,114.542416,0.000000,0,9,pass,64,113.662709;114.371875;113.470208;113.180125;117.370209;114.542416;118.531125;118.463875;121.422042 +random,4096,131072,64,cpu_distance,52.960208,0.000000,52.960208,0.000000,0,9,pass,0,54.235500;54.562542;52.976500;52.960208;51.147458;50.654209;51.172625;52.637000;53.555875 +random,4096,131072,64,cpu_pool10,16.696333,0.000000,16.696333,0.000000,0,9,pass,64,17.632417;16.696333;17.935500;17.066958;16.540042;14.694666;23.514875;14.485291;13.440750 +clos,200,20000,1,cpu_full,0.147125,0.000000,0.147125,0.000000,0,9,pass,1,0.147375;0.146416;0.147000;0.146959;0.153333;0.147583;0.151167;0.147125;0.147000 +clos,200,20000,1,cpu_distance,0.026167,0.000000,0.026167,0.000000,0,9,pass,0,0.026750;0.026708;0.029041;0.026167;0.026167;0.029041;0.025834;0.026000;0.026125 +clos,200,20000,1,cpu_pool10,0.176417,0.000000,0.176417,0.000000,0,9,pass,1,0.202625;0.176417;0.178792;0.191833;0.176125;0.169833;0.169042;0.173541;0.188042 +clos,200,20000,64,cpu_full,9.558125,0.000000,9.558125,0.000000,0,9,pass,64,9.327083;9.558125;9.654875;9.680333;9.408292;9.393375;9.611375;9.525917;9.592459 +clos,200,20000,64,cpu_distance,1.738709,0.000000,1.738709,0.000000,0,9,pass,0,1.729000;1.729417;1.792625;1.745458;1.730167;1.869125;2.065958;1.738709;1.725625 +clos,200,20000,64,cpu_pool10,1.869167,0.000000,1.869167,0.000000,0,9,pass,64,2.808834;2.692000;2.343250;2.577292;1.869167;1.174959;1.203708;1.285250;1.219667 +clos,800,320000,1,cpu_full,2.567583,0.000000,2.567583,0.000000,0,9,pass,1,2.635000;2.553959;2.598042;2.565666;2.537542;2.567583;2.579542;2.595208;2.566083 +clos,800,320000,1,cpu_distance,0.407708,0.000000,0.407708,0.000000,0,9,pass,0,0.407042;0.407583;0.408167;0.407125;0.407708;0.410375;0.424583;0.415833;0.407334 +clos,800,320000,1,cpu_pool10,2.464458,0.000000,2.464458,0.000000,0,9,pass,1,2.607250;2.708625;2.449125;2.464458;2.431584;2.487958;2.421458;2.426583;2.499208 +clos,800,320000,64,cpu_full,155.384917,0.000000,155.384917,0.000000,0,9,pass,64,163.952083;155.384917;155.413125;151.858083;156.446167;155.488000;151.541084;151.281583;151.429750 +clos,800,320000,64,cpu_distance,25.811833,0.000000,25.811833,0.000000,0,9,pass,0,25.656209;25.709083;25.892292;25.811833;25.767625;25.899542;25.672500;26.257709;26.174416 +clos,800,320000,64,cpu_pool10,18.125041,0.000000,18.125041,0.000000,0,9,pass,64,19.433500;18.233833;17.844333;17.857167;17.345709;18.285458;17.183667;19.231542;18.125041 +grid,10000,39600,1,cpu_full,0.622375,0.000000,0.622375,0.000000,0,9,pass,1,0.625916;0.622375;0.615208;0.611750;0.614209;0.612917;0.682500;0.666667;0.656125 +grid,10000,39600,1,cpu_distance,0.181792,0.000000,0.181792,0.000000,0,9,pass,0,0.184250;0.183375;0.182917;0.181792;0.183083;0.180834;0.179042;0.179750;0.180209 +grid,10000,39600,1,cpu_pool10,0.709500,0.000000,0.709500,0.000000,0,9,pass,1,0.648792;0.709500;0.644084;0.637708;0.703416;0.730292;0.742167;0.750208;0.759833 +grid,10000,39600,8,cpu_full,5.845667,0.000000,5.845667,0.000000,0,9,pass,8,5.580833;5.744125;6.192083;5.945000;6.019250;6.081042;5.845667;5.556583;5.503542 +grid,10000,39600,8,cpu_distance,1.600833,0.000000,1.600833,0.000000,0,9,pass,0,1.679667;1.590959;1.575791;1.578458;1.564791;1.768875;1.621541;1.605458;1.600833 +grid,10000,39600,8,cpu_pool10,1.225333,0.000000,1.225333,0.000000,0,9,pass,8,0.858459;0.821167;0.901125;1.336292;1.225333;1.265792;1.339875;1.428417;1.167250 +grid,40000,159200,1,cpu_full,3.005208,0.000000,3.005208,0.000000,0,9,pass,1,3.052750;3.039291;3.014625;2.943125;2.901375;2.935542;3.052791;2.982208;3.005208 +grid,40000,159200,1,cpu_distance,0.861333,0.000000,0.861333,0.000000,0,9,pass,0,0.865708;0.860334;0.861333;0.857000;0.863750;0.860375;0.859708;0.953250;0.933792 +grid,40000,159200,1,cpu_pool10,3.089417,0.000000,3.089417,0.000000,0,9,pass,1,3.089417;2.962667;2.994000;3.129125;3.048042;3.150875;3.102834;2.986583;3.166417 diff --git a/dev/research/metal_pathfinding/results/rejected-race/b-stderr.txt b/dev/research/metal_pathfinding/results/rejected-race/b-stderr.txt new file mode 100644 index 0000000..7806da3 --- /dev/null +++ b/dev/research/metal_pathfinding/results/rejected-race/b-stderr.txt @@ -0,0 +1,2 @@ +device=Apple M4 Max setup_ms=29.6173 execution_width=32 +FAIL: distance mismatch at query 59 diff --git a/dev/research/metal_pathfinding/results/rejected-race/b.csv b/dev/research/metal_pathfinding/results/rejected-race/b.csv new file mode 100644 index 0000000..9126f3c --- /dev/null +++ b/dev/research/metal_pathfinding/results/rejected-race/b.csv @@ -0,0 +1,23 @@ +case,n,e,queries,method,wall_ms,gpu_ms,distance_wall_ms,upload_ms,rounds,samples,correct,exact_order_queries,wall_samples_ms +random,128,1024,1,metal_pull,0.816458,0.307250,0.812917,0.019833,16,9,pass,0,0.592208;0.819542;0.819458;0.816458;0.901334;0.811084;0.817583;0.560375;0.555250 +random,128,1024,1,metal_group,0.249250,0.129500,0.245459,0.019833,9,9,pass,0,0.269541;0.249250;0.257125;0.247125;0.242083;0.247875;0.248792;0.251792;0.253833 +random,128,1024,1,metal_shared,0.271792,0.122250,0.267583,0.019833,9,9,pass,0,0.268500;0.485333;0.264667;0.495959;0.361625;0.271792;0.494625;0.270625;0.244917 +random,128,1024,64,metal_pull,0.878042,0.346833,0.616208,0.061167,16,9,pass,0,0.898375;0.871459;0.857708;0.866667;0.878208;0.863583;0.878042;0.909083;0.938750 +random,128,1024,64,metal_group,0.569875,0.178625,0.308000,0.061167,13,9,pass,0,0.555916;0.559583;0.596000;0.651334;0.581583;0.575791;0.569875;0.567708;0.563708 +random,128,1024,64,metal_shared,0.537708,0.168042,0.295042,0.061167,13,9,pass,0,0.548917;0.549375;0.567167;0.531750;0.537708;0.601708;0.531583;0.516333;0.532208 +random,1024,8192,1,metal_pull,0.676250,0.397875,0.641792,0.083584,16,9,pass,0,0.703584;0.701583;0.679083;0.676250;0.663709;0.722417;0.666791;0.667666;0.656167 +random,1024,8192,1,metal_group,0.842583,0.678083,0.809167,0.083584,13,9,pass,0,1.298250;0.830208;0.842583;0.845167;0.841125;0.837417;0.840041;0.845750;0.852083 +random,1024,8192,1,metal_shared,0.811125,0.637792,0.775833,0.083584,13,9,pass,0,0.819959;0.808292;0.812000;0.811125;0.798291;0.811250;0.809458;0.813041;0.801084 +random,1024,8192,64,metal_pull,4.685833,1.546416,2.311167,0.097167,24,9,pass,0,4.668167;4.401916;5.264625;4.813000;4.743792;4.685833;4.779792;4.610958;4.660625 +random,1024,8192,64,metal_group,3.703708,0.886125,1.335375,0.097167,17,9,pass,0,3.703708;3.667417;3.495459;3.551833;3.825667;3.801500;3.883542;3.540250;3.747000 +random,1024,8192,64,metal_shared,3.640583,0.831125,1.256917,0.097167,17,9,pass,0,3.393333;3.665417;3.607333;3.547959;3.653458;3.624833;3.640583;3.653792;3.644208 +fabric,288,16384,1,metal_pull,1.831416,1.649458,1.774709,0.121750,8,9,pass,0,1.831416;1.898416;1.873500;1.825333;1.838958;1.826833;1.808167;2.394584;1.186584 +fabric,288,16384,1,metal_group,0.754041,0.575708,0.697125,0.121750,3,9,pass,0,0.759167;0.756791;0.754041;0.866458;0.763750;0.600625;0.514000;0.504291;0.568208 +fabric,288,16384,1,metal_shared,0.700750,0.507750,0.643667,0.121750,3,9,pass,0,0.749250;0.750541;0.729708;0.735500;0.700750;0.500625;0.499959;0.504042;0.564667 +fabric,288,16384,64,metal_pull,5.854333,1.801583,2.349125,0.128458,8,9,pass,0,5.230666;5.573292;6.165708;5.854333;5.898959;5.926500;5.789875;6.005459;5.788750 +fabric,288,16384,64,metal_group,4.626000,0.643250,1.182875,0.128458,3,9,pass,0,4.626000;4.593708;4.322292;4.596375;4.634209;4.741584;4.599625;4.722167;4.693709 +fabric,288,16384,64,metal_shared,4.613333,0.621375,1.159000,0.128458,3,9,pass,0,4.405417;4.666458;4.603375;4.603334;4.613333;4.720250;4.403458;4.680416;4.707125 +grid,1024,3968,1,metal_pull,1.759875,0.653875,1.743750,0.060083,64,9,pass,0,2.030541;1.759875;1.747459;2.255083;1.600958;2.206875;1.709500;1.800334;1.600042 +grid,1024,3968,1,metal_group,1.156208,1.000000,1.139875,0.060083,63,9,pass,0,1.154667;1.164959;1.157417;1.147209;1.134917;1.148125;1.156208;1.665167;1.197417 +grid,1024,3968,1,metal_shared,0.486500,0.345750,0.469042,0.060083,63,9,pass,0,0.498750;0.507834;0.482208;0.486500;0.488375;0.488166;0.465291;0.485917;0.467125 +grid,1024,3968,64,metal_pull,3.018000,0.569042,2.047500,0.095667,64,9,pass,0,3.018000;2.953667;3.431208;2.733709;2.995208;2.668375;3.199958;3.169250;3.109583 diff --git a/dev/research/metal_pathfinding/results/rejected-race/environment.txt b/dev/research/metal_pathfinding/results/rejected-race/environment.txt new file mode 100644 index 0000000..6fc5908 --- /dev/null +++ b/dev/research/metal_pathfinding/results/rejected-race/environment.txt @@ -0,0 +1,17 @@ +2026-09-26T23:00:02Z +fbab119e794c843838f4f3f96d75cb7f32f06845 +ProductName: macOS +ProductVersion: 26.6.1 +BuildVersion: 25G76 +Apple M4 Max +38654705664 +14 +Apple clang version 21.0.0 (clang-2100.1.1.101) +Target: arm64-apple-darwin25.6.0 +Thread model: posix +InstalledDir: /Library/Developer/CommandLineTools/usr/bin +c7d33ce878a8f0f1a6822efff641c8fdf0514edabcb521cfe7ae3044e56170d7 dev/research/metal_pathfinding/experiment.mm +bd5f14bdb079c40a4e0ef26ab4d48e16b8c63b830858a53a18445a2addc2b480 dev/research/metal_pathfinding/sssp.metal +Note: No thermal warning level has been recorded +Note: No performance warning level has been recorded +Note: No CPU power status has been recorded diff --git a/dev/research/metal_pathfinding/results/rejected-race/load-a1.txt b/dev/research/metal_pathfinding/results/rejected-race/load-a1.txt new file mode 100644 index 0000000..9e27631 --- /dev/null +++ b/dev/research/metal_pathfinding/results/rejected-race/load-a1.txt @@ -0,0 +1,40 @@ +Processes: 1025 total, 4 running, 1021 sleeping, 5327 threads +2026/09/27 00:00:02 +Load Avg: 3.96, 4.55, 4.69 +CPU usage: 16.11% user, 13.13% sys, 70.74% idle +SharedLibs: 914M resident, 168M data, 135M linkedit. +MemRegions: 639741 total, 10G resident, 737M private, 4343M shared. +PhysMem: 35G used (4508M wired, 633M compressor), 577M unused. +VM: 453T vsize, 6144M framework vsize, 2843881(0) swapins, 4729331(0) swapouts. +Networks: packets: 190075863/161G in, 145485402/163G out. +Disks: 97533882/2474G read, 117262731/2097G written. + +PID COMMAND %CPU #TH +99753 mscamerad-xpc 0.0 2 +99752 PlugInLibrarySer 0.0 2 +99750 QuickLookUIServi 0.0 3 +99749 com.apple.appkit 0.0 3 +99710 PlugInLibrarySer 0.0 2 +99709 Preview 0.0 4 +99428 crashpad_handler 0.0 4 +98995 crashpad_handler 0.0 4 +Processes: 1027 total, 3 running, 1024 sleeping, 5343 threads +2026/09/27 00:00:03 +Load Avg: 3.96, 4.55, 4.69 +CPU usage: 11.46% user, 5.96% sys, 82.56% idle +SharedLibs: 914M resident, 168M data, 135M linkedit. +MemRegions: 204 total, 26M resident, 737M private, 4344M shared. +PhysMem: 34G used (4463M wired, 633M compressor), 634M unused. +VM: 454T vsize, 6144M framework vsize, 2843881(0) swapins, 4729331(0) swapouts. +Networks: packets: 190075966/161G in, 145485507/163G out. +Disks: 97534168/2474G read, 117262748/2097G written. + +PID COMMAND %CPU #TH +590 WindowServer 30.6 28 +1331 NotificationCent 17.7 17 +70968 Superset Helper 16.5 32 +0 kernel_task 15.9 850/14 +70942 Superset Helper 6.2 19 +45949 top 5.9 1/1 +39196 PerfPowerService 5.3 8 +70934 Superset 3.4 51 diff --git a/dev/research/metal_pathfinding/results/rejected-race/load-b.txt b/dev/research/metal_pathfinding/results/rejected-race/load-b.txt new file mode 100644 index 0000000..592e523 --- /dev/null +++ b/dev/research/metal_pathfinding/results/rejected-race/load-b.txt @@ -0,0 +1,40 @@ +Processes: 1026 total, 4 running, 1022 sleeping, 5280 threads +2026/09/27 00:01:03 +Load Avg: 4.62, 4.67, 4.73 +CPU usage: 14.6% user, 9.18% sys, 76.75% idle +SharedLibs: 914M resident, 167M data, 135M linkedit. +MemRegions: 676023 total, 10G resident, 736M private, 4305M shared. +PhysMem: 34G used (4015M wired, 633M compressor), 891M unused. +VM: 458T vsize, 6144M framework vsize, 2843881(0) swapins, 4729331(0) swapouts. +Networks: packets: 190086917/161G in, 145497019/163G out. +Disks: 97535297/2474G read, 117266119/2097G written. + +PID COMMAND %CPU #TH +99753 mscamerad-xpc 0.0 2 +99752 PlugInLibrarySer 0.0 2 +99750 QuickLookUIServi 0.0 3 +99749 com.apple.appkit 0.0 3 +99710 PlugInLibrarySer 0.0 2 +99709 Preview 0.0 4 +99428 crashpad_handler 0.0 4 +98995 crashpad_handler 0.0 4 +Processes: 1026 total, 3 running, 1023 sleeping, 5287 threads +2026/09/27 00:01:04 +Load Avg: 4.62, 4.67, 4.73 +CPU usage: 12.45% user, 3.0% sys, 84.54% idle +SharedLibs: 914M resident, 167M data, 135M linkedit. +MemRegions: 0 total, 0B resident, 736M private, 4305M shared. +PhysMem: 34G used (4054M wired, 633M compressor), 911M unused. +VM: 458T vsize, 6144M framework vsize, 2843881(0) swapins, 4729331(0) swapouts. +Networks: packets: 190087017/161G in, 145497121/163G out. +Disks: 97535298/2474G read, 117266121/2097G written. + +PID COMMAND %CPU #TH +48825 Python 73.0 1/1 +590 WindowServer 25.5 28 +70968 Superset Helper 20.9 32 +0 kernel_task 10.0 850/15 +70942 Superset Helper 7.6 18 +21666 2.1.283 6.5 28 +48902 top 6.3 1/1 +70934 Superset 3.8 51 diff --git a/dev/research/metal_pathfinding/results/rejected-race/pre-fix-smoke.csv b/dev/research/metal_pathfinding/results/rejected-race/pre-fix-smoke.csv new file mode 100644 index 0000000..bbcfc40 --- /dev/null +++ b/dev/research/metal_pathfinding/results/rejected-race/pre-fix-smoke.csv @@ -0,0 +1,21 @@ +case,n,e,queries,method,wall_ms,gpu_ms,distance_wall_ms,upload_ms,rounds,samples,correct +random,128,1024,1,metal_pull,0.614208,0.304625,0.606959,0.053541,16,3,pass +random,128,1024,1,metal_group,0.310458,0.129667,0.307333,0.053541,9,3,pass +random,128,1024,64,metal_pull,0.886292,0.347083,0.624083,0.055542,16,3,pass +random,128,1024,64,metal_group,0.570625,0.177500,0.315042,0.055542,13,3,pass +random,1024,8192,1,metal_pull,0.704750,0.398333,0.662834,0.078125,16,3,pass +random,1024,8192,1,metal_group,0.862250,0.722333,0.827125,0.078125,13,3,pass +random,1024,8192,64,metal_pull,4.660125,1.654750,2.257041,0.088125,24,3,pass +random,1024,8192,64,metal_group,3.771334,0.891792,1.350084,0.088125,17,3,pass +fabric,288,16384,1,metal_pull,1.844583,1.652417,1.794125,0.118167,8,3,pass +fabric,288,16384,1,metal_group,0.790083,0.583125,0.732959,0.118167,3,3,pass +fabric,288,16384,64,metal_pull,5.691166,1.800708,2.326167,0.114166,8,3,pass +fabric,288,16384,64,metal_group,4.476125,0.652125,1.174042,0.114166,3,3,pass +grid,1024,3968,1,metal_pull,1.953792,0.654417,1.936833,0.073500,64,3,pass +grid,1024,3968,1,metal_group,1.172875,1.000375,1.159500,0.073500,63,3,pass +grid,1024,3968,64,metal_pull,3.767584,1.438375,2.877834,0.084959,64,3,pass +grid,1024,3968,64,metal_group,2.245667,0.944250,1.384000,0.084959,63,3,pass +chain,256,255,1,metal_pull,6.148250,1.919250,6.146208,0.065667,256,3,pass +chain,256,255,1,metal_group,0.701417,0.575583,0.699959,0.065667,256,3,pass +random_masked_int64_reverse,1024,8192,8,metal_pull,0.689167,0.133750,0.271792,0.088000,8,3,pass +random_masked_int64_reverse,1024,8192,8,metal_group,0.792458,0.241500,0.385917,0.088000,8,3,pass diff --git a/dev/research/metal_pathfinding/results/sanitize-test.txt b/dev/research/metal_pathfinding/results/sanitize-test.txt new file mode 100644 index 0000000..20e81e8 --- /dev/null +++ b/dev/research/metal_pathfinding/results/sanitize-test.txt @@ -0,0 +1,372 @@ +-- pybind11 not found via config; using FetchContent +-- pybind11 v3.0.0 +-- Enabling sanitizers (disables optimizations) +-- Configuring done (0.6s) +-- Generating done (0.0s) +-- Build files have been written to: /Users/networmix/ws/NetGraph-Core/build/cpp-sanitize +[1/21] Building CXX object CMakeFiles/netgraph_core.dir/src/strict_multidigraph.cpp.o +[2/21] Building CXX object CMakeFiles/netgraph_core.dir/src/k_shortest_paths.cpp.o +[3/21] Building CXX object CMakeFiles/netgraph_core.dir/src/shortest_paths.cpp.o +[4/21] Building CXX object CMakeFiles/netgraph_core.dir/src/max_flow.cpp.o +[5/21] Building CXX object CMakeFiles/netgraph_core.dir/src/cpu_backend.cpp.o +[6/21] Building CXX object CMakeFiles/netgraph_core.dir/src/flow_state.cpp.o +[7/21] Building CXX object CMakeFiles/netgraph_core.dir/src/flow_graph.cpp.o +[8/21] Building CXX object CMakeFiles/netgraph_core.dir/src/flow_policy.cpp.o +[9/21] Building CXX object CMakeFiles/netgraph_core_tests.dir/tests/cpp/smoke_test.cpp.o +[10/21] Building CXX object CMakeFiles/netgraph_core_tests.dir/tests/cpp/strict_multidigraph_tests.cpp.o +[11/21] Building CXX object CMakeFiles/netgraph_core_tests.dir/tests/cpp/flow_policy_tests.cpp.o +[12/21] Building CXX object CMakeFiles/netgraph_core_tests.dir/tests/cpp/shortest_paths_tests.cpp.o +[13/21] Building CXX object CMakeFiles/netgraph_core_tests.dir/tests/cpp/flow_state_tests.cpp.o +[14/21] Building CXX object CMakeFiles/netgraph_core_tests.dir/tests/cpp/flow_graph_tests.cpp.o +[15/21] Linking CXX static library libnetgraph_core.a +[16/21] Building CXX object CMakeFiles/netgraph_core_tests.dir/tests/cpp/max_flow_tests.cpp.o +[17/21] Building CXX object CMakeFiles/netgraph_core_tests.dir/tests/cpp/k_shortest_paths_tests.cpp.o +[18/21] Building CXX object CMakeFiles/netgraph_core_tests.dir/tests/cpp/masking_tests.cpp.o +[19/21] Linking CXX executable netgraph_core_tests +[20/21] Building CXX object CMakeFiles/_netgraph_core.dir/bindings/python/module.cpp.o +[21/21] Linking CXX shared module _netgraph_core.cpython-314-darwin.so +Test project /Users/networmix/ws/NetGraph-Core/build/cpp-sanitize + Start 93: FlowGraphStamp.CopiesAndMovesGetFreshUids + Start 94: FlowGraphStamp.EqualVersionDivergentCopiesCompareUnequal + Start 16: FlowPolicyCostBounds.MaxPathCostFactor_HugeProduct_DropsBoundInsteadOfWrapping + Start 15: FlowPolicyCostBounds.MaxPathCostFactor_UnreachableDst_KeepsSentinelOutOfTheCast + 1/170 Test #93: FlowGraphStamp.CopiesAndMovesGetFreshUids ......................................... Passed 0.06 sec + 2/170 Test #94: FlowGraphStamp.EqualVersionDivergentCopiesCompareUnequal .......................... Passed 0.06 sec + 3/170 Test #16: FlowPolicyCostBounds.MaxPathCostFactor_HugeProduct_DropsBoundInsteadOfWrapping .... Passed 0.06 sec + Start 47: ShortestPaths.ResolveToPathsWithMaxPathsLimit + Start 46: ShortestPaths.ResolveToPathsSplittingParallelEdges + Start 11: FlowPolicyCore.EqualBalanced_ShortestPath_IgnoresHigherCostTier + 4/170 Test #15: FlowPolicyCostBounds.MaxPathCostFactor_UnreachableDst_KeepsSentinelOutOfTheCast ... Passed 0.06 sec + Start 43: ShortestPaths.PredDAGIntegrity + 5/170 Test #11: FlowPolicyCore.EqualBalanced_ShortestPath_IgnoresHigherCostTier ................... Passed 0.06 sec + Start 18: StrictMultiDiGraph.SingleNode + 6/170 Test #46: ShortestPaths.ResolveToPathsSplittingParallelEdges ................................ Passed 0.06 sec + 7/170 Test #43: ShortestPaths.PredDAGIntegrity .................................................... Passed 0.06 sec + Start 45: ShortestPaths.PreferHigherResidualTieBreak + Start 30: StrictMultiDiGraph.OutOfRangeNodeThrows + 8/170 Test #47: ShortestPaths.ResolveToPathsWithMaxPathsLimit ..................................... Passed 0.06 sec + Start 38: ShortestPaths.MultipleEqualCostPaths + 9/170 Test #45: ShortestPaths.PreferHigherResidualTieBreak ........................................ Passed 0.06 sec + Start 41: ShortestPaths.EdgeMaskFiltering + 10/170 Test #18: StrictMultiDiGraph.SingleNode ..................................................... Passed 0.06 sec + 11/170 Test #30: StrictMultiDiGraph.OutOfRangeNodeThrows ........................................... Passed 0.06 sec + 12/170 Test #38: ShortestPaths.MultipleEqualCostPaths .............................................. Passed 0.06 sec + Start 130: MaxFlow.Sensitivity_TwoParallelPaths + Start 103: MaxFlow.ECMP_FourPaths_ClosFabric_Simulation + Start 31: StrictMultiDiGraph.NegativeCapacityThrows + 13/170 Test #41: ShortestPaths.EdgeMaskFiltering ................................................... Passed 0.06 sec + Start 28: StrictMultiDiGraph.MismatchedArrayLengthsThrow + 14/170 Test #130: MaxFlow.Sensitivity_TwoParallelPaths .............................................. Passed 0.06 sec + Start 71: FlowState.EqualBalanced_ECMP3_FirstHopEqualization + 15/170 Test #103: MaxFlow.ECMP_FourPaths_ClosFabric_Simulation ...................................... Passed 0.06 sec + 16/170 Test #31: StrictMultiDiGraph.NegativeCapacityThrows ......................................... Passed 0.06 sec + Start 109: MaxFlow.ZeroCapacityPath_CorrectFiltering + Start 147: MaskingTests.MaskedSourceWithDestination + 17/170 Test #28: StrictMultiDiGraph.MismatchedArrayLengthsThrow .................................... Passed 0.06 sec + Start 152: MaskingTests.MaskedIntermediateNode + 18/170 Test #71: FlowState.EqualBalanced_ECMP3_FirstHopEqualization ................................ Passed 0.06 sec + 19/170 Test #109: MaxFlow.ZeroCapacityPath_CorrectFiltering ......................................... Passed 0.06 sec + 20/170 Test #147: MaskingTests.MaskedSourceWithDestination .......................................... Passed 0.06 sec + Start 12: FlowPolicyStatic.PerFlowBundleBinding + Start 112: MaxFlow.EqualCost_ShortestVsFull_Equivalent + Start 5: FlowPolicyCore.Proportional_SingleDemand_PartialPlacement_InsufficientCapacity + 21/170 Test #152: MaskingTests.MaskedIntermediateNode ............................................... Passed 0.06 sec + Start 122: MaxFlow.GridGraph_3x3_MultipleEqualCostPaths + 22/170 Test #12: FlowPolicyStatic.PerFlowBundleBinding ............................................. Passed 0.06 sec + Start 68: FlowState.ResetWithInvalidResidualThrows + 23/170 Test #112: MaxFlow.EqualCost_ShortestVsFull_Equivalent ....................................... Passed 0.06 sec + 24/170 Test #5: FlowPolicyCore.Proportional_SingleDemand_PartialPlacement_InsufficientCapacity .... Passed 0.06 sec + Start 44: ShortestPaths.TieBreakingDeterminism + Start 39: ShortestPaths.ResidualAwareFiltering + 25/170 Test #122: MaxFlow.GridGraph_3x3_MultipleEqualCostPaths ...................................... Passed 0.07 sec + Start 4: FlowPolicyCore.Proportional_SingleDemand_MaxFlowCount1_UsesSinglePath + 26/170 Test #44: ShortestPaths.TieBreakingDeterminism .............................................. Passed 0.07 sec + Start 108: MaxFlow.EqualBalanced_NodeMask_ReducesECMPWidth + 27/170 Test #39: ShortestPaths.ResidualAwareFiltering .............................................. Passed 0.07 sec + Start 73: FlowState.EqualBalanced_DownstreamSplitEqualization + 28/170 Test #68: FlowState.ResetWithInvalidResidualThrows .......................................... Passed 0.07 sec + Start 137: KShortestPaths.NodeMaskBlocksPaths + 29/170 Test #4: FlowPolicyCore.Proportional_SingleDemand_MaxFlowCount1_UsesSinglePath ............. Passed 0.07 sec + Start 72: FlowState.EqualBalanced_MinFlowGating_DoesNotPruneValidParallelEdges + 30/170 Test #73: FlowState.EqualBalanced_DownstreamSplitEqualization ............................... Passed 0.06 sec + Start 107: MaxFlow.AsymmetricCapacity_1to100_EqualBalanced + 31/170 Test #108: MaxFlow.EqualBalanced_NodeMask_ReducesECMPWidth ................................... Passed 0.06 sec + 32/170 Test #137: KShortestPaths.NodeMaskBlocksPaths ................................................ Passed 0.06 sec + Start 140: KShortestPaths.PathsSortedByCost + Start 36: ShortestPaths.SingleSourceAllNodes + 33/170 Test #72: FlowState.EqualBalanced_MinFlowGating_DoesNotPruneValidParallelEdges .............. Passed 0.06 sec + Start 158: MaskingTests.MaskWithResidualCapacity + 34/170 Test #107: MaxFlow.AsymmetricCapacity_1to100_EqualBalanced ................................... Passed 0.06 sec + 35/170 Test #140: KShortestPaths.PathsSortedByCost .................................................. Passed 0.06 sec + 36/170 Test #36: ShortestPaths.SingleSourceAllNodes ................................................ Passed 0.06 sec + Start 148: MaskingTests.MaskedSourceInMaxFlow + Start 113: MaxFlow.ThreeCostTiers_ShortestPath_LowestTierOnly + Start 157: MaskingTests.NodeMaskOverridesEdgeMask + 37/170 Test #158: MaskingTests.MaskWithResidualCapacity ............................................. Passed 0.06 sec + Start 146: MaskingTests.MaskedSourceReturnsEmptyDAG + 38/170 Test #148: MaskingTests.MaskedSourceInMaxFlow ................................................ Passed 0.06 sec + 39/170 Test #113: MaxFlow.ThreeCostTiers_ShortestPath_LowestTierOnly ................................ Passed 0.06 sec + 40/170 Test #157: MaskingTests.NodeMaskOverridesEdgeMask ............................................ Passed 0.06 sec + Start 1: GraphSmoke.ConstructAndRunSPF + Start 24: StrictMultiDiGraph.CSRReverseAdjacency + Start 67: FlowState.InvalidResidualInitThrows + 41/170 Test #146: MaskingTests.MaskedSourceReturnsEmptyDAG .......................................... Passed 0.07 sec + 42/170 Test #1: GraphSmoke.ConstructAndRunSPF ..................................................... Passed 0.06 sec + 43/170 Test #24: StrictMultiDiGraph.CSRReverseAdjacency ............................................ Passed 0.06 sec + Start 92: FlowGraph.LedgerMicroFlows_RemovalRestoresResidual + Start 10: FlowPolicyCore.EqualBalanced_ShortestPath_DownstreamSplit_BalancesBottleneck + Start 40: ShortestPaths.NodeMaskIsolation + 44/170 Test #67: FlowState.InvalidResidualInitThrows ............................................... Passed 0.07 sec + Start 123: MaxFlow.SharedBottleneck_MultiplePathsMerge + 45/170 Test #40: ShortestPaths.NodeMaskIsolation ................................................... Passed 0.06 sec + Start 22: StrictMultiDiGraph.ExternalEdgeIdsPreserved + 46/170 Test #10: FlowPolicyCore.EqualBalanced_ShortestPath_DownstreamSplit_BalancesBottleneck ...... Passed 0.06 sec + 47/170 Test #123: MaxFlow.SharedBottleneck_MultiplePathsMerge ....................................... Passed 0.06 sec + Start 74: FlowState.EqualBalanced_ZeroCapacityOnShortestPath_ReturnsZero + Start 20: StrictMultiDiGraph.ParallelEdges + 48/170 Test #92: FlowGraph.LedgerMicroFlows_RemovalRestoresResidual ................................ Passed 0.07 sec + Start 115: MaxFlow.FlowConservation_IntermediateNodes + 49/170 Test #74: FlowState.EqualBalanced_ZeroCapacityOnShortestPath_ReturnsZero .................... Passed 0.07 sec + Start 91: FlowGraph.LedgerHistory_RemovalRestoresResidual + 50/170 Test #22: StrictMultiDiGraph.ExternalEdgeIdsPreserved ....................................... Passed 0.07 sec + 51/170 Test #20: StrictMultiDiGraph.ParallelEdges .................................................. Passed 0.07 sec + Start 35: StrictMultiDiGraph.MultipleCostTiers + Start 33: StrictMultiDiGraph.SelfLoopAllowed + 52/170 Test #115: MaxFlow.FlowConservation_IntermediateNodes ........................................ Passed 0.07 sec + Start 9: FlowPolicyCore.EqualBalanced_ShortestPath_ECMP3_SaturatesAllEqualCostPaths + 53/170 Test #33: StrictMultiDiGraph.SelfLoopAllowed ................................................ Passed 0.07 sec + Start 29: StrictMultiDiGraph.ExtEdgeIdsWrongLengthThrows + 54/170 Test #91: FlowGraph.LedgerHistory_RemovalRestoresResidual ................................... Passed 0.07 sec + 55/170 Test #35: StrictMultiDiGraph.MultipleCostTiers .............................................. Passed 0.07 sec + Start 2: FlowPolicyCore.Proportional_SingleDemand_UsesShortestPath + Start 75: FlowState.Proportional_ZeroCapacityOnShortestPath_ReturnsZero + 56/170 Test #9: FlowPolicyCore.EqualBalanced_ShortestPath_ECMP3_SaturatesAllEqualCostPaths ........ Passed 0.06 sec + Start 101: MaxFlow.ECMP_TwoPaths_EqualBalanced_ShortestPath + 57/170 Test #2: FlowPolicyCore.Proportional_SingleDemand_UsesShortestPath ......................... Passed 0.07 sec + Start 145: KSP.MaxCostFactorBelowOne_ReturnsEmptyForAllK + 58/170 Test #29: StrictMultiDiGraph.ExtEdgeIdsWrongLengthThrows .................................... Passed 0.07 sec + 59/170 Test #75: FlowState.Proportional_ZeroCapacityOnShortestPath_ReturnsZero ..................... Passed 0.07 sec + Start 119: MaxFlow.NodeMask_BlocksFlowThroughNode + Start 134: MaxFlow.CompletionPhase_RespectsNodeMask + 60/170 Test #101: MaxFlow.ECMP_TwoPaths_EqualBalanced_ShortestPath .................................. Passed 0.07 sec + Start 126: MaxFlow.Triangle_Topology_Combine_Mode + 61/170 Test #145: KSP.MaxCostFactorBelowOne_ReturnsEmptyForAllK ..................................... Passed 0.07 sec + Start 167: MaskingTests.AllNodesMaskedNoReachability + 62/170 Test #119: MaxFlow.NodeMask_BlocksFlowThroughNode ............................................ Passed 0.07 sec + 63/170 Test #134: MaxFlow.CompletionPhase_RespectsNodeMask .......................................... Passed 0.07 sec + Start 21: StrictMultiDiGraph.EdgeSortingByCost + Start 19: StrictMultiDiGraph.SingleEdge + 64/170 Test #126: MaxFlow.Triangle_Topology_Combine_Mode ............................................ Passed 0.07 sec + Start 17: StrictMultiDiGraph.EmptyGraph + 65/170 Test #21: StrictMultiDiGraph.EdgeSortingByCost .............................................. Passed 0.07 sec + Start 14: FlowPolicyStatic.ValidationRejectsForeignAndDisconnectedBundles + 66/170 Test #167: MaskingTests.AllNodesMaskedNoReachability ......................................... Passed 0.07 sec + 67/170 Test #19: StrictMultiDiGraph.SingleEdge ..................................................... Passed 0.07 sec + Start 151: MaskingTests.MaskedDestinationUnreachable + Start 37: ShortestPaths.DisconnectedComponents + 68/170 Test #17: StrictMultiDiGraph.EmptyGraph ..................................................... Passed 0.07 sec + Start 100: MaxFlow.ECMP_TwoPaths_Proportional_FullMaxFlow + 69/170 Test #14: FlowPolicyStatic.ValidationRejectsForeignAndDisconnectedBundles ................... Passed 0.07 sec + Start 106: MaxFlow.AsymmetricCapacity_1to1M_NumericalStability + 70/170 Test #151: MaskingTests.MaskedDestinationUnreachable ......................................... Passed 0.07 sec + 71/170 Test #37: ShortestPaths.DisconnectedComponents .............................................. Passed 0.07 sec + Start 99: MaxFlow.ECMP_TwoPaths_Proportional_ShortestPath + Start 85: FlowGraph.RemovalDeletesEntry + 72/170 Test #100: MaxFlow.ECMP_TwoPaths_Proportional_FullMaxFlow .................................... Passed 0.07 sec + Start 114: MaxFlow.PlacementModes_EqualCapacity_IdenticalResult + 73/170 Test #99: MaxFlow.ECMP_TwoPaths_Proportional_ShortestPath ................................... Passed 0.07 sec + Start 89: FlowGraph.GetFlowPathForDAGReturnsEmpty + 74/170 Test #106: MaxFlow.AsymmetricCapacity_1to1M_NumericalStability ............................... Passed 0.07 sec + 75/170 Test #85: FlowGraph.RemovalDeletesEntry ..................................................... Passed 0.07 sec + Start 13: FlowPolicyStatic.MaskedBundleIsDown + Start 139: KShortestPaths.MaxCostFactorLimit + 76/170 Test #114: MaxFlow.PlacementModes_EqualCapacity_IdenticalResult .............................. Passed 0.07 sec + Start 135: KShortestPaths.FindsKPaths + 77/170 Test #13: FlowPolicyStatic.MaskedBundleIsDown ............................................... Passed 0.07 sec + Start 149: MaskingTests.MaskedSourceInComputeMinCut + 78/170 Test #89: FlowGraph.GetFlowPathForDAGReturnsEmpty ........................................... Passed 0.07 sec + 79/170 Test #139: KShortestPaths.MaxCostFactorLimit ................................................. Passed 0.07 sec + 80/170 Test #135: KShortestPaths.FindsKPaths ........................................................ Passed 0.07 sec + Start 96: MaxFlow.SinglePath_BottleneckConstraint + Start 27: StrictMultiDiGraph.InvalidNumNodesThrows + Start 63: FlowState.ApplyDeltasSubtractive + 81/170 Test #27: StrictMultiDiGraph.InvalidNumNodesThrows .......................................... Passed 0.07 sec + Start 170: MaskingTests.AlgorithmsAPIMaxFlowWithMask + 82/170 Test #149: MaskingTests.MaskedSourceInComputeMinCut .......................................... Passed 0.07 sec + 83/170 Test #96: MaxFlow.SinglePath_BottleneckConstraint ........................................... Passed 0.07 sec + 84/170 Test #63: FlowState.ApplyDeltasSubtractive .................................................. Passed 0.07 sec + Start 110: MaxFlow.TwoCostTiers_ShortestPath_SingleTierOnly + Start 160: MaskingTests.KSPWithNodeMask + Start 6: FlowPolicyCore.EqualBalanced_SingleDemand_FlowCount2_BalancedDistribution + 85/170 Test #170: MaskingTests.AlgorithmsAPIMaxFlowWithMask ......................................... Passed 0.07 sec + 86/170 Test #160: MaskingTests.KSPWithNodeMask ...................................................... Passed 0.07 sec + 87/170 Test #6: FlowPolicyCore.EqualBalanced_SingleDemand_FlowCount2_BalancedDistribution ......... Passed 0.07 sec + Start 144: KShortestPaths.LargerOutOfOrderTopology + Start 23: StrictMultiDiGraph.CSROffsetsMonotonicity + Start 8: FlowPolicyCore.DiminishingReturnsCutoff + 88/170 Test #110: MaxFlow.TwoCostTiers_ShortestPath_SingleTierOnly .................................. Passed 0.07 sec + Start 97: MaxFlow.SinglePath_ShortestPathEquivalence + 89/170 Test #144: KShortestPaths.LargerOutOfOrderTopology ........................................... Passed 0.07 sec + 90/170 Test #8: FlowPolicyCore.DiminishingReturnsCutoff ........................................... Passed 0.07 sec + Start 156: MaskingTests.CombinedNodeAndEdgeMasks + Start 169: MaskingTests.AlgorithmsAPIMaskedSource + 91/170 Test #23: StrictMultiDiGraph.CSROffsetsMonotonicity ......................................... Passed 0.07 sec + 92/170 Test #97: MaxFlow.SinglePath_ShortestPathEquivalence ........................................ Passed 0.07 sec + Start 117: MaxFlow.CostDistribution_AccountsForAllFlow + Start 86: FlowGraph.RemoveByClassFiltersCorrectly + 93/170 Test #117: MaxFlow.CostDistribution_AccountsForAllFlow ....................................... Passed 0.07 sec + Start 136: KShortestPaths.KEqualsZeroReturnsEmpty + 94/170 Test #156: MaskingTests.CombinedNodeAndEdgeMasks ............................................. Passed 0.08 sec + 95/170 Test #169: MaskingTests.AlgorithmsAPIMaskedSource ............................................ Passed 0.08 sec + 96/170 Test #86: FlowGraph.RemoveByClassFiltersCorrectly ........................................... Passed 0.08 sec + Start 104: MaxFlow.ECMP_TenPaths_ScalabilityValidation + Start 132: MaxFlow.Sensitivity_ShortestPathVsMaxFlow + Start 120: MaxFlow.EdgeMask_SelectiveEdgeFiltering + 97/170 Test #136: KShortestPaths.KEqualsZeroReturnsEmpty ............................................ Passed 0.07 sec + Start 124: MaxFlow.Clos_3Tier_Topology_Proportional_Shortest + 98/170 Test #104: MaxFlow.ECMP_TenPaths_ScalabilityValidation ....................................... Passed 0.07 sec + 99/170 Test #132: MaxFlow.Sensitivity_ShortestPathVsMaxFlow ......................................... Passed 0.07 sec +100/170 Test #120: MaxFlow.EdgeMask_SelectiveEdgeFiltering ........................................... Passed 0.07 sec + Start 65: FlowState.ResetRestoresCapacity + Start 49: ShortestPaths.RejectsMaskLengthMismatch + Start 133: MaxFlow.CompletionPhase_RecoversCancellation +101/170 Test #65: FlowState.ResetRestoresCapacity ................................................... Passed 0.07 sec + Start 165: MaskingTests.EmptyNodeMaskAllowsAllNodes +102/170 Test #124: MaxFlow.Clos_3Tier_Topology_Proportional_Shortest ................................. Passed 0.07 sec +103/170 Test #49: ShortestPaths.RejectsMaskLengthMismatch ........................................... Passed 0.07 sec + Start 111: MaxFlow.TwoCostTiers_FullMaxFlow_AllTiers + Start 129: MaxFlow.Sensitivity_SinglePath +104/170 Test #133: MaxFlow.CompletionPhase_RecoversCancellation ...................................... Passed 0.07 sec + Start 161: MaskingTests.KSPWithEdgeMask +105/170 Test #165: MaskingTests.EmptyNodeMaskAllowsAllNodes .......................................... Passed 0.07 sec + Start 32: StrictMultiDiGraph.NegativeCostThrows +106/170 Test #111: MaxFlow.TwoCostTiers_FullMaxFlow_AllTiers ......................................... Passed 0.07 sec +107/170 Test #129: MaxFlow.Sensitivity_SinglePath .................................................... Passed 0.07 sec +108/170 Test #161: MaskingTests.KSPWithEdgeMask ...................................................... Passed 0.07 sec + Start 66: FlowState.CustomInitialResidual + Start 42: ShortestPaths.EarlyExitOptimization + Start 88: FlowGraph.GetFlowPathForLinearFlow +109/170 Test #66: FlowState.CustomInitialResidual ................................................... Passed 0.07 sec + Start 25: StrictMultiDiGraph.MaxCapacityEdges +110/170 Test #32: StrictMultiDiGraph.NegativeCostThrows ............................................. Passed 0.07 sec +111/170 Test #42: ShortestPaths.EarlyExitOptimization ............................................... Passed 0.07 sec +112/170 Test #88: FlowGraph.GetFlowPathForLinearFlow ................................................ Passed 0.07 sec + Start 168: MaskingTests.AllEdgesMaskedNoReachability + Start 142: KShortestPaths.LooplessPaths + Start 138: KShortestPaths.UniqueModeFiltering +113/170 Test #25: StrictMultiDiGraph.MaxCapacityEdges ............................................... Passed 0.07 sec +114/170 Test #138: KShortestPaths.UniqueModeFiltering ................................................ Passed 0.07 sec + Start 7: FlowPolicyCore.EqualBalanced_SingleDemand_FlowCount3_SaturatesBothPaths + Start 3: FlowPolicyCore.Proportional_SingleDemand_SplitsAcrossTwoEqualCostPaths +115/170 Test #168: MaskingTests.AllEdgesMaskedNoReachability ......................................... Passed 0.07 sec +116/170 Test #142: KShortestPaths.LooplessPaths ...................................................... Passed 0.07 sec + Start 159: MaskingTests.ResidualAndNodeMaskCombined + Start 143: KShortestPaths.OutOfOrderNodePredDAGSemantics +117/170 Test #7: FlowPolicyCore.EqualBalanced_SingleDemand_FlowCount3_SaturatesBothPaths ........... Passed 0.07 sec +118/170 Test #159: MaskingTests.ResidualAndNodeMaskCombined .......................................... Passed 0.07 sec + Start 62: FlowState.ApplyDeltasAdditive + Start 131: MaxFlow.Sensitivity_PartialSaturation +119/170 Test #3: FlowPolicyCore.Proportional_SingleDemand_SplitsAcrossTwoEqualCostPaths ............ Passed 0.07 sec +120/170 Test #143: KShortestPaths.OutOfOrderNodePredDAGSemantics ..................................... Passed 0.07 sec + Start 83: FlowGraph.EmptyLedgerInitially + Start 84: FlowGraph.PlacementCreatesEntry +121/170 Test #83: FlowGraph.EmptyLedgerInitially .................................................... Passed 0.07 sec + Start 76: FlowState.RepeatedPlacementAfterResetAndIndependentInstancesStayStable +122/170 Test #62: FlowState.ApplyDeltasAdditive ..................................................... Passed 0.07 sec +123/170 Test #131: MaxFlow.Sensitivity_PartialSaturation ............................................. Passed 0.07 sec +124/170 Test #84: FlowGraph.PlacementCreatesEntry ................................................... Passed 0.07 sec + Start 153: MaskingTests.MaskedEdgeBlocksPath + Start 102: MaxFlow.ECMP_ThreePaths_Proportional_ShortestPath + Start 64: FlowState.MinCutComputation +125/170 Test #76: FlowState.RepeatedPlacementAfterResetAndIndependentInstancesStayStable ............ Passed 0.07 sec + Start 69: FlowState.ApplyDeltasClampsWithinCapacityBounds +126/170 Test #153: MaskingTests.MaskedEdgeBlocksPath ................................................. Passed 0.07 sec +127/170 Test #102: MaxFlow.ECMP_ThreePaths_Proportional_ShortestPath ................................. Passed 0.07 sec +128/170 Test #64: FlowState.MinCutComputation ....................................................... Passed 0.07 sec + Start 95: MaxFlow.SinglePath_BasicLinear + Start 121: MaxFlow.BatchMaxFlow_IndependentMaskApplication + Start 116: MaxFlow.MinCut_ValidEdgeIdentification +129/170 Test #95: MaxFlow.SinglePath_BasicLinear .................................................... Passed 0.07 sec +130/170 Test #121: MaxFlow.BatchMaxFlow_IndependentMaskApplication ................................... Passed 0.07 sec + Start 34: StrictMultiDiGraph.NegativeNodeIdThrows + Start 87: FlowGraph.GetFlowEdgesReturnsDeltas +131/170 Test #69: FlowState.ApplyDeltasClampsWithinCapacityBounds ................................... Passed 0.08 sec +132/170 Test #116: MaxFlow.MinCut_ValidEdgeIdentification ............................................ Passed 0.07 sec + Start 50: ShortestPaths.ZeroCostEdges_PredDAGIsAcyclic + Start 105: MaxFlow.AsymmetricCapacity_1to100_Proportional +133/170 Test #34: StrictMultiDiGraph.NegativeNodeIdThrows ........................................... Passed 0.07 sec +134/170 Test #87: FlowGraph.GetFlowEdgesReturnsDeltas ............................................... Passed 0.07 sec +135/170 Test #50: ShortestPaths.ZeroCostEdges_PredDAGIsAcyclic ...................................... Passed 0.07 sec +136/170 Test #105: MaxFlow.AsymmetricCapacity_1to100_Proportional .................................... Passed 0.07 sec + Start 128: MaxFlow.ShortestPath_MustSaturateAllEqualCostPaths + Start 125: MaxFlow.Clos_3Tier_Topology_EqualBalanced_Shortest + Start 98: MaxFlow.DegenerateCase_SourceEqualsSink + Start 118: MaxFlow.OptionalOutputs_ResidualAndReachable +137/170 Test #128: MaxFlow.ShortestPath_MustSaturateAllEqualCostPaths ................................ Passed 0.08 sec + Start 90: FlowGraph.CoalescesDuplicateEdgeIds +138/170 Test #125: MaxFlow.Clos_3Tier_Topology_EqualBalanced_Shortest ................................ Passed 0.08 sec +139/170 Test #98: MaxFlow.DegenerateCase_SourceEqualsSink ........................................... Passed 0.08 sec +140/170 Test #118: MaxFlow.OptionalOutputs_ResidualAndReachable ...................................... Passed 0.08 sec + Start 48: ShortestPaths.LargeGraphStressTest + Start 163: MaskingTests.MaxFlowWithEdgeMask + Start 164: MaskingTests.MaxFlowAllPathsMasked +141/170 Test #90: FlowGraph.CoalescesDuplicateEdgeIds ............................................... Passed 0.08 sec + Start 26: StrictMultiDiGraph.ZeroCostEdges +142/170 Test #163: MaskingTests.MaxFlowWithEdgeMask .................................................. Passed 0.08 sec +143/170 Test #164: MaskingTests.MaxFlowAllPathsMasked ................................................ Passed 0.08 sec + Start 60: FlowState.EqualBalancedDistribution + Start 141: KShortestPaths.DisconnectedReturnsEmpty +144/170 Test #48: ShortestPaths.LargeGraphStressTest ................................................ Passed 0.08 sec + Start 154: MaskingTests.MaskedEdgeSelectsAlternativePath +145/170 Test #60: FlowState.EqualBalancedDistribution ............................................... Passed 0.08 sec + Start 150: MaskingTests.OutOfRangeSourceInComputeMinCut +146/170 Test #26: StrictMultiDiGraph.ZeroCostEdges .................................................. Passed 0.08 sec +147/170 Test #141: KShortestPaths.DisconnectedReturnsEmpty ........................................... Passed 0.08 sec +148/170 Test #154: MaskingTests.MaskedEdgeSelectsAlternativePath ..................................... Passed 0.08 sec + Start 166: MaskingTests.EmptyEdgeMaskAllowsAllEdges + Start 70: FlowState.EqualBalancedReconvergentDAGPlacesAll + Start 162: MaskingTests.MaxFlowWithNodeMask +149/170 Test #150: MaskingTests.OutOfRangeSourceInComputeMinCut ...................................... Passed 0.07 sec +150/170 Test #166: MaskingTests.EmptyEdgeMaskAllowsAllEdges .......................................... Passed 0.07 sec + Start 61: FlowState.ZeroCapacityHandling + Start 59: FlowState.ProportionalDistribution +151/170 Test #70: FlowState.EqualBalancedReconvergentDAGPlacesAll ................................... Passed 0.07 sec +152/170 Test #162: MaskingTests.MaxFlowWithNodeMask .................................................. Passed 0.07 sec + Start 155: MaskingTests.MultipleEdgesMasked + Start 57: FlowState.InitialResidualEqualsCapacity +153/170 Test #59: FlowState.ProportionalDistribution ................................................ Passed 0.07 sec + Start 127: MaxFlow.SimpleParallelPaths_Topology +154/170 Test #61: FlowState.ZeroCapacityHandling .................................................... Passed 0.07 sec +155/170 Test #155: MaskingTests.MultipleEdgesMasked .................................................. Passed 0.07 sec +156/170 Test #57: FlowState.InitialResidualEqualsCapacity ........................................... Passed 0.07 sec + Start 58: FlowState.PlacementReducesResidual + Start 51: ShortestPathsTo.DistancesMatchForwardDistancesToDst + Start 52: ShortestPathsTo.ForwardSpfFromPseudoSourceKeepsOnlyNearestSource +157/170 Test #58: FlowState.PlacementReducesResidual ................................................ Passed 0.07 sec + Start 53: ShortestPathsTo.FanoutEdgesForceEverySourceIntoTheDag +158/170 Test #127: MaxFlow.SimpleParallelPaths_Topology .............................................. Passed 0.07 sec +159/170 Test #51: ShortestPathsTo.DistancesMatchForwardDistancesToDst ............................... Passed 0.07 sec +160/170 Test #52: ShortestPathsTo.ForwardSpfFromPseudoSourceKeepsOnlyNearestSource .................. Passed 0.07 sec + Start 54: ShortestPathsTo.FanoutSkipsUnreachableAndMaskedHeads + Start 55: ShortestPathsTo.FanoutFromInteriorNodeIsRejected + Start 56: ShortestPathsTo.SinglePathModeKeepsOneSuccessorPerNode +161/170 Test #53: ShortestPathsTo.FanoutEdgesForceEverySourceIntoTheDag ............................. Passed 0.07 sec + Start 77: FlowState.EqualBalanced_SaturatedMemberBlocksAdmission +162/170 Test #54: ShortestPathsTo.FanoutSkipsUnreachableAndMaskedHeads .............................. Passed 0.07 sec +163/170 Test #55: ShortestPathsTo.FanoutFromInteriorNodeIsRejected .................................. Passed 0.07 sec +164/170 Test #56: ShortestPathsTo.SinglePathModeKeepsOneSuccessorPerNode ............................ Passed 0.07 sec + Start 78: FlowState.EqualBalanced_ProgressesOnlyThroughResidualAwareSpf + Start 79: FlowState.EqualBalancedLossy_FillAndDropReportsDrops + Start 80: FlowState.EqualBalancedLossy_DeficitPropagatesDownstream +165/170 Test #79: FlowState.EqualBalancedLossy_FillAndDropReportsDrops .............................. Passed 0.07 sec + Start 81: FlowState.EqualBalancedLossy_InfiniteRequestFillsWithoutDrops +166/170 Test #77: FlowState.EqualBalanced_SaturatedMemberBlocksAdmission ............................ Passed 0.07 sec +167/170 Test #78: FlowState.EqualBalanced_ProgressesOnlyThroughResidualAwareSpf ..................... Passed 0.07 sec +168/170 Test #80: FlowState.EqualBalancedLossy_DeficitPropagatesDownstream .......................... Passed 0.07 sec + Start 82: FlowGraph.LossyPlacementIsReversibleAndDropsStayOutOfLedger +169/170 Test #81: FlowState.EqualBalancedLossy_InfiniteRequestFillsWithoutDrops ..................... Passed 0.07 sec +170/170 Test #82: FlowGraph.LossyPlacementIsReversibleAndDropsStayOutOfLedger ....................... Passed 0.07 sec + +100% tests passed out of 170 + +Total Test time (real) = 3.00 sec diff --git a/dev/research/metal_pathfinding/results/stress-sanitized.csv b/dev/research/metal_pathfinding/results/stress-sanitized.csv new file mode 100644 index 0000000..c9d9fb1 --- /dev/null +++ b/dev/research/metal_pathfinding/results/stress-sanitized.csv @@ -0,0 +1,7 @@ +case,n,e,queries,method,wall_ms,gpu_ms,distance_wall_ms,upload_ms,rounds,samples,correct,exact_order_queries,wall_samples_ms +grid,1024,3968,64,metal_pull,15.530167,4.484500,9.108750,0.188375,64,20,pass,0,16.700250;15.530167;15.417208;14.727875;14.057000;15.392333;16.472042;15.792750;15.891250;11.988333;15.802375;15.560042;16.590166;15.518750;11.375958;16.363709;17.054667;15.159750;15.207500;15.467084 +grid,1024,3968,64,metal_group,11.060208,3.933417,4.879000,0.188375,63,20,pass,0,11.942000;7.964375;11.096834;10.917458;11.153459;8.798208;11.295417;11.240333;10.839417;11.959583;11.143958;11.022000;10.818417;11.017167;8.111667;11.060208;11.184917;10.825750;11.167166;10.949792 +grid,1024,3968,64,metal_shared,10.228625,3.022375,3.916833,0.188375,63,20,pass,0,9.921208;10.004083;9.822125;9.661958;10.228625;11.134167;10.203042;10.252459;10.255542;10.094833;10.453375;10.557041;10.717250;9.984875;10.313458;10.648125;10.205625;10.073000;10.538500;10.068917 +random_masked_int64_reverse,1024,8192,64,metal_pull,13.439750,0.905375,1.931417,0.195667,8,20,pass,6,13.597583;13.481542;13.092833;13.398708;13.384584;13.448375;14.449125;15.040625;13.340542;13.603958;13.039250;13.253625;13.401208;13.473250;13.170750;13.203708;13.391417;13.586667;15.356334;13.439750 +random_masked_int64_reverse,1024,8192,64,metal_group,13.348292,0.879917,1.800458,0.195667,8,20,pass,6,13.703917;13.791375;13.181167;13.526292;13.570083;13.179875;13.348292;13.530625;13.278459;13.327250;13.056458;13.275542;14.277209;13.365333;13.212542;13.166417;12.992666;12.752334;13.547125;14.419541 +random_masked_int64_reverse,1024,8192,64,metal_shared,13.334542,0.695792,1.711416,0.195667,8,20,pass,6,13.044125;13.625292;14.034959;13.278042;14.283083;14.222250;13.571042;13.812625;13.348125;14.462250;13.157583;12.979958;13.194167;13.043500;13.855750;13.129500;13.334542;12.628834;12.541375;13.082375 diff --git a/dev/research/metal_pathfinding/results/stress-stderr.txt b/dev/research/metal_pathfinding/results/stress-stderr.txt new file mode 100644 index 0000000..8052255 --- /dev/null +++ b/dev/research/metal_pathfinding/results/stress-stderr.txt @@ -0,0 +1 @@ +device=Apple M4 Max setup_ms=98.9218 execution_width=32 diff --git a/dev/research/metal_pathfinding/results/stress-validation.txt b/dev/research/metal_pathfinding/results/stress-validation.txt new file mode 100644 index 0000000..c87a5f1 --- /dev/null +++ b/dev/research/metal_pathfinding/results/stress-validation.txt @@ -0,0 +1,3 @@ +2026-09-27 00:02:38.195 experiment-sanitize[57642:38285138] Metal API Validation Enabled +2026-09-27 00:02:38.195 experiment-sanitize[57642:38285138] Metal GPU Validation Enabled +device=Apple M4 Max setup_ms=223.541 execution_width=32 diff --git a/dev/research/metal_pathfinding/results/stress.csv b/dev/research/metal_pathfinding/results/stress.csv new file mode 100644 index 0000000..59e8274 --- /dev/null +++ b/dev/research/metal_pathfinding/results/stress.csv @@ -0,0 +1,7 @@ +case,n,e,queries,method,wall_ms,gpu_ms,distance_wall_ms,upload_ms,rounds,samples,correct,exact_order_queries,wall_samples_ms +grid,1024,3968,64,metal_pull,2.893875,0.425792,2.019709,0.078417,64,100,pass,0,4.494667;4.062667;4.002000;3.562250;3.658292;3.957500;3.817125;3.879208;4.127208;3.733583;3.796667;3.714583;3.924333;4.171167;3.697167;4.234458;3.981083;4.905542;3.749833;3.651375;3.933417;3.802250;4.545875;3.511667;3.961000;3.879709;3.730875;3.300042;3.143708;3.516167;3.528167;3.266792;3.355542;2.673291;3.135584;3.154791;3.013542;2.940125;2.839459;2.471667;3.009083;2.916875;2.351375;3.027959;2.859958;2.249584;2.713750;2.853708;2.942916;2.976084;2.883708;2.293750;2.909208;2.350291;2.887291;2.889542;2.879709;2.956083;2.806000;2.873542;2.270250;2.895084;2.823958;2.835458;2.635125;2.893375;2.209375;2.224666;3.001459;2.193958;2.865291;2.849334;2.713083;2.704917;2.349458;2.787459;2.347500;2.919917;2.832500;2.252667;2.293708;2.299542;2.930000;2.809125;2.607875;2.154125;2.661750;2.835375;2.214000;2.893875;2.839666;2.221583;2.192500;2.323375;2.456792;2.335750;2.697167;2.229375;2.864916;3.039958 +grid,1024,3968,64,metal_group,2.067916,0.943375,1.156792,0.078417,63,100,pass,0,1.222208;1.703584;1.525334;1.843750;1.220291;1.866208;1.850000;1.772125;1.237916;1.877125;1.660875;1.669625;1.827416;1.852958;1.781875;1.837208;1.869250;1.172917;1.594416;2.365458;2.554708;2.298959;2.377958;2.293208;1.330625;1.203458;1.702000;1.770416;1.217500;1.702458;1.827042;2.313958;1.974291;2.381541;2.276708;2.289041;1.233959;1.722250;1.691166;1.880875;1.246125;1.601250;1.355666;2.275250;2.019166;2.305542;2.237250;2.303208;2.269292;2.261667;2.271166;2.288416;2.285459;2.386250;2.067916;2.284542;2.339292;2.054292;2.208500;2.065125;2.321167;2.278708;2.346000;2.342958;2.289416;2.306541;2.283458;2.056000;2.273750;1.973334;2.322375;2.281417;2.016667;2.242208;2.006250;2.290208;2.322584;2.174125;2.274917;2.294291;2.330667;2.292000;2.628000;2.086458;2.317583;2.328709;1.567959;1.733708;1.753625;1.792584;1.828083;1.726375;1.306916;2.292541;2.073167;2.431583;2.308167;2.337917;1.889792;1.825292 +grid,1024,3968,64,metal_shared,1.748708,0.194750,0.873834,0.078417,63,100,pass,0,1.833000;1.229542;1.731500;1.226667;1.749833;1.360959;1.781084;1.281334;1.243667;2.318000;1.971333;2.212125;2.285458;2.207833;1.792750;1.802042;1.796000;1.777417;1.533959;1.195459;1.818208;1.806666;1.810291;1.678708;1.785708;1.711917;1.671625;1.780625;1.780208;1.677208;1.704709;1.198375;1.743000;1.746542;1.808875;1.270416;2.439500;2.051083;2.253208;2.199917;2.006209;2.074958;2.267041;2.015084;2.284958;2.247500;2.188542;1.660917;1.655208;1.228000;1.673292;1.323083;1.648625;1.705459;1.497542;1.635709;1.679042;1.681250;1.265291;1.663875;2.260708;2.035417;1.929333;2.587208;1.982041;1.679209;1.204375;1.643542;1.670334;1.625000;1.618125;1.735833;1.605792;1.632875;1.602917;2.221916;2.270500;1.966791;2.231417;2.152958;1.751167;1.204500;1.677833;1.891417;1.779500;1.690167;1.708208;1.707584;1.644125;1.264458;1.793792;1.272667;1.186375;2.311500;2.077917;2.057791;2.246125;2.278958;1.748708;1.746708 +random_masked_int64_reverse,1024,8192,64,metal_pull,4.320500,0.411000,0.942125,0.098667,8,100,pass,6,3.915584;3.984333;4.290417;4.201541;4.721584;4.304333;3.936375;3.948584;4.342250;4.290167;4.296041;4.371125;4.213667;4.409000;4.367542;4.160125;4.006542;4.411709;4.427792;4.432417;4.385458;4.346709;4.013458;4.421708;4.260875;4.200708;4.396167;4.359709;4.305542;4.258334;4.253750;4.311791;3.961292;4.247125;3.931042;3.962000;4.304584;3.920083;4.041000;4.367583;4.228875;4.334459;4.284000;4.374584;4.071542;4.312375;4.656291;4.328000;3.946334;4.320500;4.079333;4.190416;4.930666;3.979875;4.378458;4.446834;4.385833;4.225792;4.216667;4.382917;4.363083;4.369875;4.332917;4.398625;3.892083;4.374167;4.355875;3.985459;4.380292;4.356917;4.203583;4.345500;4.419958;3.965208;4.269792;4.254334;4.234917;4.338792;3.941584;4.135791;4.342584;4.314334;4.395084;4.393708;4.362541;4.325458;4.271375;4.331833;4.662667;4.429875;4.387000;4.061250;4.395959;4.346167;4.068583;4.460083;4.419750;4.284042;4.372291;4.326500 +random_masked_int64_reverse,1024,8192,64,metal_group,4.130833,0.240250,0.757125,0.098667,8,100,pass,6,4.159792;4.163750;4.188959;4.129250;3.907334;3.927416;4.088083;3.847333;4.244208;4.168333;4.101375;4.115000;4.250917;4.249542;4.077417;4.133125;3.820667;4.157292;3.801416;4.237917;4.132083;3.737250;4.185458;4.106667;4.181875;4.294000;4.160042;4.162167;4.141166;4.067666;4.287959;4.048417;4.080208;4.074666;4.122000;3.814500;4.130166;3.799666;3.773208;4.202458;4.118959;4.077041;4.130833;3.951708;4.453959;3.985458;3.756459;4.193500;4.245542;4.392292;4.224667;4.173541;4.192459;3.817833;3.784459;4.228708;4.218500;3.784750;4.124833;4.093875;4.086666;4.084334;4.235750;3.813291;4.238541;4.105792;3.827084;4.104416;4.121208;4.295375;4.366209;4.095417;4.200125;3.931375;4.102583;4.208416;4.233666;4.141541;4.237000;4.259541;4.127334;4.149750;3.713833;3.788292;4.195959;4.113458;4.112209;3.820500;3.793334;4.329583;4.180000;4.204083;4.143041;4.254959;4.079416;4.259917;4.167875;4.093000;4.297709;4.166625 +random_masked_int64_reverse,1024,8192,64,metal_shared,4.154125,0.221417,0.721583,0.098667,8,100,pass,6,3.756917;3.782208;4.299417;4.174375;4.168166;4.101584;4.228833;3.782625;4.102625;4.134833;4.242875;4.193500;4.115209;4.191000;4.190875;4.146167;4.107166;4.026375;4.243250;4.117167;4.027459;3.831667;4.176167;4.154125;4.148583;4.222792;4.025041;4.497167;4.314084;4.296291;3.930791;4.316917;4.131417;4.165375;3.806875;3.835833;4.255666;4.048333;4.141417;4.261666;3.805750;3.877667;4.506167;4.162500;4.181750;4.146666;3.890250;3.849875;4.116166;4.118083;4.208167;3.950000;4.283625;4.089875;4.224333;4.217750;4.234625;4.166709;4.066666;4.212584;4.336375;4.250292;4.180875;4.222458;4.219125;4.060125;4.200833;3.887084;4.454250;4.179708;4.046416;4.045667;4.104625;3.936666;4.128667;4.157583;4.193084;3.881291;4.401875;3.909542;4.126500;4.319250;4.151291;4.130417;4.142500;4.205666;4.290834;4.397625;4.086833;4.155250;4.330625;4.169792;4.146333;3.774916;4.187500;3.773834;3.897834;4.243042;3.813334;4.321792 diff --git a/dev/research/metal_pathfinding/results/validation.txt b/dev/research/metal_pathfinding/results/validation.txt new file mode 100644 index 0000000..a0d4adc --- /dev/null +++ b/dev/research/metal_pathfinding/results/validation.txt @@ -0,0 +1,3 @@ +2026-09-27 00:02:40.947 experiment-sanitize[57855:38285628] Metal API Validation Enabled +2026-09-27 00:02:40.947 experiment-sanitize[57855:38285628] Metal GPU Validation Enabled +device=Apple M4 Max setup_ms=28.2634 execution_width=32 diff --git a/dev/research/metal_pathfinding/results/witnesses-sanitized.txt b/dev/research/metal_pathfinding/results/witnesses-sanitized.txt new file mode 100644 index 0000000..6159e5d --- /dev/null +++ b/dev/research/metal_pathfinding/results/witnesses-sanitized.txt @@ -0,0 +1,9 @@ +PASS diamond: all ECMP alternatives, parallel edges, positive self-loop excluded, isolated node +PASS reverse diamond: hand-derived distances and forward DAG +PASS masked source and transit node +PASS double capacity threshold: below rejected, exact threshold admitted +PASS edge mask and residual gate combined +PASS exact int64 costs above 2^53 and one-unit path difference +PASS expected gap: zero-cost distances agree, tight-edge GPU DAG has 1->2->1 cycle; CPU DAG has 2 edges +PASS precision gaps: float32 collapses 16777216/16777217 and admits nextafter(kMinCap,0) +PASS capacity tie gap: CPU chooses edge 1 at 1+1e-8; float32 collapses both capacities diff --git a/dev/research/metal_pathfinding/results/witnesses-stderr.txt b/dev/research/metal_pathfinding/results/witnesses-stderr.txt new file mode 100644 index 0000000..6958d46 --- /dev/null +++ b/dev/research/metal_pathfinding/results/witnesses-stderr.txt @@ -0,0 +1 @@ +device=Apple M4 Max setup_ms=25.3313 execution_width=32 diff --git a/dev/research/metal_pathfinding/results/witnesses-validation.txt b/dev/research/metal_pathfinding/results/witnesses-validation.txt new file mode 100644 index 0000000..eb1391c --- /dev/null +++ b/dev/research/metal_pathfinding/results/witnesses-validation.txt @@ -0,0 +1,3 @@ +2026-09-27 00:02:41.134 experiment-sanitize[57187:38285642] Metal API Validation Enabled +2026-09-27 00:02:41.134 experiment-sanitize[57187:38285642] Metal GPU Validation Enabled +device=Apple M4 Max setup_ms=33.3338 execution_width=32 diff --git a/dev/research/metal_pathfinding/results/witnesses.txt b/dev/research/metal_pathfinding/results/witnesses.txt new file mode 100644 index 0000000..6159e5d --- /dev/null +++ b/dev/research/metal_pathfinding/results/witnesses.txt @@ -0,0 +1,9 @@ +PASS diamond: all ECMP alternatives, parallel edges, positive self-loop excluded, isolated node +PASS reverse diamond: hand-derived distances and forward DAG +PASS masked source and transit node +PASS double capacity threshold: below rejected, exact threshold admitted +PASS edge mask and residual gate combined +PASS exact int64 costs above 2^53 and one-unit path difference +PASS expected gap: zero-cost distances agree, tight-edge GPU DAG has 1->2->1 cycle; CPU DAG has 2 edges +PASS precision gaps: float32 collapses 16777216/16777217 and admits nextafter(kMinCap,0) +PASS capacity tie gap: CPU chooses edge 1 at 1+1e-8; float32 collapses both capacities diff --git a/dev/research/metal_pathfinding/results/workspace-check.txt b/dev/research/metal_pathfinding/results/workspace-check.txt new file mode 100644 index 0000000..7f3aec6 --- /dev/null +++ b/dev/research/metal_pathfinding/results/workspace-check.txt @@ -0,0 +1,411 @@ +📦 Installing package (editable, default optimizations) +Obtaining file:///Users/networmix/ws/NetGraph-Core + Installing build dependencies: started + Installing build dependencies: finished with status 'done' + Checking if build backend supports build_editable: started + Checking if build backend supports build_editable: finished with status 'done' + Getting requirements to build editable: started + Getting requirements to build editable: finished with status 'done' + Installing backend dependencies: started + Installing backend dependencies: finished with status 'done' + Preparing editable metadata (pyproject.toml): started + Preparing editable metadata (pyproject.toml): finished with status 'done' +Requirement already satisfied: numpy>=1.23.2 in ./venv/lib/python3.14/site-packages (from netgraph-core==0.10.0) (2.5.2) +Building wheels for collected packages: netgraph-core + Building editable for netgraph-core (pyproject.toml): started + Building editable for netgraph-core (pyproject.toml): finished with status 'done' + Created wheel for netgraph-core: filename=netgraph_core-0.10.0-cp314-cp314-macosx_15_0_arm64.whl size=314893 sha256=4dbd81d69e154acb7b436937ec9e484f0a6e31c56787e8ac028619002e4fa1f9 + Stored in directory: /private/var/folders/8q/438f_q5s0ys8nlnvjqkf953m0000gn/T/pip-ephem-wheel-cache-lpf_6ry7/wheels/18/8c/1a/f701a43f4b69f7c794e11f1f5dd0c17e819d2c98bfd1285718 +Successfully built netgraph-core +Installing collected packages: netgraph-core + Attempting uninstall: netgraph-core + Found existing installation: netgraph-core 0.10.0 + Uninstalling netgraph-core-0.10.0: + Successfully uninstalled netgraph-core-0.10.0 +Successfully installed netgraph-core-0.10.0 +44 files already formatted +All checks passed! +0 errors, 0 warnings, 0 informations +WARNING: there is a new pyright version available (v1.1.401 -> v1.1.414). +Please install the new version or set PYRIGHT_PYTHON_FORCE_VERSION to `latest` + +-- pybind11 not found via config; using FetchContent +-- pybind11 v3.0.0 +-- LTO not supported: CMake doesn't support IPO for current C compiler +-- Configuring done (0.6s) +-- Generating done (0.0s) +-- Build files have been written to: /Users/networmix/ws/NetGraph-Core/build/cpp-tests +[1/21] Building CXX object CMakeFiles/netgraph_core.dir/src/strict_multidigraph.cpp.o +[2/21] Building CXX object CMakeFiles/netgraph_core.dir/src/k_shortest_paths.cpp.o +[3/21] Building CXX object CMakeFiles/netgraph_core.dir/src/shortest_paths.cpp.o +[4/21] Building CXX object CMakeFiles/netgraph_core.dir/src/max_flow.cpp.o +[5/21] Building CXX object CMakeFiles/netgraph_core.dir/src/cpu_backend.cpp.o +[6/21] Building CXX object CMakeFiles/netgraph_core.dir/src/flow_state.cpp.o +[7/21] Building CXX object CMakeFiles/netgraph_core.dir/src/flow_graph.cpp.o +[8/21] Building CXX object CMakeFiles/netgraph_core_tests.dir/tests/cpp/smoke_test.cpp.o +[9/21] Building CXX object CMakeFiles/netgraph_core.dir/src/flow_policy.cpp.o +[10/21] Building CXX object CMakeFiles/netgraph_core_tests.dir/tests/cpp/strict_multidigraph_tests.cpp.o +[11/21] Building CXX object CMakeFiles/netgraph_core_tests.dir/tests/cpp/flow_policy_tests.cpp.o +[12/21] Building CXX object CMakeFiles/netgraph_core_tests.dir/tests/cpp/shortest_paths_tests.cpp.o +[13/21] Building CXX object CMakeFiles/netgraph_core_tests.dir/tests/cpp/flow_state_tests.cpp.o +[14/21] Building CXX object CMakeFiles/netgraph_core_tests.dir/tests/cpp/flow_graph_tests.cpp.o +[15/21] Linking CXX static library libnetgraph_core.a +[16/21] Building CXX object CMakeFiles/netgraph_core_tests.dir/tests/cpp/max_flow_tests.cpp.o +[17/21] Building CXX object CMakeFiles/netgraph_core_tests.dir/tests/cpp/k_shortest_paths_tests.cpp.o +[18/21] Building CXX object CMakeFiles/netgraph_core_tests.dir/tests/cpp/masking_tests.cpp.o +[19/21] Linking CXX executable netgraph_core_tests +[20/21] Building CXX object CMakeFiles/_netgraph_core.dir/bindings/python/module.cpp.o +[21/21] Linking CXX shared module _netgraph_core.cpython-314-darwin.so +Test project /Users/networmix/ws/NetGraph-Core/build/cpp-tests + Start 141: KShortestPaths.DisconnectedReturnsEmpty + Start 132: MaxFlow.Sensitivity_ShortestPathVsMaxFlow + Start 34: StrictMultiDiGraph.NegativeNodeIdThrows + Start 11: FlowPolicyCore.EqualBalanced_ShortestPath_IgnoresHigherCostTier + 1/170 Test #141: KShortestPaths.DisconnectedReturnsEmpty ........................................... Passed 0.00 sec + Start 152: MaskingTests.MaskedIntermediateNode + 2/170 Test #132: MaxFlow.Sensitivity_ShortestPathVsMaxFlow ......................................... Passed 0.00 sec + Start 9: FlowPolicyCore.EqualBalanced_ShortestPath_ECMP3_SaturatesAllEqualCostPaths + 3/170 Test #34: StrictMultiDiGraph.NegativeNodeIdThrows ........................................... Passed 0.00 sec + 4/170 Test #11: FlowPolicyCore.EqualBalanced_ShortestPath_IgnoresHigherCostTier ................... Passed 0.00 sec + Start 105: MaxFlow.AsymmetricCapacity_1to100_Proportional + Start 10: FlowPolicyCore.EqualBalanced_ShortestPath_DownstreamSplit_BalancesBottleneck + 5/170 Test #152: MaskingTests.MaskedIntermediateNode ............................................... Passed 0.00 sec + Start 154: MaskingTests.MaskedEdgeSelectsAlternativePath + 6/170 Test #9: FlowPolicyCore.EqualBalanced_ShortestPath_ECMP3_SaturatesAllEqualCostPaths ........ Passed 0.00 sec + Start 156: MaskingTests.CombinedNodeAndEdgeMasks + 7/170 Test #105: MaxFlow.AsymmetricCapacity_1to100_Proportional .................................... Passed 0.00 sec + Start 144: KShortestPaths.LargerOutOfOrderTopology + 8/170 Test #10: FlowPolicyCore.EqualBalanced_ShortestPath_DownstreamSplit_BalancesBottleneck ...... Passed 0.00 sec + Start 43: ShortestPaths.PredDAGIntegrity + 9/170 Test #154: MaskingTests.MaskedEdgeSelectsAlternativePath ..................................... Passed 0.00 sec + Start 148: MaskingTests.MaskedSourceInMaxFlow + 10/170 Test #156: MaskingTests.CombinedNodeAndEdgeMasks ............................................. Passed 0.00 sec + Start 118: MaxFlow.OptionalOutputs_ResidualAndReachable + 11/170 Test #144: KShortestPaths.LargerOutOfOrderTopology ........................................... Passed 0.00 sec + Start 33: StrictMultiDiGraph.SelfLoopAllowed + 12/170 Test #43: ShortestPaths.PredDAGIntegrity .................................................... Passed 0.00 sec + Start 8: FlowPolicyCore.DiminishingReturnsCutoff + 13/170 Test #148: MaskingTests.MaskedSourceInMaxFlow ................................................ Passed 0.00 sec + Start 138: KShortestPaths.UniqueModeFiltering + 14/170 Test #118: MaxFlow.OptionalOutputs_ResidualAndReachable ...................................... Passed 0.00 sec + Start 92: FlowGraph.LedgerMicroFlows_RemovalRestoresResidual + 15/170 Test #33: StrictMultiDiGraph.SelfLoopAllowed ................................................ Passed 0.00 sec + Start 47: ShortestPaths.ResolveToPathsWithMaxPathsLimit + 16/170 Test #8: FlowPolicyCore.DiminishingReturnsCutoff ........................................... Passed 0.00 sec + Start 83: FlowGraph.EmptyLedgerInitially + 17/170 Test #138: KShortestPaths.UniqueModeFiltering ................................................ Passed 0.00 sec + Start 67: FlowState.InvalidResidualInitThrows + 18/170 Test #47: ShortestPaths.ResolveToPathsWithMaxPathsLimit ..................................... Passed 0.00 sec + Start 17: StrictMultiDiGraph.EmptyGraph + 19/170 Test #92: FlowGraph.LedgerMicroFlows_RemovalRestoresResidual ................................ Passed 0.00 sec + Start 106: MaxFlow.AsymmetricCapacity_1to1M_NumericalStability + 20/170 Test #83: FlowGraph.EmptyLedgerInitially .................................................... Passed 0.00 sec + Start 1: GraphSmoke.ConstructAndRunSPF + 21/170 Test #67: FlowState.InvalidResidualInitThrows ............................................... Passed 0.00 sec + Start 41: ShortestPaths.EdgeMaskFiltering + 22/170 Test #17: StrictMultiDiGraph.EmptyGraph ..................................................... Passed 0.00 sec + Start 89: FlowGraph.GetFlowPathForDAGReturnsEmpty + 23/170 Test #106: MaxFlow.AsymmetricCapacity_1to1M_NumericalStability ............................... Passed 0.00 sec + Start 104: MaxFlow.ECMP_TenPaths_ScalabilityValidation + 24/170 Test #1: GraphSmoke.ConstructAndRunSPF ..................................................... Passed 0.00 sec + Start 61: FlowState.ZeroCapacityHandling + 25/170 Test #41: ShortestPaths.EdgeMaskFiltering ................................................... Passed 0.00 sec + Start 22: StrictMultiDiGraph.ExternalEdgeIdsPreserved + 26/170 Test #89: FlowGraph.GetFlowPathForDAGReturnsEmpty ........................................... Passed 0.00 sec + Start 149: MaskingTests.MaskedSourceInComputeMinCut + 27/170 Test #104: MaxFlow.ECMP_TenPaths_ScalabilityValidation ....................................... Passed 0.00 sec + Start 103: MaxFlow.ECMP_FourPaths_ClosFabric_Simulation + 28/170 Test #61: FlowState.ZeroCapacityHandling .................................................... Passed 0.00 sec + Start 155: MaskingTests.MultipleEdgesMasked + 29/170 Test #22: StrictMultiDiGraph.ExternalEdgeIdsPreserved ....................................... Passed 0.00 sec + Start 109: MaxFlow.ZeroCapacityPath_CorrectFiltering + 30/170 Test #149: MaskingTests.MaskedSourceInComputeMinCut .......................................... Passed 0.00 sec + Start 126: MaxFlow.Triangle_Topology_Combine_Mode + 31/170 Test #103: MaxFlow.ECMP_FourPaths_ClosFabric_Simulation ...................................... Passed 0.00 sec + Start 107: MaxFlow.AsymmetricCapacity_1to100_EqualBalanced + 32/170 Test #155: MaskingTests.MultipleEdgesMasked .................................................. Passed 0.00 sec + Start 122: MaxFlow.GridGraph_3x3_MultipleEqualCostPaths + 33/170 Test #109: MaxFlow.ZeroCapacityPath_CorrectFiltering ......................................... Passed 0.00 sec + Start 42: ShortestPaths.EarlyExitOptimization + 34/170 Test #126: MaxFlow.Triangle_Topology_Combine_Mode ............................................ Passed 0.00 sec + Start 64: FlowState.MinCutComputation + 35/170 Test #107: MaxFlow.AsymmetricCapacity_1to100_EqualBalanced ................................... Passed 0.00 sec + Start 75: FlowState.Proportional_ZeroCapacityOnShortestPath_ReturnsZero + 36/170 Test #122: MaxFlow.GridGraph_3x3_MultipleEqualCostPaths ...................................... Passed 0.00 sec + Start 29: StrictMultiDiGraph.ExtEdgeIdsWrongLengthThrows + 37/170 Test #42: ShortestPaths.EarlyExitOptimization ............................................... Passed 0.00 sec + Start 32: StrictMultiDiGraph.NegativeCostThrows + 38/170 Test #64: FlowState.MinCutComputation ....................................................... Passed 0.00 sec + Start 135: KShortestPaths.FindsKPaths + 39/170 Test #75: FlowState.Proportional_ZeroCapacityOnShortestPath_ReturnsZero ..................... Passed 0.00 sec + Start 99: MaxFlow.ECMP_TwoPaths_Proportional_ShortestPath + 40/170 Test #29: StrictMultiDiGraph.ExtEdgeIdsWrongLengthThrows .................................... Passed 0.00 sec + Start 21: StrictMultiDiGraph.EdgeSortingByCost + 41/170 Test #32: StrictMultiDiGraph.NegativeCostThrows ............................................. Passed 0.00 sec + Start 143: KShortestPaths.OutOfOrderNodePredDAGSemantics + 42/170 Test #135: KShortestPaths.FindsKPaths ........................................................ Passed 0.00 sec + Start 37: ShortestPaths.DisconnectedComponents + 43/170 Test #99: MaxFlow.ECMP_TwoPaths_Proportional_ShortestPath ................................... Passed 0.00 sec + Start 7: FlowPolicyCore.EqualBalanced_SingleDemand_FlowCount3_SaturatesBothPaths + 44/170 Test #21: StrictMultiDiGraph.EdgeSortingByCost .............................................. Passed 0.00 sec + Start 69: FlowState.ApplyDeltasClampsWithinCapacityBounds + 45/170 Test #143: KShortestPaths.OutOfOrderNodePredDAGSemantics ..................................... Passed 0.00 sec + Start 134: MaxFlow.CompletionPhase_RespectsNodeMask + 46/170 Test #37: ShortestPaths.DisconnectedComponents .............................................. Passed 0.00 sec + Start 68: FlowState.ResetWithInvalidResidualThrows + 47/170 Test #7: FlowPolicyCore.EqualBalanced_SingleDemand_FlowCount3_SaturatesBothPaths ........... Passed 0.00 sec + Start 112: MaxFlow.EqualCost_ShortestVsFull_Equivalent + 48/170 Test #69: FlowState.ApplyDeltasClampsWithinCapacityBounds ................................... Passed 0.00 sec + Start 157: MaskingTests.NodeMaskOverridesEdgeMask + 49/170 Test #134: MaxFlow.CompletionPhase_RespectsNodeMask .......................................... Passed 0.00 sec + Start 46: ShortestPaths.ResolveToPathsSplittingParallelEdges + 50/170 Test #68: FlowState.ResetWithInvalidResidualThrows .......................................... Passed 0.00 sec + Start 35: StrictMultiDiGraph.MultipleCostTiers + 51/170 Test #112: MaxFlow.EqualCost_ShortestVsFull_Equivalent ....................................... Passed 0.00 sec + Start 133: MaxFlow.CompletionPhase_RecoversCancellation + 52/170 Test #157: MaskingTests.NodeMaskOverridesEdgeMask ............................................ Passed 0.00 sec + Start 153: MaskingTests.MaskedEdgeBlocksPath + 53/170 Test #46: ShortestPaths.ResolveToPathsSplittingParallelEdges ................................ Passed 0.00 sec + Start 114: MaxFlow.PlacementModes_EqualCapacity_IdenticalResult + 54/170 Test #35: StrictMultiDiGraph.MultipleCostTiers .............................................. Passed 0.00 sec + Start 27: StrictMultiDiGraph.InvalidNumNodesThrows + 55/170 Test #133: MaxFlow.CompletionPhase_RecoversCancellation ...................................... Passed 0.00 sec + Start 91: FlowGraph.LedgerHistory_RemovalRestoresResidual + 56/170 Test #153: MaskingTests.MaskedEdgeBlocksPath ................................................. Passed 0.00 sec + Start 20: StrictMultiDiGraph.ParallelEdges + 57/170 Test #114: MaxFlow.PlacementModes_EqualCapacity_IdenticalResult .............................. Passed 0.00 sec + Start 71: FlowState.EqualBalanced_ECMP3_FirstHopEqualization + 58/170 Test #27: StrictMultiDiGraph.InvalidNumNodesThrows .......................................... Passed 0.00 sec + Start 63: FlowState.ApplyDeltasSubtractive + 59/170 Test #91: FlowGraph.LedgerHistory_RemovalRestoresResidual ................................... Passed 0.00 sec + Start 31: StrictMultiDiGraph.NegativeCapacityThrows + 60/170 Test #20: StrictMultiDiGraph.ParallelEdges .................................................. Passed 0.00 sec + Start 2: FlowPolicyCore.Proportional_SingleDemand_UsesShortestPath + 61/170 Test #71: FlowState.EqualBalanced_ECMP3_FirstHopEqualization ................................ Passed 0.00 sec + Start 100: MaxFlow.ECMP_TwoPaths_Proportional_FullMaxFlow + 62/170 Test #63: FlowState.ApplyDeltasSubtractive .................................................. Passed 0.00 sec + Start 5: FlowPolicyCore.Proportional_SingleDemand_PartialPlacement_InsufficientCapacity + 63/170 Test #31: StrictMultiDiGraph.NegativeCapacityThrows ......................................... Passed 0.00 sec + Start 150: MaskingTests.OutOfRangeSourceInComputeMinCut + 64/170 Test #2: FlowPolicyCore.Proportional_SingleDemand_UsesShortestPath ......................... Passed 0.00 sec + Start 76: FlowState.RepeatedPlacementAfterResetAndIndependentInstancesStayStable + 65/170 Test #100: MaxFlow.ECMP_TwoPaths_Proportional_FullMaxFlow .................................... Passed 0.00 sec + Start 121: MaxFlow.BatchMaxFlow_IndependentMaskApplication + 66/170 Test #5: FlowPolicyCore.Proportional_SingleDemand_PartialPlacement_InsufficientCapacity .... Passed 0.00 sec + Start 117: MaxFlow.CostDistribution_AccountsForAllFlow + 67/170 Test #150: MaskingTests.OutOfRangeSourceInComputeMinCut ...................................... Passed 0.00 sec + Start 113: MaxFlow.ThreeCostTiers_ShortestPath_LowestTierOnly + 68/170 Test #76: FlowState.RepeatedPlacementAfterResetAndIndependentInstancesStayStable ............ Passed 0.00 sec + Start 23: StrictMultiDiGraph.CSROffsetsMonotonicity + 69/170 Test #121: MaxFlow.BatchMaxFlow_IndependentMaskApplication ................................... Passed 0.00 sec + Start 48: ShortestPaths.LargeGraphStressTest + 70/170 Test #117: MaxFlow.CostDistribution_AccountsForAllFlow ....................................... Passed 0.00 sec + Start 59: FlowState.ProportionalDistribution + 71/170 Test #113: MaxFlow.ThreeCostTiers_ShortestPath_LowestTierOnly ................................ Passed 0.00 sec + Start 6: FlowPolicyCore.EqualBalanced_SingleDemand_FlowCount2_BalancedDistribution + 72/170 Test #23: StrictMultiDiGraph.CSROffsetsMonotonicity ......................................... Passed 0.00 sec + Start 58: FlowState.PlacementReducesResidual + 73/170 Test #48: ShortestPaths.LargeGraphStressTest ................................................ Passed 0.00 sec + Start 4: FlowPolicyCore.Proportional_SingleDemand_MaxFlowCount1_UsesSinglePath + 74/170 Test #59: FlowState.ProportionalDistribution ................................................ Passed 0.00 sec + Start 130: MaxFlow.Sensitivity_TwoParallelPaths + 75/170 Test #6: FlowPolicyCore.EqualBalanced_SingleDemand_FlowCount2_BalancedDistribution ......... Passed 0.00 sec + Start 44: ShortestPaths.TieBreakingDeterminism + 76/170 Test #58: FlowState.PlacementReducesResidual ................................................ Passed 0.00 sec + Start 140: KShortestPaths.PathsSortedByCost + 77/170 Test #4: FlowPolicyCore.Proportional_SingleDemand_MaxFlowCount1_UsesSinglePath ............. Passed 0.00 sec + Start 158: MaskingTests.MaskWithResidualCapacity + 78/170 Test #130: MaxFlow.Sensitivity_TwoParallelPaths .............................................. Passed 0.00 sec + Start 161: MaskingTests.KSPWithEdgeMask + 79/170 Test #44: ShortestPaths.TieBreakingDeterminism .............................................. Passed 0.00 sec + Start 18: StrictMultiDiGraph.SingleNode + 80/170 Test #140: KShortestPaths.PathsSortedByCost .................................................. Passed 0.00 sec + Start 127: MaxFlow.SimpleParallelPaths_Topology + 81/170 Test #158: MaskingTests.MaskWithResidualCapacity ............................................. Passed 0.00 sec + Start 39: ShortestPaths.ResidualAwareFiltering + 82/170 Test #161: MaskingTests.KSPWithEdgeMask ...................................................... Passed 0.00 sec + Start 162: MaskingTests.MaxFlowWithNodeMask + 83/170 Test #18: StrictMultiDiGraph.SingleNode ..................................................... Passed 0.00 sec + Start 49: ShortestPaths.RejectsMaskLengthMismatch + 84/170 Test #127: MaxFlow.SimpleParallelPaths_Topology .............................................. Passed 0.00 sec + Start 137: KShortestPaths.NodeMaskBlocksPaths + 85/170 Test #39: ShortestPaths.ResidualAwareFiltering .............................................. Passed 0.00 sec + Start 3: FlowPolicyCore.Proportional_SingleDemand_SplitsAcrossTwoEqualCostPaths + 86/170 Test #162: MaskingTests.MaxFlowWithNodeMask .................................................. Passed 0.00 sec + Start 160: MaskingTests.KSPWithNodeMask + 87/170 Test #49: ShortestPaths.RejectsMaskLengthMismatch ........................................... Passed 0.00 sec + Start 116: MaxFlow.MinCut_ValidEdgeIdentification + 88/170 Test #137: KShortestPaths.NodeMaskBlocksPaths ................................................ Passed 0.00 sec + Start 142: KShortestPaths.LooplessPaths + 89/170 Test #3: FlowPolicyCore.Proportional_SingleDemand_SplitsAcrossTwoEqualCostPaths ............ Passed 0.00 sec + Start 88: FlowGraph.GetFlowPathForLinearFlow + 90/170 Test #160: MaskingTests.KSPWithNodeMask ...................................................... Passed 0.00 sec + Start 108: MaxFlow.EqualBalanced_NodeMask_ReducesECMPWidth + 91/170 Test #116: MaxFlow.MinCut_ValidEdgeIdentification ............................................ Passed 0.00 sec + Start 50: ShortestPaths.ZeroCostEdges_PredDAGIsAcyclic + 92/170 Test #142: KShortestPaths.LooplessPaths ...................................................... Passed 0.00 sec + Start 36: ShortestPaths.SingleSourceAllNodes + 93/170 Test #88: FlowGraph.GetFlowPathForLinearFlow ................................................ Passed 0.00 sec + Start 136: KShortestPaths.KEqualsZeroReturnsEmpty + 94/170 Test #108: MaxFlow.EqualBalanced_NodeMask_ReducesECMPWidth ................................... Passed 0.00 sec + Start 38: ShortestPaths.MultipleEqualCostPaths + 95/170 Test #50: ShortestPaths.ZeroCostEdges_PredDAGIsAcyclic ...................................... Passed 0.00 sec + Start 97: MaxFlow.SinglePath_ShortestPathEquivalence + 96/170 Test #36: ShortestPaths.SingleSourceAllNodes ................................................ Passed 0.00 sec + Start 90: FlowGraph.CoalescesDuplicateEdgeIds + 97/170 Test #136: KShortestPaths.KEqualsZeroReturnsEmpty ............................................ Passed 0.00 sec + Start 131: MaxFlow.Sensitivity_PartialSaturation + 98/170 Test #38: ShortestPaths.MultipleEqualCostPaths .............................................. Passed 0.00 sec + Start 45: ShortestPaths.PreferHigherResidualTieBreak + 99/170 Test #97: MaxFlow.SinglePath_ShortestPathEquivalence ........................................ Passed 0.00 sec + Start 129: MaxFlow.Sensitivity_SinglePath +100/170 Test #90: FlowGraph.CoalescesDuplicateEdgeIds ............................................... Passed 0.00 sec + Start 110: MaxFlow.TwoCostTiers_ShortestPath_SingleTierOnly +101/170 Test #131: MaxFlow.Sensitivity_PartialSaturation ............................................. Passed 0.00 sec + Start 28: StrictMultiDiGraph.MismatchedArrayLengthsThrow +102/170 Test #45: ShortestPaths.PreferHigherResidualTieBreak ........................................ Passed 0.00 sec + Start 111: MaxFlow.TwoCostTiers_FullMaxFlow_AllTiers +103/170 Test #129: MaxFlow.Sensitivity_SinglePath .................................................... Passed 0.00 sec + Start 146: MaskingTests.MaskedSourceReturnsEmptyDAG +104/170 Test #110: MaxFlow.TwoCostTiers_ShortestPath_SingleTierOnly .................................. Passed 0.00 sec + Start 24: StrictMultiDiGraph.CSRReverseAdjacency +105/170 Test #28: StrictMultiDiGraph.MismatchedArrayLengthsThrow .................................... Passed 0.00 sec + Start 124: MaxFlow.Clos_3Tier_Topology_Proportional_Shortest +106/170 Test #111: MaxFlow.TwoCostTiers_FullMaxFlow_AllTiers ......................................... Passed 0.00 sec + Start 120: MaxFlow.EdgeMask_SelectiveEdgeFiltering +107/170 Test #146: MaskingTests.MaskedSourceReturnsEmptyDAG .......................................... Passed 0.00 sec + Start 25: StrictMultiDiGraph.MaxCapacityEdges +108/170 Test #24: StrictMultiDiGraph.CSRReverseAdjacency ............................................ Passed 0.00 sec + Start 57: FlowState.InitialResidualEqualsCapacity +109/170 Test #124: MaxFlow.Clos_3Tier_Topology_Proportional_Shortest ................................. Passed 0.00 sec + Start 123: MaxFlow.SharedBottleneck_MultiplePathsMerge +110/170 Test #120: MaxFlow.EdgeMask_SelectiveEdgeFiltering ........................................... Passed 0.00 sec + Start 40: ShortestPaths.NodeMaskIsolation +111/170 Test #25: StrictMultiDiGraph.MaxCapacityEdges ............................................... Passed 0.00 sec + Start 125: MaxFlow.Clos_3Tier_Topology_EqualBalanced_Shortest +112/170 Test #57: FlowState.InitialResidualEqualsCapacity ........................................... Passed 0.00 sec + Start 128: MaxFlow.ShortestPath_MustSaturateAllEqualCostPaths +113/170 Test #123: MaxFlow.SharedBottleneck_MultiplePathsMerge ....................................... Passed 0.00 sec + Start 74: FlowState.EqualBalanced_ZeroCapacityOnShortestPath_ReturnsZero +114/170 Test #40: ShortestPaths.NodeMaskIsolation ................................................... Passed 0.00 sec + Start 70: FlowState.EqualBalancedReconvergentDAGPlacesAll +115/170 Test #125: MaxFlow.Clos_3Tier_Topology_EqualBalanced_Shortest ................................ Passed 0.00 sec + Start 147: MaskingTests.MaskedSourceWithDestination +116/170 Test #128: MaxFlow.ShortestPath_MustSaturateAllEqualCostPaths ................................ Passed 0.00 sec + Start 159: MaskingTests.ResidualAndNodeMaskCombined +117/170 Test #74: FlowState.EqualBalanced_ZeroCapacityOnShortestPath_ReturnsZero .................... Passed 0.00 sec + Start 84: FlowGraph.PlacementCreatesEntry +118/170 Test #70: FlowState.EqualBalancedReconvergentDAGPlacesAll ................................... Passed 0.00 sec + Start 62: FlowState.ApplyDeltasAdditive +119/170 Test #147: MaskingTests.MaskedSourceWithDestination .......................................... Passed 0.00 sec + Start 30: StrictMultiDiGraph.OutOfRangeNodeThrows +120/170 Test #159: MaskingTests.ResidualAndNodeMaskCombined .......................................... Passed 0.00 sec + Start 139: KShortestPaths.MaxCostFactorLimit +121/170 Test #84: FlowGraph.PlacementCreatesEntry ................................................... Passed 0.00 sec + Start 65: FlowState.ResetRestoresCapacity +122/170 Test #62: FlowState.ApplyDeltasAdditive ..................................................... Passed 0.00 sec + Start 19: StrictMultiDiGraph.SingleEdge +123/170 Test #30: StrictMultiDiGraph.OutOfRangeNodeThrows ........................................... Passed 0.00 sec + Start 151: MaskingTests.MaskedDestinationUnreachable +124/170 Test #139: KShortestPaths.MaxCostFactorLimit ................................................. Passed 0.00 sec + Start 60: FlowState.EqualBalancedDistribution +125/170 Test #65: FlowState.ResetRestoresCapacity ................................................... Passed 0.00 sec + Start 96: MaxFlow.SinglePath_BottleneckConstraint +126/170 Test #19: StrictMultiDiGraph.SingleEdge ..................................................... Passed 0.00 sec + Start 26: StrictMultiDiGraph.ZeroCostEdges +127/170 Test #151: MaskingTests.MaskedDestinationUnreachable ......................................... Passed 0.00 sec + Start 115: MaxFlow.FlowConservation_IntermediateNodes +128/170 Test #60: FlowState.EqualBalancedDistribution ............................................... Passed 0.00 sec + Start 72: FlowState.EqualBalanced_MinFlowGating_DoesNotPruneValidParallelEdges +129/170 Test #96: MaxFlow.SinglePath_BottleneckConstraint ........................................... Passed 0.00 sec + Start 66: FlowState.CustomInitialResidual +130/170 Test #26: StrictMultiDiGraph.ZeroCostEdges .................................................. Passed 0.00 sec + Start 102: MaxFlow.ECMP_ThreePaths_Proportional_ShortestPath +131/170 Test #115: MaxFlow.FlowConservation_IntermediateNodes ........................................ Passed 0.00 sec + Start 101: MaxFlow.ECMP_TwoPaths_EqualBalanced_ShortestPath +132/170 Test #72: FlowState.EqualBalanced_MinFlowGating_DoesNotPruneValidParallelEdges .............. Passed 0.00 sec + Start 95: MaxFlow.SinglePath_BasicLinear +133/170 Test #66: FlowState.CustomInitialResidual ................................................... Passed 0.00 sec + Start 98: MaxFlow.DegenerateCase_SourceEqualsSink +134/170 Test #102: MaxFlow.ECMP_ThreePaths_Proportional_ShortestPath ................................. Passed 0.00 sec + Start 86: FlowGraph.RemoveByClassFiltersCorrectly +135/170 Test #101: MaxFlow.ECMP_TwoPaths_EqualBalanced_ShortestPath .................................. Passed 0.00 sec + Start 73: FlowState.EqualBalanced_DownstreamSplitEqualization +136/170 Test #95: MaxFlow.SinglePath_BasicLinear .................................................... Passed 0.00 sec + Start 119: MaxFlow.NodeMask_BlocksFlowThroughNode +137/170 Test #98: MaxFlow.DegenerateCase_SourceEqualsSink ........................................... Passed 0.00 sec + Start 85: FlowGraph.RemovalDeletesEntry +138/170 Test #86: FlowGraph.RemoveByClassFiltersCorrectly ........................................... Passed 0.00 sec + Start 87: FlowGraph.GetFlowEdgesReturnsDeltas +139/170 Test #73: FlowState.EqualBalanced_DownstreamSplitEqualization ............................... Passed 0.00 sec + Start 163: MaskingTests.MaxFlowWithEdgeMask +140/170 Test #119: MaxFlow.NodeMask_BlocksFlowThroughNode ............................................ Passed 0.00 sec + Start 164: MaskingTests.MaxFlowAllPathsMasked +141/170 Test #85: FlowGraph.RemovalDeletesEntry ..................................................... Passed 0.00 sec + Start 165: MaskingTests.EmptyNodeMaskAllowsAllNodes +142/170 Test #87: FlowGraph.GetFlowEdgesReturnsDeltas ............................................... Passed 0.00 sec + Start 12: FlowPolicyStatic.PerFlowBundleBinding +143/170 Test #163: MaskingTests.MaxFlowWithEdgeMask .................................................. Passed 0.00 sec + Start 169: MaskingTests.AlgorithmsAPIMaskedSource +144/170 Test #164: MaskingTests.MaxFlowAllPathsMasked ................................................ Passed 0.00 sec + Start 13: FlowPolicyStatic.MaskedBundleIsDown +145/170 Test #165: MaskingTests.EmptyNodeMaskAllowsAllNodes .......................................... Passed 0.00 sec + Start 15: FlowPolicyCostBounds.MaxPathCostFactor_UnreachableDst_KeepsSentinelOutOfTheCast +146/170 Test #12: FlowPolicyStatic.PerFlowBundleBinding ............................................. Passed 0.00 sec + Start 14: FlowPolicyStatic.ValidationRejectsForeignAndDisconnectedBundles +147/170 Test #169: MaskingTests.AlgorithmsAPIMaskedSource ............................................ Passed 0.00 sec + Start 55: ShortestPathsTo.FanoutFromInteriorNodeIsRejected +148/170 Test #13: FlowPolicyStatic.MaskedBundleIsDown ............................................... Passed 0.00 sec + Start 166: MaskingTests.EmptyEdgeMaskAllowsAllEdges +149/170 Test #15: FlowPolicyCostBounds.MaxPathCostFactor_UnreachableDst_KeepsSentinelOutOfTheCast ... Passed 0.00 sec + Start 81: FlowState.EqualBalancedLossy_InfiniteRequestFillsWithoutDrops +150/170 Test #14: FlowPolicyStatic.ValidationRejectsForeignAndDisconnectedBundles ................... Passed 0.00 sec + Start 16: FlowPolicyCostBounds.MaxPathCostFactor_HugeProduct_DropsBoundInsteadOfWrapping +151/170 Test #55: ShortestPathsTo.FanoutFromInteriorNodeIsRejected .................................. Passed 0.00 sec + Start 52: ShortestPathsTo.ForwardSpfFromPseudoSourceKeepsOnlyNearestSource +152/170 Test #166: MaskingTests.EmptyEdgeMaskAllowsAllEdges .......................................... Passed 0.00 sec + Start 51: ShortestPathsTo.DistancesMatchForwardDistancesToDst +153/170 Test #81: FlowState.EqualBalancedLossy_InfiniteRequestFillsWithoutDrops ..................... Passed 0.00 sec + Start 170: MaskingTests.AlgorithmsAPIMaxFlowWithMask +154/170 Test #16: FlowPolicyCostBounds.MaxPathCostFactor_HugeProduct_DropsBoundInsteadOfWrapping .... Passed 0.00 sec + Start 82: FlowGraph.LossyPlacementIsReversibleAndDropsStayOutOfLedger +155/170 Test #52: ShortestPathsTo.ForwardSpfFromPseudoSourceKeepsOnlyNearestSource .................. Passed 0.00 sec + Start 167: MaskingTests.AllNodesMaskedNoReachability +156/170 Test #51: ShortestPathsTo.DistancesMatchForwardDistancesToDst ............................... Passed 0.00 sec + Start 168: MaskingTests.AllEdgesMaskedNoReachability +157/170 Test #170: MaskingTests.AlgorithmsAPIMaxFlowWithMask ......................................... Passed 0.00 sec + Start 94: FlowGraphStamp.EqualVersionDivergentCopiesCompareUnequal +158/170 Test #82: FlowGraph.LossyPlacementIsReversibleAndDropsStayOutOfLedger ....................... Passed 0.00 sec + Start 79: FlowState.EqualBalancedLossy_FillAndDropReportsDrops +159/170 Test #167: MaskingTests.AllNodesMaskedNoReachability ......................................... Passed 0.00 sec + Start 53: ShortestPathsTo.FanoutEdgesForceEverySourceIntoTheDag +160/170 Test #168: MaskingTests.AllEdgesMaskedNoReachability ......................................... Passed 0.00 sec + Start 80: FlowState.EqualBalancedLossy_DeficitPropagatesDownstream +161/170 Test #94: FlowGraphStamp.EqualVersionDivergentCopiesCompareUnequal .......................... Passed 0.00 sec + Start 93: FlowGraphStamp.CopiesAndMovesGetFreshUids +162/170 Test #79: FlowState.EqualBalancedLossy_FillAndDropReportsDrops .............................. Passed 0.00 sec +163/170 Test #53: ShortestPathsTo.FanoutEdgesForceEverySourceIntoTheDag ............................. Passed 0.00 sec + Start 145: KSP.MaxCostFactorBelowOne_ReturnsEmptyForAllK + Start 54: ShortestPathsTo.FanoutSkipsUnreachableAndMaskedHeads +164/170 Test #80: FlowState.EqualBalancedLossy_DeficitPropagatesDownstream .......................... Passed 0.00 sec + Start 77: FlowState.EqualBalanced_SaturatedMemberBlocksAdmission +165/170 Test #93: FlowGraphStamp.CopiesAndMovesGetFreshUids ......................................... Passed 0.00 sec + Start 56: ShortestPathsTo.SinglePathModeKeepsOneSuccessorPerNode +166/170 Test #145: KSP.MaxCostFactorBelowOne_ReturnsEmptyForAllK ..................................... Passed 0.00 sec + Start 78: FlowState.EqualBalanced_ProgressesOnlyThroughResidualAwareSpf +167/170 Test #54: ShortestPathsTo.FanoutSkipsUnreachableAndMaskedHeads .............................. Passed 0.00 sec +168/170 Test #77: FlowState.EqualBalanced_SaturatedMemberBlocksAdmission ............................ Passed 0.00 sec +169/170 Test #56: ShortestPathsTo.SinglePathModeKeepsOneSuccessorPerNode ............................ Passed 0.00 sec +170/170 Test #78: FlowState.EqualBalanced_ProgressesOnlyThroughResidualAwareSpf ..................... Passed 0.00 sec + +100% tests passed out of 170 + +Total Test time (real) = 0.10 sec +........................................................................ [ 15%] +........................................................................ [ 30%] +........................................................................ [ 46%] +........................................................................ [ 61%] +........................................................................ [ 77%] +........................................................................ [ 92%] +................................. [100%] +465 passed in 4.07s diff --git a/dev/research/metal_pathfinding/run_aba.sh b/dev/research/metal_pathfinding/run_aba.sh new file mode 100644 index 0000000..70f8f25 --- /dev/null +++ b/dev/research/metal_pathfinding/run_aba.sh @@ -0,0 +1,24 @@ +#!/usr/bin/env bash +# Serial fresh-process CPU / Metal / CPU runs. Do not overlap with builds/tests. +set -euo pipefail +cd "$(dirname "$0")/../.." +out=${1:-dev/research/metal_pathfinding/results} +mkdir -p "$out" +unset NGRAPH_CORE_PROFILE +{ + date -u '+%Y-%m-%dT%H:%M:%SZ' + git rev-parse HEAD + sw_vers + sysctl -n machdep.cpu.brand_string hw.memsize hw.ncpu + xcrun clang++ --version + shasum -a 256 dev/research/metal_pathfinding/experiment.mm dev/research/metal_pathfinding/sssp.metal + pmset -g therm +} > "$out/environment.txt" +for phase in a1 b a2; do + top -l 2 -n 8 -o cpu -stats pid,command,cpu,threads > "$out/load-$phase.txt" + ioreg -r -c AGXAccelerator -l | sed -n '/"PerformanceStatistics"/p' > "$out/gpu-load-$phase.txt" + mode=cpu + [[ $phase != b ]] || mode=gpu + build/metal_pathfinding/experiment "$mode" dev/research/metal_pathfinding/sssp.metal full 9 \ + > "$out/$phase.csv" 2> "$out/$phase-stderr.txt" +done diff --git a/dev/research/metal_pathfinding/sssp.metal b/dev/research/metal_pathfinding/sssp.metal new file mode 100644 index 0000000..c8e486c --- /dev/null +++ b/dev/research/metal_pathfinding/sssp.metal @@ -0,0 +1,122 @@ +#include +using namespace metal; + +// Research kernels: exact int64, nonnegative costs, one writer per distance. +// Incoming CSR includes a host-computed edge eligibility byte, so double +// capacity comparisons keep their CPU semantics. +constant long INF = 0x7fffffffffffffffL; +struct Params { uint n; uint queries; uint round; uint unused; }; + +kernel void relax_pull(device const int* row [[buffer(0)]], + device const int* col [[buffer(1)]], + device const long* cost [[buffer(2)]], + device const uchar* allowed [[buffer(3)]], + device const long* before [[buffer(4)]], + device long* after [[buffer(5)]], + device atomic_uint* changed [[buffer(6)]], + constant Params& p [[buffer(7)]], + uint tid [[thread_position_in_grid]]) { + if (tid >= p.n * p.queries) return; + uint v = tid % p.n; + uint base = tid - v; + long best = before[tid]; + for (int j = row[v]; j < row[v + 1]; ++j) { + long d = before[base + col[j]]; + if (allowed[j] && d != INF) best = min(best, d + cost[j]); + } + after[tid] = best; + if (best != before[tid]) + atomic_store_explicit(changed + p.round, 1u, memory_order_relaxed); +} + +// A whole SSSP in one threadgroup, with independent queries across groups. +// Each group owns both of its N-element distance arrays. Device-memory barriers +// are local to that group; no unsafe grid-wide barrier or in-place data race. +kernel void solve_group(device const int* row [[buffer(0)]], + device const int* col [[buffer(1)]], + device const long* cost [[buffer(2)]], + device const uchar* allowed [[buffer(3)]], + device long* a [[buffer(4)]], + device long* b [[buffer(5)]], + device uint* rounds [[buffer(6)]], + constant Params& p [[buffer(7)]], + device const int* sources [[buffer(8)]], + uint lane [[thread_index_in_threadgroup]], + uint width [[threads_per_threadgroup]], + uint query [[threadgroup_position_in_grid]]) { + uint base = query * p.n; + for (uint v = lane; v < p.n; v += width) + a[base + v] = (int(v) == sources[query]) ? 0L : INF; + threadgroup atomic_uint changed; + threadgroup_barrier(mem_flags::mem_device); + uint step = 0; + for (; step < p.n; ++step) { + if (lane == 0) atomic_store_explicit(&changed, 0u, memory_order_relaxed); + threadgroup_barrier(mem_flags::mem_threadgroup); + for (uint v = lane; v < p.n; v += width) { + long best = a[base + v]; + for (int j = row[v]; j < row[v + 1]; ++j) { + long d = a[base + col[j]]; + if (allowed[j] && d != INF) best = min(best, d + cost[j]); + } + b[base + v] = best; + if (best != a[base + v]) + atomic_store_explicit(&changed, 1u, memory_order_relaxed); + } + threadgroup_barrier(mem_flags::mem_device | mem_flags::mem_threadgroup); + uint any_changed = atomic_load_explicit(&changed, memory_order_relaxed); + // Every lane must observe this round before lane 0 resets the flag for the + // next one. A barrier *before* the loads alone does not prevent that race. + threadgroup_barrier(mem_flags::mem_threadgroup); + if (any_changed == 0) break; + device long* tmp = a; a = b; b = tmp; + } + // Host selects the output buffer by round parity; convergence leaves a == b. + if (lane == 0) rounds[query] = min(step + 1, p.n); +} + +// Small-graph variant: 2 * N * 8 bytes of threadgroup memory, N <= 2048 on +// this device. Removes repeated device-memory accesses and barriers per round. +kernel void solve_shared(device const int* row [[buffer(0)]], + device const int* col [[buffer(1)]], + device const long* cost [[buffer(2)]], + device const uchar* allowed [[buffer(3)]], + device long* output [[buffer(4)]], + device uint* rounds [[buffer(6)]], + constant Params& p [[buffer(7)]], + device const int* sources [[buffer(8)]], + threadgroup long* scratch [[threadgroup(0)]], + uint lane [[thread_index_in_threadgroup]], + uint width [[threads_per_threadgroup]], + uint query [[threadgroup_position_in_grid]]) { + threadgroup long* a = scratch; + threadgroup long* b = scratch + p.n; + for (uint v = lane; v < p.n; v += width) + a[v] = (int(v) == sources[query]) ? 0L : INF; + threadgroup atomic_uint changed; + threadgroup_barrier(mem_flags::mem_threadgroup); + uint step = 0; + for (; step < p.n; ++step) { + if (lane == 0) atomic_store_explicit(&changed, 0u, memory_order_relaxed); + threadgroup_barrier(mem_flags::mem_threadgroup); + bool lane_changed = false; + for (uint v = lane; v < p.n; v += width) { + long best = a[v]; + for (int j = row[v]; j < row[v + 1]; ++j) { + long d = a[col[j]]; + if (allowed[j] && d != INF) best = min(best, d + cost[j]); + } + b[v] = best; + lane_changed |= best != a[v]; + } + if (simd_any(lane_changed) && (lane % 32 == 0)) + atomic_store_explicit(&changed, 1u, memory_order_relaxed); + threadgroup_barrier(mem_flags::mem_threadgroup); + threadgroup long* tmp = a; a = b; b = tmp; + uint any_changed = atomic_load_explicit(&changed, memory_order_relaxed); + threadgroup_barrier(mem_flags::mem_threadgroup); + if (any_changed == 0) break; + } + for (uint v = lane; v < p.n; v += width) output[query * p.n + v] = a[v]; + if (lane == 0) rounds[query] = min(step + 1, p.n); +} diff --git a/dev/research/metal_pathfinding/summarize.py b/dev/research/metal_pathfinding/summarize.py new file mode 100644 index 0000000..217d582 --- /dev/null +++ b/dev/research/metal_pathfinding/summarize.py @@ -0,0 +1,74 @@ +"""Summarize fresh-process A/B/A CSVs; timings are milliseconds per whole batch.""" + +from __future__ import annotations + +import csv +import sys +from pathlib import Path + + +def read(path: Path) -> dict[tuple[str, int, int, int], dict[str, dict[str, str]]]: + cases: dict[tuple[str, int, int, int], dict[str, dict[str, str]]] = {} + with path.open() as file: + for row in csv.DictReader(file): + assert row["correct"] == "pass", row + key = (row["case"], int(row["n"]), int(row["e"]), int(row["queries"])) + cases.setdefault(key, {})[row["method"]] = row + return cases + + +def main() -> None: + root = Path(sys.argv[1]) + a1, b, a2 = (read(root / name) for name in ("a1.csv", "b.csv", "a2.csv")) + assert a1.keys() == b.keys() == a2.keys() + print("Exploratory observations, not a production performance acceptance result.") + print( + "Inspect load-*.txt and gpu-load-*.txt; speedup claims require a quiet machine." + ) + print("The prototype matches supported DAG edge sets, not CPU predecessor order.\n") + print("All times are medians in milliseconds per batch, with nine timed samples.") + print("CPU A columns use serial SPF for Q=1 and the 10-worker pool otherwise.") + print("GPU includes host distance copies and serial CPU ECMP DAG reconstruction.") + print("Upload and pipeline setup are excluded and recorded separately in raw data.") + print("The table picks the fastest measured GPU method for each case.\n") + print( + "| Case | V / E | Q | CPU A1 | GPU B | CPU A2 | GPU method | " + "Distance-only B | CPU drift |" + ) + print("|---|---:|---:|---:|---:|---:|---|---:|---:|") + for key, runs in b.items(): + name, n, e, q = key + baseline = "cpu_full" if q == 1 else "cpu_pool10" + left = float(a1[key][baseline]["wall_ms"]) + right = float(a2[key][baseline]["wall_ms"]) + best = min(runs.values(), key=lambda row: float(row["wall_ms"])) + dist = float(best["distance_wall_ms"]) + drift = 100 * (right / left - 1) + print( + f"| {name} | {n:,} / {e:,} | {q} | {left:.3f} | " + f"{float(best['wall_ms']):.3f} | {right:.3f} | {best['method']} | " + f"{dist:.3f} | {drift:+.1f}% |" + ) + print( + "\nDistance-only timings stop before DAG reconstruction; they are not SPF API timings." + ) + print( + "CPU distance-only and serial full-batch controls are also available in a1/a2.csv." + ) + print("\nDistances-only comparison (both sides omit DAG construction):\n") + print("| Case | V / E | Q | CPU A1 | GPU B | CPU A2 | GPU method |") + print("|---|---:|---:|---:|---:|---:|---|") + for key, runs in b.items(): + name, n, e, q = key + baseline = "cpu_distance" if q == 1 else "cpu_pool10_distance" + left = float(a1[key][baseline]["wall_ms"]) + right = float(a2[key][baseline]["wall_ms"]) + best = min(runs.values(), key=lambda row: float(row["distance_wall_ms"])) + print( + f"| {name} | {n:,} / {e:,} | {q} | {left:.3f} | " + f"{float(best['distance_wall_ms']):.3f} | {right:.3f} | {best['method']} |" + ) + + +if __name__ == "__main__": + main() diff --git a/include/netgraph/core/shortest_paths.hpp b/include/netgraph/core/shortest_paths.hpp index e22699d..30bcd9d 100644 --- a/include/netgraph/core/shortest_paths.hpp +++ b/include/netgraph/core/shortest_paths.hpp @@ -31,6 +31,17 @@ struct PredDAG { std::vector via_edges; // EdgeId used to reach node from predecessor }; +// Frontier queue used by shortest_paths / shortest_paths_to. Both queues pop in +// the same (cost, -bottleneck, node) order and produce bit-identical results; +// the bucket queue is faster when the graph's costs fit a bounded number of +// buckets (max_cost / gcd(costs) + 1 <= 65536), and the heap is used otherwise. +// Auto (the default) applies that rule, or the process-wide override +// NGRAPH_CORE_SPF_QUEUE=heap|bucket read once from the environment. Heap forces +// the reference binary heap; Bucket prefers the bucket queue when the graph is +// eligible. This parameter exists for tests and benchmarks; the Python bindings +// do not expose it. +enum class SpfQueue { Auto, Heap, Bucket }; + // Compute shortest paths from src using Dijkstra's algorithm. // Returns (distances, predecessor_dag) where distances[v] is the shortest cost to reach v // (or inf if unreachable), and predecessor_dag encodes the shortest path structure. @@ -57,7 +68,8 @@ shortest_paths(const StrictMultiDiGraph& g, NodeId src, const EdgeSelection& selection, std::span residual = {}, std::span node_mask = {}, - std::span edge_mask = {}); + std::span edge_mask = {}, + SpfQueue queue = SpfQueue::Auto); // Build the SPF-compatible (distances, PredDAG) pair for one concrete path given // as node/edge sequences (nodes[i] -> nodes[i+1] via edges[i]; so nodes.size() == @@ -126,6 +138,7 @@ shortest_paths_to(const StrictMultiDiGraph& g, NodeId dst, std::span residual = {}, std::span node_mask = {}, std::span edge_mask = {}, - std::span fanout_edges = {}); + std::span fanout_edges = {}, + SpfQueue queue = SpfQueue::Auto); } // namespace netgraph::core diff --git a/include/netgraph/core/strict_multidigraph.hpp b/include/netgraph/core/strict_multidigraph.hpp index 5f14498..42531bc 100644 --- a/include/netgraph/core/strict_multidigraph.hpp +++ b/include/netgraph/core/strict_multidigraph.hpp @@ -44,6 +44,11 @@ class StrictMultiDiGraph { [[nodiscard]] std::span capacity_view() const noexcept { return capacity_; } [[nodiscard]] std::span cost_view() const noexcept { return cost_; } + // Cost summary recorded at construction (0 for a graph without edges): + // the largest edge cost, and the gcd of all edge costs (0 when every cost is + // 0). SPF uses them to size its bucket queue; see shortest_paths.cpp. + [[nodiscard]] Cost max_cost() const noexcept { return max_cost_; } + [[nodiscard]] Cost cost_gcd() const noexcept { return cost_gcd_; } [[nodiscard]] std::span edge_src_view() const noexcept { return src_; } [[nodiscard]] std::span edge_dst_view() const noexcept { return dst_; } [[nodiscard]] std::span ext_edge_ids_view() const noexcept { return ext_edge_ids_; } @@ -62,6 +67,8 @@ class StrictMultiDiGraph { // Core storage (edges may be reordered in compact form) std::int32_t num_nodes_ {0}; std::size_t edges_ {0}; + Cost max_cost_ {0}; + Cost cost_gcd_ {0}; std::vector capacity_ {}; std::vector cost_ {}; std::vector src_ {}; diff --git a/pyproject.toml b/pyproject.toml index 312e5eb..82f3e35 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "scikit_build_core.build" [project] name = "netgraph-core" -version = "0.10.0" +version = "0.11.0" description = "C++ implementation of graph algorithms for network flow analysis and traffic engineering with Python bindings" readme = "README.md" requires-python = ">=3.11" @@ -50,6 +50,8 @@ Homepage = "https://github.com/networmix/NetGraph-Core" wheel.expand-macos-universal-tags = true build-dir = "build/{wheel_tag}" cmake.version = ">=3.23" +# Developer tooling and research records are not part of the distribution. +sdist.exclude = ["dev/"] # Include Python sources from the "python/" directory wheel.packages = ["python/netgraph_core"] diff --git a/src/flow_policy.cpp b/src/flow_policy.cpp index 1c6f3b3..001da5d 100644 --- a/src/flow_policy.cpp +++ b/src/flow_policy.cpp @@ -235,7 +235,7 @@ std::optional> FlowPolicy::get_path_bundle(const FlowGr if (static_cast(dst) >= dag.parent_offsets.size()-1) return std::nullopt; if (dag.parent_offsets[static_cast(dst)] == dag.parent_offsets[static_cast(dst)+1]) return std::nullopt; // Return DAG and cost as-is; placement logic decides proportional vs equal-balanced behavior. - return std::make_optional(std::make_pair(dag, dst_cost)); + return std::make_optional(std::make_pair(std::move(dag), dst_cost)); } /* Create a new flow using the current path bundle. Returns nullptr if no diff --git a/src/flow_state.cpp b/src/flow_state.cpp index 5932f64..3262a1b 100644 --- a/src/flow_state.cpp +++ b/src/flow_state.cpp @@ -535,14 +535,22 @@ Flow FlowState::place_max_flow(NodeId src, NodeId dst, FlowPlacement placement, } Flow total = static_cast(0.0); + // With require_capacity=false the search ignores residuals, so its inputs + // are identical on every pass: compute it once and reuse the result. + std::pair, PredDAG> path_result; + bool have_path_result = false; while (true) { EdgeSelection sel; sel.multi_edge = true; sel.require_capacity = require_capacity; sel.tie_break = EdgeTieBreak::Deterministic; - auto [dist, dag] = shortest_paths(*g_, src, dst, /*multipath=*/true, sel, - require_capacity ? residual_ : std::span{}, - node_mask, edge_mask); + if (require_capacity || !have_path_result) { + path_result = shortest_paths(*g_, src, dst, /*multipath=*/true, sel, + require_capacity ? residual_ : std::span{}, + node_mask, edge_mask); + have_path_result = true; + } + const auto& [dist, dag] = path_result; if (static_cast(dst) >= dag.parent_offsets.size()-1 || dag.parent_offsets[static_cast(dst)] == dag.parent_offsets[static_cast(dst)+1]) { break; } diff --git a/src/max_flow.cpp b/src/max_flow.cpp index 81e3b29..91ee426 100644 --- a/src/max_flow.cpp +++ b/src/max_flow.cpp @@ -120,18 +120,26 @@ calc_max_flow(const StrictMultiDiGraph& g, NodeId src, NodeId dst, // Iterate tiers: SPF over current residual or costs only // require_capacity=true: Require edges to have capacity, exclude saturated links (SDN/TE behavior) // require_capacity=false: Routes based on costs only, ignore capacity (IP/IGP behavior) + // With require_capacity=false the search ignores residuals, so its inputs + // are identical on every tier: compute it once and reuse the result. + std::pair, PredDAG> path_result; + bool have_path_result = false; while (true) { EdgeSelection sel; sel.multi_edge = true; sel.require_capacity = require_capacity; sel.tie_break = EdgeTieBreak::Deterministic; - auto [dist, dag] = shortest_paths( - g, src, dst, - /*multipath=*/true, - sel, - require_capacity ? fs.residual_view() : std::span{}, - use_node_mask ? node_mask : std::span{}, - use_edge_mask ? edge_mask : std::span{}); + if (require_capacity || !have_path_result) { + path_result = shortest_paths( + g, src, dst, + /*multipath=*/true, + sel, + require_capacity ? fs.residual_view() : std::span{}, + use_node_mask ? node_mask : std::span{}, + use_edge_mask ? edge_mask : std::span{}); + have_path_result = true; + } + const auto& [dist, dag] = path_result; // No path if t has no parents in DAG if (static_cast(dst) >= dag.parent_offsets.size() - 1 || diff --git a/src/shortest_paths.cpp b/src/shortest_paths.cpp index 73bdedb..16a40e5 100644 --- a/src/shortest_paths.cpp +++ b/src/shortest_paths.cpp @@ -4,12 +4,14 @@ #include "netgraph/core/profiling.hpp" #include +#include #include #include +#include #include #include -#include #include +#include #include #include #include @@ -239,95 +241,407 @@ resolve_to_paths(const PredDAG& dag, NodeId src, NodeId dst, * Edge-level tie-breaking for parallel edges (PreferHigherResidual or Deterministic) * Node-level tie-breaking for equal-cost nodes (prefers higher bottleneck capacity) - Early exit when specific destination is reached + + Frontier queue. The reference queue is a binary heap on (cost, -bottleneck, + node). When the graph's costs fit a bounded number of buckets + (W = max_cost / gcd(costs) + 1 <= kMaxBucketWidth) the search uses a monotone + bucket queue instead: Dijkstra pops costs in non-decreasing order and every + push is at least the cost being popped, so with W cyclic buckets each bucket + holds exactly one cost value at a time. The active bucket is itself a small + heap on (-bottleneck, node), so the pop sequence is identical to the heap's, + including zero-cost pushes into the active bucket, single-path re-pushes, + stale entries and destination early exit. The two queues therefore produce + bit-identical results; ShortestPaths.QueueDifferential_* enforce that. + + Scratch state lives in a thread-local workspace that is reset after each + search: only the touched nodes when few were touched, the whole arrays + otherwise. This removes the O(N) per-query initialisation that dominated small + destination-limited searches on large graphs. A workspace holds no pointer + into any graph, residual or mask; see ForwardWorkspace for what it retains + between searches and when it shrinks. */ namespace netgraph::core { namespace { -static std::pair, PredDAG> -shortest_paths_core(const StrictMultiDiGraph& g, NodeId src, - std::optional dst, - bool multipath_arg, - const EdgeSelection& selection, - std::span residual, - std::span node_mask, - std::span edge_mask) { - NGRAPH_PROFILE_SCOPE("shortest_paths_core"); + +constexpr Cost kInf = std::numeric_limits::max(); +constexpr std::size_t kMaxBucketWidth = std::size_t{1} << 16; + +using QItem = std::tuple; + +// Reference queue: binary heap on (cost, -bottleneck, node). Keys are unique per +// push (a node is re-pushed only with a strictly smaller cost or a strictly +// larger bottleneck), so the pop order is fully determined by the key. +struct HeapQueue { + // Functor, not a function pointer: std::push_heap / pop_heap inline it. + struct Greater { bool operator()(const QItem& a, const QItem& b) const { return a > b; } }; + std::vector h; + void begin(std::size_t, Cost) { h.clear(); } + void end() { h.clear(); } + void drop_storage() { std::vector fresh; h.swap(fresh); } + bool empty() const { return h.empty(); } + Cost top_cost() const { return std::get<0>(h.front()); } + QItem pop() { + std::pop_heap(h.begin(), h.end(), Greater{}); + QItem t = h.back(); h.pop_back(); return t; + } + void push(Cost c, Cap nr, NodeId v) { + h.emplace_back(c, nr, v); + std::push_heap(h.begin(), h.end(), Greater{}); + } +}; + +// Monotone bucket queue with ordered buckets (see the file comment). +struct BucketQueue { + struct Item { Cap neg_res; NodeId node; }; + struct Greater { + bool operator()(const Item& a, const Item& b) const { + return a.neg_res != b.neg_res ? a.neg_res > b.neg_res : a.node > b.node; + } + }; + std::vector> buckets; + std::vector occ; // one bit per non-empty bucket; all zero between searches + std::vector dirty; // occupancy words set during the current search + std::size_t W = 0, cur_b = 0, pending = 0; + std::size_t item_capacity = 0; // sum of the buckets' retained capacities + std::size_t peak_pending = 0; // largest frontier of the current search + Cost cur = 0, stride = 1; + // A frontier of exactly one item is held inline rather than in a bucket, so + // chain-like stretches pay no bucket bookkeeping; a second push promotes it. + bool inline_item = false; + QItem single; + + void begin(std::size_t width, Cost stride_) { + stride = stride_; + W = width; + if (buckets.size() < W) buckets.resize(W); + const std::size_t words = (W + 63) / 64; + if (occ.size() < words) occ.resize(words, 0); // existing words are already zero + cur = 0; cur_b = 0; pending = 0; peak_pending = 0; inline_item = false; + } + // Early exit can leave items behind: clear the buckets of the words this + // search set (O(buckets used), not O(W)). Retained item storage is dropped + // when it exceeds a small multiple of what this search needed, so the + // workspace does not accumulate the high-water marks of every bucket ever + // used across differently shaped graphs. + void end() { + for (auto w : dirty) { + std::uint64_t word = occ[w]; + while (word) { + const std::size_t b = (static_cast(w) << 6) + static_cast(std::countr_zero(word)); + buckets[b].clear(); + word &= word - 1; + } + occ[w] = 0; + } + dirty.clear(); + pending = 0; inline_item = false; + if (item_capacity > 4 * peak_pending + 4096) drop_storage(); + } + void drop_storage() { + for (auto& b : buckets) { std::vector fresh; b.swap(fresh); } + item_capacity = 0; + } + bool empty() const { return pending == 0; } + std::size_t bucket_of(Cost c) const { + const Cost q = stride == 1 ? c : c / stride; + return static_cast(q % static_cast(W)); + } + void push_bucket(Cost c, Cap nr, NodeId v) { + const std::size_t b = bucket_of(c); + auto& vec = buckets[b]; + if (vec.empty()) { + const std::size_t w = b >> 6; + if (occ[w] == 0) dirty.push_back(static_cast(w)); + occ[w] |= (std::uint64_t{1} << (b & 63)); + } + const std::size_t cap_before = vec.capacity(); + vec.push_back({nr, v}); + if (vec.capacity() != cap_before) item_capacity += vec.capacity() - cap_before; + if (b == cur_b) std::push_heap(vec.begin(), vec.end(), Greater{}); + ++pending; + if (pending > peak_pending) peak_pending = pending; + } + void push(Cost c, Cap nr, NodeId v) { + if (pending == 0) { + single = {c, nr, v}; inline_item = true; pending = 1; + if (peak_pending == 0) peak_pending = 1; + return; + } + if (inline_item) { + // Promote the inline item into the buckets. cur is the cost of the last + // popped item, so every pending cost lies in [cur, cur + max_cost] and + // the cyclic bucket invariant holds from cur_b = bucket_of(cur). + inline_item = false; pending = 0; + cur_b = bucket_of(cur); + push_bucket(std::get<0>(single), std::get<1>(single), std::get<2>(single)); + } + push_bucket(c, nr, v); + } + // Advance to the next non-empty bucket when the active one is exhausted. + // Precondition: pending > 0 and no inline item. + void settle_active() { + if (!buckets[cur_b].empty()) return; + std::size_t i = cur_b + 1; if (i == W) i = 0; + std::size_t w = i >> 6; + std::uint64_t word = occ[w] & (~std::uint64_t{0} << (i & 63)); + const std::size_t nwords = (W + 63) / 64; + while (!word) { w = (w + 1 == nwords) ? 0 : w + 1; word = occ[w]; } + const std::size_t f = (w << 6) + static_cast(std::countr_zero(word)); + const std::size_t steps = f > cur_b ? f - cur_b : f + W - cur_b; + cur += static_cast(steps) * stride; cur_b = f; + std::make_heap(buckets[f].begin(), buckets[f].end(), Greater{}); + } + Cost top_cost() { + if (inline_item) return std::get<0>(single); + settle_active(); return cur; + } + QItem pop() { + if (inline_item) { + inline_item = false; pending = 0; + cur = std::get<0>(single); // cur_b keeps the last activation; promotion recomputes it + return single; + } + settle_active(); + auto& vec = buckets[cur_b]; + std::pop_heap(vec.begin(), vec.end(), Greater{}); + const Item it = vec.back(); vec.pop_back(); --pending; + if (vec.empty()) occ[cur_b >> 6] &= ~(std::uint64_t{1} << (cur_b & 63)); + return {cur, it.neg_res, it.node}; + } +}; + +struct BucketPlan { bool eligible = false; std::size_t width = 0; Cost stride = 1; }; + +BucketPlan plan_buckets(const StrictMultiDiGraph& g) { + BucketPlan p; + p.stride = g.cost_gcd() > 0 ? g.cost_gcd() : 1; + const Cost w = g.max_cost() / p.stride + 1; // max_cost < 2^62, no overflow + p.eligible = w <= static_cast(kMaxBucketWidth); + p.width = p.eligible ? static_cast(w) : 0; + return p; +} + +SpfQueue env_queue_override() { + static const SpfQueue q = [] { + const char* v = std::getenv("NGRAPH_CORE_SPF_QUEUE"); + if (!v) return SpfQueue::Auto; + const std::string s(v); + if (s == "heap") return SpfQueue::Heap; + if (s == "bucket") return SpfQueue::Bucket; + return SpfQueue::Auto; + }(); + return q; +} + +bool use_bucket_queue(const StrictMultiDiGraph& g, SpfQueue requested, BucketPlan& plan) { + const SpfQueue q = requested == SpfQueue::Auto ? env_queue_override() : requested; + if (q == SpfQueue::Heap) return false; + plan = plan_buckets(g); + return plan.eligible; +} + +// Shared reset policy: sparse when few nodes were touched, wholesale otherwise. +// The same predicate decides how outputs are materialised, so the two agree. +template +bool sparse_reset(const WS& ws) { return ws.touched.size() * 4 < ws.dist.size(); } + +// Resizes a fixed-size scratch array; returns true when a much larger buffer +// was released because the graph shrank. +template +bool ensure_sized(Vec& v, std::size_t n, typename Vec::value_type init) { + if (v.size() == n) return false; + bool released = false; + if (n * 4 < v.capacity()) { Vec fresh; v.swap(fresh); released = true; } + v.assign(n, init); + return released; +} + +template +void drop(Vec& v) { Vec fresh; v.swap(fresh); } + +// Forward search scratch. Invariant between searches: dist == kInf, +// min_res == 0, pred_head/pred_tail == -1, pred_count == 0, settled == 0 for +// every node; the entry arrays, touched list and queues are empty. +// +// Retention: the node arrays are sized to the current graph and released when +// a graph less than a quarter the size is searched; at that point the entry +// arrays, touched list, heap and bucket storage are released too. Otherwise +// those growable buffers keep their high-water capacity, except that the +// bucket queue drops its item storage when it exceeds a small multiple of the +// last search's peak frontier. The searches are synchronous and do not call +// back into user code, so a workspace is never re-entered on its thread. +struct ForwardWorkspace { + std::vector dist; + std::vector min_res; + std::vector pred_head, pred_tail, pred_count; + std::vector settled; + std::vector ent_parent; + std::vector ent_edge; + std::vector ent_next; + std::vector touched; + std::vector sel_buf; + HeapQueue heap; + BucketQueue bucket; + + void acquire(std::size_t n) { + const bool shrank = ensure_sized(dist, n, kInf); + ensure_sized(min_res, n, static_cast(0)); + ensure_sized(pred_head, n, -1); + ensure_sized(pred_tail, n, -1); + ensure_sized(pred_count, n, 0); + ensure_sized(settled, n, 0); + if (shrank) { + drop(ent_parent); drop(ent_edge); drop(ent_next); drop(touched); drop(sel_buf); + heap.drop_storage(); bucket.drop_storage(); + } + ent_parent.clear(); ent_edge.clear(); ent_next.clear(); touched.clear(); + } + void release() { + if (sparse_reset(*this)) { + for (auto v : touched) { + const auto i = static_cast(v); + dist[i] = kInf; min_res[i] = 0; pred_head[i] = -1; pred_tail[i] = -1; pred_count[i] = 0; settled[i] = 0; + } + } else { + std::fill(dist.begin(), dist.end(), kInf); + std::fill(min_res.begin(), min_res.end(), static_cast(0)); + std::fill(pred_head.begin(), pred_head.end(), -1); + std::fill(pred_tail.begin(), pred_tail.end(), -1); + std::fill(pred_count.begin(), pred_count.end(), 0); + std::fill(settled.begin(), settled.end(), 0); + } + touched.clear(); + heap.end(); bucket.end(); + } +}; + +// Reverse search scratch; same invariant. Successor lists per tail node u are +// a flat intrusive list of (v, e) entries (succ_head/succ_tail into ent_*). +// has_in_entry[v]: some DAG entry u -> v exists; a fanout edge may not leave +// such a node. +struct ReverseWorkspace { + std::vector dist; + std::vector min_res; + std::vector succ_head, succ_tail; + std::vector settled; + std::vector has_in_entry; + std::vector ent_node; + std::vector ent_edge; + std::vector ent_next; + std::vector touched; + std::vector sel_buf; + HeapQueue heap; + BucketQueue bucket; + + void acquire(std::size_t n) { + const bool shrank = ensure_sized(dist, n, kInf); + ensure_sized(min_res, n, static_cast(0)); + ensure_sized(succ_head, n, -1); + ensure_sized(succ_tail, n, -1); + ensure_sized(settled, n, 0); + ensure_sized(has_in_entry, n, 0); + if (shrank) { + drop(ent_node); drop(ent_edge); drop(ent_next); drop(touched); drop(sel_buf); + heap.drop_storage(); bucket.drop_storage(); + } + ent_node.clear(); ent_edge.clear(); ent_next.clear(); touched.clear(); + } + void release() { + if (sparse_reset(*this)) { + for (auto v : touched) { + const auto i = static_cast(v); + dist[i] = kInf; min_res[i] = 0; succ_head[i] = -1; succ_tail[i] = -1; + settled[i] = 0; has_in_entry[i] = 0; + } + } else { + std::fill(dist.begin(), dist.end(), kInf); + std::fill(min_res.begin(), min_res.end(), static_cast(0)); + std::fill(succ_head.begin(), succ_head.end(), -1); + std::fill(succ_tail.begin(), succ_tail.end(), -1); + std::fill(settled.begin(), settled.end(), 0); + std::fill(has_in_entry.begin(), has_in_entry.end(), 0); + } + touched.clear(); + heap.end(); bucket.end(); + } +}; + +thread_local ForwardWorkspace tls_forward; +thread_local ReverseWorkspace tls_reverse; + +// Restores the workspace invariant on every exit path, including exceptions. +// Callers must record a node in `touched` before writing its scratch entries, +// so that a throwing push_back cannot leave an unrecorded modification behind. +template +struct WorkspaceLease { + WS& ws; + ~WorkspaceLease() { ws.release(); } +}; + +// The search loop, shared by both queues. Precondition: src is allowed and +// initialised in ws (dist 0, min_res max, touched). +template +void run_forward(Queue& pq, ForwardWorkspace& ws, const StrictMultiDiGraph& g, NodeId src, + std::optional dst, bool multipath, const EdgeSelection& selection, + std::span residual, std::span node_mask, + std::span edge_mask, const BucketPlan& plan) { const auto N = g.num_nodes(); const auto row = g.row_offsets_view(); const auto col = g.col_indices_view(); const auto aei = g.adj_edge_index_view(); const auto cost = g.cost_view(); const auto cap = g.capacity_view(); + // Raw pointers into the fixed-size arrays: they are not resized during the + // search, and hoisting them keeps the compiler from reloading the vector + // bases around every store (the workspace is a thread-local object). + Cost* const dist = ws.dist.data(); + Cap* const min_residual_to_node = ws.min_res.data(); + std::int32_t* const pred_head = ws.pred_head.data(); + std::int32_t* const pred_tail = ws.pred_tail.data(); + std::int32_t* const pred_count = ws.pred_count.data(); + char* const settled = ws.settled.data(); + auto& ent_parent = ws.ent_parent; + auto& ent_edge = ws.ent_edge; + auto& ent_next = ws.ent_next; - // Initialize distance array to infinity (max value). - std::vector dist(static_cast(N), std::numeric_limits::max()); - - // Track minimum residual capacity along the path to each node (for node-level tie-breaking). - // When distances are equal, prefer paths with higher bottleneck capacity. - std::vector min_residual_to_node(static_cast(N), static_cast(0)); - - const bool use_node_mask = (node_mask.size() == static_cast(g.num_nodes())); + const bool use_node_mask = (node_mask.size() == static_cast(N)); const bool use_edge_mask = (edge_mask.size() == static_cast(g.num_edges())); - const bool src_allowed = (src >= 0 && src < N && (!use_node_mask || node_mask[static_cast(src)])); - if (src_allowed) { - dist[static_cast(src)] = static_cast(0); - min_residual_to_node[static_cast(src)] = std::numeric_limits::max(); - } + const bool has_residual = (residual.size() == static_cast(g.num_edges())); + const bool require_cap = selection.require_capacity || has_residual; // Predecessor storage as a flat intrusive list: pred_head/pred_tail index into // the ent_* arrays, whose entries are (parent, via_edge) pairs appended in - // discovery order. This avoids the per-node/per-group vector allocations that - // previously dominated SPF runtime (~70% of samples in malloc/free). - std::vector pred_head(static_cast(N), -1); - std::vector pred_tail(static_cast(N), -1); - std::vector ent_parent; ent_parent.reserve(static_cast(g.num_edges())); - std::vector ent_edge; ent_edge.reserve(static_cast(g.num_edges())); - std::vector ent_next; ent_next.reserve(static_cast(g.num_edges())); - auto pred_clear = [&](std::size_t v){ pred_head[v] = -1; pred_tail[v] = -1; }; + // discovery order. pred_count tracks the live length of each list so the + // result can be sized without walking the lists twice. + auto pred_clear = [&](std::size_t v){ pred_head[v] = -1; pred_tail[v] = -1; pred_count[v] = 0; }; auto pred_append = [&](std::size_t v, NodeId p, EdgeId e){ const auto idx = static_cast(ent_parent.size()); ent_parent.push_back(p); ent_edge.push_back(e); ent_next.push_back(-1); if (pred_head[v] < 0) { pred_head[v] = idx; } else { ent_next[static_cast(pred_tail[v])] = idx; } pred_tail[v] = idx; + ++pred_count[v]; }; - if (src_allowed) { - // source has no predecessors - } else { - // Source is out of range or masked out: no traversal, return empty DAG. - PredDAG dag; - dag.parent_offsets.assign(static_cast(N + 1), 0); - return {std::move(dist), std::move(dag)}; - } - - // Priority queue for Dijkstra with capacity-aware node-level tie-breaking. - // QItem is (cost, -residual, node). Negated residual ensures higher capacity = higher priority. - // Lexicographic ordering: cost (minimize) -> residual (maximize) -> node (deterministic). - // This naturally distributes flows across equal-cost paths based on available capacity. - using QItem = std::tuple; - auto cmp = [](const QItem& a, const QItem& b) { return a > b; }; - std::priority_queue, decltype(cmp)> pq(cmp); - pq.emplace(static_cast(0), -std::numeric_limits::max(), src); - Cost best_dst_cost = std::numeric_limits::max(); + + // Queue items are (cost, -residual, node): cost (minimize) -> residual + // (maximize) -> node (deterministic). This naturally distributes flows across + // equal-cost paths based on available capacity. + pq.begin(plan.width, plan.stride); + pq.push(static_cast(0), -std::numeric_limits::max(), src); + Cost best_dst_cost = kInf; bool have_best_dst = false; const bool early_exit = dst.has_value(); const NodeId dst_node = dst.value_or(-1); - const bool has_residual = (residual.size() == static_cast(g.num_edges())); - const bool require_cap = selection.require_capacity || has_residual; - const bool multipath = multipath_arg; - // settled[v] is set once v is popped at its final distance. Equal-cost // predecessor updates are only accepted while v is unsettled: with positive // edge costs every equal-cost parent is discovered before v settles, and with // zero-cost edges this guard is what keeps the PredDAG acyclic (previously a // zero-cost pair u<->v recorded each node as the other's parent). - std::vector settled(static_cast(N), 0); - std::vector sel_buf; sel_buf.reserve(16); + std::vector& selected_edges = ws.sel_buf; while (!pq.empty()) { - // Extract min-cost node from priority queue. - // Structured binding: auto [d_u, neg_res_u, u] = ... destructures the tuple. - auto [d_u, neg_res_u, u] = pq.top(); pq.pop(); + auto [d_u, neg_res_u, u] = pq.pop(); if (u < 0 || u >= N) continue; // Skip stale entries (node already processed at a lower cost). if (d_u > dist[static_cast(u)]) continue; @@ -336,33 +650,30 @@ shortest_paths_core(const StrictMultiDiGraph& g, NodeId src, -neg_res_u < min_residual_to_node[static_cast(u)] - kEpsilon) continue; settled[static_cast(u)] = 1; - // Early exit optimization: record when we first reach destination. if (early_exit && u == dst_node && !have_best_dst) { best_dst_cost = d_u; have_best_dst = true; } if (early_exit && u == dst_node) { - if (pq.empty() || std::get<0>(pq.top()) > best_dst_cost) break; else continue; + if (pq.empty() || pq.top_cost() > best_dst_cost) break; else continue; } - // Iterate over u's outgoing edges using CSR row offsets. auto start = static_cast(row[static_cast(u)]); auto end = static_cast(row[static_cast(u)+1]); std::size_t i = start; - // Process edges grouped by destination node. - // Multigraph may have multiple edges (u, v); CSR clusters them together. + // Process edges grouped by destination node (parallel edges are consecutive in CSR). + // A settled neighbour cannot be improved (costs are non-negative) and no + // longer accepts equal-cost or capacity-tie updates, so its whole parallel + // group is skipped before any edge is examined. while (i < end) { NodeId v = col[i]; - // Skip masked nodes (skip entire neighbor group). - if (use_node_mask && !node_mask[static_cast(v)]) { + if (settled[static_cast(v)] || (use_node_mask && !node_mask[static_cast(v)])) { std::size_t j_skip = i; while (j_skip < end && col[j_skip] == v) ++j_skip; i = j_skip; continue; } // Select best edge(s) from u to v according to policy. - Cost min_edge_cost = std::numeric_limits::max(); - std::vector& selected_edges = sel_buf; selected_edges.clear(); + Cost min_edge_cost = kInf; + selected_edges.clear(); double best_rem_for_min_cost = -1.0; std::size_t j = i; int best_edge_id = -1; - - // Scan all parallel edges from u to v (they are consecutive in CSR). for (; j < end && col[j] == v; ++j) { auto e = static_cast(aei[j]); if (use_edge_mask && !edge_mask[e]) continue; @@ -406,14 +717,10 @@ shortest_paths_core(const StrictMultiDiGraph& g, NodeId src, selected_edges.clear(); selected_edges.push_back(static_cast(best_edge_id)); } - // Update distance and predecessors if we found a better path (or equal-cost with better capacity). if (!selected_edges.empty()) { Cost new_cost = static_cast(d_u + min_edge_cost); auto v_idx = static_cast(v); - - // Compute bottleneck capacity along path to v through u for node-level tie-breaking. - // Uses dynamic residuals if provided, otherwise static capacity. - // This allows tie-breaking by capacity even in cost-only routing mode. + // Bottleneck capacity along the path to v through u (node-level tie-breaking). Cap max_edge_residual = static_cast(0); for (auto edge_id : selected_edges) { const Cap rem = has_residual ? residual[static_cast(edge_id)] @@ -421,60 +728,101 @@ shortest_paths_core(const StrictMultiDiGraph& g, NodeId src, if (rem > max_edge_residual) max_edge_residual = rem; } Cap path_residual = std::min(min_residual_to_node[static_cast(u)], max_edge_residual); - - // Relaxation: found shorter path to v, or equal-cost path with better capacity (single-path mode). + // Relaxation: shorter path, or equal-cost path with better capacity (single-path mode). if (new_cost < dist[v_idx] || (!multipath && new_cost == dist[v_idx] && !settled[v_idx] && path_residual > min_residual_to_node[v_idx] + kEpsilon)) { + if (dist[v_idx] == kInf) ws.touched.push_back(v); dist[v_idx] = new_cost; min_residual_to_node[v_idx] = path_residual; pred_clear(v_idx); for (auto sel_e : selected_edges) pred_append(v_idx, u, sel_e); - pq.emplace(new_cost, -path_residual, v); // Negate residual for max-heap behavior + pq.push(new_cost, -path_residual, v); } - // Multipath: found equal-cost alternative path to v (only while v is - // unsettled; see the settled[] comment above). + // Multipath: equal-cost alternative (only while v is unsettled; see above). + // min_residual_to_node is not updated here: all equal-cost paths are kept, + // none is chosen by residual. else if (multipath && new_cost == dist[v_idx] && !settled[v_idx]) { for (auto sel_e : selected_edges) pred_append(v_idx, u, sel_e); - // Note: In multipath mode, we don't update min_residual_to_node because - // we're collecting all equal-cost paths, not choosing based on residual. } } - i = j; // Advance to next neighbor group + i = j; } - if (have_best_dst) { if (pq.empty() || std::get<0>(pq.top()) > best_dst_cost) break; } + if (have_best_dst) { if (pq.empty() || pq.top_cost() > best_dst_cost) break; } } +} - // Convert flat predecessor lists to PredDAG using CSR-like layout. - // parent_offsets[v]:parent_offsets[v+1] gives the range in parents/via_edges for node v. +// Materialise (distances, PredDAG) from the forward workspace. Per-node +// predecessor lists are independent, so visiting only touched nodes yields the +// same arrays as visiting every node. +std::pair, PredDAG> finish_forward(ForwardWorkspace& ws, std::int32_t N) { + const bool sparse = sparse_reset(ws); + std::vector dist; + if (sparse) { + dist.assign(static_cast(N), kInf); + for (auto v : ws.touched) dist[static_cast(v)] = ws.dist[static_cast(v)]; + } else { + dist = ws.dist; + } PredDAG dag; dag.parent_offsets.assign(static_cast(N+1), 0); - - // Step 1: Count total predecessor entries per node. - for (std::int32_t v=0; v(v)]; i >= 0; i = ent_next[static_cast(i)]) ++c; - dag.parent_offsets[static_cast(v+1)] = static_cast(c); + if (sparse) { + for (auto v : ws.touched) dag.parent_offsets[static_cast(v) + 1] = ws.pred_count[static_cast(v)]; + } else { + for (std::int32_t v = 0; v < N; ++v) dag.parent_offsets[static_cast(v) + 1] = ws.pred_count[static_cast(v)]; } - - // Step 2: Convert counts to cumulative offsets (prefix sum). - for (std::size_t k=1; k(dag.parent_offsets.back())); dag.via_edges.resize(static_cast(dag.parent_offsets.back())); - for (std::int32_t v=0; v(dag.parent_offsets[static_cast(v)]); std::size_t k = 0; - for (std::int32_t i = pred_head[static_cast(v)]; i >= 0; i = ent_next[static_cast(i)]) { - dag.parents[base+k] = ent_parent[static_cast(i)]; - dag.via_edges[base+k] = ent_edge[static_cast(i)]; + for (std::int32_t i = ws.pred_head[static_cast(v)]; i >= 0; i = ws.ent_next[static_cast(i)]) { + dag.parents[base+k] = ws.ent_parent[static_cast(i)]; + dag.via_edges[base+k] = ws.ent_edge[static_cast(i)]; ++k; } - } + }; + if (sparse) { for (auto v : ws.touched) fill(v); } + else { for (std::int32_t v = 0; v < N; ++v) fill(v); } return {std::move(dist), std::move(dag)}; } + +std::pair, PredDAG> +shortest_paths_core(const StrictMultiDiGraph& g, NodeId src, + std::optional dst, + bool multipath, + const EdgeSelection& selection, + std::span residual, + std::span node_mask, + std::span edge_mask, + SpfQueue queue) { + NGRAPH_PROFILE_SCOPE("shortest_paths_core"); + const auto N = g.num_nodes(); + const bool use_node_mask = (node_mask.size() == static_cast(N)); + const bool src_allowed = (src >= 0 && src < N && (!use_node_mask || node_mask[static_cast(src)])); + if (!src_allowed) { + // Source is out of range or masked out: no traversal, return empty DAG. + PredDAG dag; + dag.parent_offsets.assign(static_cast(N + 1), 0); + return {std::vector(static_cast(N), kInf), std::move(dag)}; + } + ForwardWorkspace& ws = tls_forward; + ws.acquire(static_cast(N)); + WorkspaceLease lease{ws}; + ws.touched.push_back(src); // before the writes: see WorkspaceLease + ws.dist[static_cast(src)] = static_cast(0); + ws.min_res[static_cast(src)] = std::numeric_limits::max(); + BucketPlan plan; + if (use_bucket_queue(g, queue, plan)) { + run_forward(ws.bucket, ws, g, src, dst, multipath, selection, residual, node_mask, edge_mask, plan); + } else { + run_forward(ws.heap, ws, g, src, dst, multipath, selection, residual, node_mask, edge_mask, plan); + } + return finish_forward(ws, N); +} + } // namespace std::pair, PredDAG> @@ -484,7 +832,8 @@ shortest_paths(const StrictMultiDiGraph& g, NodeId src, const EdgeSelection& selection, std::span residual, std::span node_mask, - std::span edge_mask) { + std::span edge_mask, + SpfQueue queue) { if (!node_mask.empty() && node_mask.size() != static_cast(g.num_nodes())) { throw std::invalid_argument("shortest_paths: node_mask length mismatch"); } @@ -494,7 +843,7 @@ shortest_paths(const StrictMultiDiGraph& g, NodeId src, if (!residual.empty() && residual.size() != static_cast(g.num_edges())) { throw std::invalid_argument("shortest_paths: residual length mismatch"); } - return shortest_paths_core(g, src, dst, multipath, selection, residual, node_mask, edge_mask); + return shortest_paths_core(g, src, dst, multipath, selection, residual, node_mask, edge_mask, queue); } } // namespace netgraph::core @@ -502,54 +851,45 @@ shortest_paths(const StrictMultiDiGraph& g, NodeId src, /* Reverse Dijkstra: shortest paths from every node *to* one destination. - Mirrors shortest_paths_core over the in-adjacency (in_row_offsets / - in_col_indices / in_adj_edge_index): the priority queue settles nodes by their - distance to dst, edge selection runs per (u -> v) parallel group exactly as in - the forward variant, and node-level tie-breaking in single-path mode prefers - the higher bottleneck capacity toward dst. Successor entries (v, e) are kept - per tail node u while u is unsettled, then bucketed by v into the forward - PredDAG layout that placement consumes. + Mirrors the forward search over the in-adjacency (in_row_offsets / + in_col_indices / in_adj_edge_index): the queue settles nodes by their distance + to dst, edge selection runs per (u -> v) parallel group exactly as in the + forward variant, and node-level tie-breaking in single-path mode prefers the + higher bottleneck capacity toward dst. Successor entries (v, e) are kept per + tail node u while u is unsettled, then bucketed by v into the forward PredDAG + layout that placement consumes. The same two queues apply. */ namespace netgraph::core { namespace { -static std::pair, PredDAG> -shortest_paths_to_core(const StrictMultiDiGraph& g, NodeId target, - bool multipath, - const EdgeSelection& selection, - std::span residual, - std::span node_mask, - std::span edge_mask, - std::span fanout_edges) { - NGRAPH_PROFILE_SCOPE("shortest_paths_to_core"); + +template +void run_reverse(Queue& pq, ReverseWorkspace& ws, const StrictMultiDiGraph& g, NodeId target, + bool multipath, const EdgeSelection& selection, + std::span residual, std::span node_mask, + std::span edge_mask, const BucketPlan& plan) { const auto N = g.num_nodes(); const auto E = g.num_edges(); const auto irow = g.in_row_offsets_view(); const auto icol = g.in_col_indices_view(); const auto iaei = g.in_adj_edge_index_view(); - const auto esrc = g.edge_src_view(); - const auto edst = g.edge_dst_view(); const auto cost = g.cost_view(); const auto cap = g.capacity_view(); - - std::vector dist(static_cast(N), std::numeric_limits::max()); - std::vector min_residual_to_dst(static_cast(N), static_cast(0)); + Cost* const dist = ws.dist.data(); + Cap* const min_residual_to_dst = ws.min_res.data(); + std::int32_t* const succ_head = ws.succ_head.data(); + std::int32_t* const succ_tail = ws.succ_tail.data(); + char* const settled = ws.settled.data(); + char* const has_in_entry = ws.has_in_entry.data(); + auto& ent_node = ws.ent_node; + auto& ent_edge = ws.ent_edge; + auto& ent_next = ws.ent_next; const bool use_node_mask = (node_mask.size() == static_cast(N)); const bool use_edge_mask = (edge_mask.size() == static_cast(E)); const bool has_residual = (residual.size() == static_cast(E)); const bool require_cap = selection.require_capacity || has_residual; - const bool target_allowed = (target >= 0 && target < N && - (!use_node_mask || node_mask[static_cast(target)])); - // Successor lists per tail node u as a flat intrusive list of (v, e) entries. - std::vector succ_head(static_cast(N), -1); - std::vector succ_tail(static_cast(N), -1); - std::vector ent_node; ent_node.reserve(static_cast(E)); - std::vector ent_edge; ent_edge.reserve(static_cast(E)); - std::vector ent_next; ent_next.reserve(static_cast(E)); - // has_in_entry[v]: some DAG entry u -> v exists; a fanout edge may not leave such a node. - std::vector has_in_entry(static_cast(N), 0); auto succ_clear = [&](std::size_t u){ succ_head[u] = -1; succ_tail[u] = -1; }; auto succ_append = [&](std::size_t u, NodeId v, EdgeId e){ const auto idx = static_cast(ent_node.size()); @@ -559,102 +899,143 @@ shortest_paths_to_core(const StrictMultiDiGraph& g, NodeId target, succ_tail[u] = idx; }; - if (target_allowed) { - dist[static_cast(target)] = static_cast(0); - min_residual_to_dst[static_cast(target)] = std::numeric_limits::max(); - - using QItem = std::tuple; - auto cmp = [](const QItem& a, const QItem& b) { return a > b; }; - std::priority_queue, decltype(cmp)> pq(cmp); - pq.emplace(static_cast(0), -std::numeric_limits::max(), target); - std::vector settled(static_cast(N), 0); - std::vector sel_buf; sel_buf.reserve(16); - - while (!pq.empty()) { - auto [d_v, neg_res_v, v] = pq.top(); pq.pop(); - if (v < 0 || v >= N) continue; - if (d_v > dist[static_cast(v)]) continue; - if (!multipath && d_v == dist[static_cast(v)] && - -neg_res_v < min_residual_to_dst[static_cast(v)] - kEpsilon) continue; - settled[static_cast(v)] = 1; - - // In-edges of v, clustered by tail node u (edges are sorted by (src, dst)). - auto start = static_cast(irow[static_cast(v)]); - auto end = static_cast(irow[static_cast(v)+1]); - std::size_t i = start; - while (i < end) { - NodeId u = icol[i]; - if (use_node_mask && !node_mask[static_cast(u)]) { - std::size_t j_skip = i; while (j_skip < end && icol[j_skip] == u) ++j_skip; i = j_skip; continue; - } - Cost min_edge_cost = std::numeric_limits::max(); - std::vector& selected_edges = sel_buf; selected_edges.clear(); - double best_rem_for_min_cost = -1.0; - std::size_t j = i; - int best_edge_id = -1; - for (; j < end && icol[j] == u; ++j) { - auto e = static_cast(iaei[j]); - if (use_edge_mask && !edge_mask[e]) continue; - const Cap rem = has_residual ? residual[e] : cap[e]; - if (require_cap && rem < kMinCap) continue; - const Cost ecost = static_cast(cost[e]); - if (ecost < min_edge_cost) { - min_edge_cost = ecost; - selected_edges.clear(); - if (selection.multi_edge) { - selected_edges.push_back(static_cast(iaei[j])); - } else { + pq.begin(plan.width, plan.stride); + pq.push(static_cast(0), -std::numeric_limits::max(), target); + std::vector& selected_edges = ws.sel_buf; + + while (!pq.empty()) { + auto [d_v, neg_res_v, v] = pq.pop(); + if (v < 0 || v >= N) continue; + if (d_v > dist[static_cast(v)]) continue; + if (!multipath && d_v == dist[static_cast(v)] && + -neg_res_v < min_residual_to_dst[static_cast(v)] - kEpsilon) continue; + settled[static_cast(v)] = 1; + + // In-edges of v, clustered by tail node u (edges are sorted by (src, dst)). + auto start = static_cast(irow[static_cast(v)]); + auto end = static_cast(irow[static_cast(v)+1]); + std::size_t i = start; + while (i < end) { + NodeId u = icol[i]; + if (settled[static_cast(u)] || (use_node_mask && !node_mask[static_cast(u)])) { + std::size_t j_skip = i; while (j_skip < end && icol[j_skip] == u) ++j_skip; i = j_skip; continue; + } + Cost min_edge_cost = kInf; + selected_edges.clear(); + double best_rem_for_min_cost = -1.0; + std::size_t j = i; + int best_edge_id = -1; + for (; j < end && icol[j] == u; ++j) { + auto e = static_cast(iaei[j]); + if (use_edge_mask && !edge_mask[e]) continue; + const Cap rem = has_residual ? residual[e] : cap[e]; + if (require_cap && rem < kMinCap) continue; + const Cost ecost = static_cast(cost[e]); + if (ecost < min_edge_cost) { + min_edge_cost = ecost; + selected_edges.clear(); + if (selection.multi_edge) { + selected_edges.push_back(static_cast(iaei[j])); + } else { + best_edge_id = static_cast(e); + best_rem_for_min_cost = static_cast(rem); + } + } else if (ecost == min_edge_cost) { + if (selection.multi_edge) { + selected_edges.push_back(static_cast(iaei[j])); + } else if (selection.tie_break == EdgeTieBreak::PreferHigherResidual) { + if (static_cast(rem) > best_rem_for_min_cost + kEpsilon) { best_edge_id = static_cast(e); best_rem_for_min_cost = static_cast(rem); - } - } else if (ecost == min_edge_cost) { - if (selection.multi_edge) { - selected_edges.push_back(static_cast(iaei[j])); - } else if (selection.tie_break == EdgeTieBreak::PreferHigherResidual) { - if (static_cast(rem) > best_rem_for_min_cost + kEpsilon) { - best_edge_id = static_cast(e); - best_rem_for_min_cost = static_cast(rem); - } else if (std::abs(static_cast(rem) - best_rem_for_min_cost) <= kEpsilon) { - if (best_edge_id < 0 || static_cast(e) < best_edge_id) best_edge_id = static_cast(e); - } - } else { + } else if (std::abs(static_cast(rem) - best_rem_for_min_cost) <= kEpsilon) { if (best_edge_id < 0 || static_cast(e) < best_edge_id) best_edge_id = static_cast(e); } + } else { + if (best_edge_id < 0 || static_cast(e) < best_edge_id) best_edge_id = static_cast(e); } } - if (!selection.multi_edge && best_edge_id >= 0) { - selected_edges.clear(); - selected_edges.push_back(static_cast(best_edge_id)); + } + if (!selection.multi_edge && best_edge_id >= 0) { + selected_edges.clear(); + selected_edges.push_back(static_cast(best_edge_id)); + } + if (!selected_edges.empty()) { + const Cost new_cost = static_cast(d_v + min_edge_cost); + const auto u_idx = static_cast(u); + Cap max_edge_residual = static_cast(0); + for (auto edge_id : selected_edges) { + const Cap rem = has_residual ? residual[static_cast(edge_id)] + : cap[static_cast(edge_id)]; + if (rem > max_edge_residual) max_edge_residual = rem; } - if (!selected_edges.empty()) { - const Cost new_cost = static_cast(d_v + min_edge_cost); - const auto u_idx = static_cast(u); - Cap max_edge_residual = static_cast(0); - for (auto edge_id : selected_edges) { - const Cap rem = has_residual ? residual[static_cast(edge_id)] - : cap[static_cast(edge_id)]; - if (rem > max_edge_residual) max_edge_residual = rem; - } - const Cap path_residual = std::min(min_residual_to_dst[static_cast(v)], max_edge_residual); - if (new_cost < dist[u_idx] || - (!multipath && new_cost == dist[u_idx] && !settled[u_idx] && - path_residual > min_residual_to_dst[u_idx] + kEpsilon)) { - dist[u_idx] = new_cost; - min_residual_to_dst[u_idx] = path_residual; - succ_clear(u_idx); - for (auto sel_e : selected_edges) succ_append(u_idx, v, sel_e); - has_in_entry[static_cast(v)] = 1; - pq.emplace(new_cost, -path_residual, u); - } else if (multipath && new_cost == dist[u_idx] && !settled[u_idx]) { - for (auto sel_e : selected_edges) succ_append(u_idx, v, sel_e); - has_in_entry[static_cast(v)] = 1; - } + const Cap path_residual = std::min(min_residual_to_dst[static_cast(v)], max_edge_residual); + if (new_cost < dist[u_idx] || + (!multipath && new_cost == dist[u_idx] && !settled[u_idx] && + path_residual > min_residual_to_dst[u_idx] + kEpsilon)) { + if (dist[u_idx] == kInf) ws.touched.push_back(u); + dist[u_idx] = new_cost; + min_residual_to_dst[u_idx] = path_residual; + succ_clear(u_idx); + for (auto sel_e : selected_edges) succ_append(u_idx, v, sel_e); + has_in_entry[static_cast(v)] = 1; + pq.push(new_cost, -path_residual, u); + } else if (multipath && new_cost == dist[u_idx] && !settled[u_idx]) { + for (auto sel_e : selected_edges) succ_append(u_idx, v, sel_e); + has_in_entry[static_cast(v)] = 1; } - i = j; } + i = j; + } + } +} + +std::pair, PredDAG> +shortest_paths_to_core(const StrictMultiDiGraph& g, NodeId target, + bool multipath, + const EdgeSelection& selection, + std::span residual, + std::span node_mask, + std::span edge_mask, + std::span fanout_edges, + SpfQueue queue) { + NGRAPH_PROFILE_SCOPE("shortest_paths_to_core"); + const auto N = g.num_nodes(); + const auto E = g.num_edges(); + const auto esrc = g.edge_src_view(); + const auto edst = g.edge_dst_view(); + const auto cost = g.cost_view(); + const auto cap = g.capacity_view(); + const bool use_node_mask = (node_mask.size() == static_cast(N)); + const bool use_edge_mask = (edge_mask.size() == static_cast(E)); + const bool has_residual = (residual.size() == static_cast(E)); + const bool require_cap = selection.require_capacity || has_residual; + const bool target_allowed = (target >= 0 && target < N && + (!use_node_mask || node_mask[static_cast(target)])); + + ReverseWorkspace& ws = tls_reverse; + ws.acquire(static_cast(N)); + WorkspaceLease lease{ws}; + + if (target_allowed) { + ws.touched.push_back(target); // before the writes: see WorkspaceLease + ws.dist[static_cast(target)] = static_cast(0); + ws.min_res[static_cast(target)] = std::numeric_limits::max(); + BucketPlan plan; + if (use_bucket_queue(g, queue, plan)) { + run_reverse(ws.bucket, ws, g, target, multipath, selection, residual, node_mask, edge_mask, plan); + } else { + run_reverse(ws.heap, ws, g, target, multipath, selection, residual, node_mask, edge_mask, plan); } } + auto succ_append = [&](std::size_t u, NodeId v, EdgeId e){ + const auto idx = static_cast(ws.ent_node.size()); + ws.ent_node.push_back(v); ws.ent_edge.push_back(e); ws.ent_next.push_back(-1); + if (ws.succ_head[u] < 0) { ws.succ_head[u] = idx; } + else { ws.ent_next[static_cast(ws.succ_tail[u])] = idx; } + ws.succ_tail[u] = idx; + }; + // Forced fan-out entries (see the header). for (auto e_raw : fanout_edges) { if (e_raw < 0 || e_raw >= E) { @@ -663,7 +1044,7 @@ shortest_paths_to_core(const StrictMultiDiGraph& g, NodeId target, const auto e = static_cast(e_raw); const NodeId u = esrc[e]; const NodeId v = edst[e]; - if (has_in_entry[static_cast(u)]) { + if (ws.has_in_entry[static_cast(u)]) { throw std::invalid_argument( "shortest_paths_to: a fanout edge must leave a node with no incoming DAG entry " "(otherwise the DAG could contain a cycle)"); @@ -672,40 +1053,57 @@ shortest_paths_to_core(const StrictMultiDiGraph& g, NodeId target, if (use_node_mask && (!node_mask[static_cast(u)] || !node_mask[static_cast(v)])) continue; const Cap rem = has_residual ? residual[e] : cap[e]; if (require_cap && rem < kMinCap) continue; - if (dist[static_cast(v)] == std::numeric_limits::max()) continue; + if (ws.dist[static_cast(v)] == kInf) continue; bool present = false; - for (std::int32_t i = succ_head[static_cast(u)]; i >= 0; i = ent_next[static_cast(i)]) { - if (ent_edge[static_cast(i)] == e_raw) { present = true; break; } + for (std::int32_t i = ws.succ_head[static_cast(u)]; i >= 0; i = ws.ent_next[static_cast(i)]) { + if (ws.ent_edge[static_cast(i)] == e_raw) { present = true; break; } } if (present) continue; + if (ws.dist[static_cast(u)] == kInf) ws.touched.push_back(u); succ_append(static_cast(u), v, e_raw); - if (dist[static_cast(u)] == std::numeric_limits::max()) { - dist[static_cast(u)] = static_cast(cost[e]) + dist[static_cast(v)]; + if (ws.dist[static_cast(u)] == kInf) { + ws.dist[static_cast(u)] = static_cast(cost[e]) + ws.dist[static_cast(v)]; } } - // Bucket successor entries (u -> v via e) by v into the forward PredDAG layout. + // Bucket successor entries (u -> v via e) by v into the forward PredDAG + // layout. Entries within a v range are ordered by ascending tail node, so a + // sparse pass must visit the touched tails in ascending order. + const bool sparse = sparse_reset(ws); + std::vector dist; + if (sparse) { + std::sort(ws.touched.begin(), ws.touched.end()); + dist.assign(static_cast(N), kInf); + for (auto v : ws.touched) dist[static_cast(v)] = ws.dist[static_cast(v)]; + } else { + dist = ws.dist; + } PredDAG dag; dag.parent_offsets.assign(static_cast(N+1), 0); - for (std::int32_t u = 0; u < N; ++u) { - for (std::int32_t i = succ_head[static_cast(u)]; i >= 0; i = ent_next[static_cast(i)]) { - dag.parent_offsets[static_cast(ent_node[static_cast(i)]) + 1] += 1; + auto count = [&](std::int32_t u) { + for (std::int32_t i = ws.succ_head[static_cast(u)]; i >= 0; i = ws.ent_next[static_cast(i)]) { + dag.parent_offsets[static_cast(ws.ent_node[static_cast(i)]) + 1] += 1; } - } + }; + if (sparse) { for (auto u : ws.touched) count(u); } + else { for (std::int32_t u = 0; u < N; ++u) count(u); } for (std::size_t k = 1; k < dag.parent_offsets.size(); ++k) dag.parent_offsets[k] += dag.parent_offsets[k-1]; dag.parents.resize(static_cast(dag.parent_offsets.back())); dag.via_edges.resize(static_cast(dag.parent_offsets.back())); std::vector cursor(dag.parent_offsets.begin(), dag.parent_offsets.end() - 1); - for (std::int32_t u = 0; u < N; ++u) { - for (std::int32_t i = succ_head[static_cast(u)]; i >= 0; i = ent_next[static_cast(i)]) { - const auto v = static_cast(ent_node[static_cast(i)]); + auto fill = [&](std::int32_t u) { + for (std::int32_t i = ws.succ_head[static_cast(u)]; i >= 0; i = ws.ent_next[static_cast(i)]) { + const auto v = static_cast(ws.ent_node[static_cast(i)]); const auto pos = static_cast(cursor[v]++); dag.parents[pos] = u; - dag.via_edges[pos] = ent_edge[static_cast(i)]; + dag.via_edges[pos] = ws.ent_edge[static_cast(i)]; } - } + }; + if (sparse) { for (auto u : ws.touched) fill(u); } + else { for (std::int32_t u = 0; u < N; ++u) fill(u); } return {std::move(dist), std::move(dag)}; } + } // namespace std::pair, PredDAG> @@ -715,7 +1113,8 @@ shortest_paths_to(const StrictMultiDiGraph& g, NodeId dst, std::span residual, std::span node_mask, std::span edge_mask, - std::span fanout_edges) { + std::span fanout_edges, + SpfQueue queue) { if (!node_mask.empty() && node_mask.size() != static_cast(g.num_nodes())) { throw std::invalid_argument("shortest_paths_to: node_mask length mismatch"); } @@ -725,7 +1124,7 @@ shortest_paths_to(const StrictMultiDiGraph& g, NodeId dst, if (!residual.empty() && residual.size() != static_cast(g.num_edges())) { throw std::invalid_argument("shortest_paths_to: residual length mismatch"); } - return shortest_paths_to_core(g, dst, multipath, selection, residual, node_mask, edge_mask, fanout_edges); + return shortest_paths_to_core(g, dst, multipath, selection, residual, node_mask, edge_mask, fanout_edges, queue); } } // namespace netgraph::core diff --git a/src/strict_multidigraph.cpp b/src/strict_multidigraph.cpp index c582270..546b5cf 100644 --- a/src/strict_multidigraph.cpp +++ b/src/strict_multidigraph.cpp @@ -45,6 +45,8 @@ StrictMultiDiGraph StrictMultiDiGraph::from_arrays( // corrupt results. constexpr std::uint64_t kMaxTotalCost = (std::uint64_t{1} << 62); std::uint64_t total_cost = 0; + Cost max_cost = 0; + Cost cost_gcd = 0; for (std::size_t i = 0; i < m; ++i) { if (src[i] < 0 || dst[i] < 0 || src[i] >= num_nodes || dst[i] >= num_nodes) { throw std::out_of_range("edge index out of range of num_nodes"); @@ -60,7 +62,11 @@ StrictMultiDiGraph StrictMultiDiGraph::from_arrays( "overflow int64 cost arithmetic and silently corrupt results"); } total_cost += c; + if (cost[i] > max_cost) max_cost = cost[i]; + cost_gcd = std::gcd(cost_gcd, cost[i]); } + g.max_cost_ = max_cost; + g.cost_gcd_ = cost_gcd; // Gather initial arrays std::vector src_v(src.begin(), src.end()); std::vector dst_v(dst.begin(), dst.end()); diff --git a/tests/cpp/shortest_paths_tests.cpp b/tests/cpp/shortest_paths_tests.cpp index 18d496f..0483b8b 100644 --- a/tests/cpp/shortest_paths_tests.cpp +++ b/tests/cpp/shortest_paths_tests.cpp @@ -1,5 +1,8 @@ #include #include +#include +#include +#include "netgraph/core/constants.hpp" #include "netgraph/core/shortest_paths.hpp" #include "netgraph/core/strict_multidigraph.hpp" #include "netgraph/core/backend.hpp" @@ -451,3 +454,248 @@ TEST(ShortestPathsTo, SinglePathModeKeepsOneSuccessorPerNode) { for (auto p : dag.parents) if (p == 0) ++leaving_src; EXPECT_EQ(leaving_src, 1); } + +// --------------------------------------------------------------------------- +// Queue differential: the bucket queue must reproduce the reference heap's +// results bit for bit (distances, parent_offsets, parents, via_edges) across +// the whole option matrix, including zero-cost edges, masks, residuals, +// single-path capacity ties, destination early exit and workspace reuse. +// --------------------------------------------------------------------------- +namespace { + +using SpfResult = std::pair, PredDAG>; + +struct DiffGraph { + StrictMultiDiGraph g; + std::unique_ptr node_mask, edge_mask; + std::vector residual; + std::span nm() const { return {node_mask.get(), static_cast(g.num_nodes())}; } + std::span em() const { return {edge_mask.get(), static_cast(g.num_edges())}; } +}; + +struct DiffSpec { + unsigned seed; int n; int degree; bool masked; Cost max_cost; int zero_pct; bool int64_offset; +}; + +DiffGraph make_diff_graph(const DiffSpec& s) { + std::mt19937 rng(s.seed); + std::vector src, dst; + std::vector cap; + std::vector cost; + auto draw_cost = [&]() -> Cost { + Cost c = (static_cast(rng() % 100) < s.zero_pct) ? 0 : 1 + static_cast(rng() % static_cast(s.max_cost)); + return c + (s.int64_offset ? (Cost(1) << 34) : 0); + }; + for (int u = 0; u < s.n; ++u) { + src.push_back(u); dst.push_back((u + 1) % s.n); cost.push_back(draw_cost()); cap.push_back(1.0 + double(rng() % 100) / 7.0); + for (int k = 1; k < s.degree; ++k) { + src.push_back(u); dst.push_back(static_cast(rng() % s.n)); // self-loops and parallel edges allowed + cost.push_back(draw_cost()); cap.push_back(1.0 + double(rng() % 100) / 7.0); + } + } + // A root node with out-edges only (never has an incoming DAG entry): its + // out-edges serve as legal fanout edges for the reverse search. + const int root = s.n; + for (int k = 0; k < 3; ++k) { src.push_back(root); dst.push_back(static_cast(rng() % s.n)); cost.push_back(draw_cost()); cap.push_back(2.0); } + DiffGraph d{StrictMultiDiGraph::from_arrays(s.n + 1, src, dst, cap, cost), nullptr, nullptr, {}}; + const int N = d.g.num_nodes(); const int E = d.g.num_edges(); + d.node_mask = std::make_unique(static_cast(N)); + d.edge_mask = std::make_unique(static_cast(E)); + d.residual.assign(d.g.capacity_view().begin(), d.g.capacity_view().end()); + for (int i = 0; i < N; ++i) d.node_mask[static_cast(i)] = !s.masked || rng() % 23 != 0; + for (int i = 0; i < E; ++i) { + d.edge_mask[static_cast(i)] = !s.masked || rng() % 11 != 0; + if (s.masked && rng() % 13 == 0) d.residual[static_cast(i)] = 0; + if (s.masked && rng() % 17 == 0) d.residual[static_cast(i)] = kMinCap * static_cast(rng() % 3); + } + return d; +} + +bool same_result(const SpfResult& a, const SpfResult& b) { + return a.first == b.first && a.second.parent_offsets == b.second.parent_offsets && + a.second.parents == b.second.parents && a.second.via_edges == b.second.via_edges; +} + +const std::vector kDiffSpecs = { + {1, 40, 5, true, 31, 0, false}, {2, 43, 6, true, 31, 0, false}, {3, 46, 6, true, 31, 25, false}, + {4, 60, 4, false, 1, 0, false}, {5, 64, 5, true, 1, 30, false}, {6, 80, 6, true, 1000, 10, false}, + {7, 50, 6, true, 31, 0, true}, {8, 120, 8, false, 31, 0, false}, {9, 90, 3, true, 5, 40, false}, + {10, 30, 12, true, 3, 20, false}, + // Ring graphs (degree 1): a frontier of one node exercises the bucket + // queue's inline item, and zero-cost edges its promotion into the buckets. + {11, 300, 1, false, 31, 0, false}, {12, 300, 1, true, 5, 30, false}, +}; + +template +void for_each_option(const DiffGraph& d, Fn&& fn) { + for (int mp = 0; mp < 2; ++mp) for (int me = 0; me < 2; ++me) for (int tb = 0; tb < 2; ++tb) + for (int rc = 0; rc < 2; ++rc) for (int ur = 0; ur < 2; ++ur) for (int um = 0; um < 2; ++um) { + EdgeSelection sel; + sel.multi_edge = me != 0; + sel.require_capacity = rc != 0; + sel.tie_break = tb ? EdgeTieBreak::PreferHigherResidual : EdgeTieBreak::Deterministic; + auto res = ur ? std::span(d.residual) : std::span{}; + auto nm = um ? d.nm() : std::span{}; + auto em = um ? d.em() : std::span{}; + fn(mp != 0, sel, res, nm, em); + } +} + +} // namespace + +TEST(ShortestPaths, QueueDifferential_Forward) { + std::size_t checked = 0; + for (const auto& spec : kDiffSpecs) { + auto d = make_diff_graph(spec); + const int n = d.g.num_nodes(); + for (NodeId s : {NodeId(0), NodeId(n / 3), NodeId(n - 2), NodeId(n - 1)}) { + for_each_option(d, [&](bool mp, const EdgeSelection& sel, auto res, auto nm, auto em) { + auto full = shortest_paths(d.g, s, std::nullopt, mp, sel, res, nm, em, SpfQueue::Heap); + NodeId far = -1; Cost fd = -1; + for (int v = 0; v < n; ++v) if (full.first[static_cast(v)] != std::numeric_limits::max() && full.first[static_cast(v)] > fd) { fd = full.first[static_cast(v)]; far = v; } + const auto row = d.g.row_offsets_view(); const auto col = d.g.col_indices_view(); + std::vector> dsts = {std::nullopt, s, NodeId((s + n / 2) % n), far}; + if (row[static_cast(s) + 1] > row[static_cast(s)]) dsts.push_back(col[static_cast(row[static_cast(s)])]); + for (auto dst : dsts) { + auto expected = shortest_paths(d.g, s, dst, mp, sel, res, nm, em, SpfQueue::Heap); + for (int rep = 0; rep < 2; ++rep) { + auto actual = shortest_paths(d.g, s, dst, mp, sel, res, nm, em, SpfQueue::Bucket); + ++checked; + ASSERT_TRUE(same_result(expected, actual)) + << "seed=" << spec.seed << " src=" << s << " dst=" << (dst ? *dst : -1) + << " mp=" << mp << " me=" << sel.multi_edge << " rc=" << sel.require_capacity; + } + // Auto must equal one of the two explicit routes, and both equal each other. + auto automatic = shortest_paths(d.g, s, dst, mp, sel, res, nm, em); + ASSERT_TRUE(same_result(expected, automatic)); + } + }); + } + } + EXPECT_GT(checked, 20000u); +} + +TEST(ShortestPaths, QueueDifferential_Reverse) { + std::size_t checked = 0; + for (const auto& spec : kDiffSpecs) { + auto d = make_diff_graph(spec); + const int n = d.g.num_nodes(); + const NodeId root = n - 1; + const auto row = d.g.row_offsets_view(); const auto aei = d.g.adj_edge_index_view(); + std::vector fanout(aei.begin() + row[static_cast(root)], aei.begin() + row[static_cast(root) + 1]); + for (NodeId t : {NodeId(0), NodeId(n / 3), NodeId(n - 2)}) { + for_each_option(d, [&](bool mp, const EdgeSelection& sel, auto res, auto nm, auto em) { + for (int with_fanout = 0; with_fanout < 2; ++with_fanout) { + auto fo = with_fanout ? std::span(fanout) : std::span{}; + auto expected = shortest_paths_to(d.g, t, mp, sel, res, nm, em, fo, SpfQueue::Heap); + for (int rep = 0; rep < 2; ++rep) { + auto actual = shortest_paths_to(d.g, t, mp, sel, res, nm, em, fo, SpfQueue::Bucket); + ++checked; + ASSERT_TRUE(same_result(expected, actual)) + << "seed=" << spec.seed << " dst=" << t << " mp=" << mp << " fanout=" << with_fanout; + } + } + }); + } + } + EXPECT_GT(checked, 5000u); +} + +TEST(ShortestPaths, QueueDifferential_ComparisonHasTeeth) { + // Guard: the comparison must reject a result whose predecessor order differs. + auto d = make_diff_graph(kDiffSpecs[7]); + EdgeSelection sel; + auto a = shortest_paths(d.g, 0, std::nullopt, true, sel, {}, {}, {}, SpfQueue::Heap); + auto b = a; + bool permuted = false; + for (std::size_t v = 0; v + 1 < b.second.parent_offsets.size() && !permuted; ++v) { + auto lo = static_cast(b.second.parent_offsets[v]); + auto hi = static_cast(b.second.parent_offsets[v + 1]); + if (hi - lo >= 2 && b.second.parents[lo] != b.second.parents[hi - 1]) { + std::swap(b.second.parents[lo], b.second.parents[hi - 1]); + std::swap(b.second.via_edges[lo], b.second.via_edges[hi - 1]); + permuted = true; + } + } + ASSERT_TRUE(permuted) << "fixture has no multi-parent node"; + EXPECT_FALSE(same_result(a, b)); + EXPECT_TRUE(same_result(a, a)); +} + +TEST(ShortestPaths, BucketQueueKeepsCapacityOrderedPredecessors) { + // 0 -> {1,2,3} at cost 1 with bottlenecks 1, 3, 2; each -> 4 at cost 1. + // Equal-cost nodes settle in descending bottleneck order, so 4's parents are + // recorded as 2, 3, 1 (not in node-id order). Both queues must agree. + std::vector src = {0, 0, 0, 1, 2, 3}; + std::vector dst = {1, 2, 3, 4, 4, 4}; + std::vector cap = {1.0, 3.0, 2.0, 5.0, 5.0, 5.0}; + std::vector cost = {1, 1, 1, 1, 1, 1}; + auto g = StrictMultiDiGraph::from_arrays(5, src, dst, cap, cost); + EdgeSelection sel; + for (SpfQueue q : {SpfQueue::Heap, SpfQueue::Bucket, SpfQueue::Auto}) { + auto [dist, dag] = shortest_paths(g, 0, std::nullopt, true, sel, {}, {}, {}, q); + std::vector parents(dag.parents.begin() + dag.parent_offsets[4], dag.parents.begin() + dag.parent_offsets[5]); + EXPECT_EQ(parents, (std::vector{2, 3, 1})); + EXPECT_EQ(dist[4], 2); + } +} + +TEST(ShortestPaths, WorkspaceIsResetAfterFanoutThrow) { + auto d = make_diff_graph(kDiffSpecs[1]); + const int n = d.g.num_nodes(); + EdgeSelection sel; + auto before = shortest_paths_to(d.g, 0, true, sel, d.residual, d.nm(), d.em(), {}, SpfQueue::Bucket); + auto before_fwd = shortest_paths(d.g, 3, std::nullopt, true, sel, d.residual, d.nm(), d.em(), SpfQueue::Bucket); + // A fanout edge leaving a node that already has an incoming DAG entry throws + // after the search has filled the workspace. + EdgeId offending = -1; + const auto esrc = d.g.edge_src_view(); + for (std::size_t v = 0; v + 1 < before.second.parent_offsets.size() && offending < 0; ++v) { + if (before.second.parent_offsets[v + 1] > before.second.parent_offsets[v]) { + const auto row = d.g.row_offsets_view(); const auto aei = d.g.adj_edge_index_view(); + if (row[v + 1] > row[v]) offending = aei[static_cast(row[v])]; + } + } + ASSERT_GE(offending, 0); + ASSERT_TRUE(before.second.parent_offsets[static_cast(esrc[static_cast(offending)]) + 1] > + before.second.parent_offsets[static_cast(esrc[static_cast(offending)])]); + std::vector bad = {offending}; + for (SpfQueue q : {SpfQueue::Bucket, SpfQueue::Heap}) { + EXPECT_THROW((void)shortest_paths_to(d.g, 0, true, sel, d.residual, d.nm(), d.em(), bad, q), std::invalid_argument); + EXPECT_THROW((void)shortest_paths_to(d.g, 0, true, sel, d.residual, d.nm(), d.em(), std::vector{n * 10}, q), std::invalid_argument); + auto after = shortest_paths_to(d.g, 0, true, sel, d.residual, d.nm(), d.em(), {}, q); + EXPECT_TRUE(same_result(before, after)); + auto after_fwd = shortest_paths(d.g, 3, std::nullopt, true, sel, d.residual, d.nm(), d.em(), q); + EXPECT_TRUE(same_result(before_fwd, after_fwd)); + } +} + +TEST(ShortestPaths, WorkspaceReuseAcrossGraphSizesAndEmptyGraphs) { + auto small = make_diff_graph(kDiffSpecs[0]); + auto large = make_diff_graph(kDiffSpecs[7]); + auto empty = StrictMultiDiGraph::from_arrays(0, {}, {}, {}, {}); + EdgeSelection sel; + for (SpfQueue q : {SpfQueue::Bucket, SpfQueue::Heap}) { + auto s1 = shortest_paths(small.g, 1, std::nullopt, true, sel, small.residual, small.nm(), small.em(), q); + auto l1 = shortest_paths(large.g, 5, NodeId(7), false, sel, {}, {}, {}, q); + auto r1 = shortest_paths_to(large.g, 9, true, sel, large.residual, {}, {}, {}, q); + auto e1 = shortest_paths(empty, 0, std::nullopt, true, sel, {}, {}, {}, q); + EXPECT_TRUE(e1.first.empty()); + EXPECT_EQ(e1.second.parent_offsets.size(), 1u); + auto e2 = shortest_paths_to(empty, 0, true, sel, {}, {}, {}, {}, q); + EXPECT_TRUE(e2.first.empty()); + auto s2 = shortest_paths(small.g, 1, std::nullopt, true, sel, small.residual, small.nm(), small.em(), q); + auto l2 = shortest_paths(large.g, 5, NodeId(7), false, sel, {}, {}, {}, q); + auto r2 = shortest_paths_to(large.g, 9, true, sel, large.residual, {}, {}, {}, q); + EXPECT_TRUE(same_result(s1, s2)); + EXPECT_TRUE(same_result(l1, l2)); + EXPECT_TRUE(same_result(r1, r2)); + // A masked-out source still returns an all-INF result without touching the workspace. + auto masked = make_bool_mask(static_cast(small.g.num_nodes()), true); + masked[1] = false; + auto m = shortest_paths(small.g, 1, std::nullopt, true, sel, {}, std::span(masked.get(), static_cast(small.g.num_nodes())), {}, q); + for (auto dv : m.first) EXPECT_EQ(dv, std::numeric_limits::max()); + auto s3 = shortest_paths(small.g, 1, std::nullopt, true, sel, small.residual, small.nm(), small.em(), q); + EXPECT_TRUE(same_result(s1, s3)); + } +} diff --git a/tests/cpp/strict_multidigraph_tests.cpp b/tests/cpp/strict_multidigraph_tests.cpp index fb72973..c475009 100644 --- a/tests/cpp/strict_multidigraph_tests.cpp +++ b/tests/cpp/strict_multidigraph_tests.cpp @@ -316,3 +316,39 @@ TEST(StrictMultiDiGraph, MultipleCostTiers) { EXPECT_EQ(cost_view[4], 10); EXPECT_EQ(cost_view[5], 10); } + +TEST(StrictMultiDiGraph, CostSummaryMaxAndGcd) { + auto empty = StrictMultiDiGraph::from_arrays(0, {}, {}, {}, {}); + EXPECT_EQ(empty.max_cost(), 0); + EXPECT_EQ(empty.cost_gcd(), 0); + { + std::vector src = {0, 1, 2}, dst = {1, 2, 0}; + std::vector cap = {1.0, 1.0, 1.0}; + std::vector cost = {6, 9, 0}; + auto g = StrictMultiDiGraph::from_arrays(3, src, dst, cap, cost); + EXPECT_EQ(g.max_cost(), 9); + EXPECT_EQ(g.cost_gcd(), 3); + StrictMultiDiGraph copy = g; + EXPECT_EQ(copy.max_cost(), 9); + EXPECT_EQ(copy.cost_gcd(), 3); + StrictMultiDiGraph moved = std::move(copy); + EXPECT_EQ(moved.max_cost(), 9); + EXPECT_EQ(moved.cost_gcd(), 3); + } + { + std::vector src = {0, 1}, dst = {1, 0}; + std::vector cap = {1.0, 1.0}; + std::vector cost = {0, 0}; + auto g = StrictMultiDiGraph::from_arrays(2, src, dst, cap, cost); + EXPECT_EQ(g.max_cost(), 0); + EXPECT_EQ(g.cost_gcd(), 0); + } + { + std::vector src = {0}, dst = {1}; + std::vector cap = {1.0}; + std::vector cost = {(std::int64_t{1} << 40) + 7}; + auto g = StrictMultiDiGraph::from_arrays(2, src, dst, cap, cost); + EXPECT_EQ(g.max_cost(), (std::int64_t{1} << 40) + 7); + EXPECT_EQ(g.cost_gcd(), (std::int64_t{1} << 40) + 7); + } +} diff --git a/tests/py/test_spf_queue_env.py b/tests/py/test_spf_queue_env.py new file mode 100644 index 0000000..962e814 --- /dev/null +++ b/tests/py/test_spf_queue_env.py @@ -0,0 +1,69 @@ +"""NGRAPH_CORE_SPF_QUEUE selects the SPF frontier queue; both routes must agree.""" + +from __future__ import annotations + +import os +import subprocess +import sys + +SCRIPT = r""" +import hashlib +import numpy as np +import netgraph_core as ngc + +rng = np.random.default_rng(7) +n = 300 +src, dst, cost, cap = [], [], [], [] +for u in range(n): + for k in range(6): + src.append(u); dst.append(int(rng.integers(0, n))) + cost.append(0 if rng.integers(0, 5) == 0 else int(rng.integers(1, 32))) + cap.append(float(1 + rng.integers(0, 100) / 7.0)) +g = ngc.StrictMultiDiGraph.from_arrays( + n, + src=np.array(src, dtype=np.int32), dst=np.array(dst, dtype=np.int32), + capacity=np.array(cap, dtype=np.float64), cost=np.array(cost, dtype=np.int64), + ext_edge_ids=np.arange(len(src), dtype=np.int64), +) +algs = ngc.Algorithms(ngc.Backend.cpu()) +gh = algs.build_graph(g) +h = hashlib.sha256() +residual = np.array(cap, dtype=np.float64); residual[::13] = 0.0 +for s in (0, 17, 150): + for dstn in (None, 5, 299): + for multipath in (True, False): + for me in (True, False): + sel = ngc.EdgeSelection(multi_edge=me, require_capacity=not me, tie_break=ngc.EdgeTieBreak.PREFER_HIGHER_RESIDUAL) + dist, dag = algs.spf(gh, s, dstn, selection=sel, residual=residual, multipath=multipath) + for arr in (np.asarray(dist), np.asarray(dag.parent_offsets), np.asarray(dag.parents), np.asarray(dag.via_edges)): + h.update(np.ascontiguousarray(arr).tobytes()) + dist, dag = algs.spf_to(gh, s, multipath=True) + for arr in (np.asarray(dist), np.asarray(dag.parent_offsets), np.asarray(dag.parents), np.asarray(dag.via_edges)): + h.update(np.ascontiguousarray(arr).tobytes()) +flow, summary = algs.max_flow(gh, 0, 299, with_edge_flows=True) +h.update(repr((flow, list(summary.costs), list(summary.flows))).encode()) +print(h.hexdigest()) +""" + + +def _run(queue: str | None) -> str: + env = dict(os.environ) + env.pop("NGRAPH_CORE_SPF_QUEUE", None) + if queue is not None: + env["NGRAPH_CORE_SPF_QUEUE"] = queue + out = subprocess.run( + [sys.executable, "-c", SCRIPT], + env=env, + check=True, + capture_output=True, + text=True, + ) + return out.stdout.strip() + + +def test_queue_routes_agree_bit_for_bit() -> None: + heap = _run("heap") + bucket = _run("bucket") + auto = _run(None) + assert len(heap) == 64 + assert heap == bucket == auto