DequantizePacked¶
DequantizePacked - 29¶
Version¶
domain:
mainsince_version:
29function:
Falsesupport_level:
SupportType.COMMONshape inference:
True
This version of the operator has been available since version 29.
Summary¶
Dequantizes the packed payload of one quantized tensor.
x is a one-dimensional UINT8 tensor containing exactly the tensor’s bytes.
All multibyte fields are little-endian.
format selects the quantization format using an ONNX-defined, case-sensitive
string identifier. The gguf: prefix identifies the existing GGML/GGUF layouts.
Only the following fixed identifiers are supported; they accept no parameters:
Identifier |
Format |
Elements |
Bytes |
|---|---|---|---|
gguf:q4_0 |
Q4_0 |
32 |
18 |
gguf:q4_1 |
Q4_1 |
32 |
20 |
gguf:q5_0 |
Q5_0 |
32 |
22 |
gguf:q5_1 |
Q5_1 |
32 |
24 |
gguf:q8_0 |
Q8_0 |
32 |
34 |
gguf:q8_1 |
Q8_1 |
32 |
36 |
gguf:q2_k |
Q2_K |
256 |
84 |
gguf:q3_k |
Q3_K |
256 |
110 |
gguf:q4_k |
Q4_K |
256 |
144 |
gguf:q5_k |
Q5_K |
256 |
176 |
gguf:q6_k |
Q6_K |
256 |
210 |
gguf:q8_k |
Q8_K |
256 |
292 |
gguf:iq2_xxs |
IQ2_XXS |
256 |
66 |
gguf:iq2_xs |
IQ2_XS |
256 |
74 |
gguf:iq3_xxs |
IQ3_XXS |
256 |
98 |
gguf:iq1_s |
IQ1_S |
256 |
50 |
gguf:iq4_nl |
IQ4_NL |
32 |
18 |
gguf:iq3_s |
IQ3_S |
256 |
110 |
gguf:iq2_s |
IQ2_S |
256 |
82 |
gguf:iq4_xs |
IQ4_XS |
256 |
136 |
gguf:iq1_m |
IQ1_M |
256 |
56 |
gguf:tq1_0 |
TQ1_0 |
256 |
54 |
gguf:tq2_0 |
TQ2_0 |
256 |
66 |
gguf:mxfp4 |
MXFP4 |
32 |
17 |
gguf:nvfp4 |
NVFP4 |
64 |
36 |
gguf:q1_0 |
Q1_0 |
128 |
18 |
gguf:q2_0 |
Q2_0 |
64 |
18 |
The byte layouts, per-format decoding algorithms, and complete IQ codebooks are defined in the in-tree DequantizePacked decoding specification. The online specification is also accessible from installed schema documentation.
shape gives the logical output dimensions in ONNX (row-major) order.
For a GGUF descriptor [ne0, ne1, ...], use shape=[..., ne1, ne0].
Decoding preserves the flattened element order.
Rank must be at least one. Dimensions are nonnegative literal sizes;
a zero dimension produces an empty tensor. The last dimension must be a
multiple of the format’s elements per block, even for an empty tensor.
If B is elements per block and S is bytes per block, the input length must be
product(shape[:-1]) * (shape[-1] / B) * S.
Blocks are decoded in input order to FLOAT using the specified
arithmetic and codebooks. The concatenated values are reshaped to shape
and converted once to output_dtype. Decoding arithmetic uses FLOAT
precision for all output types. FLOAT16 and BFLOAT16 conversion uses
round-to-nearest, ties-to-even, as in Cast.
For example, a Q4_0 block is a little-endian FLOAT16 scale d followed
by 16 bytes q. It produces y[j]=d*((q[j]&15)-8) and
y[j+16]=d*((q[j]>>4)-8) for j=0,…,15. Thus 36 bytes containing two
blocks can be decoded with format="gguf:q4_0", shape=[2,32].
Attributes¶
format - STRING (required) :
ONNX-defined, case-sensitive fixed quantization format identifier.
output_dtype - INT (default is
1):ONNX TensorProto data type of the output: FLOAT, FLOAT16, BFLOAT16, or DOUBLE.
shape - INTS (required) :
Logical output dimensions in ONNX order; rank at least one.
Inputs¶
x (heterogeneous) - tensor(uint8):
Consecutive quantization blocks with little-endian fields.
Outputs¶
y (heterogeneous) - T:
Dequantized tensor with the specified shape and output_dtype.
Type Constraints¶
T in (
tensor(bfloat16),tensor(double),tensor(float),tensor(float16)):Floating-point output.
Examples¶
_q4_0¶
import numpy as np
import onnx
node = helper.make_node(
"DequantizePacked", ["x"], ["y"], format="gguf:q4_0", shape=[2, 32]
)
x = np.frombuffer(
struct.pack("<e", 0.5)
+ bytes(range(16))
+ struct.pack("<e", -2)
+ bytes([0xF0] * 16),
dtype=np.uint8,
)
y = np.array(
[
list(np.arange(-8, 8) * 0.5) + [-4] * 16,
[16] * 16 + [-14] * 16,
],
dtype=np.float32,
)
expect(node, inputs=[x], outputs=[y], name="test_dequantizepacked_q4_0")
_q5_1¶
import numpy as np
import onnx
node = helper.make_node(
"DequantizePacked", ["x"], ["y"], format="gguf:q5_1", shape=[32]
)
x = np.frombuffer(
struct.pack("<eeI", 0.5, -1, 0xFFFF0000) + bytes(range(16)), dtype=np.uint8
)
y = np.array(list(np.arange(16) * 0.5 - 1) + [7] * 16, dtype=np.float32)
expect(node, inputs=[x], outputs=[y], name="test_dequantizepacked_q5_1")
_iq4_nl¶
import numpy as np
import onnx
node = helper.make_node(
"DequantizePacked",
["x"],
["y"],
format="gguf:iq4_nl",
shape=[32],
output_dtype=TensorProto.FLOAT16,
)
x = np.frombuffer(struct.pack("<e", 0.5) + bytes(range(16)), dtype=np.uint8)
y = np.array(
[
-127,
-104,
-83,
-65,
-49,
-35,
-22,
-10,
1,
13,
25,
38,
53,
69,
89,
113,
]
+ [-127] * 16,
dtype=np.float16,
) * np.float16(0.5)
expect(
node, inputs=[x], outputs=[y], name="test_dequantizepacked_iq4_nl_float16"
)
_mxfp4¶
import numpy as np
import onnx
node = helper.make_node(
"DequantizePacked", ["x"], ["y"], format="gguf:mxfp4", shape=[32]
)
x = np.array([127, *list(range(16))], dtype=np.uint8)
y = np.array(
[0, 0.5, 1, 1.5, 2, 3, 4, 6, 0, -0.5, -1, -1.5, -2, -3, -4, -6] + [0] * 16,
dtype=np.float32,
)
expect(node, inputs=[x], outputs=[y], name="test_dequantizepacked_mxfp4")
_empty¶
import numpy as np
import onnx
node = helper.make_node(
"DequantizePacked", ["x"], ["y"], format="gguf:q2_k", shape=[0, 256]
)
expect(
node,
inputs=[np.empty(0, dtype=np.uint8)],
outputs=[np.empty((0, 256), dtype=np.float32)],
name="test_dequantizepacked_empty",
)