@graphty/webgpu-graph-algorithms 0.6.14 → 0.6.15

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (95) hide show
  1. package/README.md +52 -52
  2. package/dist/browser.js +1 -1
  3. package/dist/chunks/{context-Bi6AhScG.js → context-oXphO3yj.js} +36 -28
  4. package/dist/chunks/context-oXphO3yj.js.map +1 -0
  5. package/dist/node.js +1 -1
  6. package/dist/src/accelerator.d.ts +3 -2
  7. package/dist/src/accelerator.d.ts.map +1 -1
  8. package/dist/src/accelerator.js +48 -4
  9. package/dist/src/accelerator.js.map +1 -1
  10. package/dist/src/algorithms/betweenness.d.ts +70 -0
  11. package/dist/src/algorithms/betweenness.d.ts.map +1 -0
  12. package/dist/src/algorithms/betweenness.js +538 -0
  13. package/dist/src/algorithms/betweenness.js.map +1 -0
  14. package/dist/src/algorithms/closeness.d.ts +15 -5
  15. package/dist/src/algorithms/closeness.d.ts.map +1 -1
  16. package/dist/src/algorithms/closeness.js +112 -26
  17. package/dist/src/algorithms/closeness.js.map +1 -1
  18. package/dist/src/constants.d.ts +8 -0
  19. package/dist/src/constants.d.ts.map +1 -1
  20. package/dist/src/constants.js +8 -0
  21. package/dist/src/constants.js.map +1 -1
  22. package/dist/src/index.d.ts +4 -2
  23. package/dist/src/index.d.ts.map +1 -1
  24. package/dist/src/index.js +1 -0
  25. package/dist/src/index.js.map +1 -1
  26. package/dist/src/kernels.d.ts +12 -6
  27. package/dist/src/kernels.d.ts.map +1 -1
  28. package/dist/src/kernels.js +153 -7
  29. package/dist/src/kernels.js.map +1 -1
  30. package/dist/src/primitives/frontier.d.ts +2 -0
  31. package/dist/src/primitives/frontier.d.ts.map +1 -1
  32. package/dist/src/primitives/frontier.js +2 -0
  33. package/dist/src/primitives/frontier.js.map +1 -1
  34. package/dist/src/types/accelerator.d.ts +11 -7
  35. package/dist/src/types/accelerator.d.ts.map +1 -1
  36. package/dist/src/types/algorithms.d.ts +4 -0
  37. package/dist/src/types/algorithms.d.ts.map +1 -1
  38. package/dist/src/types/betweenness.d.ts +35 -0
  39. package/dist/src/types/betweenness.d.ts.map +1 -0
  40. package/dist/src/types/betweenness.js +7 -0
  41. package/dist/src/types/betweenness.js.map +1 -0
  42. package/dist/src/wgsl/bc-backward.wgsl.d.ts +15 -0
  43. package/dist/src/wgsl/bc-backward.wgsl.d.ts.map +1 -0
  44. package/dist/src/wgsl/bc-backward.wgsl.js +34 -0
  45. package/dist/src/wgsl/bc-backward.wgsl.js.map +1 -0
  46. package/dist/src/wgsl/bc-edge-gather.wgsl.d.ts +12 -0
  47. package/dist/src/wgsl/bc-edge-gather.wgsl.d.ts.map +1 -0
  48. package/dist/src/wgsl/bc-edge-gather.wgsl.js +36 -0
  49. package/dist/src/wgsl/bc-edge-gather.wgsl.js.map +1 -0
  50. package/dist/src/wgsl/bc-finalize.wgsl.d.ts +21 -0
  51. package/dist/src/wgsl/bc-finalize.wgsl.d.ts.map +1 -0
  52. package/dist/src/wgsl/bc-finalize.wgsl.js +47 -0
  53. package/dist/src/wgsl/bc-finalize.wgsl.js.map +1 -0
  54. package/dist/src/wgsl/bc-forward-edge.wgsl.d.ts +15 -0
  55. package/dist/src/wgsl/bc-forward-edge.wgsl.d.ts.map +1 -0
  56. package/dist/src/wgsl/bc-forward-edge.wgsl.js +76 -0
  57. package/dist/src/wgsl/bc-forward-edge.wgsl.js.map +1 -0
  58. package/dist/src/wgsl/bc-forward.wgsl.d.ts +23 -0
  59. package/dist/src/wgsl/bc-forward.wgsl.d.ts.map +1 -0
  60. package/dist/src/wgsl/bc-forward.wgsl.js +106 -0
  61. package/dist/src/wgsl/bc-forward.wgsl.js.map +1 -0
  62. package/dist/src/wgsl/bc-gather.wgsl.d.ts +9 -0
  63. package/dist/src/wgsl/bc-gather.wgsl.d.ts.map +1 -0
  64. package/dist/src/wgsl/bc-gather.wgsl.js +20 -0
  65. package/dist/src/wgsl/bc-gather.wgsl.js.map +1 -0
  66. package/dist/src/wgsl/closeness-reduce.wgsl.d.ts +4 -1
  67. package/dist/src/wgsl/closeness-reduce.wgsl.d.ts.map +1 -1
  68. package/dist/src/wgsl/closeness-reduce.wgsl.js +8 -4
  69. package/dist/src/wgsl/closeness-reduce.wgsl.js.map +1 -1
  70. package/dist/src/wgsl/closeness-sweep.wgsl.d.ts +4 -2
  71. package/dist/src/wgsl/closeness-sweep.wgsl.d.ts.map +1 -1
  72. package/dist/src/wgsl/closeness-sweep.wgsl.js +12 -2
  73. package/dist/src/wgsl/closeness-sweep.wgsl.js.map +1 -1
  74. package/dist/webgpu-graph-algorithms.js +1037 -168
  75. package/dist/webgpu-graph-algorithms.js.map +1 -1
  76. package/package.json +5 -5
  77. package/src/accelerator.ts +75 -7
  78. package/src/algorithms/betweenness.ts +739 -0
  79. package/src/algorithms/closeness.ts +124 -32
  80. package/src/constants.ts +8 -0
  81. package/src/index.ts +8 -0
  82. package/src/kernels.ts +169 -10
  83. package/src/primitives/frontier.ts +4 -0
  84. package/src/types/accelerator.ts +18 -6
  85. package/src/types/algorithms.ts +5 -0
  86. package/src/types/betweenness.ts +38 -0
  87. package/src/wgsl/bc-backward.wgsl.ts +33 -0
  88. package/src/wgsl/bc-edge-gather.wgsl.ts +35 -0
  89. package/src/wgsl/bc-finalize.wgsl.ts +46 -0
  90. package/src/wgsl/bc-forward-edge.wgsl.ts +75 -0
  91. package/src/wgsl/bc-forward.wgsl.ts +105 -0
  92. package/src/wgsl/bc-gather.wgsl.ts +19 -0
  93. package/src/wgsl/closeness-reduce.wgsl.ts +8 -4
  94. package/src/wgsl/closeness-sweep.wgsl.ts +12 -2
  95. package/dist/chunks/context-Bi6AhScG.js.map +0 -1
@@ -0,0 +1,538 @@
1
+ /**
2
+ * Betweenness and edge betweenness on the device (design 8.4 "Betweenness (A7)", 3.3 lines 811-812, 9.7): Brandes'
3
+ * algorithm as McLaughlin-Bader run it, k sources at a time.
4
+ *
5
+ * A source batch keeps four `n x k` arrays -- `depthK`, `sigmaK` (u32 shortest-path counts), `deltaK` (f32
6
+ * dependencies) and the claim log `S` -- plus `ends`, the level boundaries into the log. Every array is indexed by
7
+ * `s * n + v`, and a log entry IS that index, so one u32 names a `(vertex, source)` pair: `4 n k` bytes can never
8
+ * reach 2^32 because each array is one storage binding. The forward pass is a tagged breadth-first search: every
9
+ * level is `bc-finalize` (the boundary: `ends[level + 1] = stackTop`, `done` on an empty level) and then ONE forward
10
+ * dispatch, either `bc-forward` (block-mapped over the level's range of the log) or `bc-forward-edge` (every edge of
11
+ * the `edgeList` view for every source), both claiming, counting and appending with the same rules. Levels are
12
+ * recorded `MAX_LEVELS_PER_SUBMIT` per submit with one small readback (the counters block and the `ends` prefix), and
13
+ * the log's `ends` is known on the host when the forward phase ends, so the backward pass is planned exactly: one
14
+ * `bc-backward` dispatch per level from the deepest to depth 1, each writing `delta[s][w]` once by pulling over the
15
+ * successors; then `bc-gather` adds each vertex's k dependencies into `bc` (and `bc-edge-gather` each arc's k terms
16
+ * into `arcScores`). Nothing accumulates a float through an atomic, so the scores are bitwise reproducible.
17
+ *
18
+ * The batch size k is planned from the device limits at 16 bytes per (node, source) -- the three arrays design 4.7
19
+ * counts plus the 4-byte log entry it omits -- as `min(floor(maxStorageBufferBindingSize / 4n), floor(0.25 x
20
+ * maxBufferSize / 16n), 64)`, at least 1 (`planBatchSize`); a graph whose single source does not fit one binding is
21
+ * E_TOO_LARGE. The forward form is chosen per batch: the first batch runs `bc-forward`; a later one runs the
22
+ * edge-parallel form when the previous batch's level count -- the MAXIMUM depth over its sources, the only depth
23
+ * figure the host has, which over-estimates the median of design 8.4's rule and so errs toward the frontier form --
24
+ * is below `BC_EDGE_PARALLEL_GAMMA x log2(n)`.
25
+ *
26
+ * The host applies the CPU package's convention after the readback (`@graphty/algorithms` betweenness.ts): the vertex
27
+ * scores are halved on an undirected snapshot (the gather counts each unordered pair from both ends); the edge scores
28
+ * are folded with `foldArcs(s, perArc, "sum")` and halved the same way, because an undirected edge's two arcs carry
29
+ * the pairs that cross it in each direction. Over every source both arcs hold the same sum, but over a sample they do
30
+ * not: on the path 0-1-2 with the one source 2, arc 1->0 collects 1 and arc 0->1 collects 0, so keeping either arc
31
+ * alone would lose the pairs crossing the other way. `normalized`
32
+ * divides both by `(n - 1)(n - 2)` directed or half that undirected, when positive. A sampled run (`sources` or `k`)
33
+ * is the UNSCALED sum over the sources run, reported beside `sourcesUsed`. `endpoints: true` is refused: the CPU's
34
+ * endpoints branch (`algorithms/src/algorithms/centrality/betweenness.ts`, `predecessors.length === 0 && w !==
35
+ * source`) can never fire for a vertex on the Brandes stack, so there is no behaviour to be in parity with.
36
+ * Betweenness is breadth-first on both packages; weights are ignored. Parallel edges are distinct shortest paths
37
+ * here (each arc adds to sigma), where the CPU package refuses them or, with `allowParallelEdges`, collapses them to
38
+ * one: on a multigraph the two packages' scores differ.
39
+ */
40
+ import { foldArcs } from "@graphty/graph-format";
41
+ import { BC_BACKWARD_LEVELS_PER_SUBMIT, BC_BATCH_BUDGET_FRACTION, BC_EDGE_PARALLEL_GAMMA, BC_MAX_BATCH, MAX_LEVELS_PER_SUBMIT, } from "../constants.js";
42
+ import { WebGpuGraphError } from "../errors.js";
43
+ import { CommandBatch } from "../kernel/batch.js";
44
+ import { plan1d, planGridStride } from "../kernel/dispatch.js";
45
+ import { BC_PARAMS, FILL_PARAMS, FRONTIER_COUNTERS, kernelSpec } from "../kernels.js";
46
+ import { assertWholeCore } from "../primitives/core-shape.js";
47
+ import { W } from "../primitives/frontier.js";
48
+ import { assertDeviceComputes } from "../primitives/verify.js";
49
+ import { algorithmScope } from "./scope.js";
50
+ import { aborted, bindingOf, checkDest } from "./sssp.js";
51
+ const ALGORITHM = "betweennessCentrality";
52
+ /** Bytes one (node, source) pair holds in a batch: depthK, sigmaK, deltaK and the claim-log entry, 4 each. */
53
+ const BYTES_PER_NODE_SOURCE = 16;
54
+ /** The seed of the deterministic draw of `k` sources (any fixed value: the draw only has to repeat). */
55
+ const SAMPLE_SEED = 0x9e3779b9;
56
+ /** Params slots of the ring: a backward submit's levels plus the fills, the seed, the gathers and the per-submit forward records. */
57
+ const RING_SLOTS = BC_BACKWARD_LEVELS_PER_SUBMIT + 16;
58
+ /**
59
+ * The source batch size (design 8.4, 10.1): `min(floor(maxStorageBufferBindingSize / 4n), floor(0.25 x maxBufferSize /
60
+ * 16n), 64, remaining)`, at least 1. Each of the four `n x k` arrays is one binding of `4 n k` bytes, and the batch's
61
+ * four together stay inside a quarter of the largest buffer.
62
+ * @internal
63
+ * @param n - the vertex count (>= 1)
64
+ * @param remaining - the sources still to run (>= 1)
65
+ * @param limits - the device limits
66
+ * @returns k
67
+ * @throws E_TOO_LARGE when one source's `ends` array (`4 (n + 2)` bytes, the largest) exceeds the binding limit
68
+ */
69
+ export function planBatchSize(n, remaining, limits) {
70
+ // the largest single binding of a one-source batch is `ends`, 4 (n + 2) bytes
71
+ const needed = 4 * (n + 2);
72
+ if (needed > limits.maxStorageBufferBindingSize) {
73
+ throw new WebGpuGraphError("E_TOO_LARGE", `${ALGORITHM}: one source needs ${needed} bytes in its largest binding at n = ${n}, above maxStorageBufferBindingSize = ${limits.maxStorageBufferBindingSize}; a limit of at least ${needed} admits one source per batch`, { needed, limit: limits.maxStorageBufferBindingSize, path: "binding", algorithm: ALGORITHM });
74
+ }
75
+ const kByBinding = Math.floor(limits.maxStorageBufferBindingSize / (4 * n));
76
+ const kByBudget = Math.floor((BC_BATCH_BUDGET_FRACTION * limits.maxBufferSize) / (BYTES_PER_NODE_SOURCE * n));
77
+ return Math.max(1, Math.min(kByBinding, kByBudget, BC_MAX_BATCH, remaining));
78
+ }
79
+ /**
80
+ * `k` distinct vertices drawn by a partial Fisher-Yates shuffle over a fixed-seed mulberry32 stream: the same call
81
+ * draws the same sources every time.
82
+ * @param n - the vertex count
83
+ * @param k - how many to draw (<= n)
84
+ * @returns the sources
85
+ */
86
+ function drawSources(n, k) {
87
+ const pool = Array.from({ length: n }, (_, i) => i);
88
+ let state = SAMPLE_SEED;
89
+ for (let i = 0; i < k; i++) {
90
+ state = (state + 0x6d2b79f5) >>> 0;
91
+ let t = Math.imul(state ^ (state >>> 15), state | 1);
92
+ t = (t + Math.imul(t ^ (t >>> 7), t | 61)) ^ t;
93
+ const unit = ((t ^ (t >>> 14)) >>> 0) / 2 ** 32;
94
+ const j = i + Math.floor(unit * (n - i));
95
+ [pool[i], pool[j]] = [pool[j], pool[i]];
96
+ }
97
+ return pool.slice(0, k);
98
+ }
99
+ /**
100
+ * The E_INVALID_ARGUMENT of a bad option.
101
+ * @param argument - the option
102
+ * @param value - its value
103
+ * @param expected - what it must be
104
+ * @returns the error
105
+ */
106
+ function badArgument(argument, value, expected) {
107
+ return new WebGpuGraphError("E_INVALID_ARGUMENT", `${ALGORITHM}: ${argument} must be ${expected}`, {
108
+ argument,
109
+ value,
110
+ expected,
111
+ });
112
+ }
113
+ /**
114
+ * The sources a call runs: `sources` as given, else `k` drawn, else every vertex.
115
+ * @param options - the call's options
116
+ * @param n - the vertex count
117
+ * @returns the sources
118
+ */
119
+ function resolveSources(options, n) {
120
+ const k = options?.k;
121
+ if (k !== undefined && (!Number.isInteger(k) || k < 0 || k > n)) {
122
+ throw badArgument("k", k, `an integer in [0, ${n}]`);
123
+ }
124
+ const given = options?.sources;
125
+ if (given !== undefined) {
126
+ for (const v of given) {
127
+ if (!Number.isInteger(v) || v < 0 || v >= n) {
128
+ throw badArgument("sources", v, `node indices in [0, ${n})`);
129
+ }
130
+ }
131
+ if (k !== undefined && k !== given.length) {
132
+ throw badArgument("k", k, `absent or equal to sources.length (${given.length})`);
133
+ }
134
+ return [...given];
135
+ }
136
+ if (k !== undefined) {
137
+ return drawSources(n, k);
138
+ }
139
+ return Array.from({ length: n }, (_, i) => i);
140
+ }
141
+ /**
142
+ * Records one `fill` of `count` words.
143
+ * @param state - the run
144
+ * @param pass - the pass
145
+ * @param dst - the buffer
146
+ * @param count - the words
147
+ * @param value - the u32 written
148
+ */
149
+ function recordFill(state, pass, dst, count, value) {
150
+ const { scope, fill, ctx } = state;
151
+ const params = scope.params(FILL_PARAMS, { count, value, mode: 0, pad0: 0 });
152
+ fill.dispatch(pass, fill.bind({ dst, P: params.binding }), plan1d(count, ctx.workgroupSize, ctx.caps), [
153
+ params.offset,
154
+ ]);
155
+ }
156
+ /**
157
+ * Records a kernel with one BcParams record; the kernel is bound on its first use in the run.
158
+ * @param state - the run
159
+ * @param pass - the pass
160
+ * @param kernel - the kernel
161
+ * @param resources - its storage bindings (the same on every call for one kernel)
162
+ * @param fields - the BcParams fields
163
+ * @param items - the items the grid-stride plan covers
164
+ */
165
+ function recordBc(state, pass, kernel, resources, fields, items) {
166
+ const { scope, ctx } = state;
167
+ const plan = planGridStride(items, ctx.workgroupSize, ctx.caps);
168
+ const params = scope.params(BC_PARAMS, { ...fields, stride: plan.stride ?? 0 });
169
+ let bound = state.bound.get(kernel);
170
+ if (bound === undefined) {
171
+ bound = kernel.bind({ ...resources, P: params.binding });
172
+ state.bound.set(kernel, bound);
173
+ }
174
+ kernel.dispatch(pass, bound, items === 0 ? plan1d(1, ctx.workgroupSize, ctx.caps) : plan, [params.offset]);
175
+ }
176
+ /**
177
+ * Submits after flushing the ring and waits for the readback; aborts between submits.
178
+ * @param state - the run
179
+ * @param batch - the batch
180
+ * @param signal - the caller's signal
181
+ * @returns the readback bytes
182
+ */
183
+ async function submit(state, batch, signal) {
184
+ state.scope.flush();
185
+ const submitted = batch.submit();
186
+ const back = await submitted.readback;
187
+ state.ctx.assertReady();
188
+ if (signal?.aborted) {
189
+ throw aborted(ALGORITHM, submitted.id);
190
+ }
191
+ return back;
192
+ }
193
+ /**
194
+ * One source batch: seed, forward levels until an empty one, backward levels, the gathers.
195
+ * @param state - the run
196
+ * @param sources - the batch's sources
197
+ * @param form - the forward body
198
+ * @param levelsPerSubmit - the forward cadence
199
+ * @param tuning - the knobs
200
+ * @param signal - the caller's signal
201
+ * @returns the batch's levels and overflow flag
202
+ */
203
+ async function runBatch(state, sources, form, levelsPerSubmit, tuning, signal) {
204
+ const { ctx, n, S, ends, depthK, sigmaK, deltaK, counters } = state;
205
+ const k = sources.length;
206
+ const words = n * k;
207
+ const seeds = Uint32Array.from(sources, (v, s) => s * n + v);
208
+ ctx.device.queue.writeBuffer(S.buffer, S.offset, seeds);
209
+ // the forward phase: the first submit also clears the batch's arrays and seeds it
210
+ const forwardFields = { n, k, count: form === "edge" ? state.edgeCount : 0 };
211
+ const forwardItems = form === "edge" ? state.edgeCount : words;
212
+ let recorded = 0;
213
+ let levels = 0;
214
+ let overflow = false;
215
+ let endsWords = null;
216
+ for (let first = true; endsWords === null; first = false) {
217
+ const batch = new CommandBatch(ctx, `${ALGORITHM}/forward`);
218
+ const pass = batch.pass("forward");
219
+ if (first) {
220
+ recordFill(state, pass, depthK, words, 0xffffffff);
221
+ recordFill(state, pass, sigmaK, words, 0);
222
+ recordFill(state, pass, deltaK, words, 0);
223
+ recordBc(state, pass, state.finalize, { counters, ends, S, depthK, sigmaK }, { n, k, role: 1 }, 1);
224
+ }
225
+ for (let level = 0; level < levelsPerSubmit; level++) {
226
+ recordBc(state, pass, state.finalize, { counters, ends, S, depthK, sigmaK }, { n, k, role: 0 }, 1);
227
+ if (form === "edge" && state.forwardEdge !== null && state.edgeSrc !== null && state.edgeDst !== null) {
228
+ recordBc(state, pass, state.forwardEdge, { edgeSrc: state.edgeSrc, edgeDst: state.edgeDst, S, ends, counters, depthK, sigmaK }, forwardFields, forwardItems);
229
+ }
230
+ else {
231
+ recordBc(state, pass, state.forward, { rowPtr: state.rowPtr, colIdx: state.colIdx, S, ends, counters, depthK, sigmaK }, forwardFields, forwardItems);
232
+ }
233
+ }
234
+ recorded += levelsPerSubmit;
235
+ batch.endPass();
236
+ const endsCount = Math.min(n + 2, recorded + 1);
237
+ const countersRequest = batch.readback(counters.buffer, counters.offset, FRONTIER_COUNTERS.byteLength);
238
+ const endsRequest = batch.readback(ends.buffer, ends.offset, 4 * endsCount);
239
+ const back = await submit(state, batch, signal);
240
+ const words32 = new Uint32Array(back, countersRequest.offset, FRONTIER_COUNTERS.byteLength / 4);
241
+ if (words32[W.done] !== 0) {
242
+ levels = words32[W.level];
243
+ overflow = words32[W.sigmaOverflow] !== 0;
244
+ endsWords = new Uint32Array(back, endsRequest.offset, endsCount).slice(0, levels + 1);
245
+ }
246
+ else if (recorded > n + 2) {
247
+ // a batch claims at most n - 1 levels deep, then one level is empty
248
+ throw new WebGpuGraphError("E_VALIDATION", `${ALGORITHM}: the done flag never rose in ${recorded} levels`, {
249
+ label: ALGORITHM,
250
+ message: `the done flag never rose in ${recorded} levels`,
251
+ });
252
+ }
253
+ }
254
+ // the backward phase, planned from ends: depth levels - 1 down to 1, then the gathers
255
+ const backwardLevels = [];
256
+ for (let level = levels - 1; level >= 1; level--) {
257
+ backwardLevels.push(level);
258
+ }
259
+ let arrays = null;
260
+ for (let i = 0;; i += BC_BACKWARD_LEVELS_PER_SUBMIT) {
261
+ const chunk = backwardLevels.slice(i, i + BC_BACKWARD_LEVELS_PER_SUBMIT);
262
+ const last = i + BC_BACKWARD_LEVELS_PER_SUBMIT >= backwardLevels.length;
263
+ const batch = new CommandBatch(ctx, `${ALGORITHM}/backward`);
264
+ const pass = batch.pass("backward");
265
+ for (const level of chunk) {
266
+ const start = endsWords[level];
267
+ const count = endsWords[level + 1] - start;
268
+ recordBc(state, pass, state.backward, { rowPtr: state.rowPtr, colIdx: state.colIdx, S, depthK, sigmaK, deltaK }, { n, k, start, count }, count);
269
+ }
270
+ if (last) {
271
+ recordBc(state, pass, state.gather, { deltaK, bc: state.bc }, { n, k }, n);
272
+ if (state.edgeGather !== null && state.arcScores !== null) {
273
+ recordBc(state, pass, state.edgeGather, { rowPtr: state.rowPtr, colIdx: state.colIdx, depthK, sigmaK, deltaK, arcScores: state.arcScores }, { n, k, count: state.arcCount }, state.arcCount);
274
+ }
275
+ }
276
+ batch.endPass();
277
+ const wantArrays = last && tuning.readArrays === true;
278
+ const requests = wantArrays
279
+ ? [depthK, sigmaK, deltaK].map((b) => batch.readback(b.buffer, b.offset, 4 * words))
280
+ : [];
281
+ const back = await submit(state, batch, signal);
282
+ if (wantArrays) {
283
+ arrays = {
284
+ depthK: new Uint32Array(back, requests[0].offset, words).slice(),
285
+ sigmaK: new Uint32Array(back, requests[1].offset, words).slice(),
286
+ deltaK: new Float32Array(back, requests[2].offset, words).slice(),
287
+ };
288
+ }
289
+ if (last) {
290
+ break;
291
+ }
292
+ }
293
+ tuning.onBatch?.({
294
+ sources,
295
+ forward: form,
296
+ levels,
297
+ ends: endsWords.slice(),
298
+ sigmaOverflow: overflow,
299
+ depthK: arrays?.depthK ?? null,
300
+ sigmaK: arrays?.sigmaK ?? null,
301
+ deltaK: arrays?.deltaK ?? null,
302
+ });
303
+ return { levels, overflow };
304
+ }
305
+ /**
306
+ * The raw sums of a run over `sources` (see the file comment).
307
+ * @param ctx - the context
308
+ * @param s - the snapshot
309
+ * @param sources - the sources (non-empty, n >= 1)
310
+ * @param withEdges - also accumulate the per-arc scores
311
+ * @param tuning - the knobs
312
+ * @param options - signal / onProgress
313
+ * @returns the raw sums
314
+ */
315
+ async function runRaw(ctx, s, sources, withEdges, tuning, options) {
316
+ const n = s.nodeCount;
317
+ const pinned = tuning.forward ?? "auto";
318
+ const levelsPerSubmit = tuning.levelsPerSubmit ?? MAX_LEVELS_PER_SUBMIT;
319
+ if (!Number.isInteger(levelsPerSubmit) || levelsPerSubmit < 1 || levelsPerSubmit > MAX_LEVELS_PER_SUBMIT) {
320
+ throw badArgument("levelsPerSubmit", levelsPerSubmit, `an integer in [1, ${MAX_LEVELS_PER_SUBMIT}]`);
321
+ }
322
+ const limits = tuning.limits ?? ctx.caps.limits;
323
+ const kMax = planBatchSize(n, sources.length, limits);
324
+ const core = ctx.residency.core(s);
325
+ assertWholeCore(core, s.arcCount, ctx.caps.limits.maxStorageBufferBindingSize, ALGORITHM);
326
+ const { edgeCount } = s;
327
+ // the edge-parallel form runs only when pinned, or from the second batch on: a one-batch run never uploads the view
328
+ const mayRunEdge = pinned === "edge" || (pinned === "auto" && sources.length > kMax);
329
+ const edgeView = mayRunEdge && edgeCount > 0 ? ctx.residency.view(s, "edgeList") : null;
330
+ const scope = algorithmScope(ctx, ALGORITHM, RING_SLOTS);
331
+ try {
332
+ const arrayBytes = 4 * n * kMax;
333
+ const lease = (bytes, label) => bindingOf(scope.scratch(bytes, label), bytes);
334
+ const arcBytes = 4 * Math.max(1, s.arcCount);
335
+ const [fill, finalize, forward, backward, gather] = await Promise.all(["fill", "bc-finalize", "bc-forward", "bc-backward", "bc-gather"].map((id) => ctx.pipelines.kernel(kernelSpec(id))));
336
+ const forwardEdge = edgeView === null
337
+ ? null
338
+ : await ctx.pipelines.kernel(kernelSpec("bc-forward-edge", { UNDIRECTED: !s.directed }));
339
+ const edgeGather = withEdges ? await ctx.pipelines.kernel(kernelSpec("bc-edge-gather")) : null;
340
+ const state = {
341
+ ctx,
342
+ scope,
343
+ n,
344
+ S: lease(arrayBytes, "S"),
345
+ ends: lease(4 * (n + 2), "ends"),
346
+ depthK: lease(arrayBytes, "depthK"),
347
+ sigmaK: lease(arrayBytes, "sigmaK"),
348
+ deltaK: lease(arrayBytes, "deltaK"),
349
+ counters: lease(FRONTIER_COUNTERS.byteLength, "counters"),
350
+ bc: lease(4 * n, "bc"),
351
+ arcScores: withEdges ? lease(arcBytes, "arc-scores") : null,
352
+ rowPtr: core.rowPtr,
353
+ colIdx: core.colIdx ?? core.rowPtr,
354
+ edgeSrc: edgeView?.bindings.src ?? null,
355
+ edgeDst: edgeView?.bindings.dst ?? null,
356
+ edgeCount,
357
+ arcCount: s.arcCount,
358
+ fill,
359
+ finalize,
360
+ forward,
361
+ forwardEdge,
362
+ backward,
363
+ gather,
364
+ edgeGather,
365
+ bound: new Map(),
366
+ };
367
+ await ctx.allocator.check();
368
+ // the result accumulators start at 0
369
+ const setup = new CommandBatch(ctx, `${ALGORITHM}/setup`);
370
+ const setupPass = setup.pass("setup");
371
+ recordFill(state, setupPass, state.bc, n, 0);
372
+ if (state.arcScores !== null) {
373
+ recordFill(state, setupPass, state.arcScores, arcBytes / 4, 0);
374
+ }
375
+ setup.endPass();
376
+ await submit(state, setup, options?.signal);
377
+ let overflow = false;
378
+ let batches = 0;
379
+ let previousLevels = -1;
380
+ for (let start = 0; start < sources.length;) {
381
+ const k = planBatchSize(n, sources.length - start, limits);
382
+ let form = pinned === "edge" ? "edge" : "frontier";
383
+ if (pinned === "auto" && previousLevels >= 0) {
384
+ form = previousLevels < BC_EDGE_PARALLEL_GAMMA * Math.log2(n) ? "edge" : "frontier";
385
+ }
386
+ if (state.forwardEdge === null) {
387
+ form = "frontier"; // no edges to run edge-parallel over
388
+ }
389
+ const batch = sources.slice(start, start + k);
390
+ const outcome = await runBatch(state, batch, form, levelsPerSubmit, tuning, options?.signal);
391
+ overflow = overflow || outcome.overflow;
392
+ previousLevels = outcome.levels;
393
+ start += k;
394
+ batches += 1;
395
+ options?.onProgress?.(start, sources.length);
396
+ }
397
+ const result = new CommandBatch(ctx, `${ALGORITHM}/result`);
398
+ const vertexRequest = result.readback(state.bc.buffer, state.bc.offset, 4 * n);
399
+ const arcRequest = state.arcScores === null
400
+ ? null
401
+ : result.readback(state.arcScores.buffer, state.arcScores.offset, 4 * s.arcCount);
402
+ const back = await submit(state, result, options?.signal);
403
+ return {
404
+ vertex: new Float32Array(back, vertexRequest.offset, n).slice(),
405
+ perArc: arcRequest === null ? null : new Float32Array(back, arcRequest.offset, s.arcCount).slice(),
406
+ sourcesUsed: sources.length,
407
+ sigmaOverflow: overflow,
408
+ batches,
409
+ };
410
+ }
411
+ finally {
412
+ scope.dispose();
413
+ }
414
+ }
415
+ /**
416
+ * The CPU's normalisation factor: `(n - 1)(n - 2)` directed, half that undirected; 1 when not normalising or when the
417
+ * factor is not positive.
418
+ * @param s - the snapshot
419
+ * @param normalized - the option
420
+ * @returns the divisor
421
+ */
422
+ function normaliser(s, normalized) {
423
+ const n = s.nodeCount;
424
+ const factor = s.directed ? (n - 1) * (n - 2) : ((n - 1) * (n - 2)) / 2;
425
+ return normalized === true && factor > 0 ? factor : 1;
426
+ }
427
+ /**
428
+ * The checks every entry makes before any device work.
429
+ * @param ctx - the context
430
+ * @param options - the options
431
+ */
432
+ async function precheck(ctx, options) {
433
+ ctx.assertReady();
434
+ await assertDeviceComputes(ctx);
435
+ if (options?.endpoints === true) {
436
+ throw new WebGpuGraphError("E_UNSUPPORTED", `${ALGORITHM}: endpoints: true is not supported`, {
437
+ feature: "betweenness.endpoints",
438
+ hint: "the CPU endpoints branch in algorithms/src/algorithms/centrality/betweenness.ts (predecessors.length === 0 && w !== source) never fires, so there is no convention to match",
439
+ });
440
+ }
441
+ }
442
+ /**
443
+ * Vertex betweenness with the test knobs; `betweennessCentrality` is this with an empty tuning.
444
+ * @internal
445
+ * @param ctx - the context whose device runs the kernels
446
+ * @param s - the snapshot
447
+ * @param options - the betweenness options plus dest / signal / onProgress
448
+ * @param tuning - the knobs
449
+ * @returns the scores
450
+ */
451
+ export async function betweennessWithTuning(ctx, s, options, tuning) {
452
+ await precheck(ctx, options);
453
+ const n = s.nodeCount;
454
+ const scores = checkDest(ALGORITHM, options?.dest, n) ?? new Float32Array(n);
455
+ const sources = resolveSources(options, n);
456
+ if (options?.signal?.aborted) {
457
+ throw aborted(ALGORITHM);
458
+ }
459
+ if (n === 0 || sources.length === 0) {
460
+ scores.fill(0);
461
+ return { scores, iterations: 0, converged: true, precision: "f32", sourcesUsed: 0, sigmaOverflow: false };
462
+ }
463
+ const raw = await runRaw(ctx, s, sources, false, tuning, options);
464
+ const divisor = (s.directed ? 1 : 2) * normaliser(s, options?.normalized);
465
+ for (let v = 0; v < n; v++) {
466
+ scores[v] = raw.vertex[v] / divisor;
467
+ }
468
+ return {
469
+ scores,
470
+ iterations: raw.batches,
471
+ converged: true,
472
+ precision: "f32",
473
+ sourcesUsed: raw.sourcesUsed,
474
+ sigmaOverflow: raw.sigmaOverflow,
475
+ };
476
+ }
477
+ /**
478
+ * Edge betweenness with the test knobs; `edgeBetweennessCentrality` is this with an empty tuning.
479
+ * @internal
480
+ * @param ctx - the context whose device runs the kernels
481
+ * @param s - the snapshot
482
+ * @param options - the betweenness options plus dest (a Float32Array of edgeCount) / signal / onProgress
483
+ * @param tuning - the knobs
484
+ * @param onArcs - called with the per-arc scores before the fold (the tests' pairing check)
485
+ * @returns the per-edge scores
486
+ */
487
+ export async function edgeBetweennessWithTuning(ctx, s, options, tuning, onArcs) {
488
+ await precheck(ctx, options);
489
+ const n = s.nodeCount;
490
+ const scores = checkDest("edgeBetweennessCentrality", options?.dest, s.edgeCount) ?? new Float32Array(s.edgeCount);
491
+ const sources = resolveSources(options, n);
492
+ if (options?.signal?.aborted) {
493
+ throw aborted(ALGORITHM);
494
+ }
495
+ if (n === 0 || sources.length === 0 || s.arcCount === 0) {
496
+ scores.fill(0);
497
+ return { scores, precision: "f32", sourcesUsed: sources.length, sigmaOverflow: false };
498
+ }
499
+ const raw = await runRaw(ctx, s, sources, true, tuning, options);
500
+ const perArc = raw.perArc ?? new Float32Array(s.arcCount);
501
+ onArcs?.(perArc);
502
+ const folded = foldArcs(s, perArc, "sum");
503
+ const divisor = (s.directed ? 1 : 2) * normaliser(s, options?.normalized);
504
+ for (let e = 0; e < s.edgeCount; e++) {
505
+ scores[e] = folded[e] / divisor;
506
+ }
507
+ return { scores, precision: "f32", sourcesUsed: raw.sourcesUsed, sigmaOverflow: raw.sigmaOverflow };
508
+ }
509
+ /**
510
+ * Betweenness centrality on the device (spec 3.3 line 811, design 8.4): Brandes' algorithm, k sources per batch.
511
+ * Exact over every vertex by default; `sources` or `k` gives the SAMPLED form, whose scores are the unscaled sum over
512
+ * the sources run (`sourcesUsed` beside them; multiply by `n / sourcesUsed` for the estimator of the full sum). The
513
+ * CPU package's convention: halved on an undirected snapshot, `normalized` divides by `(n - 1)(n - 2)` directed or
514
+ * half that undirected. Weights are ignored (breadth-first on both packages). `endpoints: true` is E_UNSUPPORTED.
515
+ * `sigmaOverflow` is true when some pair has more than 2^32 shortest paths: the scores are then wrong.
516
+ * @param ctx - the context whose device runs the kernels
517
+ * @param s - the snapshot (uploaded through ctx.residency, or found there)
518
+ * @param options - `normalized`, `endpoints`, `sources`, `k`, plus dest (a Float32Array of length n) / signal / onProgress (sources done, sources total)
519
+ * @returns the f32 scores, `iterations` (the source batches run), `converged: true`, `sourcesUsed`, `sigmaOverflow`
520
+ */
521
+ export function betweennessCentrality(ctx, s, options) {
522
+ return betweennessWithTuning(ctx, s, options, {});
523
+ }
524
+ /**
525
+ * Edge betweenness centrality on the device (spec 3.3 line 812, design 8.4): the per-arc terms of the same batches,
526
+ * folded to one score per edge with `foldArcs(s, perArc, "sum")` and halved on an undirected snapshot (the two arcs
527
+ * carry the pairs crossing the edge in each direction, so their sum counts each unordered pair twice; this is the CPU
528
+ * package's number, and it holds for a sample too). `normalized`, sampling, `endpoints` and `sigmaOverflow` as in
529
+ * `betweennessCentrality`.
530
+ * @param ctx - the context whose device runs the kernels
531
+ * @param s - the snapshot (uploaded through ctx.residency, or found there)
532
+ * @param options - as `betweennessCentrality`, dest a Float32Array of length edgeCount
533
+ * @returns the f32 per-edge scores, `sourcesUsed`, `sigmaOverflow`
534
+ */
535
+ export function edgeBetweennessCentrality(ctx, s, options) {
536
+ return edgeBetweennessWithTuning(ctx, s, options, {});
537
+ }
538
+ //# sourceMappingURL=betweenness.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"betweenness.js","sourceRoot":"","sources":["../../../src/algorithms/betweenness.ts"],"names":[],"mappings":"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"}
@@ -23,6 +23,11 @@
23
23
  * seam's placeholder keys and an exact traversal has neither, so a defined value is REFUSED before any device work
24
24
  * (`E_UNSUPPORTED { option }`, the package's rule for an option it does not implement, PD-25); `undefined` is legal.
25
25
  * `iterations` reports the source batches run (the sources, on the weighted route), `converged` is always true.
26
+ * A SAMPLED run (`sources`, issue #426; undirected snapshots only) seeds its batches from the listed sources (the
27
+ * reduce's role 2 reads the list the host wrote after the per-node sums in `perSource`), and the sweep also adds each
28
+ * claim's distance into a per-node sum (`perNode`), read back with every submit and folded on the host in f64 into
29
+ * `1 / sum` per NODE, where the exact run folds per SOURCE: on an undirected graph the distance from a source to a node
30
+ * is the distance from the node to the source, which is what the CPU port's sampled closeness sums.
26
31
  *
27
32
  * Cost, stated so nobody is surprised: closeness is O(n x m) on any device -- at 1M nodes it is 31,250 batches of a
28
33
  * full multi-source traversal, minutes on the card, and no target in design 10.4 asks for less. `compact.record`
@@ -35,8 +40,8 @@
35
40
  */
36
41
  import { type GraphSnapshot } from "@graphty/graph-format";
37
42
  import { type GpuContext } from "../context.js";
38
- import { type HitsOptionsLike } from "../types/accelerator.js";
39
- import { type GpuScoresResult } from "../types/algorithms.js";
43
+ import { type ClosenessAcceleratorOptions, type HitsOptionsLike } from "../types/accelerator.js";
44
+ import { type GpuClosenessResult } from "../types/algorithms.js";
40
45
  import { type GpuRunOptions } from "../types/run.js";
41
46
  /**
42
47
  * Closeness centrality on the device (spec 3.3 line 810, design 8.4, 9.7): `scores[s] = 1 / sumDist_s` over the finite
@@ -44,10 +49,15 @@ import { type GpuRunOptions } from "../types/run.js";
44
49
  * `closenessCentrality`, unweighted by one bit-parallel multi-source search per 32 sources, weighted by one `sssp`
45
50
  * per source; `weighted` defaults to the snapshot's flag, `maxIterations` / `tolerance` are refused when defined
46
51
  * (PD-25). `iterations` is the source batches run and `converged` is always true.
52
+ *
53
+ * SAMPLED (`sources`, node indices, duplicates run twice; undirected snapshots only, E_UNSUPPORTED
54
+ * `closenessCentrality.directedSources` otherwise): the batches seed the listed sources instead of every node, and
55
+ * each node's score is `1 / sum` of its distances to the sources that reach it (itself excluded), `0` when none does:
56
+ * the sampled score of the CPU port, unscaled. `sourcesUsed` is the list's length (`n` exact).
47
57
  * @param ctx - the context whose device runs the kernels
48
58
  * @param s - the snapshot (uploaded through ctx.residency, or found there)
49
- * @param options - the seam's `HitsOptionsLike`, plus dest (a Float32Array of length n for `scores`) / signal / onProgress
50
- * @returns the scores, the batches run, `converged: true` and `precision: "f32"`
59
+ * @param options - `weighted`, `sources`, plus dest (a Float32Array of length n for `scores`) / signal / onProgress
60
+ * @returns the scores, the batches run, `converged: true`, `precision: "f32"` and `sourcesUsed`
51
61
  */
52
- export declare function closenessCentrality(ctx: GpuContext, s: GraphSnapshot, options?: HitsOptionsLike & GpuRunOptions): Promise<GpuScoresResult>;
62
+ export declare function closenessCentrality(ctx: GpuContext, s: GraphSnapshot, options?: ClosenessAcceleratorOptions & HitsOptionsLike & GpuRunOptions): Promise<GpuClosenessResult>;
53
63
  //# sourceMappingURL=closeness.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"closeness.d.ts","sourceRoot":"","sources":["../../../src/algorithms/closeness.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AAEH,OAAO,EAAY,KAAK,aAAa,EAAY,MAAM,uBAAuB,CAAC;AAG/E,OAAO,EAAE,KAAK,UAAU,EAAE,MAAM,eAAe,CAAC;AAiBhD,OAAO,EAAE,KAAK,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAC/D,OAAO,EAAE,KAAK,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAE9D,OAAO,EAAE,KAAK,aAAa,EAAE,MAAM,iBAAiB,CAAC;AA8TrD;;;;;;;;;;GAUG;AACH,wBAAgB,mBAAmB,CAC/B,GAAG,EAAE,UAAU,EACf,CAAC,EAAE,aAAa,EAChB,OAAO,CAAC,EAAE,eAAe,GAAG,aAAa,GAC1C,OAAO,CAAC,eAAe,CAAC,CAE1B"}
1
+ {"version":3,"file":"closeness.d.ts","sourceRoot":"","sources":["../../../src/algorithms/closeness.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuCG;AAEH,OAAO,EAAY,KAAK,aAAa,EAAY,MAAM,uBAAuB,CAAC;AAG/E,OAAO,EAAE,KAAK,UAAU,EAAE,MAAM,eAAe,CAAC;AAiBhD,OAAO,EAAE,KAAK,2BAA2B,EAAE,KAAK,eAAe,EAAE,MAAM,yBAAyB,CAAC;AACjG,OAAO,EAAE,KAAK,kBAAkB,EAAE,MAAM,wBAAwB,CAAC;AAEjE,OAAO,EAAE,KAAK,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAgZrD;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,mBAAmB,CAC/B,GAAG,EAAE,UAAU,EACf,CAAC,EAAE,aAAa,EAChB,OAAO,CAAC,EAAE,2BAA2B,GAAG,eAAe,GAAG,aAAa,GACxE,OAAO,CAAC,kBAAkB,CAAC,CAE7B"}