a Jax quantization library
See the codeQwix is a Jax quantization library supporting Quantization-Aware Training (QAT) and Post-Training Quantization (PTQ) for both XLA targets (CPU/GPU/TPU) and ODML targets (LiteRT).
int4, int8, fp8.int1 to int7, nf4.absmax: symmetric quantization using maximum absolute value.minmax: asymmetric quantization using minimum and maximum values.rms: symmetric quantization using root mean square.fixed: fixed range.conv_general_dilated: per-channel.dot_general and einsum: per-channel and sub-channel.conv, matmul, and fully_connected: per-channel.Qwix doesn't provide a PyPI package yet. To use Qwix, you need to install from GitHub directly.
pip install git+https://github.com/google/qwix
We're going to use a simple MLP model in the example. Qwix integrates with models without need to modify their code, so any model can be used below.
import jax
from flax import linen as nn
class MLP(nn.Module):
dhidden: int
dout: int
@nn.compact
def __call__(self, x):
x = nn.Dense(self.dhidden, use_bias=False)(x)
x = nn.relu(x)
x = nn.Dense(self.dout, use_bias=False)(x)
return x
model = MLP(64, 16)
model_input = jax.random.uniform(jax.random.key(0), (8, 16))
Qwix uses a regex-based configuration system to instruct how to quantize a Jax
model. Configurations are defined as a list of QuantizationRule. Each rule
consists of a key that matches Flax modules, and a set of values that control
quantization behavior.
For example, to quantize the above model in int8 (w8a8), we need to define the rules as below.
import qwix
rules = [
qwix.QuantizationRule(
module_path='.*', # this rule matches all modules.
weight_qtype='int8', # quantizes weights in int8.
act_qtype='int8', # quantizes activations in int8.
)
]
Unlike some other libraries that provides limited number of quantization recipes, Qwix doesn't have a list of presets. Instead, different quantization schemas are achieved by combinations of quantization configs.
To apply PTQ to the above model, we only need to call qwix.quantize_model.
ptq_model = qwix.quantize_model(model, qwix.PtqProvider(rules))
Now the ptq_model will contain quantized weights. We could verify that.
>>> jax.eval_shape(ptq_model.init, jax.random.key(0), model_input)['params']
{
'Dense_0': {
'kernel': WithAux(
array=QArray(
qvalue=ShapeDtypeStruct(shape=(16, 64), dtype=int8),
scale=ShapeDtypeStruct(shape=(1, 64), dtype=float32),
...
),
...
)
},
'Dense_1': {
'kernel': WithAux(
array=QArray(
qvalue=ShapeDtypeStruct(shape=(64, 16), dtype=int8),
scale=ShapeDtypeStruct(shape=(1, 16), dtype=float32),
...
),
...
)
}
}
Since Flax Linen modules are pure-functional, weights quantization are separate
from model quantization. To quantize weights for the above ptq_model, we
need to call qwix.quantize_params.
# Floating-point params, usually loaded from checkpoints.
fp_params = ...
# Abstract quantized params, which serve as a template for quantize_params.
abs_ptq_params = jax.eval_shape(ptq_model.init, jax.random.key(0), model_input)['params']
# Weight quantization.
ptq_params = qwix.quantize_params(fp_params, abs_ptq_params)
# ptq_params contains the quantized weights and can be consumed by ptq_model.
quantized_model_output = ptq_model.apply({'params': ptq_params}, model_input)
The design of Qwix was inspired by AQT and borrowed many great ideas from it. Here's a brief list of the similarities and the differences.
QArray is similar to AQT's QTensor, both supporting sub-channel
quantization.einsum and dot_general, each of
these having to be configured separately. Qwix provides addtional mechanisms
to integrate with a whole model implicitly.Please refer to CONTRIBUTING.md for more information.
To cite Qwix please use the citation:
@software{Qwix,
title = {Qwix: A Quantization Library for Jax},
author={Dangyi Liu, Jiwon Shin, et al.},
year = {2024},
howpublished = {\url{https://github.com/google/qwix}},
}
Python
100.0%
a Jax quantization library
See the codeQwix is a Jax quantization library supporting Quantization-Aware Training (QAT) and Post-Training Quantization (PTQ) for both XLA targets (CPU/GPU/TPU) and ODML targets (LiteRT).
int4, int8, fp8.int1 to int7, nf4.absmax: symmetric quantization using maximum absolute value.minmax: asymmetric quantization using minimum and maximum values.rms: symmetric quantization using root mean square.fixed: fixed range.conv_general_dilated: per-channel.dot_general and einsum: per-channel and sub-channel.conv, matmul, and fully_connected: per-channel.Qwix doesn't provide a PyPI package yet. To use Qwix, you need to install from GitHub directly.
pip install git+https://github.com/google/qwix
We're going to use a simple MLP model in the example. Qwix integrates with models without need to modify their code, so any model can be used below.
import jax
from flax import linen as nn
class MLP(nn.Module):
dhidden: int
dout: int
@nn.compact
def __call__(self, x):
x = nn.Dense(self.dhidden, use_bias=False)(x)
x = nn.relu(x)
x = nn.Dense(self.dout, use_bias=False)(x)
return x
model = MLP(64, 16)
model_input = jax.random.uniform(jax.random.key(0), (8, 16))
Qwix uses a regex-based configuration system to instruct how to quantize a Jax
model. Configurations are defined as a list of QuantizationRule. Each rule
consists of a key that matches Flax modules, and a set of values that control
quantization behavior.
For example, to quantize the above model in int8 (w8a8), we need to define the rules as below.
import qwix
rules = [
qwix.QuantizationRule(
module_path='.*', # this rule matches all modules.
weight_qtype='int8', # quantizes weights in int8.
act_qtype='int8', # quantizes activations in int8.
)
]
Unlike some other libraries that provides limited number of quantization recipes, Qwix doesn't have a list of presets. Instead, different quantization schemas are achieved by combinations of quantization configs.
To apply PTQ to the above model, we only need to call qwix.quantize_model.
ptq_model = qwix.quantize_model(model, qwix.PtqProvider(rules))
Now the ptq_model will contain quantized weights. We could verify that.
>>> jax.eval_shape(ptq_model.init, jax.random.key(0), model_input)['params']
{
'Dense_0': {
'kernel': WithAux(
array=QArray(
qvalue=ShapeDtypeStruct(shape=(16, 64), dtype=int8),
scale=ShapeDtypeStruct(shape=(1, 64), dtype=float32),
...
),
...
)
},
'Dense_1': {
'kernel': WithAux(
array=QArray(
qvalue=ShapeDtypeStruct(shape=(64, 16), dtype=int8),
scale=ShapeDtypeStruct(shape=(1, 16), dtype=float32),
...
),
...
)
}
}
Since Flax Linen modules are pure-functional, weights quantization are separate
from model quantization. To quantize weights for the above ptq_model, we
need to call qwix.quantize_params.
# Floating-point params, usually loaded from checkpoints.
fp_params = ...
# Abstract quantized params, which serve as a template for quantize_params.
abs_ptq_params = jax.eval_shape(ptq_model.init, jax.random.key(0), model_input)['params']
# Weight quantization.
ptq_params = qwix.quantize_params(fp_params, abs_ptq_params)
# ptq_params contains the quantized weights and can be consumed by ptq_model.
quantized_model_output = ptq_model.apply({'params': ptq_params}, model_input)
The design of Qwix was inspired by AQT and borrowed many great ideas from it. Here's a brief list of the similarities and the differences.
QArray is similar to AQT's QTensor, both supporting sub-channel
quantization.einsum and dot_general, each of
these having to be configured separately. Qwix provides addtional mechanisms
to integrate with a whole model implicitly.Please refer to CONTRIBUTING.md for more information.
To cite Qwix please use the citation:
@software{Qwix,
title = {Qwix: A Quantization Library for Jax},
author={Dangyi Liu, Jiwon Shin, et al.},
year = {2024},
howpublished = {\url{https://github.com/google/qwix}},
}
Python
100.0%