jaxknn
Exact k-nearest neighbours in JAX: a kd-tree that traces under jit, vmap and grad.
pip install jaxknn
>>> import jax
>>> import jax.numpy as jnp
>>> import jaxknn
>>> points = jax.random.normal(jax.random.key(0), (1000, 3))
>>> idx, dist = jaxknn.knn(points, 5) # each point's 5 nearest *other* points
>>> idx.shape, dist.shape
((1000, 5), (1000, 5))
>>> queries = jnp.zeros((2, 3))
>>> idx, dist = jax.jit(lambda p, q: jaxknn.knn(p, 1, queries=q))(points, queries)
>>> idx.shape
(2, 1)
What it gives you
- Exact results. No approximation. Ties go to the lower index, identically eagerly and under
jit. - Fully traceable.
knnworks insidejit,vmapandgrad. Distances are differentiable with respect to the coordinates, with the neighbour selection held fixed, and the gradient is 0 rather than NaN at coincident points. - Robust inputs.
- NaN or inf input is an error, not a silently wrong answer:
ValueErroreagerly, a runtime error underjit. - Integers and bfloat16 are promoted to float32.
- Coordinates are divided by an exact power of two when float32 would overflow or underflow, so values from about 1e-38 to 3e38 keep their neighbours. Typical cases are metres at kiloparsec scale, or tiny lengths.
- NaN or inf input is an error, not a silently wrong answer:
- Compiles once per size bucket. Eager calls pad
nto a bucket (2ʲ or 1.5·2ʲ), so inputs of different sizes share compiled code. - A raw tree for custom queries.
jaxknn.treeexposesbuild_tree,knn,all_knnand label-excluding queries (knn(tree, q, k, exclude=(point_labels, query_labels)): the nearest point with a different label, with whole same-label subtrees pruned).
jaxknn.brute_knn has the same contract by brute force. It's faster for small inputs.
When to use it
Use jaxknn when the kNN has to live inside a traced JAX program: under jit, vmap or grad, or on an accelerator.
On a CPU, eagerly, SciPy's cKDTree is faster, because it queries with every core. Here's all-points kNN (k=10, a 3-D stream with 2% interlopers), comparing jaxknn compiled under jit with SciPy called eagerly. It was measured on an Apple M2 Pro under load, so the ratios matter more than the absolute times.
| n | jit compile (first call) |
jaxknn under jit, steady |
SciPy, eager | jaxknn / SciPy |
|---|---|---|---|---|
| 2,000 | 9.4 s | 17.8 ms | 6.0 ms | 2.9× |
| 10,000 | 11.6 s | 106 ms | 16.4 ms | 6.5× |
| 100,000 | 13.2 s | 1,261 ms | 148 ms | 8.5× |
| 1,000,000 | 26.8 s | 11,719 ms | 1,990 ms | 5.9× |
The first call compiles, which takes seconds per input shape and k. To pay that once per machine rather than once per process, turn on JAX's persistent compilation cache:
export JAX_COMPILATION_CACHE_DIR="$HOME/.cache/jax"
Or, in Python, jax.config.update("jax_compilation_cache_dir", ...) before the first call. Later processes then load the compiled kNN from disk; tracing still runs each time. At n = 100,000, the first call in a new process fell from 6.8 s to 2.8 s.
Against jaxkd at n = 100,000 (all-points, k = 10, CPU):
| data | jaxknn | jaxkd | SciPy |
|---|---|---|---|
| stream | 307 ms | 815 ms | 73 ms |
| blob | 355 ms | 1,161 ms | 80 ms |
| stream + interlopers | 513 ms | ~140 s | 78 ms |
Origin
jaxknn was extracted from phasecurvefit, where it is the traceable kNN behind MSTOrderer, with its history. See phasecurvefit#197.
License
MIT
Metadata
Release files for jaxknn 0.1.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| jaxknn-0.1.1.tar.gz | 113.8 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| jaxknn-0.1.1-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 135.9 kB
Release files / jaxknn-0.1.1.tar.gz
| Download URL | jaxknn-0.1.1.tar.gz |
|---|---|
| Size | 113.8 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
15f11a539c7ce969aedcc4064b6d20c813084451e4e97246932d8b2562b9b1ff
|
|
BLAKE2b-256 checksum How to use checksums |
76b080f11d4c00d3fc1b8e80ccd1d3617471c9330b440955fdb84947d8c2540d
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 19, 2026.
Transparency logRelease files / jaxknn-0.1.1-py3-none-any.whl
| Download URL | jaxknn-0.1.1-py3-none-any.whl |
|---|---|
| Size | 22.1 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
7a90f64407cf97407d87868569491d095704898e2713ad23d5ad3cd14f4bb76f
|
|
BLAKE2b-256 checksum How to use checksums |
62d1cfa7560bd492bd4b156dffbfb240a34057bb33e446ddcc456744f27d3251
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 19, 2026.
Transparency log