Skip to content
bksaikiPublic

About

Embedded Python DSL for numerical computing

Resources

Stars

8 stars

Watchers

2 watching

Forks

Repository files navigation

FPy

An embedded Python DSL for specifying and simulating numerical algorithms.

Important links:

Example

FPy is Python with explicit control of both the mathematics and rounding: every operation is correctly rounded by the rounding context it appears in, and contexts are ordinary values you can pass around — including fp.REAL, which never rounds. Here is a blocked dot product: the products are exact, each block of K elements is summed in a narrow format, and the running total is float32.

import fpy2 as fp

@fp.fpy(ctx=fp.REAL)
def dot(xs: list[fp.Real], ys: list[fp.Real], K: int, block: fp.Context) -> fp.Real:
    """A blocked dot product: exact products, blocks of `K` summed in `block`.
    The length of `xs` must be a multiple of `K`."""
    assert len(xs) == len(ys)
    acc = 0
    for start in range(0, len(xs), K):
        with block:
            inner_acc = 0
            for x, y in zip(xs[start:start + K], ys[start:start + K]):
                with fp.REAL:
                    p = x * y       # every product is exact ...
                inner_acc += p      # ... but block sums round to `block`
        with fp.FP32:
            acc += inner_acc        # one fp32 addition per block
    return acc

@fp.fpy(ctx=fp.REAL)
def dot_ref(xs: list[fp.Real], ys: list[fp.Real]) -> fp.Real:
    """The same dot product, with no rounding anywhere."""
    return sum([x * y for x, y in zip(xs, ys)])

xs = ys = [0.1] * 4096
exact = dot_ref(xs, ys).as_rational()   # the true value, as a Fraction

print(f'{"block":>6} {"format":>9} {"result":>11} {"rel. error":>11}')
for K, name, ctx in [(4096, 'float16', fp.FP16), (32, 'float16', fp.FP16),
                     (4096, 'bfloat16', fp.BF16), (32, 'bfloat16', fp.BF16),
                     (32, 'float32', fp.FP32)]:
    r = dot(xs, ys, K, ctx)
    err = abs(r.as_rational() - exact) / exact
    print(f'{K:>6} {name:>9} {float(r):>11.6f} {float(err):>11.3%}')

which prints

 block    format      result  rel. error
  4096   float16   32.000000     21.875%
    32   float16   40.968750      0.021%
  4096  bfloat16    4.000000     90.234%
    32  bfloat16   40.250000      1.733%
    32   float32   40.959972      0.000%

A flat float16 accumulator stalls out once the running total dwarfs the product being added to it; summing 32 elements at a time keeps the error three orders of magnitude smaller.

See the usage guide for the language and the examples page for more.

Installation

FPy can be installed from PyPI with either uv or pip, or built from source for development. The following instructions assume a bash-like shell.

Installing from PyPI

Requirements:

  • Python 3.11 or later

To install the latest stable release of FPy, run:

uv pip install fpy2

or, with pip:

pip install fpy2

The Triton backend also needs PyTorch, Triton and a GPU: install fpy2[triton].

Installing from source

Requirements:

  • Python 3.11 or later
  • make

With uv (preferred)

uv is the recommended development workflow — it handles the virtual environment and dependency installation in a single step:

uv sync

This creates .venv/ and installs FPy in editable mode along with the dev dependency group, pinned by uv.lock. Rerun it to reset .venv/ to the lockfile; it removes anything installed by hand. Activate the environment with

source .venv/bin/activate

or prefix individual commands with uv run (e.g. uv run pytest tests/unit).

With pip (legacy)

This path is preserved for compatibility with existing tooling; new contributors should prefer uv above.

If you do not have a Python virtual environment, create one using

python3 -m venv .venv/

and activate it using

source .venv/bin/activate

To install an instance of FPy for development, run:

pip install -e .[dev]

To uninstall FPy, run:

pip uninstall fpy2

Testing

There are a number of tests that can be run through the Makefile including

make lint

to ensure formatting and type safety;

make unittest

to run the unit tests;

make infratest

to run the infrastructure tests.

About

Embedded Python DSL for numerical computing

Resources

Stars

8 stars

Watchers

2 watching

Forks

Releases

Packages

Contributors

Languages