@graphty/webgpu-graph-algorithms 0.5.1 → 0.6.1
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 +459 -58
- package/dist/browser.js +1 -1
- package/dist/chunks/{context-BR7fx3vR.js → context-BXqgCifx.js} +190 -40
- package/dist/chunks/context-BXqgCifx.js.map +1 -0
- package/dist/node.js +1 -1
- package/dist/src/algorithms/components.d.ts.map +1 -1
- package/dist/src/algorithms/components.js +12 -13
- package/dist/src/algorithms/components.js.map +1 -1
- package/dist/src/algorithms/degree.d.ts +6 -8
- package/dist/src/algorithms/degree.d.ts.map +1 -1
- package/dist/src/algorithms/degree.js +58 -35
- package/dist/src/algorithms/degree.js.map +1 -1
- package/dist/src/algorithms/pagerank.d.ts.map +1 -1
- package/dist/src/algorithms/pagerank.js +16 -14
- package/dist/src/algorithms/pagerank.js.map +1 -1
- package/dist/src/algorithms/power-iteration.d.ts +2 -2
- package/dist/src/algorithms/power-iteration.d.ts.map +1 -1
- package/dist/src/algorithms/power-iteration.js +17 -14
- package/dist/src/algorithms/power-iteration.js.map +1 -1
- package/dist/src/constants.d.ts +38 -8
- package/dist/src/constants.d.ts.map +1 -1
- package/dist/src/constants.js +38 -8
- package/dist/src/constants.js.map +1 -1
- package/dist/src/errors.d.ts +3 -2
- package/dist/src/errors.d.ts.map +1 -1
- package/dist/src/errors.js +2 -1
- package/dist/src/errors.js.map +1 -1
- package/dist/src/index.d.ts +6 -4
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +8 -3
- package/dist/src/index.js.map +1 -1
- package/dist/src/kernel/dispatch.d.ts +8 -3
- package/dist/src/kernel/dispatch.d.ts.map +1 -1
- package/dist/src/kernel/dispatch.js +18 -7
- package/dist/src/kernel/dispatch.js.map +1 -1
- package/dist/src/kernel/kernel.d.ts +30 -1
- package/dist/src/kernel/kernel.d.ts.map +1 -1
- package/dist/src/kernel/kernel.js +49 -5
- package/dist/src/kernel/kernel.js.map +1 -1
- package/dist/src/kernel/prelude.d.ts.map +1 -1
- package/dist/src/kernel/prelude.js +6 -1
- package/dist/src/kernel/prelude.js.map +1 -1
- package/dist/src/kernel/profiler.d.ts +15 -3
- package/dist/src/kernel/profiler.d.ts.map +1 -1
- package/dist/src/kernel/profiler.js +27 -4
- package/dist/src/kernel/profiler.js.map +1 -1
- package/dist/src/kernels.d.ts +17 -7
- package/dist/src/kernels.d.ts.map +1 -1
- package/dist/src/kernels.js +323 -16
- package/dist/src/kernels.js.map +1 -1
- package/dist/src/layouts/calibrate.d.ts +51 -0
- package/dist/src/layouts/calibrate.d.ts.map +1 -0
- package/dist/src/layouts/calibrate.js +172 -0
- package/dist/src/layouts/calibrate.js.map +1 -0
- package/dist/src/layouts/force-simulation.d.ts +39 -4
- package/dist/src/layouts/force-simulation.d.ts.map +1 -1
- package/dist/src/layouts/force-simulation.js +71 -19
- package/dist/src/layouts/force-simulation.js.map +1 -1
- package/dist/src/layouts/forceatlas2.d.ts +107 -36
- package/dist/src/layouts/forceatlas2.d.ts.map +1 -1
- package/dist/src/layouts/forceatlas2.js +296 -100
- package/dist/src/layouts/forceatlas2.js.map +1 -1
- package/dist/src/layouts/fruchterman-reingold.d.ts +73 -27
- package/dist/src/layouts/fruchterman-reingold.d.ts.map +1 -1
- package/dist/src/layouts/fruchterman-reingold.js +230 -70
- package/dist/src/layouts/fruchterman-reingold.js.map +1 -1
- package/dist/src/layouts/model-common.d.ts +41 -3
- package/dist/src/layouts/model-common.d.ts.map +1 -1
- package/dist/src/layouts/model-common.js +74 -3
- package/dist/src/layouts/model-common.js.map +1 -1
- package/dist/src/layouts/repulsion-grid.d.ts +152 -0
- package/dist/src/layouts/repulsion-grid.d.ts.map +1 -0
- package/dist/src/layouts/repulsion-grid.js +318 -0
- package/dist/src/layouts/repulsion-grid.js.map +1 -0
- package/dist/src/layouts/spring-electrical.d.ts +75 -30
- package/dist/src/layouts/spring-electrical.d.ts.map +1 -1
- package/dist/src/layouts/spring-electrical.js +231 -74
- package/dist/src/layouts/spring-electrical.js.map +1 -1
- package/dist/src/memory/residency.d.ts +6 -2
- package/dist/src/memory/residency.d.ts.map +1 -1
- package/dist/src/memory/residency.js +84 -14
- package/dist/src/memory/residency.js.map +1 -1
- package/dist/src/primitives/core-shape.d.ts +38 -2
- package/dist/src/primitives/core-shape.d.ts.map +1 -1
- package/dist/src/primitives/core-shape.js +71 -3
- package/dist/src/primitives/core-shape.js.map +1 -1
- package/dist/src/primitives/grid-pyramid.d.ts +71 -0
- package/dist/src/primitives/grid-pyramid.d.ts.map +1 -0
- package/dist/src/primitives/grid-pyramid.js +143 -0
- package/dist/src/primitives/grid-pyramid.js.map +1 -0
- package/dist/src/primitives/grid.d.ts +118 -0
- package/dist/src/primitives/grid.d.ts.map +1 -0
- package/dist/src/primitives/grid.js +225 -0
- package/dist/src/primitives/grid.js.map +1 -0
- package/dist/src/primitives/histogram.d.ts +67 -0
- package/dist/src/primitives/histogram.d.ts.map +1 -0
- package/dist/src/primitives/histogram.js +190 -0
- package/dist/src/primitives/histogram.js.map +1 -0
- package/dist/src/primitives/radix-sort.d.ts +75 -0
- package/dist/src/primitives/radix-sort.d.ts.map +1 -0
- package/dist/src/primitives/radix-sort.js +168 -0
- package/dist/src/primitives/radix-sort.js.map +1 -0
- package/dist/src/primitives/scan.d.ts +44 -0
- package/dist/src/primitives/scan.d.ts.map +1 -0
- package/dist/src/primitives/scan.js +151 -0
- package/dist/src/primitives/scan.js.map +1 -0
- package/dist/src/primitives/segmented-reduce.d.ts +25 -17
- package/dist/src/primitives/segmented-reduce.d.ts.map +1 -1
- package/dist/src/primitives/segmented-reduce.js +166 -47
- package/dist/src/primitives/segmented-reduce.js.map +1 -1
- package/dist/src/primitives/spmv.d.ts +18 -14
- package/dist/src/primitives/spmv.d.ts.map +1 -1
- package/dist/src/primitives/spmv.js +94 -58
- package/dist/src/primitives/spmv.js.map +1 -1
- package/dist/src/primitives/verify.d.ts +49 -0
- package/dist/src/primitives/verify.d.ts.map +1 -0
- package/dist/src/primitives/verify.js +229 -0
- package/dist/src/primitives/verify.js.map +1 -0
- package/dist/src/types/context.d.ts +53 -0
- package/dist/src/types/context.d.ts.map +1 -1
- package/dist/src/types/layout.d.ts +20 -0
- package/dist/src/types/layout.d.ts.map +1 -1
- package/dist/src/wgsl/counting-scatter.wgsl.d.ts +8 -0
- package/dist/src/wgsl/counting-scatter.wgsl.d.ts.map +1 -0
- package/dist/src/wgsl/counting-scatter.wgsl.js +17 -0
- package/dist/src/wgsl/counting-scatter.wgsl.js.map +1 -0
- package/dist/src/wgsl/fa2-attraction.wgsl.d.ts +23 -11
- package/dist/src/wgsl/fa2-attraction.wgsl.d.ts.map +1 -1
- package/dist/src/wgsl/fa2-attraction.wgsl.js +98 -20
- package/dist/src/wgsl/fa2-attraction.wgsl.js.map +1 -1
- package/dist/src/wgsl/fa2-stats-finalize.wgsl.d.ts +6 -2
- package/dist/src/wgsl/fa2-stats-finalize.wgsl.d.ts.map +1 -1
- package/dist/src/wgsl/fa2-stats-finalize.wgsl.js +22 -1
- package/dist/src/wgsl/fa2-stats-finalize.wgsl.js.map +1 -1
- package/dist/src/wgsl/grid-cell-key.wgsl.d.ts +8 -0
- package/dist/src/wgsl/grid-cell-key.wgsl.d.ts.map +1 -0
- package/dist/src/wgsl/grid-cell-key.wgsl.js +30 -0
- package/dist/src/wgsl/grid-cell-key.wgsl.js.map +1 -0
- package/dist/src/wgsl/grid-centroid-hub.wgsl.d.ts +8 -0
- package/dist/src/wgsl/grid-centroid-hub.wgsl.d.ts.map +1 -0
- package/dist/src/wgsl/grid-centroid-hub.wgsl.js +29 -0
- package/dist/src/wgsl/grid-centroid-hub.wgsl.js.map +1 -0
- package/dist/src/wgsl/grid-centroid.wgsl.d.ts +8 -0
- package/dist/src/wgsl/grid-centroid.wgsl.d.ts.map +1 -0
- package/dist/src/wgsl/grid-centroid.wgsl.js +29 -0
- package/dist/src/wgsl/grid-centroid.wgsl.js.map +1 -0
- package/dist/src/wgsl/grid-downsample.wgsl.d.ts +7 -0
- package/dist/src/wgsl/grid-downsample.wgsl.d.ts.map +1 -0
- package/dist/src/wgsl/grid-downsample.wgsl.js +28 -0
- package/dist/src/wgsl/grid-downsample.wgsl.js.map +1 -0
- package/dist/src/wgsl/grid-far-field.wgsl.d.ts +13 -0
- package/dist/src/wgsl/grid-far-field.wgsl.d.ts.map +1 -0
- package/dist/src/wgsl/grid-far-field.wgsl.js +98 -0
- package/dist/src/wgsl/grid-far-field.wgsl.js.map +1 -0
- package/dist/src/wgsl/grid-near-field.wgsl.d.ts +19 -0
- package/dist/src/wgsl/grid-near-field.wgsl.d.ts.map +1 -0
- package/dist/src/wgsl/grid-near-field.wgsl.js +129 -0
- package/dist/src/wgsl/grid-near-field.wgsl.js.map +1 -0
- package/dist/src/wgsl/histogram.wgsl.d.ts +7 -0
- package/dist/src/wgsl/histogram.wgsl.d.ts.map +1 -0
- package/dist/src/wgsl/histogram.wgsl.js +15 -0
- package/dist/src/wgsl/histogram.wgsl.js.map +1 -0
- package/dist/src/wgsl/indirect-finalize.wgsl.d.ts +8 -0
- package/dist/src/wgsl/indirect-finalize.wgsl.d.ts.map +1 -0
- package/dist/src/wgsl/indirect-finalize.wgsl.js +26 -0
- package/dist/src/wgsl/indirect-finalize.wgsl.js.map +1 -0
- package/dist/src/wgsl/radix-hist.wgsl.d.ts +9 -0
- package/dist/src/wgsl/radix-hist.wgsl.d.ts.map +1 -0
- package/dist/src/wgsl/radix-hist.wgsl.js +31 -0
- package/dist/src/wgsl/radix-hist.wgsl.js.map +1 -0
- package/dist/src/wgsl/radix-scatter.wgsl.d.ts +9 -0
- package/dist/src/wgsl/radix-scatter.wgsl.d.ts.map +1 -0
- package/dist/src/wgsl/radix-scatter.wgsl.js +40 -0
- package/dist/src/wgsl/radix-scatter.wgsl.js.map +1 -0
- package/dist/src/wgsl/scan-add.wgsl.d.ts +6 -0
- package/dist/src/wgsl/scan-add.wgsl.d.ts.map +1 -0
- package/dist/src/wgsl/scan-add.wgsl.js +14 -0
- package/dist/src/wgsl/scan-add.wgsl.js.map +1 -0
- package/dist/src/wgsl/scan-block.wgsl.d.ts +8 -0
- package/dist/src/wgsl/scan-block.wgsl.d.ts.map +1 -0
- package/dist/src/wgsl/scan-block.wgsl.js +30 -0
- package/dist/src/wgsl/scan-block.wgsl.js.map +1 -0
- package/dist/src/wgsl/segmented-reduce.wgsl.d.ts +22 -8
- package/dist/src/wgsl/segmented-reduce.wgsl.d.ts.map +1 -1
- package/dist/src/wgsl/segmented-reduce.wgsl.js +84 -15
- package/dist/src/wgsl/segmented-reduce.wgsl.js.map +1 -1
- package/dist/src/wgsl/spmv-pull.wgsl.d.ts +22 -11
- package/dist/src/wgsl/spmv-pull.wgsl.d.ts.map +1 -1
- package/dist/src/wgsl/spmv-pull.wgsl.js +110 -36
- package/dist/src/wgsl/spmv-pull.wgsl.js.map +1 -1
- package/dist/tsconfig.build.tsbuildinfo +1 -1
- package/dist/webgpu-graph-algorithms.js +3815 -1003
- package/dist/webgpu-graph-algorithms.js.map +1 -1
- package/package.json +9 -8
- package/src/algorithms/components.ts +12 -16
- package/src/algorithms/degree.ts +58 -43
- package/src/algorithms/pagerank.ts +20 -18
- package/src/algorithms/power-iteration.ts +19 -18
- package/src/constants.ts +38 -8
- package/src/errors.ts +3 -1
- package/src/index.ts +14 -4
- package/src/kernel/dispatch.ts +18 -7
- package/src/kernel/kernel.ts +59 -5
- package/src/kernel/prelude.ts +9 -0
- package/src/kernel/profiler.ts +28 -4
- package/src/kernels.ts +356 -18
- package/src/layouts/calibrate.ts +187 -0
- package/src/layouts/force-simulation.ts +91 -23
- package/src/layouts/forceatlas2.ts +331 -106
- package/src/layouts/fruchterman-reingold.ts +255 -74
- package/src/layouts/model-common.ts +98 -3
- package/src/layouts/repulsion-grid.ts +451 -0
- package/src/layouts/spring-electrical.ts +257 -78
- package/src/memory/residency.ts +126 -20
- package/src/primitives/core-shape.ts +91 -4
- package/src/primitives/grid-pyramid.ts +221 -0
- package/src/primitives/grid.ts +349 -0
- package/src/primitives/histogram.ts +273 -0
- package/src/primitives/radix-sort.ts +246 -0
- package/src/primitives/scan.ts +197 -0
- package/src/primitives/segmented-reduce.ts +214 -56
- package/src/primitives/spmv.ts +125 -65
- package/src/primitives/verify.ts +249 -0
- package/src/types/context.ts +56 -0
- package/src/types/layout.ts +22 -0
- package/src/wgsl/counting-scatter.wgsl.ts +16 -0
- package/src/wgsl/fa2-attraction.wgsl.ts +98 -20
- package/src/wgsl/fa2-stats-finalize.wgsl.ts +22 -1
- package/src/wgsl/grid-cell-key.wgsl.ts +29 -0
- package/src/wgsl/grid-centroid-hub.wgsl.ts +28 -0
- package/src/wgsl/grid-centroid.wgsl.ts +28 -0
- package/src/wgsl/grid-downsample.wgsl.ts +27 -0
- package/src/wgsl/grid-far-field.wgsl.ts +97 -0
- package/src/wgsl/grid-near-field.wgsl.ts +128 -0
- package/src/wgsl/histogram.wgsl.ts +14 -0
- package/src/wgsl/indirect-finalize.wgsl.ts +25 -0
- package/src/wgsl/radix-hist.wgsl.ts +30 -0
- package/src/wgsl/radix-scatter.wgsl.ts +39 -0
- package/src/wgsl/scan-add.wgsl.ts +13 -0
- package/src/wgsl/scan-block.wgsl.ts +29 -0
- package/src/wgsl/segmented-reduce.wgsl.ts +84 -15
- package/src/wgsl/spmv-pull.wgsl.ts +110 -36
- package/dist/chunks/context-BR7fx3vR.js.map +0 -1
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* The pull SpMV primitive of spec 6 row 9 / 8.2
|
|
3
|
-
*
|
|
4
|
-
* `weight * xNorm[nbr]` over its row's in-arcs (Kahan-compensated, f32) and writing
|
|
2
|
+
* The pull SpMV primitive of spec 6 row 9 / 8.2 (P7; M8b plan PD-1 / PD-2): the `spmv-pull` module over the rows of
|
|
3
|
+
* a REVERSE adjacency, each row folding `weight * xNorm[nbr]` over its in-arcs (a two-level f32 sum) and writing
|
|
5
4
|
* `rankOut[v] = beta * pv + alpha * (sum + danglingMass * pv)`, where `pv` is `personalization[v]` under
|
|
6
5
|
* HAS_PERSONALIZATION and the uniform `P.uniformP` otherwise, and `danglingMass` is `partials[0].danglingMass`
|
|
7
6
|
* under USE_DANGLING. PageRank sets alpha to the damping, beta to 1 - alpha and USE_DANGLING; HITS and eigenvector
|
|
@@ -9,93 +8,130 @@
|
|
|
9
8
|
*
|
|
10
9
|
* It is its own registry entry rather than a `segmentedReduce` VALUE snippet (PD-1): the snippet vocabulary is
|
|
11
10
|
* `row, arc, nbr, weight, v` and cannot read `xNorm[nbr]`, and the design's binding table gives the kernel eight
|
|
12
|
-
* storage bindings of its own.
|
|
13
|
-
*
|
|
14
|
-
*
|
|
11
|
+
* storage bindings of its own. Without tiers it is ONE grid-stride dispatch (TIER 0, USE_PERM false: the perm slot
|
|
12
|
+
* carries the rowPtr dummy of graphBindings); with the in-degree tiers of `reverseDegreeOrder()` (P4-T5, PD-6) it
|
|
13
|
+
* is up to three dispatches over the permuted rows -- TIER 2 one workgroup per row over [0, hiEnd), TIER 1 32 lanes
|
|
14
|
+
* per row over [hiEnd, midEnd), TIER 0 grid-stride over [midEnd, n) -- each compiled only when its range is
|
|
15
|
+
* non-empty. The row and arc counts come from the core's binding sizes exactly as segmentedReduce derives them.
|
|
15
16
|
*/
|
|
16
17
|
import { WebGpuGraphError } from "../errors.js";
|
|
17
|
-
import { planGridStride } from "../kernel/dispatch.js";
|
|
18
|
+
import { plan1d, planGridStride } from "../kernel/dispatch.js";
|
|
18
19
|
import { graphBindings, graphOverrides, kernelSpec, SPMV_PARAMS } from "../kernels.js";
|
|
19
|
-
import { arcCountOf, assertNotWindowed, rowCountOf } from "./core-shape.js";
|
|
20
|
-
/**
|
|
20
|
+
import { arcCountOf, assertNotWindowed, MID_TIER_LANES, rowCountOf } from "./core-shape.js";
|
|
21
|
+
/**
|
|
22
|
+
* The tiered planner: without tiers ONE `spmv-pull` dispatch, grid-stride over every row; with tiers TIER 2 over
|
|
23
|
+
* [0, hiEnd) (one workgroup per row), then TIER 1 over [hiEnd, midEnd) (WG / 32 rows per workgroup), then TIER 0
|
|
24
|
+
* grid-stride over [midEnd, n), each with its own SpmvParams record (`n` is the range END) and the perm binding.
|
|
25
|
+
*/
|
|
21
26
|
class SpmvPullPlannerImpl {
|
|
22
27
|
/**
|
|
23
|
-
* Wraps
|
|
24
|
-
* @param scope - the scope the
|
|
25
|
-
* @param
|
|
26
|
-
* @param
|
|
28
|
+
* Wraps the compiled tier pipelines with the choices they were compiled for.
|
|
29
|
+
* @param scope - the scope the pipelines were prepared in
|
|
30
|
+
* @param tiers - the compiled tiers in dispatch order (TIER 2, 1, 0; only the non-empty ones)
|
|
31
|
+
* @param perm - the reverseDegreeOrder permutation binding (null: USE_PERM false, rows are node indices)
|
|
32
|
+
* @param weights - the weights option the pipelines' HAS_WEIGHTS was derived from; record() binds the same way
|
|
27
33
|
*/
|
|
28
|
-
constructor(scope,
|
|
34
|
+
constructor(scope, tiers, perm, weights) {
|
|
29
35
|
this.dispatches = 0;
|
|
30
36
|
this.scope = scope;
|
|
31
|
-
this.
|
|
37
|
+
this.tiers = tiers;
|
|
38
|
+
this.perm = perm;
|
|
32
39
|
this.weights = weights;
|
|
33
40
|
}
|
|
34
41
|
/**
|
|
35
42
|
* Dispatches the last record() issued.
|
|
36
|
-
* @returns
|
|
43
|
+
* @returns 0 when the last record covered no rows, else the number of non-empty tier ranges
|
|
37
44
|
*/
|
|
38
45
|
get lastDispatches() {
|
|
39
46
|
return this.dispatches;
|
|
40
47
|
}
|
|
41
48
|
/**
|
|
42
|
-
* Records the
|
|
43
|
-
*
|
|
44
|
-
*
|
|
49
|
+
* Records the dispatches: every tier's rows over the arcs [0, arcCount), each with its own params record (TIER 0
|
|
50
|
+
* grid-stride through planGridStride, the tiers through plan1d); nothing for n = 0 (no zero-length binding is
|
|
51
|
+
* ever created). `personalization ?? xNorm` follows the group-0 dummy rule: both slots are storage-ro, so the
|
|
52
|
+
* aliasing check of Kernel.bind does not fire, and HAS_PERSONALIZATION false never reads it.
|
|
45
53
|
* @param pass - the pass to record into
|
|
46
|
-
* @param rev - the reverse core (any snapshot with the weights pattern the planner was prepared for
|
|
54
|
+
* @param rev - the reverse core (any snapshot with the weights pattern the planner was prepared for; with tiers,
|
|
55
|
+
* the one the tiers were built from)
|
|
47
56
|
* @param resources - xNorm, rankOut, personalization, partials
|
|
48
57
|
* @param coefficients - alpha, beta, uniformP
|
|
49
58
|
*/
|
|
50
59
|
record(pass, rev, resources, coefficients) {
|
|
51
60
|
const n = rowCountOf(rev, "spmvPull");
|
|
52
|
-
const
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
61
|
+
const wg = this.scope.workgroupSize;
|
|
62
|
+
this.dispatches = 0;
|
|
63
|
+
for (const { tier, kernel, start, end } of this.tiers) {
|
|
64
|
+
const last = tier === 0 ? n : end;
|
|
65
|
+
const rows = last - start;
|
|
66
|
+
if (rows <= 0) {
|
|
67
|
+
continue;
|
|
68
|
+
}
|
|
69
|
+
const plan = tier === 0
|
|
70
|
+
? planGridStride(rows, wg, this.scope.caps)
|
|
71
|
+
: plan1d(rows, tier === 2 ? 1 : wg / MID_TIER_LANES, this.scope.caps);
|
|
72
|
+
if (plan.x === 0) {
|
|
73
|
+
continue;
|
|
74
|
+
}
|
|
75
|
+
const params = this.scope.params(SPMV_PARAMS, {
|
|
76
|
+
n: last,
|
|
77
|
+
arcBase: 0,
|
|
78
|
+
arcEnd: arcCountOf(rev),
|
|
79
|
+
stride: plan.stride ?? rows,
|
|
80
|
+
alpha: coefficients.alpha,
|
|
81
|
+
beta: coefficients.beta,
|
|
82
|
+
uniformP: coefficients.uniformP,
|
|
83
|
+
start,
|
|
84
|
+
});
|
|
85
|
+
const bound = kernel.bind({
|
|
86
|
+
...graphBindings(rev, this.perm, this.weights),
|
|
87
|
+
xNorm: resources.xNorm,
|
|
88
|
+
rankOut: resources.rankOut,
|
|
89
|
+
personalization: resources.personalization ?? resources.xNorm,
|
|
90
|
+
partials: resources.partials,
|
|
91
|
+
P: params.binding,
|
|
92
|
+
});
|
|
93
|
+
kernel.dispatch(pass, bound, plan, [params.offset]);
|
|
94
|
+
this.dispatches++;
|
|
56
95
|
}
|
|
57
|
-
const params = this.scope.params(SPMV_PARAMS, {
|
|
58
|
-
n,
|
|
59
|
-
arcBase: 0,
|
|
60
|
-
arcEnd: arcCountOf(rev),
|
|
61
|
-
stride: plan.stride ?? n,
|
|
62
|
-
alpha: coefficients.alpha,
|
|
63
|
-
beta: coefficients.beta,
|
|
64
|
-
uniformP: coefficients.uniformP,
|
|
65
|
-
pad0: 0,
|
|
66
|
-
});
|
|
67
|
-
const bound = this.kernel.bind({
|
|
68
|
-
...graphBindings(rev, null, this.weights),
|
|
69
|
-
xNorm: resources.xNorm,
|
|
70
|
-
rankOut: resources.rankOut,
|
|
71
|
-
personalization: resources.personalization ?? resources.xNorm,
|
|
72
|
-
partials: resources.partials,
|
|
73
|
-
P: params.binding,
|
|
74
|
-
});
|
|
75
|
-
this.kernel.dispatch(pass, bound, plan, [params.offset]);
|
|
76
|
-
this.dispatches = 1;
|
|
77
96
|
}
|
|
78
97
|
}
|
|
79
98
|
/**
|
|
80
|
-
* Prepares the
|
|
99
|
+
* Prepares the pull pipelines for a reverse core's weights pattern and the two variant flags: TIER 0 always
|
|
100
|
+
* (USE_PERM = tiers !== null); TIER 1 iff a row of in-degree 32..1023 exists (segmentOffsets[2] >
|
|
101
|
+
* segmentOffsets[1]); TIER 2 iff a row of in-degree >= 1024 exists (segmentOffsets[1] > 0). The mid tier folds 32
|
|
102
|
+
* lanes per row, so a device whose workgroup size is below 32 is E_UNSUPPORTED { feature: "spmvPull.tiers" }.
|
|
81
103
|
* @param scope - the reduce scope (pipelines, params writer)
|
|
82
|
-
* @param rev - the reverse core whose weights pattern selects HAS_WEIGHTS
|
|
83
|
-
* @param options - personalization, dangling, weights, tiers (
|
|
104
|
+
* @param rev - the reverse core whose weights pattern selects HAS_WEIGHTS
|
|
105
|
+
* @param options - personalization, dangling, weights, tiers (null: the single grid-stride dispatch)
|
|
84
106
|
* @returns the planner
|
|
85
107
|
*/
|
|
86
108
|
export async function prepareSpmvPull(scope, rev, options) {
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
109
|
+
assertNotWindowed(rev, "spmvPull");
|
|
110
|
+
const { tiers } = options;
|
|
111
|
+
const perm = tiers?.perm ?? null;
|
|
112
|
+
if (tiers !== null && scope.workgroupSize < MID_TIER_LANES) {
|
|
113
|
+
throw new WebGpuGraphError("E_UNSUPPORTED", `spmvPull: the mid tier folds ${MID_TIER_LANES} lanes per row, more than the workgroup size ${scope.workgroupSize}`, { feature: "spmvPull.tiers" });
|
|
114
|
+
}
|
|
115
|
+
const ranges = tiers === null
|
|
116
|
+
? [{ tier: 0, start: 0, end: rowCountOf(rev, "spmvPull") }]
|
|
117
|
+
: [
|
|
118
|
+
{ tier: 2, start: 0, end: tiers.segmentOffsets[1] },
|
|
119
|
+
{ tier: 1, start: tiers.segmentOffsets[1], end: tiers.segmentOffsets[2] },
|
|
120
|
+
{ tier: 0, start: tiers.segmentOffsets[2], end: tiers.segmentOffsets[4] },
|
|
121
|
+
];
|
|
122
|
+
const compiled = [];
|
|
123
|
+
for (const range of ranges) {
|
|
124
|
+
if (range.tier !== 0 && range.end <= range.start) {
|
|
125
|
+
continue;
|
|
126
|
+
}
|
|
127
|
+
const spec = kernelSpec("spmv-pull", {
|
|
128
|
+
...graphOverrides(rev, perm, options.weights),
|
|
129
|
+
HAS_PERSONALIZATION: options.personalization,
|
|
130
|
+
USE_DANGLING: options.dangling,
|
|
131
|
+
TIER: range.tier,
|
|
90
132
|
});
|
|
133
|
+
compiled.push({ ...range, kernel: await scope.pipelines.kernel(spec) });
|
|
91
134
|
}
|
|
92
|
-
|
|
93
|
-
const spec = kernelSpec("spmv-pull", {
|
|
94
|
-
...graphOverrides(rev, null, options.weights),
|
|
95
|
-
HAS_PERSONALIZATION: options.personalization,
|
|
96
|
-
USE_DANGLING: options.dangling,
|
|
97
|
-
});
|
|
98
|
-
const kernel = await scope.pipelines.kernel(spec);
|
|
99
|
-
return new SpmvPullPlannerImpl(scope, kernel, options.weights);
|
|
135
|
+
return new SpmvPullPlannerImpl(scope, compiled, perm, options.weights);
|
|
100
136
|
}
|
|
101
137
|
//# sourceMappingURL=spmv.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"spmv.js","sourceRoot":"","sources":["../../../src/primitives/spmv.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"spmv.js","sourceRoot":"","sources":["../../../src/primitives/spmv.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The device self-check: one real exclusive scan of known numbers, run once per device before this package
|
|
3
|
+
* computes anything on it, so a device that returns wrong numbers is refused instead of believed.
|
|
4
|
+
*
|
|
5
|
+
* WHY IT EXISTS. On the Windows host lane -- Dawn's D3D12 backend over the Microsoft Basic Render Driver, the
|
|
6
|
+
* software renderer built into Windows -- every exclusive scan of more than one workgroup came back wrong: a
|
|
7
|
+
* block total of 1 where 256 belonged, or a second block nothing wrote at all, differing between two runs of
|
|
8
|
+
* identical code in one job. Everything built on the scan was wrong with it (the histogram, the radix sort, the
|
|
9
|
+
* grid build and every layout above them, eighteen test files), while every single-block scan and every earlier
|
|
10
|
+
* primitive stayed right. Three shader repairs failed; copying Microsoft's current redistributable renderer
|
|
11
|
+
* beside the runner's Node executable made all of it pass untouched. The defect is the driver's, and the danger
|
|
12
|
+
* to a caller is not a crash but silence: a graph laid out from wrong numbers with no error anywhere.
|
|
13
|
+
*
|
|
14
|
+
* WHY IT SCANS RATHER THAN PROBING A CONSTRUCT. An earlier hand-written probe matrix of workgroup constructs
|
|
15
|
+
* (test/primitives/workgroup-id-probe.test.ts) was measured PASSING on that renderer in the same job in which the
|
|
16
|
+
* real scan returned the wrong answer, so a copy of the shader's shape is not evidence about the shader. This
|
|
17
|
+
* check therefore drives the shipped `prepareScan` through the shipped composer and pipeline cache: it tests the
|
|
18
|
+
* code that runs, and it cannot drift away from it. One scan covers both recorded failures -- a value crossing
|
|
19
|
+
* `workgroupBarrier` inside a block, and a block total crossing from one dispatch of a compute pass to the next
|
|
20
|
+
* dispatch that reads it, which is the shape of every driver in this package.
|
|
21
|
+
*
|
|
22
|
+
* WHY IT REFUSES RATHER THAN ROUTING AROUND THE DEFECT. See docs/decisions/device-self-check.md: a barrier-free second
|
|
23
|
+
* implementation was designed and costed, and rejected because it would ship unverified on the only platform it
|
|
24
|
+
* exists for.
|
|
25
|
+
*
|
|
26
|
+
* WHERE IT RUNS. Lazily, at the first compute entry point a caller reaches, memoised per GPUDevice: the
|
|
27
|
+
* algorithms (degree, connectedComponents, the power-iteration family) and calibrateLayout await it on entry, and
|
|
28
|
+
* a layout simulation awaits it in the compile-and-bind promise `load()` starts -- the promise every batch and
|
|
29
|
+
* every debug run already awaits before it may submit. So a caller is covered whether the context was created,
|
|
30
|
+
* adopted through `create({ device })` or adopted through `GpuContext.from`, and a simulation refuses before its
|
|
31
|
+
* first iteration without the check sitting on the per-batch path, where an extra await would move the moment a
|
|
32
|
+
* submission becomes visible to a step() issued in the same tick and so change how the frame loop coalesces.
|
|
33
|
+
* It deliberately does NOT run in GpuContext.create:
|
|
34
|
+
* a context that only compiles -- Dawn's null backend, which computes nothing by design -- must stay usable, and
|
|
35
|
+
* `src/context.ts` may not import a primitive (the layer rule of spec 3.2).
|
|
36
|
+
*/
|
|
37
|
+
import { type CheckedContext, type DeviceCheck } from "../types/context.js";
|
|
38
|
+
/**
|
|
39
|
+
* What this device computed when it was asked for an answer this package already knows, run once per device and
|
|
40
|
+
* remembered. A caller may await it before committing work to a context; every compute entry point of the
|
|
41
|
+
* package awaits it too, so the cost is paid once whoever asks first.
|
|
42
|
+
*
|
|
43
|
+
* It reports rather than throws, so a caller can ask a device a question without having to catch the answer. The
|
|
44
|
+
* entry points use `assertDeviceComputes`, which turns a failing report into E_DEVICE_INCORRECT.
|
|
45
|
+
* @param ctx - the context whose device is checked
|
|
46
|
+
* @returns the capability record; `ok` false means this device returns wrong numbers
|
|
47
|
+
*/
|
|
48
|
+
export declare function verifyDevice(ctx: CheckedContext): Promise<DeviceCheck>;
|
|
49
|
+
//# sourceMappingURL=verify.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"verify.d.ts","sourceRoot":"","sources":["../../../src/primitives/verify.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmCG;AAIH,OAAO,EAAE,KAAK,cAAc,EAAE,KAAK,WAAW,EAA4B,MAAM,qBAAqB,CAAC;AA0ItG;;;;;;;;;GASG;AACH,wBAAgB,YAAY,CAAC,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,WAAW,CAAC,CAatE"}
|
|
@@ -0,0 +1,229 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The device self-check: one real exclusive scan of known numbers, run once per device before this package
|
|
3
|
+
* computes anything on it, so a device that returns wrong numbers is refused instead of believed.
|
|
4
|
+
*
|
|
5
|
+
* WHY IT EXISTS. On the Windows host lane -- Dawn's D3D12 backend over the Microsoft Basic Render Driver, the
|
|
6
|
+
* software renderer built into Windows -- every exclusive scan of more than one workgroup came back wrong: a
|
|
7
|
+
* block total of 1 where 256 belonged, or a second block nothing wrote at all, differing between two runs of
|
|
8
|
+
* identical code in one job. Everything built on the scan was wrong with it (the histogram, the radix sort, the
|
|
9
|
+
* grid build and every layout above them, eighteen test files), while every single-block scan and every earlier
|
|
10
|
+
* primitive stayed right. Three shader repairs failed; copying Microsoft's current redistributable renderer
|
|
11
|
+
* beside the runner's Node executable made all of it pass untouched. The defect is the driver's, and the danger
|
|
12
|
+
* to a caller is not a crash but silence: a graph laid out from wrong numbers with no error anywhere.
|
|
13
|
+
*
|
|
14
|
+
* WHY IT SCANS RATHER THAN PROBING A CONSTRUCT. An earlier hand-written probe matrix of workgroup constructs
|
|
15
|
+
* (test/primitives/workgroup-id-probe.test.ts) was measured PASSING on that renderer in the same job in which the
|
|
16
|
+
* real scan returned the wrong answer, so a copy of the shader's shape is not evidence about the shader. This
|
|
17
|
+
* check therefore drives the shipped `prepareScan` through the shipped composer and pipeline cache: it tests the
|
|
18
|
+
* code that runs, and it cannot drift away from it. One scan covers both recorded failures -- a value crossing
|
|
19
|
+
* `workgroupBarrier` inside a block, and a block total crossing from one dispatch of a compute pass to the next
|
|
20
|
+
* dispatch that reads it, which is the shape of every driver in this package.
|
|
21
|
+
*
|
|
22
|
+
* WHY IT REFUSES RATHER THAN ROUTING AROUND THE DEFECT. See docs/decisions/device-self-check.md: a barrier-free second
|
|
23
|
+
* implementation was designed and costed, and rejected because it would ship unverified on the only platform it
|
|
24
|
+
* exists for.
|
|
25
|
+
*
|
|
26
|
+
* WHERE IT RUNS. Lazily, at the first compute entry point a caller reaches, memoised per GPUDevice: the
|
|
27
|
+
* algorithms (degree, connectedComponents, the power-iteration family) and calibrateLayout await it on entry, and
|
|
28
|
+
* a layout simulation awaits it in the compile-and-bind promise `load()` starts -- the promise every batch and
|
|
29
|
+
* every debug run already awaits before it may submit. So a caller is covered whether the context was created,
|
|
30
|
+
* adopted through `create({ device })` or adopted through `GpuContext.from`, and a simulation refuses before its
|
|
31
|
+
* first iteration without the check sitting on the per-batch path, where an extra await would move the moment a
|
|
32
|
+
* submission becomes visible to a step() issued in the same tick and so change how the frame loop coalesces.
|
|
33
|
+
* It deliberately does NOT run in GpuContext.create:
|
|
34
|
+
* a context that only compiles -- Dawn's null backend, which computes nothing by design -- must stay usable, and
|
|
35
|
+
* `src/context.ts` may not import a primitive (the layer rule of spec 3.2).
|
|
36
|
+
*/
|
|
37
|
+
import { WebGpuGraphError } from "../errors.js";
|
|
38
|
+
import { UniformRing } from "../kernel/uniform-ring.js";
|
|
39
|
+
import { prepareScan } from "./scan.js";
|
|
40
|
+
/**
|
|
41
|
+
* The word written into every output slot before the dispatch, so a word NOTHING wrote is distinguishable from
|
|
42
|
+
* a word written wrongly. The Windows lane returned this value from the second block, which is how the failure
|
|
43
|
+
* was read as "the block was never written" rather than "the block was miscomputed".
|
|
44
|
+
*/
|
|
45
|
+
const POISON = 0xdeadbeef;
|
|
46
|
+
/** Full workgroups the check scans; one partial workgroup of a single word follows them. */
|
|
47
|
+
const CHECK_BLOCKS = 32;
|
|
48
|
+
/** Params slots the scan's levels need (two levels of block scan plus one add-back, with room to spare). */
|
|
49
|
+
const RING_SLOTS = 8;
|
|
50
|
+
/** The settled check per device: the one work a second caller never repeats. A rejection is dropped, so a check that failed to RUN is retried. */
|
|
51
|
+
const checked = new WeakMap();
|
|
52
|
+
/**
|
|
53
|
+
* The input word at `i`: 1, 2, 3, ... so no two workgroups have the same block total (all-ones would give every
|
|
54
|
+
* block the same one, and a block total stored at the wrong index would still read correct -- which is exactly
|
|
55
|
+
* the Windows symptom) and every output word is a different number.
|
|
56
|
+
* @param i - the word index
|
|
57
|
+
* @returns the input value
|
|
58
|
+
*/
|
|
59
|
+
function inputAt(i) {
|
|
60
|
+
return i + 1;
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* The verdict: the first output word or total that disagrees with the arithmetic answer, or null when nothing
|
|
64
|
+
* does. Pure, so test/primitives/verify.test.ts can drive it past a fabricated wrong result and exercise the
|
|
65
|
+
* refusal without a broken device.
|
|
66
|
+
* @param words - the `count` output words read back from the device
|
|
67
|
+
* @param total - the total word read back from the device
|
|
68
|
+
* @param count - the words scanned
|
|
69
|
+
* @returns the first disagreement, or null
|
|
70
|
+
* @internal
|
|
71
|
+
*/
|
|
72
|
+
export function checkScanWords(words, total, count) {
|
|
73
|
+
let running = 0;
|
|
74
|
+
for (let i = 0; i < count; i++) {
|
|
75
|
+
const got = words[i];
|
|
76
|
+
if (got !== running) {
|
|
77
|
+
return { where: `out[${String(i)}]`, expected: running, actual: got, poison: got === POISON };
|
|
78
|
+
}
|
|
79
|
+
// u32 addition wraps in WGSL, so the host oracle wraps too: at WORKGROUP_SIZE 256 the total cannot
|
|
80
|
+
// reach 2^32, but a false refusal would deny every device on earth, so it is not left to that constant
|
|
81
|
+
running = (running + inputAt(i)) >>> 0;
|
|
82
|
+
}
|
|
83
|
+
if (total !== running) {
|
|
84
|
+
return { where: "total", expected: running, actual: total, poison: total === POISON };
|
|
85
|
+
}
|
|
86
|
+
return null;
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Binds a whole scratch buffer.
|
|
90
|
+
* @param buffer - the buffer
|
|
91
|
+
* @param size - the bytes bound
|
|
92
|
+
* @returns the binding
|
|
93
|
+
*/
|
|
94
|
+
function whole(buffer, size) {
|
|
95
|
+
return { buffer, offset: 0, size, window: null };
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Runs the check once: one scan of `CHECK_BLOCKS * workgroupSize + 1` words recorded into one compute pass, one
|
|
99
|
+
* submit, the output and the total read back and verified on the host.
|
|
100
|
+
*
|
|
101
|
+
* It never throws for a wrong ANSWER -- that is the returned record's job. A failure of the machinery (a lost
|
|
102
|
+
* device, a validation error, out of memory) propagates with its own code, so "the driver computes incorrectly"
|
|
103
|
+
* is never said about a device that merely died.
|
|
104
|
+
* @param ctx - the context to check
|
|
105
|
+
* @returns what the check found
|
|
106
|
+
*/
|
|
107
|
+
async function runCheck(ctx) {
|
|
108
|
+
const started = performance.now();
|
|
109
|
+
const wg = ctx.workgroupSize;
|
|
110
|
+
const count = CHECK_BLOCKS * wg + 1;
|
|
111
|
+
const bytes = 4 * count;
|
|
112
|
+
const lease = ctx.pool.lease();
|
|
113
|
+
const ring = new UniformRing(ctx.device, ctx.allocator, RING_SLOTS, "device-check/ring");
|
|
114
|
+
try {
|
|
115
|
+
const scope = {
|
|
116
|
+
device: ctx.device,
|
|
117
|
+
caps: ctx.caps,
|
|
118
|
+
pipelines: ctx.pipelines,
|
|
119
|
+
pool: ctx.pool,
|
|
120
|
+
workgroupSize: wg,
|
|
121
|
+
scratch: (byteLength, label) => lease.storage(byteLength, `device-check/${label}`),
|
|
122
|
+
params(block, values) {
|
|
123
|
+
const slot = ring.reserve(1);
|
|
124
|
+
ring.write(slot, block, values);
|
|
125
|
+
return { binding: ring.binding(block), offset: ring.offsetOf(slot) };
|
|
126
|
+
},
|
|
127
|
+
};
|
|
128
|
+
const planner = await prepareScan(scope);
|
|
129
|
+
const src = lease.storage(bytes, "device-check/src");
|
|
130
|
+
const out = lease.storage(bytes, "device-check/out");
|
|
131
|
+
const input = new Uint32Array(count);
|
|
132
|
+
for (let i = 0; i < count; i++) {
|
|
133
|
+
input[i] = inputAt(i);
|
|
134
|
+
}
|
|
135
|
+
ctx.device.queue.writeBuffer(src, 0, input);
|
|
136
|
+
ctx.device.queue.writeBuffer(out, 0, new Uint32Array(count).fill(POISON));
|
|
137
|
+
const encoder = ctx.device.createCommandEncoder({ label: "device-check" });
|
|
138
|
+
const pass = encoder.beginComputePass({ label: "device-check" });
|
|
139
|
+
const total = planner.record(pass, whole(src, bytes), count, whole(out, bytes));
|
|
140
|
+
pass.end();
|
|
141
|
+
ring.flush();
|
|
142
|
+
ctx.device.queue.submit([encoder.finish()]);
|
|
143
|
+
const words = new Uint32Array(await ctx.readback.read(out, bytes));
|
|
144
|
+
const totalWord = new Uint32Array(await ctx.readback.read(total.binding.buffer, 4, undefined, total.binding.offset + 4 * total.index));
|
|
145
|
+
const mismatch = checkScanWords(words, totalWord[0], count);
|
|
146
|
+
return {
|
|
147
|
+
check: "exclusive-scan",
|
|
148
|
+
ok: mismatch === null,
|
|
149
|
+
workgroupSize: wg,
|
|
150
|
+
count,
|
|
151
|
+
blocks: CHECK_BLOCKS,
|
|
152
|
+
ms: performance.now() - started,
|
|
153
|
+
vendor: ctx.caps.vendor,
|
|
154
|
+
architecture: ctx.caps.architecture,
|
|
155
|
+
description: ctx.caps.description,
|
|
156
|
+
mismatch,
|
|
157
|
+
};
|
|
158
|
+
}
|
|
159
|
+
finally {
|
|
160
|
+
ring.destroy();
|
|
161
|
+
lease.release();
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
/**
|
|
165
|
+
* What this device computed when it was asked for an answer this package already knows, run once per device and
|
|
166
|
+
* remembered. A caller may await it before committing work to a context; every compute entry point of the
|
|
167
|
+
* package awaits it too, so the cost is paid once whoever asks first.
|
|
168
|
+
*
|
|
169
|
+
* It reports rather than throws, so a caller can ask a device a question without having to catch the answer. The
|
|
170
|
+
* entry points use `assertDeviceComputes`, which turns a failing report into E_DEVICE_INCORRECT.
|
|
171
|
+
* @param ctx - the context whose device is checked
|
|
172
|
+
* @returns the capability record; `ok` false means this device returns wrong numbers
|
|
173
|
+
*/
|
|
174
|
+
export function verifyDevice(ctx) {
|
|
175
|
+
const cached = checked.get(ctx.device);
|
|
176
|
+
if (cached !== undefined) {
|
|
177
|
+
return cached;
|
|
178
|
+
}
|
|
179
|
+
const running = runCheck(ctx).catch((err) => {
|
|
180
|
+
// only a settled verdict is worth keeping: a check that could not RUN (a lost device, a transient
|
|
181
|
+
// out-of-memory) must not answer for the device forever
|
|
182
|
+
checked.delete(ctx.device);
|
|
183
|
+
throw err;
|
|
184
|
+
});
|
|
185
|
+
checked.set(ctx.device, running);
|
|
186
|
+
return running;
|
|
187
|
+
}
|
|
188
|
+
/**
|
|
189
|
+
* The guard every compute entry point awaits: resolves on a device that computed the check correctly, throws
|
|
190
|
+
* E_DEVICE_INCORRECT on one that did not, carrying the first wrong word, what was required there, and the
|
|
191
|
+
* adapter strings that separate a broken driver from a fixed one.
|
|
192
|
+
* @param ctx - the context about to be computed on
|
|
193
|
+
* @internal
|
|
194
|
+
*/
|
|
195
|
+
export async function assertDeviceComputes(ctx) {
|
|
196
|
+
const check = await verifyDevice(ctx);
|
|
197
|
+
const { mismatch } = check;
|
|
198
|
+
if (mismatch === null) {
|
|
199
|
+
return;
|
|
200
|
+
}
|
|
201
|
+
const adapter = {
|
|
202
|
+
vendor: check.vendor,
|
|
203
|
+
architecture: check.architecture,
|
|
204
|
+
device: ctx.caps.device,
|
|
205
|
+
description: check.description,
|
|
206
|
+
};
|
|
207
|
+
const hint = check.architecture === "warp"
|
|
208
|
+
? "this is the Microsoft Basic Render Driver; the Microsoft.Direct3D.WARP redistributable (1.0.21 or newer) beside the host executable computes it correctly"
|
|
209
|
+
: undefined;
|
|
210
|
+
const observed = mismatch.poison
|
|
211
|
+
? `${mismatch.where} was never written (the ${String(POISON)} the check wrote beforehand survived the dispatch)`
|
|
212
|
+
: `${mismatch.where} came back as ${String(mismatch.actual)} where ${String(mismatch.expected)} was required`;
|
|
213
|
+
const message = `this device computes multi-workgroup shaders incorrectly: an exclusive scan of ${String(check.count)} ` +
|
|
214
|
+
`known numbers is wrong -- ${observed}. Refusing to run: every number this package computed here would ` +
|
|
215
|
+
`be unreliable. adapter: ${adapter.vendor}/${adapter.architecture} "${adapter.description}"`;
|
|
216
|
+
throw new WebGpuGraphError("E_DEVICE_INCORRECT", hint === undefined ? message : `${message}. ${hint}`, {
|
|
217
|
+
check: check.check,
|
|
218
|
+
where: mismatch.where,
|
|
219
|
+
expected: mismatch.expected,
|
|
220
|
+
actual: mismatch.actual,
|
|
221
|
+
poison: mismatch.poison,
|
|
222
|
+
count: check.count,
|
|
223
|
+
blocks: check.blocks,
|
|
224
|
+
workgroupSize: check.workgroupSize,
|
|
225
|
+
adapter,
|
|
226
|
+
...(hint === undefined ? {} : { hint }),
|
|
227
|
+
});
|
|
228
|
+
}
|
|
229
|
+
//# sourceMappingURL=verify.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"verify.js","sourceRoot":"","sources":["../../../src/primitives/verify.ts"],"names":[],"mappings":"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"}
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
* as a type, so every layer may `import type` from it without a value edge (the src/types zone of the
|
|
4
4
|
* package eslint config). P0-T3 wrote AdapterInfoLike and AdapterSummary; P1-T1 completes the file.
|
|
5
5
|
*/
|
|
6
|
+
import type { GpuContext } from "../context.js";
|
|
6
7
|
import type { WebGpuGraphError } from "../errors.js";
|
|
7
8
|
/** The limits `"raise"` takes from the adapter (spec 2.2); maxComputeWorkgroupsPerDimension is deliberately absent. */
|
|
8
9
|
export type RaisableLimit = "maxBufferSize" | "maxStorageBufferBindingSize" | "maxStorageBuffersPerShaderStage" | "maxComputeWorkgroupStorageSize" | "maxComputeInvocationsPerWorkgroup" | "maxComputeWorkgroupSizeX";
|
|
@@ -111,4 +112,56 @@ export interface PlanCaps {
|
|
|
111
112
|
readonly subgroupMaxSize: number;
|
|
112
113
|
readonly software: boolean;
|
|
113
114
|
}
|
|
115
|
+
/**
|
|
116
|
+
* The context the device self-check runs on. `src/primitives/**` may not name GpuContext (the layer rule of
|
|
117
|
+
* spec 3.2), and this file may, so the alias is how src/primitives/verify.ts types its argument. It is
|
|
118
|
+
* GpuContext and nothing else: pass the context you were going to compute on.
|
|
119
|
+
*/
|
|
120
|
+
export type CheckedContext = GpuContext;
|
|
121
|
+
/**
|
|
122
|
+
* The first word a device got wrong in the self-check. `poison` is true when the word still held the
|
|
123
|
+
* 0xdeadbeef the check wrote before the dispatch, which means NOTHING wrote it -- a different failure from a
|
|
124
|
+
* word written with the wrong value, and the distinction that made the Windows diagnosis possible.
|
|
125
|
+
*/
|
|
126
|
+
export interface DeviceCheckMismatch {
|
|
127
|
+
/** Where it was found: `out[<index>]`, or `total`. */
|
|
128
|
+
readonly where: string;
|
|
129
|
+
/** The value arithmetic requires there. */
|
|
130
|
+
readonly expected: number;
|
|
131
|
+
/** The value the device returned. */
|
|
132
|
+
readonly actual: number;
|
|
133
|
+
/** True when `actual` is the poison word the check wrote beforehand: nothing wrote this word. */
|
|
134
|
+
readonly poison: boolean;
|
|
135
|
+
}
|
|
136
|
+
/**
|
|
137
|
+
* What one device self-check found (spec 3.3): the capability record a caller may read BEFORE it commits work
|
|
138
|
+
* to a device, through `verifyDevice`. `mismatch === null` (equivalently `ok`) means every one of `count`
|
|
139
|
+
* output words and the total matched the arithmetic answer; a non-null `mismatch` is the device returning
|
|
140
|
+
* wrong numbers, which every compute entry point of this package turns into E_DEVICE_INCORRECT.
|
|
141
|
+
*
|
|
142
|
+
* It reports one property -- that values crossing a workgroup barrier and block totals crossing dispatches of
|
|
143
|
+
* one compute pass survive -- and is therefore a refusal mechanism, not a certificate of correctness.
|
|
144
|
+
*/
|
|
145
|
+
export interface DeviceCheck {
|
|
146
|
+
/** The check that ran; one today, named so a second can be added without changing the shape. */
|
|
147
|
+
readonly check: "exclusive-scan";
|
|
148
|
+
/** True when nothing disagreed. */
|
|
149
|
+
readonly ok: boolean;
|
|
150
|
+
/** The device's workgroup size (spec 5.1). */
|
|
151
|
+
readonly workgroupSize: number;
|
|
152
|
+
/** The words scanned: `blocks * workgroupSize + 1`, so the last workgroup is a partial one. */
|
|
153
|
+
readonly count: number;
|
|
154
|
+
/** The full workgroups of the scan (one partial one follows). */
|
|
155
|
+
readonly blocks: number;
|
|
156
|
+
/** Wall time of this check in milliseconds, pipeline compile included on the first call. */
|
|
157
|
+
readonly ms: number;
|
|
158
|
+
/** caps.vendor of the device that ran it. */
|
|
159
|
+
readonly vendor: string;
|
|
160
|
+
/** caps.architecture of the device that ran it. */
|
|
161
|
+
readonly architecture: string;
|
|
162
|
+
/** caps.description: the string that separates a broken driver from a fixed one. */
|
|
163
|
+
readonly description: string;
|
|
164
|
+
/** The first disagreement, or null when there was none. */
|
|
165
|
+
readonly mismatch: DeviceCheckMismatch | null;
|
|
166
|
+
}
|
|
114
167
|
//# sourceMappingURL=context.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../../../src/types/context.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../../../src/types/context.ts"],"names":[],"mappings":"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"}
|
|
@@ -124,4 +124,24 @@ export interface ResolvedLayoutTuning {
|
|
|
124
124
|
readonly extentFactor: number;
|
|
125
125
|
readonly compat: "paper" | "networkx";
|
|
126
126
|
}
|
|
127
|
+
/** Spec 2.2 CalibrateOptions, verbatim: the probe sizes of calibrateLayout (default 8k / 16k / 32k / 65k). */
|
|
128
|
+
export interface CalibrateOptions {
|
|
129
|
+
readonly sizes?: readonly number[] | undefined;
|
|
130
|
+
}
|
|
131
|
+
/**
|
|
132
|
+
* Spec 2.2 GpuCalibration, verbatim: the per-size ms per iteration of both repulsion tiers on the actual device,
|
|
133
|
+
* `pairsPerSecond` of the exact tier at the largest probed size, `suggestedExactMaxNodes` by the spec 7.8 rule
|
|
134
|
+
* (the largest probed n with exactMs(n) <= min(4 ms, gridMs(n)), rounded down to a power of two; when NO probed size
|
|
135
|
+
* qualifies -- the grid tier faster at every probe, or every probe over the budget -- the largest power of two strictly
|
|
136
|
+
* below the smallest probe, so the exact tier runs at no probed size and a value below floorPow2(min(sizes)) tells the
|
|
137
|
+
* caller the rule found nothing in the range: src/layouts/calibrate.ts) and the wall time of the whole call (pipeline
|
|
138
|
+
* compilation included on the first call).
|
|
139
|
+
*/
|
|
140
|
+
export interface GpuCalibration {
|
|
141
|
+
readonly pairsPerSecond: number;
|
|
142
|
+
readonly exactMsPerIter: Readonly<Record<number, number>>;
|
|
143
|
+
readonly gridMsPerIter: Readonly<Record<number, number>>;
|
|
144
|
+
readonly suggestedExactMaxNodes: number;
|
|
145
|
+
readonly firstCallMs: number;
|
|
146
|
+
}
|
|
127
147
|
//# sourceMappingURL=layout.d.ts.map
|