For a long time, running NumPy in the browser meant running it without an accelerated BLAS. Matrix multiplications fell back to plain loops (portable, but blind to cache and SIMD).
That just changed. The Emscripten-forge NumPy package now links OpenBLAS in WebAssembly, and at n = 1024 square np.matmul jumps to about 30.92× faster ( float32 ) and 14.90× faster ( float64 ). The next OpenBLAS release, already available as an experimental package on Emscripten-forge, with kernels contributed by QuantStack, pushes it further, and an optional Relaxed SIMD build adds another step on engines that support it.
Emscripten-forge is a software distribution for WebAssembly. Together with conda-forge, it rebuilds the conda ecosystem for WebAssembly, so compilers, runtimes, and shared libraries ship as redistributable conda packages with a coherent ABI (not Python wheels, not R packages, but native libraries that any language ecosystem can link).
Bringing a scientific language to the browser is hard enough that, so far, it has mostly happened one language at a time. Pyodide pioneered it for Python. Later on, WebR did it for R, on the same premise. Each is a self-contained, language-specific distribution. Emscripten-forge takes a different shape: a language-agnostic distribution. It builds on the foundational work of the Pyodide and WebR projects, and goes further, covering not only Python and R, but also C++, OCaml, Lua, compiler toolchains, and many more tools (and shipping with a package manager).
Fortran sits at the core of foundational scientific packages: LAPACK, historically much of SciPy (although this is changing as SciPy has made strides to become Fortran-free), and R's compiled statistical routines are all Fortran underneath. Bringing any of them to WebAssembly therefore means bringing a Fortran compiler that can target wasm32 .
For a while, Pyodide worked around the absence of such a compiler: its SciPy build was produced with f2c, a Fortran-to-C translator, so the Fortran source was transpiled to C and compiled with the existing Emscripten toolchain. That workaround enabled SciPy to run in the browser, but it was not enough for R, whose distribution could not sidestep a real Fortran compiler. That constraint is what started the work on Flang (LLVM's Fortran frontend) for WebAssembly, in the context of bringing R to the browser on Emscripten-forge.
OpenBLAS is a widely used, optimized implementation of BLAS (Basic Linear Algebra Subprograms). BLAS is organized in three levels: Level 1 covers vector–vector operations (for example AXPY and dot products); Level 2 covers matrix–vector operations (for example GEMV, as in A @ x ); Level 3 covers matrix–matrix operations (for example GEMM, as in np.matmul ), which dominate large dense linear algebra. OpenBLAS also ships LAPACK (Linear Algebra PACKage): higher-level routines for solving linear systems, factorizations, and eigenproblems, and most np.linalg calls ultimately delegate to those LAPACK entry points.
Building a Fortran toolchain for WebAssembly was itself a multi-person effort. Isabel Paredes and Serge Guelton wrote the initial Flang patches for WebAssembly, inspired by George Stagg's work on Fortran in WebAssembly; Serge Guelton also upstreamed parts of that work into LLVM. Isabel Paredes now maintains the up-to-date recipe on Emscripten-forge, flang_emscripten-wasm32 .
But even with a working Flang, the toolchain alone was not enough to bring OpenBLAS to the browser. The first OpenBLAS and LAPACK builds could not be used immediately: WebAssembly enforces stricter calling conventions than native targets, and additional patches were needed to make the library compile, archive, and link under Emscripten. Ian Thomas adapted OpenBLAS for Flang and Emscripten; those patches live in the Emscripten-forge OpenBLAS recipe (the bridge between upstream OpenBLAS and the NumPy builds measured in this post).
The rest of this post walks the last mile: what changed when NumPy could finally call BLAS, and what OpenBLAS 0.3.34 and the upcoming 0.3.35 deliver.
... continue reading