graphwise 1.9.0 → 1.10.0
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/dist/async/index.cjs +98 -1
- package/dist/async/index.cjs.map +1 -0
- package/dist/async/index.d.ts +1 -0
- package/dist/async/index.d.ts.map +1 -1
- package/dist/async/index.js +96 -2
- package/dist/async/index.js.map +1 -0
- package/dist/async/ops.d.ts +2 -0
- package/dist/async/ops.d.ts.map +1 -1
- package/dist/async/protocol.d.ts +14 -0
- package/dist/async/protocol.d.ts.map +1 -1
- package/dist/async/runner-batched.d.ts +21 -0
- package/dist/async/runner-batched.d.ts.map +1 -0
- package/dist/async/runner-batched.unit.test.d.ts +2 -0
- package/dist/async/runner-batched.unit.test.d.ts.map +1 -0
- package/dist/async/runners.d.ts.map +1 -1
- package/dist/expansion/base-core.d.ts.map +1 -1
- package/dist/expansion/fuse.d.ts +24 -1
- package/dist/expansion/fuse.d.ts.map +1 -1
- package/dist/expansion/index.cjs +9 -1
- package/dist/expansion/index.js +2 -2
- package/dist/expansion/lace.d.ts +23 -2
- package/dist/expansion/lace.d.ts.map +1 -1
- package/dist/expansion/priority-helpers.d.ts +20 -1
- package/dist/expansion/priority-helpers.d.ts.map +1 -1
- package/dist/expansion/sift.d.ts +24 -1
- package/dist/expansion/sift.d.ts.map +1 -1
- package/dist/expansion/types.d.ts +30 -0
- package/dist/expansion/types.d.ts.map +1 -1
- package/dist/{expansion-DaTroIyv.cjs → expansion--UuRowv-.cjs} +267 -4
- package/dist/expansion--UuRowv-.cjs.map +1 -0
- package/dist/{expansion-ClDhlMK8.js → expansion-CZLNK6Pr.js} +220 -5
- package/dist/expansion-CZLNK6Pr.js.map +1 -0
- package/dist/gpu/csr-graph.d.ts +68 -0
- package/dist/gpu/csr-graph.d.ts.map +1 -0
- package/dist/gpu/csr-graph.unit.test.d.ts +2 -0
- package/dist/gpu/csr-graph.unit.test.d.ts.map +1 -0
- package/dist/gpu/index.cjs +220 -15
- package/dist/gpu/index.cjs.map +1 -0
- package/dist/gpu/index.d.ts +1 -0
- package/dist/gpu/index.d.ts.map +1 -1
- package/dist/gpu/index.js +204 -2
- package/dist/gpu/index.js.map +1 -0
- package/dist/gpu/kernels/adamic-adar/kernel.d.ts +39 -0
- package/dist/gpu/kernels/adamic-adar/kernel.d.ts.map +1 -0
- package/dist/gpu/kernels/intersection/kernel.d.ts +50 -0
- package/dist/gpu/kernels/intersection/kernel.d.ts.map +1 -0
- package/dist/gpu/kernels/intersection/logic.d.ts +87 -0
- package/dist/gpu/kernels/intersection/logic.d.ts.map +1 -0
- package/dist/gpu/kernels/intersection/logic.unit.test.d.ts +2 -0
- package/dist/gpu/kernels/intersection/logic.unit.test.d.ts.map +1 -0
- package/dist/gpu/kernels/kmeans/index.d.ts +6 -0
- package/dist/gpu/kernels/kmeans/index.d.ts.map +1 -0
- package/dist/gpu/kernels/kmeans/kernel.d.ts +34 -0
- package/dist/gpu/kernels/kmeans/kernel.d.ts.map +1 -0
- package/dist/gpu/kernels/kmeans/logic.d.ts +111 -0
- package/dist/gpu/kernels/kmeans/logic.d.ts.map +1 -0
- package/dist/gpu/kernels/kmeans/logic.unit.test.d.ts +5 -0
- package/dist/gpu/kernels/kmeans/logic.unit.test.d.ts.map +1 -0
- package/dist/gpu/operations.d.ts +52 -0
- package/dist/gpu/operations.d.ts.map +1 -1
- package/dist/index/index.cjs +38 -19
- package/dist/index/index.js +10 -8
- package/dist/{jaccard-Bys9_dGW.cjs → jaccard-Bdw4B0i4.cjs} +1 -1
- package/dist/{jaccard-Bys9_dGW.cjs.map → jaccard-Bdw4B0i4.cjs.map} +1 -1
- package/dist/{jaccard-3rCdilwm.js → jaccard-BwC_NuQu.js} +1 -1
- package/dist/{jaccard-3rCdilwm.js.map → jaccard-BwC_NuQu.js.map} +1 -1
- package/dist/kernel-2oH4Cn32.cjs +1001 -0
- package/dist/kernel-2oH4Cn32.cjs.map +1 -0
- package/dist/kernel-6deK9fh1.js +724 -0
- package/dist/kernel-6deK9fh1.js.map +1 -0
- package/dist/kernel-CXeGBH3s.cjs +467 -0
- package/dist/kernel-CXeGBH3s.cjs.map +1 -0
- package/dist/kernel-CigCjrts.js +467 -0
- package/dist/kernel-CigCjrts.js.map +1 -0
- package/dist/kernel-CvnRsF7E.js +1001 -0
- package/dist/kernel-CvnRsF7E.js.map +1 -0
- package/dist/kernel-DukrXtVb.cjs +724 -0
- package/dist/kernel-DukrXtVb.cjs.map +1 -0
- package/dist/{kmeans-B8x9D1kt.cjs → kmeans-CZ7tJFYw.cjs} +1 -1
- package/dist/{kmeans-B8x9D1kt.cjs.map → kmeans-CZ7tJFYw.cjs.map} +1 -1
- package/dist/{kmeans-DKkL9rAN.js → kmeans-DLrlrp6i.js} +1 -1
- package/dist/{kmeans-DKkL9rAN.js.map → kmeans-DLrlrp6i.js.map} +1 -1
- package/dist/logic-Dbyfb_-7.cjs +289 -0
- package/dist/logic-Dbyfb_-7.cjs.map +1 -0
- package/dist/logic-DyBzRg1A.js +242 -0
- package/dist/logic-DyBzRg1A.js.map +1 -0
- package/dist/operations-D-RB67WP.cjs +2269 -0
- package/dist/operations-D-RB67WP.cjs.map +1 -0
- package/dist/operations-D9otVlIH.js +2198 -0
- package/dist/operations-D9otVlIH.js.map +1 -0
- package/dist/{ops-upIi6JIi.js → ops-D5xZr4fV.js} +60 -2
- package/dist/ops-D5xZr4fV.js.map +1 -0
- package/dist/{ops-djAsQQSh.cjs → ops-paa1Nvlf.cjs} +71 -1
- package/dist/ops-paa1Nvlf.cjs.map +1 -0
- package/dist/ranking/baselines/communicability.d.ts +12 -0
- package/dist/ranking/baselines/communicability.d.ts.map +1 -1
- package/dist/ranking/baselines/katz.d.ts +12 -0
- package/dist/ranking/baselines/katz.d.ts.map +1 -1
- package/dist/ranking/baselines/pagerank.d.ts +15 -0
- package/dist/ranking/baselines/pagerank.d.ts.map +1 -1
- package/dist/ranking/baselines/types.d.ts +3 -0
- package/dist/ranking/baselines/types.d.ts.map +1 -1
- package/dist/ranking/index.cjs +5 -2
- package/dist/ranking/index.js +3 -3
- package/dist/ranking/mi/index.cjs +1 -1
- package/dist/ranking/mi/index.js +1 -1
- package/dist/ranking/parse-gpu.d.ts +31 -0
- package/dist/ranking/parse-gpu.d.ts.map +1 -0
- package/dist/ranking/parse-gpu.unit.test.d.ts +5 -0
- package/dist/ranking/parse-gpu.unit.test.d.ts.map +1 -0
- package/dist/ranking/parse.d.ts.map +1 -1
- package/dist/{ranking-3ez5m67U.js → ranking-DOKDBcIR.js} +237 -11
- package/dist/ranking-DOKDBcIR.js.map +1 -0
- package/dist/{ranking-DVvajgUZ.cjs → ranking-pe5UaxKg.cjs} +254 -10
- package/dist/ranking-pe5UaxKg.cjs.map +1 -0
- package/dist/schemas/graph.d.ts +1 -1
- package/dist/seeds/grasp-gpu.d.ts +40 -0
- package/dist/seeds/grasp-gpu.d.ts.map +1 -0
- package/dist/seeds/index.cjs +1 -1
- package/dist/seeds/index.js +1 -1
- package/dist/{gpu-CHiCN0wa.js → typegpu-Dq5FfUB8.cjs} +16 -2041
- package/dist/typegpu-Dq5FfUB8.cjs.map +1 -0
- package/dist/{gpu-Y6owRVMi.cjs → typegpu-DwnJf28i.js} +2 -2127
- package/dist/typegpu-DwnJf28i.js.map +1 -0
- package/dist/utils/index.cjs +1 -1
- package/dist/utils/index.js +1 -1
- package/package.json +1 -1
- package/dist/expansion-ClDhlMK8.js.map +0 -1
- package/dist/expansion-DaTroIyv.cjs.map +0 -1
- package/dist/gpu-CHiCN0wa.js.map +0 -1
- package/dist/gpu-Y6owRVMi.cjs.map +0 -1
- package/dist/ops-djAsQQSh.cjs.map +0 -1
- package/dist/ops-upIi6JIi.js.map +0 -1
- package/dist/ranking-3ez5m67U.js.map +0 -1
- package/dist/ranking-DVvajgUZ.cjs.map +0 -1
|
@@ -10,17 +10,6 @@ var __exportAll$1 = (all, no_symbols) => {
|
|
|
10
10
|
return target;
|
|
11
11
|
};
|
|
12
12
|
//#endregion
|
|
13
|
-
//#region src/gpu/types.ts
|
|
14
|
-
/**
|
|
15
|
-
* Error thrown when GPU backend is requested but unavailable.
|
|
16
|
-
*/
|
|
17
|
-
var GPUNotAvailableError = class extends Error {
|
|
18
|
-
constructor(reason) {
|
|
19
|
-
super(`WebGPU not available: ${reason}`);
|
|
20
|
-
this.name = "GPUNotAvailableError";
|
|
21
|
-
}
|
|
22
|
-
};
|
|
23
|
-
//#endregion
|
|
24
13
|
//#region node_modules/.pnpm/typegpu@0.10.2/node_modules/typegpu/shared/env.js
|
|
25
14
|
/**
|
|
26
15
|
* This can be used to branch functionality between "dev" and "prod" modes, so that our
|
|
@@ -14909,2037 +14898,23 @@ assignInfixOperator(MatBase, "mul", Operator.star);
|
|
|
14909
14898
|
*/
|
|
14910
14899
|
var src_default = tgpu_exports;
|
|
14911
14900
|
//#endregion
|
|
14912
|
-
|
|
14913
|
-
|
|
14914
|
-
|
|
14915
|
-
|
|
14916
|
-
* CSR format is memory-efficient for sparse graphs and maps well to
|
|
14917
|
-
* GPU parallel operations. The format stores adjacency information
|
|
14918
|
-
* in three arrays: row offsets, column indices, and optional values.
|
|
14919
|
-
*/
|
|
14920
|
-
/**
|
|
14921
|
-
* Convert a ReadableGraph to CSR format.
|
|
14922
|
-
*
|
|
14923
|
-
* For undirected graphs, each edge is stored twice (once in each direction).
|
|
14924
|
-
* For directed graphs, edges are stored in the out-direction by default.
|
|
14925
|
-
*
|
|
14926
|
-
* @param graph - The graph to convert
|
|
14927
|
-
* @param direction - Edge direction to include (default: 'out' for directed, 'both' for undirected)
|
|
14928
|
-
* @returns CSR representation with index mapping
|
|
14929
|
-
*/
|
|
14930
|
-
function graphToCSR(graph, direction = graph.directed ? "out" : "both") {
|
|
14931
|
-
const nodeToIndex = /* @__PURE__ */ new Map();
|
|
14932
|
-
const indexToNode = [];
|
|
14933
|
-
for (const nodeId of graph.nodeIds()) {
|
|
14934
|
-
const index = indexToNode.length;
|
|
14935
|
-
nodeToIndex.set(nodeId, index);
|
|
14936
|
-
indexToNode.push(nodeId);
|
|
14937
|
-
}
|
|
14938
|
-
const nodeCount = indexToNode.length;
|
|
14939
|
-
const degrees = new Uint32Array(nodeCount);
|
|
14940
|
-
for (const nodeId of graph.nodeIds()) {
|
|
14941
|
-
const srcIndex = nodeToIndex.get(nodeId);
|
|
14942
|
-
if (srcIndex === void 0) continue;
|
|
14943
|
-
degrees[srcIndex] = graph.degree(nodeId, direction);
|
|
14944
|
-
}
|
|
14945
|
-
let totalEdges = 0;
|
|
14946
|
-
for (let i = 0; i < nodeCount; i++) totalEdges += degrees[i] ?? 0;
|
|
14947
|
-
const rowOffsets = new Uint32Array(nodeCount + 1);
|
|
14948
|
-
for (let i = 0; i < nodeCount; i++) rowOffsets[i + 1] = (rowOffsets[i] ?? 0) + (degrees[i] ?? 0);
|
|
14949
|
-
const colIndices = new Uint32Array(totalEdges);
|
|
14950
|
-
const values = new Float32Array(totalEdges);
|
|
14951
|
-
for (const nodeId of graph.nodeIds()) {
|
|
14952
|
-
const srcIndex = nodeToIndex.get(nodeId);
|
|
14953
|
-
if (srcIndex === void 0) continue;
|
|
14954
|
-
const baseOffset = rowOffsets[srcIndex] ?? 0;
|
|
14955
|
-
let localOffset = 0;
|
|
14956
|
-
for (const neighbourId of graph.neighbours(nodeId, direction)) {
|
|
14957
|
-
const dstIndex = nodeToIndex.get(neighbourId);
|
|
14958
|
-
if (dstIndex === void 0) continue;
|
|
14959
|
-
const edgeIdx = baseOffset + localOffset;
|
|
14960
|
-
colIndices[edgeIdx] = dstIndex;
|
|
14961
|
-
values[edgeIdx] = graph.getEdge(nodeId, neighbourId)?.weight ?? 1;
|
|
14962
|
-
localOffset++;
|
|
14963
|
-
}
|
|
14964
|
-
}
|
|
14965
|
-
return {
|
|
14966
|
-
csr: {
|
|
14967
|
-
rowOffsets,
|
|
14968
|
-
colIndices,
|
|
14969
|
-
values,
|
|
14970
|
-
nodeCount,
|
|
14971
|
-
edgeCount: graph.directed ? graph.edgeCount : graph.edgeCount * 2
|
|
14972
|
-
},
|
|
14973
|
-
indexMap: {
|
|
14974
|
-
nodeToIndex,
|
|
14975
|
-
indexToNode
|
|
14976
|
-
}
|
|
14977
|
-
};
|
|
14978
|
-
}
|
|
14979
|
-
/**
|
|
14980
|
-
* Create TypeGPU typed buffers from a CSR matrix.
|
|
14981
|
-
*
|
|
14982
|
-
* Uses TypeGPU's typed buffer API for type-safe GPU computation.
|
|
14983
|
-
* Buffers are created with storage usage for compute operations.
|
|
14984
|
-
*
|
|
14985
|
-
* @param root - TypeGPU root instance
|
|
14986
|
-
* @param csr - CSR matrix to upload
|
|
14987
|
-
* @returns Typed buffer group
|
|
14988
|
-
*
|
|
14989
|
-
* @example
|
|
14990
|
-
* ```typescript
|
|
14991
|
-
* import { initGPU, csrToTypedBuffers, graphToCSR } from "graphwise/gpu";
|
|
14992
|
-
*
|
|
14993
|
-
* const root = await initGPU();
|
|
14994
|
-
* const { csr } = graphToCSR(graph);
|
|
14995
|
-
* const buffers = csrToTypedBuffers(root, csr);
|
|
14996
|
-
*
|
|
14997
|
-
* // Read data back to CPU
|
|
14998
|
-
* const rowOffsets = await buffers.rowOffsets.read();
|
|
14999
|
-
* console.log(rowOffsets); // Uint32Array
|
|
15000
|
-
* ```
|
|
15001
|
-
*/
|
|
15002
|
-
function csrToTypedBuffers(root, csr) {
|
|
15003
|
-
const rowOffsetsArray = Array.from(csr.rowOffsets);
|
|
15004
|
-
const colIndicesArray = Array.from(csr.colIndices);
|
|
15005
|
-
const rowOffsetsBuffer = (globalThis.__TYPEGPU_AUTONAME__ ?? ((a) => a))(root.createBuffer(data_exports.arrayOf(data_exports.u32, csr.rowOffsets.length), rowOffsetsArray).$usage("storage"), "rowOffsetsBuffer");
|
|
15006
|
-
const colIndicesBuffer = (globalThis.__TYPEGPU_AUTONAME__ ?? ((a) => a))(root.createBuffer(data_exports.arrayOf(data_exports.u32, csr.colIndices.length), colIndicesArray).$usage("storage"), "colIndicesBuffer");
|
|
15007
|
-
if (csr.values !== void 0) {
|
|
15008
|
-
const valuesArray = Array.from(csr.values);
|
|
15009
|
-
return {
|
|
15010
|
-
rowOffsets: rowOffsetsBuffer,
|
|
15011
|
-
colIndices: colIndicesBuffer,
|
|
15012
|
-
values: (globalThis.__TYPEGPU_AUTONAME__ ?? ((a) => a))(root.createBuffer(data_exports.arrayOf(data_exports.f32, csr.values.length), valuesArray).$usage("storage"), "valuesBuffer"),
|
|
15013
|
-
nodeCount: csr.nodeCount,
|
|
15014
|
-
edgeCount: csr.edgeCount
|
|
15015
|
-
};
|
|
15016
|
-
}
|
|
15017
|
-
return {
|
|
15018
|
-
rowOffsets: rowOffsetsBuffer,
|
|
15019
|
-
colIndices: colIndicesBuffer,
|
|
15020
|
-
nodeCount: csr.nodeCount,
|
|
15021
|
-
edgeCount: csr.edgeCount
|
|
15022
|
-
};
|
|
15023
|
-
}
|
|
15024
|
-
//#endregion
|
|
15025
|
-
//#region src/gpu/detect.ts
|
|
15026
|
-
/**
|
|
15027
|
-
* Detect WebGPU availability in the current environment.
|
|
15028
|
-
*
|
|
15029
|
-
* Checks for:
|
|
15030
|
-
* - Browser: navigator.gpu
|
|
15031
|
-
* - Node.js: global GPU constructor (Node.js 21+ with --experimental-webgpu)
|
|
15032
|
-
* - Deno: global GPU constructor
|
|
15033
|
-
*
|
|
15034
|
-
* @returns Detection result with availability status and reason
|
|
15035
|
-
*/
|
|
15036
|
-
function detectWebGPU() {
|
|
15037
|
-
if (typeof navigator !== "undefined" && "gpu" in navigator) return { available: true };
|
|
15038
|
-
if (typeof globalThis !== "undefined" && "GPU" in globalThis) return { available: true };
|
|
15039
|
-
const reasons = [];
|
|
15040
|
-
if (typeof navigator === "undefined" && typeof globalThis === "undefined") reasons.push("no global scope detected");
|
|
15041
|
-
else if (typeof navigator !== "undefined" && !("gpu" in navigator)) reasons.push("navigator.gpu not present (browser may not support WebGPU)");
|
|
15042
|
-
else if (typeof globalThis !== "undefined" && !("GPU" in globalThis)) reasons.push("global GPU not present (Node.js requires v21+ with --experimental-webgpu flag)");
|
|
15043
|
-
return {
|
|
15044
|
-
available: false,
|
|
15045
|
-
reason: reasons.length > 0 ? reasons.join("; ") : "unknown environment"
|
|
15046
|
-
};
|
|
15047
|
-
}
|
|
15048
|
-
/**
|
|
15049
|
-
* Check if WebGPU is available (convenience function).
|
|
15050
|
-
*
|
|
15051
|
-
* @returns true if WebGPU is available, false otherwise
|
|
15052
|
-
*/
|
|
15053
|
-
function isWebGPUAvailable() {
|
|
15054
|
-
return detectWebGPU().available;
|
|
15055
|
-
}
|
|
15056
|
-
/**
|
|
15057
|
-
* Assert that WebGPU is available, throwing an error if not.
|
|
15058
|
-
*
|
|
15059
|
-
* @throws Error if WebGPU is not available
|
|
15060
|
-
*/
|
|
15061
|
-
function assertWebGPUAvailable() {
|
|
15062
|
-
const result = detectWebGPU();
|
|
15063
|
-
if (!result.available) throw new Error(`WebGPU required but not available: ${result.reason ?? "unknown reason"}`);
|
|
15064
|
-
}
|
|
15065
|
-
//#endregion
|
|
15066
|
-
//#region src/gpu/root.ts
|
|
15067
|
-
/**
|
|
15068
|
-
* TypeGPU root initialisation for graphwise GPU operations.
|
|
15069
|
-
*
|
|
15070
|
-
* Provides a simplified wrapper around TypeGPU's tgpu.init() for
|
|
15071
|
-
* GPU device acquisition and resource management.
|
|
15072
|
-
*
|
|
15073
|
-
* @module gpu/root
|
|
15074
|
-
*/
|
|
15075
|
-
/**
|
|
15076
|
-
* Initialise a TypeGPU root for GPU compute operations.
|
|
15077
|
-
*
|
|
15078
|
-
* This wraps tgpu.init() with WebGPU availability checking and
|
|
15079
|
-
* simplified options.
|
|
15080
|
-
*
|
|
15081
|
-
* @param options - Initialisation options
|
|
15082
|
-
* @returns Promise resolving to a TypeGPU root instance
|
|
15083
|
-
* @throws Error if WebGPU is unavailable or device request fails
|
|
15084
|
-
*
|
|
15085
|
-
* @example
|
|
15086
|
-
* ```typescript
|
|
15087
|
-
* import { initGPU } from "graphwise/gpu";
|
|
15088
|
-
*
|
|
15089
|
-
* const root = await initGPU();
|
|
15090
|
-
* // Use root for GPU operations...
|
|
15091
|
-
* root.destroy();
|
|
15092
|
-
* ```
|
|
15093
|
-
*/
|
|
15094
|
-
async function initGPU(options = {}) {
|
|
15095
|
-
const detection = detectWebGPU();
|
|
15096
|
-
if (!detection.available) throw new Error(`WebGPU unavailable: ${detection.reason ?? "unknown reason"}`);
|
|
15097
|
-
return await tgpu_exports.init({ adapter: options.powerPreference ? { powerPreference: options.powerPreference } : void 0 });
|
|
15098
|
-
}
|
|
15099
|
-
/**
|
|
15100
|
-
* Create a TypeGPU root from an existing GPU device.
|
|
15101
|
-
*
|
|
15102
|
-
* Use this when you already have a GPUDevice and want to wrap it
|
|
15103
|
-
* with TypeGPU functionality.
|
|
15104
|
-
*
|
|
15105
|
-
* @param device - Existing GPU device
|
|
15106
|
-
* @returns TypeGPU root instance
|
|
15107
|
-
*
|
|
15108
|
-
* @example
|
|
15109
|
-
* ```typescript
|
|
15110
|
-
* import { initGPUFromDevice } from "graphwise/gpu";
|
|
15111
|
-
*
|
|
15112
|
-
* const adapter = await navigator.gpu.requestAdapter();
|
|
15113
|
-
* const device = await adapter.requestDevice();
|
|
15114
|
-
* const root = initGPUFromDevice(device);
|
|
15115
|
-
* ```
|
|
15116
|
-
*/
|
|
15117
|
-
function initGPUFromDevice(device) {
|
|
15118
|
-
return tgpu_exports.initFromDevice({ device });
|
|
15119
|
-
}
|
|
15120
|
-
//#endregion
|
|
15121
|
-
//#region src/gpu/dispatch.ts
|
|
15122
|
-
/**
|
|
15123
|
-
* Backend selection and dispatch utilities for GPU compute operations.
|
|
15124
|
-
*
|
|
15125
|
-
* Provides the `withBackend` function that handles auto/gpu/cpu backend
|
|
15126
|
-
* selection with timing and fallback logic.
|
|
15127
|
-
*
|
|
15128
|
-
* @module gpu/dispatch
|
|
15129
|
-
*/
|
|
15130
|
-
/**
|
|
15131
|
-
* Execute a compute operation with automatic backend selection.
|
|
15132
|
-
*
|
|
15133
|
-
* @param options - Backend selection and cancellation options
|
|
15134
|
-
* @param cpuFn - CPU fallback implementation
|
|
15135
|
-
* @param gpuFn - GPU implementation (receives TypeGPU root)
|
|
15136
|
-
* @returns Compute result with backend used and timing
|
|
15137
|
-
*/
|
|
15138
|
-
async function withBackend(options, cpuFn, gpuFn) {
|
|
15139
|
-
const backend = options.backend ?? "auto";
|
|
15140
|
-
if (options.signal?.aborted === true) throw new DOMException("Operation aborted", "AbortError");
|
|
15141
|
-
if (backend === "cpu") {
|
|
15142
|
-
const start = performance.now();
|
|
15143
|
-
return {
|
|
15144
|
-
value: cpuFn(),
|
|
15145
|
-
backend: "cpu",
|
|
15146
|
-
elapsedMs: performance.now() - start
|
|
15147
|
-
};
|
|
15148
|
-
}
|
|
15149
|
-
if (backend === "gpu") {
|
|
15150
|
-
const detection = detectWebGPU();
|
|
15151
|
-
if (!detection.available) throw new GPUNotAvailableError(detection.reason ?? "Unknown reason");
|
|
15152
|
-
const root = options.root;
|
|
15153
|
-
if (root === void 0) throw new Error("GPU backend requires a GraphwiseGPURoot. Pass one via options.root or use backend: 'auto'.");
|
|
15154
|
-
const start = performance.now();
|
|
15155
|
-
return {
|
|
15156
|
-
value: await gpuFn(root),
|
|
15157
|
-
backend: "gpu",
|
|
15158
|
-
elapsedMs: performance.now() - start
|
|
15159
|
-
};
|
|
15160
|
-
}
|
|
15161
|
-
if (!detectWebGPU().available) {
|
|
15162
|
-
const start = performance.now();
|
|
15163
|
-
return {
|
|
15164
|
-
value: cpuFn(),
|
|
15165
|
-
backend: "cpu",
|
|
15166
|
-
elapsedMs: performance.now() - start
|
|
15167
|
-
};
|
|
15168
|
-
}
|
|
15169
|
-
const root = options.root;
|
|
15170
|
-
if (root === void 0) {
|
|
15171
|
-
const start = performance.now();
|
|
15172
|
-
return {
|
|
15173
|
-
value: cpuFn(),
|
|
15174
|
-
backend: "cpu",
|
|
15175
|
-
elapsedMs: performance.now() - start
|
|
15176
|
-
};
|
|
15177
|
-
}
|
|
15178
|
-
const start = performance.now();
|
|
15179
|
-
return {
|
|
15180
|
-
value: await gpuFn(root),
|
|
15181
|
-
backend: "gpu",
|
|
15182
|
-
elapsedMs: performance.now() - start
|
|
15183
|
-
};
|
|
15184
|
-
}
|
|
15185
|
-
//#endregion
|
|
15186
|
-
//#region src/gpu/kernels/spmv/kernel.ts
|
|
15187
|
-
/**
|
|
15188
|
-
* TypeGPU compute kernel for Sparse Matrix-Vector Multiplication (SpMV).
|
|
15189
|
-
*
|
|
15190
|
-
* Computes y = A * x where A is a sparse matrix in CSR format.
|
|
15191
|
-
* Uses TypeGPU's compute pipeline for parallel GPU execution.
|
|
15192
|
-
*
|
|
15193
|
-
* @module gpu/kernels/spmv/kernel
|
|
15194
|
-
*/
|
|
15195
|
-
/**
|
|
15196
|
-
* Bind group layout for SpMV kernel.
|
|
15197
|
-
*/
|
|
15198
|
-
var SpMVLayout = (globalThis.__TYPEGPU_AUTONAME__ ?? ((a) => a))(src_default.bindGroupLayout({
|
|
15199
|
-
rowOffsets: { storage: data_exports.arrayOf(data_exports.u32) },
|
|
15200
|
-
colIndices: { storage: data_exports.arrayOf(data_exports.u32) },
|
|
15201
|
-
values: { storage: data_exports.arrayOf(data_exports.f32) },
|
|
15202
|
-
x: { storage: data_exports.arrayOf(data_exports.f32) },
|
|
15203
|
-
y: {
|
|
15204
|
-
storage: data_exports.arrayOf(data_exports.f32),
|
|
15205
|
-
access: "mutable"
|
|
15206
|
-
},
|
|
15207
|
-
nodeCount: { uniform: data_exports.u32 },
|
|
15208
|
-
hasValues: { uniform: data_exports.u32 }
|
|
15209
|
-
}), "SpMVLayout");
|
|
15210
|
-
/**
|
|
15211
|
-
* SpMV compute pipeline: y[row] = sum(A[row,col] * x[col]).
|
|
15212
|
-
*
|
|
15213
|
-
* Each thread computes one row of the output vector using the CSR format:
|
|
15214
|
-
* - rowOffsets: start/end indices for each row
|
|
15215
|
-
* - colIndices: column index for each non-zero entry
|
|
15216
|
-
* - values: edge weights (optional, defaults to 1.0)
|
|
15217
|
-
*/
|
|
15218
|
-
var spmvPipeline = (($) => (globalThis.__TYPEGPU_META__ ??= /* @__PURE__ */ new WeakMap()).set($.f = ((row) => {
|
|
15219
|
-
"use gpu";
|
|
15220
|
-
const start = SpMVLayout.$.rowOffsets[row] ?? 0;
|
|
15221
|
-
const end = SpMVLayout.$.rowOffsets[__tsover_add(row, 1)] ?? 0;
|
|
15222
|
-
let sum = 0;
|
|
15223
|
-
for (let i = start; i < end; i = __tsover_add(i, 1)) {
|
|
15224
|
-
const col = SpMVLayout.$.colIndices[i] ?? 0;
|
|
15225
|
-
const weight = SpMVLayout.$.hasValues !== 0 ? SpMVLayout.$.values[i] ?? 1 : 1;
|
|
15226
|
-
sum = __tsover_add(sum, __tsover_mul(weight, SpMVLayout.$.x[col] ?? 0));
|
|
15227
|
-
}
|
|
15228
|
-
SpMVLayout.$.y[row] = sum;
|
|
15229
|
-
}), {
|
|
15230
|
-
v: 1,
|
|
15231
|
-
name: "spmvPipeline",
|
|
15232
|
-
ast: {
|
|
15233
|
-
"params": [{
|
|
15234
|
-
"type": "i",
|
|
15235
|
-
"name": "row"
|
|
15236
|
-
}],
|
|
15237
|
-
"body": [0, [
|
|
15238
|
-
[
|
|
15239
|
-
13,
|
|
15240
|
-
"start",
|
|
15241
|
-
[
|
|
15242
|
-
3,
|
|
15243
|
-
[
|
|
15244
|
-
8,
|
|
15245
|
-
[
|
|
15246
|
-
7,
|
|
15247
|
-
[
|
|
15248
|
-
7,
|
|
15249
|
-
"SpMVLayout",
|
|
15250
|
-
"$"
|
|
15251
|
-
],
|
|
15252
|
-
"rowOffsets"
|
|
15253
|
-
],
|
|
15254
|
-
"row"
|
|
15255
|
-
],
|
|
15256
|
-
"??",
|
|
15257
|
-
[5, "0"]
|
|
15258
|
-
]
|
|
15259
|
-
],
|
|
15260
|
-
[
|
|
15261
|
-
13,
|
|
15262
|
-
"end",
|
|
15263
|
-
[
|
|
15264
|
-
3,
|
|
15265
|
-
[
|
|
15266
|
-
8,
|
|
15267
|
-
[
|
|
15268
|
-
7,
|
|
15269
|
-
[
|
|
15270
|
-
7,
|
|
15271
|
-
"SpMVLayout",
|
|
15272
|
-
"$"
|
|
15273
|
-
],
|
|
15274
|
-
"rowOffsets"
|
|
15275
|
-
],
|
|
15276
|
-
[
|
|
15277
|
-
1,
|
|
15278
|
-
"row",
|
|
15279
|
-
"+",
|
|
15280
|
-
[5, "1"]
|
|
15281
|
-
]
|
|
15282
|
-
],
|
|
15283
|
-
"??",
|
|
15284
|
-
[5, "0"]
|
|
15285
|
-
]
|
|
15286
|
-
],
|
|
15287
|
-
[
|
|
15288
|
-
12,
|
|
15289
|
-
"sum",
|
|
15290
|
-
[5, "0"]
|
|
15291
|
-
],
|
|
15292
|
-
[
|
|
15293
|
-
14,
|
|
15294
|
-
[
|
|
15295
|
-
12,
|
|
15296
|
-
"i",
|
|
15297
|
-
"start"
|
|
15298
|
-
],
|
|
15299
|
-
[
|
|
15300
|
-
1,
|
|
15301
|
-
"i",
|
|
15302
|
-
"<",
|
|
15303
|
-
"end"
|
|
15304
|
-
],
|
|
15305
|
-
[
|
|
15306
|
-
2,
|
|
15307
|
-
"i",
|
|
15308
|
-
"=",
|
|
15309
|
-
[
|
|
15310
|
-
1,
|
|
15311
|
-
"i",
|
|
15312
|
-
"+",
|
|
15313
|
-
[5, "1"]
|
|
15314
|
-
]
|
|
15315
|
-
],
|
|
15316
|
-
[0, [
|
|
15317
|
-
[
|
|
15318
|
-
13,
|
|
15319
|
-
"col",
|
|
15320
|
-
[
|
|
15321
|
-
3,
|
|
15322
|
-
[
|
|
15323
|
-
8,
|
|
15324
|
-
[
|
|
15325
|
-
7,
|
|
15326
|
-
[
|
|
15327
|
-
7,
|
|
15328
|
-
"SpMVLayout",
|
|
15329
|
-
"$"
|
|
15330
|
-
],
|
|
15331
|
-
"colIndices"
|
|
15332
|
-
],
|
|
15333
|
-
"i"
|
|
15334
|
-
],
|
|
15335
|
-
"??",
|
|
15336
|
-
[5, "0"]
|
|
15337
|
-
]
|
|
15338
|
-
],
|
|
15339
|
-
[
|
|
15340
|
-
13,
|
|
15341
|
-
"weight",
|
|
15342
|
-
[
|
|
15343
|
-
105,
|
|
15344
|
-
[
|
|
15345
|
-
1,
|
|
15346
|
-
[
|
|
15347
|
-
7,
|
|
15348
|
-
[
|
|
15349
|
-
7,
|
|
15350
|
-
"SpMVLayout",
|
|
15351
|
-
"$"
|
|
15352
|
-
],
|
|
15353
|
-
"hasValues"
|
|
15354
|
-
],
|
|
15355
|
-
"!==",
|
|
15356
|
-
[5, "0"]
|
|
15357
|
-
],
|
|
15358
|
-
[
|
|
15359
|
-
3,
|
|
15360
|
-
[
|
|
15361
|
-
8,
|
|
15362
|
-
[
|
|
15363
|
-
7,
|
|
15364
|
-
[
|
|
15365
|
-
7,
|
|
15366
|
-
"SpMVLayout",
|
|
15367
|
-
"$"
|
|
15368
|
-
],
|
|
15369
|
-
"values"
|
|
15370
|
-
],
|
|
15371
|
-
"i"
|
|
15372
|
-
],
|
|
15373
|
-
"??",
|
|
15374
|
-
[5, "1"]
|
|
15375
|
-
],
|
|
15376
|
-
[5, "1"]
|
|
15377
|
-
]
|
|
15378
|
-
],
|
|
15379
|
-
[
|
|
15380
|
-
2,
|
|
15381
|
-
"sum",
|
|
15382
|
-
"=",
|
|
15383
|
-
[
|
|
15384
|
-
1,
|
|
15385
|
-
"sum",
|
|
15386
|
-
"+",
|
|
15387
|
-
[
|
|
15388
|
-
1,
|
|
15389
|
-
"weight",
|
|
15390
|
-
"*",
|
|
15391
|
-
[
|
|
15392
|
-
3,
|
|
15393
|
-
[
|
|
15394
|
-
8,
|
|
15395
|
-
[
|
|
15396
|
-
7,
|
|
15397
|
-
[
|
|
15398
|
-
7,
|
|
15399
|
-
"SpMVLayout",
|
|
15400
|
-
"$"
|
|
15401
|
-
],
|
|
15402
|
-
"x"
|
|
15403
|
-
],
|
|
15404
|
-
"col"
|
|
15405
|
-
],
|
|
15406
|
-
"??",
|
|
15407
|
-
[5, "0"]
|
|
15408
|
-
]
|
|
15409
|
-
]
|
|
15410
|
-
]
|
|
15411
|
-
]
|
|
15412
|
-
]]
|
|
15413
|
-
],
|
|
15414
|
-
[
|
|
15415
|
-
2,
|
|
15416
|
-
[
|
|
15417
|
-
8,
|
|
15418
|
-
[
|
|
15419
|
-
7,
|
|
15420
|
-
[
|
|
15421
|
-
7,
|
|
15422
|
-
"SpMVLayout",
|
|
15423
|
-
"$"
|
|
15424
|
-
],
|
|
15425
|
-
"y"
|
|
15426
|
-
],
|
|
15427
|
-
"row"
|
|
15428
|
-
],
|
|
15429
|
-
"=",
|
|
15430
|
-
"sum"
|
|
15431
|
-
]
|
|
15432
|
-
]],
|
|
15433
|
-
"externalNames": ["SpMVLayout"]
|
|
15434
|
-
},
|
|
15435
|
-
externals: () => ({ SpMVLayout })
|
|
15436
|
-
}) && $.f)({});
|
|
15437
|
-
/**
|
|
15438
|
-
* Dispatch SpMV on GPU.
|
|
15439
|
-
*
|
|
15440
|
-
* @param root - TypeGPU root instance
|
|
15441
|
-
* @param csrBuffers - CSR matrix as typed buffers
|
|
15442
|
-
* @param x - Input vector buffer
|
|
15443
|
-
* @param y - Output vector buffer (mutable)
|
|
15444
|
-
* @param nodeCount - Number of nodes/rows
|
|
15445
|
-
* @param hasValues - Whether edge weights are present
|
|
15446
|
-
*/
|
|
15447
|
-
function dispatchSpmv(root, csrBuffers, x, y, nodeCount, hasValues) {
|
|
15448
|
-
const pipeline = (globalThis.__TYPEGPU_AUTONAME__ ?? ((a) => a))(root.createGuardedComputePipeline(spmvPipeline), "pipeline");
|
|
15449
|
-
const valuesBuffer = csrBuffers.values ?? root.createBuffer(data_exports.arrayOf(data_exports.f32, csrBuffers.edgeCount), new Array(csrBuffers.edgeCount).fill(1)).$usage("storage");
|
|
15450
|
-
const nodeCountBuffer = (globalThis.__TYPEGPU_AUTONAME__ ?? ((a) => a))(root.createBuffer(data_exports.u32, nodeCount).$usage("uniform"), "nodeCountBuffer");
|
|
15451
|
-
const hasValuesBuffer = (globalThis.__TYPEGPU_AUTONAME__ ?? ((a) => a))(root.createBuffer(data_exports.u32, hasValues ? 1 : 0).$usage("uniform"), "hasValuesBuffer");
|
|
15452
|
-
const bindGroup = root.createBindGroup(SpMVLayout, {
|
|
15453
|
-
rowOffsets: csrBuffers.rowOffsets,
|
|
15454
|
-
colIndices: csrBuffers.colIndices,
|
|
15455
|
-
values: valuesBuffer,
|
|
15456
|
-
x,
|
|
15457
|
-
y,
|
|
15458
|
-
nodeCount: nodeCountBuffer,
|
|
15459
|
-
hasValues: hasValuesBuffer
|
|
15460
|
-
});
|
|
15461
|
-
pipeline.with(bindGroup).dispatchThreads(nodeCount);
|
|
15462
|
-
}
|
|
15463
|
-
//#endregion
|
|
15464
|
-
//#region src/gpu/kernels/pagerank/kernel.ts
|
|
15465
|
-
/**
|
|
15466
|
-
* TypeGPU compute kernel for PageRank power iteration.
|
|
15467
|
-
*
|
|
15468
|
-
* Computes one iteration of PageRank:
|
|
15469
|
-
* r(v) = (1 - d)/N + d * sum(r(u) / deg_out(u)) for u -> v
|
|
15470
|
-
*
|
|
15471
|
-
* Uses TypeGPU's compute pipeline for parallel GPU execution.
|
|
15472
|
-
*
|
|
15473
|
-
* @module gpu/kernels/pagerank/kernel
|
|
15474
|
-
*/
|
|
15475
|
-
/**
|
|
15476
|
-
* Bind group layout for PageRank kernel.
|
|
15477
|
-
*/
|
|
15478
|
-
var PageRankLayout = (globalThis.__TYPEGPU_AUTONAME__ ?? ((a) => a))(src_default.bindGroupLayout({
|
|
15479
|
-
rowOffsets: { storage: data_exports.arrayOf(data_exports.u32) },
|
|
15480
|
-
colIndices: { storage: data_exports.arrayOf(data_exports.u32) },
|
|
15481
|
-
ranks: { storage: data_exports.arrayOf(data_exports.f32) },
|
|
15482
|
-
outDegrees: { storage: data_exports.arrayOf(data_exports.u32) },
|
|
15483
|
-
newRanks: {
|
|
15484
|
-
storage: data_exports.arrayOf(data_exports.f32),
|
|
15485
|
-
access: "mutable"
|
|
15486
|
-
},
|
|
15487
|
-
nodeCount: { uniform: data_exports.u32 },
|
|
15488
|
-
damping: { uniform: data_exports.f32 }
|
|
15489
|
-
}), "PageRankLayout");
|
|
15490
|
-
/**
|
|
15491
|
-
* PageRank compute pipeline: one power iteration per dispatch.
|
|
15492
|
-
*
|
|
15493
|
-
* Each thread computes one node's new rank from incoming neighbours:
|
|
15494
|
-
* newRank[v] = (1 - damping) / N + damping * sum(rank[u] / outDegree[u])
|
|
15495
|
-
*/
|
|
15496
|
-
var pagerankPipeline = (($) => (globalThis.__TYPEGPU_META__ ??= /* @__PURE__ */ new WeakMap()).set($.f = ((node) => {
|
|
15497
|
-
"use gpu";
|
|
15498
|
-
const n = PageRankLayout.$.nodeCount ?? 0;
|
|
15499
|
-
const damp = PageRankLayout.$.damping ?? .85;
|
|
15500
|
-
const start = PageRankLayout.$.rowOffsets[node] ?? 0;
|
|
15501
|
-
const end = PageRankLayout.$.rowOffsets[__tsover_add(node, 1)] ?? 0;
|
|
15502
|
-
let contribution = 0;
|
|
15503
|
-
for (let i = start; i < end; i = __tsover_add(i, 1)) {
|
|
15504
|
-
const source = PageRankLayout.$.colIndices[i] ?? 0;
|
|
15505
|
-
const deg = PageRankLayout.$.outDegrees[source] ?? 0;
|
|
15506
|
-
if (deg > 0) {
|
|
15507
|
-
const rank = PageRankLayout.$.ranks[source] ?? 0;
|
|
15508
|
-
contribution = __tsover_add(contribution, __tsover_div(rank, deg));
|
|
15509
|
-
}
|
|
15510
|
-
}
|
|
15511
|
-
const teleport = __tsover_div(__tsover_sub(1, damp), n);
|
|
15512
|
-
PageRankLayout.$.newRanks[node] = __tsover_add(teleport, __tsover_mul(damp, contribution));
|
|
15513
|
-
}), {
|
|
15514
|
-
v: 1,
|
|
15515
|
-
name: "pagerankPipeline",
|
|
15516
|
-
ast: {
|
|
15517
|
-
"params": [{
|
|
15518
|
-
"type": "i",
|
|
15519
|
-
"name": "node"
|
|
15520
|
-
}],
|
|
15521
|
-
"body": [0, [
|
|
15522
|
-
[
|
|
15523
|
-
13,
|
|
15524
|
-
"n",
|
|
15525
|
-
[
|
|
15526
|
-
3,
|
|
15527
|
-
[
|
|
15528
|
-
7,
|
|
15529
|
-
[
|
|
15530
|
-
7,
|
|
15531
|
-
"PageRankLayout",
|
|
15532
|
-
"$"
|
|
15533
|
-
],
|
|
15534
|
-
"nodeCount"
|
|
15535
|
-
],
|
|
15536
|
-
"??",
|
|
15537
|
-
[5, "0"]
|
|
15538
|
-
]
|
|
15539
|
-
],
|
|
15540
|
-
[
|
|
15541
|
-
13,
|
|
15542
|
-
"damp",
|
|
15543
|
-
[
|
|
15544
|
-
3,
|
|
15545
|
-
[
|
|
15546
|
-
7,
|
|
15547
|
-
[
|
|
15548
|
-
7,
|
|
15549
|
-
"PageRankLayout",
|
|
15550
|
-
"$"
|
|
15551
|
-
],
|
|
15552
|
-
"damping"
|
|
15553
|
-
],
|
|
15554
|
-
"??",
|
|
15555
|
-
[5, "0.85"]
|
|
15556
|
-
]
|
|
15557
|
-
],
|
|
15558
|
-
[
|
|
15559
|
-
13,
|
|
15560
|
-
"start",
|
|
15561
|
-
[
|
|
15562
|
-
3,
|
|
15563
|
-
[
|
|
15564
|
-
8,
|
|
15565
|
-
[
|
|
15566
|
-
7,
|
|
15567
|
-
[
|
|
15568
|
-
7,
|
|
15569
|
-
"PageRankLayout",
|
|
15570
|
-
"$"
|
|
15571
|
-
],
|
|
15572
|
-
"rowOffsets"
|
|
15573
|
-
],
|
|
15574
|
-
"node"
|
|
15575
|
-
],
|
|
15576
|
-
"??",
|
|
15577
|
-
[5, "0"]
|
|
15578
|
-
]
|
|
15579
|
-
],
|
|
15580
|
-
[
|
|
15581
|
-
13,
|
|
15582
|
-
"end",
|
|
15583
|
-
[
|
|
15584
|
-
3,
|
|
15585
|
-
[
|
|
15586
|
-
8,
|
|
15587
|
-
[
|
|
15588
|
-
7,
|
|
15589
|
-
[
|
|
15590
|
-
7,
|
|
15591
|
-
"PageRankLayout",
|
|
15592
|
-
"$"
|
|
15593
|
-
],
|
|
15594
|
-
"rowOffsets"
|
|
15595
|
-
],
|
|
15596
|
-
[
|
|
15597
|
-
1,
|
|
15598
|
-
"node",
|
|
15599
|
-
"+",
|
|
15600
|
-
[5, "1"]
|
|
15601
|
-
]
|
|
15602
|
-
],
|
|
15603
|
-
"??",
|
|
15604
|
-
[5, "0"]
|
|
15605
|
-
]
|
|
15606
|
-
],
|
|
15607
|
-
[
|
|
15608
|
-
12,
|
|
15609
|
-
"contribution",
|
|
15610
|
-
[5, "0"]
|
|
15611
|
-
],
|
|
15612
|
-
[
|
|
15613
|
-
14,
|
|
15614
|
-
[
|
|
15615
|
-
12,
|
|
15616
|
-
"i",
|
|
15617
|
-
"start"
|
|
15618
|
-
],
|
|
15619
|
-
[
|
|
15620
|
-
1,
|
|
15621
|
-
"i",
|
|
15622
|
-
"<",
|
|
15623
|
-
"end"
|
|
15624
|
-
],
|
|
15625
|
-
[
|
|
15626
|
-
2,
|
|
15627
|
-
"i",
|
|
15628
|
-
"=",
|
|
15629
|
-
[
|
|
15630
|
-
1,
|
|
15631
|
-
"i",
|
|
15632
|
-
"+",
|
|
15633
|
-
[5, "1"]
|
|
15634
|
-
]
|
|
15635
|
-
],
|
|
15636
|
-
[0, [
|
|
15637
|
-
[
|
|
15638
|
-
13,
|
|
15639
|
-
"source",
|
|
15640
|
-
[
|
|
15641
|
-
3,
|
|
15642
|
-
[
|
|
15643
|
-
8,
|
|
15644
|
-
[
|
|
15645
|
-
7,
|
|
15646
|
-
[
|
|
15647
|
-
7,
|
|
15648
|
-
"PageRankLayout",
|
|
15649
|
-
"$"
|
|
15650
|
-
],
|
|
15651
|
-
"colIndices"
|
|
15652
|
-
],
|
|
15653
|
-
"i"
|
|
15654
|
-
],
|
|
15655
|
-
"??",
|
|
15656
|
-
[5, "0"]
|
|
15657
|
-
]
|
|
15658
|
-
],
|
|
15659
|
-
[
|
|
15660
|
-
13,
|
|
15661
|
-
"deg",
|
|
15662
|
-
[
|
|
15663
|
-
3,
|
|
15664
|
-
[
|
|
15665
|
-
8,
|
|
15666
|
-
[
|
|
15667
|
-
7,
|
|
15668
|
-
[
|
|
15669
|
-
7,
|
|
15670
|
-
"PageRankLayout",
|
|
15671
|
-
"$"
|
|
15672
|
-
],
|
|
15673
|
-
"outDegrees"
|
|
15674
|
-
],
|
|
15675
|
-
"source"
|
|
15676
|
-
],
|
|
15677
|
-
"??",
|
|
15678
|
-
[5, "0"]
|
|
15679
|
-
]
|
|
15680
|
-
],
|
|
15681
|
-
[
|
|
15682
|
-
11,
|
|
15683
|
-
[
|
|
15684
|
-
1,
|
|
15685
|
-
"deg",
|
|
15686
|
-
">",
|
|
15687
|
-
[5, "0"]
|
|
15688
|
-
],
|
|
15689
|
-
[0, [[
|
|
15690
|
-
13,
|
|
15691
|
-
"rank",
|
|
15692
|
-
[
|
|
15693
|
-
3,
|
|
15694
|
-
[
|
|
15695
|
-
8,
|
|
15696
|
-
[
|
|
15697
|
-
7,
|
|
15698
|
-
[
|
|
15699
|
-
7,
|
|
15700
|
-
"PageRankLayout",
|
|
15701
|
-
"$"
|
|
15702
|
-
],
|
|
15703
|
-
"ranks"
|
|
15704
|
-
],
|
|
15705
|
-
"source"
|
|
15706
|
-
],
|
|
15707
|
-
"??",
|
|
15708
|
-
[5, "0"]
|
|
15709
|
-
]
|
|
15710
|
-
], [
|
|
15711
|
-
2,
|
|
15712
|
-
"contribution",
|
|
15713
|
-
"=",
|
|
15714
|
-
[
|
|
15715
|
-
1,
|
|
15716
|
-
"contribution",
|
|
15717
|
-
"+",
|
|
15718
|
-
[
|
|
15719
|
-
1,
|
|
15720
|
-
"rank",
|
|
15721
|
-
"/",
|
|
15722
|
-
"deg"
|
|
15723
|
-
]
|
|
15724
|
-
]
|
|
15725
|
-
]]]
|
|
15726
|
-
]
|
|
15727
|
-
]]
|
|
15728
|
-
],
|
|
15729
|
-
[
|
|
15730
|
-
13,
|
|
15731
|
-
"teleport",
|
|
15732
|
-
[
|
|
15733
|
-
1,
|
|
15734
|
-
[
|
|
15735
|
-
1,
|
|
15736
|
-
[5, "1"],
|
|
15737
|
-
"-",
|
|
15738
|
-
"damp"
|
|
15739
|
-
],
|
|
15740
|
-
"/",
|
|
15741
|
-
"n"
|
|
15742
|
-
]
|
|
15743
|
-
],
|
|
15744
|
-
[
|
|
15745
|
-
2,
|
|
15746
|
-
[
|
|
15747
|
-
8,
|
|
15748
|
-
[
|
|
15749
|
-
7,
|
|
15750
|
-
[
|
|
15751
|
-
7,
|
|
15752
|
-
"PageRankLayout",
|
|
15753
|
-
"$"
|
|
15754
|
-
],
|
|
15755
|
-
"newRanks"
|
|
15756
|
-
],
|
|
15757
|
-
"node"
|
|
15758
|
-
],
|
|
15759
|
-
"=",
|
|
15760
|
-
[
|
|
15761
|
-
1,
|
|
15762
|
-
"teleport",
|
|
15763
|
-
"+",
|
|
15764
|
-
[
|
|
15765
|
-
1,
|
|
15766
|
-
"damp",
|
|
15767
|
-
"*",
|
|
15768
|
-
"contribution"
|
|
15769
|
-
]
|
|
15770
|
-
]
|
|
15771
|
-
]
|
|
15772
|
-
]],
|
|
15773
|
-
"externalNames": ["PageRankLayout"]
|
|
15774
|
-
},
|
|
15775
|
-
externals: () => ({ PageRankLayout })
|
|
15776
|
-
}) && $.f)({});
|
|
15777
|
-
/**
|
|
15778
|
-
* Dispatch one PageRank iteration on GPU.
|
|
15779
|
-
*
|
|
15780
|
-
* @param root - TypeGPU root instance
|
|
15781
|
-
* @param csrBuffers - CSR matrix as typed buffers (transpose graph: in-edges)
|
|
15782
|
-
* @param ranks - Current rank values buffer
|
|
15783
|
-
* @param outDegrees - Out-degree buffer for each node
|
|
15784
|
-
* @param newRanks - Output buffer for new rank values (mutable)
|
|
15785
|
-
* @param nodeCount - Number of nodes
|
|
15786
|
-
* @param damping - Damping factor (typically 0.85)
|
|
15787
|
-
*/
|
|
15788
|
-
function dispatchPagerank(root, csrBuffers, ranks, outDegrees, newRanks, nodeCount, damping) {
|
|
15789
|
-
const pipeline = (globalThis.__TYPEGPU_AUTONAME__ ?? ((a) => a))(root.createGuardedComputePipeline(pagerankPipeline), "pipeline");
|
|
15790
|
-
const nodeCountBuffer = (globalThis.__TYPEGPU_AUTONAME__ ?? ((a) => a))(root.createBuffer(data_exports.u32, nodeCount).$usage("uniform"), "nodeCountBuffer");
|
|
15791
|
-
const dampingBuffer = (globalThis.__TYPEGPU_AUTONAME__ ?? ((a) => a))(root.createBuffer(data_exports.f32, damping).$usage("uniform"), "dampingBuffer");
|
|
15792
|
-
const bindGroup = root.createBindGroup(PageRankLayout, {
|
|
15793
|
-
rowOffsets: csrBuffers.rowOffsets,
|
|
15794
|
-
colIndices: csrBuffers.colIndices,
|
|
15795
|
-
ranks,
|
|
15796
|
-
outDegrees,
|
|
15797
|
-
newRanks,
|
|
15798
|
-
nodeCount: nodeCountBuffer,
|
|
15799
|
-
damping: dampingBuffer
|
|
15800
|
-
});
|
|
15801
|
-
pipeline.with(bindGroup).dispatchThreads(nodeCount);
|
|
15802
|
-
}
|
|
15803
|
-
//#endregion
|
|
15804
|
-
//#region src/gpu/kernels/jaccard/kernel.ts
|
|
15805
|
-
/**
|
|
15806
|
-
* TypeGPU compute kernel for batch Jaccard similarity.
|
|
15807
|
-
*
|
|
15808
|
-
* Computes Jaccard coefficient for multiple node pairs in parallel:
|
|
15809
|
-
* J(u, v) = |N(u) ∩ N(v)| / |N(u) ∪ N(v)|
|
|
15810
|
-
*
|
|
15811
|
-
* Uses binary search optimisation: iterate smaller neighbourhood, search in larger.
|
|
15812
|
-
*
|
|
15813
|
-
* @module gpu/kernels/jaccard/kernel
|
|
15814
|
-
*/
|
|
15815
|
-
/**
|
|
15816
|
-
* Bind group layout for Jaccard kernel.
|
|
15817
|
-
*/
|
|
15818
|
-
var JaccardLayout = (globalThis.__TYPEGPU_AUTONAME__ ?? ((a) => a))(src_default.bindGroupLayout({
|
|
15819
|
-
rowOffsets: { storage: data_exports.arrayOf(data_exports.u32) },
|
|
15820
|
-
colIndices: { storage: data_exports.arrayOf(data_exports.u32) },
|
|
15821
|
-
pairsU: { storage: data_exports.arrayOf(data_exports.u32) },
|
|
15822
|
-
pairsV: { storage: data_exports.arrayOf(data_exports.u32) },
|
|
15823
|
-
results: {
|
|
15824
|
-
storage: data_exports.arrayOf(data_exports.f32),
|
|
15825
|
-
access: "mutable"
|
|
15826
|
-
},
|
|
15827
|
-
pairCount: { uniform: data_exports.u32 }
|
|
15828
|
-
}), "JaccardLayout");
|
|
15829
|
-
/**
|
|
15830
|
-
* Jaccard compute pipeline: one thread per pair.
|
|
15831
|
-
*
|
|
15832
|
-
* For each pair (u, v):
|
|
15833
|
-
* - Count intersection by iterating smaller neighbourhood
|
|
15834
|
-
* - Binary search in larger neighbourhood
|
|
15835
|
-
* - Jaccard = intersection / (degU + degV - intersection)
|
|
15836
|
-
*/
|
|
15837
|
-
var jaccardPipeline = (($) => (globalThis.__TYPEGPU_META__ ??= /* @__PURE__ */ new WeakMap()).set($.f = ((pairIdx) => {
|
|
15838
|
-
"use gpu";
|
|
15839
|
-
const u = JaccardLayout.$.pairsU[pairIdx] ?? 0;
|
|
15840
|
-
const v = JaccardLayout.$.pairsV[pairIdx] ?? 0;
|
|
15841
|
-
const uStart = JaccardLayout.$.rowOffsets[u] ?? 0;
|
|
15842
|
-
const uEnd = JaccardLayout.$.rowOffsets[__tsover_add(u, 1)] ?? 0;
|
|
15843
|
-
const vStart = JaccardLayout.$.rowOffsets[v] ?? 0;
|
|
15844
|
-
const vEnd = JaccardLayout.$.rowOffsets[__tsover_add(v, 1)] ?? 0;
|
|
15845
|
-
const degU = __tsover_sub(uEnd, uStart);
|
|
15846
|
-
const degV = __tsover_sub(vEnd, vStart);
|
|
15847
|
-
if (degU === 0 || degV === 0) {
|
|
15848
|
-
JaccardLayout.$.results[pairIdx] = 0;
|
|
15849
|
-
return;
|
|
14901
|
+
Object.defineProperty(exports, "data_exports", {
|
|
14902
|
+
enumerable: true,
|
|
14903
|
+
get: function() {
|
|
14904
|
+
return data_exports;
|
|
15850
14905
|
}
|
|
15851
|
-
|
|
15852
|
-
|
|
15853
|
-
|
|
15854
|
-
|
|
15855
|
-
|
|
15856
|
-
while (lo < hi) {
|
|
15857
|
-
const mid = __tsover_add(lo, __tsover_div(__tsover_sub(hi, lo), 2));
|
|
15858
|
-
const midVal = JaccardLayout.$.colIndices[mid] ?? 0;
|
|
15859
|
-
if (midVal === neighbour) {
|
|
15860
|
-
intersection = __tsover_add(intersection, 1);
|
|
15861
|
-
lo = hi;
|
|
15862
|
-
} else if (midVal < neighbour) lo = __tsover_add(mid, 1);
|
|
15863
|
-
else hi = mid;
|
|
15864
|
-
}
|
|
14906
|
+
});
|
|
14907
|
+
Object.defineProperty(exports, "src_default", {
|
|
14908
|
+
enumerable: true,
|
|
14909
|
+
get: function() {
|
|
14910
|
+
return src_default;
|
|
15865
14911
|
}
|
|
15866
|
-
|
|
15867
|
-
|
|
15868
|
-
|
|
15869
|
-
|
|
15870
|
-
|
|
15871
|
-
const mid = __tsover_add(lo, __tsover_div(__tsover_sub(hi, lo), 2));
|
|
15872
|
-
const midVal = JaccardLayout.$.colIndices[mid] ?? 0;
|
|
15873
|
-
if (midVal === neighbour) {
|
|
15874
|
-
intersection = __tsover_add(intersection, 1);
|
|
15875
|
-
lo = hi;
|
|
15876
|
-
} else if (midVal < neighbour) lo = __tsover_add(mid, 1);
|
|
15877
|
-
else hi = mid;
|
|
15878
|
-
}
|
|
14912
|
+
});
|
|
14913
|
+
Object.defineProperty(exports, "tgpu_exports", {
|
|
14914
|
+
enumerable: true,
|
|
14915
|
+
get: function() {
|
|
14916
|
+
return tgpu_exports;
|
|
15879
14917
|
}
|
|
15880
|
-
|
|
15881
|
-
JaccardLayout.$.results[pairIdx] = __tsover_div(intersection, unionSize);
|
|
15882
|
-
}), {
|
|
15883
|
-
v: 1,
|
|
15884
|
-
name: "jaccardPipeline",
|
|
15885
|
-
ast: {
|
|
15886
|
-
"params": [{
|
|
15887
|
-
"type": "i",
|
|
15888
|
-
"name": "pairIdx"
|
|
15889
|
-
}],
|
|
15890
|
-
"body": [0, [
|
|
15891
|
-
[
|
|
15892
|
-
13,
|
|
15893
|
-
"u",
|
|
15894
|
-
[
|
|
15895
|
-
3,
|
|
15896
|
-
[
|
|
15897
|
-
8,
|
|
15898
|
-
[
|
|
15899
|
-
7,
|
|
15900
|
-
[
|
|
15901
|
-
7,
|
|
15902
|
-
"JaccardLayout",
|
|
15903
|
-
"$"
|
|
15904
|
-
],
|
|
15905
|
-
"pairsU"
|
|
15906
|
-
],
|
|
15907
|
-
"pairIdx"
|
|
15908
|
-
],
|
|
15909
|
-
"??",
|
|
15910
|
-
[5, "0"]
|
|
15911
|
-
]
|
|
15912
|
-
],
|
|
15913
|
-
[
|
|
15914
|
-
13,
|
|
15915
|
-
"v",
|
|
15916
|
-
[
|
|
15917
|
-
3,
|
|
15918
|
-
[
|
|
15919
|
-
8,
|
|
15920
|
-
[
|
|
15921
|
-
7,
|
|
15922
|
-
[
|
|
15923
|
-
7,
|
|
15924
|
-
"JaccardLayout",
|
|
15925
|
-
"$"
|
|
15926
|
-
],
|
|
15927
|
-
"pairsV"
|
|
15928
|
-
],
|
|
15929
|
-
"pairIdx"
|
|
15930
|
-
],
|
|
15931
|
-
"??",
|
|
15932
|
-
[5, "0"]
|
|
15933
|
-
]
|
|
15934
|
-
],
|
|
15935
|
-
[
|
|
15936
|
-
13,
|
|
15937
|
-
"uStart",
|
|
15938
|
-
[
|
|
15939
|
-
3,
|
|
15940
|
-
[
|
|
15941
|
-
8,
|
|
15942
|
-
[
|
|
15943
|
-
7,
|
|
15944
|
-
[
|
|
15945
|
-
7,
|
|
15946
|
-
"JaccardLayout",
|
|
15947
|
-
"$"
|
|
15948
|
-
],
|
|
15949
|
-
"rowOffsets"
|
|
15950
|
-
],
|
|
15951
|
-
"u"
|
|
15952
|
-
],
|
|
15953
|
-
"??",
|
|
15954
|
-
[5, "0"]
|
|
15955
|
-
]
|
|
15956
|
-
],
|
|
15957
|
-
[
|
|
15958
|
-
13,
|
|
15959
|
-
"uEnd",
|
|
15960
|
-
[
|
|
15961
|
-
3,
|
|
15962
|
-
[
|
|
15963
|
-
8,
|
|
15964
|
-
[
|
|
15965
|
-
7,
|
|
15966
|
-
[
|
|
15967
|
-
7,
|
|
15968
|
-
"JaccardLayout",
|
|
15969
|
-
"$"
|
|
15970
|
-
],
|
|
15971
|
-
"rowOffsets"
|
|
15972
|
-
],
|
|
15973
|
-
[
|
|
15974
|
-
1,
|
|
15975
|
-
"u",
|
|
15976
|
-
"+",
|
|
15977
|
-
[5, "1"]
|
|
15978
|
-
]
|
|
15979
|
-
],
|
|
15980
|
-
"??",
|
|
15981
|
-
[5, "0"]
|
|
15982
|
-
]
|
|
15983
|
-
],
|
|
15984
|
-
[
|
|
15985
|
-
13,
|
|
15986
|
-
"vStart",
|
|
15987
|
-
[
|
|
15988
|
-
3,
|
|
15989
|
-
[
|
|
15990
|
-
8,
|
|
15991
|
-
[
|
|
15992
|
-
7,
|
|
15993
|
-
[
|
|
15994
|
-
7,
|
|
15995
|
-
"JaccardLayout",
|
|
15996
|
-
"$"
|
|
15997
|
-
],
|
|
15998
|
-
"rowOffsets"
|
|
15999
|
-
],
|
|
16000
|
-
"v"
|
|
16001
|
-
],
|
|
16002
|
-
"??",
|
|
16003
|
-
[5, "0"]
|
|
16004
|
-
]
|
|
16005
|
-
],
|
|
16006
|
-
[
|
|
16007
|
-
13,
|
|
16008
|
-
"vEnd",
|
|
16009
|
-
[
|
|
16010
|
-
3,
|
|
16011
|
-
[
|
|
16012
|
-
8,
|
|
16013
|
-
[
|
|
16014
|
-
7,
|
|
16015
|
-
[
|
|
16016
|
-
7,
|
|
16017
|
-
"JaccardLayout",
|
|
16018
|
-
"$"
|
|
16019
|
-
],
|
|
16020
|
-
"rowOffsets"
|
|
16021
|
-
],
|
|
16022
|
-
[
|
|
16023
|
-
1,
|
|
16024
|
-
"v",
|
|
16025
|
-
"+",
|
|
16026
|
-
[5, "1"]
|
|
16027
|
-
]
|
|
16028
|
-
],
|
|
16029
|
-
"??",
|
|
16030
|
-
[5, "0"]
|
|
16031
|
-
]
|
|
16032
|
-
],
|
|
16033
|
-
[
|
|
16034
|
-
13,
|
|
16035
|
-
"degU",
|
|
16036
|
-
[
|
|
16037
|
-
1,
|
|
16038
|
-
"uEnd",
|
|
16039
|
-
"-",
|
|
16040
|
-
"uStart"
|
|
16041
|
-
]
|
|
16042
|
-
],
|
|
16043
|
-
[
|
|
16044
|
-
13,
|
|
16045
|
-
"degV",
|
|
16046
|
-
[
|
|
16047
|
-
1,
|
|
16048
|
-
"vEnd",
|
|
16049
|
-
"-",
|
|
16050
|
-
"vStart"
|
|
16051
|
-
]
|
|
16052
|
-
],
|
|
16053
|
-
[
|
|
16054
|
-
11,
|
|
16055
|
-
[
|
|
16056
|
-
3,
|
|
16057
|
-
[
|
|
16058
|
-
1,
|
|
16059
|
-
"degU",
|
|
16060
|
-
"===",
|
|
16061
|
-
[5, "0"]
|
|
16062
|
-
],
|
|
16063
|
-
"||",
|
|
16064
|
-
[
|
|
16065
|
-
1,
|
|
16066
|
-
"degV",
|
|
16067
|
-
"===",
|
|
16068
|
-
[5, "0"]
|
|
16069
|
-
]
|
|
16070
|
-
],
|
|
16071
|
-
[0, [[
|
|
16072
|
-
2,
|
|
16073
|
-
[
|
|
16074
|
-
8,
|
|
16075
|
-
[
|
|
16076
|
-
7,
|
|
16077
|
-
[
|
|
16078
|
-
7,
|
|
16079
|
-
"JaccardLayout",
|
|
16080
|
-
"$"
|
|
16081
|
-
],
|
|
16082
|
-
"results"
|
|
16083
|
-
],
|
|
16084
|
-
"pairIdx"
|
|
16085
|
-
],
|
|
16086
|
-
"=",
|
|
16087
|
-
[5, "0"]
|
|
16088
|
-
], [10]]]
|
|
16089
|
-
],
|
|
16090
|
-
[
|
|
16091
|
-
12,
|
|
16092
|
-
"intersection",
|
|
16093
|
-
[5, "0"]
|
|
16094
|
-
],
|
|
16095
|
-
[
|
|
16096
|
-
11,
|
|
16097
|
-
[
|
|
16098
|
-
1,
|
|
16099
|
-
"degU",
|
|
16100
|
-
"<=",
|
|
16101
|
-
"degV"
|
|
16102
|
-
],
|
|
16103
|
-
[0, [[
|
|
16104
|
-
14,
|
|
16105
|
-
[
|
|
16106
|
-
12,
|
|
16107
|
-
"i",
|
|
16108
|
-
"uStart"
|
|
16109
|
-
],
|
|
16110
|
-
[
|
|
16111
|
-
1,
|
|
16112
|
-
"i",
|
|
16113
|
-
"<",
|
|
16114
|
-
"uEnd"
|
|
16115
|
-
],
|
|
16116
|
-
[
|
|
16117
|
-
2,
|
|
16118
|
-
"i",
|
|
16119
|
-
"=",
|
|
16120
|
-
[
|
|
16121
|
-
1,
|
|
16122
|
-
"i",
|
|
16123
|
-
"+",
|
|
16124
|
-
[5, "1"]
|
|
16125
|
-
]
|
|
16126
|
-
],
|
|
16127
|
-
[0, [
|
|
16128
|
-
[
|
|
16129
|
-
13,
|
|
16130
|
-
"neighbour",
|
|
16131
|
-
[
|
|
16132
|
-
3,
|
|
16133
|
-
[
|
|
16134
|
-
8,
|
|
16135
|
-
[
|
|
16136
|
-
7,
|
|
16137
|
-
[
|
|
16138
|
-
7,
|
|
16139
|
-
"JaccardLayout",
|
|
16140
|
-
"$"
|
|
16141
|
-
],
|
|
16142
|
-
"colIndices"
|
|
16143
|
-
],
|
|
16144
|
-
"i"
|
|
16145
|
-
],
|
|
16146
|
-
"??",
|
|
16147
|
-
[5, "0"]
|
|
16148
|
-
]
|
|
16149
|
-
],
|
|
16150
|
-
[
|
|
16151
|
-
12,
|
|
16152
|
-
"lo",
|
|
16153
|
-
"vStart"
|
|
16154
|
-
],
|
|
16155
|
-
[
|
|
16156
|
-
12,
|
|
16157
|
-
"hi",
|
|
16158
|
-
"vEnd"
|
|
16159
|
-
],
|
|
16160
|
-
[
|
|
16161
|
-
15,
|
|
16162
|
-
[
|
|
16163
|
-
1,
|
|
16164
|
-
"lo",
|
|
16165
|
-
"<",
|
|
16166
|
-
"hi"
|
|
16167
|
-
],
|
|
16168
|
-
[0, [
|
|
16169
|
-
[
|
|
16170
|
-
13,
|
|
16171
|
-
"mid",
|
|
16172
|
-
[
|
|
16173
|
-
1,
|
|
16174
|
-
"lo",
|
|
16175
|
-
"+",
|
|
16176
|
-
[
|
|
16177
|
-
1,
|
|
16178
|
-
[
|
|
16179
|
-
1,
|
|
16180
|
-
"hi",
|
|
16181
|
-
"-",
|
|
16182
|
-
"lo"
|
|
16183
|
-
],
|
|
16184
|
-
"/",
|
|
16185
|
-
[5, "2"]
|
|
16186
|
-
]
|
|
16187
|
-
]
|
|
16188
|
-
],
|
|
16189
|
-
[
|
|
16190
|
-
13,
|
|
16191
|
-
"midVal",
|
|
16192
|
-
[
|
|
16193
|
-
3,
|
|
16194
|
-
[
|
|
16195
|
-
8,
|
|
16196
|
-
[
|
|
16197
|
-
7,
|
|
16198
|
-
[
|
|
16199
|
-
7,
|
|
16200
|
-
"JaccardLayout",
|
|
16201
|
-
"$"
|
|
16202
|
-
],
|
|
16203
|
-
"colIndices"
|
|
16204
|
-
],
|
|
16205
|
-
"mid"
|
|
16206
|
-
],
|
|
16207
|
-
"??",
|
|
16208
|
-
[5, "0"]
|
|
16209
|
-
]
|
|
16210
|
-
],
|
|
16211
|
-
[
|
|
16212
|
-
11,
|
|
16213
|
-
[
|
|
16214
|
-
1,
|
|
16215
|
-
"midVal",
|
|
16216
|
-
"===",
|
|
16217
|
-
"neighbour"
|
|
16218
|
-
],
|
|
16219
|
-
[0, [[
|
|
16220
|
-
2,
|
|
16221
|
-
"intersection",
|
|
16222
|
-
"=",
|
|
16223
|
-
[
|
|
16224
|
-
1,
|
|
16225
|
-
"intersection",
|
|
16226
|
-
"+",
|
|
16227
|
-
[5, "1"]
|
|
16228
|
-
]
|
|
16229
|
-
], [
|
|
16230
|
-
2,
|
|
16231
|
-
"lo",
|
|
16232
|
-
"=",
|
|
16233
|
-
"hi"
|
|
16234
|
-
]]],
|
|
16235
|
-
[
|
|
16236
|
-
11,
|
|
16237
|
-
[
|
|
16238
|
-
1,
|
|
16239
|
-
"midVal",
|
|
16240
|
-
"<",
|
|
16241
|
-
"neighbour"
|
|
16242
|
-
],
|
|
16243
|
-
[0, [[
|
|
16244
|
-
2,
|
|
16245
|
-
"lo",
|
|
16246
|
-
"=",
|
|
16247
|
-
[
|
|
16248
|
-
1,
|
|
16249
|
-
"mid",
|
|
16250
|
-
"+",
|
|
16251
|
-
[5, "1"]
|
|
16252
|
-
]
|
|
16253
|
-
]]],
|
|
16254
|
-
[0, [[
|
|
16255
|
-
2,
|
|
16256
|
-
"hi",
|
|
16257
|
-
"=",
|
|
16258
|
-
"mid"
|
|
16259
|
-
]]]
|
|
16260
|
-
]
|
|
16261
|
-
]
|
|
16262
|
-
]]
|
|
16263
|
-
]
|
|
16264
|
-
]]
|
|
16265
|
-
]]],
|
|
16266
|
-
[0, [[
|
|
16267
|
-
14,
|
|
16268
|
-
[
|
|
16269
|
-
12,
|
|
16270
|
-
"i",
|
|
16271
|
-
"vStart"
|
|
16272
|
-
],
|
|
16273
|
-
[
|
|
16274
|
-
1,
|
|
16275
|
-
"i",
|
|
16276
|
-
"<",
|
|
16277
|
-
"vEnd"
|
|
16278
|
-
],
|
|
16279
|
-
[
|
|
16280
|
-
2,
|
|
16281
|
-
"i",
|
|
16282
|
-
"=",
|
|
16283
|
-
[
|
|
16284
|
-
1,
|
|
16285
|
-
"i",
|
|
16286
|
-
"+",
|
|
16287
|
-
[5, "1"]
|
|
16288
|
-
]
|
|
16289
|
-
],
|
|
16290
|
-
[0, [
|
|
16291
|
-
[
|
|
16292
|
-
13,
|
|
16293
|
-
"neighbour",
|
|
16294
|
-
[
|
|
16295
|
-
3,
|
|
16296
|
-
[
|
|
16297
|
-
8,
|
|
16298
|
-
[
|
|
16299
|
-
7,
|
|
16300
|
-
[
|
|
16301
|
-
7,
|
|
16302
|
-
"JaccardLayout",
|
|
16303
|
-
"$"
|
|
16304
|
-
],
|
|
16305
|
-
"colIndices"
|
|
16306
|
-
],
|
|
16307
|
-
"i"
|
|
16308
|
-
],
|
|
16309
|
-
"??",
|
|
16310
|
-
[5, "0"]
|
|
16311
|
-
]
|
|
16312
|
-
],
|
|
16313
|
-
[
|
|
16314
|
-
12,
|
|
16315
|
-
"lo",
|
|
16316
|
-
"uStart"
|
|
16317
|
-
],
|
|
16318
|
-
[
|
|
16319
|
-
12,
|
|
16320
|
-
"hi",
|
|
16321
|
-
"uEnd"
|
|
16322
|
-
],
|
|
16323
|
-
[
|
|
16324
|
-
15,
|
|
16325
|
-
[
|
|
16326
|
-
1,
|
|
16327
|
-
"lo",
|
|
16328
|
-
"<",
|
|
16329
|
-
"hi"
|
|
16330
|
-
],
|
|
16331
|
-
[0, [
|
|
16332
|
-
[
|
|
16333
|
-
13,
|
|
16334
|
-
"mid",
|
|
16335
|
-
[
|
|
16336
|
-
1,
|
|
16337
|
-
"lo",
|
|
16338
|
-
"+",
|
|
16339
|
-
[
|
|
16340
|
-
1,
|
|
16341
|
-
[
|
|
16342
|
-
1,
|
|
16343
|
-
"hi",
|
|
16344
|
-
"-",
|
|
16345
|
-
"lo"
|
|
16346
|
-
],
|
|
16347
|
-
"/",
|
|
16348
|
-
[5, "2"]
|
|
16349
|
-
]
|
|
16350
|
-
]
|
|
16351
|
-
],
|
|
16352
|
-
[
|
|
16353
|
-
13,
|
|
16354
|
-
"midVal",
|
|
16355
|
-
[
|
|
16356
|
-
3,
|
|
16357
|
-
[
|
|
16358
|
-
8,
|
|
16359
|
-
[
|
|
16360
|
-
7,
|
|
16361
|
-
[
|
|
16362
|
-
7,
|
|
16363
|
-
"JaccardLayout",
|
|
16364
|
-
"$"
|
|
16365
|
-
],
|
|
16366
|
-
"colIndices"
|
|
16367
|
-
],
|
|
16368
|
-
"mid"
|
|
16369
|
-
],
|
|
16370
|
-
"??",
|
|
16371
|
-
[5, "0"]
|
|
16372
|
-
]
|
|
16373
|
-
],
|
|
16374
|
-
[
|
|
16375
|
-
11,
|
|
16376
|
-
[
|
|
16377
|
-
1,
|
|
16378
|
-
"midVal",
|
|
16379
|
-
"===",
|
|
16380
|
-
"neighbour"
|
|
16381
|
-
],
|
|
16382
|
-
[0, [[
|
|
16383
|
-
2,
|
|
16384
|
-
"intersection",
|
|
16385
|
-
"=",
|
|
16386
|
-
[
|
|
16387
|
-
1,
|
|
16388
|
-
"intersection",
|
|
16389
|
-
"+",
|
|
16390
|
-
[5, "1"]
|
|
16391
|
-
]
|
|
16392
|
-
], [
|
|
16393
|
-
2,
|
|
16394
|
-
"lo",
|
|
16395
|
-
"=",
|
|
16396
|
-
"hi"
|
|
16397
|
-
]]],
|
|
16398
|
-
[
|
|
16399
|
-
11,
|
|
16400
|
-
[
|
|
16401
|
-
1,
|
|
16402
|
-
"midVal",
|
|
16403
|
-
"<",
|
|
16404
|
-
"neighbour"
|
|
16405
|
-
],
|
|
16406
|
-
[0, [[
|
|
16407
|
-
2,
|
|
16408
|
-
"lo",
|
|
16409
|
-
"=",
|
|
16410
|
-
[
|
|
16411
|
-
1,
|
|
16412
|
-
"mid",
|
|
16413
|
-
"+",
|
|
16414
|
-
[5, "1"]
|
|
16415
|
-
]
|
|
16416
|
-
]]],
|
|
16417
|
-
[0, [[
|
|
16418
|
-
2,
|
|
16419
|
-
"hi",
|
|
16420
|
-
"=",
|
|
16421
|
-
"mid"
|
|
16422
|
-
]]]
|
|
16423
|
-
]
|
|
16424
|
-
]
|
|
16425
|
-
]]
|
|
16426
|
-
]
|
|
16427
|
-
]]
|
|
16428
|
-
]]]
|
|
16429
|
-
],
|
|
16430
|
-
[
|
|
16431
|
-
13,
|
|
16432
|
-
"unionSize",
|
|
16433
|
-
[
|
|
16434
|
-
1,
|
|
16435
|
-
[
|
|
16436
|
-
1,
|
|
16437
|
-
"degU",
|
|
16438
|
-
"+",
|
|
16439
|
-
"degV"
|
|
16440
|
-
],
|
|
16441
|
-
"-",
|
|
16442
|
-
"intersection"
|
|
16443
|
-
]
|
|
16444
|
-
],
|
|
16445
|
-
[
|
|
16446
|
-
2,
|
|
16447
|
-
[
|
|
16448
|
-
8,
|
|
16449
|
-
[
|
|
16450
|
-
7,
|
|
16451
|
-
[
|
|
16452
|
-
7,
|
|
16453
|
-
"JaccardLayout",
|
|
16454
|
-
"$"
|
|
16455
|
-
],
|
|
16456
|
-
"results"
|
|
16457
|
-
],
|
|
16458
|
-
"pairIdx"
|
|
16459
|
-
],
|
|
16460
|
-
"=",
|
|
16461
|
-
[
|
|
16462
|
-
1,
|
|
16463
|
-
"intersection",
|
|
16464
|
-
"/",
|
|
16465
|
-
"unionSize"
|
|
16466
|
-
]
|
|
16467
|
-
]
|
|
16468
|
-
]],
|
|
16469
|
-
"externalNames": ["JaccardLayout"]
|
|
16470
|
-
},
|
|
16471
|
-
externals: () => ({ JaccardLayout })
|
|
16472
|
-
}) && $.f)({});
|
|
16473
|
-
/**
|
|
16474
|
-
* Dispatch batch Jaccard on GPU.
|
|
16475
|
-
*
|
|
16476
|
-
* @param root - TypeGPU root instance
|
|
16477
|
-
* @param csrBuffers - CSR matrix as typed buffers
|
|
16478
|
-
* @param pairsU - First node of each pair (u32 array)
|
|
16479
|
-
* @param pairsV - Second node of each pair (u32 array)
|
|
16480
|
-
* @param results - Output Jaccard coefficients (f32 array, mutable)
|
|
16481
|
-
* @param pairCount - Number of pairs to compute
|
|
16482
|
-
*/
|
|
16483
|
-
function dispatchJaccard(root, csrBuffers, pairsU, pairsV, results, pairCount) {
|
|
16484
|
-
const pipeline = (globalThis.__TYPEGPU_AUTONAME__ ?? ((a) => a))(root.createGuardedComputePipeline(jaccardPipeline), "pipeline");
|
|
16485
|
-
const pairCountBuffer = (globalThis.__TYPEGPU_AUTONAME__ ?? ((a) => a))(root.createBuffer(data_exports.u32, pairCount).$usage("uniform"), "pairCountBuffer");
|
|
16486
|
-
const bindGroup = root.createBindGroup(JaccardLayout, {
|
|
16487
|
-
rowOffsets: csrBuffers.rowOffsets,
|
|
16488
|
-
colIndices: csrBuffers.colIndices,
|
|
16489
|
-
pairsU,
|
|
16490
|
-
pairsV,
|
|
16491
|
-
results,
|
|
16492
|
-
pairCount: pairCountBuffer
|
|
16493
|
-
});
|
|
16494
|
-
pipeline.with(bindGroup).dispatchThreads(pairCount);
|
|
16495
|
-
}
|
|
16496
|
-
//#endregion
|
|
16497
|
-
//#region src/gpu/kernels/degree-histogram/kernel.ts
|
|
16498
|
-
/**
|
|
16499
|
-
* TypeGPU compute kernel for degree computation.
|
|
16500
|
-
*
|
|
16501
|
-
* Computes degree per node from CSR row offsets.
|
|
16502
|
-
* Note: Histogram aggregation requires atomic operations or CPU reduction.
|
|
16503
|
-
*
|
|
16504
|
-
* @module gpu/kernels/degree-histogram/kernel
|
|
16505
|
-
*/
|
|
16506
|
-
/**
|
|
16507
|
-
* Bind group layout for degree kernel.
|
|
16508
|
-
*/
|
|
16509
|
-
var DegreeLayout = (globalThis.__TYPEGPU_AUTONAME__ ?? ((a) => a))(src_default.bindGroupLayout({
|
|
16510
|
-
rowOffsets: { storage: data_exports.arrayOf(data_exports.u32) },
|
|
16511
|
-
degrees: {
|
|
16512
|
-
storage: data_exports.arrayOf(data_exports.u32),
|
|
16513
|
-
access: "mutable"
|
|
16514
|
-
},
|
|
16515
|
-
nodeCount: { uniform: data_exports.u32 }
|
|
16516
|
-
}), "DegreeLayout");
|
|
16517
|
-
/**
|
|
16518
|
-
* Degree compute pipeline: compute degree for each node.
|
|
16519
|
-
*
|
|
16520
|
-
* Each thread computes one node's degree from CSR row offsets:
|
|
16521
|
-
* degree[node] = rowOffsets[node+1] - rowOffsets[node]
|
|
16522
|
-
*/
|
|
16523
|
-
var degreePipeline = (($) => (globalThis.__TYPEGPU_META__ ??= /* @__PURE__ */ new WeakMap()).set($.f = ((node) => {
|
|
16524
|
-
"use gpu";
|
|
16525
|
-
if (node >= (DegreeLayout.$.nodeCount ?? 0)) return;
|
|
16526
|
-
const start = DegreeLayout.$.rowOffsets[node] ?? 0;
|
|
16527
|
-
const end = DegreeLayout.$.rowOffsets[__tsover_add(node, 1)] ?? 0;
|
|
16528
|
-
const deg = __tsover_sub(end, start);
|
|
16529
|
-
DegreeLayout.$.degrees[node] = deg;
|
|
16530
|
-
}), {
|
|
16531
|
-
v: 1,
|
|
16532
|
-
name: "degreePipeline",
|
|
16533
|
-
ast: {
|
|
16534
|
-
"params": [{
|
|
16535
|
-
"type": "i",
|
|
16536
|
-
"name": "node"
|
|
16537
|
-
}],
|
|
16538
|
-
"body": [0, [
|
|
16539
|
-
[
|
|
16540
|
-
13,
|
|
16541
|
-
"n",
|
|
16542
|
-
[
|
|
16543
|
-
3,
|
|
16544
|
-
[
|
|
16545
|
-
7,
|
|
16546
|
-
[
|
|
16547
|
-
7,
|
|
16548
|
-
"DegreeLayout",
|
|
16549
|
-
"$"
|
|
16550
|
-
],
|
|
16551
|
-
"nodeCount"
|
|
16552
|
-
],
|
|
16553
|
-
"??",
|
|
16554
|
-
[5, "0"]
|
|
16555
|
-
]
|
|
16556
|
-
],
|
|
16557
|
-
[
|
|
16558
|
-
11,
|
|
16559
|
-
[
|
|
16560
|
-
1,
|
|
16561
|
-
"node",
|
|
16562
|
-
">=",
|
|
16563
|
-
"n"
|
|
16564
|
-
],
|
|
16565
|
-
[0, [[10]]]
|
|
16566
|
-
],
|
|
16567
|
-
[
|
|
16568
|
-
13,
|
|
16569
|
-
"start",
|
|
16570
|
-
[
|
|
16571
|
-
3,
|
|
16572
|
-
[
|
|
16573
|
-
8,
|
|
16574
|
-
[
|
|
16575
|
-
7,
|
|
16576
|
-
[
|
|
16577
|
-
7,
|
|
16578
|
-
"DegreeLayout",
|
|
16579
|
-
"$"
|
|
16580
|
-
],
|
|
16581
|
-
"rowOffsets"
|
|
16582
|
-
],
|
|
16583
|
-
"node"
|
|
16584
|
-
],
|
|
16585
|
-
"??",
|
|
16586
|
-
[5, "0"]
|
|
16587
|
-
]
|
|
16588
|
-
],
|
|
16589
|
-
[
|
|
16590
|
-
13,
|
|
16591
|
-
"end",
|
|
16592
|
-
[
|
|
16593
|
-
3,
|
|
16594
|
-
[
|
|
16595
|
-
8,
|
|
16596
|
-
[
|
|
16597
|
-
7,
|
|
16598
|
-
[
|
|
16599
|
-
7,
|
|
16600
|
-
"DegreeLayout",
|
|
16601
|
-
"$"
|
|
16602
|
-
],
|
|
16603
|
-
"rowOffsets"
|
|
16604
|
-
],
|
|
16605
|
-
[
|
|
16606
|
-
1,
|
|
16607
|
-
"node",
|
|
16608
|
-
"+",
|
|
16609
|
-
[5, "1"]
|
|
16610
|
-
]
|
|
16611
|
-
],
|
|
16612
|
-
"??",
|
|
16613
|
-
[5, "0"]
|
|
16614
|
-
]
|
|
16615
|
-
],
|
|
16616
|
-
[
|
|
16617
|
-
13,
|
|
16618
|
-
"deg",
|
|
16619
|
-
[
|
|
16620
|
-
1,
|
|
16621
|
-
"end",
|
|
16622
|
-
"-",
|
|
16623
|
-
"start"
|
|
16624
|
-
]
|
|
16625
|
-
],
|
|
16626
|
-
[
|
|
16627
|
-
2,
|
|
16628
|
-
[
|
|
16629
|
-
8,
|
|
16630
|
-
[
|
|
16631
|
-
7,
|
|
16632
|
-
[
|
|
16633
|
-
7,
|
|
16634
|
-
"DegreeLayout",
|
|
16635
|
-
"$"
|
|
16636
|
-
],
|
|
16637
|
-
"degrees"
|
|
16638
|
-
],
|
|
16639
|
-
"node"
|
|
16640
|
-
],
|
|
16641
|
-
"=",
|
|
16642
|
-
"deg"
|
|
16643
|
-
]
|
|
16644
|
-
]],
|
|
16645
|
-
"externalNames": ["DegreeLayout"]
|
|
16646
|
-
},
|
|
16647
|
-
externals: () => ({ DegreeLayout })
|
|
16648
|
-
}) && $.f)({});
|
|
16649
|
-
/**
|
|
16650
|
-
* Dispatch degree computation on GPU.
|
|
16651
|
-
*
|
|
16652
|
-
* Note: This computes per-node degrees. Histogram aggregation should be
|
|
16653
|
-
* done on CPU or with a separate reduction kernel.
|
|
16654
|
-
*
|
|
16655
|
-
* @param root - TypeGPU root instance
|
|
16656
|
-
* @param csrBuffers - CSR matrix as typed buffers
|
|
16657
|
-
* @param degrees - Output degree array (u32, mutable)
|
|
16658
|
-
* @param nodeCount - Number of nodes
|
|
16659
|
-
*/
|
|
16660
|
-
function dispatchDegreeHistogram(root, csrBuffers, degrees, nodeCount) {
|
|
16661
|
-
const pipeline = (globalThis.__TYPEGPU_AUTONAME__ ?? ((a) => a))(root.createGuardedComputePipeline(degreePipeline), "pipeline");
|
|
16662
|
-
const nodeCountBuffer = (globalThis.__TYPEGPU_AUTONAME__ ?? ((a) => a))(root.createBuffer(data_exports.u32, nodeCount).$usage("uniform"), "nodeCountBuffer");
|
|
16663
|
-
const bindGroup = root.createBindGroup(DegreeLayout, {
|
|
16664
|
-
rowOffsets: csrBuffers.rowOffsets,
|
|
16665
|
-
degrees,
|
|
16666
|
-
nodeCount: nodeCountBuffer
|
|
16667
|
-
});
|
|
16668
|
-
pipeline.with(bindGroup).dispatchThreads(nodeCount);
|
|
16669
|
-
}
|
|
16670
|
-
//#endregion
|
|
16671
|
-
//#region src/gpu/operations.ts
|
|
16672
|
-
/**
|
|
16673
|
-
* Sparse matrix-vector multiply on GPU.
|
|
16674
|
-
*
|
|
16675
|
-
* Computes y = A * x where A is the graph adjacency matrix in CSR format.
|
|
16676
|
-
*
|
|
16677
|
-
* @param graph - Input graph
|
|
16678
|
-
* @param x - Input vector (must have length = graph.nodeCount)
|
|
16679
|
-
* @param options - Compute options (backend, root, signal)
|
|
16680
|
-
* @returns Result vector y
|
|
16681
|
-
*/
|
|
16682
|
-
async function gpuSpmv(graph, x, options) {
|
|
16683
|
-
const nodeCount = graph.nodeCount;
|
|
16684
|
-
if (x.length !== nodeCount) throw new Error(`Input vector length (${String(x.length)}) must match node count (${String(nodeCount)})`);
|
|
16685
|
-
const cpuFn = () => {
|
|
16686
|
-
const { csr } = graphToCSR(graph);
|
|
16687
|
-
const y = new Float32Array(nodeCount);
|
|
16688
|
-
for (let row = 0; row < nodeCount; row++) {
|
|
16689
|
-
const start = csr.rowOffsets[row] ?? 0;
|
|
16690
|
-
const end = csr.rowOffsets[row + 1] ?? 0;
|
|
16691
|
-
let sum = 0;
|
|
16692
|
-
for (let i = start; i < end; i++) {
|
|
16693
|
-
const col = csr.colIndices[i] ?? 0;
|
|
16694
|
-
const weight = csr.values?.[i] ?? 1;
|
|
16695
|
-
sum += weight * (x[col] ?? 0);
|
|
16696
|
-
}
|
|
16697
|
-
y[row] = sum;
|
|
16698
|
-
}
|
|
16699
|
-
return y;
|
|
16700
|
-
};
|
|
16701
|
-
const gpuFn = async (root) => {
|
|
16702
|
-
const { csr } = graphToCSR(graph);
|
|
16703
|
-
const csrBuffers = csrToTypedBuffers(root, csr);
|
|
16704
|
-
const xBuffer = (globalThis.__TYPEGPU_AUTONAME__ ?? ((a) => a))(root.createBuffer(data_exports.arrayOf(data_exports.f32, nodeCount), Array.from(x)).$usage("storage"), "xBuffer");
|
|
16705
|
-
const yBuffer = (globalThis.__TYPEGPU_AUTONAME__ ?? ((a) => a))(root.createBuffer(data_exports.arrayOf(data_exports.f32, nodeCount)).$usage("storage"), "yBuffer");
|
|
16706
|
-
dispatchSpmv(root, csrBuffers, xBuffer, yBuffer, nodeCount, csr.values !== void 0);
|
|
16707
|
-
const result = await yBuffer.read();
|
|
16708
|
-
return new Float32Array(result);
|
|
16709
|
-
};
|
|
16710
|
-
return withBackend({
|
|
16711
|
-
backend: options?.backend,
|
|
16712
|
-
root: options?.root,
|
|
16713
|
-
signal: options?.signal
|
|
16714
|
-
}, cpuFn, gpuFn);
|
|
16715
|
-
}
|
|
16716
|
-
/**
|
|
16717
|
-
* PageRank via GPU-accelerated power iteration.
|
|
16718
|
-
*
|
|
16719
|
-
* @param graph - Input graph (will be converted to transpose CSR for in-edges)
|
|
16720
|
-
* @param options - Compute options plus damping factor and iteration count
|
|
16721
|
-
* @returns PageRank scores for each node
|
|
16722
|
-
*/
|
|
16723
|
-
async function gpuPageRank(graph, options) {
|
|
16724
|
-
const nodeCount = graph.nodeCount;
|
|
16725
|
-
const damping = options?.damping ?? .85;
|
|
16726
|
-
const iterations = options?.iterations ?? 20;
|
|
16727
|
-
const cpuFn = () => {
|
|
16728
|
-
const { csr } = graphToCSR(graph);
|
|
16729
|
-
const ranks = new Float32Array(nodeCount).fill(1 / nodeCount);
|
|
16730
|
-
const outDegrees = new Uint32Array(nodeCount);
|
|
16731
|
-
for (let i = 0; i < nodeCount; i++) outDegrees[i] = (csr.rowOffsets[i + 1] ?? 0) - (csr.rowOffsets[i] ?? 0);
|
|
16732
|
-
for (let iter = 0; iter < iterations; iter++) {
|
|
16733
|
-
const newRanks = new Float32Array(nodeCount);
|
|
16734
|
-
for (let v = 0; v < nodeCount; v++) {
|
|
16735
|
-
const start = csr.rowOffsets[v] ?? 0;
|
|
16736
|
-
const end = csr.rowOffsets[v + 1] ?? 0;
|
|
16737
|
-
let contribution = 0;
|
|
16738
|
-
for (let i = start; i < end; i++) {
|
|
16739
|
-
const source = csr.colIndices[i] ?? 0;
|
|
16740
|
-
const deg = outDegrees[source] ?? 0;
|
|
16741
|
-
if (deg > 0) contribution += (ranks[source] ?? 0) / deg;
|
|
16742
|
-
}
|
|
16743
|
-
newRanks[v] = (1 - damping) / nodeCount + damping * contribution;
|
|
16744
|
-
}
|
|
16745
|
-
ranks.set(newRanks);
|
|
16746
|
-
}
|
|
16747
|
-
return ranks;
|
|
16748
|
-
};
|
|
16749
|
-
const gpuFn = async (root) => {
|
|
16750
|
-
const { csr } = graphToCSR(graph);
|
|
16751
|
-
const csrBuffers = csrToTypedBuffers(root, csr);
|
|
16752
|
-
const outDegrees = new Uint32Array(nodeCount);
|
|
16753
|
-
for (let i = 0; i < nodeCount; i++) outDegrees[i] = (csr.rowOffsets[i + 1] ?? 0) - (csr.rowOffsets[i] ?? 0);
|
|
16754
|
-
const outDegreesBuffer = (globalThis.__TYPEGPU_AUTONAME__ ?? ((a) => a))(root.createBuffer(data_exports.arrayOf(data_exports.u32, nodeCount), Array.from(outDegrees)).$usage("storage"), "outDegreesBuffer");
|
|
16755
|
-
const ranksBuffer = (globalThis.__TYPEGPU_AUTONAME__ ?? ((a) => a))(root.createBuffer(data_exports.arrayOf(data_exports.f32, nodeCount), Array.from(new Float32Array(nodeCount).fill(1 / nodeCount))).$usage("storage"), "ranksBuffer");
|
|
16756
|
-
const newRanksBuffer = (globalThis.__TYPEGPU_AUTONAME__ ?? ((a) => a))(root.createBuffer(data_exports.arrayOf(data_exports.f32, nodeCount)).$usage("storage"), "newRanksBuffer");
|
|
16757
|
-
for (let iter = 0; iter < iterations; iter++) {
|
|
16758
|
-
dispatchPagerank(root, csrBuffers, ranksBuffer, outDegreesBuffer, newRanksBuffer, nodeCount, damping);
|
|
16759
|
-
const newRanks = await newRanksBuffer.read();
|
|
16760
|
-
ranksBuffer.write(Array.from(newRanks));
|
|
16761
|
-
}
|
|
16762
|
-
const result = await ranksBuffer.read();
|
|
16763
|
-
return new Float32Array(result);
|
|
16764
|
-
};
|
|
16765
|
-
return withBackend({
|
|
16766
|
-
backend: options?.backend,
|
|
16767
|
-
root: options?.root,
|
|
16768
|
-
signal: options?.signal
|
|
16769
|
-
}, cpuFn, gpuFn);
|
|
16770
|
-
}
|
|
16771
|
-
/**
|
|
16772
|
-
* Batch Jaccard similarity for node pairs on GPU.
|
|
16773
|
-
*
|
|
16774
|
-
* @param graph - Input graph
|
|
16775
|
-
* @param pairs - Array of [u, v] node ID pairs
|
|
16776
|
-
* @param options - Compute options
|
|
16777
|
-
* @returns Jaccard coefficients for each pair
|
|
16778
|
-
*/
|
|
16779
|
-
async function gpuJaccardBatch(graph, pairs, options) {
|
|
16780
|
-
const pairCount = pairs.length;
|
|
16781
|
-
const { indexMap } = graphToCSR(graph);
|
|
16782
|
-
const cpuFn = () => {
|
|
16783
|
-
const { csr } = graphToCSR(graph);
|
|
16784
|
-
const results = new Float32Array(pairCount);
|
|
16785
|
-
for (let p = 0; p < pairCount; p++) {
|
|
16786
|
-
const pair = pairs[p];
|
|
16787
|
-
if (pair === void 0) continue;
|
|
16788
|
-
const [u, v] = pair;
|
|
16789
|
-
const uIdx = indexMap.nodeToIndex.get(u);
|
|
16790
|
-
const vIdx = indexMap.nodeToIndex.get(v);
|
|
16791
|
-
if (uIdx === void 0 || vIdx === void 0) {
|
|
16792
|
-
results[p] = 0;
|
|
16793
|
-
continue;
|
|
16794
|
-
}
|
|
16795
|
-
const uStart = csr.rowOffsets[uIdx] ?? 0;
|
|
16796
|
-
const uEnd = csr.rowOffsets[uIdx + 1] ?? 0;
|
|
16797
|
-
const vStart = csr.rowOffsets[vIdx] ?? 0;
|
|
16798
|
-
const vEnd = csr.rowOffsets[vIdx + 1] ?? 0;
|
|
16799
|
-
const uNeighbours = new Set(Array.from(csr.colIndices.slice(uStart, uEnd)));
|
|
16800
|
-
const vNeighbours = new Set(Array.from(csr.colIndices.slice(vStart, vEnd)));
|
|
16801
|
-
let intersection = 0;
|
|
16802
|
-
for (const n of uNeighbours) if (vNeighbours.has(n)) intersection++;
|
|
16803
|
-
const union = uNeighbours.size + vNeighbours.size - intersection;
|
|
16804
|
-
results[p] = union > 0 ? intersection / union : 0;
|
|
16805
|
-
}
|
|
16806
|
-
return results;
|
|
16807
|
-
};
|
|
16808
|
-
const gpuFn = async (root) => {
|
|
16809
|
-
const { csr } = graphToCSR(graph);
|
|
16810
|
-
const csrBuffers = csrToTypedBuffers(root, csr);
|
|
16811
|
-
const pairsU = new Uint32Array(pairCount);
|
|
16812
|
-
const pairsV = new Uint32Array(pairCount);
|
|
16813
|
-
for (let i = 0; i < pairCount; i++) {
|
|
16814
|
-
const pair = pairs[i];
|
|
16815
|
-
if (pair === void 0) continue;
|
|
16816
|
-
const uIdx = indexMap.nodeToIndex.get(pair[0]);
|
|
16817
|
-
const vIdx = indexMap.nodeToIndex.get(pair[1]);
|
|
16818
|
-
pairsU[i] = uIdx ?? 0;
|
|
16819
|
-
pairsV[i] = vIdx ?? 0;
|
|
16820
|
-
}
|
|
16821
|
-
const pairsUBuffer = (globalThis.__TYPEGPU_AUTONAME__ ?? ((a) => a))(root.createBuffer(data_exports.arrayOf(data_exports.u32, pairCount), Array.from(pairsU)).$usage("storage"), "pairsUBuffer");
|
|
16822
|
-
const pairsVBuffer = (globalThis.__TYPEGPU_AUTONAME__ ?? ((a) => a))(root.createBuffer(data_exports.arrayOf(data_exports.u32, pairCount), Array.from(pairsV)).$usage("storage"), "pairsVBuffer");
|
|
16823
|
-
const resultsBuffer = (globalThis.__TYPEGPU_AUTONAME__ ?? ((a) => a))(root.createBuffer(data_exports.arrayOf(data_exports.f32, pairCount)).$usage("storage"), "resultsBuffer");
|
|
16824
|
-
dispatchJaccard(root, csrBuffers, pairsUBuffer, pairsVBuffer, resultsBuffer, pairCount);
|
|
16825
|
-
const result = await resultsBuffer.read();
|
|
16826
|
-
return new Float32Array(result);
|
|
16827
|
-
};
|
|
16828
|
-
return withBackend({
|
|
16829
|
-
backend: options?.backend,
|
|
16830
|
-
root: options?.root,
|
|
16831
|
-
signal: options?.signal
|
|
16832
|
-
}, cpuFn, gpuFn);
|
|
16833
|
-
}
|
|
16834
|
-
/**
|
|
16835
|
-
* BFS level assignment from source node on GPU.
|
|
16836
|
-
*
|
|
16837
|
-
* Note: Full GPU BFS requires atomics not yet available in TypeGPU.
|
|
16838
|
-
* This implementation uses CPU for now but maintains the API.
|
|
16839
|
-
*
|
|
16840
|
-
* @param graph - Input graph
|
|
16841
|
-
* @param source - Source node ID
|
|
16842
|
-
* @param options - Compute options
|
|
16843
|
-
* @returns BFS level for each node (-1 for unreachable)
|
|
16844
|
-
*/
|
|
16845
|
-
async function gpuBfsLevels(graph, source, options) {
|
|
16846
|
-
const nodeCount = graph.nodeCount;
|
|
16847
|
-
const { indexMap } = graphToCSR(graph);
|
|
16848
|
-
const cpuFn = () => {
|
|
16849
|
-
const { csr } = graphToCSR(graph);
|
|
16850
|
-
const levels = new Int32Array(nodeCount).fill(-1);
|
|
16851
|
-
const visited = new Uint8Array(nodeCount);
|
|
16852
|
-
const sourceIndex = indexMap.nodeToIndex.get(source);
|
|
16853
|
-
if (sourceIndex === void 0) throw new Error(`Source node ${source} not found in graph`);
|
|
16854
|
-
const queue = [sourceIndex];
|
|
16855
|
-
levels[sourceIndex] = 0;
|
|
16856
|
-
visited[sourceIndex] = 1;
|
|
16857
|
-
while (queue.length > 0) {
|
|
16858
|
-
const current = queue.shift();
|
|
16859
|
-
if (current === void 0) break;
|
|
16860
|
-
const currentLevel = levels[current] ?? 0;
|
|
16861
|
-
const start = csr.rowOffsets[current] ?? 0;
|
|
16862
|
-
const end = csr.rowOffsets[current + 1] ?? 0;
|
|
16863
|
-
for (let i = start; i < end; i++) {
|
|
16864
|
-
const neighbour = csr.colIndices[i] ?? 0;
|
|
16865
|
-
if (visited[neighbour] === 0) {
|
|
16866
|
-
visited[neighbour] = 1;
|
|
16867
|
-
levels[neighbour] = currentLevel + 1;
|
|
16868
|
-
queue.push(neighbour);
|
|
16869
|
-
}
|
|
16870
|
-
}
|
|
16871
|
-
}
|
|
16872
|
-
return levels;
|
|
16873
|
-
};
|
|
16874
|
-
const gpuFn = (_root) => {
|
|
16875
|
-
return cpuFn();
|
|
16876
|
-
};
|
|
16877
|
-
return withBackend({
|
|
16878
|
-
backend: options?.backend,
|
|
16879
|
-
root: options?.root,
|
|
16880
|
-
signal: options?.signal
|
|
16881
|
-
}, cpuFn, gpuFn);
|
|
16882
|
-
}
|
|
16883
|
-
/**
|
|
16884
|
-
* Degree histogram and statistics on GPU.
|
|
16885
|
-
*
|
|
16886
|
-
* @param graph - Input graph
|
|
16887
|
-
* @param options - Compute options
|
|
16888
|
-
* @returns Degree statistics with histogram
|
|
16889
|
-
*/
|
|
16890
|
-
async function gpuDegreeHistogram(graph, options) {
|
|
16891
|
-
const nodeCount = graph.nodeCount;
|
|
16892
|
-
const cpuFn = () => {
|
|
16893
|
-
const { csr } = graphToCSR(graph);
|
|
16894
|
-
const degrees = new Uint32Array(nodeCount);
|
|
16895
|
-
for (let i = 0; i < nodeCount; i++) degrees[i] = (csr.rowOffsets[i + 1] ?? 0) - (csr.rowOffsets[i] ?? 0);
|
|
16896
|
-
const max = degrees.length > 0 ? Math.max(...degrees) : 0;
|
|
16897
|
-
const histogram = Array.from({ length: max + 1 }, () => 0);
|
|
16898
|
-
let sum = 0;
|
|
16899
|
-
let min = Infinity;
|
|
16900
|
-
for (const d of degrees) {
|
|
16901
|
-
histogram[d] = (histogram[d] ?? 0) + 1;
|
|
16902
|
-
sum += d;
|
|
16903
|
-
if (d < min) min = d;
|
|
16904
|
-
}
|
|
16905
|
-
if (degrees.length === 0) min = 0;
|
|
16906
|
-
return {
|
|
16907
|
-
min,
|
|
16908
|
-
max,
|
|
16909
|
-
mean: nodeCount > 0 ? sum / nodeCount : 0,
|
|
16910
|
-
histogram
|
|
16911
|
-
};
|
|
16912
|
-
};
|
|
16913
|
-
const gpuFn = async (root) => {
|
|
16914
|
-
const { csr } = graphToCSR(graph);
|
|
16915
|
-
const csrBuffers = csrToTypedBuffers(root, csr);
|
|
16916
|
-
const degreesBuffer = (globalThis.__TYPEGPU_AUTONAME__ ?? ((a) => a))(root.createBuffer(data_exports.arrayOf(data_exports.u32, nodeCount)).$usage("storage"), "degreesBuffer");
|
|
16917
|
-
dispatchDegreeHistogram(root, csrBuffers, degreesBuffer, nodeCount);
|
|
16918
|
-
const degrees = await degreesBuffer.read();
|
|
16919
|
-
const max = degrees.length > 0 ? Math.max(...degrees) : 0;
|
|
16920
|
-
const histogram = Array.from({ length: max + 1 }, () => 0);
|
|
16921
|
-
let sum = 0;
|
|
16922
|
-
let min = Infinity;
|
|
16923
|
-
for (const d of degrees) {
|
|
16924
|
-
histogram[d] = (histogram[d] ?? 0) + 1;
|
|
16925
|
-
sum += d;
|
|
16926
|
-
if (d < min) min = d;
|
|
16927
|
-
}
|
|
16928
|
-
if (degrees.length === 0) min = 0;
|
|
16929
|
-
return {
|
|
16930
|
-
min,
|
|
16931
|
-
max,
|
|
16932
|
-
mean: nodeCount > 0 ? sum / nodeCount : 0,
|
|
16933
|
-
histogram
|
|
16934
|
-
};
|
|
16935
|
-
};
|
|
16936
|
-
return withBackend({
|
|
16937
|
-
backend: options?.backend,
|
|
16938
|
-
root: options?.root,
|
|
16939
|
-
signal: options?.signal
|
|
16940
|
-
}, cpuFn, gpuFn);
|
|
16941
|
-
}
|
|
16942
|
-
//#endregion
|
|
16943
|
-
export { gpuSpmv as a, initGPUFromDevice as c, isWebGPUAvailable as d, csrToTypedBuffers as f, gpuPageRank as i, assertWebGPUAvailable as l, GPUNotAvailableError as m, gpuDegreeHistogram as n, withBackend as o, graphToCSR as p, gpuJaccardBatch as r, initGPU as s, gpuBfsLevels as t, detectWebGPU as u };
|
|
14918
|
+
});
|
|
16944
14919
|
|
|
16945
|
-
//# sourceMappingURL=
|
|
14920
|
+
//# sourceMappingURL=typegpu-Dq5FfUB8.cjs.map
|