はじめに
WASMatrix は AssemblyScript WebAssembly core に支えられた TypeScript 製 matrix library です。matrix buffer は WASM memory に保持され、f32 row-major storage を使い、WebAssembly SIMD を必須とします。
この guide では最初に必要になる内容を順に扱います:
- package の install
- matrix の作成
- matrix / elementwise / linear algebra operation の実行
- 必要な時だけ result を readback すること
- factorization cache と lazy view が効く場面の理解
インストール
npm install wasmatrix
WASMatrix は ESM-only です。package を import すると top-level await により隣接する WASM asset が初期化されます。
import Matrix from "wasmatrix";
package は JavaScript と WASM を別々に配布します。runtime は new URL("./wasmatrix.wasm", import.meta.url) で dist/wasmatrix.wasm を解決するため、Node、Deno、Bun、browser、CDN、bundler が通常の asset として扱えます。
実行要件
WASMatrix には ESM、top-level await、WebAssembly SIMD が必要です。SIMD validation に失敗した場合は scalar fallback せず initialization 時に throw します。
import { isSimdSupported } from "wasmatrix";
console.log(isSimdSupported());
最初のプログラムを実行する
hello.ts を作成し、小さな linear system を解きます。Deno と Bun は直接実行でき、Node project では通常の TypeScript toolchain を利用できます。
import Matrix from "wasmatrix";
const A = Matrix.from(2, 2, [
4, 7,
2, 6
]);
const b = Matrix.from(2, 1, [
1,
0
]);
const x = A.solve(b);
console.log("det(A)", A.determinant());
console.log("solution", x.toArray());
console.log("check", A.matmul(x).equalsApprox(b));
deno run --allow-read hello.ts
bun hello.ts
solve、determinant、matmul は WASM 内で実行されます。JavaScript が値を受け取るのは toArray()、determinant()、equalsApprox() などで readback した時だけです。
行列を作成する
Matrix.from(rows, cols, values) は row-major values を受け取ります。zeros、ones、identity、diagonal などの static constructor は後続 shortcut のための structure tag も保持します。
const A = Matrix.from(2, 3, [
1, 2, 3,
4, 5, 6
]);
const Z = Matrix.zeros(3, 3);
const O = Matrix.ones(3, 2);
const I = Matrix.identity(4);
const D = Matrix.diagonal([2, 4, 8]);
データを WASM に保持する
多くの method は別の Matrix を返し、結果は WASM memory に留まります。JavaScript 側で値が必要になった時だけ toArray()、toFloat32Array()、row()、column()、diagonal() で readback してください。
const result = A
.scale(2)
.addScalar(1)
.sqrt()
.clamp(0, 4);
const values = result.toArray();
Elementwise Pipelines
Elementwise chain は lazy に表現され、materialize 時に 1 つの WASM pass へ fusion されます。row/column vector は dense matrix に展開せず broadcast できます。
const Y = A
.add(B)
.subtract(0.25)
.hadamard(C)
.clamp(-2, 2)
.sqrt();
const centered = X.subtract(rowMeans);
const scaled = centered.divide(columnStddev);
密な逆行列を作らない線形代数
A^-1 B が欲しい場合は solve() を優先してください。同じ matrix object では versioned LU、Cholesky、QR cache を determinant、solve、inverse、rank の間で再利用できます。
const x = A.solve(b);
const det = A.determinant();
const again = A.solve(otherRightHandSide);
変更と cache invalidation
set() は matrix version を進め、factorization、reduction、packed operand、materialized view の cache を invalidate します。cache reuse したい場合は係数 matrix object を安定させてください。
A.set(0, 0, A.at(0, 0) + 1);
Configuration
fastMath はより積極的な代数 rewrite を有効化します。cacheLimitBytes は reusable cache が使う WASM heap budget を制御します。
import { configure } from "wasmatrix";
configure({
fastMath: false,
cacheLimitBytes: 64 * 1024 * 1024
});
長寿命の temporary を dispose する
長時間動く service、app、benchmark では、不要になった大きな temporary に dispose() を呼んでください。
const tmp = A.matmul(B);
try {
console.log(tmp.frobeniusNorm());
} finally {
tmp.dispose();
}
開発ビルド
deno task build は AssemblyScript kernel、TypeScript runtime、配布用 WASM file を compile します。benchmark suite は timing、speedup、checksum を JSON で出力します。
deno task build
deno task test
deno task test:e2e
deno task benchmark
次に読むもの
全 method、structural shortcut、cache behavior、memory management の詳細は API Guide を読んでください。