@graphty/webgpu-graph-algorithms 0.6.13 → 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.
- package/README.md +52 -52
- package/dist/browser.js +1 -1
- package/dist/chunks/{context-Bi6AhScG.js → context-oXphO3yj.js} +36 -28
- package/dist/chunks/context-oXphO3yj.js.map +1 -0
- package/dist/node.js +1 -1
- package/dist/src/accelerator.d.ts +3 -2
- package/dist/src/accelerator.d.ts.map +1 -1
- package/dist/src/accelerator.js +48 -4
- package/dist/src/accelerator.js.map +1 -1
- package/dist/src/algorithms/betweenness.d.ts +70 -0
- package/dist/src/algorithms/betweenness.d.ts.map +1 -0
- package/dist/src/algorithms/betweenness.js +538 -0
- package/dist/src/algorithms/betweenness.js.map +1 -0
- package/dist/src/algorithms/closeness.d.ts +15 -5
- package/dist/src/algorithms/closeness.d.ts.map +1 -1
- package/dist/src/algorithms/closeness.js +112 -26
- package/dist/src/algorithms/closeness.js.map +1 -1
- package/dist/src/constants.d.ts +8 -0
- package/dist/src/constants.d.ts.map +1 -1
- package/dist/src/constants.js +8 -0
- package/dist/src/constants.js.map +1 -1
- package/dist/src/index.d.ts +4 -2
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +1 -0
- package/dist/src/index.js.map +1 -1
- package/dist/src/kernels.d.ts +12 -6
- package/dist/src/kernels.d.ts.map +1 -1
- package/dist/src/kernels.js +153 -7
- package/dist/src/kernels.js.map +1 -1
- package/dist/src/primitives/frontier.d.ts +2 -0
- package/dist/src/primitives/frontier.d.ts.map +1 -1
- package/dist/src/primitives/frontier.js +2 -0
- package/dist/src/primitives/frontier.js.map +1 -1
- package/dist/src/types/accelerator.d.ts +11 -7
- package/dist/src/types/accelerator.d.ts.map +1 -1
- package/dist/src/types/algorithms.d.ts +4 -0
- package/dist/src/types/algorithms.d.ts.map +1 -1
- package/dist/src/types/betweenness.d.ts +35 -0
- package/dist/src/types/betweenness.d.ts.map +1 -0
- package/dist/src/types/betweenness.js +7 -0
- package/dist/src/types/betweenness.js.map +1 -0
- package/dist/src/wgsl/bc-backward.wgsl.d.ts +15 -0
- package/dist/src/wgsl/bc-backward.wgsl.d.ts.map +1 -0
- package/dist/src/wgsl/bc-backward.wgsl.js +34 -0
- package/dist/src/wgsl/bc-backward.wgsl.js.map +1 -0
- package/dist/src/wgsl/bc-edge-gather.wgsl.d.ts +12 -0
- package/dist/src/wgsl/bc-edge-gather.wgsl.d.ts.map +1 -0
- package/dist/src/wgsl/bc-edge-gather.wgsl.js +36 -0
- package/dist/src/wgsl/bc-edge-gather.wgsl.js.map +1 -0
- package/dist/src/wgsl/bc-finalize.wgsl.d.ts +21 -0
- package/dist/src/wgsl/bc-finalize.wgsl.d.ts.map +1 -0
- package/dist/src/wgsl/bc-finalize.wgsl.js +47 -0
- package/dist/src/wgsl/bc-finalize.wgsl.js.map +1 -0
- package/dist/src/wgsl/bc-forward-edge.wgsl.d.ts +15 -0
- package/dist/src/wgsl/bc-forward-edge.wgsl.d.ts.map +1 -0
- package/dist/src/wgsl/bc-forward-edge.wgsl.js +76 -0
- package/dist/src/wgsl/bc-forward-edge.wgsl.js.map +1 -0
- package/dist/src/wgsl/bc-forward.wgsl.d.ts +23 -0
- package/dist/src/wgsl/bc-forward.wgsl.d.ts.map +1 -0
- package/dist/src/wgsl/bc-forward.wgsl.js +106 -0
- package/dist/src/wgsl/bc-forward.wgsl.js.map +1 -0
- package/dist/src/wgsl/bc-gather.wgsl.d.ts +9 -0
- package/dist/src/wgsl/bc-gather.wgsl.d.ts.map +1 -0
- package/dist/src/wgsl/bc-gather.wgsl.js +20 -0
- package/dist/src/wgsl/bc-gather.wgsl.js.map +1 -0
- package/dist/src/wgsl/closeness-reduce.wgsl.d.ts +4 -1
- package/dist/src/wgsl/closeness-reduce.wgsl.d.ts.map +1 -1
- package/dist/src/wgsl/closeness-reduce.wgsl.js +8 -4
- package/dist/src/wgsl/closeness-reduce.wgsl.js.map +1 -1
- package/dist/src/wgsl/closeness-sweep.wgsl.d.ts +4 -2
- package/dist/src/wgsl/closeness-sweep.wgsl.d.ts.map +1 -1
- package/dist/src/wgsl/closeness-sweep.wgsl.js +12 -2
- package/dist/src/wgsl/closeness-sweep.wgsl.js.map +1 -1
- package/dist/webgpu-graph-algorithms.js +1037 -168
- package/dist/webgpu-graph-algorithms.js.map +1 -1
- package/package.json +5 -5
- package/src/accelerator.ts +75 -7
- package/src/algorithms/betweenness.ts +739 -0
- package/src/algorithms/closeness.ts +124 -32
- package/src/constants.ts +8 -0
- package/src/index.ts +8 -0
- package/src/kernels.ts +169 -10
- package/src/primitives/frontier.ts +4 -0
- package/src/types/accelerator.ts +18 -6
- package/src/types/algorithms.ts +5 -0
- package/src/types/betweenness.ts +38 -0
- package/src/wgsl/bc-backward.wgsl.ts +33 -0
- package/src/wgsl/bc-edge-gather.wgsl.ts +35 -0
- package/src/wgsl/bc-finalize.wgsl.ts +46 -0
- package/src/wgsl/bc-forward-edge.wgsl.ts +75 -0
- package/src/wgsl/bc-forward.wgsl.ts +105 -0
- package/src/wgsl/bc-gather.wgsl.ts +19 -0
- package/src/wgsl/closeness-reduce.wgsl.ts +8 -4
- package/src/wgsl/closeness-sweep.wgsl.ts +12 -2
- package/dist/chunks/context-Bi6AhScG.js.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"closeness-reduce.wgsl.js","sourceRoot":"","sources":["../../../src/wgsl/closeness-reduce.wgsl.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"closeness-reduce.wgsl.js","sourceRoot":"","sources":["../../../src/wgsl/closeness-reduce.wgsl.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,CAAC,MAAM,mBAAmB,GAAG,UAAU,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAiD7C,CAAC"}
|
|
@@ -13,8 +13,10 @@
|
|
|
13
13
|
* error), and are tallied per source in WORKGROUP memory -- one global `atomicAdd` per source per workgroup after the
|
|
14
14
|
* strip loop, never one per arc. Uniformity (spec 3.5 rule 1): the guarded loads write locals, the scan and the
|
|
15
15
|
* `workgroupUniformLoad` sit unconditionally after the guard, the strip loop is bounded by the uniform aggregate, and
|
|
16
|
-
* the flush's barrier follows it in uniform control flow.
|
|
16
|
+
* the flush's barrier follows it in uniform control flow. A sampled run (`P.perNode == 1`) also adds each claim's
|
|
17
|
+
* distance (`level + 1`, one per won bit) into the per-node sum of `x`, `perSource[128 + x]`: the distance from each
|
|
18
|
+
* of the batch's sources TO `x`, which is what a node's sampled closeness sums on an undirected graph. Body only (spec 3.5, D9); the text is normative: the
|
|
17
19
|
* sabotage rows of test/helpers/sabotage.ts are textual edits of it.
|
|
18
20
|
*/
|
|
19
|
-
export declare const closenessSweepWgsl = "\nvar<workgroup> sh: array<u32, WG>; // the block's degrees, then their inclusive scan\nvar<workgroup> rowStart: array<u32, WG>; // the first bound arc of each entry's row\nvar<workgroup> rowOf: array<u32, WG>; // the frontier vertex of each entry (the source end of its arcs)\nvar<workgroup> local: array<atomic<u32>, 32>; // this workgroup's fresh claims per source\nvar<workgroup> wcount: u32; // the frontier list's length\n\n@compute @workgroup_size(WG)\nfn closeness_sweep(@builtin(workgroup_id) wid: vec3<u32>, @builtin(local_invocation_id) lid: vec3<u32>) {\n if (lid.x == 0u) {
|
|
21
|
+
export declare const closenessSweepWgsl = "\nvar<workgroup> sh: array<u32, WG>; // the block's degrees, then their inclusive scan\nvar<workgroup> rowStart: array<u32, WG>; // the first bound arc of each entry's row\nvar<workgroup> rowOf: array<u32, WG>; // the frontier vertex of each entry (the source end of its arcs)\nvar<workgroup> local: array<atomic<u32>, 32>; // this workgroup's fresh claims per source\nvar<workgroup> wcount: u32; // the frontier list's length\nvar<workgroup> wdist: u32; // the distance of this level's claims\n\n@compute @workgroup_size(WG)\nfn closeness_sweep(@builtin(workgroup_id) wid: vec3<u32>, @builtin(local_invocation_id) lid: vec3<u32>) {\n if (lid.x == 0u) {\n wcount = atomicLoad(&counters[0]); // the frontier list's length (compact's total)\n wdist = atomicLoad(&counters[11]) + 1u; // the level word: this level claims at level + 1\n }\n let count = workgroupUniformLoad(&wcount); // uniform: the block loop below holds barriers\n let dist = workgroupUniformLoad(&wdist);\n let nextBase = select(2u * P.bitsBase, P.bitsBase, P.mode == 1u); // the region that is next this level\n let frontierBase = 3u * P.bitsBase - nextBase; // the other one: the region that is the frontier\n for (var b0 = group_id(wid) * WG; b0 < count; b0 = b0 + P.stride) { // grid-stride over blocks of WG entries\n let i = b0 + lid.x; // this lane's frontier entry\n var deg = 0u;\n var start = 0u;\n var u = 0u;\n if (i < count) { // guarded loads into locals (3.5 rule 1)\n u = frontierList[i];\n let lo = max(rowPtr[u], P.arcBase);\n let hi = min(rowPtr[u + 1u], P.arcEnd);\n start = lo;\n deg = select(0u, hi - lo, hi > lo);\n }\n if (lid.x < 32u) { atomicStore(&local[lid.x], 0u); } // zeroed before the strip loop (WebGPU zero-initialises workgroup memory; said anyway)\n sh[lid.x] = deg;\n rowStart[lid.x] = start;\n rowOf[lid.x] = u;\n workgroupBarrier();\n for (var s = 1u; s < WG; s = s * 2u) { // Hillis-Steele inclusive scan of the degrees (bfs-contract's, inlined)\n var t = 0u;\n if (lid.x >= s) { t = sh[lid.x - s]; }\n workgroupBarrier();\n sh[lid.x] = sh[lid.x] + t;\n workgroupBarrier();\n }\n let aggregate = workgroupUniformLoad(&sh[WG - 1u]); // uniform; includes a barrier\n for (var p = lid.x; p < aggregate; p = p + WG) { // strip [0, aggregate): lane j takes j, j + WG, ...\n var lo = 0u; // upper_bound: the first k with sh[k] > p owns arc p\n var hi = WG;\n loop {\n if (lo >= hi) { break; }\n let mid = (lo + hi) / 2u;\n if (sh[mid] > p) { hi = mid; } else { lo = mid + 1u; }\n }\n let k = lo;\n var exclusive = 0u;\n if (k > 0u) { exclusive = sh[k - 1u]; }\n let arc = rowStart[k] + (p - exclusive);\n let x = colIdx[arc - P.arcBase];\n let mask = atomicLoad(&bits[frontierBase + rowOf[k]]) & ~atomicLoad(&bits[x]); // the sources at u that have not reached x\n if (mask != 0u) {\n let old = atomicOr(&bits[x], mask); // visited: the claim, one read-modify-write\n let fresh = mask & ~old; // the sources whose claim this lane won\n if (fresh != 0u) {\n atomicOr(&bits[nextBase + x], fresh);\n atomicStore(&bits[3u * P.bitsBase + x], 1u); // flags: x is in the next frontier list (compact reads it)\n if (P.perNode == 1u) { // a sampled run: x's distance to each source won\n atomicAdd(&perSource[128u + x], countOneBits(fresh) * dist);\n }\n var b = fresh;\n loop { // one tally per set bit of fresh\n if (b == 0u) { break; }\n let s = firstTrailingBit(b);\n atomicAdd(&local[s], 1u);\n b = b & (b - 1u);\n }\n }\n }\n }\n workgroupBarrier(); // uniform: the loop's bound is the uniform aggregate\n if (lid.x < 32u) { // ONE global atomic per source per workgroup\n let c = atomicLoad(&local[lid.x]);\n if (c != 0u) { atomicAdd(&perSource[lid.x], c); } // newCount[s]\n }\n workgroupBarrier(); // sh, rowStart, rowOf and local are reused by the next block\n }\n}\n";
|
|
20
22
|
//# sourceMappingURL=closeness-sweep.wgsl.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"closeness-sweep.wgsl.d.ts","sourceRoot":"","sources":["../../../src/wgsl/closeness-sweep.wgsl.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"closeness-sweep.wgsl.d.ts","sourceRoot":"","sources":["../../../src/wgsl/closeness-sweep.wgsl.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AACH,eAAO,MAAM,kBAAkB,inKAoF9B,CAAC"}
|
|
@@ -13,7 +13,9 @@
|
|
|
13
13
|
* error), and are tallied per source in WORKGROUP memory -- one global `atomicAdd` per source per workgroup after the
|
|
14
14
|
* strip loop, never one per arc. Uniformity (spec 3.5 rule 1): the guarded loads write locals, the scan and the
|
|
15
15
|
* `workgroupUniformLoad` sit unconditionally after the guard, the strip loop is bounded by the uniform aggregate, and
|
|
16
|
-
* the flush's barrier follows it in uniform control flow.
|
|
16
|
+
* the flush's barrier follows it in uniform control flow. A sampled run (`P.perNode == 1`) also adds each claim's
|
|
17
|
+
* distance (`level + 1`, one per won bit) into the per-node sum of `x`, `perSource[128 + x]`: the distance from each
|
|
18
|
+
* of the batch's sources TO `x`, which is what a node's sampled closeness sums on an undirected graph. Body only (spec 3.5, D9); the text is normative: the
|
|
17
19
|
* sabotage rows of test/helpers/sabotage.ts are textual edits of it.
|
|
18
20
|
*/
|
|
19
21
|
export const closenessSweepWgsl = /* wgsl */ `
|
|
@@ -22,11 +24,16 @@ var<workgroup> rowStart: array<u32, WG>; // the first bound arc of each
|
|
|
22
24
|
var<workgroup> rowOf: array<u32, WG>; // the frontier vertex of each entry (the source end of its arcs)
|
|
23
25
|
var<workgroup> local: array<atomic<u32>, 32>; // this workgroup's fresh claims per source
|
|
24
26
|
var<workgroup> wcount: u32; // the frontier list's length
|
|
27
|
+
var<workgroup> wdist: u32; // the distance of this level's claims
|
|
25
28
|
|
|
26
29
|
@compute @workgroup_size(WG)
|
|
27
30
|
fn closeness_sweep(@builtin(workgroup_id) wid: vec3<u32>, @builtin(local_invocation_id) lid: vec3<u32>) {
|
|
28
|
-
if (lid.x == 0u) {
|
|
31
|
+
if (lid.x == 0u) {
|
|
32
|
+
wcount = atomicLoad(&counters[0]); // the frontier list's length (compact's total)
|
|
33
|
+
wdist = atomicLoad(&counters[11]) + 1u; // the level word: this level claims at level + 1
|
|
34
|
+
}
|
|
29
35
|
let count = workgroupUniformLoad(&wcount); // uniform: the block loop below holds barriers
|
|
36
|
+
let dist = workgroupUniformLoad(&wdist);
|
|
30
37
|
let nextBase = select(2u * P.bitsBase, P.bitsBase, P.mode == 1u); // the region that is next this level
|
|
31
38
|
let frontierBase = 3u * P.bitsBase - nextBase; // the other one: the region that is the frontier
|
|
32
39
|
for (var b0 = group_id(wid) * WG; b0 < count; b0 = b0 + P.stride) { // grid-stride over blocks of WG entries
|
|
@@ -74,6 +81,9 @@ fn closeness_sweep(@builtin(workgroup_id) wid: vec3<u32>, @builtin(local_invocat
|
|
|
74
81
|
if (fresh != 0u) {
|
|
75
82
|
atomicOr(&bits[nextBase + x], fresh);
|
|
76
83
|
atomicStore(&bits[3u * P.bitsBase + x], 1u); // flags: x is in the next frontier list (compact reads it)
|
|
84
|
+
if (P.perNode == 1u) { // a sampled run: x's distance to each source won
|
|
85
|
+
atomicAdd(&perSource[128u + x], countOneBits(fresh) * dist);
|
|
86
|
+
}
|
|
77
87
|
var b = fresh;
|
|
78
88
|
loop { // one tally per set bit of fresh
|
|
79
89
|
if (b == 0u) { break; }
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"closeness-sweep.wgsl.js","sourceRoot":"","sources":["../../../src/wgsl/closeness-sweep.wgsl.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"closeness-sweep.wgsl.js","sourceRoot":"","sources":["../../../src/wgsl/closeness-sweep.wgsl.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAAG,UAAU,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAoF5C,CAAC"}
|