Xenova HF Staff commited on
Commit
96cf7f5
·
verified ·
1 Parent(s): 11c8823

sync 2e7068faf55e

Browse files
README.md CHANGED
@@ -1,3 +1,77 @@
1
  ---
 
2
  license: apache-2.0
 
 
 
 
3
  ---
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  ---
2
+ library_name: kernels
3
  license: apache-2.0
4
+ tags:
5
+ - kernel
6
+ - webgpu
7
+ - wgsl
8
  ---
9
+ # ai.onnx.DequantizeLinear
10
+
11
+ `ai.onnx` · standard ONNX operator · ONNX opset ≥ 25
12
+
13
+ ## Description
14
+
15
+ Dequantizes a quantized tensor back to full precision using the formula `y = (x - x_zero_point) * x_scale`. Scale and zero point determine quantization granularity: scalar for per-tensor, 1-D for per-axis, or same rank as input for blocked quantization. The output type matches `x_scale` unless overridden by `output_dtype`.
16
+
17
+ See the [ONNX `DequantizeLinear` spec](https://onnx.ai/onnx/operators/onnx__DequantizeLinear.html) for the reference semantics.
18
+
19
+ ## Inputs
20
+
21
+ | Name | Bind key | Logical dtype | Rank | Shape | Description | Presence |
22
+ | --- | --- | --- | --- | --- | --- | --- |
23
+ | `x` | `x` | `TQ` | — | — | N-D quantized input tensor to be dequantized. | required |
24
+ | `x_scale` | `x_scale` | `TF` | — | — | Scale for `x`; scalar for per-tensor, 1-D for per-axis, or same-rank tensor for blocked dequantization. | required |
25
+ | `x_zero_point` | `x_zero_point` | `TQ` | — | — | Zero point for `x` with shape matching `x_scale`; defaults to zero when absent. | optional |
26
+
27
+ ## Outputs
28
+
29
+ | Name | Bind key | Logical dtype | Rank | Shape | Description | Presence |
30
+ | --- | --- | --- | --- | --- | --- | --- |
31
+ | `y` | `y` | `TF` | same as `x` | same as `x` | N-D full-precision output with the same shape as `x`, typed according to `x_scale` or `output_dtype`. | required |
32
+
33
+ ## Attributes
34
+
35
+ Default values (overridable per request):
36
+
37
+ | Attribute | Default | Description |
38
+ | --- | --- | --- |
39
+ | `axis` | `1` | The axis of the dequantizing dimension, used for per-axis and blocked quantization; negative values index from the end. |
40
+ | `block_size` | `0` | Number of elements along `axis` that share each scale value for blocked quantization; 0 means not blocked. |
41
+ | `output_dtype` | `0` | ONNX TensorProto element-type code for `y`; `0` uses the dtype of `x_scale`. The current float16/float32 routes require it to agree with `x_scale`. |
42
+
43
+ ## Type constraints
44
+
45
+ | Variable | Allowed dtypes |
46
+ | --- | --- |
47
+ | `TQ` | `uint8`, `int8`, `int16`, `int32` |
48
+ | `TF` | `float32`, `float16` |
49
+
50
+ ## Files
51
+
52
+ - [`metadata.json`](build/webgpu/metadata.json) — kernel metadata (id, digests, provenance)
53
+ - [`manifest.json`](build/webgpu/manifest.json) — the op contract (source of truth)
54
+ - [`test.json`](build/webgpu/test.json) — correctness cases
55
+ - [`bench.json`](build/webgpu/bench.json) — benchmark + tuning cases
56
+ - [`quant-linear-blocked-axis.wgsl.jinja`](build/webgpu/quant-linear-blocked-axis.wgsl.jinja)
57
+ - [`quant-linear-scalar.wgsl.jinja`](build/webgpu/quant-linear-scalar.wgsl.jinja)
58
+ - [`quant-linear-vec4.wgsl.jinja`](build/webgpu/quant-linear-vec4.wgsl.jinja)
59
+
60
+ ## Use with `@huggingface/kernels`
61
+
62
+ The loader derives every required output's shape and logical dtype from the manifest contract and this call.
63
+ It then allocates the result tensors automatically.
64
+
65
+ The `version: 1` option selects the published kernel contract; it is independent of any operator opset, contrib `since_version`, or model version.
66
+
67
+ Replace each `*Data` placeholder with a typed array containing the corresponding input data.
68
+
69
+ ```js
70
+ import { getKernel } from "@huggingface/kernels";
71
+
72
+ const kernel = await getKernel("webgpu-kernels/ai.onnx.DequantizeLinear", { version: 1 });
73
+ const { y } = await kernel({
74
+ x: { data: xData, shape: [4] },
75
+ x_scale: { data: x_scaleData, shape: [] },
76
+ });
77
+ ```
build/webgpu/bench.json ADDED
@@ -0,0 +1,247 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "op": "ai.onnx.DequantizeLinear",
3
+ "tunableSpace": { "WORKGROUP_SIZE": [64, 128, 256] },
4
+ "cases": [
5
+ {
6
+ "name": "uint8_1m_scalar",
7
+ "preset": "smoke",
8
+ "vars": { "inputDtype": "uint8", "outputDtype": "float32", "count": 1048576 },
9
+ "inputs": {
10
+ "x": { "dtype": "uint8", "shape": [1024, 1024], "data": { "kind": "constant", "value": 127 } },
11
+ "x_scale": { "dtype": "float32", "shape": [1], "data": { "kind": "values", "values": [0.02] } },
12
+ "x_zero_point": { "dtype": "uint8", "shape": [1], "data": { "kind": "values", "values": [128] } }
13
+ },
14
+ "outputs": { "y": { "dtype": "float32", "shape": [1024, 1024] } },
15
+ "bench": {
16
+ "primary": true,
17
+ "metrics": [
18
+ { "type": "bandwidth", "value": "args.count * (dtypeBytes(args.inputDtype) + dtypeBytes(args.outputDtype))" }
19
+ ]
20
+ }
21
+ },
22
+ {
23
+ "name": "uint8_1m_no_zero_point",
24
+ "preset": "smoke",
25
+ "vars": { "inputDtype": "uint8", "outputDtype": "float32", "count": 1048576 },
26
+ "inputs": {
27
+ "x": { "dtype": "uint8", "shape": [1024, 1024], "data": { "kind": "constant", "value": 127 } },
28
+ "x_scale": { "dtype": "float32", "shape": [1], "data": { "kind": "values", "values": [0.02] } }
29
+ },
30
+ "outputs": { "y": { "dtype": "float32", "shape": [1024, 1024] } },
31
+ "bench": {
32
+ "metrics": [
33
+ { "type": "bandwidth", "value": "args.count * (dtypeBytes(args.inputDtype) + dtypeBytes(args.outputDtype))" }
34
+ ]
35
+ }
36
+ },
37
+ {
38
+ "name": "uint8_1m_plus3_scalar",
39
+ "preset": "smoke",
40
+ "vars": { "inputDtype": "uint8", "outputDtype": "float32", "count": 1048579 },
41
+ "inputs": {
42
+ "x": { "dtype": "uint8", "shape": [1048579], "data": { "kind": "constant", "value": 127 } },
43
+ "x_scale": { "dtype": "float32", "shape": [1], "data": { "kind": "values", "values": [0.02] } },
44
+ "x_zero_point": { "dtype": "uint8", "shape": [1], "data": { "kind": "values", "values": [128] } }
45
+ },
46
+ "outputs": { "y": { "dtype": "float32", "shape": [1048579] } },
47
+ "bench": {
48
+ "metrics": [
49
+ { "type": "bandwidth", "value": "args.count * (dtypeBytes(args.inputDtype) + dtypeBytes(args.outputDtype))" }
50
+ ]
51
+ }
52
+ },
53
+ {
54
+ "name": "int8_1m_plus3_no_zero_point",
55
+ "preset": "smoke",
56
+ "vars": { "inputDtype": "int8", "outputDtype": "float32", "count": 1048579 },
57
+ "inputs": {
58
+ "x": { "dtype": "int8", "shape": [1048579], "data": { "kind": "constant", "value": -42 } },
59
+ "x_scale": { "dtype": "float32", "shape": [1], "data": { "kind": "values", "values": [0.02] } }
60
+ },
61
+ "outputs": { "y": { "dtype": "float32", "shape": [1048579] } },
62
+ "bench": {
63
+ "metrics": [
64
+ { "type": "bandwidth", "value": "args.count * (dtypeBytes(args.inputDtype) + dtypeBytes(args.outputDtype))" }
65
+ ]
66
+ }
67
+ },
68
+ {
69
+ "name": "int8_1m_f16",
70
+ "preset": "smoke",
71
+ "vars": { "inputDtype": "int8", "outputDtype": "float16", "count": 1048576 },
72
+ "inputs": {
73
+ "x": { "dtype": "int8", "shape": [1024, 1024], "data": { "kind": "constant", "value": -42 } },
74
+ "x_scale": { "dtype": "float16", "shape": [1], "data": { "kind": "values", "values": [0.125] } },
75
+ "x_zero_point": { "dtype": "int8", "shape": [1], "data": { "kind": "values", "values": [2] } }
76
+ },
77
+ "outputs": { "y": { "dtype": "float16", "shape": [1024, 1024] } },
78
+ "bench": {
79
+ "metrics": [
80
+ { "type": "bandwidth", "value": "args.count * (dtypeBytes(args.inputDtype) + dtypeBytes(args.outputDtype))" }
81
+ ]
82
+ }
83
+ },
84
+ {
85
+ "name": "int8_per_axis0_512x2048",
86
+ "preset": "smoke",
87
+ "vars": { "inputDtype": "int8", "outputDtype": "float32", "count": 1048576 },
88
+ "attrs": { "axis": 0 },
89
+ "inputs": {
90
+ "x": { "dtype": "int8", "shape": [512, 2048], "data": { "kind": "constant", "value": -42 } },
91
+ "x_scale": {
92
+ "dtype": "float32",
93
+ "shape": [512],
94
+ "data": { "kind": "fillFloat32", "sinStep": 0.07, "cosStep": 0.05, "scale": 0.01, "offset": 0.02 }
95
+ },
96
+ "x_zero_point": { "dtype": "int8", "shape": [512], "data": { "kind": "constant", "value": 3 } }
97
+ },
98
+ "outputs": { "y": { "dtype": "float32", "shape": [512, 2048] } },
99
+ "bench": {
100
+ "metrics": [
101
+ { "type": "bandwidth", "value": "args.count * (dtypeBytes(args.inputDtype) + dtypeBytes(args.outputDtype))" }
102
+ ]
103
+ }
104
+ },
105
+ {
106
+ "name": "per_channel_innermost_axis1_scalar_fallback_2048x2048",
107
+ "preset": "smoke",
108
+ "vars": { "inputDtype": "int8", "outputDtype": "float32", "count": 4194304 },
109
+ "attrs": { "axis": 1 },
110
+ "inputs": {
111
+ "x": { "dtype": "int8", "shape": [2048, 2048], "data": { "kind": "constant", "value": -42 } },
112
+ "x_scale": {
113
+ "dtype": "float32",
114
+ "shape": [2048],
115
+ "data": { "kind": "fillFloat32", "sinStep": 0.07, "cosStep": 0.05, "scale": 0.01, "offset": 0.02 }
116
+ },
117
+ "x_zero_point": { "dtype": "int8", "shape": [2048], "data": { "kind": "constant", "value": 3 } }
118
+ },
119
+ "outputs": { "y": { "dtype": "float32", "shape": [2048, 2048] } },
120
+ "bench": {
121
+ "metrics": [
122
+ { "type": "bandwidth", "value": "args.count * (dtypeBytes(args.inputDtype) + dtypeBytes(args.outputDtype))" }
123
+ ]
124
+ }
125
+ },
126
+ {
127
+ "name": "per_channel_axis0_vec4_healthy_2048x2048",
128
+ "preset": "smoke",
129
+ "vars": { "inputDtype": "int8", "outputDtype": "float32", "count": 4194304 },
130
+ "attrs": { "axis": 0 },
131
+ "inputs": {
132
+ "x": { "dtype": "int8", "shape": [2048, 2048], "data": { "kind": "constant", "value": -42 } },
133
+ "x_scale": {
134
+ "dtype": "float32",
135
+ "shape": [2048],
136
+ "data": { "kind": "fillFloat32", "sinStep": 0.07, "cosStep": 0.05, "scale": 0.01, "offset": 0.02 }
137
+ },
138
+ "x_zero_point": { "dtype": "int8", "shape": [2048], "data": { "kind": "constant", "value": 3 } }
139
+ },
140
+ "outputs": { "y": { "dtype": "float32", "shape": [2048, 2048] } },
141
+ "bench": {
142
+ "metrics": [
143
+ { "type": "bandwidth", "value": "args.count * (dtypeBytes(args.inputDtype) + dtypeBytes(args.outputDtype))" }
144
+ ]
145
+ }
146
+ },
147
+ {
148
+ "name": "per_channel_axis0_unaligned_inner2050_scalar_cliff",
149
+ "preset": "smoke",
150
+ "vars": { "inputDtype": "int8", "outputDtype": "float32", "count": 1049600 },
151
+ "attrs": { "axis": 0 },
152
+ "inputs": {
153
+ "x": { "dtype": "int8", "shape": [512, 2050], "data": { "kind": "constant", "value": -42 } },
154
+ "x_scale": {
155
+ "dtype": "float32",
156
+ "shape": [512],
157
+ "data": { "kind": "fillFloat32", "sinStep": 0.07, "cosStep": 0.05, "scale": 0.01, "offset": 0.02 }
158
+ },
159
+ "x_zero_point": { "dtype": "int8", "shape": [512], "data": { "kind": "constant", "value": 3 } }
160
+ },
161
+ "outputs": { "y": { "dtype": "float32", "shape": [512, 2050] } },
162
+ "bench": {
163
+ "metrics": [
164
+ { "type": "bandwidth", "value": "args.count * (dtypeBytes(args.inputDtype) + dtypeBytes(args.outputDtype))" }
165
+ ]
166
+ }
167
+ },
168
+ {
169
+ "name": "scalar_above_67M_vec4_ceiling_fallback",
170
+ "preset": "stress",
171
+ "provenance": {
172
+ "notes": "Stress-only capacity case: uint8 elements use 4-byte WebGPU storage, bringing the declared footprint to 512 MiB."
173
+ },
174
+ "vars": { "inputDtype": "uint8", "outputDtype": "float32", "count": 67108864 },
175
+ "attrs": { "axis": 0 },
176
+ "inputs": {
177
+ "x": { "dtype": "uint8", "shape": [8192, 8192], "data": { "kind": "constant", "value": 127 } },
178
+ "x_scale": { "dtype": "float32", "shape": [1], "data": { "kind": "values", "values": [0.02] } },
179
+ "x_zero_point": { "dtype": "uint8", "shape": [1], "data": { "kind": "values", "values": [128] } }
180
+ },
181
+ "outputs": { "y": { "dtype": "float32", "shape": [8192, 8192] } },
182
+ "bench": {
183
+ "metrics": [
184
+ { "type": "bandwidth", "value": "args.count * (dtypeBytes(args.inputDtype) + dtypeBytes(args.outputDtype))" }
185
+ ]
186
+ }
187
+ },
188
+ {
189
+ "name": "f16_tail_scalar_x4_1m_plus3",
190
+ "preset": "smoke",
191
+ "vars": { "inputDtype": "int8", "outputDtype": "float16", "count": 1048579 },
192
+ "attrs": { "axis": 0 },
193
+ "inputs": {
194
+ "x": { "dtype": "int8", "shape": [1048579], "data": { "kind": "constant", "value": -42 } },
195
+ "x_scale": { "dtype": "float16", "shape": [1], "data": { "kind": "values", "values": [0.125] } },
196
+ "x_zero_point": { "dtype": "int8", "shape": [1], "data": { "kind": "values", "values": [2] } }
197
+ },
198
+ "outputs": { "y": { "dtype": "float16", "shape": [1048579] } },
199
+ "bench": {
200
+ "metrics": [
201
+ { "type": "bandwidth", "value": "args.count * (dtypeBytes(args.inputDtype) + dtypeBytes(args.outputDtype))" }
202
+ ]
203
+ }
204
+ },
205
+ {
206
+ "name": "blocked_rank4_axis1_bs32_stress_4m",
207
+ "preset": "stress",
208
+ "vars": { "inputDtype": "int8", "outputDtype": "float32", "count": 4194304 },
209
+ "attrs": { "axis": 1, "block_size": 32 },
210
+ "inputs": {
211
+ "x": { "dtype": "int8", "shape": [4, 512, 32, 64], "dist": "randint", "seed": 101, "min": -128, "max": 127 },
212
+ "x_scale": { "dtype": "float32", "shape": [4, 16, 32, 64], "dist": "normal", "seed": 102, "scale": 0.02 },
213
+ "x_zero_point": {
214
+ "dtype": "int8",
215
+ "shape": [4, 16, 32, 64],
216
+ "dist": "randint",
217
+ "seed": 103,
218
+ "min": -8,
219
+ "max": 8
220
+ }
221
+ },
222
+ "outputs": { "y": { "dtype": "float32", "shape": [4, 512, 32, 64], "dist": "empty" } },
223
+ "bench": {
224
+ "metrics": [
225
+ { "type": "bandwidth", "value": "args.count * (dtypeBytes(args.inputDtype) + dtypeBytes(args.outputDtype))" }
226
+ ]
227
+ }
228
+ },
229
+ {
230
+ "name": "per_axis_mid_axis1_rank3_inner_not_mult4_scalar_fallback_stress",
231
+ "preset": "stress",
232
+ "vars": { "inputDtype": "int8", "outputDtype": "float32", "count": 8396800 },
233
+ "attrs": { "axis": 1 },
234
+ "inputs": {
235
+ "x": { "dtype": "int8", "shape": [8, 512, 2050], "dist": "randint", "seed": 201, "min": -128, "max": 127 },
236
+ "x_scale": { "dtype": "float32", "shape": [512], "dist": "normal", "seed": 202, "scale": 0.02 },
237
+ "x_zero_point": { "dtype": "int8", "shape": [512], "dist": "randint", "seed": 203, "min": -8, "max": 8 }
238
+ },
239
+ "outputs": { "y": { "dtype": "float32", "shape": [8, 512, 2050], "dist": "empty" } },
240
+ "bench": {
241
+ "metrics": [
242
+ { "type": "bandwidth", "value": "args.count * (dtypeBytes(args.inputDtype) + dtypeBytes(args.outputDtype))" }
243
+ ]
244
+ }
245
+ }
246
+ ]
247
+ }
build/webgpu/manifest.json ADDED
@@ -0,0 +1,646 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "domain": "ai.onnx",
3
+ "name": "DequantizeLinear",
4
+ "sinceVersion": 25,
5
+ "description": "Dequantizes a quantized tensor back to full precision using the formula `y = (x - x_zero_point) * x_scale`. Scale and zero point determine quantization granularity: scalar for per-tensor, 1-D for per-axis, or same rank as input for blocked quantization. The output type matches `x_scale` unless overridden by `output_dtype`.",
6
+ "inputs": [
7
+ { "role": "x", "dtype": "TQ", "description": "N-D quantized input tensor to be dequantized." },
8
+ {
9
+ "role": "x_scale",
10
+ "dtype": "TF",
11
+ "description": "Scale for `x`; scalar for per-tensor, 1-D for per-axis, or same-rank tensor for blocked dequantization."
12
+ },
13
+ {
14
+ "role": "x_zero_point",
15
+ "dtype": "TQ",
16
+ "optional": true,
17
+ "description": "Zero point for `x` with shape matching `x_scale`; defaults to zero when absent."
18
+ }
19
+ ],
20
+ "outputs": [
21
+ {
22
+ "role": "y",
23
+ "dtype": "TF",
24
+ "rank": "ranks.x",
25
+ "description": "N-D full-precision output with the same shape as `x`, typed according to `x_scale` or `output_dtype`.",
26
+ "shape": "shapes.x"
27
+ }
28
+ ],
29
+ "attributes": { "axis": 1, "block_size": 0, "output_dtype": 0 },
30
+ "attributeDescriptions": {
31
+ "axis": "The axis of the dequantizing dimension, used for per-axis and blocked quantization; negative values index from the end.",
32
+ "block_size": "Number of elements along `axis` that share each scale value for blocked quantization; 0 means not blocked.",
33
+ "output_dtype": "ONNX TensorProto element-type code for `y`; `0` uses the dtype of `x_scale`. The current float16/float32 routes require it to agree with `x_scale`."
34
+ },
35
+ "typeConstraints": { "TQ": ["uint8", "int8", "int16", "int32"], "TF": ["float32", "float16"] },
36
+ "args": {
37
+ "x": { "kind": "tensor", "semantic": "x", "role": "input" },
38
+ "x_scale": { "kind": "tensor", "semantic": "x_scale", "role": "input" },
39
+ "x_zero_point": { "kind": "tensor", "semantic": "x_zero_point", "role": "input", "required": false },
40
+ "y": { "kind": "tensor", "semantic": "y", "role": "output" }
41
+ },
42
+ "tunables": { "WORKGROUP_SIZE": 256, "VEC4_TAIL_MIN_ELEMENTS": 4096 },
43
+ "derive": {
44
+ "deviceWorkgroupCap": "min(device.limits.maxComputeInvocationsPerWorkgroup, device.limits.maxComputeWorkgroupSizeX)",
45
+ "workgroupOk": "tunables.WORKGROUP_SIZE <= deviceWorkgroupCap",
46
+ "outputDispatchFits": "workgroupOk and ceilDiv(ceilDiv(numel(shapes.y), tunables.WORKGROUP_SIZE), device.limits.maxComputeWorkgroupsPerDimension) <= device.limits.maxComputeWorkgroupsPerDimension",
47
+ "sameShapeOk": "ranks.y == ranks.x and numel(shapes.x) == numel(shapes.y) and outputDispatchFits",
48
+ "dequantDtypesOk": "(attrs.output_dtype == 0 or attrs.output_dtype == onnxDtypeCode(logicalDtypes.TF)) and f16Ok(dtypes.TF)",
49
+ "blockedScaleOk": "attrs.block_size > 0 and ranks.x >= 2 and ranks.x_scale == ranks.x and sameShapeOk and dim(shapes.x_scale, attrs.axis) == ceil(dim(shapes.x, attrs.axis) / attrs.block_size)",
50
+ "elementCount": "numel(shapes.y)",
51
+ "elementCount4": "floor(numel(shapes.y) / 4)",
52
+ "scaleSize": "1 if ranks.x_scale == 0 else dim(shapes.x_scale, 0)",
53
+ "scaleInner": "1 if ranks.x_scale == 0 or dim(shapes.x_scale, 0) == 1 else inner(shapes.x, attrs.axis)",
54
+ "blockedAxisDim": "dim(shapes.x, attrs.axis) if ranks.x >= 2 else 1",
55
+ "blockedScaleAxisDim": "dim(shapes.x_scale, attrs.axis) if ranks.x_scale >= 2 else 1",
56
+ "blockedInner": "inner(shapes.x, attrs.axis) if ranks.x >= 2 else 1"
57
+ },
58
+ "constants": {
59
+ "usesF16": "dtypes.TF == \"f16\"",
60
+ "xScalar": "dtypes.TQ",
61
+ "xVec4": "\"vec4<\" ~ dtypes.TQ ~ \">\"",
62
+ "scaleScalar": "dtypes.TF",
63
+ "scaleVec4": "\"vec4<\" ~ dtypes.TF ~ \">\"",
64
+ "yScalar": "dtypes.TF",
65
+ "yVec4": "\"vec4<\" ~ dtypes.TF ~ \">\"",
66
+ "xUnsigned": "tensorDtypes.x == \"uint8\""
67
+ },
68
+ "variants": [
69
+ {
70
+ "id": "blocked_with_zero_point",
71
+ "priority": 19,
72
+ "when": ["present.x_zero_point", "blockedScaleOk", "ranks.x_zero_point == ranks.x", "dim(shapes.x_zero_point, attrs.axis) == dim(shapes.x_scale, attrs.axis)", "dequantDtypesOk"],
73
+ "constants": { "hasZero": true },
74
+ "passes": [
75
+ {
76
+ "id": "main",
77
+ "name": "DequantizeLinear.Blocked",
78
+ "source": { "shader": "quant-linear-blocked-axis.wgsl.jinja", "inputs": { "op": "\"dequantize\"" } },
79
+ "bindings": "blockedScalarWithZero",
80
+ "dispatch": { "threads": "numel(shapes.y)", "workgroupSize": "tunables.WORKGROUP_SIZE" }
81
+ }
82
+ ]
83
+ },
84
+ {
85
+ "id": "blocked_no_zero_point",
86
+ "priority": 19,
87
+ "when": ["not present.x_zero_point", "blockedScaleOk", "dequantDtypesOk"],
88
+ "constants": { "hasZero": false },
89
+ "passes": [
90
+ {
91
+ "id": "main",
92
+ "name": "DequantizeLinear.BlockedNoZero",
93
+ "source": { "shader": "quant-linear-blocked-axis.wgsl.jinja", "inputs": { "op": "\"dequantize\"" } },
94
+ "bindings": "blockedScalarNoZero",
95
+ "dispatch": { "threads": "numel(shapes.y)", "workgroupSize": "tunables.WORKGROUP_SIZE" }
96
+ }
97
+ ]
98
+ },
99
+ {
100
+ "id": "innermost_axis_vec4_with_zero_point",
101
+ "priority": 20,
102
+ "when": ["present.x_zero_point", "ranks.x >= 1", "attrs.axis == -1 or attrs.axis == ranks.x - 1", "ranks.x_scale == 1", "dim(shapes.x_scale, 0) == dim(shapes.x, ranks.x - 1)", "dim(shapes.x_scale, 0) % 4 == 0", "ranks.x_zero_point == 1", "dim(shapes.x_zero_point, 0) == dim(shapes.x_scale, 0)", "numel(shapes.y) > 0", "numel(shapes.y) % 4 == 0", "sameShapeOk", "dequantDtypesOk"],
103
+ "constants": { "hasZero": true },
104
+ "passes": [
105
+ {
106
+ "id": "main",
107
+ "name": "DequantizeLinear.InnermostAxisVec4",
108
+ "source": {
109
+ "shader": "quant-linear-vec4.wgsl.jinja",
110
+ "inputs": { "op": "\"dequantize\"", "perAxis": true, "vectorParams": true }
111
+ },
112
+ "bindings": "linearInnermostVec4WithZero",
113
+ "dispatch": { "threads": "floor(numel(shapes.y) / 4)", "workgroupSize": "tunables.WORKGROUP_SIZE" }
114
+ }
115
+ ]
116
+ },
117
+ {
118
+ "id": "innermost_axis_vec4_no_zero_point",
119
+ "priority": 20,
120
+ "when": ["not present.x_zero_point", "ranks.x >= 1", "attrs.axis == -1 or attrs.axis == ranks.x - 1", "ranks.x_scale == 1", "dim(shapes.x_scale, 0) == dim(shapes.x, ranks.x - 1)", "dim(shapes.x_scale, 0) % 4 == 0", "numel(shapes.y) > 0", "numel(shapes.y) % 4 == 0", "sameShapeOk", "dequantDtypesOk"],
121
+ "constants": { "hasZero": false },
122
+ "passes": [
123
+ {
124
+ "id": "main",
125
+ "name": "DequantizeLinear.InnermostAxisVec4NoZero",
126
+ "source": {
127
+ "shader": "quant-linear-vec4.wgsl.jinja",
128
+ "inputs": { "op": "\"dequantize\"", "perAxis": true, "vectorParams": true }
129
+ },
130
+ "bindings": "linearInnermostVec4NoZero",
131
+ "dispatch": { "threads": "floor(numel(shapes.y) / 4)", "workgroupSize": "tunables.WORKGROUP_SIZE" }
132
+ }
133
+ ]
134
+ },
135
+ {
136
+ "id": "vec4_cross_axis_with_zero_point",
137
+ "priority": 16,
138
+ "when": ["present.x_zero_point", "attrs.block_size == 0", "ranks.x >= 1", "attrs.axis >= 0", "attrs.axis < ranks.x", "ranks.x_scale == 1", "dim(shapes.x_scale, 0) == dim(shapes.x, attrs.axis)", "inner(shapes.x, attrs.axis) % 4 != 0", "ranks.x_zero_point == 1", "dim(shapes.x_zero_point, 0) == dim(shapes.x_scale, 0)", "numel(shapes.y) > 0", "numel(shapes.y) % 4 == 0", "sameShapeOk", "dequantDtypesOk"],
139
+ "constants": { "hasZero": true },
140
+ "passes": [
141
+ {
142
+ "id": "main",
143
+ "name": "DequantizeLinear.Vec4CrossAxis",
144
+ "source": {
145
+ "shader": "quant-linear-vec4.wgsl.jinja",
146
+ "inputs": { "op": "\"dequantize\"", "perAxis": true, "crossingParams": true }
147
+ },
148
+ "bindings": "linearVec4WithZero",
149
+ "dispatch": { "threads": "numel(shapes.y) / 4", "workgroupSize": "tunables.WORKGROUP_SIZE" }
150
+ }
151
+ ]
152
+ },
153
+ {
154
+ "id": "vec4_with_zero_point",
155
+ "priority": 15,
156
+ "when": ["present.x_zero_point", "numel(shapes.y) > 0", "numel(shapes.y) % 4 == 0", "(ranks.x_scale == 0 or ranks.x_scale == 1)", "sameShapeOk", "(ranks.x_scale == 0 or dim(shapes.x_scale, 0) == 1 or (ranks.x >= 1 and dim(shapes.x_scale, 0) == dim(shapes.x, attrs.axis) and inner(shapes.x, attrs.axis) % 4 == 0))", "(ranks.x_zero_point == 0 or ranks.x_zero_point == 1)", "(ranks.x_zero_point == 0 or dim(shapes.x_zero_point, 0) == 1 or (ranks.x >= 1 and dim(shapes.x_zero_point, 0) == dim(shapes.x, attrs.axis)))", "dequantDtypesOk"],
157
+ "constants": { "hasZero": true },
158
+ "passes": [
159
+ {
160
+ "id": "main",
161
+ "name": "DequantizeLinear.Vec4",
162
+ "source": {
163
+ "shader": "quant-linear-vec4.wgsl.jinja",
164
+ "inputs": { "op": "\"dequantize\"", "perAxis": "not (ranks.x_scale == 0 or dim(shapes.x_scale, 0) == 1)" }
165
+ },
166
+ "bindings": "linearVec4WithZero",
167
+ "dispatch": { "threads": "numel(shapes.y) / 4", "workgroupSize": "tunables.WORKGROUP_SIZE" }
168
+ }
169
+ ]
170
+ },
171
+ {
172
+ "id": "vec4_no_zero_point",
173
+ "priority": 15,
174
+ "when": ["not present.x_zero_point", "numel(shapes.y) > 0", "numel(shapes.y) % 4 == 0", "(ranks.x_scale == 0 or ranks.x_scale == 1)", "sameShapeOk", "(ranks.x_scale == 0 or dim(shapes.x_scale, 0) == 1 or (ranks.x >= 1 and dim(shapes.x_scale, 0) == dim(shapes.x, attrs.axis) and inner(shapes.x, attrs.axis) % 4 == 0))", "dequantDtypesOk"],
175
+ "constants": { "hasZero": false },
176
+ "passes": [
177
+ {
178
+ "id": "main",
179
+ "name": "DequantizeLinear.Vec4",
180
+ "source": {
181
+ "shader": "quant-linear-vec4.wgsl.jinja",
182
+ "inputs": { "op": "\"dequantize\"", "perAxis": "not (ranks.x_scale == 0 or dim(shapes.x_scale, 0) == 1)" }
183
+ },
184
+ "bindings": "linearVec4NoZero",
185
+ "dispatch": { "threads": "numel(shapes.y) / 4", "workgroupSize": "tunables.WORKGROUP_SIZE" }
186
+ }
187
+ ]
188
+ },
189
+ {
190
+ "id": "vec4_tail_with_zero_point",
191
+ "priority": 10,
192
+ "when": ["present.x_zero_point", "numel(shapes.y) >= tunables.VEC4_TAIL_MIN_ELEMENTS", "numel(shapes.y) % 4 != 0", "(ranks.x_scale == 0 or (ranks.x_scale == 1 and dim(shapes.x_scale, 0) == 1))", "(ranks.x_zero_point == 0 or (ranks.x_zero_point == 1 and dim(shapes.x_zero_point, 0) == 1))", "sameShapeOk", "dequantDtypesOk"],
193
+ "constants": { "hasZero": true },
194
+ "passes": [
195
+ {
196
+ "id": "bulk",
197
+ "name": "DequantizeLinear.Vec4Bulk",
198
+ "source": { "shader": "quant-linear-vec4.wgsl.jinja", "inputs": { "op": "\"dequantize\"", "perAxis": false } },
199
+ "bindings": "linearVec4PerTensorWithZero",
200
+ "dispatch": { "threads": "floor(numel(shapes.y) / 4)", "workgroupSize": "tunables.WORKGROUP_SIZE" }
201
+ },
202
+ {
203
+ "id": "tail",
204
+ "name": "DequantizeLinear.ScalarTail",
205
+ "source": {
206
+ "shader": "quant-linear-scalar.wgsl.jinja",
207
+ "inputs": { "op": "\"dequantize\"", "x4": true, "perAxis": false }
208
+ },
209
+ "bindings": "linearScalarPerTensorWithZero",
210
+ "dispatch": { "threads": 1, "workgroupSize": "tunables.WORKGROUP_SIZE" }
211
+ }
212
+ ]
213
+ },
214
+ {
215
+ "id": "vec4_tail_no_zero_point",
216
+ "priority": 10,
217
+ "when": ["not present.x_zero_point", "numel(shapes.y) >= tunables.VEC4_TAIL_MIN_ELEMENTS", "numel(shapes.y) % 4 != 0", "(ranks.x_scale == 0 or (ranks.x_scale == 1 and dim(shapes.x_scale, 0) == 1))", "sameShapeOk", "dequantDtypesOk"],
218
+ "constants": { "hasZero": false },
219
+ "passes": [
220
+ {
221
+ "id": "bulk",
222
+ "name": "DequantizeLinear.Vec4Bulk",
223
+ "source": { "shader": "quant-linear-vec4.wgsl.jinja", "inputs": { "op": "\"dequantize\"", "perAxis": false } },
224
+ "bindings": "linearVec4PerTensorNoZero",
225
+ "dispatch": { "threads": "floor(numel(shapes.y) / 4)", "workgroupSize": "tunables.WORKGROUP_SIZE" }
226
+ },
227
+ {
228
+ "id": "tail",
229
+ "name": "DequantizeLinear.ScalarTail",
230
+ "source": {
231
+ "shader": "quant-linear-scalar.wgsl.jinja",
232
+ "inputs": { "op": "\"dequantize\"", "x4": true, "perAxis": false }
233
+ },
234
+ "bindings": "linearScalarPerTensorNoZero",
235
+ "dispatch": { "threads": 1, "workgroupSize": "tunables.WORKGROUP_SIZE" }
236
+ }
237
+ ]
238
+ },
239
+ {
240
+ "id": "linear_scalar_or_axis_zero",
241
+ "when": ["present.x_zero_point", "(ranks.x_scale == 0 or ranks.x_scale == 1)", "sameShapeOk", "(ranks.x_scale == 0 or dim(shapes.x_scale, 0) == 1 or (ranks.x >= 1 and dim(shapes.x_scale, 0) == dim(shapes.x, attrs.axis)))", "(ranks.x_zero_point == 0 or ranks.x_zero_point == 1)", "(ranks.x_zero_point == 0 or dim(shapes.x_zero_point, 0) == 1 or (ranks.x >= 1 and dim(shapes.x_zero_point, 0) == dim(shapes.x, attrs.axis)))", "dequantDtypesOk"],
242
+ "constants": { "hasZero": true },
243
+ "passes": [
244
+ {
245
+ "id": "main",
246
+ "name": "DequantizeLinear",
247
+ "source": {
248
+ "shader": "quant-linear-scalar.wgsl.jinja",
249
+ "inputs": {
250
+ "op": "\"dequantize\"",
251
+ "x4": "false",
252
+ "perAxis": "not (ranks.x_scale == 0 or dim(shapes.x_scale, 0) == 1)"
253
+ }
254
+ },
255
+ "bindings": "linearScalarWithZero",
256
+ "dispatch": { "threads": "numel(shapes.y)", "workgroupSize": "tunables.WORKGROUP_SIZE" }
257
+ }
258
+ ]
259
+ },
260
+ {
261
+ "id": "linear_scalar_or_axis_no_zero",
262
+ "when": ["not present.x_zero_point", "(ranks.x_scale == 0 or ranks.x_scale == 1)", "sameShapeOk", "(ranks.x_scale == 0 or dim(shapes.x_scale, 0) == 1 or (ranks.x >= 1 and dim(shapes.x_scale, 0) == dim(shapes.x, attrs.axis)))", "dequantDtypesOk"],
263
+ "constants": { "hasZero": false },
264
+ "passes": [
265
+ {
266
+ "id": "main",
267
+ "name": "DequantizeLinear",
268
+ "source": {
269
+ "shader": "quant-linear-scalar.wgsl.jinja",
270
+ "inputs": {
271
+ "op": "\"dequantize\"",
272
+ "x4": "false",
273
+ "perAxis": "not (ranks.x_scale == 0 or dim(shapes.x_scale, 0) == 1)"
274
+ }
275
+ },
276
+ "bindings": "linearScalarNoZero",
277
+ "dispatch": { "threads": "numel(shapes.y)", "workgroupSize": "tunables.WORKGROUP_SIZE" }
278
+ }
279
+ ]
280
+ }
281
+ ],
282
+ "bindingSets": {
283
+ "blockedScalarWithZero": [
284
+ { "name": "x", "arg": "x", "semantic": "x", "buffer": { "type": "read-only-storage" }, "elementType": "$xScalar" },
285
+ {
286
+ "name": "x_scale",
287
+ "arg": "x_scale",
288
+ "semantic": "x_scale",
289
+ "buffer": { "type": "read-only-storage" },
290
+ "elementType": "$scaleScalar"
291
+ },
292
+ {
293
+ "name": "x_zero_point",
294
+ "arg": "x_zero_point",
295
+ "semantic": "x_zero_point",
296
+ "buffer": { "type": "read-only-storage" },
297
+ "elementType": "$xScalar"
298
+ },
299
+ { "name": "y", "arg": "y", "semantic": "y", "buffer": { "type": "storage" }, "elementType": "$yScalar" },
300
+ {
301
+ "name": "params",
302
+ "semantic": "kernel.params",
303
+ "buffer": { "type": "uniform" },
304
+ "struct": {
305
+ "name": "Params",
306
+ "fields": [
307
+ { "name": "count", "type": "u32", "value": "elementCount" },
308
+ { "name": "axisDim", "type": "u32", "value": "blockedAxisDim" },
309
+ { "name": "scaleAxisDim", "type": "u32", "value": "blockedScaleAxisDim" },
310
+ { "name": "inner", "type": "u32", "value": "blockedInner" },
311
+ { "name": "blockSize", "type": "u32", "value": "attrs.block_size" }
312
+ ]
313
+ }
314
+ }
315
+ ],
316
+ "blockedScalarNoZero": [
317
+ { "name": "x", "arg": "x", "semantic": "x", "buffer": { "type": "read-only-storage" }, "elementType": "$xScalar" },
318
+ {
319
+ "name": "x_scale",
320
+ "arg": "x_scale",
321
+ "semantic": "x_scale",
322
+ "buffer": { "type": "read-only-storage" },
323
+ "elementType": "$scaleScalar"
324
+ },
325
+ { "name": "y", "arg": "y", "semantic": "y", "buffer": { "type": "storage" }, "elementType": "$yScalar" },
326
+ {
327
+ "name": "params",
328
+ "semantic": "kernel.params",
329
+ "buffer": { "type": "uniform" },
330
+ "struct": {
331
+ "name": "Params",
332
+ "fields": [
333
+ { "name": "count", "type": "u32", "value": "elementCount" },
334
+ { "name": "axisDim", "type": "u32", "value": "blockedAxisDim" },
335
+ { "name": "scaleAxisDim", "type": "u32", "value": "blockedScaleAxisDim" },
336
+ { "name": "inner", "type": "u32", "value": "blockedInner" },
337
+ { "name": "blockSize", "type": "u32", "value": "attrs.block_size" }
338
+ ]
339
+ }
340
+ }
341
+ ],
342
+ "linearInnermostVec4WithZero": [
343
+ { "name": "x", "arg": "x", "semantic": "x", "buffer": { "type": "read-only-storage" }, "elementType": "$xVec4" },
344
+ {
345
+ "name": "x_scale",
346
+ "arg": "x_scale",
347
+ "semantic": "x_scale",
348
+ "buffer": { "type": "read-only-storage" },
349
+ "elementType": "$scaleVec4"
350
+ },
351
+ {
352
+ "name": "x_zero_point",
353
+ "arg": "x_zero_point",
354
+ "semantic": "x_zero_point",
355
+ "buffer": { "type": "read-only-storage" },
356
+ "elementType": "$xVec4"
357
+ },
358
+ { "name": "y", "arg": "y", "semantic": "y", "buffer": { "type": "storage" }, "elementType": "$yVec4" },
359
+ {
360
+ "name": "params",
361
+ "semantic": "kernel.params",
362
+ "buffer": { "type": "uniform" },
363
+ "struct": {
364
+ "name": "Params",
365
+ "fields": [
366
+ { "name": "count4", "type": "u32", "value": "elementCount4" },
367
+ { "name": "scaleSize", "type": "u32", "value": "scaleSize" }
368
+ ]
369
+ }
370
+ }
371
+ ],
372
+ "linearInnermostVec4NoZero": [
373
+ { "name": "x", "arg": "x", "semantic": "x", "buffer": { "type": "read-only-storage" }, "elementType": "$xVec4" },
374
+ {
375
+ "name": "x_scale",
376
+ "arg": "x_scale",
377
+ "semantic": "x_scale",
378
+ "buffer": { "type": "read-only-storage" },
379
+ "elementType": "$scaleVec4"
380
+ },
381
+ { "name": "y", "arg": "y", "semantic": "y", "buffer": { "type": "storage" }, "elementType": "$yVec4" },
382
+ {
383
+ "name": "params",
384
+ "semantic": "kernel.params",
385
+ "buffer": { "type": "uniform" },
386
+ "struct": {
387
+ "name": "Params",
388
+ "fields": [
389
+ { "name": "count4", "type": "u32", "value": "elementCount4" },
390
+ { "name": "scaleSize", "type": "u32", "value": "scaleSize" }
391
+ ]
392
+ }
393
+ }
394
+ ],
395
+ "linearVec4WithZero": [
396
+ { "name": "x", "arg": "x", "semantic": "x", "buffer": { "type": "read-only-storage" }, "elementType": "$xVec4" },
397
+ {
398
+ "name": "x_scale",
399
+ "arg": "x_scale",
400
+ "semantic": "x_scale",
401
+ "buffer": { "type": "read-only-storage" },
402
+ "elementType": "$scaleScalar"
403
+ },
404
+ {
405
+ "name": "x_zero_point",
406
+ "arg": "x_zero_point",
407
+ "semantic": "x_zero_point",
408
+ "buffer": { "type": "read-only-storage" },
409
+ "elementType": "$xScalar"
410
+ },
411
+ { "name": "y", "arg": "y", "semantic": "y", "buffer": { "type": "storage" }, "elementType": "$yVec4" },
412
+ {
413
+ "name": "params",
414
+ "semantic": "kernel.params",
415
+ "buffer": { "type": "uniform" },
416
+ "struct": {
417
+ "name": "Params",
418
+ "fields": [
419
+ { "name": "count4", "type": "u32", "value": "elementCount4" },
420
+ { "name": "scaleSize", "type": "u32", "value": "scaleSize" },
421
+ { "name": "inner", "type": "u32", "value": "scaleInner" }
422
+ ]
423
+ }
424
+ }
425
+ ],
426
+ "linearVec4NoZero": [
427
+ { "name": "x", "arg": "x", "semantic": "x", "buffer": { "type": "read-only-storage" }, "elementType": "$xVec4" },
428
+ {
429
+ "name": "x_scale",
430
+ "arg": "x_scale",
431
+ "semantic": "x_scale",
432
+ "buffer": { "type": "read-only-storage" },
433
+ "elementType": "$scaleScalar"
434
+ },
435
+ { "name": "y", "arg": "y", "semantic": "y", "buffer": { "type": "storage" }, "elementType": "$yVec4" },
436
+ {
437
+ "name": "params",
438
+ "semantic": "kernel.params",
439
+ "buffer": { "type": "uniform" },
440
+ "struct": {
441
+ "name": "Params",
442
+ "fields": [
443
+ { "name": "count4", "type": "u32", "value": "elementCount4" },
444
+ { "name": "scaleSize", "type": "u32", "value": "scaleSize" },
445
+ { "name": "inner", "type": "u32", "value": "scaleInner" }
446
+ ]
447
+ }
448
+ }
449
+ ],
450
+ "linearScalarWithZero": [
451
+ { "name": "x", "arg": "x", "semantic": "x", "buffer": { "type": "read-only-storage" }, "elementType": "$xScalar" },
452
+ {
453
+ "name": "x_scale",
454
+ "arg": "x_scale",
455
+ "semantic": "x_scale",
456
+ "buffer": { "type": "read-only-storage" },
457
+ "elementType": "$scaleScalar"
458
+ },
459
+ {
460
+ "name": "x_zero_point",
461
+ "arg": "x_zero_point",
462
+ "semantic": "x_zero_point",
463
+ "buffer": { "type": "read-only-storage" },
464
+ "elementType": "$xScalar"
465
+ },
466
+ { "name": "y", "arg": "y", "semantic": "y", "buffer": { "type": "storage" }, "elementType": "$yScalar" },
467
+ {
468
+ "name": "params",
469
+ "semantic": "kernel.params",
470
+ "buffer": { "type": "uniform" },
471
+ "struct": {
472
+ "name": "Params",
473
+ "fields": [
474
+ { "name": "count", "type": "u32", "value": "elementCount" },
475
+ { "name": "scaleSize", "type": "u32", "value": "scaleSize" },
476
+ { "name": "inner", "type": "u32", "value": "scaleInner" }
477
+ ]
478
+ }
479
+ }
480
+ ],
481
+ "linearScalarNoZero": [
482
+ { "name": "x", "arg": "x", "semantic": "x", "buffer": { "type": "read-only-storage" }, "elementType": "$xScalar" },
483
+ {
484
+ "name": "x_scale",
485
+ "arg": "x_scale",
486
+ "semantic": "x_scale",
487
+ "buffer": { "type": "read-only-storage" },
488
+ "elementType": "$scaleScalar"
489
+ },
490
+ { "name": "y", "arg": "y", "semantic": "y", "buffer": { "type": "storage" }, "elementType": "$yScalar" },
491
+ {
492
+ "name": "params",
493
+ "semantic": "kernel.params",
494
+ "buffer": { "type": "uniform" },
495
+ "struct": {
496
+ "name": "Params",
497
+ "fields": [
498
+ { "name": "count", "type": "u32", "value": "elementCount" },
499
+ { "name": "scaleSize", "type": "u32", "value": "scaleSize" },
500
+ { "name": "inner", "type": "u32", "value": "scaleInner" }
501
+ ]
502
+ }
503
+ }
504
+ ],
505
+ "linearVec4WithZeroIo": [
506
+ { "name": "x", "arg": "x", "semantic": "x", "buffer": { "type": "read-only-storage" }, "elementType": "$xVec4" },
507
+ {
508
+ "name": "x_scale",
509
+ "arg": "x_scale",
510
+ "semantic": "x_scale",
511
+ "buffer": { "type": "read-only-storage" },
512
+ "elementType": "$scaleScalar"
513
+ },
514
+ {
515
+ "name": "x_zero_point",
516
+ "arg": "x_zero_point",
517
+ "semantic": "x_zero_point",
518
+ "buffer": { "type": "read-only-storage" },
519
+ "elementType": "$xScalar"
520
+ },
521
+ { "name": "y", "arg": "y", "semantic": "y", "buffer": { "type": "storage" }, "elementType": "$yVec4" }
522
+ ],
523
+ "linearVec4NoZeroIo": [
524
+ { "name": "x", "arg": "x", "semantic": "x", "buffer": { "type": "read-only-storage" }, "elementType": "$xVec4" },
525
+ {
526
+ "name": "x_scale",
527
+ "arg": "x_scale",
528
+ "semantic": "x_scale",
529
+ "buffer": { "type": "read-only-storage" },
530
+ "elementType": "$scaleScalar"
531
+ },
532
+ { "name": "y", "arg": "y", "semantic": "y", "buffer": { "type": "storage" }, "elementType": "$yVec4" }
533
+ ],
534
+ "linearScalarWithZeroIo": [
535
+ { "name": "x", "arg": "x", "semantic": "x", "buffer": { "type": "read-only-storage" }, "elementType": "$xScalar" },
536
+ {
537
+ "name": "x_scale",
538
+ "arg": "x_scale",
539
+ "semantic": "x_scale",
540
+ "buffer": { "type": "read-only-storage" },
541
+ "elementType": "$scaleScalar"
542
+ },
543
+ {
544
+ "name": "x_zero_point",
545
+ "arg": "x_zero_point",
546
+ "semantic": "x_zero_point",
547
+ "buffer": { "type": "read-only-storage" },
548
+ "elementType": "$xScalar"
549
+ },
550
+ { "name": "y", "arg": "y", "semantic": "y", "buffer": { "type": "storage" }, "elementType": "$yScalar" }
551
+ ],
552
+ "linearScalarNoZeroIo": [
553
+ { "name": "x", "arg": "x", "semantic": "x", "buffer": { "type": "read-only-storage" }, "elementType": "$xScalar" },
554
+ {
555
+ "name": "x_scale",
556
+ "arg": "x_scale",
557
+ "semantic": "x_scale",
558
+ "buffer": { "type": "read-only-storage" },
559
+ "elementType": "$scaleScalar"
560
+ },
561
+ { "name": "y", "arg": "y", "semantic": "y", "buffer": { "type": "storage" }, "elementType": "$yScalar" }
562
+ ],
563
+ "linearVec4PerTensorWithZero": [
564
+ { "name": "x", "arg": "x", "semantic": "x", "buffer": { "type": "read-only-storage" }, "elementType": "$xVec4" },
565
+ {
566
+ "name": "x_scale",
567
+ "arg": "x_scale",
568
+ "semantic": "x_scale",
569
+ "buffer": { "type": "read-only-storage" },
570
+ "elementType": "$scaleScalar"
571
+ },
572
+ {
573
+ "name": "x_zero_point",
574
+ "arg": "x_zero_point",
575
+ "semantic": "x_zero_point",
576
+ "buffer": { "type": "read-only-storage" },
577
+ "elementType": "$xScalar"
578
+ },
579
+ { "name": "y", "arg": "y", "semantic": "y", "buffer": { "type": "storage" }, "elementType": "$yVec4" },
580
+ {
581
+ "name": "params",
582
+ "semantic": "kernel.params",
583
+ "buffer": { "type": "uniform" },
584
+ "struct": { "name": "Params", "fields": [{ "name": "count4", "type": "u32", "value": "elementCount4" }] }
585
+ }
586
+ ],
587
+ "linearVec4PerTensorNoZero": [
588
+ { "name": "x", "arg": "x", "semantic": "x", "buffer": { "type": "read-only-storage" }, "elementType": "$xVec4" },
589
+ {
590
+ "name": "x_scale",
591
+ "arg": "x_scale",
592
+ "semantic": "x_scale",
593
+ "buffer": { "type": "read-only-storage" },
594
+ "elementType": "$scaleScalar"
595
+ },
596
+ { "name": "y", "arg": "y", "semantic": "y", "buffer": { "type": "storage" }, "elementType": "$yVec4" },
597
+ {
598
+ "name": "params",
599
+ "semantic": "kernel.params",
600
+ "buffer": { "type": "uniform" },
601
+ "struct": { "name": "Params", "fields": [{ "name": "count4", "type": "u32", "value": "elementCount4" }] }
602
+ }
603
+ ],
604
+ "linearScalarPerTensorWithZero": [
605
+ { "name": "x", "arg": "x", "semantic": "x", "buffer": { "type": "read-only-storage" }, "elementType": "$xScalar" },
606
+ {
607
+ "name": "x_scale",
608
+ "arg": "x_scale",
609
+ "semantic": "x_scale",
610
+ "buffer": { "type": "read-only-storage" },
611
+ "elementType": "$scaleScalar"
612
+ },
613
+ {
614
+ "name": "x_zero_point",
615
+ "arg": "x_zero_point",
616
+ "semantic": "x_zero_point",
617
+ "buffer": { "type": "read-only-storage" },
618
+ "elementType": "$xScalar"
619
+ },
620
+ { "name": "y", "arg": "y", "semantic": "y", "buffer": { "type": "storage" }, "elementType": "$yScalar" },
621
+ {
622
+ "name": "params",
623
+ "semantic": "kernel.params",
624
+ "buffer": { "type": "uniform" },
625
+ "struct": { "name": "Params", "fields": [{ "name": "count", "type": "u32", "value": "elementCount" }] }
626
+ }
627
+ ],
628
+ "linearScalarPerTensorNoZero": [
629
+ { "name": "x", "arg": "x", "semantic": "x", "buffer": { "type": "read-only-storage" }, "elementType": "$xScalar" },
630
+ {
631
+ "name": "x_scale",
632
+ "arg": "x_scale",
633
+ "semantic": "x_scale",
634
+ "buffer": { "type": "read-only-storage" },
635
+ "elementType": "$scaleScalar"
636
+ },
637
+ { "name": "y", "arg": "y", "semantic": "y", "buffer": { "type": "storage" }, "elementType": "$yScalar" },
638
+ {
639
+ "name": "params",
640
+ "semantic": "kernel.params",
641
+ "buffer": { "type": "uniform" },
642
+ "struct": { "name": "Params", "fields": [{ "name": "count", "type": "u32", "value": "elementCount" }] }
643
+ }
644
+ ]
645
+ }
646
+ }
build/webgpu/metadata.json ADDED
@@ -0,0 +1,20 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "name": "ai.onnx.DequantizeLinear",
3
+ "id": "_ai_onnx_dequantizelinear_webgpu_f3ea48b",
4
+ "version": 1,
5
+ "license": "Apache-2.0",
6
+ "backend": { "type": "webgpu" },
7
+ "digest": {
8
+ "algorithm": "sha256",
9
+ "files": {
10
+ "bench.json": "2JjVTjr3ucOvyKXNWcKsP7v8YvivzR9BlRaf88Fb3ds=",
11
+ "manifest.json": "/hcoq4zBcnyUUUn2WGN+SXgx3E9rWCsw5mA5zEvo46k=",
12
+ "quant-linear-blocked-axis.wgsl.jinja": "haL3flgL3mhBuafYHdqoMWbtvP2znUTVbb/qxakgrxU=",
13
+ "quant-linear-scalar.wgsl.jinja": "9EKOoq47CEJJ0O/7QirueruVfkmZuOGcCKmov/VKacI=",
14
+ "quant-linear-vec4.wgsl.jinja": "yQkKYuSSLaGUTifXt1xBr54tkIjYD68ouw9UOLbPNW0=",
15
+ "test.json": "qEtiZ2PxB1uoK/fbGOrmRyt4bmOkki0eVGg92OA+6jI="
16
+ }
17
+ },
18
+ "provenance": { "kernel": { "sha": "2e7068faf55e7f43df740015f6d1ee49391a41c5", "dirty": false } },
19
+ "webgpu": { "manifestSpec": "1.0", "specialized": true, "opPath": "ops/ai.onnx.DequantizeLinear" }
20
+ }
build/webgpu/quant-linear-blocked-axis.wgsl.jinja ADDED
@@ -0,0 +1,43 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // Blocked-axis scale indexing for {{ source.op | default("quantize") }}.
2
+ {% if usesF16 %}
3
+ enable f16;
4
+ {% endif %}
5
+ {{ env.wgsl.resourceDeclarations }}
6
+
7
+ fn read_x(index: u32) -> i32 {
8
+ {% if xUnsigned %}
9
+ return i32(x[index]);
10
+ {% else %}
11
+ return x[index];
12
+ {% endif %}
13
+ }
14
+
15
+ fn read_zero({% if hasZero %}index: u32{% endif %}) -> i32 {
16
+ {% if hasZero %}
17
+ {% if xUnsigned %}
18
+ return i32(x_zero_point[index]);
19
+ {% else %}
20
+ return x_zero_point[index];
21
+ {% endif %}
22
+ {% else %}
23
+ return 0;
24
+ {% endif %}
25
+ }
26
+
27
+ fn scale_index(index: u32) -> u32 {
28
+ let inner_index = index % params.inner;
29
+ let axis_index = (index / params.inner) % params.axisDim;
30
+ let outer_index = index / (params.axisDim * params.inner);
31
+ return (outer_index * params.scaleAxisDim + axis_index / params.blockSize) * params.inner + inner_index;
32
+ }
33
+
34
+ @compute @workgroup_size({{ tunables.WORKGROUP_SIZE }})
35
+ fn main(@builtin(global_invocation_id) gid: vec3<u32>, @builtin(num_workgroups) nwg: vec3<u32>) {
36
+ // The flat dispatch is folded across x/y at the device's per-axis workgroup
37
+ // limit; gid.y carries the high portion of the element index.
38
+ let index = gid.x + gid.y * nwg.x * {{ tunables.WORKGROUP_SIZE }}u;
39
+ if (index >= params.count) { return; }
40
+ let scaleIndex = scale_index(index);
41
+ let result = f32(read_x(index) - read_zero({% if hasZero %}scaleIndex{% endif %})) * f32(x_scale[scaleIndex]);
42
+ y[index] = {{ yScalar }}(result);
43
+ }
build/webgpu/quant-linear-scalar.wgsl.jinja ADDED
@@ -0,0 +1,63 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // The x4 route handles widened int8/uint8 storage with scalar scale parameters;
2
+ // the linear route supports both per-tensor and per-axis quantization.
3
+ {% if usesF16 %}
4
+ enable f16;
5
+ {% endif %}
6
+ {{ env.wgsl.resourceDeclarations }}
7
+
8
+ fn read_x(index: u32) -> i32 {
9
+ {% if xUnsigned %}
10
+ return i32(x[index]);
11
+ {% else %}
12
+ return x[index];
13
+ {% endif %}
14
+ }
15
+
16
+ fn read_zero({% if hasZero %}index: u32{% endif %}) -> i32 {
17
+ {% if hasZero %}
18
+ {% if xUnsigned %}
19
+ return i32(x_zero_point[index]);
20
+ {% else %}
21
+ return x_zero_point[index];
22
+ {% endif %}
23
+ {% else %}
24
+ return 0;
25
+ {% endif %}
26
+ }
27
+
28
+ fn transform_one(index: u32, scale: f32, zero_point: i32) {
29
+ let result = f32(read_x(index) - zero_point) * scale;
30
+ y[index] = {{ yScalar }}(result);
31
+ }
32
+
33
+ @compute @workgroup_size({{ tunables.WORKGROUP_SIZE }})
34
+ fn main(@builtin(global_invocation_id) gid: vec3<u32>, @builtin(num_workgroups) nwg: vec3<u32>) {
35
+ // Fold oversized flat dispatches into two dimensions; gid.y carries work
36
+ // beyond the device-capped x dimension.
37
+ let invocation = gid.x + gid.y * nwg.x * {{ tunables.WORKGROUP_SIZE }}u;
38
+ {% if source.x4 %}
39
+ if (invocation != 0u) {
40
+ return;
41
+ }
42
+ let base = params.count - params.count % 4u;
43
+ if (base >= params.count) {
44
+ return;
45
+ }
46
+ let scale = f32(x_scale[0]);
47
+ let zero_point = read_zero({% if hasZero %}0u{% endif %});
48
+ transform_one(base, scale, zero_point);
49
+ if (base + 1u < params.count) { transform_one(base + 1u, scale, zero_point); }
50
+ if (base + 2u < params.count) { transform_one(base + 2u, scale, zero_point); }
51
+ if (base + 3u < params.count) { transform_one(base + 3u, scale, zero_point); }
52
+ {% else %}
53
+ if (invocation >= params.count) {
54
+ return;
55
+ }
56
+ var scale_index = 0u;
57
+ {% if source.perAxis %}
58
+ scale_index = (invocation / params.inner) % params.scaleSize;
59
+ {% endif %}
60
+ let scale = f32(x_scale[scale_index]);
61
+ transform_one(invocation, scale, read_zero({% if hasZero %}scale_index{% endif %}));
62
+ {% endif %}
63
+ }
build/webgpu/quant-linear-vec4.wgsl.jinja ADDED
@@ -0,0 +1,107 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // int8/uint8 tensors are stored widened (one u32/i32 per element), so the vec4
2
+ // binding gives 128-bit loads/stores of four elements. Per-component arithmetic
3
+ // remains identical to the scalar quantize/dequantize paths.
4
+ {% if usesF16 %}
5
+ enable f16;
6
+ {% endif %}
7
+ {{ env.wgsl.resourceDeclarations }}
8
+ {% if source.vectorParams is defined and source.vectorParams %}
9
+ fn read_zero4({% if hasZero %}index: u32{% endif %}) -> vec4<i32> {
10
+ {% if hasZero %}
11
+ {% if xUnsigned %}
12
+ return vec4<i32>(x_zero_point[index]);
13
+ {% else %}
14
+ return x_zero_point[index];
15
+ {% endif %}
16
+ {% else %}
17
+ return vec4<i32>(0);
18
+ {% endif %}
19
+ }
20
+ {% else %}
21
+ fn read_zero({% if hasZero %}index: u32{% endif %}) -> i32 {
22
+ {% if hasZero %}
23
+ {% if xUnsigned %}
24
+ return i32(x_zero_point[index]);
25
+ {% else %}
26
+ return x_zero_point[index];
27
+ {% endif %}
28
+ {% else %}
29
+ return 0;
30
+ {% endif %}
31
+ }
32
+ {% endif %}
33
+
34
+ @compute @workgroup_size({{ tunables.WORKGROUP_SIZE }})
35
+ fn main(@builtin(global_invocation_id) gid: vec3<u32>, @builtin(num_workgroups) nwg: vec3<u32>) {
36
+ // The flat dispatch is folded across x/y at the device's per-axis workgroup
37
+ // limit; gid.y carries the high portion of the vector index.
38
+ let i = gid.x + gid.y * nwg.x * {{ tunables.WORKGROUP_SIZE }}u;
39
+ if (i >= params.count4) {
40
+ return;
41
+ }
42
+ {% if source.vectorParams is defined and source.vectorParams %}
43
+ let scale_index = i % (params.scaleSize / 4u);
44
+ {% elif source.crossingParams is defined and source.crossingParams %}
45
+ let base_index = i * 4u;
46
+ let scale_index0 = (base_index / params.inner) % params.scaleSize;
47
+ let scale_index1 = ((base_index + 1u) / params.inner) % params.scaleSize;
48
+ let scale_index2 = ((base_index + 2u) / params.inner) % params.scaleSize;
49
+ let scale_index3 = ((base_index + 3u) / params.inner) % params.scaleSize;
50
+ {% elif source.perAxis %}
51
+ // inner % 4 == 0, so all 4 lanes share one scale index.
52
+ let scale_index = ((i * 4u) / params.inner) % params.scaleSize;
53
+ {% else %}
54
+ let scale_index = 0u;
55
+ {% endif %}
56
+ let xv = x[i];
57
+ {% if source.vectorParams is defined and source.vectorParams %}
58
+ let zp4 = read_zero4({% if hasZero %}scale_index{% endif %});
59
+ {% elif source.crossingParams is defined and source.crossingParams %}
60
+ let zp0 = read_zero(scale_index0);
61
+ let zp1 = read_zero(scale_index1);
62
+ let zp2 = read_zero(scale_index2);
63
+ let zp3 = read_zero(scale_index3);
64
+ {% else %}
65
+ let zp = read_zero({% if hasZero %}scale_index{% endif %});
66
+ {% endif %}
67
+ {% if source.vectorParams is defined and source.vectorParams %}
68
+ let scale = vec4<f32>(x_scale[scale_index]);
69
+ {% if xUnsigned %}
70
+ let r0 = f32(i32(xv.x) - zp4.x) * scale.x;
71
+ let r1 = f32(i32(xv.y) - zp4.y) * scale.y;
72
+ let r2 = f32(i32(xv.z) - zp4.z) * scale.z;
73
+ let r3 = f32(i32(xv.w) - zp4.w) * scale.w;
74
+ {% else %}
75
+ let r0 = f32(xv.x - zp4.x) * scale.x;
76
+ let r1 = f32(xv.y - zp4.y) * scale.y;
77
+ let r2 = f32(xv.z - zp4.z) * scale.z;
78
+ let r3 = f32(xv.w - zp4.w) * scale.w;
79
+ {% endif %}
80
+ {% elif source.crossingParams is defined and source.crossingParams %}
81
+ {% if xUnsigned %}
82
+ let r0 = f32(i32(xv.x) - zp0) * f32(x_scale[scale_index0]);
83
+ let r1 = f32(i32(xv.y) - zp1) * f32(x_scale[scale_index1]);
84
+ let r2 = f32(i32(xv.z) - zp2) * f32(x_scale[scale_index2]);
85
+ let r3 = f32(i32(xv.w) - zp3) * f32(x_scale[scale_index3]);
86
+ {% else %}
87
+ let r0 = f32(xv.x - zp0) * f32(x_scale[scale_index0]);
88
+ let r1 = f32(xv.y - zp1) * f32(x_scale[scale_index1]);
89
+ let r2 = f32(xv.z - zp2) * f32(x_scale[scale_index2]);
90
+ let r3 = f32(xv.w - zp3) * f32(x_scale[scale_index3]);
91
+ {% endif %}
92
+ {% else %}
93
+ let scale = f32(x_scale[scale_index]);
94
+ {% if xUnsigned %}
95
+ let r0 = f32(i32(xv.x) - zp) * scale;
96
+ let r1 = f32(i32(xv.y) - zp) * scale;
97
+ let r2 = f32(i32(xv.z) - zp) * scale;
98
+ let r3 = f32(i32(xv.w) - zp) * scale;
99
+ {% else %}
100
+ let r0 = f32(xv.x - zp) * scale;
101
+ let r1 = f32(xv.y - zp) * scale;
102
+ let r2 = f32(xv.z - zp) * scale;
103
+ let r3 = f32(xv.w - zp) * scale;
104
+ {% endif %}
105
+ {% endif %}
106
+ y[i] = vec4<{{ yScalar }}>({{ yScalar }}(r0), {{ yScalar }}(r1), {{ yScalar }}(r2), {{ yScalar }}(r3));
107
+ }
build/webgpu/test.json ADDED
@@ -0,0 +1,1020 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "op": "ai.onnx.DequantizeLinear",
3
+ "fixtureArrays": {
4
+ "uint8_axis1_rank4_onnx_backend_input_x": [3, 89, 34, 200, 74, 59, 5, 24, 24, 87, 32, 13, 245, 99, 4, 142, 121, 102],
5
+ "blocked_no_zero_point_rank4_axis1_symmetric_input_x": [-8, -4, -2, -1, 0, 1, 2, 4, 8, 16, 32, 48, -16, -32, -48, -64]
6
+ },
7
+ "cases": [
8
+ {
9
+ "name": "int16_per_axis_vec4_boundaries",
10
+ "attrs": { "axis": 1 },
11
+ "inputs": {
12
+ "x": {
13
+ "dtype": "int16",
14
+ "shape": [2, 4],
15
+ "data": { "kind": "values", "values": [-32768, -1, 0, 32767, 32767, 0, -1, -32768] }
16
+ },
17
+ "x_scale": { "dtype": "float32", "shape": [4], "data": { "kind": "values", "values": [0.5, 1.0, 2.0, 0.25] } },
18
+ "x_zero_point": {
19
+ "dtype": "int16",
20
+ "shape": [4],
21
+ "data": { "kind": "values", "values": [-32768, -2, 1, 32767] }
22
+ }
23
+ },
24
+ "outputs": {
25
+ "y": {
26
+ "dtype": "float32",
27
+ "shape": [2, 4],
28
+ "tolerance": 0.000001,
29
+ "data": { "kind": "values", "values": [0.0, 1.0, -2.0, 0.0, 32767.5, 2.0, -4.0, -16383.75] }
30
+ }
31
+ }
32
+ },
33
+ {
34
+ "name": "dispatch_cliff_scalar_scale_67M",
35
+ "attrs": { "axis": 0 },
36
+ "inputs": {
37
+ "x": { "dtype": "uint8", "shape": [67108864], "data": { "kind": "cycle", "values": [0, 1, 2, 3, 4, 5, 6, 7] } },
38
+ "x_scale": { "dtype": "float32", "shape": [1], "data": { "kind": "constant", "value": 0.5 } }
39
+ },
40
+ "outputs": { "y": { "dtype": "float32", "shape": [67108864], "tolerance": 0.0001 } }
41
+ },
42
+ {
43
+ "name": "uint8_scalar_zero",
44
+ "inputs": {
45
+ "x": { "dtype": "uint8", "shape": [2, 3], "data": { "kind": "values", "values": [0, 127, 128, 129, 255, 4] } },
46
+ "x_scale": { "dtype": "float32", "shape": [1], "data": { "kind": "values", "values": [0.5] } },
47
+ "x_zero_point": { "dtype": "uint8", "shape": [1], "data": { "kind": "values", "values": [128] } }
48
+ },
49
+ "outputs": { "y": { "dtype": "float32", "shape": [2, 3] } }
50
+ },
51
+ {
52
+ "name": "uint8_subnormal_scale_vec4_gpu_gap",
53
+ "skipGpu": {
54
+ "category": "permanent",
55
+ "reason": "Portable WGSL floating-point semantics do not guarantee preservation of the subnormal values required by this fixture. Backend evidence: Metal flushes denormal results of floating-point multiplication (e.g. 2 * 1e-40 -> 0); ORT computes (x - zp) * subnormal_scale on CPU with denormal support, so subnormal x_scale cases remain CPU-reference-only."
56
+ },
57
+ "provenance": {
58
+ "source": "onnxruntime/test/providers/cpu/tensor/quantize_linear_test.cc",
59
+ "test": "DequantizeLinearOpTest.Uint8",
60
+ "notes": "Valid positive subnormal scale: dequantized tiny values should not be flushed to zero."
61
+ },
62
+ "inputs": {
63
+ "x": { "dtype": "uint8", "shape": [4], "data": { "kind": "values", "values": [0, 1, 2, 3] } },
64
+ "x_scale": { "dtype": "float32", "shape": [1], "data": { "kind": "values", "values": [1e-40] } }
65
+ },
66
+ "outputs": { "y": { "dtype": "float32", "shape": [4], "tolerance": 0 } }
67
+ },
68
+ {
69
+ "name": "uint8_subnormal_scale_nonzero_zero_point_gpu_gap",
70
+ "skipGpu": {
71
+ "category": "permanent",
72
+ "reason": "Portable WGSL floating-point semantics do not guarantee preservation of the subnormal values required by this fixture. Backend evidence: Metal flushes denormal results of floating-point multiplication (e.g. 2 * 1e-40 -> 0); ORT computes (x - zp) * subnormal_scale on CPU with denormal support, so subnormal x_scale cases remain CPU-reference-only."
73
+ },
74
+ "provenance": {
75
+ "source": "onnxruntime/test/providers/cpu/tensor/quantize_linear_test.cc",
76
+ "test": "DequantizeLinearOpTest.Uint8",
77
+ "notes": "Subnormal scale with a nonzero zero point should preserve tiny signed dequantized offsets around zero."
78
+ },
79
+ "inputs": {
80
+ "x": { "dtype": "uint8", "shape": [4], "data": { "kind": "values", "values": [126, 127, 128, 129] } },
81
+ "x_scale": { "dtype": "float32", "shape": [1], "data": { "kind": "values", "values": [1e-40] } },
82
+ "x_zero_point": { "dtype": "uint8", "shape": [1], "data": { "kind": "values", "values": [128] } }
83
+ },
84
+ "outputs": { "y": { "dtype": "float32", "shape": [4], "tolerance": 0 } }
85
+ },
86
+ {
87
+ "name": "int8_subnormal_scale_preserves_signed_steps_gpu_gap",
88
+ "skipGpu": {
89
+ "category": "permanent",
90
+ "reason": "Portable WGSL floating-point semantics do not guarantee preservation of the subnormal values required by this fixture. Backend evidence: Metal flushes denormal results of floating-point multiplication (e.g. 2 * 1e-40 -> 0); ORT computes (x - zp) * subnormal_scale on CPU with denormal support, so subnormal x_scale cases remain CPU-reference-only."
91
+ },
92
+ "provenance": {
93
+ "source": "onnxruntime/test/providers/cpu/tensor/quantize_linear_test.cc",
94
+ "test": "DequantizeLinearOpTest.Int8",
95
+ "notes": "Signed-output companion: subnormal scale should preserve tiny signed dequantized offsets around zero."
96
+ },
97
+ "inputs": {
98
+ "x": { "dtype": "int8", "shape": [5], "data": { "kind": "values", "values": [-2, -1, 0, 1, 2] } },
99
+ "x_scale": { "dtype": "float32", "shape": [1], "data": { "kind": "values", "values": [1e-40] } },
100
+ "x_zero_point": { "dtype": "int8", "shape": [1], "data": { "kind": "values", "values": [0] } }
101
+ },
102
+ "outputs": { "y": { "dtype": "float32", "shape": [5], "tolerance": 0 } }
103
+ },
104
+ {
105
+ "name": "int8_subnormal_scale_vec4_preserves_signed_steps_gpu_gap",
106
+ "skipGpu": {
107
+ "category": "permanent",
108
+ "reason": "Portable WGSL floating-point semantics do not guarantee preservation of the subnormal values required by this fixture. Backend evidence: Metal flushes denormal results of floating-point multiplication (e.g. 2 * 1e-40 -> 0); ORT computes (x - zp) * subnormal_scale on CPU with denormal support, so subnormal x_scale cases remain CPU-reference-only."
109
+ },
110
+ "provenance": {
111
+ "source": "onnxruntime/test/providers/cpu/tensor/quantize_linear_test.cc",
112
+ "test": "DequantizeLinearOpTest.Int8",
113
+ "notes": "Vec4 signed-output companion for subnormal DequantizeLinear scale handling."
114
+ },
115
+ "inputs": {
116
+ "x": { "dtype": "int8", "shape": [4], "data": { "kind": "values", "values": [-1, 0, 1, 2] } },
117
+ "x_scale": { "dtype": "float32", "shape": [1], "data": { "kind": "values", "values": [1e-40] } },
118
+ "x_zero_point": { "dtype": "int8", "shape": [1], "data": { "kind": "values", "values": [0] } }
119
+ },
120
+ "outputs": { "y": { "dtype": "float32", "shape": [4], "tolerance": 0 } }
121
+ },
122
+ {
123
+ "name": "uint8_axis1_per_channel_subnormal_scale_gpu_gap",
124
+ "skipGpu": {
125
+ "category": "permanent",
126
+ "reason": "Portable WGSL floating-point semantics do not guarantee preservation of the subnormal values required by this fixture. Backend evidence: Metal flushes denormal results of floating-point multiplication (e.g. 2 * 1e-40 -> 0); ORT computes (x - zp) * subnormal_scale on CPU with denormal support, so subnormal x_scale cases remain CPU-reference-only."
127
+ },
128
+ "provenance": {
129
+ "source": "onnxruntime/test/providers/cpu/tensor/quantize_linear_test.cc",
130
+ "test": "DequantizeLinearOpTest.Per_Channel_Axis_Default",
131
+ "notes": "Per-axis companion for subnormal DequantizeLinear scale handling: each channel uses a valid subnormal scale and nonzero zero point."
132
+ },
133
+ "attrs": { "axis": 1 },
134
+ "inputs": {
135
+ "x": {
136
+ "dtype": "uint8",
137
+ "shape": [2, 4],
138
+ "data": { "kind": "values", "values": [10, 21, 29, 42, 12, 18, 30, 41] }
139
+ },
140
+ "x_scale": {
141
+ "dtype": "float32",
142
+ "shape": [4],
143
+ "data": { "kind": "values", "values": [1e-40, 1e-40, 1e-40, 1e-40] }
144
+ },
145
+ "x_zero_point": { "dtype": "uint8", "shape": [4], "data": { "kind": "values", "values": [10, 20, 30, 40] } }
146
+ },
147
+ "outputs": {
148
+ "y": {
149
+ "dtype": "float32",
150
+ "shape": [2, 4],
151
+ "tolerance": 0,
152
+ "data": { "kind": "values", "values": [0.0, 1e-40, -1e-40, 2e-40, 2e-40, -2e-40, 0.0, 1e-40] }
153
+ }
154
+ }
155
+ },
156
+ {
157
+ "name": "uint8_axis0_per_channel_subnormal_scale_vec4_gpu_gap",
158
+ "skipGpu": {
159
+ "category": "permanent",
160
+ "reason": "Portable WGSL floating-point semantics do not guarantee preservation of the subnormal values required by this fixture. Backend evidence: Metal flushes denormal results of floating-point multiplication (e.g. 2 * 1e-40 -> 0); ORT computes (x - zp) * subnormal_scale on CPU with denormal support, so subnormal x_scale cases remain CPU-reference-only."
161
+ },
162
+ "provenance": {
163
+ "source": "onnxruntime/test/providers/cpu/tensor/quantize_linear_test.cc",
164
+ "test": "DequantizeLinearOpTest.Per_Channel_Axis_0",
165
+ "notes": "Vec4 per-axis companion for subnormal DequantizeLinear scale handling: axis=0 has inner size 4, so the vectorized channel path must preserve tiny one-LSB steps."
166
+ },
167
+ "attrs": { "axis": 0 },
168
+ "inputs": {
169
+ "x": {
170
+ "dtype": "uint8",
171
+ "shape": [2, 4],
172
+ "data": { "kind": "values", "values": [10, 11, 12, 13, 22, 18, 20, 21] }
173
+ },
174
+ "x_scale": { "dtype": "float32", "shape": [2], "data": { "kind": "values", "values": [1e-40, 1e-40] } },
175
+ "x_zero_point": { "dtype": "uint8", "shape": [2], "data": { "kind": "values", "values": [10, 20] } }
176
+ },
177
+ "outputs": {
178
+ "y": {
179
+ "dtype": "float32",
180
+ "shape": [2, 4],
181
+ "tolerance": 0,
182
+ "data": { "kind": "values", "values": [0.0, 1e-40, 2e-40, 3e-40, 2e-40, -2e-40, 0.0, 1e-40] }
183
+ }
184
+ }
185
+ },
186
+ {
187
+ "name": "uint8_axis1_per_channel_subnormal_scale_no_zero_point_gpu_gap",
188
+ "skipGpu": {
189
+ "category": "permanent",
190
+ "reason": "Portable WGSL floating-point semantics do not guarantee preservation of the subnormal values required by this fixture. Backend evidence: Metal flushes denormal results of floating-point multiplication (e.g. 2 * 1e-40 -> 0); ORT computes (x - zp) * subnormal_scale on CPU with denormal support, so subnormal x_scale cases remain CPU-reference-only."
191
+ },
192
+ "provenance": {
193
+ "source": "onnxruntime/test/providers/cpu/tensor/quantize_linear_test.cc",
194
+ "test": "DequantizeLinearOpTest.Without_Zero_Point",
195
+ "notes": "Per-axis extension of omitted-zero-point coverage: default uint8 zero point is zero, but each channel still uses a valid subnormal scale."
196
+ },
197
+ "attrs": { "axis": 1 },
198
+ "inputs": {
199
+ "x": { "dtype": "uint8", "shape": [2, 4], "data": { "kind": "values", "values": [0, 1, 2, 3, 2, 0, 1, 0] } },
200
+ "x_scale": {
201
+ "dtype": "float32",
202
+ "shape": [4],
203
+ "data": { "kind": "values", "values": [1e-40, 1e-40, 1e-40, 1e-40] }
204
+ }
205
+ },
206
+ "outputs": {
207
+ "y": {
208
+ "dtype": "float32",
209
+ "shape": [2, 4],
210
+ "tolerance": 0,
211
+ "data": { "kind": "values", "values": [0.0, 1e-40, 2e-40, 3e-40, 2e-40, 0.0, 1e-40, 0.0] }
212
+ }
213
+ }
214
+ },
215
+ {
216
+ "name": "uint8_axis0_per_channel_subnormal_scale_no_zero_point_vec4_gpu_gap",
217
+ "skipGpu": {
218
+ "category": "permanent",
219
+ "reason": "Portable WGSL floating-point semantics do not guarantee preservation of the subnormal values required by this fixture. Backend evidence: Metal flushes denormal results of floating-point multiplication (e.g. 2 * 1e-40 -> 0); ORT computes (x - zp) * subnormal_scale on CPU with denormal support, so subnormal x_scale cases remain CPU-reference-only."
220
+ },
221
+ "provenance": {
222
+ "source": "onnxruntime/test/providers/cpu/tensor/quantize_linear_test.cc",
223
+ "test": "DequantizeLinearOpTest.Without_Zero_Point",
224
+ "notes": "Vec4 per-axis extension of omitted-zero-point coverage with valid subnormal scales."
225
+ },
226
+ "attrs": { "axis": 0 },
227
+ "inputs": {
228
+ "x": { "dtype": "uint8", "shape": [2, 4], "data": { "kind": "values", "values": [0, 1, 2, 3, 2, 0, 0, 1] } },
229
+ "x_scale": { "dtype": "float32", "shape": [2], "data": { "kind": "values", "values": [1e-40, 1e-40] } }
230
+ },
231
+ "outputs": {
232
+ "y": {
233
+ "dtype": "float32",
234
+ "shape": [2, 4],
235
+ "tolerance": 0,
236
+ "data": { "kind": "values", "values": [0.0, 1e-40, 2e-40, 3e-40, 2e-40, 0.0, 0.0, 1e-40] }
237
+ }
238
+ }
239
+ },
240
+ {
241
+ "name": "int32_subnormal_scale_no_zero_point_gpu_gap",
242
+ "skipGpu": {
243
+ "category": "permanent",
244
+ "reason": "Portable WGSL floating-point semantics do not guarantee preservation of the subnormal values required by this fixture. Backend evidence: Metal flushes denormal results of floating-point multiplication (e.g. 2 * 1e-40 -> 0); ORT computes (x - zp) * subnormal_scale on CPU with denormal support, so subnormal x_scale cases remain CPU-reference-only."
245
+ },
246
+ "provenance": {
247
+ "source": "onnxruntime/test/providers/cpu/tensor/quantize_linear_test.cc",
248
+ "test": "DequantizeLinearOpTest.Int32",
249
+ "notes": "Valid int32 dequantization with a subnormal scale and omitted zero point; outputs should remain finite subnormal values."
250
+ },
251
+ "inputs": {
252
+ "x": { "dtype": "int32", "shape": [4], "data": { "kind": "values", "values": [-2, -1, 0, 1] } },
253
+ "x_scale": { "dtype": "float32", "shape": [1], "data": { "kind": "values", "values": [1e-40] } }
254
+ },
255
+ "outputs": { "y": { "dtype": "float32", "shape": [4], "tolerance": 0 } }
256
+ },
257
+ {
258
+ "name": "int8_axis1_f16",
259
+ "attrs": { "axis": 1 },
260
+ "inputs": {
261
+ "x": { "dtype": "int8", "shape": [2, 3], "data": { "kind": "values", "values": [-128, -1, 0, 1, 2, 127] } },
262
+ "x_scale": { "dtype": "float16", "shape": [3], "data": { "kind": "values", "values": [0.25, 0.5, 2.0] } },
263
+ "x_zero_point": { "dtype": "int8", "shape": [3], "data": { "kind": "values", "values": [0, -1, 1] } }
264
+ },
265
+ "outputs": { "y": { "dtype": "float16", "shape": [2, 3] } },
266
+ "tolerance": 0.002
267
+ },
268
+ {
269
+ "name": "uint8_no_zero_negative_axis",
270
+ "attrs": { "axis": -1 },
271
+ "inputs": {
272
+ "x": { "dtype": "uint8", "shape": [2, 2], "data": { "kind": "values", "values": [10, 20, 30, 40] } },
273
+ "x_scale": { "dtype": "float32", "shape": [2], "data": { "kind": "values", "values": [0.1, 0.25] } }
274
+ },
275
+ "outputs": { "y": { "dtype": "float32", "shape": [2, 2] } }
276
+ },
277
+ {
278
+ "name": "ort_int16_negative_zero_point",
279
+ "provenance": {
280
+ "source": "onnxruntime/test/providers/cpu/tensor/quantize_linear_test.cc",
281
+ "test": "DequantizeLinearOpTest.Int16"
282
+ },
283
+ "attrs": { "axis": 0 },
284
+ "inputs": {
285
+ "x": { "dtype": "int16", "shape": [4], "data": { "kind": "values", "values": [-300, -30, -1025, 1270] } },
286
+ "x_scale": { "dtype": "float32", "shape": [], "data": { "kind": "values", "values": [2.0] } },
287
+ "x_zero_point": { "dtype": "int16", "shape": [], "data": { "kind": "values", "values": [-1024] } }
288
+ },
289
+ "outputs": { "y": { "dtype": "float32", "shape": [4], "tolerance": 0.000001 } }
290
+ },
291
+ {
292
+ "name": "uint8_scalar_onnx_backend",
293
+ "provenance": {
294
+ "source": "onnxruntime/test/providers/cpu/tensor/quantize_linear_test.cc",
295
+ "test": "DequantizeLinearOpTest.Uint8"
296
+ },
297
+ "attrs": { "axis": 0 },
298
+ "inputs": {
299
+ "x": { "dtype": "uint8", "shape": [4], "data": { "kind": "values", "values": [0, 3, 128, 255] } },
300
+ "x_scale": { "dtype": "float32", "shape": [1], "data": { "kind": "values", "values": [2.0] } },
301
+ "x_zero_point": { "dtype": "uint8", "shape": [1], "data": { "kind": "values", "values": [128] } }
302
+ },
303
+ "outputs": { "y": { "dtype": "float32", "shape": [4], "tolerance": 0.000001 } }
304
+ },
305
+ {
306
+ "name": "ort_uint8_rank0_scale_zero_point",
307
+ "provenance": {
308
+ "source": "onnxruntime/test/providers/cpu/tensor/quantize_linear_test.cc",
309
+ "test": "DequantizeLinearOpTest.Uint8"
310
+ },
311
+ "attrs": { "axis": 0 },
312
+ "inputs": {
313
+ "x": { "dtype": "uint8", "shape": [4], "data": { "kind": "values", "values": [0, 3, 128, 255] } },
314
+ "x_scale": { "dtype": "float32", "shape": [], "data": { "kind": "values", "values": [2.0] } },
315
+ "x_zero_point": { "dtype": "uint8", "shape": [], "data": { "kind": "values", "values": [128] } }
316
+ },
317
+ "outputs": { "y": { "dtype": "float32", "shape": [4], "tolerance": 0.000001 } }
318
+ },
319
+ {
320
+ "name": "uint8_axis1_rank4_onnx_backend",
321
+ "attrs": { "axis": 1 },
322
+ "inputs": {
323
+ "x": {
324
+ "dtype": "uint8",
325
+ "shape": [1, 3, 3, 2],
326
+ "data": { "kind": "values", "values": { "$ref": "#/fixtureArrays/uint8_axis1_rank4_onnx_backend_input_x" } }
327
+ },
328
+ "x_scale": { "dtype": "float32", "shape": [3], "data": { "kind": "values", "values": [2.0, 4.0, 5.0] } },
329
+ "x_zero_point": { "dtype": "uint8", "shape": [3], "data": { "kind": "values", "values": [84, 24, 196] } }
330
+ },
331
+ "outputs": { "y": { "dtype": "float32", "shape": [1, 3, 3, 2], "tolerance": 0.000001 } }
332
+ },
333
+ {
334
+ "name": "int8_scalar_zero_point_ort",
335
+ "provenance": {
336
+ "source": "onnxruntime/test/providers/cpu/tensor/quantize_linear_test.cc",
337
+ "test": "DequantizeLinearOpTest.Int8"
338
+ },
339
+ "attrs": { "axis": 0 },
340
+ "inputs": {
341
+ "x": { "dtype": "int8", "shape": [4], "data": { "kind": "values", "values": [-30, -3, 100, 127] } },
342
+ "x_scale": { "dtype": "float32", "shape": [1], "data": { "kind": "values", "values": [2.0] } },
343
+ "x_zero_point": { "dtype": "int8", "shape": [1], "data": { "kind": "values", "values": [-10] } }
344
+ },
345
+ "outputs": { "y": { "dtype": "float32", "shape": [4], "tolerance": 0.000001 } }
346
+ },
347
+ {
348
+ "name": "ort_int8_rank0_scale_zero_point",
349
+ "provenance": {
350
+ "source": "onnxruntime/test/providers/cpu/tensor/quantize_linear_test.cc",
351
+ "test": "DequantizeLinearOpTest.Int8"
352
+ },
353
+ "attrs": { "axis": 0 },
354
+ "inputs": {
355
+ "x": { "dtype": "int8", "shape": [4], "data": { "kind": "values", "values": [-30, -3, 100, 127] } },
356
+ "x_scale": { "dtype": "float32", "shape": [], "data": { "kind": "values", "values": [2.0] } },
357
+ "x_zero_point": { "dtype": "int8", "shape": [], "data": { "kind": "values", "values": [-10] } }
358
+ },
359
+ "outputs": { "y": { "dtype": "float32", "shape": [4], "tolerance": 0.000001 } }
360
+ },
361
+ {
362
+ "name": "ort_uint8_large_tail_1039",
363
+ "provenance": {
364
+ "source": "onnxruntime/test/providers/cpu/tensor/quantize_linear_test.cc",
365
+ "test": "DequantizeLinearOpTest.Uint8_Large"
366
+ },
367
+ "attrs": { "axis": 0 },
368
+ "inputs": {
369
+ "x": { "dtype": "uint8", "shape": [1, 1039], "data": { "kind": "constant", "value": 1 } },
370
+ "x_scale": { "dtype": "float32", "shape": [], "data": { "kind": "values", "values": [1.0] } },
371
+ "x_zero_point": { "dtype": "uint8", "shape": [], "data": { "kind": "values", "values": [1] } }
372
+ },
373
+ "outputs": { "y": { "dtype": "float32", "shape": [1, 1039], "tolerance": 0.000001 } }
374
+ },
375
+ {
376
+ "name": "ort_int8_large_tail_1039",
377
+ "provenance": {
378
+ "source": "onnxruntime/test/providers/cpu/tensor/quantize_linear_test.cc",
379
+ "test": "DequantizeLinearOpTest.Int8_Large"
380
+ },
381
+ "attrs": { "axis": 0 },
382
+ "inputs": {
383
+ "x": { "dtype": "int8", "shape": [1, 1039], "data": { "kind": "constant", "value": 1 } },
384
+ "x_scale": { "dtype": "float32", "shape": [], "data": { "kind": "values", "values": [1.0] } },
385
+ "x_zero_point": { "dtype": "int8", "shape": [], "data": { "kind": "values", "values": [1] } }
386
+ },
387
+ "outputs": { "y": { "dtype": "float32", "shape": [1, 1039], "tolerance": 0.000001 } }
388
+ },
389
+ {
390
+ "name": "ort_uint8_2d_scalar_scale_zero_point",
391
+ "provenance": {
392
+ "source": "onnxruntime/test/providers/cpu/tensor/quantize_linear_test.cc",
393
+ "test": "DequantizeLinearOpTest.2D"
394
+ },
395
+ "attrs": { "axis": 0 },
396
+ "inputs": {
397
+ "x": {
398
+ "dtype": "uint8",
399
+ "shape": [3, 4],
400
+ "data": { "kind": "values", "values": [0, 1, 2, 3, 0, 1, 2, 3, 0, 10, 20, 30] }
401
+ },
402
+ "x_scale": { "dtype": "float32", "shape": [], "data": { "kind": "values", "values": [1.0] } },
403
+ "x_zero_point": { "dtype": "uint8", "shape": [], "data": { "kind": "values", "values": [0] } }
404
+ },
405
+ "outputs": { "y": { "dtype": "float32", "shape": [3, 4], "tolerance": 0.000001 } }
406
+ },
407
+ {
408
+ "name": "ort_scalar_input_rank0_with_zero_point",
409
+ "provenance": {
410
+ "source": "onnxruntime/test/providers/cpu/tensor/quantize_linear_test.cc",
411
+ "test": "DequantizeLinearOpTest.Scalar"
412
+ },
413
+ "attrs": { "axis": 0 },
414
+ "inputs": {
415
+ "x": { "dtype": "int8", "shape": [], "data": { "kind": "values", "values": [100] } },
416
+ "x_scale": { "dtype": "float32", "shape": [], "data": { "kind": "values", "values": [2.0] } },
417
+ "x_zero_point": { "dtype": "int8", "shape": [], "data": { "kind": "values", "values": [-10] } }
418
+ },
419
+ "outputs": { "y": { "dtype": "float32", "shape": [], "tolerance": 0.000001 } }
420
+ },
421
+ {
422
+ "name": "ort_scalar_input_rank0_no_zero_point",
423
+ "provenance": {
424
+ "source": "onnxruntime/test/providers/cpu/tensor/quantize_linear_test.cc",
425
+ "test": "DequantizeLinearOpTest.Without_Zero_Point"
426
+ },
427
+ "attrs": { "axis": 0 },
428
+ "inputs": {
429
+ "x": { "dtype": "int8", "shape": [], "data": { "kind": "values", "values": [100] } },
430
+ "x_scale": { "dtype": "float32", "shape": [], "data": { "kind": "values", "values": [2.0] } }
431
+ },
432
+ "outputs": { "y": { "dtype": "float32", "shape": [], "tolerance": 0.000001 } }
433
+ },
434
+ {
435
+ "name": "ort_scalar_input_rank0_f16_with_zero_point",
436
+ "provenance": {
437
+ "source": "onnxruntime/test/providers/cpu/tensor/quantize_linear_test.cc",
438
+ "test": "DequantizeLinearOpMLFloat16Test.Scalar"
439
+ },
440
+ "attrs": { "axis": 0 },
441
+ "inputs": {
442
+ "x": { "dtype": "int8", "shape": [], "data": { "kind": "values", "values": [100] } },
443
+ "x_scale": { "dtype": "float16", "shape": [], "data": { "kind": "values", "values": [2.0] } },
444
+ "x_zero_point": { "dtype": "int8", "shape": [], "data": { "kind": "values", "values": [-10] } }
445
+ },
446
+ "outputs": { "y": { "dtype": "float16", "shape": [], "tolerance": 0.002 } }
447
+ },
448
+ {
449
+ "name": "ort_opset25_f16_int8_axis1",
450
+ "provenance": {
451
+ "source": "onnxruntime/test/providers/cpu/tensor/quantize_linear_test.cc",
452
+ "test": "DequantizeLinearOpMLFloat16Test.Opset25_PerAxisInt8_Cuda"
453
+ },
454
+ "attrs": { "axis": 1 },
455
+ "inputs": {
456
+ "x": { "dtype": "int8", "shape": [2, 4], "data": { "kind": "values", "values": [-2, -1, 0, 1, 2, 3, 4, 5] } },
457
+ "x_scale": { "dtype": "float16", "shape": [4], "data": { "kind": "values", "values": [2.0, 2.0, 4.0, 4.0] } },
458
+ "x_zero_point": { "dtype": "int8", "shape": [4], "data": { "kind": "values", "values": [0, 0, 0, 0] } }
459
+ },
460
+ "outputs": { "y": { "dtype": "float16", "shape": [2, 4], "tolerance": 0.002 } }
461
+ },
462
+ {
463
+ "name": "ort_no_zero_point_int8_1x8",
464
+ "provenance": {
465
+ "source": "onnxruntime/test/providers/cpu/tensor/quantize_linear_test.cc",
466
+ "test": "DequantizeLinearOpTest.No_Zero_Point_int8"
467
+ },
468
+ "attrs": { "axis": 0 },
469
+ "inputs": {
470
+ "x": {
471
+ "dtype": "int8",
472
+ "shape": [1, 8],
473
+ "data": { "kind": "values", "values": [-10, 50, 100, 120, -9, 49, 99, 119] }
474
+ },
475
+ "x_scale": { "dtype": "float32", "shape": [], "data": { "kind": "values", "values": [2.0] } }
476
+ },
477
+ "outputs": { "y": { "dtype": "float32", "shape": [1, 8], "tolerance": 0.000001 } }
478
+ },
479
+ {
480
+ "name": "ort_no_zero_point_uint8_1x8",
481
+ "provenance": {
482
+ "source": "onnxruntime/test/providers/cpu/tensor/quantize_linear_test.cc",
483
+ "test": "DequantizeLinearOpTest.No_Zero_Point_uint8"
484
+ },
485
+ "attrs": { "axis": 0 },
486
+ "inputs": {
487
+ "x": {
488
+ "dtype": "uint8",
489
+ "shape": [1, 8],
490
+ "data": { "kind": "values", "values": [10, 50, 100, 180, 9, 49, 99, 179] }
491
+ },
492
+ "x_scale": { "dtype": "float32", "shape": [], "data": { "kind": "values", "values": [2.0] } }
493
+ },
494
+ "outputs": { "y": { "dtype": "float32", "shape": [1, 8], "tolerance": 0.000001 } }
495
+ },
496
+ {
497
+ "name": "ort_zero_point_int8_1x8",
498
+ "provenance": {
499
+ "source": "onnxruntime/test/providers/cpu/tensor/quantize_linear_test.cc",
500
+ "test": "DequantizeLinearOpTest.Zero_Point_int8"
501
+ },
502
+ "attrs": { "axis": 0 },
503
+ "inputs": {
504
+ "x": {
505
+ "dtype": "int8",
506
+ "shape": [1, 8],
507
+ "data": { "kind": "values", "values": [-10, 50, 100, 120, -9, 49, 99, 119] }
508
+ },
509
+ "x_scale": { "dtype": "float32", "shape": [], "data": { "kind": "values", "values": [2.0] } },
510
+ "x_zero_point": { "dtype": "int8", "shape": [], "data": { "kind": "values", "values": [-10] } }
511
+ },
512
+ "outputs": { "y": { "dtype": "float32", "shape": [1, 8], "tolerance": 0.000001 } }
513
+ },
514
+ {
515
+ "name": "ort_zero_point_uint8_1x8",
516
+ "provenance": {
517
+ "source": "onnxruntime/test/providers/cpu/tensor/quantize_linear_test.cc",
518
+ "test": "DequantizeLinearOpTest.Zero_Point_uint8"
519
+ },
520
+ "attrs": { "axis": 0 },
521
+ "inputs": {
522
+ "x": {
523
+ "dtype": "uint8",
524
+ "shape": [1, 8],
525
+ "data": { "kind": "values", "values": [10, 50, 100, 180, 9, 49, 99, 119] }
526
+ },
527
+ "x_scale": { "dtype": "float32", "shape": [], "data": { "kind": "values", "values": [2.0] } },
528
+ "x_zero_point": { "dtype": "uint8", "shape": [], "data": { "kind": "values", "values": [10] } }
529
+ },
530
+ "outputs": { "y": { "dtype": "float32", "shape": [1, 8], "tolerance": 0.000001 } }
531
+ },
532
+ {
533
+ "name": "int8_no_zero_scalar_explicit_float32_output_dtype",
534
+ "provenance": {
535
+ "notes": "Explicit output_dtype=FLOAT is the non-default spelling of the same float32 route selected from x_scale when output_dtype is omitted."
536
+ },
537
+ "attrs": { "axis": 0, "output_dtype": 1 },
538
+ "inputs": {
539
+ "x": { "dtype": "int8", "shape": [5], "data": { "kind": "values", "values": [-128, -1, 0, 1, 127] } },
540
+ "x_scale": { "dtype": "float32", "shape": [1], "data": { "kind": "values", "values": [0.25] } }
541
+ },
542
+ "outputs": { "y": { "dtype": "float32", "shape": [5], "tolerance": 0.000001 } }
543
+ },
544
+ {
545
+ "name": "scalar_x4_int8_no_zero_tail",
546
+ "attrs": { "axis": 0 },
547
+ "inputs": {
548
+ "x": {
549
+ "dtype": "int8",
550
+ "shape": [17],
551
+ "data": { "kind": "values", "values": [-64, -32, -16, -8, -4, -2, -1, 0, 1, 2, 4, 8, 16, 32, 48, 64, 96] }
552
+ },
553
+ "x_scale": { "dtype": "float32", "shape": [1], "data": { "kind": "values", "values": [0.125] } }
554
+ },
555
+ "outputs": { "y": { "dtype": "float32", "shape": [17], "tolerance": 0.000001 } }
556
+ },
557
+ {
558
+ "name": "vec4_tail_int8_no_zero_4097",
559
+ "attrs": { "axis": 0 },
560
+ "inputs": {
561
+ "x": { "dtype": "int8", "shape": [4097], "data": { "kind": "constant", "value": -4 } },
562
+ "x_scale": { "dtype": "float32", "shape": [1], "data": { "kind": "values", "values": [0.5] } }
563
+ },
564
+ "outputs": { "y": { "dtype": "float32", "shape": [4097], "tolerance": 0.000001 } },
565
+ "provenance": { "notes": "Covers the packed bulk plus scalar tail without a zero point." }
566
+ },
567
+ {
568
+ "name": "scalar_x4_uint8_with_zero_point_tail",
569
+ "attrs": { "axis": 0 },
570
+ "provenance": {
571
+ "notes": "Compact sibling of the large uint8 tail benchmark: scalar scale and scalar uint8 zero point with numel % 4 != 0 selects the scalar_x4_with_zero_point path and exercises tail handling."
572
+ },
573
+ "inputs": {
574
+ "x": {
575
+ "dtype": "uint8",
576
+ "shape": [17],
577
+ "data": {
578
+ "kind": "values",
579
+ "values": [0, 3, 7, 11, 15, 31, 63, 95, 127, 128, 129, 160, 192, 224, 240, 252, 255]
580
+ }
581
+ },
582
+ "x_scale": { "dtype": "float32", "shape": [1], "data": { "kind": "values", "values": [0.125] } },
583
+ "x_zero_point": { "dtype": "uint8", "shape": [1], "data": { "kind": "values", "values": [128] } }
584
+ },
585
+ "outputs": { "y": { "dtype": "float32", "shape": [17], "tolerance": 0.000001 } }
586
+ },
587
+ {
588
+ "name": "vec4_tail_uint8_with_zero_point_4097",
589
+ "attrs": { "axis": 0 },
590
+ "inputs": {
591
+ "x": { "dtype": "uint8", "shape": [4097], "data": { "kind": "constant", "value": 7 } },
592
+ "x_scale": { "dtype": "float32", "shape": [1], "data": { "kind": "values", "values": [0.25] } },
593
+ "x_zero_point": { "dtype": "uint8", "shape": [1], "data": { "kind": "values", "values": [3] } }
594
+ },
595
+ "outputs": { "y": { "dtype": "float32", "shape": [4097], "tolerance": 0.000001 } },
596
+ "provenance": { "notes": "Covers the packed bulk plus scalar tail with a scalar zero point." }
597
+ },
598
+ {
599
+ "name": "uint8_axis0_rank2_per_row",
600
+ "attrs": { "axis": 0 },
601
+ "inputs": {
602
+ "x": { "dtype": "uint8", "shape": [3, 2], "data": { "kind": "values", "values": [6, 14, 40, 42, 20, 130] } },
603
+ "x_scale": { "dtype": "float32", "shape": [3], "data": { "kind": "values", "values": [0.5, 1.0, 2.0] } },
604
+ "x_zero_point": { "dtype": "uint8", "shape": [3], "data": { "kind": "values", "values": [10, 20, 30] } }
605
+ },
606
+ "outputs": { "y": { "dtype": "float32", "shape": [3, 2], "tolerance": 0.000001 } }
607
+ },
608
+ {
609
+ "name": "ort_uint8_per_channel_axis0",
610
+ "provenance": {
611
+ "source": "onnxruntime/test/providers/cpu/tensor/quantize_linear_test.cc",
612
+ "test": "DequantizeLinearOpTest.Per_Channel_Axis_0"
613
+ },
614
+ "attrs": { "axis": 0 },
615
+ "inputs": {
616
+ "x": {
617
+ "dtype": "uint8",
618
+ "shape": [3, 4],
619
+ "data": { "kind": "values", "values": [0, 1, 2, 3, 0, 1, 2, 3, 0, 10, 20, 30] }
620
+ },
621
+ "x_scale": { "dtype": "float32", "shape": [3], "data": { "kind": "values", "values": [1.0, 2.0, 4.0] } },
622
+ "x_zero_point": { "dtype": "uint8", "shape": [3], "data": { "kind": "values", "values": [0, 0, 0] } }
623
+ },
624
+ "outputs": { "y": { "dtype": "float32", "shape": [3, 4], "tolerance": 0.000001 } }
625
+ },
626
+ {
627
+ "name": "ort_int8_per_channel_axis1_nonzero_zero_points",
628
+ "provenance": {
629
+ "source": "onnxruntime/test/providers/cpu/tensor/quantize_linear_test.cc",
630
+ "test": "DequantizeLinearOpTest.Per_Channel_Axis_1_int8"
631
+ },
632
+ "attrs": { "axis": 1 },
633
+ "inputs": {
634
+ "x": {
635
+ "dtype": "int8",
636
+ "shape": [3, 4],
637
+ "data": { "kind": "values", "values": [0, 1, 2, 3, 0, 2, 4, 6, 0, 10, 20, 30] }
638
+ },
639
+ "x_scale": { "dtype": "float32", "shape": [4], "data": { "kind": "values", "values": [1.0, 2.0, 4.0, 8.0] } },
640
+ "x_zero_point": { "dtype": "int8", "shape": [4], "data": { "kind": "values", "values": [0, -10, -20, -30] } }
641
+ },
642
+ "outputs": { "y": { "dtype": "float32", "shape": [3, 4], "tolerance": 0.000001 } }
643
+ },
644
+ {
645
+ "name": "int32_scalar_ort",
646
+ "provenance": {
647
+ "source": "onnxruntime/test/providers/cpu/tensor/quantize_linear_test.cc",
648
+ "test": "DequantizeLinearOpTest.Int32",
649
+ "notes": "Uses a length-1 scale tensor for the framework's scalar-style fixture encoding."
650
+ },
651
+ "attrs": { "axis": 0 },
652
+ "inputs": {
653
+ "x": { "dtype": "int32", "shape": [4], "data": { "kind": "values", "values": [-30, -3, 100, 127] } },
654
+ "x_scale": { "dtype": "float32", "shape": [1], "data": { "kind": "values", "values": [2.0] } }
655
+ },
656
+ "outputs": { "y": { "dtype": "float32", "shape": [4], "tolerance": 0.000001 } }
657
+ },
658
+ {
659
+ "name": "int32_nonzero_zero_point_ort",
660
+ "provenance": {
661
+ "source": "onnxruntime/test/providers/cpu/tensor/quantize_linear_test.cc",
662
+ "test": "DequantizeLinearOpTest.Int32_Non_Zero_Zero_Point",
663
+ "notes": "Uses length-1 scale and zero-point tensors for the framework's scalar-style fixture encoding."
664
+ },
665
+ "attrs": { "axis": 0 },
666
+ "inputs": {
667
+ "x": { "dtype": "int32", "shape": [4], "data": { "kind": "values", "values": [-30, -3, 100, 127] } },
668
+ "x_scale": { "dtype": "float32", "shape": [1], "data": { "kind": "values", "values": [2.0] } },
669
+ "x_zero_point": { "dtype": "int32", "shape": [1], "data": { "kind": "values", "values": [1] } }
670
+ },
671
+ "outputs": { "y": { "dtype": "float32", "shape": [4], "tolerance": 0.000001 } }
672
+ },
673
+ {
674
+ "name": "ort_int8_per_channel_default_axis_rank4",
675
+ "provenance": {
676
+ "source": "onnxruntime/test/providers/cpu/tensor/quantize_linear_test.cc",
677
+ "test": "DequantizeLinearOpTest.Per_Channel_Axis_Default"
678
+ },
679
+ "inputs": {
680
+ "x": {
681
+ "dtype": "int8",
682
+ "shape": [2, 3, 2, 4],
683
+ "data": {
684
+ "kind": "values",
685
+ "values": [7, 9, 10, 10, 5, 8, 9, 1, 8, 6, 7, 9, 10, 0, 7, 10, 8, 2, 6, 0, 5, 9, 8, 1, 2, 7, 5, 3, 2, 4, 1, 3, 8, 7, 4, 8, 10, 1, 5, 5, 7, 7, 0, 2, 4, 4, 0, 5]
686
+ }
687
+ },
688
+ "x_scale": { "dtype": "float32", "shape": [3], "data": { "kind": "values", "values": [1.0, 10.0, 7.0] } },
689
+ "x_zero_point": { "dtype": "int8", "shape": [3], "data": { "kind": "values", "values": [10, 2, 1] } }
690
+ },
691
+ "outputs": { "y": { "dtype": "float32", "shape": [2, 3, 2, 4], "tolerance": 0.000001 } }
692
+ },
693
+ {
694
+ "name": "ort_int32_per_channel_axis1",
695
+ "provenance": {
696
+ "source": "onnxruntime/test/providers/cpu/tensor/quantize_linear_test.cc",
697
+ "test": "DequantizeLinearOpTest.Per_Channel_Axis_1_int32"
698
+ },
699
+ "attrs": { "axis": 1 },
700
+ "inputs": {
701
+ "x": {
702
+ "dtype": "int32",
703
+ "shape": [3, 4],
704
+ "data": { "kind": "values", "values": [0, 1, 2, 3, 0, 2, 4, 6, 0, 10, 20, 30] }
705
+ },
706
+ "x_scale": { "dtype": "float32", "shape": [4], "data": { "kind": "values", "values": [1.0, 2.0, 4.0, 8.0] } },
707
+ "x_zero_point": { "dtype": "int32", "shape": [4], "data": { "kind": "values", "values": [0, 0, 0, 0] } }
708
+ },
709
+ "outputs": { "y": { "dtype": "float32", "shape": [3, 4], "tolerance": 0.000001 } }
710
+ },
711
+ {
712
+ "name": "ort_uint8_per_channel_negative_axis_minus2",
713
+ "provenance": {
714
+ "source": "onnxruntime/test/providers/cpu/tensor/quantize_linear_test.cc",
715
+ "test": "DequantizeLinearOpTest.Per_Channel_Neg_2"
716
+ },
717
+ "attrs": { "axis": -2 },
718
+ "inputs": {
719
+ "x": {
720
+ "dtype": "uint8",
721
+ "shape": [3, 4],
722
+ "data": { "kind": "values", "values": [0, 1, 2, 3, 0, 1, 2, 3, 0, 10, 20, 30] }
723
+ },
724
+ "x_scale": { "dtype": "float32", "shape": [3], "data": { "kind": "values", "values": [1.0, 2.0, 4.0] } },
725
+ "x_zero_point": { "dtype": "uint8", "shape": [3], "data": { "kind": "values", "values": [0, 0, 0] } }
726
+ },
727
+ "outputs": { "y": { "dtype": "float32", "shape": [3, 4], "tolerance": 0.000001 } }
728
+ },
729
+ {
730
+ "name": "ort_uint8_large_vectorized_zero",
731
+ "provenance": {
732
+ "source": "onnxruntime/test/providers/cpu/tensor/quantize_linear_test.cc",
733
+ "test": "DequantizeLinearOpTest.Uint8_Large",
734
+ "notes": "Same non-vector-aligned element count as ORT, flattened from [1, 1039] to [1039]."
735
+ },
736
+ "inputs": {
737
+ "x": { "dtype": "uint8", "shape": [1039], "data": { "kind": "constant", "value": 1 } },
738
+ "x_scale": { "dtype": "float32", "shape": [1], "data": { "kind": "values", "values": [1.0] } },
739
+ "x_zero_point": { "dtype": "uint8", "shape": [1], "data": { "kind": "values", "values": [1] } }
740
+ },
741
+ "outputs": { "y": { "dtype": "float32", "shape": [1039], "tolerance": 0.000001 } }
742
+ },
743
+ {
744
+ "name": "ort_int8_large_vectorized_zero",
745
+ "provenance": {
746
+ "source": "onnxruntime/test/providers/cpu/tensor/quantize_linear_test.cc",
747
+ "test": "DequantizeLinearOpTest.Int8_Large",
748
+ "notes": "Same non-vector-aligned element count as ORT, flattened from [1, 1039] to [1039]."
749
+ },
750
+ "inputs": {
751
+ "x": { "dtype": "int8", "shape": [1039], "data": { "kind": "constant", "value": 1 } },
752
+ "x_scale": { "dtype": "float32", "shape": [1], "data": { "kind": "values", "values": [1.0] } },
753
+ "x_zero_point": { "dtype": "int8", "shape": [1], "data": { "kind": "values", "values": [1] } }
754
+ },
755
+ "outputs": { "y": { "dtype": "float32", "shape": [1039], "tolerance": 0.000001 } }
756
+ },
757
+ {
758
+ "name": "ort_int8_non_aligned_size_135",
759
+ "provenance": {
760
+ "source": "onnxruntime/test/providers/cpu/tensor/quantize_linear_test.cc",
761
+ "test": "DequantizeLinearOpTest.Int8_NonAlignedSize_Initializer",
762
+ "notes": "Same non-aligned length; constant data keeps the fixture compact."
763
+ },
764
+ "inputs": {
765
+ "x": { "dtype": "int8", "shape": [135], "data": { "kind": "constant", "value": 7 } },
766
+ "x_scale": { "dtype": "float32", "shape": [1], "data": { "kind": "values", "values": [0.25] } },
767
+ "x_zero_point": { "dtype": "int8", "shape": [1], "data": { "kind": "values", "values": [0] } }
768
+ },
769
+ "outputs": { "y": { "dtype": "float32", "shape": [135], "tolerance": 0.000001 } }
770
+ },
771
+ {
772
+ "name": "onnx_backend_dequantizelinear",
773
+ "provenance": { "source": "cmake/external/onnx/onnx/backend/test/data/node/test_dequantizelinear" },
774
+ "inputs": {
775
+ "x": { "dtype": "uint8", "shape": [4], "data": { "kind": "values", "values": [0, 3, 128, 255] } },
776
+ "x_scale": { "dtype": "float32", "shape": [], "data": { "kind": "values", "values": [2.0] } },
777
+ "x_zero_point": { "dtype": "uint8", "shape": [], "data": { "kind": "values", "values": [128] } }
778
+ },
779
+ "outputs": { "y": { "dtype": "float32", "shape": [4], "tolerance": 0.00001 } }
780
+ },
781
+ {
782
+ "name": "onnx_backend_dequantizelinear_axis",
783
+ "provenance": { "source": "cmake/external/onnx/onnx/backend/test/data/node/test_dequantizelinear_axis" },
784
+ "inputs": {
785
+ "x": {
786
+ "dtype": "uint8",
787
+ "shape": [1, 3, 3, 2],
788
+ "data": { "kind": "values", "values": { "$ref": "#/fixtureArrays/uint8_axis1_rank4_onnx_backend_input_x" } }
789
+ },
790
+ "x_scale": { "dtype": "float32", "shape": [3], "data": { "kind": "values", "values": [2.0, 4.0, 5.0] } },
791
+ "x_zero_point": { "dtype": "uint8", "shape": [3], "data": { "kind": "values", "values": [84, 24, 196] } }
792
+ },
793
+ "outputs": { "y": { "dtype": "float32", "shape": [1, 3, 3, 2], "tolerance": 0.00001 } }
794
+ },
795
+ {
796
+ "name": "onnx_backend_dequantizelinear_blocked",
797
+ "provenance": { "source": "cmake/external/onnx/onnx/backend/test/data/node/test_dequantizelinear_blocked" },
798
+ "attrs": { "axis": 1, "block_size": 2 },
799
+ "inputs": {
800
+ "x": {
801
+ "dtype": "uint8",
802
+ "shape": [1, 4, 3, 2],
803
+ "data": {
804
+ "kind": "values",
805
+ "values": [3, 89, 34, 200, 74, 59, 5, 24, 24, 87, 32, 13, 5, 12, 12, 33, 65, 42, 245, 99, 4, 142, 121, 102]
806
+ }
807
+ },
808
+ "x_scale": {
809
+ "dtype": "float32",
810
+ "shape": [1, 2, 3, 2],
811
+ "data": { "kind": "values", "values": [3.0, 2.0, 4.0, 1.0, 2.0, 2.0, 5.0, 2.0, 4.0, 3.0, 5.0, 2.0] }
812
+ },
813
+ "x_zero_point": {
814
+ "dtype": "uint8",
815
+ "shape": [1, 2, 3, 2],
816
+ "data": { "kind": "values", "values": [1, 0, 0, 1, 2, 20, 3, 2, 4, 3, 15, 2] }
817
+ }
818
+ },
819
+ "outputs": { "y": { "dtype": "float32", "shape": [1, 4, 3, 2], "tolerance": 0.00001 } }
820
+ },
821
+ {
822
+ "name": "ort_blocked_uint8_with_zero_point_rank3_axis2",
823
+ "provenance": {
824
+ "source": "onnxruntime/test/providers/cpu/tensor/quantize_linear_test.cc",
825
+ "test": "DequantizeLinearOp21BlockedTest.UnsignedInt_UseZeroPoint_LastAxis",
826
+ "notes": "Valid blocked dequantization with per-block zero-points on the last axis."
827
+ },
828
+ "attrs": { "axis": 2, "block_size": 2 },
829
+ "inputs": {
830
+ "x": {
831
+ "dtype": "uint8",
832
+ "shape": [2, 2, 4],
833
+ "data": { "kind": "values", "values": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15] }
834
+ },
835
+ "x_scale": {
836
+ "dtype": "float32",
837
+ "shape": [2, 2, 2],
838
+ "data": { "kind": "values", "values": [-2.0, -4.0, 3.5, 1.0, 2.0, 4.0, -3.5, -1.0] }
839
+ },
840
+ "x_zero_point": {
841
+ "dtype": "uint8",
842
+ "shape": [2, 2, 2],
843
+ "data": { "kind": "values", "values": [2, 0, 1, 9, 13, 5, 11, 6] }
844
+ }
845
+ },
846
+ "outputs": { "y": { "dtype": "float32", "shape": [2, 2, 4], "tolerance": 0.000001 } }
847
+ },
848
+ {
849
+ "name": "ort_blocked_uint8_no_zero_point_rank3_axis0",
850
+ "provenance": {
851
+ "source": "onnxruntime/test/providers/cpu/tensor/quantize_linear_test.cc",
852
+ "test": "DequantizeLinearOp21BlockedTest.UnsignedInt_NoZeroPoint_FirstAxis"
853
+ },
854
+ "attrs": { "axis": 0, "block_size": 2 },
855
+ "inputs": {
856
+ "x": {
857
+ "dtype": "uint8",
858
+ "shape": [4, 2, 2],
859
+ "data": { "kind": "values", "values": [1, 2, 3, 4, 5, 6, 7, 8, 20, 22, 24, 26, 40, 42, 44, 46] }
860
+ },
861
+ "x_scale": {
862
+ "dtype": "float32",
863
+ "shape": [2, 2, 2],
864
+ "data": { "kind": "values", "values": [0.5, 1.0, 1.5, 2.0, 2.5, 3.0, 4.0, 5.0] }
865
+ }
866
+ },
867
+ "outputs": { "y": { "dtype": "float32", "shape": [4, 2, 2], "tolerance": 0.000001 } }
868
+ },
869
+ {
870
+ "name": "empty_input_zero_dim",
871
+ "inputs": {
872
+ "x": { "dtype": "uint8", "shape": [2, 0], "data": { "kind": "values", "values": [] } },
873
+ "x_scale": { "dtype": "float32", "shape": [0], "data": { "kind": "values", "values": [] } },
874
+ "x_zero_point": { "dtype": "uint8", "shape": [0], "data": { "kind": "values", "values": [] } }
875
+ },
876
+ "outputs": { "y": { "dtype": "float32", "shape": [2, 0], "tolerance": 0 } }
877
+ },
878
+ {
879
+ "name": "int8_blocked_rank4_axis1_nonzero_zp",
880
+ "attrs": { "axis": 1, "block_size": 2 },
881
+ "inputs": {
882
+ "x": {
883
+ "dtype": "int8",
884
+ "shape": [1, 4, 3, 2],
885
+ "data": {
886
+ "kind": "values",
887
+ "values": [-50, 12, -7, 88, 30, -41, 5, -24, 24, 87, -32, 13, 5, -12, 12, -33, 65, 42, -120, 99, 4, -100, 121, -102]
888
+ }
889
+ },
890
+ "x_scale": {
891
+ "dtype": "float32",
892
+ "shape": [1, 2, 3, 2],
893
+ "data": { "kind": "values", "values": [3.0, 2.0, 4.0, 1.0, 2.0, 2.0, 5.0, 2.0, 4.0, 3.0, 5.0, 2.0] }
894
+ },
895
+ "x_zero_point": {
896
+ "dtype": "int8",
897
+ "shape": [1, 2, 3, 2],
898
+ "data": { "kind": "values", "values": [1, 0, -2, 1, 2, -20, 3, 2, -4, 3, 15, 2] }
899
+ }
900
+ },
901
+ "outputs": { "y": { "dtype": "float32", "shape": [1, 4, 3, 2], "tolerance": 0.000001 } }
902
+ },
903
+ {
904
+ "name": "blocked_no_zero_point_rank4_axis1_symmetric",
905
+ "attrs": { "axis": 1, "block_size": 2 },
906
+ "inputs": {
907
+ "x": {
908
+ "dtype": "int8",
909
+ "shape": [1, 4, 2, 2],
910
+ "data": {
911
+ "kind": "values",
912
+ "values": { "$ref": "#/fixtureArrays/blocked_no_zero_point_rank4_axis1_symmetric_input_x" }
913
+ }
914
+ },
915
+ "x_scale": {
916
+ "dtype": "float32",
917
+ "shape": [1, 2, 2, 2],
918
+ "data": { "kind": "values", "values": [0.5, 1.0, 1.5, 2.0, 0.25, 0.75, 1.25, 1.75] }
919
+ }
920
+ },
921
+ "outputs": { "y": { "dtype": "float32", "shape": [1, 4, 2, 2], "tolerance": 0.000001 } }
922
+ },
923
+ {
924
+ "name": "empty_blocked_rank4_axis1_zero_channel",
925
+ "attrs": { "axis": 1, "block_size": 2 },
926
+ "inputs": {
927
+ "x": { "dtype": "int8", "shape": [1, 0, 2, 2], "data": { "kind": "values", "values": [] } },
928
+ "x_scale": { "dtype": "float32", "shape": [1, 0, 2, 2], "data": { "kind": "values", "values": [] } },
929
+ "x_zero_point": { "dtype": "int8", "shape": [1, 0, 2, 2], "data": { "kind": "values", "values": [] } }
930
+ },
931
+ "outputs": { "y": { "dtype": "float32", "shape": [1, 0, 2, 2], "tolerance": 0 } }
932
+ },
933
+ {
934
+ "name": "per_axis0_dispatch_fold_17M_last_rows",
935
+ "requires": { "limits": { "maxBufferSize": 281018368, "maxStorageBufferBindingSize": 281018368 } },
936
+ "provenance": {
937
+ "notes": "Its largest tensor is 281018368 bytes, so the case needs an adapter whose maxBufferSize and maxStorageBufferBindingSize both reach it — declared, because the WebGPU guaranteed minimums (256 MiB / 128 MiB) do not, and a device at them must report the case inapplicable rather than fail allocating it."
938
+ },
939
+ "attrs": { "axis": 0 },
940
+ "inputs": {
941
+ "x": {
942
+ "dtype": "uint8",
943
+ "shape": [67, 1048576],
944
+ "data": { "kind": "cycle", "values": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] }
945
+ },
946
+ "x_scale": {
947
+ "dtype": "float32",
948
+ "shape": [67],
949
+ "data": { "kind": "fillFloat32", "sinStep": 0.07, "cosStep": 0.05, "scale": 0.01, "offset": 0.02 }
950
+ },
951
+ "x_zero_point": { "dtype": "uint8", "shape": [67], "data": { "kind": "constant", "value": 5 } }
952
+ },
953
+ "outputs": { "y": { "dtype": "float32", "shape": [67, 1048576], "tolerance": 0.0001 } }
954
+ },
955
+ {
956
+ "name": "innermost_axis_vec4_no_zero_two_rows",
957
+ "provenance": {
958
+ "notes": "Exercises vec4-bound innermost per-axis scales without a zero point. Expected values come from the TypeScript dequantization reference."
959
+ },
960
+ "attrs": { "axis": 1 },
961
+ "inputs": {
962
+ "x": {
963
+ "dtype": "int8",
964
+ "shape": [2, 4],
965
+ "data": { "kind": "values", "values": [-8, -4, 2, 7, 10, -12, 20, -24] }
966
+ },
967
+ "x_scale": { "dtype": "float32", "shape": [4], "data": { "kind": "values", "values": [0.25, 0.5, 1.5, 2.0] } }
968
+ },
969
+ "outputs": { "y": { "dtype": "float32", "shape": [2, 4], "tolerance": 0.000001 } }
970
+ },
971
+ {
972
+ "name": "vec4_cross_axis_rows_width6_with_zero_point",
973
+ "provenance": {
974
+ "notes": "A vec4 crosses each six-element row boundary, so its four lanes may use two different per-axis scale and zero-point entries. Locks the lane-specific parameter-index path."
975
+ },
976
+ "attrs": { "axis": 0 },
977
+ "inputs": {
978
+ "x": { "dtype": "int8", "shape": [4, 6], "data": { "kind": "cycle", "values": [-42, -8, 0, 7, 31, 63] } },
979
+ "x_scale": { "dtype": "float32", "shape": [4], "data": { "kind": "values", "values": [0.25, 0.5, 1.0, 2.0] } },
980
+ "x_zero_point": { "dtype": "int8", "shape": [4], "data": { "kind": "values", "values": [-3, 2, 5, -7] } }
981
+ },
982
+ "outputs": { "y": { "dtype": "float32", "shape": [4, 6], "tolerance": 0.000001 } }
983
+ },
984
+ {
985
+ "name": "vec4_cross_axis_rows_width6_no_zero_point",
986
+ "provenance": {
987
+ "notes": "Symmetric per-channel dequantization over six-element rows with x_zero_point omitted (ONNX makes it optional and defaults it to 0), so a four-lane vector still crosses each row boundary and may need two different per-axis scale entries while no zero-point binding exists. Twin of vec4_cross_axis_rows_width6_with_zero_point; the seven-value input cycle is coprime with the six-wide row so no two rows repeat the same lane pattern. Expected values come from the TypeScript dequantization reference."
988
+ },
989
+ "attrs": { "axis": 0 },
990
+ "inputs": {
991
+ "x": { "dtype": "int8", "shape": [4, 6], "data": { "kind": "cycle", "values": [-42, -8, 0, 7, 31, 63, -19] } },
992
+ "x_scale": { "dtype": "float32", "shape": [4], "data": { "kind": "values", "values": [0.25, 0.5, 1.0, 2.0] } }
993
+ },
994
+ "outputs": { "y": { "dtype": "float32", "shape": [4, 6], "tolerance": 0.000001 } }
995
+ },
996
+ {
997
+ "name": "blocked_no_zero_point_rank4_axis1_symmetric_f16",
998
+ "provenance": {
999
+ "notes": "float16 output exercises half-precision storage on the blocked-axis route without a zero point."
1000
+ },
1001
+ "attrs": { "axis": 1, "block_size": 2 },
1002
+ "inputs": {
1003
+ "x": {
1004
+ "dtype": "int8",
1005
+ "shape": [1, 4, 2, 2],
1006
+ "data": {
1007
+ "kind": "values",
1008
+ "values": { "$ref": "#/fixtureArrays/blocked_no_zero_point_rank4_axis1_symmetric_input_x" }
1009
+ }
1010
+ },
1011
+ "x_scale": {
1012
+ "dtype": "float16",
1013
+ "shape": [1, 2, 2, 2],
1014
+ "data": { "kind": "values", "values": [0.5, 1.0, 1.5, 2.0, 0.25, 0.75, 1.25, 1.75] }
1015
+ }
1016
+ },
1017
+ "outputs": { "y": { "dtype": "float16", "shape": [1, 4, 2, 2], "tolerance": 0 } }
1018
+ }
1019
+ ]
1020
+ }