@graphty/webgpu-graph-algorithms 0.6.24 → 0.6.25
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/LICENSE +1 -1
- package/dist/browser.js +1 -1
- package/dist/chunks/{context-B40Z6lV_.js → context-BZY6SMsM.js} +41 -35
- package/dist/chunks/context-BZY6SMsM.js.map +1 -0
- package/dist/node.js +1 -1
- package/dist/src/algorithms/betweenness.d.ts +24 -9
- package/dist/src/algorithms/betweenness.d.ts.map +1 -1
- package/dist/src/algorithms/betweenness.js +105 -39
- package/dist/src/algorithms/betweenness.js.map +1 -1
- package/dist/src/constants.d.ts +11 -0
- package/dist/src/constants.d.ts.map +1 -1
- package/dist/src/constants.js +11 -0
- package/dist/src/constants.js.map +1 -1
- package/dist/src/kernel/prelude.d.ts.map +1 -1
- package/dist/src/kernel/prelude.js +4 -1
- package/dist/src/kernel/prelude.js.map +1 -1
- package/dist/src/kernels.d.ts +4 -4
- package/dist/src/kernels.d.ts.map +1 -1
- package/dist/src/kernels.js +43 -13
- package/dist/src/kernels.js.map +1 -1
- package/dist/src/types/betweenness.d.ts +5 -2
- package/dist/src/types/betweenness.d.ts.map +1 -1
- package/dist/src/wgsl/bc-backward.wgsl.d.ts +5 -2
- package/dist/src/wgsl/bc-backward.wgsl.d.ts.map +1 -1
- package/dist/src/wgsl/bc-backward.wgsl.js +12 -3
- package/dist/src/wgsl/bc-backward.wgsl.js.map +1 -1
- package/dist/src/wgsl/bc-count.wgsl.d.ts +22 -0
- package/dist/src/wgsl/bc-count.wgsl.d.ts.map +1 -0
- package/dist/src/wgsl/bc-count.wgsl.js +46 -0
- package/dist/src/wgsl/bc-count.wgsl.js.map +1 -0
- package/dist/src/wgsl/bc-edge-gather.wgsl.d.ts +3 -2
- package/dist/src/wgsl/bc-edge-gather.wgsl.d.ts.map +1 -1
- package/dist/src/wgsl/bc-edge-gather.wgsl.js +10 -2
- package/dist/src/wgsl/bc-edge-gather.wgsl.js.map +1 -1
- package/dist/src/wgsl/bc-finalize.wgsl.d.ts +4 -3
- package/dist/src/wgsl/bc-finalize.wgsl.d.ts.map +1 -1
- package/dist/src/wgsl/bc-finalize.wgsl.js +5 -3
- package/dist/src/wgsl/bc-finalize.wgsl.js.map +1 -1
- package/dist/src/wgsl/bc-forward-edge.wgsl.d.ts +2 -2
- package/dist/src/wgsl/bc-forward-edge.wgsl.js +2 -2
- package/dist/src/wgsl/bc-forward.wgsl.d.ts +4 -2
- package/dist/src/wgsl/bc-forward.wgsl.d.ts.map +1 -1
- package/dist/src/wgsl/bc-forward.wgsl.js +4 -2
- package/dist/src/wgsl/bc-forward.wgsl.js.map +1 -1
- package/dist/webgpu-graph-algorithms.js +171 -47
- package/dist/webgpu-graph-algorithms.js.map +1 -1
- package/package.json +3 -3
- package/src/algorithms/betweenness.ts +155 -48
- package/src/constants.ts +11 -0
- package/src/kernel/prelude.ts +4 -0
- package/src/kernels.ts +45 -13
- package/src/types/betweenness.ts +5 -2
- package/src/wgsl/bc-backward.wgsl.ts +12 -3
- package/src/wgsl/bc-count.wgsl.ts +45 -0
- package/src/wgsl/bc-edge-gather.wgsl.ts +10 -2
- package/src/wgsl/bc-finalize.wgsl.ts +5 -3
- package/src/wgsl/bc-forward-edge.wgsl.ts +2 -2
- package/src/wgsl/bc-forward.wgsl.ts +4 -2
- package/dist/chunks/context-B40Z6lV_.js.map +0 -1
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { W as WebGpuGraphError, U as UNIFORM_SLOT_BYTES, B as BufferUsage, M as MAX_WORKGROUPS_PER_DIM, a as WGSL_RESERVED_WORDS, S as STATE_HEADER_BYTES, d as deviceLostError, i as isWebGpuGraphError, b as U32_MAX$2, c as MAX_LEVELS_PER_SUBMIT, R as RADIX_BINS, F as FUSED_FRONTIER_MAX, e as BEAMER_BETA, f as SSSP_DELTA_FACTOR, g as F32_INF_BITS, h as BC_EDGE_PARALLEL_GAMMA, j as BC_BATCH_BUDGET_FRACTION, k as BC_MAX_BATCH, l as BC_BACKWARD_LEVELS_PER_SUBMIT, A as APSP_MAX_DISPATCHES_PER_SUBMIT,
|
|
2
|
-
import {
|
|
1
|
+
import { W as WebGpuGraphError, U as UNIFORM_SLOT_BYTES, B as BufferUsage, M as MAX_WORKGROUPS_PER_DIM, a as WGSL_RESERVED_WORDS, S as STATE_HEADER_BYTES, d as deviceLostError, i as isWebGpuGraphError, b as U32_MAX$2, c as MAX_LEVELS_PER_SUBMIT, R as RADIX_BINS, F as FUSED_FRONTIER_MAX, e as BEAMER_BETA, f as SSSP_DELTA_FACTOR, g as F32_INF_BITS, h as BC_EDGE_PARALLEL_GAMMA, j as BC_BATCH_BUDGET_FRACTION, k as BC_MAX_BATCH, l as BC_BACKWARD_LEVELS_PER_SUBMIT, m as BC_COUNT_MAX_GROUPS, A as APSP_MAX_DISPATCHES_PER_SUBMIT, n as APSP_TILE, o as GROUP_ROW_THREAD_MAX, p as GROUP_ROW_THREAD_LIMIT, q as GROUP_HASH_LOAD_FACTOR, P as PARALLEL_MERGE_LIMIT, L as LABEL_PROP_PASSES_PER_SUBMIT, r as BORUVKA_ROUNDS_PER_SUBMIT, s as GRID_COARSEST_SIDE, t as GRID_MIN_SIDE, u as GRID_SORT_BITS, v as FA2_DEFAULTS, w as MAX_ITERATIONS_PER_STEP, x as MAX_1D_ITEMS, y as hasErrorCode, z as FA2_FLAG_FIRST, C as PARTIAL_BYTES, E as EXACT_TILES_PER_PASS, I as INDIRECT_ARGS_STRIDE, D as GRID_HUB_CELL, H as LAYOUT_TUNING_DEFAULTS, J as EXACT_MAX_NODES, K as SETTLE_FLOOR_UNBOUNDED, T as TRACE_RECORD_BYTES, N as GRID_BBOX_MARGIN, O as GRID_EXTENT_FLOOR, Q as FR_ADAPTIVE_MAX_ITERATIONS, V as FR_START_TEMPERATURE, X as FA2_FLAG_ADAPTIVE, Y as SETTLE_FLOOR_FRACTION, Z as FR_REHEAT_FRACTION, _ as FR_DEFAULTS, $ as SE_DEFAULTS, a0 as SETTLE_FLOOR_REFERENCE_NODES, a1 as SE_SCALE_REFERENCE_NODES } from "./chunks/context-BZY6SMsM.js";
|
|
2
|
+
import { a2, G, a3, a4, a5, a6 } from "./chunks/context-BZY6SMsM.js";
|
|
3
3
|
import { renumberPartition, INVALID_INDEX, foldArcs, makeMask, maskTest, expandEdges, fromEdgeArrays } from "@graphty/graph-format";
|
|
4
4
|
class UniformRing {
|
|
5
5
|
/**
|
|
@@ -722,6 +722,11 @@ fn apsp_init(@builtin(workgroup_id) wid: vec3<u32>, @builtin(local_invocation_id
|
|
|
722
722
|
const bcBackwardWgsl = (
|
|
723
723
|
/* wgsl */
|
|
724
724
|
`
|
|
725
|
+
fn sigma_of(word: u32) -> f32 { // a stored count: u32, or f32 bits when SCALED
|
|
726
|
+
if (SCALED) { return bitcast<f32>(word); }
|
|
727
|
+
return f32(word);
|
|
728
|
+
}
|
|
729
|
+
|
|
725
730
|
@compute @workgroup_size(WG)
|
|
726
731
|
fn bc_backward(@builtin(workgroup_id) wid: vec3<u32>, @builtin(local_invocation_id) lid: vec3<u32>) {
|
|
727
732
|
for (var i = linear_id(wid, lid.x); i < P.count; i = i + P.stride) {
|
|
@@ -729,12 +734,13 @@ fn bc_backward(@builtin(workgroup_id) wid: vec3<u32>, @builtin(local_invocation_
|
|
|
729
734
|
let w = t % P.n;
|
|
730
735
|
let base = t - w; // s * n
|
|
731
736
|
let succ = depthK[t] + 1u;
|
|
732
|
-
let sw =
|
|
737
|
+
let sw = sigma_of(sigmaK[t]);
|
|
738
|
+
let shift = select(0i, sigma_shift(levelMax[depthK[t]]), SCALED); // the scale step to the successors' depth
|
|
733
739
|
var acc = 0.0;
|
|
734
740
|
for (var a = rowPtr[w]; a < rowPtr[w + 1u]; a = a + 1u) {
|
|
735
741
|
let v = base + colIdx[a];
|
|
736
742
|
if (depthK[v] == succ) { // v is a successor of w for source s
|
|
737
|
-
acc = acc + (sw /
|
|
743
|
+
acc = acc + ldexp(sw / sigma_of(sigmaK[v]), -shift) * (1.0 + deltaK[v]);
|
|
738
744
|
}
|
|
739
745
|
}
|
|
740
746
|
deltaK[t] = acc; // written once per (w, s)
|
|
@@ -742,9 +748,42 @@ fn bc_backward(@builtin(workgroup_id) wid: vec3<u32>, @builtin(local_invocation_
|
|
|
742
748
|
}
|
|
743
749
|
`
|
|
744
750
|
);
|
|
751
|
+
const bcCountWgsl = (
|
|
752
|
+
/* wgsl */
|
|
753
|
+
`
|
|
754
|
+
@compute @workgroup_size(WG)
|
|
755
|
+
fn bc_count(@builtin(workgroup_id) wid: vec3<u32>, @builtin(local_invocation_id) lid: vec3<u32>) {
|
|
756
|
+
let level = atomicLoad(&counters[11]);
|
|
757
|
+
let start = ends[level + 1u]; // the boundary closed the claim-from level here
|
|
758
|
+
let count = atomicLoad(&counters[26]) - start; // stackTop: what the forward dispatch appended
|
|
759
|
+
let shift = sigma_shift(atomicLoad(&levelMax[level]));
|
|
760
|
+
for (var i = linear_id(wid, lid.x); i < count; i = i + P.stride) {
|
|
761
|
+
let t = S[start + i]; // s * n + x, at depth level + 1
|
|
762
|
+
let x = t % P.n;
|
|
763
|
+
let base = t - x; // s * n
|
|
764
|
+
var acc = 0.0;
|
|
765
|
+
for (var a = rowPtr[x]; a < rowPtr[x + 1u]; a = a + 1u) { // the in-arcs (v, x)
|
|
766
|
+
let v = base + colIdx[a];
|
|
767
|
+
if (depthK[v] == level) { acc = acc + bitcast<f32>(sigmaK[v]); } // every predecessor's paths, CSR order
|
|
768
|
+
}
|
|
769
|
+
let sigma = ldexp(acc, -shift);
|
|
770
|
+
let bits = bitcast<u32>(sigma);
|
|
771
|
+
sigmaK[t] = bits;
|
|
772
|
+
let exponent = (bits >> 23u) & 0xffu;
|
|
773
|
+
if (exponent == 0u || exponent == 0xffu) { atomicOr(&counters[27], 1u); } // out of f32's normal range
|
|
774
|
+
atomicMax(&levelMax[level + 1u], bits);
|
|
775
|
+
}
|
|
776
|
+
}
|
|
777
|
+
`
|
|
778
|
+
);
|
|
745
779
|
const bcEdgeGatherWgsl = (
|
|
746
780
|
/* wgsl */
|
|
747
781
|
`
|
|
782
|
+
fn sigma_of(word: u32) -> f32 { // a stored count: u32, or f32 bits when SCALED
|
|
783
|
+
if (SCALED) { return bitcast<f32>(word); }
|
|
784
|
+
return f32(word);
|
|
785
|
+
}
|
|
786
|
+
|
|
748
787
|
@compute @workgroup_size(WG)
|
|
749
788
|
fn bc_edge_gather(@builtin(workgroup_id) wid: vec3<u32>, @builtin(local_invocation_id) lid: vec3<u32>) {
|
|
750
789
|
for (var a = linear_id(wid, lid.x); a < P.count; a = a + P.stride) {
|
|
@@ -762,7 +801,9 @@ fn bc_edge_gather(@builtin(workgroup_id) wid: vec3<u32>, @builtin(local_invocati
|
|
|
762
801
|
let base = s * P.n;
|
|
763
802
|
let dw = depthK[base + w];
|
|
764
803
|
if (dw != INVALID_INDEX && depthK[base + nbr] == dw + 1u) { // (w, nbr) is on a shortest path from s
|
|
765
|
-
|
|
804
|
+
let shift = select(0i, sigma_shift(levelMax[dw]), SCALED);
|
|
805
|
+
let ratio = ldexp(sigma_of(sigmaK[base + w]) / sigma_of(sigmaK[base + nbr]), -shift);
|
|
806
|
+
acc = acc + ratio * (1.0 + deltaK[base + nbr]);
|
|
766
807
|
}
|
|
767
808
|
}
|
|
768
809
|
arcScores[a] = acc;
|
|
@@ -780,8 +821,9 @@ fn bc_finalize(@builtin(local_invocation_id) lid: vec3<u32>) {
|
|
|
780
821
|
for (var i = 0u; i < P.k; i = i + 1u) {
|
|
781
822
|
let t = S[i];
|
|
782
823
|
depthK[t] = 0u; // the source is at depth 0
|
|
783
|
-
sigmaK[t] = 1u;
|
|
824
|
+
sigmaK[t] = select(1u, bitcast<u32>(1.0), SCALED); // with one shortest path, itself (f32 bits when SCALED)
|
|
784
825
|
}
|
|
826
|
+
levelMax[0] = bitcast<u32>(1.0); // the largest count at depth 0
|
|
785
827
|
ends[0] = 0u;
|
|
786
828
|
atomicStore(&counters[26], P.k); // stackTop: the seeds are the log's first k entries
|
|
787
829
|
atomicStore(&counters[27], 0u); // sigmaOverflow
|
|
@@ -865,7 +907,7 @@ fn bc_forward(@builtin(workgroup_id) wid: vec3<u32>, @builtin(local_invocation_i
|
|
|
865
907
|
if (atomicLoad(&depthK[x]) == INVALID_INDEX) { // the pre-check of design 16.1
|
|
866
908
|
won = atomicMin(&depthK[x], next) == INVALID_INDEX; // the claim: the one winner appends
|
|
867
909
|
}
|
|
868
|
-
if (atomicLoad(&depthK[x]) == next) {
|
|
910
|
+
if (!SCALED && atomicLoad(&depthK[x]) == next) { // the count: EVERY arc on a shortest path adds
|
|
869
911
|
let add = atomicLoad(&sigmaK[origin]);
|
|
870
912
|
let old = atomicAdd(&sigmaK[x], add);
|
|
871
913
|
if (old + add < old) { atomicOr(&counters[27], 1u); } // the u32 wrap, reported
|
|
@@ -900,7 +942,7 @@ fn claim(x: u32, next: u32) -> bool {
|
|
|
900
942
|
}
|
|
901
943
|
|
|
902
944
|
fn count_paths(origin: u32, x: u32, next: u32) {
|
|
903
|
-
if (atomicLoad(&depthK[x]) == next) {
|
|
945
|
+
if (!SCALED && atomicLoad(&depthK[x]) == next) { // every arc on a shortest path adds
|
|
904
946
|
let add = atomicLoad(&sigmaK[origin]);
|
|
905
947
|
let old = atomicAdd(&sigmaK[x], add);
|
|
906
948
|
if (old + add < old) { atomicOr(&counters[27], 1u); } // the u32 wrap, reported
|
|
@@ -4381,9 +4423,10 @@ const BC_FINALIZE = {
|
|
|
4381
4423
|
decl(1, 2, "S", "storage-ro", "array<u32>"),
|
|
4382
4424
|
decl(1, 3, "depthK", "storage", "array<u32>"),
|
|
4383
4425
|
decl(1, 4, "sigmaK", "storage", "array<u32>"),
|
|
4426
|
+
decl(1, 5, "levelMax", "storage", "array<u32>"),
|
|
4384
4427
|
decl(2, 0, "P", "uniform", "BcParams")
|
|
4385
4428
|
],
|
|
4386
|
-
overrideDecls: [],
|
|
4429
|
+
overrideDecls: [{ name: "SCALED", type: "bool", default: false }],
|
|
4387
4430
|
uniforms: [BC_PARAMS],
|
|
4388
4431
|
needs: [],
|
|
4389
4432
|
snippetSlots: [],
|
|
@@ -4403,7 +4446,7 @@ const BC_FORWARD = {
|
|
|
4403
4446
|
decl(1, 6, "sigmaK", "storage", "array<atomic<u32>>"),
|
|
4404
4447
|
decl(2, 0, "P", "uniform", "BcParams")
|
|
4405
4448
|
],
|
|
4406
|
-
overrideDecls: [],
|
|
4449
|
+
overrideDecls: [{ name: "SCALED", type: "bool", default: false }],
|
|
4407
4450
|
uniforms: [BC_PARAMS],
|
|
4408
4451
|
needs: [],
|
|
4409
4452
|
snippetSlots: [],
|
|
@@ -4420,9 +4463,10 @@ const BC_BACKWARD = {
|
|
|
4420
4463
|
decl(1, 3, "depthK", "storage-ro", "array<u32>"),
|
|
4421
4464
|
decl(1, 4, "sigmaK", "storage-ro", "array<u32>"),
|
|
4422
4465
|
decl(1, 5, "deltaK", "storage", "array<f32>"),
|
|
4466
|
+
decl(1, 6, "levelMax", "storage-ro", "array<u32>"),
|
|
4423
4467
|
decl(2, 0, "P", "uniform", "BcParams")
|
|
4424
4468
|
],
|
|
4425
|
-
overrideDecls: [],
|
|
4469
|
+
overrideDecls: [{ name: "SCALED", type: "bool", default: false }],
|
|
4426
4470
|
uniforms: [BC_PARAMS],
|
|
4427
4471
|
needs: [],
|
|
4428
4472
|
snippetSlots: [],
|
|
@@ -4454,9 +4498,10 @@ const BC_EDGE_GATHER = {
|
|
|
4454
4498
|
decl(1, 3, "sigmaK", "storage-ro", "array<u32>"),
|
|
4455
4499
|
decl(1, 4, "deltaK", "storage-ro", "array<f32>"),
|
|
4456
4500
|
decl(1, 5, "arcScores", "storage", "array<f32>"),
|
|
4501
|
+
decl(1, 6, "levelMax", "storage-ro", "array<u32>"),
|
|
4457
4502
|
decl(2, 0, "P", "uniform", "BcParams")
|
|
4458
4503
|
],
|
|
4459
|
-
overrideDecls: [],
|
|
4504
|
+
overrideDecls: [{ name: "SCALED", type: "bool", default: false }],
|
|
4460
4505
|
uniforms: [BC_PARAMS],
|
|
4461
4506
|
needs: [],
|
|
4462
4507
|
snippetSlots: [],
|
|
@@ -4476,7 +4521,31 @@ const BC_FORWARD_EDGE = {
|
|
|
4476
4521
|
decl(1, 6, "sigmaK", "storage", "array<atomic<u32>>"),
|
|
4477
4522
|
decl(2, 0, "P", "uniform", "BcParams")
|
|
4478
4523
|
],
|
|
4479
|
-
overrideDecls: [
|
|
4524
|
+
overrideDecls: [
|
|
4525
|
+
{ name: "UNDIRECTED", type: "bool", default: false },
|
|
4526
|
+
{ name: "SCALED", type: "bool", default: false }
|
|
4527
|
+
],
|
|
4528
|
+
uniforms: [BC_PARAMS],
|
|
4529
|
+
needs: [],
|
|
4530
|
+
snippetSlots: [],
|
|
4531
|
+
phase: "P9"
|
|
4532
|
+
};
|
|
4533
|
+
const BC_COUNT = {
|
|
4534
|
+
id: "bc-count",
|
|
4535
|
+
body: bcCountWgsl,
|
|
4536
|
+
entryPoint: "bc_count",
|
|
4537
|
+
bindings: [
|
|
4538
|
+
decl(1, 0, "rowPtr", "storage-ro", "array<u32>"),
|
|
4539
|
+
decl(1, 1, "colIdx", "storage-ro", "array<u32>"),
|
|
4540
|
+
decl(1, 2, "S", "storage-ro", "array<u32>"),
|
|
4541
|
+
decl(1, 3, "ends", "storage-ro", "array<u32>"),
|
|
4542
|
+
decl(1, 4, "counters", "storage", "array<atomic<u32>>"),
|
|
4543
|
+
decl(1, 5, "depthK", "storage-ro", "array<u32>"),
|
|
4544
|
+
decl(1, 6, "sigmaK", "storage", "array<u32>"),
|
|
4545
|
+
decl(1, 7, "levelMax", "storage", "array<atomic<u32>>"),
|
|
4546
|
+
decl(2, 0, "P", "uniform", "BcParams")
|
|
4547
|
+
],
|
|
4548
|
+
overrideDecls: [],
|
|
4480
4549
|
uniforms: [BC_PARAMS],
|
|
4481
4550
|
needs: [],
|
|
4482
4551
|
snippetSlots: [],
|
|
@@ -4733,6 +4802,7 @@ const REGISTRY = Object.freeze({
|
|
|
4733
4802
|
"bc-forward": BC_FORWARD,
|
|
4734
4803
|
"bc-backward": BC_BACKWARD,
|
|
4735
4804
|
"bc-gather": BC_GATHER,
|
|
4805
|
+
"bc-count": BC_COUNT,
|
|
4736
4806
|
"bc-edge-gather": BC_EDGE_GATHER,
|
|
4737
4807
|
"bc-forward-edge": BC_FORWARD_EDGE,
|
|
4738
4808
|
"apsp-init": APSP_INIT,
|
|
@@ -8300,7 +8370,7 @@ async function bellmanFord(ctx, s, source, options) {
|
|
|
8300
8370
|
const ALGORITHM$5 = "betweennessCentrality";
|
|
8301
8371
|
const BYTES_PER_NODE_SOURCE = 16;
|
|
8302
8372
|
const SAMPLE_SEED = 2654435769;
|
|
8303
|
-
const RING_SLOTS$4 = BC_BACKWARD_LEVELS_PER_SUBMIT + 16;
|
|
8373
|
+
const RING_SLOTS$4 = Math.max(3 * MAX_LEVELS_PER_SUBMIT, BC_BACKWARD_LEVELS_PER_SUBMIT) + 16;
|
|
8304
8374
|
function planBatchSize(n, remaining, limits) {
|
|
8305
8375
|
const needed = 4 * (n + 2);
|
|
8306
8376
|
if (needed > limits.maxStorageBufferBindingSize) {
|
|
@@ -8356,6 +8426,26 @@ function resolveSources(options, n) {
|
|
|
8356
8426
|
}
|
|
8357
8427
|
return Array.from({ length: n }, (_, i) => i);
|
|
8358
8428
|
}
|
|
8429
|
+
async function modeKernels(ctx, s, core, withForwardEdge, withEdges, scaled) {
|
|
8430
|
+
const SCALED = scaled;
|
|
8431
|
+
const [finalize, forward, backward] = await Promise.all(
|
|
8432
|
+
["bc-finalize", "bc-forward", "bc-backward"].map(
|
|
8433
|
+
(id) => ctx.pipelines.kernel(kernelSpec(id, { SCALED }))
|
|
8434
|
+
)
|
|
8435
|
+
);
|
|
8436
|
+
const forwardEdge = withForwardEdge ? await ctx.pipelines.kernel(kernelSpec("bc-forward-edge", { UNDIRECTED: !s.directed, SCALED })) : null;
|
|
8437
|
+
const edgeGather = withEdges ? await ctx.pipelines.kernel(kernelSpec("bc-edge-gather", { SCALED })) : null;
|
|
8438
|
+
let count = null;
|
|
8439
|
+
if (scaled) {
|
|
8440
|
+
const reverse = s.directed ? reverseOf(ctx, s) : core;
|
|
8441
|
+
count = {
|
|
8442
|
+
kernel: await ctx.pipelines.kernel(kernelSpec("bc-count")),
|
|
8443
|
+
rowPtr: reverse.rowPtr,
|
|
8444
|
+
colIdx: reverse.colIdx ?? reverse.rowPtr
|
|
8445
|
+
};
|
|
8446
|
+
}
|
|
8447
|
+
return { finalize, forward, forwardEdge, backward, edgeGather, count };
|
|
8448
|
+
}
|
|
8359
8449
|
function recordFill(state, pass, dst, count, value) {
|
|
8360
8450
|
const { scope, fill, ctx } = state;
|
|
8361
8451
|
const params = scope.params(FILL_PARAMS, { count, value, mode: 0, pad0: 0 });
|
|
@@ -8363,9 +8453,9 @@ function recordFill(state, pass, dst, count, value) {
|
|
|
8363
8453
|
params.offset
|
|
8364
8454
|
]);
|
|
8365
8455
|
}
|
|
8366
|
-
function recordBc(state, pass, kernel, resources, fields, items) {
|
|
8456
|
+
function recordBc(state, pass, kernel, resources, fields, items, maxGroups) {
|
|
8367
8457
|
const { scope, ctx } = state;
|
|
8368
|
-
const plan = planGridStride(items, ctx.workgroupSize, ctx.caps);
|
|
8458
|
+
const plan = planGridStride(items, ctx.workgroupSize, ctx.caps, maxGroups);
|
|
8369
8459
|
const params = scope.params(BC_PARAMS, { ...fields, stride: plan.stride ?? 0 });
|
|
8370
8460
|
let bound = state.bound.get(kernel);
|
|
8371
8461
|
if (bound === void 0) {
|
|
@@ -8384,8 +8474,8 @@ async function submit(state, batch, signal) {
|
|
|
8384
8474
|
}
|
|
8385
8475
|
return back;
|
|
8386
8476
|
}
|
|
8387
|
-
async function runBatch(state, sources, form, levelsPerSubmit, tuning, signal) {
|
|
8388
|
-
const { ctx, n, S, ends, depthK, sigmaK, deltaK, counters } = state;
|
|
8477
|
+
async function runBatch(state, mode, sources, form, levelsPerSubmit, tuning, signal) {
|
|
8478
|
+
const { ctx, n, S, ends, levelMax, depthK, sigmaK, deltaK, counters } = state;
|
|
8389
8479
|
const k = sources.length;
|
|
8390
8480
|
const words = n * k;
|
|
8391
8481
|
const seeds = Uint32Array.from(sources, (v, s) => s * n + v);
|
|
@@ -8403,15 +8493,18 @@ async function runBatch(state, sources, form, levelsPerSubmit, tuning, signal) {
|
|
|
8403
8493
|
recordFill(state, pass, depthK, words, 4294967295);
|
|
8404
8494
|
recordFill(state, pass, sigmaK, words, 0);
|
|
8405
8495
|
recordFill(state, pass, deltaK, words, 0);
|
|
8406
|
-
|
|
8496
|
+
if (mode.count !== null) {
|
|
8497
|
+
recordFill(state, pass, levelMax, n + 2, 0);
|
|
8498
|
+
}
|
|
8499
|
+
recordBc(state, pass, mode.finalize, { counters, ends, S, depthK, sigmaK, levelMax }, { n, k, role: 1 }, 1);
|
|
8407
8500
|
}
|
|
8408
8501
|
for (let level = 0; level < levelsPerSubmit; level++) {
|
|
8409
|
-
recordBc(state, pass,
|
|
8410
|
-
if (form === "edge" &&
|
|
8502
|
+
recordBc(state, pass, mode.finalize, { counters, ends, S, depthK, sigmaK, levelMax }, { n, k, role: 0 }, 1);
|
|
8503
|
+
if (form === "edge" && mode.forwardEdge !== null && state.edgeSrc !== null && state.edgeDst !== null) {
|
|
8411
8504
|
recordBc(
|
|
8412
8505
|
state,
|
|
8413
8506
|
pass,
|
|
8414
|
-
|
|
8507
|
+
mode.forwardEdge,
|
|
8415
8508
|
{ edgeSrc: state.edgeSrc, edgeDst: state.edgeDst, S, ends, counters, depthK, sigmaK },
|
|
8416
8509
|
forwardFields,
|
|
8417
8510
|
forwardItems
|
|
@@ -8420,12 +8513,24 @@ async function runBatch(state, sources, form, levelsPerSubmit, tuning, signal) {
|
|
|
8420
8513
|
recordBc(
|
|
8421
8514
|
state,
|
|
8422
8515
|
pass,
|
|
8423
|
-
|
|
8516
|
+
mode.forward,
|
|
8424
8517
|
{ rowPtr: state.rowPtr, colIdx: state.colIdx, S, ends, counters, depthK, sigmaK },
|
|
8425
8518
|
forwardFields,
|
|
8426
8519
|
forwardItems
|
|
8427
8520
|
);
|
|
8428
8521
|
}
|
|
8522
|
+
if (mode.count !== null) {
|
|
8523
|
+
const { kernel, rowPtr, colIdx } = mode.count;
|
|
8524
|
+
recordBc(
|
|
8525
|
+
state,
|
|
8526
|
+
pass,
|
|
8527
|
+
kernel,
|
|
8528
|
+
{ rowPtr, colIdx, S, ends, counters, depthK, sigmaK, levelMax },
|
|
8529
|
+
{ n, k },
|
|
8530
|
+
words,
|
|
8531
|
+
BC_COUNT_MAX_GROUPS
|
|
8532
|
+
);
|
|
8533
|
+
}
|
|
8429
8534
|
}
|
|
8430
8535
|
recorded += levelsPerSubmit;
|
|
8431
8536
|
batch.endPass();
|
|
@@ -8438,6 +8543,9 @@ async function runBatch(state, sources, form, levelsPerSubmit, tuning, signal) {
|
|
|
8438
8543
|
levels = words32[W.level];
|
|
8439
8544
|
overflow = words32[W.sigmaOverflow] !== 0;
|
|
8440
8545
|
endsWords = new Uint32Array(back, endsRequest.offset, endsCount).slice(0, levels + 1);
|
|
8546
|
+
if (overflow && mode.count === null) {
|
|
8547
|
+
return { levels, wrapped: true, overflow: false };
|
|
8548
|
+
}
|
|
8441
8549
|
} else if (recorded > n + 2) {
|
|
8442
8550
|
throw new WebGpuGraphError("E_VALIDATION", `${ALGORITHM$5}: the done flag never rose in ${recorded} levels`, {
|
|
8443
8551
|
label: ALGORITHM$5,
|
|
@@ -8461,20 +8569,28 @@ async function runBatch(state, sources, form, levelsPerSubmit, tuning, signal) {
|
|
|
8461
8569
|
recordBc(
|
|
8462
8570
|
state,
|
|
8463
8571
|
pass,
|
|
8464
|
-
|
|
8465
|
-
{ rowPtr: state.rowPtr, colIdx: state.colIdx, S, depthK, sigmaK, deltaK },
|
|
8572
|
+
mode.backward,
|
|
8573
|
+
{ rowPtr: state.rowPtr, colIdx: state.colIdx, S, depthK, sigmaK, deltaK, levelMax },
|
|
8466
8574
|
{ n, k, start, count },
|
|
8467
8575
|
count
|
|
8468
8576
|
);
|
|
8469
8577
|
}
|
|
8470
8578
|
if (last) {
|
|
8471
8579
|
recordBc(state, pass, state.gather, { deltaK, bc: state.bc }, { n, k }, n);
|
|
8472
|
-
if (
|
|
8580
|
+
if (mode.edgeGather !== null && state.arcScores !== null) {
|
|
8473
8581
|
recordBc(
|
|
8474
8582
|
state,
|
|
8475
8583
|
pass,
|
|
8476
|
-
|
|
8477
|
-
{
|
|
8584
|
+
mode.edgeGather,
|
|
8585
|
+
{
|
|
8586
|
+
rowPtr: state.rowPtr,
|
|
8587
|
+
colIdx: state.colIdx,
|
|
8588
|
+
depthK,
|
|
8589
|
+
sigmaK,
|
|
8590
|
+
deltaK,
|
|
8591
|
+
arcScores: state.arcScores,
|
|
8592
|
+
levelMax
|
|
8593
|
+
},
|
|
8478
8594
|
{ n, k, count: state.arcCount },
|
|
8479
8595
|
state.arcCount
|
|
8480
8596
|
);
|
|
@@ -8500,12 +8616,13 @@ async function runBatch(state, sources, form, levelsPerSubmit, tuning, signal) {
|
|
|
8500
8616
|
forward: form,
|
|
8501
8617
|
levels,
|
|
8502
8618
|
ends: endsWords.slice(),
|
|
8619
|
+
scaled: mode.count !== null,
|
|
8503
8620
|
sigmaOverflow: overflow,
|
|
8504
8621
|
depthK: arrays?.depthK ?? null,
|
|
8505
8622
|
sigmaK: arrays?.sigmaK ?? null,
|
|
8506
8623
|
deltaK: arrays?.deltaK ?? null
|
|
8507
8624
|
});
|
|
8508
|
-
return { levels, overflow };
|
|
8625
|
+
return { levels, wrapped: false, overflow };
|
|
8509
8626
|
}
|
|
8510
8627
|
async function runRaw(ctx, s, sources, withEdges, tuning, options) {
|
|
8511
8628
|
const n = s.nodeCount;
|
|
@@ -8526,19 +8643,17 @@ async function runRaw(ctx, s, sources, withEdges, tuning, options) {
|
|
|
8526
8643
|
const arrayBytes = 4 * n * kMax;
|
|
8527
8644
|
const lease = (bytes, label) => bindingOf(scope.scratch(bytes, label), bytes);
|
|
8528
8645
|
const arcBytes = 4 * Math.max(1, s.arcCount);
|
|
8529
|
-
const [fill,
|
|
8530
|
-
["fill", "bc-
|
|
8531
|
-
(id) => ctx.pipelines.kernel(kernelSpec(id))
|
|
8532
|
-
)
|
|
8646
|
+
const [fill, gather] = await Promise.all(
|
|
8647
|
+
["fill", "bc-gather"].map((id) => ctx.pipelines.kernel(kernelSpec(id)))
|
|
8533
8648
|
);
|
|
8534
|
-
const
|
|
8535
|
-
const edgeGather = withEdges ? await ctx.pipelines.kernel(kernelSpec("bc-edge-gather")) : null;
|
|
8649
|
+
const exact = await modeKernels(ctx, s, core, edgeView !== null, withEdges, false);
|
|
8536
8650
|
const state = {
|
|
8537
8651
|
ctx,
|
|
8538
8652
|
scope,
|
|
8539
8653
|
n,
|
|
8540
8654
|
S: lease(arrayBytes, "S"),
|
|
8541
8655
|
ends: lease(4 * (n + 2), "ends"),
|
|
8656
|
+
levelMax: lease(4 * (n + 2), "level-max"),
|
|
8542
8657
|
depthK: lease(arrayBytes, "depthK"),
|
|
8543
8658
|
sigmaK: lease(arrayBytes, "sigmaK"),
|
|
8544
8659
|
deltaK: lease(arrayBytes, "deltaK"),
|
|
@@ -8552,12 +8667,9 @@ async function runRaw(ctx, s, sources, withEdges, tuning, options) {
|
|
|
8552
8667
|
edgeCount,
|
|
8553
8668
|
arcCount: s.arcCount,
|
|
8554
8669
|
fill,
|
|
8555
|
-
finalize,
|
|
8556
|
-
forward,
|
|
8557
|
-
forwardEdge,
|
|
8558
|
-
backward,
|
|
8559
8670
|
gather,
|
|
8560
|
-
|
|
8671
|
+
exact,
|
|
8672
|
+
scaled: null,
|
|
8561
8673
|
bound: /* @__PURE__ */ new Map()
|
|
8562
8674
|
};
|
|
8563
8675
|
await ctx.allocator.check();
|
|
@@ -8578,11 +8690,23 @@ async function runRaw(ctx, s, sources, withEdges, tuning, options) {
|
|
|
8578
8690
|
if (pinned === "auto" && previousLevels >= 0) {
|
|
8579
8691
|
form = previousLevels < BC_EDGE_PARALLEL_GAMMA * Math.log2(n) ? "edge" : "frontier";
|
|
8580
8692
|
}
|
|
8581
|
-
if (state.forwardEdge === null) {
|
|
8693
|
+
if (state.exact.forwardEdge === null) {
|
|
8582
8694
|
form = "frontier";
|
|
8583
8695
|
}
|
|
8584
8696
|
const batch = sources.slice(start, start + k);
|
|
8585
|
-
|
|
8697
|
+
let outcome = await runBatch(
|
|
8698
|
+
state,
|
|
8699
|
+
state.scaled ?? state.exact,
|
|
8700
|
+
batch,
|
|
8701
|
+
form,
|
|
8702
|
+
levelsPerSubmit,
|
|
8703
|
+
tuning,
|
|
8704
|
+
options?.signal
|
|
8705
|
+
);
|
|
8706
|
+
if (outcome.wrapped) {
|
|
8707
|
+
state.scaled ??= await modeKernels(ctx, s, core, edgeView !== null, withEdges, true);
|
|
8708
|
+
outcome = await runBatch(state, state.scaled, batch, form, levelsPerSubmit, tuning, options?.signal);
|
|
8709
|
+
}
|
|
8586
8710
|
overflow = overflow || outcome.overflow;
|
|
8587
8711
|
previousLevels = outcome.levels;
|
|
8588
8712
|
start += k;
|
|
@@ -15508,7 +15632,7 @@ async function calibrateLayout(ctx, options) {
|
|
|
15508
15632
|
};
|
|
15509
15633
|
}
|
|
15510
15634
|
export {
|
|
15511
|
-
|
|
15635
|
+
a2 as ARC_WINDOW_ALIGN,
|
|
15512
15636
|
EXACT_MAX_NODES,
|
|
15513
15637
|
FA2_DEFAULTS,
|
|
15514
15638
|
FR_DEFAULTS,
|
|
@@ -15516,10 +15640,10 @@ export {
|
|
|
15516
15640
|
LAYOUT_TUNING_DEFAULTS,
|
|
15517
15641
|
MAX_1D_ITEMS,
|
|
15518
15642
|
MAX_WORKGROUPS_PER_DIM,
|
|
15519
|
-
|
|
15643
|
+
a3 as PASSTHROUGH_FORMAT_CODES,
|
|
15520
15644
|
SE_DEFAULTS,
|
|
15521
|
-
|
|
15522
|
-
|
|
15645
|
+
a4 as STORAGE_ALIGN,
|
|
15646
|
+
a5 as WORKGROUP_SIZE,
|
|
15523
15647
|
WebGpuGraphError,
|
|
15524
15648
|
allPairsShortestPath,
|
|
15525
15649
|
bellmanFord,
|
|
@@ -15537,7 +15661,7 @@ export {
|
|
|
15537
15661
|
eigenvectorCentrality,
|
|
15538
15662
|
hasErrorCode,
|
|
15539
15663
|
hits,
|
|
15540
|
-
|
|
15664
|
+
a6 as isSoftwareAdapter,
|
|
15541
15665
|
isWebGpuGraphError,
|
|
15542
15666
|
katzCentrality,
|
|
15543
15667
|
labelPropagation,
|