Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions src/pages/sponsor/NumbaInWasm/GetAQuote.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import useDocusaurusContext from '@docusaurus/useDocusaurusContext';
import GetAQuotePage from '@site/src/components/fundable/GetAQuotePage';

export default function FundablePage() {
const { siteConfig } = useDocusaurusContext();
return (
<GetAQuotePage/>
);
}
9 changes: 9 additions & 0 deletions src/pages/sponsor/NumbaInWasm/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import useDocusaurusContext from '@docusaurus/useDocusaurusContext';
import LargeProjectCardPage from '@site/src/components/fundable/LargeProjectCardPage';

export default function FundablePage() {
const { siteConfig } = useDocusaurusContext();
return (
<LargeProjectCardPage/>
);
}
13 changes: 13 additions & 0 deletions src/pages/sponsor/_projectsDetails.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import Decimal32InArrowCppMD from "@site/src/pages/sponsor/descriptions/Decimal3
import Float16InArrowCppMD from "@site/src/pages/sponsor/descriptions/Float16InArrowCpp.md"
import RunEndEncodedInArrowCppMD from "@site/src/pages/sponsor/descriptions/RunEndEncodedInArrowCpp.md"
import ParquetNullOptimizationsMD from "@site/src/pages/sponsor/descriptions/ParquetNullOptimizations.md"
import NumbaInWasmMD from "@site/src/pages/sponsor/descriptions/NumbaInWasm.md"

export const fundableProjectsDetails = {
jupyterEcosystem: [
Expand Down Expand Up @@ -50,6 +51,18 @@ export const fundableProjectsDetails = {
currentFundingPercentage: 0,
repoLink: "https://github.com/geojupyter/jupytergis"
},
{
category: "Jupyter Ecosystem",
title: "Numba and llvmlite in the browser",
pageName: "NumbaInWasm",
shortDescription: "Numba, the standard JIT compiler for numerical Python, cannot run in Pyodide or emscripten-forge today. Its llvmlite backend relies on MCJIT, which WebAssembly does not allow. We have working demos of llvmlite and Numba scalar @jit in the browser. This proof-of-concept effort will resolve the remaining issues to make Numba work generally and initiate upstreaming of the patches.",

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's remove the MCJIT tidbit?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes

description: NumbaInWasmMD,
price: "TBD",
maxNbOfFunders: 1,
currentNbOfFunders: 0,
currentFundingPercentage: 0,
repoLink: "https://github.com/numba/llvmlite"
},
],
packageManagement: [
{
Expand Down
77 changes: 77 additions & 0 deletions src/pages/sponsor/descriptions/NumbaInWasm.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
#### Overview

[Numba](https://numba.pydata.org/) is the standard
just-in-time (JIT) compiler for numerical Python, widely used
across the scientific stack to accelerate compute-heavy code.
[Pyodide](https://pyodide.org/) brings CPython to the browser
through WebAssembly and powers JupyterLite, while
[emscripten-forge](https://github.com/emscripten-forge)
provides a conda-based package distribution for the same
target. Today, Numba cannot run in either environment.

We propose to make Numba and its JIT backend,
[llvmlite](https://github.com/numba/llvmlite),
browser-compatible using WebAssembly, and thus enabling
Pyodide and emscripten-forge users to JIT-compile numerical
code just like they do on a native CPython interpreter.

#### Why Numba in the Browser Matters

In a native CPython environment, many paths exist to make
numerical Python fast: Numba's JIT compilation,
multiprocessing, native C extensions, or offloading to a GPU.
In the browser, multithreading/processing and GPU access are
mostly unavailable, and shipping pre-compiled native
extensions for everything is impractical. In addition, the
Comment on lines +24 to +25

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Isn't "shipping pre-compiled native extensions" exactly what we do in emscripten-forge? Why would it be more impractical for the browser than for native code?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The key word is everything here. We can't ship compiled extensions for every loop and small code snippet. That is what is impractical on native and in the browser. Maybe it can be written better.

@pitrou pitrou Jul 22, 2026

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But this doesn't make sense either. The equation is for same for Wasm than it is for native code. Performance-critical Python scientific code is never written in pure Python. It's already available either in C/Rust/C++, or as Numba/Cython.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

2-5x slower for pure Python code sounds severe, but it's also small compared to the 50-100x faster that you can get with C/C++/Rust vs. pure Python. So you would want native extensions in the same situations regardless of whether the Python interpreter is running in Wasm or not.

@MMesch MMesch Jul 22, 2026

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess that depends on the situation and absolute numbers as well, 2x can be decisive or not at all.

Underlying is the argument that you have more incentives to JIT compile Python in the browser:

  • you generally pay a larger performance hit for Python in the browser than for compiled stuff (2x+ based on the numbers we cited).
  • it's more complicated to compile and load extensions manually in the browser. It's probably possible since done on the pyodide side afaik but seems involved in any case for the user.
  • you are in dynamic, notebook style situations requiring quick solutions that you can trigger immediately from the same interface.
  • What else would you do for acceleration? Multi threading, GPU aren't easily available.

And then you have libraries that use Numba anyway for acceleration and that might work out of the box if we had it available.

overhead of the Python interpreter is larger in the browser

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not convinced the overhead of the Python interpreter is larger in the browser, unless you can link to an independent study.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's generally cited in the pyodide community. The standard numbers are <2.5x native for compiled stuff (based on a 2019 paper), 2-5x for python (cited on pyodide issues in their roadmap and more based on their benchmarks). If you actually look at the pyodide benchmarks you could say 2 -10x though. I'll put a reference in. I don't think they have rigorously isolated the effect of the interpreter.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pyodide is not independent of course in that sense.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, perhaps link to a recent evaluation by PyOdide, then?
(I would stress recent, though; I wouldn't trust 2019 numbers to still apply currently, given that we're talking about a fast-moving ecosystem)

@MMesch MMesch Jul 22, 2026

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On performance numbers: I did a pretty long search and didn't find papers newer than the 2019 one. That paper "Not so Fast" is already an evolution to the older WASM paper which showed close to native performance for a different benchmark set. I recommend reading both. But the lack of newer studies is why new published benchmarks (even just as blog posts) for us, and for specific domains, are so important. The numbers I recently shared internally are all over the place, sometimes WASM is even a bit faster, often a bit (<2x) and sometimes much slower for compiled (10x+). But much is in the 2-5x range as the often cited numbers. My own numbers aren't able to isolate the interpreter overhead.

Pyodide has more numbers, but unfortunately they don't run their CI benchmarks regularly anymore it seems. You need to run them locally or find snapshots in issues. And even with those numbers available, to me the python browser overhead is anecdotal because I am unsure those benchmarks isolate the interpreter well (not because they are bad but because I didn't understand myself whether they do. And again, maybe I didn't find the right sources and others have a better understanding).

and many existing libraries use Numba, sometimes as hard

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
and many existing libraries use Numba, sometimes as hard
and many existing scientific libraries use Numba, sometimes as hard

requirements. JIT compilation is therefore an interesting
route to improved performance in a fully client-side,
browser-based Python environment.

#### Current Progress

We have already patched llvmlite and demonstrated that it runs
in the browser including compilation and execution of the WASM
code it generates. A live demo is available at
https://notebook.link/@anutosh491/llvmlite.

We also have a working demo of Numba's `@jit` decorator
operating on scalar functions in the browser. However, several
issues have been identified that must be overcome to make
Numba work generally (e.g. with arrays). These likely include
WebAssembly's lack of writable-and-executable memory pages
(which rules out MCJIT), unsupported atomic instructions
without shared memory, variadic C calls that cannot be lowered
to WASM, and linkage incompatibilities in the LLVM WASM PIC
backend. But these seem surmountable based on our experience.
Comment on lines +42 to +47

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would remove the details, some of which are probably wrong.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yea could do. It would be nice to show that we have some idea about the non trivial parts though.


#### Why QuantStack

QuantStack is uniquely positioned to deliver this work. We
have shipped several JIT and WebAssembly projects in the
scientific Python ecosystem, including
[xeus-cpp](https://github.com/jupyter-xeus/xeus-cpp), a C++
interpreter running in the browser via Clang and LLVM compiled
to WebAssembly. Our team also includes Numba core developers,
giving us a direct upstream relationship.
Comment on lines +56 to +57

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not even sure I still have commit rights on Numba, and we have nobody else in the Numba team. So this sentence is a lie AFAICT.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, core developer is not correct? Or the upstream relationship?

@pitrou pitrou Jul 22, 2026

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have not contributed to Numba since 2017 or 2018, I think. I don't have any reliable evaluation of my upstream relationship, but I wouldn't count on it. By default you cannot assume that we are in a privileged position.

I do have expertise in Numba, though, and the internals don't seem to have changed much. So you could stress that we have in-house Numba expertise (and such expertise is rather rare).

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok that sounds good to me. We can just write it as such.


#### Proposed Work

The goal of this project is to:

- upstream llvmlite compatibility with browser environments,
based on our existing patches.
- build a proof of concept for general Numba use in the browser to

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would say it's up to us to show a proof of concept before getting some funding. A sponsor will want dependable upstream changes for full-blown Numba functionality.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I thought about this as well. But my understanding is that the proof of concept itself is a significant undertaking, and probably the main challenge right now. Under that hypothesis, funding already for the PoC would be necessary because otherwise we may not be able to stem it ourselves.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure the effort to demonstrate JIT-acceleration of NumPy array code is that significant. @anutosh491 could perhaps give more insight.

- demonstrate, ideally all of Numba, or at least a large part of it, in the browser
- demonstrate the ability to run libraries that depend on it (such as pytensor/pymc) in the browser
- gather and understand the changes required
- upstream the required changes

Note that this is a proof of concept effort, we will advance
incrementally, deliver sub-parts, and adjust the plan based
on new learnings.

##### Are you interested in this project? Either entirely or
partially, contact us for more information on how to help us
fund it.
Loading