quantize-py
python bindings for quantize, a simple, fast quantization library written in rust. quantization stores numbers in fewer bits, trading a little accuracy for a lot less memory.
pip install quantize-py
requires python 3.12 or newer, or 3.14 or newer for free-threaded python. numpy is installed with it. where no wheel fits, like alpine linux, pip builds it from source, which needs rust 1.88 or newer.
from quantize import Scale, quantize
weights = [0.42, -0.10, 0.70, -0.50]
q = quantize(weights, bits=8, block=32, scale=Scale.F16)
back = q.dequantize() # [0.421, -0.098, 0.700, -0.498]
dot = q.dot(weights) # 0.926
bits is the width of each code, from 2 to 16. block is how many values share one scale, and scale is how that scale is stored: Scale.F32 (the default), Scale.F16, or Scale.BF16. values can be a list, a numpy array, or anything else np.asarray reads, like a pytorch tensor. a 2-d array keeps its shape, so q.dequantize() gives back a matrix and q.matmul(x) computes x @ W.T, like a linear layer. both can write into a float32 numpy array or pytorch tensor you pass, like q.matmul(x, out=y), so a loop can reuse it. q.shape gives its rows and columns, and len(q) the number of values, as in rust.
the scales count toward the size: 4-bit codes with one f16 scale per 32 values cost 4.5 bits per value, or 5 with the default f32 scale. q.bits_per_element reports it. above about 10 bits, use f32 scales with asymmetric.quantize, since f16 and bf16 zero-points cap its accuracy.
the other schemes return the same Quantized type:
asymmetric.quantize(weights, bits=8, block=32)adds a zero-point per block, for values that aren't centered on zeroadaptive.quantize(weights, tolerance=0.1 * weights.std())gives each block the fewest bits, from 2 to 8, that round every weight withintolerance, in the weights' own units. a tenth of their standard deviation gives about 5 bits a block. for a list, usenp.std(weights)learned.refine(q, weights)refits each block's scale, and its zero-point if it has one, to lower the mean squared error. it changesqin place, so callq.copy()first to keep the original. it lets other threads run while it works, so threads can refit several layers at oncelearned.alternate(q, weights)refits too, then rounds each value to the nearest code on its block's new line, and repeats until no code moves. it also changesqin place and lets other threads run. both can raise the worst error past an adaptive tensor's tolerance, and lowering the error of the weights doesn't always lower the error of a model's outputs, so check those tooScheme.Q4_32.quantize(weights)picks a scheme at run time, andScheme("symmetric(bits=4)")reads one from text, like a config value, whichstr(scheme)writes
a block with outliers can need more than 8 bits, which raises ToleranceTooTightError. retrying with its smallest_tolerance works, but loosens every block, not just that one:
import numpy as np
from quantize import ToleranceTooTightError, adaptive
weights = np.array(weights) # a list has no .std(). skip this line for a pytorch tensor
try:
q = adaptive.quantize(weights, tolerance=0.1 * weights.std())
except ToleranceTooTightError as error:
q = adaptive.quantize(weights, tolerance=error.smallest_tolerance)
quantized values can be pickled, and compared with ==. q.to_bytes() saves one as bytes, in the same format as the rust crate, and Quantized.from_bytes(data) loads it back. to keep it in an np.savez or safetensors file, store np.frombuffer(q.to_bytes(), np.uint8).
to save its parts as plain arrays instead, like with np.savez, pass them back by name to Quantized.from_parts. leave out the one that's None: bits for an adaptive tensor, or block_bits for the others:
parts = dict(kind=q.kind, shape=q.shape, block=q.block, bits=q.bits, block_bits=q.block_bits,
codes=q.codes, scales=q.scales, zero_points=q.zero_points, scale=q.scale.name)
np.savez("layer.npz", **{name: part for name, part in parts.items() if part is not None})
q = Quantized.from_parts(**np.load("layer.npz"))
to keep quantized values in a torch.save checkpoint, store torch.frombuffer(bytearray(q.to_bytes()), dtype=torch.uint8), and load each back with Quantized(t). the checkpoint is then as small as the bytes, and torch.load reads it without add_safe_globals. pickling q itself makes the checkpoint about 1.5 times larger, since torch.save stores bytes as text, and needs torch.serialization.add_safe_globals([Quantized]) before torch.load.
q.matmul runs on one core, but it lets other threads run while it multiplies, so threads can share out a batch. on an 8-core intel xeon, this multiplies a batch of 512 by a 4-bit 1536 × 576 matrix in 6 ms instead of 33 ms, with the same result, bit for bit:
import os
from concurrent.futures import ThreadPoolExecutor
pool = ThreadPoolExecutor() # make it once, and reuse it for every layer
def linear(q, x): # x has shape (batch, columns)
# a piece per core, or pieces of 64 rows for a big batch, which stay in a core's cache
pieces = np.array_split(x, max(os.cpu_count(), len(x) // 64))
return np.concatenate(list(pool.map(q.matmul, pieces)))
out = linear(q, x)
with a gil, while another thread keeps running python, each piece can wait up to sys.getswitchinterval(), 5 ms by default, to get the gil back, so splitting pays off only while your other threads are idle or in native code, or on free-threaded python. dequantize, dot, and matmul on 65,536 values or fewer, like one vector times a 256 × 256 matrix, keep the gil, so they don't wait. quantizing and refitting keep it only up to 4,096 values, so threads can quantize a model's layers in parallel.
each value decodes as code * scale, or (code - zero_point) * scale with zero-points, using the scale and zero-point of its block. codes are signed and bits wide, and q.codes packs them low bits first. scales can be negative, since a symmetric block puts its value farthest from zero on the most negative code. help(Quantized) has the details.
to build and test from a clone of the repo, with rust 1.88 or newer and just:
just setup
just python
on debian or ubuntu, run sudo apt install python3-venv first.
Metadata
Release files for quantize-py 0.3.2
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| quantize_py-0.3.2.tar.gz | 96.6 kB | Details |
Built distributions (wheels)
Total release size: 4.6 MB
Release files / quantize_py-0.3.2.tar.gz
| Download URL | quantize_py-0.3.2.tar.gz |
|---|---|
| Size | 96.6 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
574842f87cf4fcd81bf8dd08e3237a1b90f9700756a3afc8be931d0a361f3927
|
|
BLAKE2b-256 checksum How to use checksums |
ddb682a5e65fd0beaaa3398b51c3b682f40242428abb6b3201a899bfb14c3669
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
uv/0.12.23 {"installer":{"name":"uv","version":"0.12.23","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}
|
Release files / quantize_py-0.3.2-cp314-cp314t-win_amd64.whl
| Download URL | quantize_py-0.3.2-cp314-cp314t-win_amd64.whl |
|---|---|
| Size | 338.5 kB |
| Tags | CPython 3.14 CPython 3.14 free-threading Windows x86-64 |
|
SHA-256 checksum How to use checksums |
308d4e86b6f12c712fc94c410c7ceed7c4aec86682cf59348853241c0e2d5a9f
|
|
BLAKE2b-256 checksum How to use checksums |
47f45ffbc6149ce0f1c3b6cb720d7d3ee52c31bc3aadf8c1bb8a5c4d47b3fa77
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
uv/0.12.23 {"installer":{"name":"uv","version":"0.12.23","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}
|
Release files / quantize_py-0.3.2-cp314-cp314t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
| Download URL | quantize_py-0.3.2-cp314-cp314t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl |
|---|---|
| Size | 500.8 kB |
| Tags | CPython 3.14 CPython 3.14 free-threading Linux glibc 2.17+ x86-64 |
|
SHA-256 checksum How to use checksums |
f72e3dae33f9db98389391235cedae5cef17082c7bbac645774880f1e368597c
|
|
BLAKE2b-256 checksum How to use checksums |
0cf14c21772527a617527689d3ecccdf4c47566df1c430db3dca524c673b9c74
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
uv/0.12.23 {"installer":{"name":"uv","version":"0.12.23","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}
|
Release files / quantize_py-0.3.2-cp314-cp314t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
| Download URL | quantize_py-0.3.2-cp314-cp314t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl |
|---|---|
| Size | 492.1 kB |
| Tags | CPython 3.14 CPython 3.14 free-threading Linux glibc 2.17+ ARM64 |
|
SHA-256 checksum How to use checksums |
96b0c580aaa0bca9d64132af05e0db7e54aaf454fa23533fd7027db926fa2a24
|
|
BLAKE2b-256 checksum How to use checksums |
f255d62d1f44768f801d140f385b00b0be3bbc713b9cdd35d3eaa1af7b287f55
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
uv/0.12.23 {"installer":{"name":"uv","version":"0.12.23","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}
|
Release files / quantize_py-0.3.2-cp314-cp314t-macosx_11_0_arm64.whl
| Download URL | quantize_py-0.3.2-cp314-cp314t-macosx_11_0_arm64.whl |
|---|---|
| Size | 440.5 kB |
| Tags | CPython 3.14 CPython 3.14 free-threading macOS 11.0+ ARM64 |
|
SHA-256 checksum How to use checksums |
c87bd6c80b1ffa258b7e8d4ca5e3c39cc9696a60293993d13aa8c71954e80bb2
|
|
BLAKE2b-256 checksum How to use checksums |
b1206e334114bcc51443021198a0e9488fde0b7c32a9c47bb94cc2270d675ce8
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
uv/0.12.23 {"installer":{"name":"uv","version":"0.12.23","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}
|
Release files / quantize_py-0.3.2-cp314-cp314t-macosx_10_12_x86_64.whl
| Download URL | quantize_py-0.3.2-cp314-cp314t-macosx_10_12_x86_64.whl |
|---|---|
| Size | 459.0 kB |
| Tags | CPython 3.14 CPython 3.14 free-threading macOS 10.12+ x86-64 |
|
SHA-256 checksum How to use checksums |
88115f82ed620d19b6cdbd7b24e70001750eac035c3e234e69422df7cb61a0d6
|
|
BLAKE2b-256 checksum How to use checksums |
81adaea4421f3f005dbd300a501127c24e264ef6bbdf429b2699781641cf1ab1
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
uv/0.12.23 {"installer":{"name":"uv","version":"0.12.23","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}
|
Release files / quantize_py-0.3.2-cp312-abi3-win_amd64.whl
| Download URL | quantize_py-0.3.2-cp312-abi3-win_amd64.whl |
|---|---|
| Size | 352.4 kB |
| Tags | CPython 3.12 Windows x86-64 abi3 |
|
SHA-256 checksum How to use checksums |
4af794b17fee5ec3bb2a50741c6fdee4ebaebb2a74353bfd22f0440b9a81a588
|
|
BLAKE2b-256 checksum How to use checksums |
9cb71803d1588a2abf5fbd0142feef481b512dd98f8a2a0b6b6207a878c8053e
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
uv/0.12.23 {"installer":{"name":"uv","version":"0.12.23","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}
|
Release files / quantize_py-0.3.2-cp312-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
| Download URL | quantize_py-0.3.2-cp312-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl |
|---|---|
| Size | 513.4 kB |
| Tags | CPython 3.12 Linux glibc 2.17+ x86-64 abi3 |
|
SHA-256 checksum How to use checksums |
8a0a715ea1892a46d426ccd8bff1d90e631590b4f11f87ffd4a58625d848a131
|
|
BLAKE2b-256 checksum How to use checksums |
9409123e406a29ec856187c7d4d0283ede8c577a53c4ecdbc1e1f7d4441fb98f
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
uv/0.12.23 {"installer":{"name":"uv","version":"0.12.23","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}
|
Release files / quantize_py-0.3.2-cp312-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
| Download URL | quantize_py-0.3.2-cp312-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl |
|---|---|
| Size | 503.8 kB |
| Tags | CPython 3.12 Linux glibc 2.17+ ARM64 abi3 |
|
SHA-256 checksum How to use checksums |
0ec543cdcd17f43d320b257c2115804542691fa124fdcdb9c8e59905920d6942
|
|
BLAKE2b-256 checksum How to use checksums |
2516d6cc1de7194acffee123f02c02a76c86ab64f01844aa4daae30c4580a7d7
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
uv/0.12.23 {"installer":{"name":"uv","version":"0.12.23","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}
|
Release files / quantize_py-0.3.2-cp312-abi3-macosx_11_0_arm64.whl
| Download URL | quantize_py-0.3.2-cp312-abi3-macosx_11_0_arm64.whl |
|---|---|
| Size | 453.5 kB |
| Tags | CPython 3.12 abi3 macOS 11.0+ ARM64 |
|
SHA-256 checksum How to use checksums |
b2e100812e81e1539d0372fd5fe08baa292db281f8be3f2365e31768739436d8
|
|
BLAKE2b-256 checksum How to use checksums |
6f6c996acf632772374c35a7f135783e19f2f8236e4d900b3bbd33b6a2f0b497
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
uv/0.12.23 {"installer":{"name":"uv","version":"0.12.23","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}
|
Release files / quantize_py-0.3.2-cp312-abi3-macosx_10_12_x86_64.whl
| Download URL | quantize_py-0.3.2-cp312-abi3-macosx_10_12_x86_64.whl |
|---|---|
| Size | 473.2 kB |
| Tags | CPython 3.12 abi3 macOS 10.12+ x86-64 |
|
SHA-256 checksum How to use checksums |
43b9bec59a95bcc53bad5e36bc5bac23c162e0d9990877a55986c4433b0adb48
|
|
BLAKE2b-256 checksum How to use checksums |
777ec9d99cbdfd7055ef5c3b3a64918557a9fbe4b49cc543049c5342e75beca1
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
uv/0.12.23 {"installer":{"name":"uv","version":"0.12.23","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}
|