@danielsimonjr/mathts-parallel 0.6.11 → 0.7.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 +9 -3
- package/dist/ComputePool.d.ts +15 -14
- package/dist/ComputePool.d.ts.map +1 -1
- package/dist/WorkerPool.d.ts +55 -0
- package/dist/WorkerPool.d.ts.map +1 -0
- package/dist/gemm-rows.d.ts +19 -0
- package/dist/gemm-rows.d.ts.map +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +285 -227
- package/dist/matrix.worker.d.ts +0 -11
- package/dist/matrix.worker.d.ts.map +1 -1
- package/dist/matrix.worker.js +10 -5
- package/dist/strategies/chunk.d.ts +9 -2
- package/dist/strategies/chunk.d.ts.map +1 -1
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -12,9 +12,15 @@ npm install @danielsimonjr/mathts-parallel
|
|
|
12
12
|
|
|
13
13
|
## What it provides
|
|
14
14
|
|
|
15
|
-
- `ComputePool` for chunked
|
|
16
|
-
|
|
17
|
-
-
|
|
15
|
+
- `ComputePool` for chunked work over `Float64Array` data (parallel only when an op's
|
|
16
|
+
threshold is met — most element-wise defaults are `'never'` / sequential).
|
|
17
|
+
- `DEFAULT_THRESHOLD_BY_OP`, `resolveOpThreshold`, standalone `parallel*` helpers, and
|
|
18
|
+
bitwise ops.
|
|
19
|
+
- `WorkerPool`, the low-level pool that `execute(data, transferables?, timeoutMs?)` runs on:
|
|
20
|
+
opt-in per-task timeouts with hung-worker replacement. A call that waits in the queue is
|
|
21
|
+
covered by its timeout too, and `terminate()` cancels the timers and stops a worker that
|
|
22
|
+
was still starting. `@danielsimonjr/mathts-functions` uses it for `searchScalars`
|
|
23
|
+
(`parallel` option).
|
|
18
24
|
|
|
19
25
|
## License
|
|
20
26
|
|
package/dist/ComputePool.d.ts
CHANGED
|
@@ -105,20 +105,6 @@ export interface ParallelResult<T> {
|
|
|
105
105
|
/** Whether parallelization was used */
|
|
106
106
|
parallelized: boolean;
|
|
107
107
|
}
|
|
108
|
-
/**
|
|
109
|
-
* Pure-JS tensordot computation over a contiguous range of output elements
|
|
110
|
-
* `[outStart, outEnd)`.
|
|
111
|
-
*
|
|
112
|
-
* This is the shared inner kernel used by both the sequential fallback path in
|
|
113
|
-
* `ComputePool.tensordot` and the worker-dispatched `tensordotChunk` handler.
|
|
114
|
-
* By exporting it and registering it in the worker, we keep the algorithm in
|
|
115
|
-
* one place and avoid divergence.
|
|
116
|
-
*
|
|
117
|
-
* Contracts axis `axesA[i]` of `a` (shape `aShape`) with axis `axesB[i]` of
|
|
118
|
-
* `b` (shape `bShape`). The result layout is free-A axes first, then free-B
|
|
119
|
-
* axes (NumPy convention).
|
|
120
|
-
*/
|
|
121
|
-
export declare function tensordotChunkKernel(a: Float64Array, aShape: readonly number[], b: Float64Array, bShape: readonly number[], axesA: readonly number[], axesB: readonly number[], resultShape: readonly number[], outStart: number, outEnd: number): Float64Array;
|
|
122
108
|
/**
|
|
123
109
|
* ComputePool for parallel MathTS operations
|
|
124
110
|
*
|
|
@@ -171,6 +157,21 @@ export declare class ComputePool {
|
|
|
171
157
|
* its threshold.
|
|
172
158
|
*/
|
|
173
159
|
private seqResult;
|
|
160
|
+
/**
|
|
161
|
+
* Gated Float64Array binary reduction (dot / distance): per-op threshold, shared shape.
|
|
162
|
+
* @internal
|
|
163
|
+
*/
|
|
164
|
+
private gatedBinary;
|
|
165
|
+
/**
|
|
166
|
+
* Gated Int32Array element-wise binary bitwise op.
|
|
167
|
+
* @internal
|
|
168
|
+
*/
|
|
169
|
+
private bitwiseBinary;
|
|
170
|
+
/**
|
|
171
|
+
* Gated Int32Array shift (scalar or per-element counts).
|
|
172
|
+
* @internal
|
|
173
|
+
*/
|
|
174
|
+
private bitwiseShift;
|
|
174
175
|
/**
|
|
175
176
|
* Execute a method in the worker pool
|
|
176
177
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ComputePool.d.ts","sourceRoot":"","sources":["../src/ComputePool.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AASH,OAAO,EACL,cAAc,EACd,QAAQ,
|
|
1
|
+
{"version":3,"file":"ComputePool.d.ts","sourceRoot":"","sources":["../src/ComputePool.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* WorkerPool manages a pool of Web Workers for parallel computation
|
|
3
|
+
* Supports both Node.js (worker_threads) and browser (Web Workers)
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* Runs tasks on a set of workers and queues tasks when no worker is free.
|
|
7
|
+
*
|
|
8
|
+
* The pool uses `worker_threads` when `process.versions.node` is defined, and
|
|
9
|
+
* module Web Workers otherwise. When the caller gives no worker count, the
|
|
10
|
+
* count is `navigator.hardwareConcurrency - 1` (minimum 2), or 4 when that
|
|
11
|
+
* value is not available. A worker error rejects all active tasks.
|
|
12
|
+
* `terminate` rejects all queued and active tasks and stops all workers.
|
|
13
|
+
*/
|
|
14
|
+
export declare class WorkerPool {
|
|
15
|
+
private workers;
|
|
16
|
+
private availableWorkers;
|
|
17
|
+
private taskQueue;
|
|
18
|
+
private activeTasks;
|
|
19
|
+
private maxWorkers;
|
|
20
|
+
private workerScript;
|
|
21
|
+
private isNode;
|
|
22
|
+
private terminated;
|
|
23
|
+
constructor(workerScript: string, maxWorkers?: number);
|
|
24
|
+
private getOptimalWorkerCount;
|
|
25
|
+
private initialize;
|
|
26
|
+
protected createWorker(): Promise<Worker>;
|
|
27
|
+
private handleWorkerMessage;
|
|
28
|
+
private handleWorkerError;
|
|
29
|
+
private processQueue;
|
|
30
|
+
private executeTask;
|
|
31
|
+
/**
|
|
32
|
+
* Handle a timed-out task: terminate the offending worker, evict it from
|
|
33
|
+
* the pool, spawn a replacement so subsequent calls still find a free
|
|
34
|
+
* worker, and reject the task.
|
|
35
|
+
*/
|
|
36
|
+
private handleTaskTimeout;
|
|
37
|
+
/**
|
|
38
|
+
* Submit work to the pool.
|
|
39
|
+
*
|
|
40
|
+
* @param data Payload sent to the worker.
|
|
41
|
+
* @param transferables Optional transferables for zero-copy postMessage.
|
|
42
|
+
* @param timeoutMs Optional timeout in milliseconds. When the worker does
|
|
43
|
+
* not reply within `timeoutMs` the worker is `terminate()`d, a fresh
|
|
44
|
+
* replacement is spawned, and the returned promise rejects. Pass `0`
|
|
45
|
+
* or omit to disable the timeout (legacy behaviour).
|
|
46
|
+
*/
|
|
47
|
+
execute<T = unknown, R = unknown>(data: T, transferables?: Transferable[], timeoutMs?: number): Promise<R>;
|
|
48
|
+
private generateTaskId;
|
|
49
|
+
terminate(): Promise<void>;
|
|
50
|
+
private clearTaskTimer;
|
|
51
|
+
get activeTaskCount(): number;
|
|
52
|
+
get queuedTaskCount(): number;
|
|
53
|
+
get workerCount(): number;
|
|
54
|
+
}
|
|
55
|
+
//# sourceMappingURL=WorkerPool.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"WorkerPool.d.ts","sourceRoot":"","sources":["../src/WorkerPool.ts"],"names":[],"mappings":"AAAA;;;GAGG;AA2BH;;;;;;;;GAQG;AACH,qBAAa,UAAU;IACrB,OAAO,CAAC,OAAO,CAAgB;IAC/B,OAAO,CAAC,gBAAgB,CAAgB;IACxC,OAAO,CAAC,SAAS,CAAoB;IACrC,OAAO,CAAC,WAAW,CAAsC;IACzD,OAAO,CAAC,UAAU,CAAS;IAC3B,OAAO,CAAC,YAAY,CAAS;IAC7B,OAAO,CAAC,MAAM,CAAU;IACxB,OAAO,CAAC,UAAU,CAAS;IAE3B,YAAY,YAAY,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,MAAM,EAKpD;IAED,OAAO,CAAC,qBAAqB;YAOf,UAAU;IAkBxB,UAAgB,YAAY,IAAI,OAAO,CAAC,MAAM,CAAC,CAyC9C;IAED,OAAO,CAAC,mBAAmB;IAqB3B,OAAO,CAAC,iBAAiB;IAYzB,OAAO,CAAC,YAAY;IAQpB,OAAO,CAAC,WAAW;IAiBnB;;;;OAIG;YACW,iBAAiB;IA2C/B;;;;;;;;;OASG;IACU,OAAO,CAAC,CAAC,GAAG,OAAO,EAAE,CAAC,GAAG,OAAO,EAC3C,IAAI,EAAE,CAAC,EACP,aAAa,CAAC,EAAE,YAAY,EAAE,EAC9B,SAAS,CAAC,EAAE,MAAM,GACjB,OAAO,CAAC,CAAC,CAAC,CA8BZ;IAED,OAAO,CAAC,cAAc;IAIT,SAAS,IAAI,OAAO,CAAC,IAAI,CAAC,CAsBtC;IAED,OAAO,CAAC,cAAc;IAOtB,IAAW,eAAe,IAAI,MAAM,CAEnC;IAED,IAAW,eAAe,IAAI,MAAM,CAEnC;IAED,IAAW,WAAW,IAAI,MAAM,CAE/B;CACF"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Row-block dense matrix multiply (ijk inner-k product). Shared by the main
|
|
3
|
+
* thread sequential path and worker row tasks; no package dependencies so the
|
|
4
|
+
* worker bundle stays lean.
|
|
5
|
+
*/
|
|
6
|
+
/**
|
|
7
|
+
* Multiply rows `[rowStart, rowEnd)` of `A` by `B`, writing into `out`.
|
|
8
|
+
*
|
|
9
|
+
* @param aData - Row-major `A` with `aCols` columns
|
|
10
|
+
* @param aCols - Inner dimension (columns of `A`, rows of `B`)
|
|
11
|
+
* @param bData - Row-major `B` with `bCols` columns
|
|
12
|
+
* @param bCols - Columns of `B` and of the product
|
|
13
|
+
* @param rowStart - First row of `A` to accumulate (inclusive)
|
|
14
|
+
* @param rowEnd - Last row of `A` to accumulate (exclusive)
|
|
15
|
+
* @param out - Output buffer; row `i` is stored at `(i - outRowBase) * bCols`
|
|
16
|
+
* @param outRowBase - Row index in `out` corresponding to `rowStart`
|
|
17
|
+
*/
|
|
18
|
+
export declare function gemmRows(aData: ArrayLike<number>, aCols: number, bData: ArrayLike<number>, bCols: number, rowStart: number, rowEnd: number, out: Float64Array, outRowBase: number): void;
|
|
19
|
+
//# sourceMappingURL=gemm-rows.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"gemm-rows.d.ts","sourceRoot":"","sources":["../src/gemm-rows.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH;;;;;;;;;;;GAWG;AACH,wBAAgB,QAAQ,CACtB,KAAK,EAAE,SAAS,CAAC,MAAM,CAAC,EACxB,KAAK,EAAE,MAAM,EACb,KAAK,EAAE,SAAS,CAAC,MAAM,CAAC,EACxB,KAAK,EAAE,MAAM,EACb,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,MAAM,EACd,GAAG,EAAE,YAAY,EACjB,UAAU,EAAE,MAAM,GACjB,IAAI,CAUN"}
|
package/dist/index.d.ts
CHANGED
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
* @packageDocumentation
|
|
8
8
|
*/
|
|
9
9
|
export { ComputePool, computePool, Transfer, DEFAULT_POOL_CONFIG, DEFAULT_THRESHOLD_BY_OP, resolveOpThreshold, } from './ComputePool.js';
|
|
10
|
+
export { WorkerPool } from './WorkerPool.js';
|
|
10
11
|
export type { ComputePoolConfig, ParallelResult, OpName, OpThreshold } from './ComputePool.js';
|
|
11
12
|
export { parallelMatmul, parallelMatvec, parallelTranspose, parallelOuter, parallelDot, parallelAdd, parallelSubtract, parallelMultiply, parallelDivide, parallelScale, parallelAbs, parallelNegate, parallelSquare, parallelSqrt, parallelExp, parallelLog, parallelSin, parallelCos, parallelTan, parallelElementwise, parallelUnary, parallelSum, parallelMean, parallelMin, parallelMax, parallelMinMax, parallelVariance, parallelStd, parallelNorm, parallelDistance, parallelHistogram, parallelReduce, parallelMap, parallelFilter, parallelFind, parallelSort, parallelForEach, parallelSome, parallelEvery, parallelCount, } from './operations/index.js';
|
|
12
13
|
export type { MatmulOptions, ElementwiseOptions, ReduceOptions, MapOptions, } from './operations/index.js';
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAMH,OAAO,EACL,WAAW,EACX,WAAW,EACX,QAAQ,EACR,mBAAmB,EACnB,uBAAuB,EACvB,kBAAkB,GACnB,MAAM,kBAAkB,CAAC;AAE1B,YAAY,EAAE,iBAAiB,EAAE,cAAc,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAM/F,OAAO,EAEL,cAAc,EACd,cAAc,EACd,iBAAiB,EACjB,aAAa,EACb,WAAW,EAGX,WAAW,EACX,gBAAgB,EAChB,gBAAgB,EAChB,cAAc,EACd,aAAa,EACb,WAAW,EACX,cAAc,EACd,cAAc,EACd,YAAY,EACZ,WAAW,EACX,WAAW,EACX,WAAW,EACX,WAAW,EACX,WAAW,EACX,mBAAmB,EACnB,aAAa,EAGb,WAAW,EACX,YAAY,EACZ,WAAW,EACX,WAAW,EACX,cAAc,EACd,gBAAgB,EAChB,WAAW,EACX,YAAY,EACZ,gBAAgB,EAChB,iBAAiB,EACjB,cAAc,EAGd,WAAW,EACX,cAAc,EACd,YAAY,EACZ,YAAY,EACZ,eAAe,EACf,YAAY,EACZ,aAAa,EACb,aAAa,GACd,MAAM,uBAAuB,CAAC;AAE/B,YAAY,EACV,aAAa,EACb,kBAAkB,EAClB,aAAa,EACb,UAAU,GACX,MAAM,uBAAuB,CAAC;AAM/B,OAAO,EACL,MAAM,EACN,KAAK,EACL,MAAM,EACN,MAAM,EACN,SAAS,EACT,eAAe,EACf,aAAa,GACd,MAAM,kBAAkB,CAAC;AAE1B,YAAY,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AAMxD,OAAO,EAEL,sBAAsB,EACtB,iBAAiB,EACjB,UAAU,EACV,kBAAkB,EAClB,gBAAgB,EAChB,sBAAsB,EACtB,cAAc,EACd,WAAW,EAGX,mBAAmB,EACnB,mBAAmB,EACnB,iBAAiB,EACjB,QAAQ,EACR,eAAe,EACf,kBAAkB,GACnB,MAAM,uBAAuB,CAAC;AAE/B,YAAY,EACV,YAAY,EACZ,WAAW,EACX,SAAS,EACT,eAAe,EACf,iBAAiB,EACjB,aAAa,EACb,cAAc,GACf,MAAM,uBAAuB,CAAC;AAU/B,YAAY,EAAE,WAAW,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,kCAAkC,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAMH,OAAO,EACL,WAAW,EACX,WAAW,EACX,QAAQ,EACR,mBAAmB,EACnB,uBAAuB,EACvB,kBAAkB,GACnB,MAAM,kBAAkB,CAAC;AAE1B,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAE7C,YAAY,EAAE,iBAAiB,EAAE,cAAc,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAM/F,OAAO,EAEL,cAAc,EACd,cAAc,EACd,iBAAiB,EACjB,aAAa,EACb,WAAW,EAGX,WAAW,EACX,gBAAgB,EAChB,gBAAgB,EAChB,cAAc,EACd,aAAa,EACb,WAAW,EACX,cAAc,EACd,cAAc,EACd,YAAY,EACZ,WAAW,EACX,WAAW,EACX,WAAW,EACX,WAAW,EACX,WAAW,EACX,mBAAmB,EACnB,aAAa,EAGb,WAAW,EACX,YAAY,EACZ,WAAW,EACX,WAAW,EACX,cAAc,EACd,gBAAgB,EAChB,WAAW,EACX,YAAY,EACZ,gBAAgB,EAChB,iBAAiB,EACjB,cAAc,EAGd,WAAW,EACX,cAAc,EACd,YAAY,EACZ,YAAY,EACZ,eAAe,EACf,YAAY,EACZ,aAAa,EACb,aAAa,GACd,MAAM,uBAAuB,CAAC;AAE/B,YAAY,EACV,aAAa,EACb,kBAAkB,EAClB,aAAa,EACb,UAAU,GACX,MAAM,uBAAuB,CAAC;AAM/B,OAAO,EACL,MAAM,EACN,KAAK,EACL,MAAM,EACN,MAAM,EACN,SAAS,EACT,eAAe,EACf,aAAa,GACd,MAAM,kBAAkB,CAAC;AAE1B,YAAY,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AAMxD,OAAO,EAEL,sBAAsB,EACtB,iBAAiB,EACjB,UAAU,EACV,kBAAkB,EAClB,gBAAgB,EAChB,sBAAsB,EACtB,cAAc,EACd,WAAW,EAGX,mBAAmB,EACnB,mBAAmB,EACnB,iBAAiB,EACjB,QAAQ,EACR,eAAe,EACf,kBAAkB,GACnB,MAAM,uBAAuB,CAAC;AAE/B,YAAY,EACV,YAAY,EACZ,WAAW,EACX,SAAS,EACT,eAAe,EACf,iBAAiB,EACjB,aAAa,EACb,cAAc,GACf,MAAM,uBAAuB,CAAC;AAU/B,YAAY,EAAE,WAAW,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,kCAAkC,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { norm2, pairwiseDot, pairwiseSum, scaledDistance, sumSquaredDeviations } from "@danielsimonjr/mathts-core";
|
|
2
|
-
import { MathWorkerPool, Transfer } from "@danielsimonjr/mathts-workerpool";
|
|
2
|
+
import { MathWorkerPool, Transfer, tensordotRange } from "@danielsimonjr/mathts-workerpool";
|
|
3
3
|
//#region src/strategies/chunk.ts
|
|
4
4
|
const DEFAULT_CHUNK_OPTIONS = {
|
|
5
5
|
minChunkSize: 1e3,
|
|
@@ -7,41 +7,19 @@ const DEFAULT_CHUNK_OPTIONS = {
|
|
|
7
7
|
targetChunkSize: 0,
|
|
8
8
|
balanced: true
|
|
9
9
|
};
|
|
10
|
-
function
|
|
11
|
-
const {
|
|
12
|
-
...DEFAULT_CHUNK_OPTIONS,
|
|
13
|
-
...options
|
|
14
|
-
};
|
|
15
|
-
if (totalElements === 0) return 0;
|
|
16
|
-
if (targetChunkSize > 0) return Math.min(maxChunks, Math.ceil(totalElements / targetChunkSize));
|
|
17
|
-
const maxPossibleChunks = Math.floor(totalElements / minChunkSize);
|
|
18
|
-
return Math.max(1, Math.min(maxChunks, maxPossibleChunks));
|
|
19
|
-
}
|
|
20
|
-
function chunkFloat64Array(data, options = {}) {
|
|
21
|
-
const { minChunkSize, balanced } = {
|
|
10
|
+
function planChunks(totalElements, options = {}, unbalancedChunkMin = 0) {
|
|
11
|
+
const { balanced } = {
|
|
22
12
|
...DEFAULT_CHUNK_OPTIONS,
|
|
23
13
|
...options
|
|
24
14
|
};
|
|
25
|
-
|
|
26
|
-
if (totalElements === 0) return {
|
|
27
|
-
chunks: [],
|
|
28
|
-
chunkInfo: [],
|
|
29
|
-
totalElements: 0,
|
|
30
|
-
numChunks: 0
|
|
31
|
-
};
|
|
15
|
+
if (totalElements === 0) return [];
|
|
32
16
|
const numChunks = calculateOptimalChunks(totalElements, options);
|
|
33
|
-
if (numChunks <= 1) return {
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
chunkIndex: 0
|
|
40
|
-
}],
|
|
41
|
-
totalElements,
|
|
42
|
-
numChunks: 1
|
|
43
|
-
};
|
|
44
|
-
const chunks = [];
|
|
17
|
+
if (numChunks <= 1) return [{
|
|
18
|
+
startIndex: 0,
|
|
19
|
+
endIndex: totalElements,
|
|
20
|
+
length: totalElements,
|
|
21
|
+
chunkIndex: 0
|
|
22
|
+
}];
|
|
45
23
|
const chunkInfo = [];
|
|
46
24
|
if (balanced) {
|
|
47
25
|
const baseChunkSize = Math.floor(totalElements / numChunks);
|
|
@@ -50,7 +28,6 @@ function chunkFloat64Array(data, options = {}) {
|
|
|
50
28
|
for (let i = 0; i < numChunks; i++) {
|
|
51
29
|
const thisChunkSize = baseChunkSize + (i < remainder ? 1 : 0);
|
|
52
30
|
const endIndex = currentIndex + thisChunkSize;
|
|
53
|
-
chunks.push(data.subarray(currentIndex, endIndex));
|
|
54
31
|
chunkInfo.push({
|
|
55
32
|
startIndex: currentIndex,
|
|
56
33
|
endIndex,
|
|
@@ -60,13 +37,12 @@ function chunkFloat64Array(data, options = {}) {
|
|
|
60
37
|
currentIndex = endIndex;
|
|
61
38
|
}
|
|
62
39
|
} else {
|
|
63
|
-
const chunkSize = Math.max(
|
|
40
|
+
const chunkSize = Math.max(unbalancedChunkMin, Math.ceil(totalElements / numChunks));
|
|
64
41
|
let currentIndex = 0;
|
|
65
42
|
let chunkIndex = 0;
|
|
66
43
|
while (currentIndex < totalElements) {
|
|
67
44
|
const endIndex = Math.min(currentIndex + chunkSize, totalElements);
|
|
68
45
|
const thisChunkSize = endIndex - currentIndex;
|
|
69
|
-
chunks.push(data.subarray(currentIndex, endIndex));
|
|
70
46
|
chunkInfo.push({
|
|
71
47
|
startIndex: currentIndex,
|
|
72
48
|
endIndex,
|
|
@@ -77,73 +53,34 @@ function chunkFloat64Array(data, options = {}) {
|
|
|
77
53
|
chunkIndex++;
|
|
78
54
|
}
|
|
79
55
|
}
|
|
80
|
-
return
|
|
81
|
-
chunks,
|
|
82
|
-
chunkInfo,
|
|
83
|
-
totalElements,
|
|
84
|
-
numChunks: chunks.length
|
|
85
|
-
};
|
|
56
|
+
return chunkInfo;
|
|
86
57
|
}
|
|
87
|
-
function
|
|
88
|
-
const {
|
|
58
|
+
function calculateOptimalChunks(totalElements, options = {}) {
|
|
59
|
+
const { minChunkSize, maxChunks, targetChunkSize } = {
|
|
89
60
|
...DEFAULT_CHUNK_OPTIONS,
|
|
90
61
|
...options
|
|
91
62
|
};
|
|
92
|
-
|
|
63
|
+
if (totalElements === 0) return 0;
|
|
64
|
+
if (targetChunkSize > 0) return Math.min(maxChunks, Math.ceil(totalElements / targetChunkSize));
|
|
65
|
+
const maxPossibleChunks = Math.floor(totalElements / minChunkSize);
|
|
66
|
+
return Math.max(1, Math.min(maxChunks, maxPossibleChunks));
|
|
67
|
+
}
|
|
68
|
+
function assembleChunks(totalElements, options, minChunkSizeForPlan, whole, materialize) {
|
|
93
69
|
if (totalElements === 0) return {
|
|
94
70
|
chunks: [],
|
|
95
71
|
chunkInfo: [],
|
|
96
72
|
totalElements: 0,
|
|
97
73
|
numChunks: 0
|
|
98
74
|
};
|
|
99
|
-
const
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
endIndex: totalElements,
|
|
105
|
-
length: totalElements,
|
|
106
|
-
chunkIndex: 0
|
|
107
|
-
}],
|
|
75
|
+
const planned = calculateOptimalChunks(totalElements, options);
|
|
76
|
+
const chunkInfo = planChunks(totalElements, options, minChunkSizeForPlan);
|
|
77
|
+
if (planned <= 1) return {
|
|
78
|
+
chunks: [whole],
|
|
79
|
+
chunkInfo,
|
|
108
80
|
totalElements,
|
|
109
81
|
numChunks: 1
|
|
110
82
|
};
|
|
111
|
-
const chunks =
|
|
112
|
-
const chunkInfo = [];
|
|
113
|
-
if (balanced) {
|
|
114
|
-
const baseChunkSize = Math.floor(totalElements / numChunks);
|
|
115
|
-
const remainder = totalElements % numChunks;
|
|
116
|
-
let currentIndex = 0;
|
|
117
|
-
for (let i = 0; i < numChunks; i++) {
|
|
118
|
-
const thisChunkSize = baseChunkSize + (i < remainder ? 1 : 0);
|
|
119
|
-
const endIndex = currentIndex + thisChunkSize;
|
|
120
|
-
chunks.push(data.slice(currentIndex, endIndex));
|
|
121
|
-
chunkInfo.push({
|
|
122
|
-
startIndex: currentIndex,
|
|
123
|
-
endIndex,
|
|
124
|
-
length: thisChunkSize,
|
|
125
|
-
chunkIndex: i
|
|
126
|
-
});
|
|
127
|
-
currentIndex = endIndex;
|
|
128
|
-
}
|
|
129
|
-
} else {
|
|
130
|
-
const chunkSize = Math.ceil(totalElements / numChunks);
|
|
131
|
-
let currentIndex = 0;
|
|
132
|
-
let chunkIndex = 0;
|
|
133
|
-
while (currentIndex < totalElements) {
|
|
134
|
-
const endIndex = Math.min(currentIndex + chunkSize, totalElements);
|
|
135
|
-
const thisChunkSize = endIndex - currentIndex;
|
|
136
|
-
chunks.push(data.slice(currentIndex, endIndex));
|
|
137
|
-
chunkInfo.push({
|
|
138
|
-
startIndex: currentIndex,
|
|
139
|
-
endIndex,
|
|
140
|
-
length: thisChunkSize,
|
|
141
|
-
chunkIndex
|
|
142
|
-
});
|
|
143
|
-
currentIndex = endIndex;
|
|
144
|
-
chunkIndex++;
|
|
145
|
-
}
|
|
146
|
-
}
|
|
83
|
+
const chunks = chunkInfo.map((info) => materialize(info.startIndex, info.endIndex));
|
|
147
84
|
return {
|
|
148
85
|
chunks,
|
|
149
86
|
chunkInfo,
|
|
@@ -151,6 +88,16 @@ function chunkArray(data, options = {}) {
|
|
|
151
88
|
numChunks: chunks.length
|
|
152
89
|
};
|
|
153
90
|
}
|
|
91
|
+
function chunkFloat64Array(data, options = {}) {
|
|
92
|
+
const { minChunkSize } = {
|
|
93
|
+
...DEFAULT_CHUNK_OPTIONS,
|
|
94
|
+
...options
|
|
95
|
+
};
|
|
96
|
+
return assembleChunks(data.length, options, minChunkSize, data, (start, end) => data.subarray(start, end));
|
|
97
|
+
}
|
|
98
|
+
function chunkArray(data, options = {}) {
|
|
99
|
+
return assembleChunks(data.length, options, 0, data, (start, end) => data.slice(start, end));
|
|
100
|
+
}
|
|
154
101
|
function mergeFloat64Chunks(chunks) {
|
|
155
102
|
if (chunks.length === 0) return /* @__PURE__ */ new Float64Array(0);
|
|
156
103
|
if (chunks.length === 1) return chunks[0];
|
|
@@ -409,78 +356,6 @@ function toWorkerConfig(config) {
|
|
|
409
356
|
taskTimeout: config.taskTimeout
|
|
410
357
|
};
|
|
411
358
|
}
|
|
412
|
-
function _rowMajorStrides(shape) {
|
|
413
|
-
const strides = new Array(shape.length);
|
|
414
|
-
let stride = 1;
|
|
415
|
-
for (let i = shape.length - 1; i >= 0; i--) {
|
|
416
|
-
strides[i] = stride;
|
|
417
|
-
stride *= shape[i];
|
|
418
|
-
}
|
|
419
|
-
return strides;
|
|
420
|
-
}
|
|
421
|
-
function _flatIndex(idx, strides) {
|
|
422
|
-
let flat = 0;
|
|
423
|
-
for (let i = 0; i < idx.length; i++) flat += idx[i] * strides[i];
|
|
424
|
-
return flat;
|
|
425
|
-
}
|
|
426
|
-
function _forEachIndex(sizes, cb) {
|
|
427
|
-
const rank = sizes.length;
|
|
428
|
-
if (rank === 0) {
|
|
429
|
-
cb([]);
|
|
430
|
-
return;
|
|
431
|
-
}
|
|
432
|
-
const idx = new Array(rank).fill(0);
|
|
433
|
-
const total = sizes.reduce((a, b) => a * b, 1);
|
|
434
|
-
for (let n = 0; n < total; n++) {
|
|
435
|
-
cb(idx.slice());
|
|
436
|
-
for (let d = rank - 1; d >= 0; d--) {
|
|
437
|
-
idx[d]++;
|
|
438
|
-
if (idx[d] < sizes[d]) break;
|
|
439
|
-
idx[d] = 0;
|
|
440
|
-
}
|
|
441
|
-
}
|
|
442
|
-
}
|
|
443
|
-
function tensordotChunkKernel(a, aShape, b, bShape, axesA, axesB, resultShape, outStart, outEnd) {
|
|
444
|
-
const aStrides = _rowMajorStrides(aShape);
|
|
445
|
-
const bStrides = _rowMajorStrides(bShape);
|
|
446
|
-
const outStrides = _rowMajorStrides(resultShape);
|
|
447
|
-
const aRank = aShape.length;
|
|
448
|
-
const bRank = bShape.length;
|
|
449
|
-
const contractedAxesA = Array.from(axesA);
|
|
450
|
-
const contractedAxesB = Array.from(axesB);
|
|
451
|
-
const contractedSetA = new Set(contractedAxesA);
|
|
452
|
-
const contractedSetB = new Set(contractedAxesB);
|
|
453
|
-
const aFreeAxes = [];
|
|
454
|
-
const bFreeAxes = [];
|
|
455
|
-
for (let i = 0; i < aRank; i++) if (!contractedSetA.has(i)) aFreeAxes.push(i);
|
|
456
|
-
for (let i = 0; i < bRank; i++) if (!contractedSetB.has(i)) bFreeAxes.push(i);
|
|
457
|
-
const contractedSizes = contractedAxesA.map((ax) => aShape[ax]);
|
|
458
|
-
const chunkLen = outEnd - outStart;
|
|
459
|
-
const result = new Float64Array(chunkLen);
|
|
460
|
-
const outRank = resultShape.length;
|
|
461
|
-
const outIdx = new Array(outRank);
|
|
462
|
-
for (let outFlat = outStart; outFlat < outEnd; outFlat++) {
|
|
463
|
-
let rem = outFlat;
|
|
464
|
-
for (let d = 0; d < outRank; d++) {
|
|
465
|
-
outIdx[d] = Math.floor(rem / outStrides[d]);
|
|
466
|
-
rem -= outIdx[d] * outStrides[d];
|
|
467
|
-
}
|
|
468
|
-
const aFreeVals = outIdx.slice(0, aFreeAxes.length);
|
|
469
|
-
const bFreeVals = outIdx.slice(aFreeAxes.length);
|
|
470
|
-
let acc = 0;
|
|
471
|
-
_forEachIndex(contractedSizes, (contractVals) => {
|
|
472
|
-
const aIdx = new Array(aRank).fill(0);
|
|
473
|
-
for (let fi = 0; fi < aFreeAxes.length; fi++) aIdx[aFreeAxes[fi]] = aFreeVals[fi];
|
|
474
|
-
for (let ci = 0; ci < contractedAxesA.length; ci++) aIdx[contractedAxesA[ci]] = contractVals[ci];
|
|
475
|
-
const bIdx = new Array(bRank).fill(0);
|
|
476
|
-
for (let fi = 0; fi < bFreeAxes.length; fi++) bIdx[bFreeAxes[fi]] = bFreeVals[fi];
|
|
477
|
-
for (let ci = 0; ci < contractedAxesB.length; ci++) bIdx[contractedAxesB[ci]] = contractVals[ci];
|
|
478
|
-
acc += a[_flatIndex(aIdx, aStrides)] * b[_flatIndex(bIdx, bStrides)];
|
|
479
|
-
});
|
|
480
|
-
result[outFlat - outStart] = acc;
|
|
481
|
-
}
|
|
482
|
-
return result;
|
|
483
|
-
}
|
|
484
359
|
var ComputePool = class {
|
|
485
360
|
workerPool;
|
|
486
361
|
config;
|
|
@@ -517,6 +392,35 @@ var ComputePool = class {
|
|
|
517
392
|
parallelized: false
|
|
518
393
|
};
|
|
519
394
|
}
|
|
395
|
+
async gatedBinary(a, b, options) {
|
|
396
|
+
if (!this.shouldParallelize(a.length, options.op)) {
|
|
397
|
+
if (a.length !== b.length) throw new Error(`${options.op}: vectors must have the same length`);
|
|
398
|
+
return this.seqResult(options.sequential(a, b));
|
|
399
|
+
}
|
|
400
|
+
return toParallelResult(await options.worker(a, b));
|
|
401
|
+
}
|
|
402
|
+
async bitwiseBinary(a, b, options) {
|
|
403
|
+
if (a.length !== b.length) throw new Error(`Array lengths must match: ${a.length} vs ${b.length}`);
|
|
404
|
+
if (this.shouldParallelize(a.length, options.op)) return toParallelResult(await this.workerPool.bitwiseBinary(a, b, options.op));
|
|
405
|
+
const start = performance.now();
|
|
406
|
+
return {
|
|
407
|
+
result: options.fallback(a, b),
|
|
408
|
+
duration: performance.now() - start,
|
|
409
|
+
chunks: 1,
|
|
410
|
+
parallelized: false
|
|
411
|
+
};
|
|
412
|
+
}
|
|
413
|
+
async bitwiseShift(a, b, options) {
|
|
414
|
+
if (typeof b !== "number" && a.length !== b.length) throw new Error(`Array lengths must match: ${a.length} vs ${b.length}`);
|
|
415
|
+
if (this.shouldParallelize(a.length, options.op)) return toParallelResult(typeof b === "number" ? await this.workerPool.bitwiseScalar(a, b, options.op) : await this.workerPool.bitwiseBinary(a, b, options.op));
|
|
416
|
+
const start = performance.now();
|
|
417
|
+
return {
|
|
418
|
+
result: options.fallback(a, b),
|
|
419
|
+
duration: performance.now() - start,
|
|
420
|
+
chunks: 1,
|
|
421
|
+
parallelized: false
|
|
422
|
+
};
|
|
423
|
+
}
|
|
520
424
|
async exec(method, params, options) {
|
|
521
425
|
return this.workerPool.exec(method, params, options);
|
|
522
426
|
}
|
|
@@ -536,11 +440,11 @@ var ComputePool = class {
|
|
|
536
440
|
return toParallelResult(await this.workerPool.prod(data));
|
|
537
441
|
}
|
|
538
442
|
async dot(a, b) {
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
443
|
+
return this.gatedBinary(a, b, {
|
|
444
|
+
op: "dot",
|
|
445
|
+
sequential: pairwiseDot,
|
|
446
|
+
worker: (x, y) => this.workerPool.dot(x, y)
|
|
447
|
+
});
|
|
544
448
|
}
|
|
545
449
|
poolOptions(elementCount, op) {
|
|
546
450
|
return this.shouldParallelize(elementCount, op) ? { forceParallel: true } : { forceSequential: true };
|
|
@@ -615,11 +519,11 @@ var ComputePool = class {
|
|
|
615
519
|
return toParallelResult(await this.workerPool.norm(data));
|
|
616
520
|
}
|
|
617
521
|
async distance(a, b) {
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
522
|
+
return this.gatedBinary(a, b, {
|
|
523
|
+
op: "distance",
|
|
524
|
+
sequential: scaledDistance,
|
|
525
|
+
worker: (x, y) => this.workerPool.distance(x, y)
|
|
526
|
+
});
|
|
623
527
|
}
|
|
624
528
|
async histogram(data, bins, min, max) {
|
|
625
529
|
if (!this.shouldParallelize(data.length, "histogram")) {
|
|
@@ -851,7 +755,7 @@ var ComputePool = class {
|
|
|
851
755
|
}
|
|
852
756
|
return {
|
|
853
757
|
result: {
|
|
854
|
-
data: resultSize === 0 ? /* @__PURE__ */ new Float64Array(0) :
|
|
758
|
+
data: resultSize === 0 ? /* @__PURE__ */ new Float64Array(0) : tensordotRange(a, aShape, b, bShape, axesA, axesB, resultShape, 0, resultSize),
|
|
855
759
|
shape: resultShape
|
|
856
760
|
},
|
|
857
761
|
duration: performance.now() - start,
|
|
@@ -888,37 +792,22 @@ var ComputePool = class {
|
|
|
888
792
|
};
|
|
889
793
|
}
|
|
890
794
|
async bitAnd(a, b) {
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
result: bitAnd(a, b),
|
|
896
|
-
duration: performance.now() - start,
|
|
897
|
-
chunks: 1,
|
|
898
|
-
parallelized: false
|
|
899
|
-
};
|
|
795
|
+
return this.bitwiseBinary(a, b, {
|
|
796
|
+
op: "bitAnd",
|
|
797
|
+
fallback: bitAnd
|
|
798
|
+
});
|
|
900
799
|
}
|
|
901
800
|
async bitOr(a, b) {
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
result: bitOr(a, b),
|
|
907
|
-
duration: performance.now() - start,
|
|
908
|
-
chunks: 1,
|
|
909
|
-
parallelized: false
|
|
910
|
-
};
|
|
801
|
+
return this.bitwiseBinary(a, b, {
|
|
802
|
+
op: "bitOr",
|
|
803
|
+
fallback: bitOr
|
|
804
|
+
});
|
|
911
805
|
}
|
|
912
806
|
async bitXor(a, b) {
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
result: bitXor(a, b),
|
|
918
|
-
duration: performance.now() - start,
|
|
919
|
-
chunks: 1,
|
|
920
|
-
parallelized: false
|
|
921
|
-
};
|
|
807
|
+
return this.bitwiseBinary(a, b, {
|
|
808
|
+
op: "bitXor",
|
|
809
|
+
fallback: bitXor
|
|
810
|
+
});
|
|
922
811
|
}
|
|
923
812
|
async bitNot(a) {
|
|
924
813
|
if (this.shouldParallelize(a.length, "bitNot")) return toParallelResult(await this.workerPool.bitwiseNot(a));
|
|
@@ -931,37 +820,22 @@ var ComputePool = class {
|
|
|
931
820
|
};
|
|
932
821
|
}
|
|
933
822
|
async leftShift(a, b) {
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
result: leftShift(a, b),
|
|
939
|
-
duration: performance.now() - start,
|
|
940
|
-
chunks: 1,
|
|
941
|
-
parallelized: false
|
|
942
|
-
};
|
|
823
|
+
return this.bitwiseShift(a, b, {
|
|
824
|
+
op: "leftShift",
|
|
825
|
+
fallback: leftShift
|
|
826
|
+
});
|
|
943
827
|
}
|
|
944
828
|
async rightArithShift(a, b) {
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
result: rightArithShift(a, b),
|
|
950
|
-
duration: performance.now() - start,
|
|
951
|
-
chunks: 1,
|
|
952
|
-
parallelized: false
|
|
953
|
-
};
|
|
829
|
+
return this.bitwiseShift(a, b, {
|
|
830
|
+
op: "rightArithShift",
|
|
831
|
+
fallback: rightArithShift
|
|
832
|
+
});
|
|
954
833
|
}
|
|
955
834
|
async rightLogShift(a, b) {
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
result: rightLogShift(a, b),
|
|
961
|
-
duration: performance.now() - start,
|
|
962
|
-
chunks: 1,
|
|
963
|
-
parallelized: false
|
|
964
|
-
};
|
|
835
|
+
return this.bitwiseShift(a, b, {
|
|
836
|
+
op: "rightLogShift",
|
|
837
|
+
fallback: rightLogShift
|
|
838
|
+
});
|
|
965
839
|
}
|
|
966
840
|
async terminate(force = false) {
|
|
967
841
|
await this.workerPool.terminate(force);
|
|
@@ -986,6 +860,190 @@ var ComputePool = class {
|
|
|
986
860
|
};
|
|
987
861
|
const computePool = new ComputePool();
|
|
988
862
|
//#endregion
|
|
863
|
+
//#region src/WorkerPool.ts
|
|
864
|
+
var WorkerPool = class {
|
|
865
|
+
workers = [];
|
|
866
|
+
availableWorkers = [];
|
|
867
|
+
taskQueue = [];
|
|
868
|
+
activeTasks = /* @__PURE__ */ new Map();
|
|
869
|
+
maxWorkers;
|
|
870
|
+
workerScript;
|
|
871
|
+
isNode;
|
|
872
|
+
terminated = false;
|
|
873
|
+
constructor(workerScript, maxWorkers) {
|
|
874
|
+
this.workerScript = workerScript;
|
|
875
|
+
this.maxWorkers = maxWorkers || this.getOptimalWorkerCount();
|
|
876
|
+
this.isNode = typeof process !== "undefined" && process.versions?.node !== void 0;
|
|
877
|
+
this.initialize();
|
|
878
|
+
}
|
|
879
|
+
getOptimalWorkerCount() {
|
|
880
|
+
if (typeof navigator !== "undefined" && navigator.hardwareConcurrency) return Math.max(2, navigator.hardwareConcurrency - 1);
|
|
881
|
+
return 4;
|
|
882
|
+
}
|
|
883
|
+
async initialize() {
|
|
884
|
+
for (let i = 0; i < this.maxWorkers; i++) {
|
|
885
|
+
const worker = await this.createWorker();
|
|
886
|
+
if (this.terminated) {
|
|
887
|
+
worker.terminate();
|
|
888
|
+
return;
|
|
889
|
+
}
|
|
890
|
+
this.workers.push(worker);
|
|
891
|
+
this.availableWorkers.push(worker);
|
|
892
|
+
this.processQueue();
|
|
893
|
+
}
|
|
894
|
+
}
|
|
895
|
+
async createWorker() {
|
|
896
|
+
let worker;
|
|
897
|
+
if (this.isNode) {
|
|
898
|
+
const { Worker: NodeWorker } = await import("worker_threads");
|
|
899
|
+
const nodeWorker = new NodeWorker(this.workerScript.startsWith("file://") ? new URL(this.workerScript) : this.workerScript);
|
|
900
|
+
nodeWorker.on("message", (data) => {
|
|
901
|
+
this.handleWorkerMessage(worker, data);
|
|
902
|
+
});
|
|
903
|
+
nodeWorker.on("error", (error) => {
|
|
904
|
+
this.handleWorkerError(worker, { message: error.message });
|
|
905
|
+
});
|
|
906
|
+
worker = nodeWorker;
|
|
907
|
+
} else {
|
|
908
|
+
worker = new Worker(this.workerScript, { type: "module" });
|
|
909
|
+
worker.onmessage = (event) => {
|
|
910
|
+
this.handleWorkerMessage(worker, event.data);
|
|
911
|
+
};
|
|
912
|
+
worker.onerror = (error) => {
|
|
913
|
+
this.handleWorkerError(worker, error);
|
|
914
|
+
};
|
|
915
|
+
}
|
|
916
|
+
return worker;
|
|
917
|
+
}
|
|
918
|
+
handleWorkerMessage(worker, message) {
|
|
919
|
+
const task = this.activeTasks.get(message.id);
|
|
920
|
+
if (!task) return;
|
|
921
|
+
this.activeTasks.delete(message.id);
|
|
922
|
+
if (task.timeoutHandle) {
|
|
923
|
+
clearTimeout(task.timeoutHandle);
|
|
924
|
+
task.timeoutHandle = void 0;
|
|
925
|
+
}
|
|
926
|
+
if (message.type === "result") task.resolve(message.data);
|
|
927
|
+
else if (message.type === "error") task.reject(new Error(message.error || "Worker error"));
|
|
928
|
+
this.availableWorkers.push(worker);
|
|
929
|
+
this.processQueue();
|
|
930
|
+
}
|
|
931
|
+
handleWorkerError(worker, error) {
|
|
932
|
+
console.error("Worker error:", error);
|
|
933
|
+
for (const [id, task] of this.activeTasks) if (this.workers.includes(worker)) {
|
|
934
|
+
this.activeTasks.delete(id);
|
|
935
|
+
this.clearTaskTimer(task);
|
|
936
|
+
task.reject(/* @__PURE__ */ new Error(`Worker error: ${error.message}`));
|
|
937
|
+
}
|
|
938
|
+
}
|
|
939
|
+
processQueue() {
|
|
940
|
+
while (this.taskQueue.length > 0 && this.availableWorkers.length > 0) {
|
|
941
|
+
const task = this.taskQueue.shift();
|
|
942
|
+
const worker = this.availableWorkers.shift();
|
|
943
|
+
this.executeTask(worker, task);
|
|
944
|
+
}
|
|
945
|
+
}
|
|
946
|
+
executeTask(worker, task) {
|
|
947
|
+
this.activeTasks.set(task.id, task);
|
|
948
|
+
task.worker = worker;
|
|
949
|
+
const message = {
|
|
950
|
+
id: task.id,
|
|
951
|
+
type: "task",
|
|
952
|
+
data: task.data
|
|
953
|
+
};
|
|
954
|
+
if (task.transferables && task.transferables.length > 0) worker.postMessage(message, task.transferables);
|
|
955
|
+
else worker.postMessage(message);
|
|
956
|
+
}
|
|
957
|
+
async handleTaskTimeout(task, timeoutMs) {
|
|
958
|
+
const queuedAt = this.taskQueue.indexOf(task);
|
|
959
|
+
if (queuedAt >= 0) {
|
|
960
|
+
this.taskQueue.splice(queuedAt, 1);
|
|
961
|
+
task.reject(/* @__PURE__ */ new Error(`Worker task timed out after ${timeoutMs}ms`));
|
|
962
|
+
return;
|
|
963
|
+
}
|
|
964
|
+
if (!this.activeTasks.has(task.id)) return;
|
|
965
|
+
this.activeTasks.delete(task.id);
|
|
966
|
+
const dead = task.worker;
|
|
967
|
+
if (dead) {
|
|
968
|
+
try {
|
|
969
|
+
dead.terminate();
|
|
970
|
+
} catch {}
|
|
971
|
+
this.workers = this.workers.filter((w) => w !== dead);
|
|
972
|
+
this.availableWorkers = this.availableWorkers.filter((w) => w !== dead);
|
|
973
|
+
try {
|
|
974
|
+
const replacement = await this.createWorker();
|
|
975
|
+
if (this.terminated) {
|
|
976
|
+
replacement.terminate();
|
|
977
|
+
task.reject(/* @__PURE__ */ new Error(`Worker task timed out after ${timeoutMs}ms`));
|
|
978
|
+
return;
|
|
979
|
+
}
|
|
980
|
+
this.workers.push(replacement);
|
|
981
|
+
this.availableWorkers.push(replacement);
|
|
982
|
+
this.processQueue();
|
|
983
|
+
} catch (err) {
|
|
984
|
+
console.error("WorkerPool: failed to spawn replacement worker:", err);
|
|
985
|
+
}
|
|
986
|
+
}
|
|
987
|
+
task.reject(/* @__PURE__ */ new Error(`Worker task timed out after ${timeoutMs}ms`));
|
|
988
|
+
}
|
|
989
|
+
async execute(data, transferables, timeoutMs) {
|
|
990
|
+
return new Promise((resolve, reject) => {
|
|
991
|
+
if (this.terminated) {
|
|
992
|
+
reject(/* @__PURE__ */ new Error("WorkerPool terminated"));
|
|
993
|
+
return;
|
|
994
|
+
}
|
|
995
|
+
const task = {
|
|
996
|
+
id: this.generateTaskId(),
|
|
997
|
+
data,
|
|
998
|
+
resolve: (value) => resolve(value),
|
|
999
|
+
reject,
|
|
1000
|
+
transferables
|
|
1001
|
+
};
|
|
1002
|
+
if (typeof timeoutMs === "number" && timeoutMs > 0) task.timeoutHandle = setTimeout(() => {
|
|
1003
|
+
this.handleTaskTimeout(task, timeoutMs);
|
|
1004
|
+
}, timeoutMs);
|
|
1005
|
+
if (this.availableWorkers.length > 0) {
|
|
1006
|
+
const worker = this.availableWorkers.shift();
|
|
1007
|
+
this.executeTask(worker, task);
|
|
1008
|
+
} else this.taskQueue.push(task);
|
|
1009
|
+
});
|
|
1010
|
+
}
|
|
1011
|
+
generateTaskId() {
|
|
1012
|
+
return `task_${Date.now()}_${globalThis.crypto.randomUUID()}`;
|
|
1013
|
+
}
|
|
1014
|
+
async terminate() {
|
|
1015
|
+
this.terminated = true;
|
|
1016
|
+
for (const task of this.taskQueue) {
|
|
1017
|
+
this.clearTaskTimer(task);
|
|
1018
|
+
task.reject(/* @__PURE__ */ new Error("WorkerPool terminated"));
|
|
1019
|
+
}
|
|
1020
|
+
this.taskQueue = [];
|
|
1021
|
+
for (const task of this.activeTasks.values()) {
|
|
1022
|
+
this.clearTaskTimer(task);
|
|
1023
|
+
task.reject(/* @__PURE__ */ new Error("WorkerPool terminated"));
|
|
1024
|
+
}
|
|
1025
|
+
this.activeTasks.clear();
|
|
1026
|
+
for (const worker of this.workers) worker.terminate();
|
|
1027
|
+
this.workers = [];
|
|
1028
|
+
this.availableWorkers = [];
|
|
1029
|
+
}
|
|
1030
|
+
clearTaskTimer(task) {
|
|
1031
|
+
if (task.timeoutHandle !== void 0) {
|
|
1032
|
+
clearTimeout(task.timeoutHandle);
|
|
1033
|
+
task.timeoutHandle = void 0;
|
|
1034
|
+
}
|
|
1035
|
+
}
|
|
1036
|
+
get activeTaskCount() {
|
|
1037
|
+
return this.activeTasks.size;
|
|
1038
|
+
}
|
|
1039
|
+
get queuedTaskCount() {
|
|
1040
|
+
return this.taskQueue.length;
|
|
1041
|
+
}
|
|
1042
|
+
get workerCount() {
|
|
1043
|
+
return this.workers.length;
|
|
1044
|
+
}
|
|
1045
|
+
};
|
|
1046
|
+
//#endregion
|
|
989
1047
|
//#region src/operations/matmul.ts
|
|
990
1048
|
async function parallelMatmul(a, aRows, aCols, b, bCols, options = {}) {
|
|
991
1049
|
return (options.pool ?? computePool).matmul(a, aRows, aCols, b, bCols);
|
|
@@ -1231,4 +1289,4 @@ function calculateChunks(elementCount, category = "general") {
|
|
|
1231
1289
|
return thresholdDispatcher.calculateChunks(elementCount, category);
|
|
1232
1290
|
}
|
|
1233
1291
|
//#endregion
|
|
1234
|
-
export { ComputePool, DEFAULT_POOL_CONFIG, DEFAULT_THRESHOLDS, DEFAULT_THRESHOLD_BY_OP, ThresholdDispatcher, Transfer, bitAnd, bitNot, bitOr, bitXor, calculateChunks, calculateOptimalChunks, chunkArray, chunkFloat64Array, computePool, dispatch, leftShift, mergeArrayChunks, mergeFloat64Chunks, parallelAbs, parallelAdd, parallelCos, parallelCount, parallelDistance, parallelDivide, parallelDot, parallelElementwise, parallelEvery, parallelExp, parallelFilter, parallelFind, parallelForEach, parallelHistogram, parallelLog, parallelMap, parallelMatmul, parallelMatvec, parallelMax, parallelMean, parallelMin, parallelMinMax, parallelMultiply, parallelNegate, parallelNorm, parallelOuter, parallelReduce, parallelScale, parallelSin, parallelSome, parallelSort, parallelSqrt, parallelSquare, parallelStd, parallelSubtract, parallelSum, parallelTan, parallelTranspose, parallelUnary, parallelVariance, partition2D, partitionRange, resolveOpThreshold, rightArithShift, rightLogShift, shouldParallelize as shouldChunkParallelize, shouldParallelize$1 as shouldParallelize, thresholdDispatcher };
|
|
1292
|
+
export { ComputePool, DEFAULT_POOL_CONFIG, DEFAULT_THRESHOLDS, DEFAULT_THRESHOLD_BY_OP, ThresholdDispatcher, Transfer, WorkerPool, bitAnd, bitNot, bitOr, bitXor, calculateChunks, calculateOptimalChunks, chunkArray, chunkFloat64Array, computePool, dispatch, leftShift, mergeArrayChunks, mergeFloat64Chunks, parallelAbs, parallelAdd, parallelCos, parallelCount, parallelDistance, parallelDivide, parallelDot, parallelElementwise, parallelEvery, parallelExp, parallelFilter, parallelFind, parallelForEach, parallelHistogram, parallelLog, parallelMap, parallelMatmul, parallelMatvec, parallelMax, parallelMean, parallelMin, parallelMinMax, parallelMultiply, parallelNegate, parallelNorm, parallelOuter, parallelReduce, parallelScale, parallelSin, parallelSome, parallelSort, parallelSqrt, parallelSquare, parallelStd, parallelSubtract, parallelSum, parallelTan, parallelTranspose, parallelUnary, parallelVariance, partition2D, partitionRange, resolveOpThreshold, rightArithShift, rightLogShift, shouldParallelize as shouldChunkParallelize, shouldParallelize$1 as shouldParallelize, thresholdDispatcher };
|
package/dist/matrix.worker.d.ts
CHANGED
|
@@ -1,13 +1,2 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Matrix Worker for parallel computation
|
|
3
|
-
* Handles matrix operations in a separate thread.
|
|
4
|
-
*
|
|
5
|
-
* Each task computes a contiguous slice of the output and returns it. The
|
|
6
|
-
* parent ({@link ParallelMatrix}) copies returned slices back into the result
|
|
7
|
-
* buffer. Returning the data (rather than relying on in-place mutation of a
|
|
8
|
-
* shared buffer) keeps the worker correct whether or not the caller is using
|
|
9
|
-
* SharedArrayBuffer — a structured-clone copy of a non-shared `resultData`
|
|
10
|
-
* would otherwise be discarded and the caller would observe all zeros.
|
|
11
|
-
*/
|
|
12
1
|
export {};
|
|
13
2
|
//# sourceMappingURL=matrix.worker.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"matrix.worker.d.ts","sourceRoot":"","sources":["../src/matrix.worker.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"matrix.worker.d.ts","sourceRoot":"","sources":["../src/matrix.worker.ts"],"names":[],"mappings":""}
|
package/dist/matrix.worker.js
CHANGED
|
@@ -1,3 +1,12 @@
|
|
|
1
|
+
//#region src/gemm-rows.ts
|
|
2
|
+
function gemmRows(aData, aCols, bData, bCols, rowStart, rowEnd, out, outRowBase) {
|
|
3
|
+
for (let i = rowStart; i < rowEnd; i++) for (let j = 0; j < bCols; j++) {
|
|
4
|
+
let sum = 0;
|
|
5
|
+
for (let k = 0; k < aCols; k++) sum += aData[i * aCols + k] * bData[k * bCols + j];
|
|
6
|
+
out[(i - outRowBase) * bCols + j] = sum;
|
|
7
|
+
}
|
|
8
|
+
}
|
|
9
|
+
//#endregion
|
|
1
10
|
//#region src/matrix.worker.ts
|
|
2
11
|
const isNode = typeof process !== "undefined" && process.versions?.node !== void 0;
|
|
3
12
|
let nodeParentPort = null;
|
|
@@ -55,11 +64,7 @@ function multiplyTask(task) {
|
|
|
55
64
|
const { aData, aCols, bData, bCols, startRow, endRow } = task;
|
|
56
65
|
const rowCount = endRow - startRow;
|
|
57
66
|
const out = new Float64Array(rowCount * bCols);
|
|
58
|
-
|
|
59
|
-
let sum = 0;
|
|
60
|
-
for (let k = 0; k < aCols; k++) sum += aData[i * aCols + k] * bData[k * bCols + j];
|
|
61
|
-
out[(i - startRow) * bCols + j] = sum;
|
|
62
|
-
}
|
|
67
|
+
gemmRows(aData, aCols, bData, bCols, startRow, endRow, out, startRow);
|
|
63
68
|
return out;
|
|
64
69
|
}
|
|
65
70
|
function elementwiseTask(task, op) {
|
|
@@ -54,7 +54,10 @@ export interface ChunkOptions {
|
|
|
54
54
|
*/
|
|
55
55
|
export declare function calculateOptimalChunks(totalElements: number, options?: ChunkOptions): number;
|
|
56
56
|
/**
|
|
57
|
-
* Chunk a Float64Array into multiple smaller arrays
|
|
57
|
+
* Chunk a Float64Array into multiple smaller arrays.
|
|
58
|
+
*
|
|
59
|
+
* Split ranges are views (`subarray`). A single planned chunk returns `data`
|
|
60
|
+
* itself.
|
|
58
61
|
*
|
|
59
62
|
* @param data - The array to chunk
|
|
60
63
|
* @param options - Chunking options
|
|
@@ -62,7 +65,11 @@ export declare function calculateOptimalChunks(totalElements: number, options?:
|
|
|
62
65
|
*/
|
|
63
66
|
export declare function chunkFloat64Array(data: Float64Array, options?: ChunkOptions): ChunkResult<Float64Array>;
|
|
64
67
|
/**
|
|
65
|
-
* Chunk a generic array into multiple smaller arrays
|
|
68
|
+
* Chunk a generic array into multiple smaller arrays.
|
|
69
|
+
*
|
|
70
|
+
* Split ranges are copies (`slice`). A single planned chunk returns `data`
|
|
71
|
+
* itself. `planChunks` is called with minimum size 0, which is not the
|
|
72
|
+
* Float64 default.
|
|
66
73
|
*
|
|
67
74
|
* @param data - The array to chunk
|
|
68
75
|
* @param options - Chunking options
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"chunk.d.ts","sourceRoot":"","sources":["../../src/strategies/chunk.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH;;GAEG;AACH,MAAM,WAAW,WAAW,CAAC,CAAC;IAC5B,uBAAuB;IACvB,MAAM,EAAE,CAAC,EAAE,CAAC;IACZ,gCAAgC;IAChC,SAAS,EAAE,SAAS,EAAE,CAAC;IACvB,+BAA+B;IAC/B,aAAa,EAAE,MAAM,CAAC;IACtB,+BAA+B;IAC/B,SAAS,EAAE,MAAM,CAAC;CACnB;AAED;;GAEG;AACH,MAAM,WAAW,SAAS;IACxB,wCAAwC;IACxC,UAAU,EAAE,MAAM,CAAC;IACnB,kDAAkD;IAClD,QAAQ,EAAE,MAAM,CAAC;IACjB,2BAA2B;IAC3B,MAAM,EAAE,MAAM,CAAC;IACf,kBAAkB;IAClB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED;;GAEG;AACH,MAAM,WAAW,YAAY;IAC3B,iDAAiD;IACjD,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,yDAAyD;IACzD,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,mDAAmD;IACnD,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,4DAA4D;IAC5D,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;
|
|
1
|
+
{"version":3,"file":"chunk.d.ts","sourceRoot":"","sources":["../../src/strategies/chunk.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH;;GAEG;AACH,MAAM,WAAW,WAAW,CAAC,CAAC;IAC5B,uBAAuB;IACvB,MAAM,EAAE,CAAC,EAAE,CAAC;IACZ,gCAAgC;IAChC,SAAS,EAAE,SAAS,EAAE,CAAC;IACvB,+BAA+B;IAC/B,aAAa,EAAE,MAAM,CAAC;IACtB,+BAA+B;IAC/B,SAAS,EAAE,MAAM,CAAC;CACnB;AAED;;GAEG;AACH,MAAM,WAAW,SAAS;IACxB,wCAAwC;IACxC,UAAU,EAAE,MAAM,CAAC;IACnB,kDAAkD;IAClD,QAAQ,EAAE,MAAM,CAAC;IACjB,2BAA2B;IAC3B,MAAM,EAAE,MAAM,CAAC;IACf,kBAAkB;IAClB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED;;GAEG;AACH,MAAM,WAAW,YAAY;IAC3B,iDAAiD;IACjD,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,yDAAyD;IACzD,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,mDAAmD;IACnD,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,4DAA4D;IAC5D,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AA0FD;;;;;;GAMG;AACH,wBAAgB,sBAAsB,CAAC,aAAa,EAAE,MAAM,EAAE,OAAO,GAAE,YAAiB,GAAG,MAAM,CAgBhG;AAqDD;;;;;;;;;GASG;AACH,wBAAgB,iBAAiB,CAC/B,IAAI,EAAE,YAAY,EAClB,OAAO,GAAE,YAAiB,GACzB,WAAW,CAAC,YAAY,CAAC,CAK3B;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,UAAU,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,EAAE,OAAO,GAAE,YAAiB,GAAG,WAAW,CAAC,CAAC,EAAE,CAAC,CAErF;AAED;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,YAAY,EAAE,GAAG,YAAY,CAcvE;AAED;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,EAAE,GAAG,CAAC,EAAE,CAKtD;AAED;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAAC,YAAY,EAAE,MAAM,EAAE,SAAS,GAAE,MAAc,GAAG,OAAO,CAE1F;AAED;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,YAAY,GAAG,MAAM,CAE1D;AAED;;;;;;;GAOG;AACH,wBAAgB,cAAc,CAC5B,KAAK,EAAE,MAAM,EACb,GAAG,EAAE,MAAM,EACX,OAAO,GAAE,YAAiB,GACzB,KAAK,CAAC,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAsBzB;AAED;;;;;;;GAOG;AACH,wBAAgB,WAAW,CACzB,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,EACZ,OAAO,GAAE,YAAiB,GACzB,KAAK,CAAC,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC,CAKzC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@danielsimonjr/mathts-parallel",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.7.1",
|
|
4
4
|
"description": "WebWorker parallelization for MathTS computations",
|
|
5
5
|
"author": "Daniel Simon Jr.",
|
|
6
6
|
"license": "MIT",
|
|
@@ -42,8 +42,8 @@
|
|
|
42
42
|
}
|
|
43
43
|
},
|
|
44
44
|
"dependencies": {
|
|
45
|
-
"@danielsimonjr/mathts-workerpool": "^0.2.
|
|
46
|
-
"@danielsimonjr/mathts-core": "^0.
|
|
45
|
+
"@danielsimonjr/mathts-workerpool": "^0.2.7",
|
|
46
|
+
"@danielsimonjr/mathts-core": "^0.21.0"
|
|
47
47
|
},
|
|
48
48
|
"devDependencies": {
|
|
49
49
|
"@types/node": "^26.4.0",
|