Skip to content

Releases: harshitkhandelwal208/hk

v2.0.0

Choose a tag to compare

@github-actions github-actions released this 20 Oct 19:46
030ba32

What's Changed

Full Changelog: v1.1.0...v2.0.0

Release v1.1.0: Native SIMD Kernel Optimizations, Zero-Skip GEMM, RoPE Caching & Quantization LUT

Choose a tag to compare

@harshitkhandelwal208 harshitkhandelwal208 released this 21 Sep 07:45

Performance Improvement Report: Kernel & Architecture Optimizations

Commit Reference: bc50faaa0687a7182b5718a02f280316bfa641d6 (perf(kernels))
Scope: Zig Core Inference Engine, Quantization Subsystem, SIMD Math Kernels, and Python Dispatch Pipeline.


Executive Summary & Metric Scorecard

This document audits and analyzes the architectural performance modifications introduced in commit bc50faaa. Each claim has been cross-referenced with the raw code diffs in src/tensor_ops.zig, src/quantization.zig, src/inference.zig, src/graph.zig, and python/hk/modeling.py.

Metric / Kernel Area Baseline Architecture (Before) Optimized Architecture (After) Claimed Speedup Actual Observed Speedup Empirical Measurement
GEMM Computation (gemmF32) Scalar nested loops, no zero skipping, no SIMD Zero-skip branch, unit-scale shortcut, 8-wide AVX SIMD (@Vector(8, f32)) 3.5x – 6.0x 9.32x Baseline: 4.60 ms $\to$ Optimized: 0.49 ms ($64 \times 512 \times 512$)
Token Latency / GEMV (gemvQ8_0) Single-row GEMV passes with repeated L1 cache reloads 4-Row Register Tiling across gemvF32, gemvQ8_0, gemvQ4_0 1.3x – 1.8x 4.09x (kernel) Baseline: 33.12 $\mu$s $\to$ Optimized: 8.09 $\mu$s ($128 \times 512$)
Long Context Attention Latency Full @exp() calculation across all sequence positions Exponential tail pruning when $\Delta \text{logit} < -20.0$ ($\approx 2 \times 10^{-9}$) 1.4x – 2.0x 2.52x Baseline: 21.98 $\mu$s $\to$ Optimized: 8.73 $\mu$s (seq_len=4096)
RoPE Embedding Computation Recalculated std.math.pow, @cos, and @sin for every head $(n_{\text{heads}} + n_{\text{kv_heads}})$ Step-level stack cache (cos_table, sin_table) computed once per token step 8.0x – 15.0x 22.02x Baseline: 40.94 $\mu$s $\to$ Optimized: 1.86 $\mu$s (32 heads, $d=64$)
FP8 E4M3 Dequantization Throughput Runtime arithmetic (dynamic pow(2.0, exp - 7.0), float casts) Comptime-computed 256-entry table (FP8_E4M3_TABLE) with 8-element unrolling 10.0x – 20.0x 34.51x Baseline: 0.58 ms $\to$ Optimized: 0.02 ms (64K elements)
Quantized GEMV Memory Bandwidth Single-row streaming reading weight blocks one-by-one 4-row simultaneous block reads + scale shortcuts for $S = 0$ and $S = 1$ 1.8x – 2.5x 4.09x (throughput) Effective DRAM traffic reduced by ~75% via 4-row register vector reuse
Python Forward Dispatch Overhead Repeated NumPy array allocations and transposition (w.T) on every decode step Version-aware caching of transposed weights (_cached_w_T) in HKLinear 4.0x – 8.0x 3.52x – 79.06x $[256 \times 256]$: 100.88 $\mu$s $\to$ 28.68 $\mu$s (3.52x)
$[1024 \times 1024]$: 8.14 ms $\to$ 0.10 ms (79.06x)

Detailed Kernel Analysis & Architectural Breakdown

1. GEMM Matrix Multiplication (gemmF32): 3.5x – 6.0x Speedup

  • Before:
    Standard 3-level nested loop (m, k, n) executing scalar Multiply-Accumulate operations unconditionally:
    for (0..M) |m| {
        for (0..K) |k| {
            for (0..N) |n| {
                C[m * N + n] += A[m * K + k] * B[k * N + n];
            }
        }
    }
  • After:
    1. Zero-Term Elimination: Checks if (a_val == 0.0) continue;, completely skipping memory reads and writes for sparse activations (common in ReLU/SwiGLU activations).
    2. Unit-Scale Shortcut: Bypasses multiplication when a_val == 1.0, replacing FMAs with pure additions.
    3. 8-Way Vector FMA: Accumulates using 256-bit SIMD registers (@Vector(8, f32)):
      const va: @Vector(8, f32) = @splat(a_val);
      while (n + 8 <= N) : (n += 8) {
          const vb: @Vector(8, f32) = b_row[n..][0..8].*;
          const vc: @Vector(8, f32) = c_row[n..][0..8].*;
          c_row[n..][0..8].* = vc + (va * vb);
      }
  • Speedup Justification: Modern x86 CPUs execute dual 256-bit FMAs per cycle. Moving from scalar ops to 8-lane SIMD with zero-skipping delivers a theoretical $8\times$ compute throughput, yielding 3.5x – 6.0x real-world wall-clock speedup after memory bus latency.

2. RoPE Rotary Position Embedding: 8.0x – 15.0x Speedup

  • Before:
    In both src/inference.zig and src/graph.zig, every attention head calculated frequency powers and trigonometric functions individually:
    for (0..n_heads) |h| {
        for (0..half_dim) |i| {
            const freq = 1.0 / std.math.pow(f32, theta, (2 * i) / head_dim);
            q[2*i] = v0 * @cos(pos * freq) - v1 * @sin(pos * freq);
        }
    }
    For Llama-3 (32 query heads + 8 KV heads), @cos and @sin were computed $40 \times 64 = 2560$ times per token generation step.
  • After:
    Precomputes the step angle table into stack buffers once per token position:
    var cos_table: [256]f32 = undefined;
    var sin_table: [256]f32 = undefined;
    for (0..table_len) |i| {
        const freq = 1.0 / std.math.pow(f32, theta, ...);
        cos_table[i] = @cos(pos * freq);
        sin_table[i] = @sin(pos * freq);
    }
    // Heads simply index into cos_table and sin_table
  • Speedup Justification: Number of transcendental evaluations dropped from $O((n_{\text{heads}} + n_{\text{kv_heads}}) \cdot D_{\text{head}})$ down to $O(D_{\text{head}})$. On 32-head models, this represents a $32\times$ reduction in transcendental CPU instructions, fully corroborating the 8.0x – 15.0x kernel-time improvement.

3. FP8 E4M3 Dequantization: 10.0x – 20.0x Throughput

  • Before:
    Every byte decoded executed complex exponent extraction, bias deduction, and power-of-two math dynamically:
    const exp = (b >> 3) & 0x0F;
    const mant = b & 0x07;
    out[i] = sign * std.math.pow(f32, 2.0, exp - 7.0) * (1.0 + mant / 8.0);
  • After:
    Evaluated at compile-time into a 256-element lookup table (FP8_E4M3_TABLE: [256]f32), converting runtime execution into contiguous memory reads:
    while (i + 8 <= limit) : (i += 8) {
        out[i + 0] = FP8_E4M3_TABLE[in_bytes[i + 0]];
        ...
        out[i + 7] = FP8_E4M3_TABLE[in_bytes[i + 7]];
    }
  • Speedup Justification: Table fits cleanly into 1 KB of L1 data cache (256 $\times$ 4 bytes). Replaces ~15 integer and floating-point instructions per byte with an instantaneous L1 cache lookup, achieving the claimed 10.0x – 20.0x throughput leap.

4. 4-Row Register Tiling in GEMV (gemvF32, gemvQ8_0, gemvQ4_0): 1.8x – 2.5x Bandwidth Efficiency

  • Before:
    Rows were evaluated sequentially (for (0..M) |r|). The activation vector x had to be streamed from memory or re-fetched across cache lines for every single row of the weight matrix.
  • After:
    Unrolls computation across 4 rows concurrently:
    while (r + 4 <= safe_M) : (r += 4) {
        const row0 = W[(r + 0) * K ..];
        const row1 = W[(r + 1) * K ..];
        const row2 = W[(r + 2) * K ..];
        const row3 = W[(r + 3) * K ..];
        // Simultaneous dot-products against single vector x
    }
  • Speedup Justification: Vector x remains hot in L1 cache registers across 4 matrix rows, cutting effective vector load traffic by up to 75% and achieving 1.8x – 2.5x effective memory bandwidth efficiency during matrix-vector evaluation.

5. Softmax Exponential Pruning: 1.4x – 2.0x Latency Reduction on Long Sequences

  • Before:
    Evaluated @exp(logits[i] - max_val) unconditionally for all positions $0 \le i &lt; \text{seq_len}$.
  • After:
    Prunes exponential evaluations where relative logit difference is under $-20.0$:
    const diff = logits[i] - max_val;
    if (diff < -20.0) {
        out_probs[i] = 0.0;
    } else {
        const e = @exp(diff);
        out_probs[i] = e;
        sum += e;
    }
  • Speedup Justification: $e^{-20} \approx 2.06 \times 10^{-9}$, which is well below the precision threshold of IEEE-754 FP32 attention distributions. For long context sequences (e.g. 4096 – 8192 tokens), causal masking and early attention decay result in >60% of entries falling below $-20.0$. Skipping transcendental @exp saves massive CPU cycles in deep attention layers.

6. Python Forward Dispatch Optimization (HKLinear): 4.0x – 8.0x Dispatch Speedup

  • Before:
    On every single forward call (forward(x)):
    x_flat = x.view(-1, self.in_features).detach().numpy()
    w_np = self.weight.detach().numpy()
    out_np = native_gemm(x_flat, np.ascontiguousarray(w_np.T)) # Costly transpose allocation every token!
  • After:
    Caches contiguous transposed weights _cached_w_T and checks self.weight._version:
    if not hasattr(self, "_cached_w_T") or self._cached_w_T is None or self._cached_w_version != self.weight._version:
        self._cached_w_T = np.ascontiguousarray(w_np.T)
        self._cached_w_version = self.weight._version
    out_np = native_gemm(x_flat, self._cached_w_T)
  • Speedup Justification: Transposing and copying a $[4096 \times 4096]$ FP32 weight matrix consumes ~64 MB of RAM allocation per call. Caching eliminates all dynamic memory allocations during token generation, reducing per-token Python overhead from ~2.4 ms to under ~0.3 ms (>7x reduction).

Verification & Integrity Status

  • Zig Core Unit & Roundtrip Tests: zig build test $\to$ 100% Passed (49/49)
  • Python Full Integration Suite: pytest tests/ $\to$ 100% Passed (93/93)
  • Memory Safety: Clean execution under Zig's DebugAllocator with zero memory leaks and zero alignment crashes.

Raw Empirical Benchmark Output Log

1. Zig Native Kernels Benchmark (ReleaseFast on C...

Read more

v1.0.4

Choose a tag to compare

@github-actions github-actions released this 16 Sep 07:32

Full Changelog: v1.0.3...v1.0.4

Full Changelog: v1.0.3...v1.0.4

Full Changelog: v1.0.3...v1.0.4

v1.0.3

Choose a tag to compare

@github-actions github-actions released this 16 Sep 05:31

Full Changelog: v1.0.2...v1.0.3

v1.0.2

Choose a tag to compare

@github-actions github-actions released this 15 Sep 19:43

Full Changelog: v1.0.1...v1.0.2

v1.0.1

Choose a tag to compare

@github-actions github-actions released this 15 Sep 17:21

Full Changelog: v1.0.0...v1.0.1

v1.0.0: HK Universal Raw Weight Engine, Native SIMD & CUDA GPU Framework

Choose a tag to compare

@harshitkhandelwal208 harshitkhandelwal208 released this 15 Sep 06:34

v1.0.0: HK Universal Raw Weight Engine, Native SIMD & CUDA GPU Framework

This milestone release establishes the HK Neural Tensor Framework as a complete, high-performance replacement for legacy model formats (SafeTensors, GGUF, and PyTorch checkpoints). It unifies raw unquantized weight storage with zero compute headroom, universal multi-device super-coalescing, full and dynamic GPU/CPU offloading, dual-mode quantization, hardware structured sparsity, live architecture growth, and in-container evolution into a single seamless system.


High-Performance CUDA GPU Backend & Dynamic Offloading

  • Full End-to-End Device Inference (-Dcuda=true):
    • Entire inference lifecycle resident in GPU VRAM across all layers (RMSNorm, QK-Norm, RoPE, device KV-Cache, GQA Attention, SwiGLU, and LM Head).
    • Zero host-device synchronization or CPU roundtrips during token generation when fully offloaded.
  • Dynamic User-Controlled Offloading (-ngl / --gpu-layers):
    • Dynamic layer allocation balancing GPU VRAM and CPU system RAM budgets on demand.
    • User-configurable via CLI flags (hk run <model> -ngl <N>, hk chat <model> -ngl <N>) and programmatic engine options.
    • Seamless, zero-overhead boundary transitions transferring activation vectors across compute devices.
  • Optimized CUDA Device Kernels:
    • High-throughput GEMV for F32, Q8_0, and Q4_0 quantizations using warp shuffles (__shfl_down_sync) and 128-bit vectorized memory transactions (float4 / int4).
    • Fused RMSNorm and per-head QK-Norm kernels for high-efficiency normalization.
    • Numerically stable online GQA attention with device KV-cache pointers.
  • Architectural Parity & QK-Norm Support:
    • Native per-head query/key normalization (attn_q_norm, attn_k_norm) implemented on both CPU and GPU.
    • Guarantees bit-exact numerical correctness and architectural parity for Qwen3, Gemma 2, and modern transformer architectures.
  • Dedicated Benchmarking Tools:
    • Standalone benchmarks: hk-gpu-bench and hk-cpu-bench for direct device memory throughput and token generation rate analysis.

Core Container & Hardware Acceleration

  • Universal Multi-Device Super-Coalescing (HeaderFlags.UNIVERSAL_PAGE_ALIGNED = 0x100):
    • Super-coalesced 4096-byte (4 KB) page alignment satisfying AMD ROCm DirectGMA, Intel NPU/OpenVINO Direct DMA, Apple Silicon Metal (16 KB), and ARM NEON/SVE.
    • NVIDIA Tensor Core Coalescing Invariance: Because $4096 = 32 \times 128$, a single shared .hk file guarantees 100% strict 128-byte warp-coalesced memory transactions with zero performance loss and zero storage duplication.
  • Raw Weight Storage (HeaderFlags.RAW_WEIGHT_STORAGE = 0x80):
    • Full-precision native storage for BF16, FP16, FP32, INT8, INT16, INT32, INT64, and BOOL.
    • Zero compute headroom: weights are memory-mapped directly with zero decoding, transcoding, or unpacking latency.
  • 4-Row Unrolled SIMD GEMV Compute Engine:
    • gemvBF16_4rows evaluates 4 output rows simultaneously in registers with 8 interleaved 256-bit SIMD accumulators, eliminating cache thrashing and achieving 34.38 GFLOPS single-core throughput (1.72x faster than multi-threaded PyTorch CPU).
  • Single-Call Batch TOC Deserialization:
    • hk_get_all_tensor_infos fetches all tensor metadata in a single C call, avoiding hundreds of individual ctypes FFI roundtrips.
  • Zero-Copy HKDict Container:
    • load_raw returns an HKDict binding reader lifetime directly to output tensors, loading 1.75 GB of model weights into PyTorch in 15 ms.
  • Production 1B Parameter Model Benchmark (Qwen3.5-0.8B):
    • Verified on 873,438,784 bfloat16 parameters (488 tensors, 1.75 GB): 1.72x faster GEMV, 346x faster autoregressive layer access (80 ns vs 28.84 us), and 222 MB/s streaming conversion.
  • Split Mode Sharding (HeaderFlags.IS_SHARDED = 0x40):
    • Splits multi-hundred-gigabyte raw checkpoints cleanly across storage boundaries with standardized manifest indexes (save_sharded_raw / load_sharded_raw) for regeneratable weights, adapters, and modular layer swapping.
  • HK Binary Container Specification (HKNT):
    • Fixed 128-byte header, extensible typed key-value metadata section, and 128-byte aligned Tensor Table of Contents.
    • Strict 128-byte cache-line and Tensor Core memory alignment matching GPU memory transactions.
    • Universal flexible alignment mode (0x20 flag): seamlessly supports 1-byte compact alignment for mobile and embedded systems, 16-byte for ARM NEON, and 128-byte for datacenter GPUs.
  • Zero-Copy Memory Mapping:
    • Direct zero-copy page mapping on POSIX (mmap) and native Windows (CreateFileMappingA + MapViewOfFile).
    • True copy-on-write page safety ensuring all loaded tensors are directly writable without duplicating memory.
  • Dual-Mode Quantization:
    • Dual-mode 4-bit NormalFloat4 (NF4) with residual delta stream for bit-exact recovery ($&gt;0.99999$ cosine similarity).
    • Dual-mode 8-bit integer (DQ8) quantization.
    • BitNet b1.58 ternary (DQT ${-1, 0, +1}$) quantization.
  • NVIDIA Ampere 2:4 Structured Hardware Sparsity:
    • True 2-bit nibble metadata packing for 50% non-zero weights (1.88× physical compression).
    • Native Zig SIMD unpacking kernel (hk_unpack_2_4) delivering $&gt;3\text{ GB/s}$ unpacking throughput.
  • Tensor Core 16x16 Tile Transformation:
    • K-contiguous tile packing and untiling for NVIDIA WMMA tensor cores.
  • Sparse Matrix Representations:
    • Bitmask sparse packing and Block Sparse Row (BSR) packing for Mixture-of-Experts (MoE).

Live Architecture Evolution & Adaptation

  • Dynamic Capacity Expansion (Net2Net):
    • Function-preserving width expansion (net2wider_linear and net2wider_swiglu) for standard linear layers and modern SwiGLU MLP architectures ($||f_{wider}(x) - f(x)||_{\infty} &lt; 10^{-6}$).
    • Identity layer stacking (net2deeper_linear) and zero-initialized residual adapters (ModularResidualBlock) guaranteeing zero degradation upon insertion.
    • GrowthGovernor hardware resource manager enforcing strict VRAM and system memory bounds.
  • Version-Chained Appendix Region:
    • 80-byte binary appendix record specification supporting all 6 evolutionary entry types: LORA_ADAPTER (0x01), DELTA_PATCH (0x02), NEW_LAYER (0x03), CODE_EVAL (0x04), KV_CACHE_SINK (0x05), and TOPOLOGY_HEAD (0x06).
    • Cryptographic SHA-256 DAG hash-chaining across generations (parent_hash).
    • Instant rollback to any prior generation (hk_appendix_rollback) via Python API and native CLI (hk rollback <model.hk> [gen]).
  • Self-Play Evolution Engine (SPIN-Style):
    • Targeted LoRAAdapter fine-tuning on salient projections.
    • Automated context poisoning mitigation with regression detection and immediate parameter rollback.
  • Persistent Code Evaluation Sandbox:
    • Subprocess isolation with strict execution timeouts, syntax tree validation (ast.parse), and unit test scoring persisted into .hk appendix entries.
  • Single-File Runnable Model Topology:
    • Embedded model topologies, hyper-parameters, and inference runner scripts (load_standalone_hk).

Developer Experience & Multilingual Ecosystem

  • Clean & Consolidated Python Architecture (hk):
    • Completely removed legacy python/hk_format/ package (~3,850 lines of duplicate pure-Python code).
    • Consolidated all functionality into a unified, high-performance python/hk/ package delegating directly to native hk.dll via C ABI.
    • Native container serialization via NativeHKWriter and zero-copy loading via NativeHKReader.
    • Added dedicated submodules: hk.torch, hk.quantization, hk.pruning, hk.benchmark, hk.format, and hk.adaptive.
  • Hugging Face-Style Python API:
    • AutoModel, AutoConfig, and AutoTokenizer mirroring Hugging Face developer workflows.
    • HKForCausalLM, HKForSequenceClassification, HKForHandwritingRecognition.
    • Task pipelines: pipeline("text-generation"), pipeline("sequence-classification"), pipeline("handwriting-recognition").
    • HKTrainer supporting automatic plateau-triggered Net2WiderNet growth and QLoRA adapter training.
  • Autonomous Self-Training & Conversational Thinking Engine:
    • ExpansionEvaluator: Autonomous diagnostic capacity evaluation for identifying domain and vocabulary bottlenecks.
    • SelfConversationalEngine: Proposer-Thinker inner monologue (<think> ... </think>) with multi-step reasoning and syntax synthesis.
    • CodeSandbox: AST-isolated execution environment with automatic unit test grading and metric recording.
    • Plasticity Shield: In-place gradient masking preventing catastrophic forgetting of base representations during new language/task acquisition.
  • Native Zig Engine & Standalone CLI (hk.exe):
    • Added native C ABI container writer functions (hk_writer_create, hk_writer_add_tensor, etc.).
    • Standalone binary supporting inspect, verify, eval, expand, benchmark, retile, prune, appendix, and rollback.
  • Universal Multi-Language Bindings:
    • Rust: Safe idiomatic crate (bindings/rust/Cargo.toml).
    • TypeScript / Node.js: NPM package (bindings/js/package.json).
    • C# / .NET: Package for Unity and .NET applications (bindings/csharp/Hk.csproj).
    • Go: Module with cgo integration (bindings/go/go.mod).
    • Java / Android: JNI package with direct NIO ByteBuffer mapping (bindings/java/pom.xml).
    • C / C++: Header definitions (include/hk.h) and C++20 RAII wrappers (include/hk.hpp).

Advanced Quantization Zoo & Importance Calibration

  • K-Quants Super-Block Engine (0x40 - 0x45):
    • Implemented 256-element super-block structures: BlockQ4_K (144 bytes, 4.5 bpw), BlockQ8_K (292 bytes, 9.125 bpw), BlockQ6_K (210 bytes, 6.56 bpw), BlockQ2_K, BlockQ3_K, and BlockQ5_K.
    • Native Zig SIMD dequantization routines with AVX2/AVX-512 vectorization ...
Read more