# DGEMM in Mojo with NEON and SME2 micro kernels

**URL:** <https://forum.modular.com/t/dgemm-in-mojo-with-neon-and-sme2-micro-kernels/3670>\
**Category:** General\
**Created:** [November 13, 2026, 9:19pm UTC](https://forum.modular.com/t/dgemm-in-mojo-with-neon-and-sme2-micro-kernels/3670 "2026-11-13T21:19:14Z")\
**Posts on this page:** 3\
**Page:** 1

<div class="post-metadata">

**Author:** ![michael-lehn](https://avatars.discourse-cdn.com/v4/letter/m/7ba0ec/32.png) [@michael-lehn](https://forum.modular.com/u/michael-lehn)\
**Post date:** [November 13, 2026, 9:19pm UTC](https://forum.modular.com/t/dgemm-in-mojo-with-neon-and-sme2-micro-kernels/3670/1 "2026-11-13T21:19:15Z")

</div>

Hi everyone,

I am evaluating if one can write a high performance DGEMM (double precision general matrix-matrix multiply) in Mojo. So I tried: [GitHub - michael-lehn/mojo-gemm: DGEMM in Mojo with NEON and SME2 micro kernels, benchmarked on Apple M5 · GitHub](https://github.com/michael-lehn/mojo-gemm)

About me: I wrote ulmBLAS, a BLAS (Basic Linear Algebra Subprograms) library in C++. Also FLENS-LAPACK. This is my first experiement with Mojo. It is not a full port of ulmBLAS. It is more what my students implement in my HPC (High Performance Computing) course.

The idea is simple. Pack blocks of A and B. A macro kernel runs over the packed blocks. A micro kernel keeps a small tile of C in registers. Row major, column major and arbitrary strides all work. Like in BLIS (BLAS-like Library Instantiation Software).

The micro kernels are from ulmBLAS:

- NEON (8 x 6) is plain Mojo SIMD (single instruction, multiple data) code
- SME2 (Scalable Matrix Extension 2, 32 x 16) is inline assembly

Results on an Apple M5, one thread. Compared with ulmBLAS and Apple Accelerate:

- large matrizes: about 2% behind ulmBLAS with NEON, about 5% with SME2
- small matrizes: SME2 falls behind. At n = 250 its about 63% of ulmBLAS

The gap for small matrizes is my port, not Mojo. ulmBLAS packs in streaming mode. It handles partial tiles with predicates. The Mojo code dont do that yet.

How Mojo felt:

- The SIMD types are nice. The NEON kernel is plain Mojo. Its as fast as the C++ one.
- Inline assembly for SME2 works. smstart/smstop go inside the asm block.
- Streaming functions work too. `@__llvm_metadata(`llvm.arm_streaming`)` and the compiler does smstart/smstop. Not documented, found it by trial and error.
- The exclusivity checker rejects two mutable pointers into the same matrix. `MutUntrackedOrigin` solved it. Took me a while to find that.

Next I am thinking about LAPACK (Linear Algebra PACKage) in Mojo. First blocked Cholesky, LU and the solvers. Later QR, SVD (singular value decomposition) and eig. Is somebody allready working on this? Or are there plans at Modular? Happy about any feedback.

Also asked the NuMojo folks: [DGEMM in Mojo: close to C++ for large matrices, behind for small ones · Mojo-Numerics-and-Algorithms-group/NuMojo · Discussion #437 · GitHub](https://github.com/Mojo-Numerics-and-Algorithms-group/NuMojo/discussions/437)

---

<div class="post-metadata">

**Author:** ![Ehsan](https://sea1.discourse-cdn.com/flex001/user_avatar/forum.modular.com/ehsan/32/142_2.png) [@Ehsan](https://forum.modular.com/u/Ehsan)\
**Post date:** [November 13, 2026, 10:31pm UTC](https://forum.modular.com/t/dgemm-in-mojo-with-neon-and-sme2-micro-kernels/3670/2 "2026-11-13T22:31:18Z")

</div>

That’s great! I’ve been working on this on the side [GitHub - ehsanmok/numax: NumPy and SciPy for Mojo and MAX on any Accelerator · GitHub](https://github.com/ehsanmok/numax). Please feel free to contribute if you’d like 🙂

---

<div class="post-metadata">

**Author:** ![michael-lehn](https://avatars.discourse-cdn.com/v4/letter/m/7ba0ec/32.png) [@michael-lehn](https://forum.modular.com/u/michael-lehn)\
**Post date:** [November 13, 2026, 10:59pm UTC](https://forum.modular.com/t/dgemm-in-mojo-with-neon-and-sme2-micro-kernels/3670/3 "2026-11-13T22:59:35Z")

</div>

Thanks, I will look into it!
