Skip to main content

JIT unit-stripping decorator: write Pint-annotated code, run at float speed

Project description

unit-jit

JIT unit-stripping decorator for Pint-annotated Python. Write clean, unit-safe code; pay no Pint overhead in hot loops.

from unit_jit import unit_jit, ureg

@unit_jit
def simulate(n: int) -> np.ndarray:
    mrna = 10.0 * ureg.mol / ureg.L
    dt   =  0.1 * ureg.s
    delta = 0.01 / ureg.s
    out = np.empty(n)
    for i in range(n):
        mrna = mrna - delta * mrna * dt
        out[i] = mrna.to_base_units().magnitude
    return out

First call runs the original Pint function (warm-up). All subsequent calls run a rewritten, pure-float version — ~10× faster for tight loops.

How it works

  1. Module-level compilation — on first call, all @unit_jit functions in the same module are rewritten together: .magnitude, .to_base_units(), and cast("Quantity", x) are stripped from the source.
  2. Eager snapshot — Quantity attributes on objects (e.g. self.params.alpha) are pre-converted to SI floats once at boundary entry. Attribute access inside the loop is a plain dict lookup.
  3. Fast zone — a thread-local flag marks the outermost @unit_jit frame. Inner @unit_jit calls skip boundary conversion entirely.
  4. Return wrapping — the SI unit of the return value is inferred from the first call and used to wrap subsequent results back into Quantity.
  5. Dimension guard — argument dimensions are cached from the first call; any later call with a different dimension raises TypeError immediately.

The right entry point is the outermost function that owns the hot loop — not the leaf functions it calls.

Installation

# uv (recommended)
uv add unit-jit

# pip
pip install unit-jit

From source:

git clone ...
cd unit-jit

# uv
uv sync --extra dev

# pip
pip install -e ".[dev]"

Usage

Simple function

from unit_jit import unit_jit, ureg

@unit_jit
def velocity(d, t):
    return d / t

velocity(10 * ureg.m, 2 * ureg.s)   # warm-up (runs Pint)
velocity(10 * ureg.m, 2 * ureg.s)   # fast (pure float internally)
velocity(10 * ureg.cm, 2 * ureg.s)  # fine — same dimension, different unit
velocity(10 * ureg.m, 2 * ureg.m)   # TypeError — wrong dimension for arg 1

Class with Quantity attributes

from dataclasses import dataclass
from unit_jit import unit_jit, ureg

@dataclass
class Params:
    alpha: Quantity   # [mol/L/s]
    delta: Quantity   # [1/s]

class Model:
    def __init__(self, params):
        self.params = params

    @unit_jit
    def rate(self, mrna):
        return self.params.alpha - self.params.delta * mrna

    @unit_jit                          # ← entry point: owns the hot loop
    def simulate(self, n):
        mrna = self.params.alpha / self.params.delta
        out = np.empty(n)
        for i in range(n):
            mrna = mrna + self.rate(mrna) * (0.1 * ureg.s)   # rate() in fast zone
            out[i] = mrna.to_base_units().magnitude
        return out

self.params.alpha and all other Quantity attributes are converted to SI floats once when simulate is first called fast; self.rate() is called from inside the fast zone, so it skips boundary conversion entirely.

Running tests

pytest

License

Apache-2.0

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

unit_jit-0.1.0.tar.gz (14.4 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

unit_jit-0.1.0-py3-none-any.whl (10.0 kB view details)

Uploaded Python 3

File details

Details for the file unit_jit-0.1.0.tar.gz.

File metadata

  • Download URL: unit_jit-0.1.0.tar.gz
  • Upload date:
  • Size: 14.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.10.12 {"installer":{"name":"uv","version":"0.10.12","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for unit_jit-0.1.0.tar.gz
Algorithm Hash digest
SHA256 202fd71bed16126d5d4f285858d176d36cba5c1aeed4a033873ded2a94558c7b
MD5 06849fddee680a59c6142599500acd87
BLAKE2b-256 d3d872e3d3d8b78c47ee41b8bef72f8a19511a79a02f6722a17b9acdad648d6f

See more details on using hashes here.

File details

Details for the file unit_jit-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: unit_jit-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 10.0 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.10.12 {"installer":{"name":"uv","version":"0.10.12","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for unit_jit-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 3896ff080ea386398f44bfcf63ec4d51daced7c8f61e8bdfde8d136a0b481fe1
MD5 a9e5f97c023bffea8e714f87384c862e
BLAKE2b-256 a8364c7c5d15cccabdce6654289205ef9d8ca85d3dcb7936268dbc7dea1dff3d

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page