quantizers 1.2.2__tar.gz → 2.0.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (85) hide show
  1. quantizers-2.0.0/.github/workflows/python-publish.yml +33 -0
  2. {quantizers-1.2.2 → quantizers-2.0.0}/.github/workflows/python-test.yml +8 -6
  3. {quantizers-1.2.2 → quantizers-2.0.0}/.pre-commit-config.yaml +5 -5
  4. quantizers-2.0.0/PKG-INFO +156 -0
  5. quantizers-2.0.0/README.md +125 -0
  6. {quantizers-1.2.2 → quantizers-2.0.0}/pyproject.toml +24 -29
  7. quantizers-2.0.0/src/quantizers/_backends.py +551 -0
  8. quantizers-2.0.0/src/quantizers/_torch_ops.py +20 -0
  9. quantizers-2.0.0/src/quantizers/_version.py +24 -0
  10. quantizers-2.0.0/src/quantizers/binary/__init__.py +3 -0
  11. quantizers-2.0.0/src/quantizers/binary/binary_ops.py +17 -0
  12. quantizers-2.0.0/src/quantizers/fixed_point/__init__.py +3 -0
  13. quantizers-2.0.0/src/quantizers/fixed_point/fixed_point_ops.py +168 -0
  14. quantizers-2.0.0/src/quantizers/minifloat/__init__.py +3 -0
  15. quantizers-2.0.0/src/quantizers/minifloat/float_point_ops.py +61 -0
  16. {quantizers-1.2.2 → quantizers-2.0.0}/src/quantizers/stateful_quantizers.py +17 -45
  17. quantizers-2.0.0/src/quantizers/triton/__init__.py +215 -0
  18. quantizers-2.0.0/src/quantizers/triton/_lowering.py +317 -0
  19. quantizers-2.0.0/src/quantizers.egg-info/PKG-INFO +156 -0
  20. quantizers-2.0.0/src/quantizers.egg-info/SOURCES.txt +43 -0
  21. quantizers-2.0.0/src/quantizers.egg-info/requires.txt +21 -0
  22. quantizers-2.0.0/src/quantizers.egg-info/scm_file_list.json +39 -0
  23. quantizers-2.0.0/src/quantizers.egg-info/scm_version.json +8 -0
  24. quantizers-2.0.0/test/conftest.py +204 -0
  25. quantizers-2.0.0/test/cpp_source/.gitignore +1 -0
  26. quantizers-2.0.0/test/cpp_source/Makefile +22 -0
  27. quantizers-2.0.0/test/cpp_source/ac_types/LICENSE +201 -0
  28. quantizers-2.0.0/test/cpp_source/ac_types/ac_fixed.h +2032 -0
  29. quantizers-2.0.0/test/cpp_source/ac_types/ac_float.h +1235 -0
  30. quantizers-2.0.0/test/cpp_source/ac_types/ac_int.h +3636 -0
  31. quantizers-2.0.0/test/cpp_source/ac_types/ac_std_float.h +2687 -0
  32. quantizers-2.0.0/test/cpp_source/quantizers.h +27 -0
  33. quantizers-2.0.0/test/gen_configs.py +67 -0
  34. quantizers-2.0.0/test/test_backends.py +206 -0
  35. quantizers-2.0.0/test/test_quantizer_match.py +98 -0
  36. quantizers-2.0.0/test/test_stateless_quantizer.py +207 -0
  37. quantizers-2.0.0/test/test_triton.py +195 -0
  38. quantizers-2.0.0/test/triton_quantizers.py +120 -0
  39. quantizers-1.2.2/.github/workflows/python-publish.yml +0 -33
  40. quantizers-1.2.2/PKG-INFO +0 -138
  41. quantizers-1.2.2/README.md +0 -110
  42. quantizers-1.2.2/src/quantizers/_version.py +0 -21
  43. quantizers-1.2.2/src/quantizers/binary/__init__.py +0 -4
  44. quantizers-1.2.2/src/quantizers/binary/_binary_ops.py +0 -27
  45. quantizers-1.2.2/src/quantizers/binary/binary_ops.py +0 -10
  46. quantizers-1.2.2/src/quantizers/binary/binary_ops_np.py +0 -9
  47. quantizers-1.2.2/src/quantizers/fixed_point/__init__.py +0 -4
  48. quantizers-1.2.2/src/quantizers/fixed_point/_fixed_point_ops.py +0 -215
  49. quantizers-1.2.2/src/quantizers/fixed_point/fixed_point_ops.py +0 -19
  50. quantizers-1.2.2/src/quantizers/fixed_point/fixed_point_ops_np.py +0 -163
  51. quantizers-1.2.2/src/quantizers/minifloat/__init__.py +0 -4
  52. quantizers-1.2.2/src/quantizers/minifloat/_float_point_ops.py +0 -56
  53. quantizers-1.2.2/src/quantizers/minifloat/float_point_ops.py +0 -15
  54. quantizers-1.2.2/src/quantizers/minifloat/float_point_ops_np.py +0 -42
  55. quantizers-1.2.2/src/quantizers.egg-info/PKG-INFO +0 -138
  56. quantizers-1.2.2/src/quantizers.egg-info/SOURCES.txt +0 -49
  57. quantizers-1.2.2/src/quantizers.egg-info/requires.txt +0 -15
  58. quantizers-1.2.2/test/cpp_source/ap_types/ap_binary.h +0 -78
  59. quantizers-1.2.2/test/cpp_source/ap_types/ap_common.h +0 -376
  60. quantizers-1.2.2/test/cpp_source/ap_types/ap_decl.h +0 -212
  61. quantizers-1.2.2/test/cpp_source/ap_types/ap_fixed.h +0 -360
  62. quantizers-1.2.2/test/cpp_source/ap_types/ap_fixed_base.h +0 -2354
  63. quantizers-1.2.2/test/cpp_source/ap_types/ap_fixed_ref.h +0 -718
  64. quantizers-1.2.2/test/cpp_source/ap_types/ap_fixed_special.h +0 -230
  65. quantizers-1.2.2/test/cpp_source/ap_types/ap_float.h +0 -197
  66. quantizers-1.2.2/test/cpp_source/ap_types/ap_int.h +0 -330
  67. quantizers-1.2.2/test/cpp_source/ap_types/ap_int_base.h +0 -1885
  68. quantizers-1.2.2/test/cpp_source/ap_types/ap_int_ref.h +0 -1346
  69. quantizers-1.2.2/test/cpp_source/ap_types/ap_int_special.h +0 -223
  70. quantizers-1.2.2/test/cpp_source/ap_types/ap_shift_reg.h +0 -138
  71. quantizers-1.2.2/test/cpp_source/ap_types/etc/ap_private.h +0 -7199
  72. quantizers-1.2.2/test/cpp_source/ap_types/hls_math.h +0 -27
  73. quantizers-1.2.2/test/cpp_source/ap_types/hls_stream.h +0 -263
  74. quantizers-1.2.2/test/cpp_source/ap_types/test.cpp +0 -22
  75. quantizers-1.2.2/test/cpp_source/ap_types/utils/x_hls_utils.h +0 -80
  76. quantizers-1.2.2/test/cpp_source/quantizers.h +0 -35
  77. quantizers-1.2.2/test/test_quantizer_match.py +0 -189
  78. quantizers-1.2.2/test/test_stateless_quantizer.py +0 -179
  79. {quantizers-1.2.2 → quantizers-2.0.0}/.clang-format +0 -0
  80. {quantizers-1.2.2 → quantizers-2.0.0}/.gitignore +0 -0
  81. {quantizers-1.2.2 → quantizers-2.0.0}/LICENSE +0 -0
  82. {quantizers-1.2.2 → quantizers-2.0.0}/setup.cfg +0 -0
  83. {quantizers-1.2.2 → quantizers-2.0.0}/src/quantizers/__init__.py +0 -0
  84. {quantizers-1.2.2 → quantizers-2.0.0}/src/quantizers.egg-info/dependency_links.txt +0 -0
  85. {quantizers-1.2.2 → quantizers-2.0.0}/src/quantizers.egg-info/top_level.txt +0 -0
@@ -0,0 +1,33 @@
1
+ name: Upload Python Package
2
+
3
+ on:
4
+ release:
5
+ types: [published]
6
+
7
+ permissions:
8
+ contents: read
9
+
10
+ jobs:
11
+ deploy:
12
+ environment:
13
+ name: pypi
14
+ url: https://pypi.org/p/quantizers
15
+ runs-on: ubuntu-latest
16
+ permissions:
17
+ id-token: write
18
+ steps:
19
+ - uses: actions/checkout@v7
20
+ with:
21
+ fetch-depth: 0
22
+ - name: Set up Python
23
+ uses: actions/setup-python@v7
24
+ with:
25
+ python-version: "3.14"
26
+ - name: Install dependencies
27
+ run: |
28
+ python -m pip install --upgrade pip
29
+ pip install build
30
+ - name: Build package
31
+ run: python -m build
32
+ - name: Publish package
33
+ uses: pypa/gh-action-pypi-publish@release/v1
@@ -9,24 +9,26 @@ jobs:
9
9
  runs-on: ubuntu-latest
10
10
  steps:
11
11
  - name: Checkout
12
- uses: actions/checkout@v4
12
+ uses: actions/checkout@v7
13
13
  with:
14
14
  fetch-depth: 0
15
15
 
16
16
  - name: Set up Python
17
- uses: actions/setup-python@v4
17
+ uses: actions/setup-python@v7
18
18
  with:
19
- python-version: 3.x
19
+ python-version: '3.13'
20
+ cache-dependency-path: pyproject.toml
21
+ cache: 'pip'
20
22
 
21
23
  - name: Install dependencies
22
24
  run: |
23
- cd $GITHUB_WORKSPACE
25
+ pip install torch --index-url https://download.pytorch.org/whl/cpu # CPU-only: skips the CUDA wheels
24
26
  pip install -e '.[test]'
25
27
 
26
28
  - name: Run tests
27
- run: pytest --import-mode=importlib -n4 --cov --cov-report=xml --cov=src/quantizers
29
+ run: pytest -n4
28
30
 
29
31
  - name: Upload results to Codecov
30
- uses: codecov/codecov-action@v4
32
+ uses: codecov/codecov-action@v7
31
33
  with:
32
34
  token: ${{ secrets.CODECOV_TOKEN }}
@@ -2,14 +2,14 @@ exclude: '\.svg$|ap_types/|_version.py'
2
2
 
3
3
  repos:
4
4
  - repo: https://github.com/astral-sh/ruff-pre-commit
5
- rev: v0.8.2
5
+ rev: v0.15.0
6
6
  hooks:
7
7
  - id: ruff
8
8
  args: [--fix]
9
9
  - id: ruff-format
10
10
 
11
11
  - repo: https://github.com/pre-commit/pre-commit-hooks
12
- rev: v4.6.0
12
+ rev: v6.0.0
13
13
  hooks:
14
14
  - id: check-added-large-files
15
15
  - id: check-case-conflict
@@ -23,18 +23,18 @@ repos:
23
23
  - id: trailing-whitespace
24
24
 
25
25
  - repo: https://github.com/asottile/setup-cfg-fmt
26
- rev: v2.5.0
26
+ rev: v3.2.0
27
27
  hooks:
28
28
  - id: setup-cfg-fmt
29
29
 
30
30
  - repo: https://github.com/asottile/pyupgrade
31
- rev: v3.16.0
31
+ rev: v3.21.2
32
32
  hooks:
33
33
  - id: pyupgrade
34
34
  args: ["--py310-plus"]
35
35
 
36
36
  - repo: https://github.com/pre-commit/mirrors-clang-format
37
- rev: v18.1.8
37
+ rev: v21.1.8
38
38
  hooks:
39
39
  - id: clang-format
40
40
  types_or: [c++, c, cuda]
@@ -0,0 +1,156 @@
1
+ Metadata-Version: 2.4
2
+ Name: quantizers
3
+ Version: 2.0.0
4
+ Author-email: Chang Sun <chsun@cern.ch>
5
+ License-Expression: LGPL-3.0-only
6
+ Project-URL: repository, https://github.com/calad0i/quantizers
7
+ Keywords: quantization
8
+ Classifier: Programming Language :: Python :: 3
9
+ Classifier: Operating System :: OS Independent
10
+ Classifier: Development Status :: 5 - Production/Stable
11
+ Requires-Python: >=3.10
12
+ Description-Content-Type: text/markdown
13
+ License-File: LICENSE
14
+ Provides-Extra: keras
15
+ Requires-Dist: keras>=3.0.0; extra == "keras"
16
+ Provides-Extra: torch
17
+ Requires-Dist: torch>=2.12; extra == "torch"
18
+ Provides-Extra: test
19
+ Requires-Dist: pytest; extra == "test"
20
+ Requires-Dist: pytest-cov; extra == "test"
21
+ Requires-Dist: pytest-xdist; extra == "test"
22
+ Requires-Dist: pytest-env; extra == "test"
23
+ Requires-Dist: jax; extra == "test"
24
+ Requires-Dist: tensorflow; extra == "test"
25
+ Requires-Dist: torch; extra == "test"
26
+ Requires-Dist: tinygrad; extra == "test"
27
+ Requires-Dist: mlx[cpu]; extra == "test"
28
+ Requires-Dist: keras>=3.0.0; extra == "test"
29
+ Requires-Dist: triton; sys_platform == "linux" and extra == "test"
30
+ Dynamic: license-file
31
+
32
+ # Quantizers
33
+ [![PyPI version](https://badge.fury.io/py/quantizers.svg)](https://badge.fury.io/py/quantizers)
34
+ [![License](https://img.shields.io/badge/License-LGPL-blue)](LICENSE)
35
+ [![Tests](https://github.com/calad0i/quantizers/actions/workflows/python-test.yml/badge.svg)](https://github.com/calad0i/quantizers/actions/workflows/python-test.yml)
36
+ [![Coverage](https://img.shields.io/codecov/c/github/calad0i/quantizers)](https://app.codecov.io/gh/calad0i/quantizers)
37
+
38
+
39
+ Hardware-oriented numerical quantizers for deep learning models: same quantizers for `numpy`, `jax`, `torch`, `tensorflow`, `mlx`, `tinygrad`, plus keras 3 variables ones and triton device functions for custom kernels. Bit-exact with the fixed-point and floating-point types of Siemens HLS libraries (`ac_types`), and differentiable through each framework's autodiff when available.
40
+
41
+ ## Features
42
+
43
+ - Bit-accurate fixed-point and minifloat quantization, tested against [ac_types](https://github.com/hlslibs/ac_types)' `ac_fixed` and `ac_std_float`
44
+ - `einops` like multi framework dispatched based on the tensor type and lazy import
45
+ - Differentiable, through each framework's own autodiff (and XLA/JIT compilation like `torch.compile`, `jax.jit`, `tf.function`)
46
+ - Surrogate gradients on the bit widths as described in [HGQ [FPGA'26]](https://doi.org/10.1145/3748173.3779200)
47
+ - Triton device functions of every quantizer with vjps for use in custom kernels
48
+
49
+ ## Supported Quantizers
50
+
51
+ ### Fixed-Point Quantizer
52
+
53
+ Parameters:
54
+ - `k` (keep_negative): Enable negative numbers
55
+ - `i` (integer_bits): Number of bits before decimal point (excludes sign bit)
56
+ - `f` (fractional_bits): Number of bits after decimal point
57
+ - For C++: `W = k + i + f`, `I = k + i`, `S = k`
58
+
59
+ Supported modes:
60
+ - Rounding: `TRN`, `RND`, `RND_CONV`, `TRN_ZERO`, `RND_ZERO`, `RND_MIN_INF`, `RND_INF`
61
+ - Overflow: `WRAP`, `SAT`, `SAT_SYM`, `SAT_ZERO`
62
+
63
+ Gradients:
64
+ - `x`: passed through, except where the value saturates, wraps or is zeroed
65
+ - `i`, `f`: surrogate gradients; `WRAP` and `SAT_ZERO` give none on `i`
66
+ - Zero width (`k + i + f <= 0`): the value is 0, the gradients are left as they are; `null_xgrad_on_zero_width=True` drops the gradient on `x` there
67
+
68
+ Differences from `ap_fixed`: a signed 1-bit `SAT_SYM` gives 0, the only symmetric value (`ap_fixed` keeps `{-1, 0}`), and `WRAP_SM` is not supported.
69
+
70
+ ### Minifloat Quantizer
71
+
72
+ Parameters:
73
+ - `m` (mantissa_bits): Mantissa width, excluding the implicit leading bit
74
+ - `e` (exponent_bits): Exponent width
75
+ - `e0` (exponent_zero): Exponent bias, default 1 (IEEE's bias)
76
+ - Normal exponents: `[e0 + 1 - 2^(e-1), e0 - 1 + 2^(e-1)]`
77
+
78
+ Features:
79
+ - Supports subnormal numbers
80
+ - No inf or NaN encodings: the top exponent holds numbers, value beyond the maximum saturates
81
+ - `RND_CONV` rounding for all
82
+
83
+ ### Simplified Quantizers
84
+
85
+ - **Binary**: Maps to {-1, 1}, with 0 to 1. Gradient of tanh
86
+ - **Ternary**: Maps to {-1, 0, 1}, i.e. fixed-point `fixed<2, 2, RND_CONV, SAT_SYM>`. Gradient of tanh
87
+
88
+
89
+ ## Installation
90
+
91
+ **requires python>=3.10**
92
+
93
+ ```bash
94
+ pip install quantizers
95
+ ```
96
+ numpy arrays and python scalars need `numpy`. Otherwise, no dependency is required beyond the particular framework you already have. For keras, install `keras>=3.0.0` is expected.
97
+
98
+ ## Usage
99
+
100
+ ### Stateless Quantizers
101
+ ```python
102
+ from quantizers import FixedPointQuantizer, binary_quantize, fixed_quantize, float_quantize, ternary_quantize
103
+
104
+ # Fixed-point: x, k, i, f are tensors of one framework (or python scalars), broadcast together
105
+ quantizer = FixedPointQuantizer(round_mode='RND', overflow_mode='SAT')
106
+ xq = quantizer(x, k, i, f)
107
+ xq = fixed_quantize(x, k, i, f, round_mode='RND', overflow_mode='SAT') # shortcut for the above
108
+ xq = quantizer.round(x, f) # rounding to f fractional bits only, without overflow handling
109
+
110
+ # Minifloat
111
+ xq = float_quantize(x, mantissa_bits, exponent_bits, exponent_zero)
112
+
113
+ # Simplified quantizers
114
+ xq = binary_quantize(x)
115
+ xq = ternary_quantize(x)
116
+ ```
117
+
118
+ ### Stateful Quantizers
119
+ ```python
120
+ from quantizers import BinaryQ, FixedQ, MinifloatQ, TernaryQ
121
+
122
+ # Fixed formats, for inference and testing; for training use the stateless ones
123
+ fixed_q = FixedQ(width, integer_bits, signed, rounding='RND', overflow='SAT') # integer_bits includes the sign bit
124
+ xq = fixed_q(x)
125
+
126
+ mfloat_q = MinifloatQ(mantissa_bits, exponent_bits, exponent_zero)
127
+ xq = mfloat_q(x)
128
+ ```
129
+
130
+ ### Triton Device Functions
131
+ ```python
132
+ import triton
133
+ import triton.language as tl
134
+ from quantizers import triton as qt
135
+
136
+ @triton.jit
137
+ def kernel(x_ptr, i_ptr, f_ptr, g_ptr, y_ptr, dx_ptr, di_ptr, df_ptr, BLOCK: tl.constexpr):
138
+ o = tl.program_id(0) * BLOCK + tl.arange(0, BLOCK)
139
+ x, i, f, g = tl.load(x_ptr + o), tl.load(i_ptr + o), tl.load(f_ptr + o), tl.load(g_ptr + o)
140
+ tl.store(y_ptr + o, qt.fixed_quantize(x, 1, i, f, 'RND', 'SAT'))
141
+ dx, dk, di, df = qt.fixed_quantize_vjp(x, 1, i, f, g, 'RND', 'SAT')
142
+ ...
143
+ ```
144
+ - `fixed_quantize`, `fixed_round`, `float_quantize`, `binary_quantize`, `ternary_quantize`, each with a `_vjp`, and `float_decompose`
145
+ - Elementwise in float32 over the operands broadcast together (tensors of any dtype, or scalars); modes are constexpr strings
146
+ - A `_vjp` takes the cotangent `g` of the value and returns the cotangent of every operand, of the broadcast shape: reduce those of broadcast operands in the kernel
147
+ - Values match the JAX backend bit for bit on finite floats of the normal range, gradients to float32 rounding
148
+ - Kernels using them recompile when quantizers changes; with `TRITON_INTERPRET=1` they run in Triton's CPU interpreter
149
+
150
+ ## Development
151
+
152
+ ```bash
153
+ pip install -e '.[test]'
154
+ pytest -n auto
155
+ ```
156
+ The tests compare against a C++ reference built with `make` on the first run (a C++ compiler is needed) and run on the CPU only, Triton kernels in its interpreter.
@@ -0,0 +1,125 @@
1
+ # Quantizers
2
+ [![PyPI version](https://badge.fury.io/py/quantizers.svg)](https://badge.fury.io/py/quantizers)
3
+ [![License](https://img.shields.io/badge/License-LGPL-blue)](LICENSE)
4
+ [![Tests](https://github.com/calad0i/quantizers/actions/workflows/python-test.yml/badge.svg)](https://github.com/calad0i/quantizers/actions/workflows/python-test.yml)
5
+ [![Coverage](https://img.shields.io/codecov/c/github/calad0i/quantizers)](https://app.codecov.io/gh/calad0i/quantizers)
6
+
7
+
8
+ Hardware-oriented numerical quantizers for deep learning models: same quantizers for `numpy`, `jax`, `torch`, `tensorflow`, `mlx`, `tinygrad`, plus keras 3 variables ones and triton device functions for custom kernels. Bit-exact with the fixed-point and floating-point types of Siemens HLS libraries (`ac_types`), and differentiable through each framework's autodiff when available.
9
+
10
+ ## Features
11
+
12
+ - Bit-accurate fixed-point and minifloat quantization, tested against [ac_types](https://github.com/hlslibs/ac_types)' `ac_fixed` and `ac_std_float`
13
+ - `einops` like multi framework dispatched based on the tensor type and lazy import
14
+ - Differentiable, through each framework's own autodiff (and XLA/JIT compilation like `torch.compile`, `jax.jit`, `tf.function`)
15
+ - Surrogate gradients on the bit widths as described in [HGQ [FPGA'26]](https://doi.org/10.1145/3748173.3779200)
16
+ - Triton device functions of every quantizer with vjps for use in custom kernels
17
+
18
+ ## Supported Quantizers
19
+
20
+ ### Fixed-Point Quantizer
21
+
22
+ Parameters:
23
+ - `k` (keep_negative): Enable negative numbers
24
+ - `i` (integer_bits): Number of bits before decimal point (excludes sign bit)
25
+ - `f` (fractional_bits): Number of bits after decimal point
26
+ - For C++: `W = k + i + f`, `I = k + i`, `S = k`
27
+
28
+ Supported modes:
29
+ - Rounding: `TRN`, `RND`, `RND_CONV`, `TRN_ZERO`, `RND_ZERO`, `RND_MIN_INF`, `RND_INF`
30
+ - Overflow: `WRAP`, `SAT`, `SAT_SYM`, `SAT_ZERO`
31
+
32
+ Gradients:
33
+ - `x`: passed through, except where the value saturates, wraps or is zeroed
34
+ - `i`, `f`: surrogate gradients; `WRAP` and `SAT_ZERO` give none on `i`
35
+ - Zero width (`k + i + f <= 0`): the value is 0, the gradients are left as they are; `null_xgrad_on_zero_width=True` drops the gradient on `x` there
36
+
37
+ Differences from `ap_fixed`: a signed 1-bit `SAT_SYM` gives 0, the only symmetric value (`ap_fixed` keeps `{-1, 0}`), and `WRAP_SM` is not supported.
38
+
39
+ ### Minifloat Quantizer
40
+
41
+ Parameters:
42
+ - `m` (mantissa_bits): Mantissa width, excluding the implicit leading bit
43
+ - `e` (exponent_bits): Exponent width
44
+ - `e0` (exponent_zero): Exponent bias, default 1 (IEEE's bias)
45
+ - Normal exponents: `[e0 + 1 - 2^(e-1), e0 - 1 + 2^(e-1)]`
46
+
47
+ Features:
48
+ - Supports subnormal numbers
49
+ - No inf or NaN encodings: the top exponent holds numbers, value beyond the maximum saturates
50
+ - `RND_CONV` rounding for all
51
+
52
+ ### Simplified Quantizers
53
+
54
+ - **Binary**: Maps to {-1, 1}, with 0 to 1. Gradient of tanh
55
+ - **Ternary**: Maps to {-1, 0, 1}, i.e. fixed-point `fixed<2, 2, RND_CONV, SAT_SYM>`. Gradient of tanh
56
+
57
+
58
+ ## Installation
59
+
60
+ **requires python>=3.10**
61
+
62
+ ```bash
63
+ pip install quantizers
64
+ ```
65
+ numpy arrays and python scalars need `numpy`. Otherwise, no dependency is required beyond the particular framework you already have. For keras, install `keras>=3.0.0` is expected.
66
+
67
+ ## Usage
68
+
69
+ ### Stateless Quantizers
70
+ ```python
71
+ from quantizers import FixedPointQuantizer, binary_quantize, fixed_quantize, float_quantize, ternary_quantize
72
+
73
+ # Fixed-point: x, k, i, f are tensors of one framework (or python scalars), broadcast together
74
+ quantizer = FixedPointQuantizer(round_mode='RND', overflow_mode='SAT')
75
+ xq = quantizer(x, k, i, f)
76
+ xq = fixed_quantize(x, k, i, f, round_mode='RND', overflow_mode='SAT') # shortcut for the above
77
+ xq = quantizer.round(x, f) # rounding to f fractional bits only, without overflow handling
78
+
79
+ # Minifloat
80
+ xq = float_quantize(x, mantissa_bits, exponent_bits, exponent_zero)
81
+
82
+ # Simplified quantizers
83
+ xq = binary_quantize(x)
84
+ xq = ternary_quantize(x)
85
+ ```
86
+
87
+ ### Stateful Quantizers
88
+ ```python
89
+ from quantizers import BinaryQ, FixedQ, MinifloatQ, TernaryQ
90
+
91
+ # Fixed formats, for inference and testing; for training use the stateless ones
92
+ fixed_q = FixedQ(width, integer_bits, signed, rounding='RND', overflow='SAT') # integer_bits includes the sign bit
93
+ xq = fixed_q(x)
94
+
95
+ mfloat_q = MinifloatQ(mantissa_bits, exponent_bits, exponent_zero)
96
+ xq = mfloat_q(x)
97
+ ```
98
+
99
+ ### Triton Device Functions
100
+ ```python
101
+ import triton
102
+ import triton.language as tl
103
+ from quantizers import triton as qt
104
+
105
+ @triton.jit
106
+ def kernel(x_ptr, i_ptr, f_ptr, g_ptr, y_ptr, dx_ptr, di_ptr, df_ptr, BLOCK: tl.constexpr):
107
+ o = tl.program_id(0) * BLOCK + tl.arange(0, BLOCK)
108
+ x, i, f, g = tl.load(x_ptr + o), tl.load(i_ptr + o), tl.load(f_ptr + o), tl.load(g_ptr + o)
109
+ tl.store(y_ptr + o, qt.fixed_quantize(x, 1, i, f, 'RND', 'SAT'))
110
+ dx, dk, di, df = qt.fixed_quantize_vjp(x, 1, i, f, g, 'RND', 'SAT')
111
+ ...
112
+ ```
113
+ - `fixed_quantize`, `fixed_round`, `float_quantize`, `binary_quantize`, `ternary_quantize`, each with a `_vjp`, and `float_decompose`
114
+ - Elementwise in float32 over the operands broadcast together (tensors of any dtype, or scalars); modes are constexpr strings
115
+ - A `_vjp` takes the cotangent `g` of the value and returns the cotangent of every operand, of the broadcast shape: reduce those of broadcast operands in the kernel
116
+ - Values match the JAX backend bit for bit on finite floats of the normal range, gradients to float32 rounding
117
+ - Kernels using them recompile when quantizers changes; with `TRITON_INTERPRET=1` they run in Triton's CPU interpreter
118
+
119
+ ## Development
120
+
121
+ ```bash
122
+ pip install -e '.[test]'
123
+ pytest -n auto
124
+ ```
125
+ The tests compare against a C++ reference built with `make` on the first run (a C++ compiler is needed) and run on the CPU only, Triton kernels in its interpreter.
@@ -1,79 +1,74 @@
1
1
  [build-system]
2
- requires = ["setuptools>=67.8", "setuptools_scm>=8"]
2
+ requires = ["setuptools>=77", "setuptools_scm>=8"]
3
3
 
4
4
  build-backend = "setuptools.build_meta"
5
5
 
6
6
  [project]
7
7
  name = "quantizers"
8
- version = "1.2.2"
9
8
  authors = [{ name = "Chang Sun", email = "chsun@cern.ch" }]
10
9
  description = ""
11
10
  readme = "README.md"
12
11
  requires-python = ">=3.10"
13
- license = { text = "GNU Lesser General Public License v3 (LGPLv3)" }
12
+ license = "LGPL-3.0-only"
13
+ license-files = ["LICENSE"]
14
14
  keywords = ["quantization"]
15
15
 
16
16
  classifiers = [
17
17
  "Programming Language :: Python :: 3",
18
18
  "Operating System :: OS Independent",
19
- "License :: OSI Approved :: GNU Lesser General Public License v3 (LGPLv3)",
20
19
  "Development Status :: 5 - Production/Stable",
21
20
  ]
21
+ dynamic = ["version"]
22
+
22
23
 
23
24
  [project.urls]
24
25
  repository = "https://github.com/calad0i/quantizers"
25
26
 
26
27
 
27
28
  [tool.setuptools]
28
- packages = ["quantizers"]
29
29
  include-package-data = true
30
- package-dir = { "" = "src" }
30
+
31
+ [tool.setuptools.packages.find]
32
+ where = ["src"]
31
33
 
32
34
 
33
35
  [tool.setuptools_scm]
34
36
  write_to = "src/quantizers/_version.py"
35
37
 
36
38
  [project.optional-dependencies]
37
- dependencies = ["numpy"]
38
-
39
- grad = ['keras>=3.10']
39
+ keras = ["keras>=3.0.0"]
40
+ torch = ["torch>=2.12"]
40
41
  test = [
41
42
  'pytest',
42
43
  'pytest-cov',
43
44
  'pytest-xdist',
44
45
  'pytest-env',
45
- 'keras>=3.0',
46
- 'cppyy',
47
46
  'jax',
47
+ 'tensorflow',
48
+ 'torch',
49
+ 'tinygrad',
50
+ 'mlx[cpu]',
51
+ 'keras>=3.0.0',
52
+ 'triton; sys_platform == "linux"',
48
53
  ]
49
54
 
50
55
  [tool.pytest.ini_options]
51
- filterwarnings = [
52
- "ignore:WARNING\\W Pytorch converter is not enabled!:UserWarning",
53
- "ignore:.\\[93mcover_factor<1.0 will likely to result in overflows:UserWarning",
54
- "ignore:You are saving your model as an HDF5 file:UserWarning",
55
- "ignore:Even though the `tf.config.experimental_run_functions_eagerly`:UserWarning",
56
- "ignore:pkg_resources is deprecated as an API:DeprecationWarning",
57
- "ignore:distutils Version classes are deprecated:DeprecationWarning",
58
- "ignore:module 'sre_constants' is deprecated:DeprecationWarning",
59
- "ignore:Deprecated call to `pkg_resources.declare_namespace:DeprecationWarning",
60
- ]
56
+ filterwarnings = []
61
57
 
62
- env = [
63
- "KERAS_BACKEND=jax",
64
- "JAX_PLATFORMS=cpu",
65
- "CUDA_VISIBLE_DEVICES=-1",
66
- "CLING_ENABLE_CUDA=0",
67
- ]
58
+ env = ["JAX_PLATFORMS=cpu", "CUDA_VISIBLE_DEVICES=-1", "TRITON_INTERPRET=1"]
68
59
 
60
+ pythonpath = ["test"]
69
61
  addopts = "--import-mode=importlib --cov=src/quantizers --cov-report=xml --cov-report=html"
70
62
 
71
63
  [tool.coverage.run]
72
64
  omit = ["*/_version.py"]
65
+ patch = ["subprocess"]
73
66
 
74
67
  [tool.coverage.report]
75
- exclude_lines = ['pragma: no cover', 'if TYPE_CHECKING:']
76
-
68
+ exclude_also = [
69
+ '^[ \t]*\.\.\.[ \t]*(?:#.*)?$',
70
+ '^[ \t]*raise NotImplementedError\b',
71
+ ]
77
72
  [tool.ruff]
78
73
  include = ["src/**/*.py"]
79
74