JSPM

numrs-node

0.1.1
    • ESM via JSPM
    • ES Module Entrypoint
    • Export Map
    • Keywords
    • License
    • Repository URL
    • TypeScript Types
    • README
    • Created
    • Published
    • Downloads 15
    • Score
      100M100P100Q37978F
    • License AGPL-3.0-only

    Node.js bindings for NumRs

    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 build

      Quick 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)); // Float32Array

      API 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 number

      Shape 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 operations

      Benchmarking

      Run the comprehensive benchmark suite:

      node benchmark_gen.js

      This 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

      1. Use Float32Arrays directly - Avoid conversions from/to regular JavaScript arrays
      2. Batch operations - Process larger arrays to amortize overhead
      3. Reuse arrays - Create Float32Arrays once and reuse them
      4. 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:cpu

      License

      See LICENSE for details.

      See Also