Package Exports
This package does not declare an exports field, so the exports above have been automatically detected and optimized by JSPM instead. If any package subpath is missing, it is recommended to post an issue to the original package (@numrs/node) to support the "exports" field. If that is not possible, create a JSPM override to customize the exports field for this package.
Readme
NumRs JavaScript Bindings
High-performance Node.js bindings for NumRs with zero-copy Float32 operations powered by Intel MKL.
✨ Features
- 🚀 Zero-Copy Operations: Direct Float32Array access with no conversions (5-7x faster than standard API)
- ⚡ Intel MKL Backend: Optimized BLAS operations with multi-threading support
- 📊 25+ Operations: Binary, unary, reduction, linear algebra, and shape operations
- 💾 Memory Efficient: 50% memory reduction using Float32 instead of Float64
- 🔧 Type Safe: Full TypeScript definitions included
Performance
Benchmark results on 12th Gen Intel Core i9-12900HK:
| Operation Category | Average Throughput | Best Performance |
|---|---|---|
| Matrix Multiplication | 40.44 Gops/s | 114.13 Gops/s (512×512) |
| Reduction Operations | 513.54 Mops/s | 803.79 Mops/s (min) |
| Binary Operations | 164.59 Mops/s | 278 Mops/s (sub) |
| Unary Operations | 161.75 Mops/s | 577 Mops/s (neg) |
See BENCHMARK_JS_12th_Gen_IntelR_CoreTM_i9-12900HK.md for complete benchmark results.
Installation
npm install
npm run buildQuick Start
const numrs = require('./index.node');
// Create Float32Arrays
const size = 10000;
const a = new Float32Array(size);
const b = new Float32Array(size);
// Initialize with random data
for (let i = 0; i < size; i++) {
a[i] = Math.random();
b[i] = Math.random();
}
// Zero-copy operations with clean API!
const result = numrs.add(a, [size], b, [size]);
console.log('Result:', result.slice(0, 5)); // Float32ArrayAPI Reference
All operations work directly with Float32Arrays - no type conversions!
Binary Operations
Operations on two arrays of the same shape:
// Syntax: operation(data1, shape1, data2, shape2) -> Float32Array
numrs.add(a, [rows, cols], b, [rows, cols]);
numrs.sub(a, [rows, cols], b, [rows, cols]);
numrs.mul(a, [rows, cols], b, [rows, cols]);
numrs.div(a, [rows, cols], b, [rows, cols]);
numrs.pow(a, [rows, cols], b, [rows, cols]);Unary Operations
Operations on a single array:
// Syntax: operation(data, shape) -> Float32Array
numrs.sin(data, [size]);
numrs.cos(data, [size]);
numrs.tan(data, [size]);
numrs.exp(data, [size]);
numrs.log(data, [size]);
numrs.sqrt(data, [size]);
numrs.abs(data, [size]);
numrs.relu(data, [size]);
numrs.sigmoid(data, [size]);
numrs.tanh(data, [size]);Special case - Negation:
// Returns Array<number> instead of Float32Array
const result = numrs.neg(data, [size]); // Array<number>
const typedResult = new Float32Array(result);Reduction Operations
Operations that reduce an array to a single scalar:
// Syntax: operation(data, shape) -> number
const total = numrs.sum(data, [rows, cols]);
const average = numrs.mean(data, [rows, cols]);
const maximum = numrs.max(data, [rows, cols]);
const minimum = numrs.min(data, [rows, cols]);
const variance = numrs.variance(data, [rows, cols]);Linear Algebra
// Matrix multiplication: (M×K) @ (K×N) -> (M×N)
const result = numrs.matmul(
matA, [M, K], // First matrix
matB, [K, N] // Second matrix
); // Returns Float32Array of size M*N
// Dot product: returns scalar
const dotResult = numrs.dot(
vecA, [size],
vecB, [size]
); // Returns numberShape Operations
// Transpose: (M×N) -> (N×M)
const transposed = numrs.transpose(data, [rows, cols]);
// Reshape: change dimensions without copying data
const reshaped = numrs.reshape(data, [oldShape], [newShape]);Complete Example
See example.js for a comprehensive demo of all operations.
const numrs = require('./index.node');
// Binary operations
const a = new Float32Array([1, 2, 3, 4]);
const b = new Float32Array([5, 6, 7, 8]);
const sum = numrs.add(a, [4], b, [4]);
console.log('Sum:', sum); // Float32Array [6, 8, 10, 12]
// Unary operations
const angles = new Float32Array([0, Math.PI/4, Math.PI/2]);
const sines = numrs.sin(angles, [3]);
console.log('Sine:', sines);
// Reductions
const data = new Float32Array([1, 2, 3, 4, 5]);
console.log('Sum:', numrs.sum(data, [5])); // 15
console.log('Mean:', numrs.mean(data, [5])); // 3
// Matrix multiplication
const matA = new Float32Array([1, 2, 3, 4]); // 2×2
const matB = new Float32Array([5, 6, 7, 8]); // 2×2
const product = numrs.matmul(matA, [2, 2], matB, [2, 2]);
console.log('Matrix product:', product); // Float32Array [19, 22, 43, 50]TypeScript Support
Full TypeScript definitions are available:
import type { Float32Array } from './index';
declare function add(
data1: Float32Array,
shape1: number[],
data2: Float32Array,
shape2: number[]
): Float32Array;
// ... all other operationsBenchmarking
Run the comprehensive benchmark suite:
node benchmark_gen.jsThis generates a detailed markdown report with:
- System configuration
- Performance metrics for all 77 operation/size combinations
- Throughput statistics (Mops/s and Gops/s)
- Operation categories and summaries
Performance Tips
- Use Float32Arrays directly - Avoid conversions from/to regular JavaScript arrays
- Batch operations - Process larger arrays to amortize overhead
- Reuse arrays - Create Float32Arrays once and reuse them
- Matrix sizes - MKL performs best with matrices ≥256×256
Legacy API
The original JsArray-based API has been deprecated in favor of the zero-copy Float32Array API:
// Old (deprecated) - 5-7x slower
const a = numrs.array([2, 2], [1, 2, 3, 4], 'float32');
const b = numrs.array([2, 2], [5, 6, 7, 8], 'float32');
const result = numrs.add(a, b);
// New (recommended) - Zero-copy, ultra fast!
const aData = new Float32Array([1, 2, 3, 4]);
const bData = new Float32Array([5, 6, 7, 8]);
const result = numrs.add(aData, [2, 2], bData, [2, 2]);Building from Source
# Debug build
cargo build
# Release build with optimizations
npm run build
# CPU-only (no WebGPU)
npm run build:cpuLicense
See LICENSE for details.