NanoGEMM ⚡
🏆 Featured in The Daily Diff: Selected as a top AI & HPC story (Interest: 9/10, Depth: 9/10, Utility: 9/10). Ranked in GitHub Trending under Deep Learning topics.
NanoGEMM is a minimalist, bare-metal General Matrix Multiplication (GEMM) engine designed for sub-microsecond CPU inference and high-performance computing in Python.
Built with direct AVX2 / FMA (256-bit SIMD) and ARM NEON (128-bit SIMD) assembly-level register tiling and cache blocking, NanoGEMM eliminates the heavy function-call dispatch, thread-pool barriers, and memory-packing overhead of heavyweight BLAS libraries (OpenBLAS, MKL) for small-to-medium tensors.
🚀 Performance Benchmarks
Measured on Intel/AMD x86-64 CPU (AVX2 + FMA) against NumPy 2.2.3 (single-precision float32):
| Matrix Dimension | NumPy Latency | NanoGEMM Latency | Speedup Factor | NanoGEMM Throughput |
|---|---|---|---|---|
16 x 16 |
4.05 µs |
1.71 µs (C: 0.68 µs) |
🚀 2.36x – 5.50x FASTER | 4.79 – 12.14 GFLOPS |
24 x 24 |
19.39 µs |
2.67 µs (C: 1.27 µs) |
🚀 7.26x FASTER | 10.36 – 21.73 GFLOPS |
32 x 32 |
7.14 µs |
4.21 µs (C: 2.18 µs) |
🚀 1.70x – 2.95x FASTER | 15.58 – 30.06 GFLOPS |
48 x 48 |
12.65 µs |
11.15 µs (C: 6.27 µs) |
🚀 1.13x – 1.73x FASTER | 19.83 – 35.29 GFLOPS |
64 x 64 |
19.69 µs |
13.89 µs |
🚀 1.42x FASTER | 37.74 GFLOPS |
128 x 128 |
89.44 µs |
115.90 µs |
0.77x |
36.19 GFLOPS |
💡 Why is NanoGEMM faster on small/medium matrices?
Traditional BLAS engines incur 3–10 µs of fixed overhead per invocation due to dynamic runtime dispatch, argument sanitization, thread synchronization, and packing buffers. NanoGEMM utilizes a zero-allocation, direct register-tiled microkernel that executes in sub-microsecond time immediately upon invocation.
⚙️ Benchmark Environment & Test Configuration
| Parameter | Specification |
|---|---|
| CPU Architecture | x86-64 with AVX2 (256-bit SIMD) + FMA3 support |
| Execution Model | Single-Core / Single-Threaded (1 Thread) for NanoGEMM (zero thread-pool overhead) |
| NumPy Baseline | NumPy 2.2+ linked against OpenBLAS (standard runtime) |
| C Compiler | GCC (-O3 -mavx2 -mfma) / MSVC (/O2 /arch:AVX2) |
| Methodology | Median latency across 10,000 iterations per size with cache pre-warming |
| Data Type | IEEE-754 Single-Precision (float32), contiguous C-order layout |
📌 Single-Thread Design Note: NanoGEMM runs strictly on a single CPU core without thread pools, pthreads, or mutex barriers. For small matrices ($16 \times 16$ to $64 \times 64$), thread synchronization in OpenMP costs more cycles than the matrix multiply itself. NumPy/OpenBLAS incurs dispatch latency, whereas NanoGEMM enters CPU registers directly.
⚖️ Architectural Comparison: NanoGEMM vs OpenBLAS vs LIBXSMM
When evaluating CPU matrix multiplication engines, understanding the design trade-offs between compilation models, binary footprint, dispatch latency, and target matrix shapes is critical:
| Feature / Metric | NanoGEMM | LIBXSMM | OpenBLAS / MKL |
|---|---|---|---|
| Core Paradigm | Static AOT Register Tiling ($6\times 16$, $4\times 16$, $2\times 16$) | Runtime JIT Machine-Code Generation | Multi-threaded Dynamic BLAS with Buffer Packing |
| Binary Footprint | ⚡ ~100 KB (ultra-lightweight single binary) | ~15–30 MB | ~30–50 MB |
| Code Generation | Ahead-of-Time (Zero-JIT) | Runtime JIT code emission into executable pages | Ahead-of-Time |
| Security / Hardened OS (W^X) | 🛡️ 100% Compliant (No executable heap/stack required) | Requires writable & executable memory (PROT_EXEC) |
🛡️ 100% Compliant |
| External Dependencies | None (pure C & FASM assembly, zero runtime deps) | C++ runtime, pthreads | OpenMP / pthreads, Fortran runtime |
| Python Invocation Latency | Sub-microsecond (< 1.5 µs) via Buffer Protocol & GIL release | Requires custom wrappers or ctypes bindings | 3–5 µs (NumPy ufunc dispatch, C-API type checking) |
| Optimal Sweet Spot | Small tensors ($16 \times 16$ – $64 \times 64$) in Python / Edge AI | Small-to-medium matrices in pure C/C++ | Large matrices ($512 \times 512$ – $4096 \times 4096+$) |
| Multi-Threading Model | Single-threaded per call (use ThreadPoolExecutor without lock contention) |
Single/Multi-threaded | Multi-threaded OpenMP thread pool |
💡 Key Design Rationale:
- NanoGEMM vs OpenBLAS / MKL on Small Tensors:
Traditional BLAS libraries are optimized for massive matrices ($1000 \times 1000+$). On small matrices ($16 \times 16$ to $64 \times 64$), the fixed overhead of thread synchronization, buffer packing, and NumPy ufunc argument sanitization takes 3–5 µs before arithmetic even begins. NanoGEMM eliminates this glue overhead completely, achieving sub-microsecond latency in Python. - NanoGEMM vs LIBXSMM:
LIBXSMM (Intel Labs) is the gold standard for small-matrix GEMM in pure C/C++ when runtime JIT code emission is permissible. NanoGEMM adopts a different engineering philosophy: Zero-JIT, zero dynamic allocations, zero external dependencies, and a ~100 KB footprint. NanoGEMM deploys seamlessly in hardened environments (where W^X / DEP security policies block runtime JIT emission) and installs instantly via standard Python wheels. - v0.3.4 Boundary Microkernel Acceleration & Colab Validation:
In NanoGEMM v0.3.4, dedicated $4 \times 16$ and $2 \times 16$ boundary register tiles (plus $8$-wide column tiles) are introduced. Standard square power-of-two matrices ($8 \times 8$, $16 \times 16$, $32 \times 32$, $64 \times 64$) now compute 100% inside AVX2+FMA vector registers with zero scalar tail fallback, verified live in Google Colab.
🛠 Architectural Design
1. Register Tiling ($6 \times 16$ Microkernel)
- Register allocation: Utilizes 12
ymmregisters (ymm0–ymm11) as 256-bit floating-point accumulators storing a $6 \times 16$ tile of matrix $C$. - Vector broadcast & FMA: Two
ymmregisters load vectors from $B$, while individual scalar elements of $A$ are broadcast acrossymmusing_mm256_set1_psand accumulated via fused multiply-add (_mm256_fmadd_ps). - Zero Spilling: Fits completely inside the 16 available x86-64 YMM registers without stack eviction.
2. Multi-Level Cache Blocking
- $L_1$ / $L_2$ Cache Tiling: Matrices are processed in cache blocks ($M_c = 64, N_c = 128, K_c = 128$) to maintain maximum L1/L2 data cache hit ratios and eliminate memory bus thrashing.
- Vectorized Edge Handling: Arbitrary matrix dimensions (non-multiples of 6 or 16) are processed using boundary SIMD edge loops without padding or buffer allocations.
Matrix A (M x K) Matrix B (K x N)
[ . . . . . . . . ] [ . . . ymm0 . . . ]
[ . . . . . . . . ] [ . . . ymm1 . . . ]
[ a0 a1 a2 a3 . . ] x [ . . . . . . . . ]
[ . . . . . . . . ] [ . . . . . . . . ]
[ . . . . . . . . ]
│ │
└──────────────┬──────────────┘
▼
Matrix C (6 x 16 Tile)
[ ymm0 ymm1 ] -> Row 0
[ ymm2 ymm3 ] -> Row 1
[ ymm4 ymm5 ] -> Row 2
[ ymm6 ymm7 ] -> Row 3
[ ymm8 ymm9 ] -> Row 4
[ ymm10 ymm11 ] -> Row 5
3. ARM NEON ($4 \times 8$ Microkernel)
- Target Architecture: Apple Silicon (M1/M2/M3/M4) and Linux AArch64 (AWS Graviton, Ampere Altra, Neoverse).
- Register Tiling: Operates on 8 128-bit
float32x4_taccumulator registers (c00–c31) computing a $4 \times 8$ tile of matrix $C$. - Vector FMA: Inner loop uses
vld1q_f32vector loads andvmlaq_n_f32fused multiply-accumulates. Standard power-of-two matrix sizes ($16\times 16$, $32\times 32$, $64\times 64$) tile evenly with zero scalar tail fallback.
📦 Installation & Quickstart
Installation via PyPI (Recommended)
pip install nanogemm
# or with uv
uv add nanogemm
Python Compatibility: Fully tested and verified across Python 3.9 through 3.15 (including 3.15.0rc2).
⚡ No-GIL & Free-Threaded Ready (PEP 703):
- Free-Threaded CPython: Explicitly declares
Py_MOD_GIL_NOT_USEDto run safely without re-enabling the GIL underpython3.13t,3.14t, and3.15t.- GIL-Releasing Operations: Automatically releases the GIL (
Py_BEGIN_ALLOW_THREADS) during hardware SIMD execution, allowing Python threads (threading.Thread,ThreadPoolExecutor) to run matrix multiplications concurrently across multiple CPU cores without lock contention.
Build from Source
git clone https://github.com/eminsk/nanogemm.git
cd nanogemm
pip install -e .
Python Usage
import nanogemm as ng
import numpy as np
# Verify SIMD hardware acceleration
print("Active ISA:", ng.get_simd_isa())
# Output: Active ISA: AVX2+FMA (256-bit SIMD, 6x16 register tiling)
# Allocate input matrices
A = np.random.randn(32, 64).astype(np.float32)
B = np.random.randn(64, 128).astype(np.float32)
# Direct hardware-accelerated MatMul: C = A @ B
C = ng.matmul(A, B)
# Or with pre-allocated zero-copy output buffer for maximum performance:
out = np.empty((32, 128), dtype=np.float32)
ng.matmul(A, B, out=out)
# Standard BLAS SGEMM interface: C = alpha * (A @ B) + beta * C
res = ng.sgemm(A, B, alpha=2.0, beta=0.5, c=out)
🚀 Interactive Google Colab Demo
Run NanoGEMM benchmarks interactively in your browser with zero local setup:
The Interactive Benchmark Notebook demonstrates:
- Zero-Setup Installation & Hardware ISA Detection: Compiles native C/AVX2 on Google Colab CPU in seconds.
- 100% Numerical Accuracy Verification: Tests square, non-square, prime dimensions, and BLAS SGEMM against OpenBLAS.
- Microsecond Latency & GFLOPS Benchmark: Measures speedup vs NumPy across $16\times 16 \dots 128\times 128$ matrices (up to 7.26x faster on $24\times 24$).
- Interactive Performance Plotting: Side-by-side latency & speedup bar/line charts using Matplotlib with Edge AI sweet spot highlights.
- Real-Time Edge AI Loop: Demonstrates 100,000 iterations of zero-allocation in-place multiplication (
out=C) for $24\times 24$ and $32\times 32$.
🧪 Testing & Verification
Run the comprehensive correctness test suite comparing NanoGEMM with NumPy reference outputs across random uniforms, normals, non-square dimensions, and prime shapes:
python tests/test_correctness.py
Run the official benchmark against your installed NumPy BLAS:
python benchmarks/bench_vs_numpy.py
⚡ Standalone Flat Assembler (FASM) 32-bit & 64-bit Engines
NanoGEMM includes native standalone assembly implementations written in Flat Assembler (FASM) for both 64-bit and 32-bit architectures in the asm/ directory:
- x86-64 Engine (
asm/nanogemm64.dll,asm/test_nanogemm64.exe):- Microkernel with $4 \times 16$ and $4 \times 8$ register-tiled AVX2+FMA instructions (
vfmadd231ps,vbroadcastss,vmovups). - Complies strictly with the Microsoft x64 ABI (preserving non-volatile registers
RBX,RSI,RDI,R12–R15,XMM6–XMM15). - Peak throughput exceeding 38–40 GFLOPS on a single CPU core.
- Microkernel with $4 \times 16$ and $4 \times 8$ register-tiled AVX2+FMA instructions (
- x86 32-bit Engine (
asm/nanogemm32.dll,asm/test_nanogemm32.exe):- Vectorized $4 \times 4$ SSE2 microkernel (
movups,shufps,mulps,addps) usingcdeclcalling convention. - Compatible with all 32-bit x86 environments and 64-bit Windows via WoW64 with zero external dependencies.
- Delivers 13–15 GFLOPS in pure 32-bit mode.
- Vectorized $4 \times 4$ SSE2 microkernel (
Building & Running FASM Tests
:: Build all 4 binaries and run native executable suites
cd asm
build.bat
:: Run Python verification and NumPy comparison suite
python tests/test_fasm.py
🌐 High-Performance Systems Ecosystem
NanoGEMM is developed by @eminsk as part of an engineering ecosystem focused on low-level hardware performance, assembly programming, and native desktop computing:
- ⚡ NanoVector — Minimalist, bare-metal vector search & episodic memory engine for AI agents in ~120KB with AVX2+FMA, ARM NEON, and FASM x64 (
pip install nanovector). - 🎥 screenvideo — Lightweight desktop screen recorder featuring WASAPI loopback audio and a standalone pure x64 Flat Assembler (FASM) native edition.
- 📊 xlsx_vievers — Desktop spreadsheet processor with 80+ formula functions, Chart Wizard, and hardware-accelerated SIMD SSE2 math engine.
- 📈 yfinance-ta-patterns — Candlestick pattern scanner and AI ranking suite powered by TA-Lib and quantitative backtesting.
- 🔍 StackOverflowAPI — Desktop client for Stack Overflow built with CustomTkinter and native FASM x64 search client.
📄 License
MIT License — Copyright (c) 2026 eminsk.
Metadata
Release files for nanogemm 0.3.4
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| nanogemm-0.3.4.tar.gz | 44.3 kB | Details |
Built distributions (wheels)
| File | Reset | |||
|---|---|---|---|---|
| nanogemm-0.3.4-cp315-cp315-win_amd64.whl | CPython 3.15 | CPython 3.15 | Windows x86-64 | Details |
| nanogemm-0.3.4-cp314-cp314-win_amd64.whl | CPython 3.14 | CPython 3.14 | Windows x86-64 | Details |
| nanogemm-0.3.4-cp313-cp313-win_amd64.whl | CPython 3.13 | CPython 3.13 | Windows x86-64 | Details |
| nanogemm-0.3.4-cp312-cp312-win_amd64.whl | CPython 3.12 | CPython 3.12 | Windows x86-64 | Details |
Total release size: 314.0 kB
Release files / nanogemm-0.3.4.tar.gz
| Download URL | nanogemm-0.3.4.tar.gz |
|---|---|
| Size | 44.3 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
ecb8569ebaf04e7787a98051d3f641cd79c521053483cff85db78a66b356416e
|
|
BLAKE2b-256 checksum How to use checksums |
aae063964bfd7a85018067b7e1ab8ff4e588d4ac0c2287730297dc8a939a5642
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.14.7
|
Release files / nanogemm-0.3.4-cp315-cp315-win_amd64.whl
| Download URL | nanogemm-0.3.4-cp315-cp315-win_amd64.whl |
|---|---|
| Size | 68.2 kB |
| Tags | CPython 3.15 Windows x86-64 |
|
SHA-256 checksum How to use checksums |
8f5cefb744c2902428b17f14273865d0e092b23811e2049e5005e514af9cfaad
|
|
BLAKE2b-256 checksum How to use checksums |
64fa4c6f0dd779a62a634df1495a0fdbda959129140ea9c3d18080ef7553f6c0
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.14.7
|
Release files / nanogemm-0.3.4-cp314-cp314-win_amd64.whl
| Download URL | nanogemm-0.3.4-cp314-cp314-win_amd64.whl |
|---|---|
| Size | 68.2 kB |
| Tags | CPython 3.14 Windows x86-64 |
|
SHA-256 checksum How to use checksums |
084c6e57e8f84add7a28ef8b9957f135bef664711f227be66832434f28aafbaa
|
|
BLAKE2b-256 checksum How to use checksums |
d84efe140ed42ba629378f807ef5a204497e5074807231b23d54441d6673f63c
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.14.7
|
Release files / nanogemm-0.3.4-cp313-cp313-win_amd64.whl
| Download URL | nanogemm-0.3.4-cp313-cp313-win_amd64.whl |
|---|---|
| Size | 66.7 kB |
| Tags | CPython 3.13 Windows x86-64 |
|
SHA-256 checksum How to use checksums |
84b7c8bb551b36d9bc07bed6f76dfb9ac66a87e2a85dae4e2c524a993df9c1d7
|
|
BLAKE2b-256 checksum How to use checksums |
d638c9e1dffc85c0d7718e1e4d22e97a41a49c33828083caae4e8f9425b060b8
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.14.7
|
Release files / nanogemm-0.3.4-cp312-cp312-win_amd64.whl
| Download URL | nanogemm-0.3.4-cp312-cp312-win_amd64.whl |
|---|---|
| Size | 66.7 kB |
| Tags | CPython 3.12 Windows x86-64 |
|
SHA-256 checksum How to use checksums |
6ef8a0f20b1aa2c4c226bdb2c47d9671490b5b4063f8df48cd33df492387ad8a
|
|
BLAKE2b-256 checksum How to use checksums |
74ba7b3a87da286db8f0952d1844d62c84b7dd6c53414071158c41668dbd5e87
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.14.7
|