| { |
| "op": "ai.onnx.DynamicQuantizeLinear", |
| "cases": [ |
| { |
| "name": "mixed_sign_values", |
| "inputs": { |
| "x": { |
| "dtype": "float32", |
| "shape": [6], |
| "data": { "kind": "values", "values": [-1.0, -0.5, 0.0, 0.5, 1.0, 2.0] } |
| } |
| }, |
| "outputs": { |
| "y": { "dtype": "uint8", "shape": [6] }, |
| "y_scale": { "dtype": "float32", "shape": [], "tolerance": 0.000001 }, |
| "y_zero_point": { "dtype": "uint8", "shape": [] } |
| } |
| }, |
| { |
| "name": "ort_mixed_sign_rounding_formulation", |
| "provenance": { |
| "source": "onnxruntime/test/providers/cpu/tensor/dynamic_quantize_linear_test.cc", |
| "test": "QuantizeLinearOpTest.DynamicQuantizeLinear" |
| }, |
| "inputs": { |
| "x": { |
| "dtype": "float32", |
| "shape": [6], |
| "data": { "kind": "values", "values": [0.0, 2.0, -3.0, -2.5, 1.34, 0.5] } |
| } |
| }, |
| "outputs": { |
| "y": { "dtype": "uint8", "shape": [6] }, |
| "y_scale": { "dtype": "float32", "shape": [], "tolerance": 0.000001 }, |
| "y_zero_point": { "dtype": "uint8", "shape": [] } |
| } |
| }, |
| { |
| "name": "all_positive_includes_zero_range", |
| "inputs": { |
| "x": { "dtype": "float32", "shape": [4], "data": { "kind": "values", "values": [1.0, 2.0, 3.0, 4.0] } } |
| }, |
| "outputs": { |
| "y": { "dtype": "uint8", "shape": [4] }, |
| "y_scale": { "dtype": "float32", "shape": [], "tolerance": 0.000001 }, |
| "y_zero_point": { "dtype": "uint8", "shape": [] } |
| } |
| }, |
| { |
| "name": "constant_zero_scale_fallback", |
| "inputs": { |
| "x": { "dtype": "float32", "shape": [4], "data": { "kind": "values", "values": [0.0, 0.0, 0.0, 0.0] } } |
| }, |
| "outputs": { |
| "y": { "dtype": "uint8", "shape": [4] }, |
| "y_scale": { "dtype": "float32", "shape": [] }, |
| "y_zero_point": { "dtype": "uint8", "shape": [] } |
| } |
| }, |
| { |
| "name": "subnormal_positive_range_preserves_scale_gpu_gap", |
| "skipGpu": { |
| "category": "permanent", |
| "reason": "Portable WGSL floating-point semantics do not guarantee preservation of the subnormal scale values required by this fixture. Backend evidence: DynamicQuantizeLinear computes scale=(max-min)/255 then x/scale; a subnormal input range yields a subnormal scale and Metal flushes denormals in floating-point division (-> NaN/0), so subnormal-range cases remain CPU-reference-only." |
| }, |
| "provenance": { |
| "source": "onnxruntime/test/providers/cpu/tensor/dynamic_quantize_linear_test.cc", |
| "test": "QuantizeLinearOpTest.DynamicQuantizeLinear", |
| "notes": "Tiny but valid positive range: y_scale is a float32 subnormal, so a backend must not flush it to zero and take the constant-input fallback." |
| }, |
| "inputs": { "x": { "dtype": "float32", "shape": [2], "data": { "kind": "values", "values": [0.0, 1e-40] } } }, |
| "outputs": { |
| "y": { "dtype": "uint8", "shape": [2], "tolerance": 0 }, |
| "y_scale": { "dtype": "float32", "shape": [], "tolerance": 0 }, |
| "y_zero_point": { "dtype": "uint8", "shape": [], "tolerance": 0 } |
| } |
| }, |
| { |
| "name": "subnormal_negative_range_preserves_scale_gpu_gap", |
| "skipGpu": { |
| "category": "permanent", |
| "reason": "Portable WGSL floating-point semantics do not guarantee preservation of the subnormal scale values required by this fixture. Backend evidence: DynamicQuantizeLinear computes scale=(max-min)/255 then x/scale; a subnormal input range yields a subnormal scale and Metal flushes denormals in floating-point division (-> NaN/0), so subnormal-range cases remain CPU-reference-only." |
| }, |
| "provenance": { |
| "source": "onnxruntime/test/providers/cpu/tensor/dynamic_quantize_linear_test.cc", |
| "test": "QuantizeLinearOpTest.DynamicQuantizeLinear_Max_Adjusted", |
| "notes": "Tiny but valid negative range: ONNX adjusts the max to zero, producing a float32 subnormal scale and a high zero point rather than the constant-input fallback." |
| }, |
| "inputs": { "x": { "dtype": "float32", "shape": [2], "data": { "kind": "values", "values": [-1e-40, 0.0] } } }, |
| "outputs": { |
| "y": { "dtype": "uint8", "shape": [2], "tolerance": 0 }, |
| "y_scale": { "dtype": "float32", "shape": [], "tolerance": 0 }, |
| "y_zero_point": { "dtype": "uint8", "shape": [], "tolerance": 0 } |
| } |
| }, |
| { |
| "name": "subnormal_mixed_sign_range_vec4_reduce_gpu_gap", |
| "skipGpu": { |
| "category": "permanent", |
| "reason": "Portable WGSL floating-point semantics do not guarantee preservation of the subnormal scale values required by this fixture. Backend evidence: DynamicQuantizeLinear computes scale=(max-min)/255 then x/scale; a subnormal input range yields a subnormal scale and Metal flushes denormals in floating-point division (-> NaN/0), so subnormal-range cases remain CPU-reference-only." |
| }, |
| "provenance": { |
| "source": "onnxruntime/test/providers/cpu/tensor/dynamic_quantize_linear_test.cc", |
| "test": "QuantizeLinearOpTest.DynamicQuantizeLinear", |
| "notes": "Tiny mixed-sign range with four elements exercises the vec4 reduce path: ONNX should keep a subnormal scale and nonzero zero point." |
| }, |
| "inputs": { |
| "x": { |
| "dtype": "float32", |
| "shape": [4], |
| "data": { "kind": "values", "values": [-1e-40, -5e-41, 5e-41, 1e-40] } |
| } |
| }, |
| "outputs": { |
| "y": { "dtype": "uint8", "shape": [4], "tolerance": 0 }, |
| "y_scale": { "dtype": "float32", "shape": [], "tolerance": 0 }, |
| "y_zero_point": { "dtype": "uint8", "shape": [], "tolerance": 0 } |
| } |
| }, |
| { |
| "name": "min_adjusted_positive_2d_ort", |
| "provenance": { |
| "source": "onnxruntime/test/providers/cpu/tensor/dynamic_quantize_linear_test.cc", |
| "test": "QuantizeLinearOpTest.DynamicQuantizeLinear_Min_Adjusted" |
| }, |
| "inputs": { |
| "x": { |
| "dtype": "float32", |
| "shape": [3, 4], |
| "data": { "kind": "values", "values": [1.0, 2.1, 1.3, 2.5, 3.34, 4.0, 1.5, 2.6, 3.9, 4.0, 3.0, 2.345] } |
| } |
| }, |
| "outputs": { |
| "y": { "dtype": "uint8", "shape": [3, 4] }, |
| "y_scale": { "dtype": "float32", "shape": [], "tolerance": 0.000001 }, |
| "y_zero_point": { "dtype": "uint8", "shape": [] } |
| } |
| }, |
| { |
| "name": "max_adjusted_negative_ort", |
| "provenance": { |
| "source": "onnxruntime/test/providers/cpu/tensor/dynamic_quantize_linear_test.cc", |
| "test": "QuantizeLinearOpTest.DynamicQuantizeLinear_Max_Adjusted" |
| }, |
| "inputs": { |
| "x": { |
| "dtype": "float32", |
| "shape": [6], |
| "data": { "kind": "values", "values": [-1.0, -2.1, -1.3, -2.5, -3.34, -4.0] } |
| } |
| }, |
| "outputs": { |
| "y": { "dtype": "uint8", "shape": [6] }, |
| "y_scale": { "dtype": "float32", "shape": [], "tolerance": 0.000001 }, |
| "y_zero_point": { "dtype": "uint8", "shape": [] } |
| } |
| }, |
| { |
| "name": "singleton_positive_adjusts_min_to_zero", |
| "inputs": { "x": { "dtype": "float32", "shape": [1], "data": { "kind": "values", "values": [5.0] } } }, |
| "outputs": { |
| "y": { "dtype": "uint8", "shape": [1] }, |
| "y_scale": { "dtype": "float32", "shape": [], "tolerance": 0.000001 }, |
| "y_zero_point": { "dtype": "uint8", "shape": [] } |
| } |
| }, |
| { |
| "name": "onnx_backend_dynamicquantizelinear", |
| "provenance": { "source": "cmake/external/onnx/onnx/backend/test/data/node/test_dynamicquantizelinear" }, |
| "inputs": { |
| "x": { |
| "dtype": "float32", |
| "shape": [6], |
| "data": { "kind": "values", "values": [0.0, 2.0, -3.0, -2.5, 1.340000033378601, 0.5] } |
| } |
| }, |
| "outputs": { |
| "y": { "dtype": "uint8", "shape": [6], "tolerance": 0 }, |
| "y_scale": { "dtype": "float32", "shape": [], "tolerance": 0.00001 }, |
| "y_zero_point": { "dtype": "uint8", "shape": [], "tolerance": 0 } |
| } |
| }, |
| { |
| "name": "onnx_backend_dynamicquantizelinear_max_adjusted", |
| "provenance": { |
| "source": "cmake/external/onnx/onnx/backend/test/data/node/test_dynamicquantizelinear_max_adjusted" |
| }, |
| "inputs": { |
| "x": { |
| "dtype": "float32", |
| "shape": [6], |
| "data": { |
| "kind": "values", |
| "values": [-1.0, -2.0999999046325684, -1.2999999523162842, -2.5, -3.3399999141693115, -4.0] |
| } |
| } |
| }, |
| "outputs": { |
| "y": { "dtype": "uint8", "shape": [6], "tolerance": 0 }, |
| "y_scale": { "dtype": "float32", "shape": [], "tolerance": 0.00001 }, |
| "y_zero_point": { "dtype": "uint8", "shape": [], "tolerance": 0 } |
| } |
| }, |
| { |
| "name": "onnx_backend_dynamicquantizelinear_min_adjusted", |
| "provenance": { |
| "source": "cmake/external/onnx/onnx/backend/test/data/node/test_dynamicquantizelinear_min_adjusted" |
| }, |
| "inputs": { |
| "x": { |
| "dtype": "float32", |
| "shape": [3, 4], |
| "data": { |
| "kind": "values", |
| "values": [1.0, 2.0999999046325684, 1.2999999523162842, 2.5, 3.3399999141693115, 4.0, 1.5, 2.5999999046325684, 3.9000000953674316, 4.0, 3.0, 2.3450000286102295] |
| } |
| } |
| }, |
| "outputs": { |
| "y": { "dtype": "uint8", "shape": [3, 4], "tolerance": 0 }, |
| "y_scale": { "dtype": "float32", "shape": [], "tolerance": 0.00001 }, |
| "y_zero_point": { "dtype": "uint8", "shape": [], "tolerance": 0 } |
| } |
| }, |
| { |
| "name": "parallel_mixed_sign_5000", |
| "inputs": { |
| "x": { |
| "dtype": "float32", |
| "shape": [5000], |
| "data": { "kind": "fillFloat32", "sinStep": 0.013, "cosStep": 0.017, "scale": 3.0 } |
| } |
| }, |
| "outputs": { |
| "y": { "dtype": "uint8", "shape": [5000], "tolerance": 0 }, |
| "y_scale": { "dtype": "float32", "shape": [], "tolerance": 0.000001 }, |
| "y_zero_point": { "dtype": "uint8", "shape": [], "tolerance": 0 } |
| } |
| }, |
| { |
| "name": "parallel_all_negative_1500_tail", |
| "inputs": { |
| "x": { |
| "dtype": "float32", |
| "shape": [1500], |
| "data": { |
| "kind": "cycle", |
| "values": [-1.0, -2.1, -1.3, -2.5, -3.34, -4.0, -0.25, -7.75, -0.001, -6.5, -2.75, -5.125, -3.5] |
| } |
| } |
| }, |
| "outputs": { |
| "y": { "dtype": "uint8", "shape": [1500], "tolerance": 0 }, |
| "y_scale": { "dtype": "float32", "shape": [], "tolerance": 0.000001 }, |
| "y_zero_point": { "dtype": "uint8", "shape": [], "tolerance": 0 } |
| } |
| }, |
| { |
| "name": "parallel_const_zero_1027_tail", |
| "inputs": { "x": { "dtype": "float32", "shape": [1027], "data": { "kind": "cycle", "values": [0.0] } } }, |
| "outputs": { |
| "y": { "dtype": "uint8", "shape": [1027], "tolerance": 0 }, |
| "y_scale": { "dtype": "float32", "shape": [], "tolerance": 0 }, |
| "y_zero_point": { "dtype": "uint8", "shape": [], "tolerance": 0 } |
| } |
| }, |
| { |
| "name": "scalar_rank0_positive", |
| "inputs": { "x": { "dtype": "float32", "shape": [], "data": { "kind": "values", "values": [5.0] } } }, |
| "outputs": { |
| "y": { "dtype": "uint8", "shape": [], "tolerance": 0 }, |
| "y_scale": { "dtype": "float32", "shape": [], "tolerance": 0.000001 }, |
| "y_zero_point": { "dtype": "uint8", "shape": [], "tolerance": 0 } |
| } |
| }, |
| { |
| "name": "scalar_rank0_negative", |
| "provenance": { |
| "source": "onnxruntime/test/providers/cpu/tensor/dynamic_quantize_linear_test.cc", |
| "test": "QuantizeLinearOpTest.DynamicQuantizeLinear_Max_Adjusted", |
| "notes": "Rank-0 scalar companion for the all-negative max-adjusted path: max is adjusted to include zero, producing zero_point=255." |
| }, |
| "inputs": { "x": { "dtype": "float32", "shape": [], "data": { "kind": "values", "values": [-5.0] } } }, |
| "outputs": { |
| "y": { "dtype": "uint8", "shape": [], "tolerance": 0 }, |
| "y_scale": { "dtype": "float32", "shape": [], "tolerance": 0.000001 }, |
| "y_zero_point": { "dtype": "uint8", "shape": [], "tolerance": 0 } |
| } |
| }, |
| { |
| "name": "empty_zero_dim", |
| "inputs": { "x": { "dtype": "float32", "shape": [0], "data": { "kind": "values", "values": [] } } }, |
| "outputs": { |
| "y": { "dtype": "uint8", "shape": [0], "tolerance": 0 }, |
| "y_scale": { "dtype": "float32", "shape": [], "tolerance": 0.0001 }, |
| "y_zero_point": { "dtype": "uint8", "shape": [], "tolerance": 0 } |
| } |
| }, |
| { |
| "name": "ort_caseB_empty", |
| "inputs": { "x": { "dtype": "float32", "shape": [0], "data": { "kind": "values", "values": [] } } }, |
| "outputs": { |
| "y": { "dtype": "uint8", "shape": [0], "data": { "kind": "values", "values": [] }, "tolerance": 0.001 }, |
| "y_scale": { |
| "dtype": "float32", |
| "shape": [], |
| "data": { "kind": "values", "values": [1.0] }, |
| "tolerance": 0.001 |
| }, |
| "y_zero_point": { |
| "dtype": "uint8", |
| "shape": [], |
| "data": { "kind": "values", "values": [0] }, |
| "tolerance": 0.001 |
| } |
| } |
| }, |
| { |
| "name": "grid_stride_reduce_1m_mixed_sign", |
| "provenance": { |
| "notes": "numel = 1048576 >= 262144 selects grid_stride_reduce_vec4: the reduce dispatches a capped min(256, ceil(numel/1024))=256 workgroups, each grid-striding over the whole tensor and writing ONE partial, so the @workgroup_size(1) finalize folds only 256 partials (vs 4096 for the per-block reduce). Validates the grid-stride min/max is bit-identical to the serial reference (y_scale/y_zero_point exact) and that the capped 1D dispatch covers all elements." |
| }, |
| "inputs": { |
| "x": { |
| "dtype": "float32", |
| "shape": [1024, 1024], |
| "data": { "kind": "fillFloat32", "sinStep": 0.013, "cosStep": 0.017, "scale": 3.0 } |
| } |
| }, |
| "outputs": { |
| "y": { "dtype": "uint8", "shape": [1024, 1024], "tolerance": 0 }, |
| "y_scale": { "dtype": "float32", "shape": [], "tolerance": 0.000001 }, |
| "y_zero_point": { "dtype": "uint8", "shape": [], "tolerance": 0 } |
| } |
| }, |
| { |
| "name": "dispatch_cliff_blocks_65536", |
| "provenance": { |
| "notes": "numel = 67108864 = 65536*1024 > 65535*1024 forces the folded block dispatch (x=65535, y=2) in the reduce + quantize passes. Validates blk = wg.x + wg.y*nwg.x AND the new `blk >= numBlocks` reduce-pass early-return that protects the partial_min/max[blk] scratch store from an over-dispatched OOB write. linspace puts the global min/max at the first/last block (the last block lives in the wg.y=1 folded region), so a wrong fold corrupts the scale. Before the 2D fold the plan-time dispatch-limit guard throws." |
| }, |
| "inputs": { |
| "x": { "dtype": "float32", "shape": [67108864], "data": { "kind": "linspace", "start": -1.0, "end": 1.0 } } |
| }, |
| "outputs": { |
| "y": { "dtype": "uint8", "shape": [67108864], "tolerance": 1 }, |
| "y_scale": { "dtype": "float32", "shape": [], "tolerance": 0.000001 }, |
| "y_zero_point": { "dtype": "uint8", "shape": [] } |
| } |
| }, |
| { |
| "name": "grid_stride_reduce_clean_int_262145", |
| "inputs": { |
| "x": { |
| "dtype": "float32", |
| "shape": [262145], |
| "data": { "kind": "cycle", "values": [0.0, 32.0, 64.0, 96.0, 128.0, 160.0, 192.0, 224.0, 255.0] } |
| } |
| }, |
| "outputs": { |
| "y": { "dtype": "uint8", "shape": [262145], "tolerance": 0 }, |
| "y_scale": { "dtype": "float32", "shape": [], "tolerance": 0 }, |
| "y_zero_point": { "dtype": "uint8", "shape": [], "tolerance": 0 } |
| } |
| }, |
| { |
| "name": "non_vec4_large_finalize_fold_mixed_sign_corrected_division", |
| "provenance": { |
| "notes": "Regression for cross-backend f32 division: raw and fma-residual quotients disagreed with correctly-rounded ORT at half-integer boundaries on Metal and shifted the zero point on Intel D3D. The backend-independent integer significand fallback must keep this odd-sized grid-stride path bit-exact." |
| }, |
| "inputs": { |
| "x": { |
| "dtype": "float32", |
| "shape": [4194305], |
| "data": { "kind": "fillFloat32", "sinStep": 0.013, "cosStep": 0.017, "scale": 3.0 } |
| } |
| }, |
| "outputs": { |
| "y": { "dtype": "uint8", "shape": [4194305], "tolerance": 0 }, |
| "y_scale": { "dtype": "float32", "shape": [], "tolerance": 0.000001 }, |
| "y_zero_point": { "dtype": "uint8", "shape": [], "tolerance": 0 } |
| } |
| }, |
| { |
| "name": "per_token_activation_2d_vec4", |
| "inputs": { |
| "x": { |
| "dtype": "float32", |
| "shape": [3, 4096], |
| "data": { "kind": "fillFloat32", "sinStep": 0.011, "cosStep": 0.019, "scale": 2.5 } |
| } |
| }, |
| "outputs": { |
| "y": { "dtype": "uint8", "shape": [3, 4096], "tolerance": 0 }, |
| "y_scale": { "dtype": "float32", "shape": [], "tolerance": 0.000001 }, |
| "y_zero_point": { "dtype": "uint8", "shape": [], "tolerance": 0 } |
| } |
| }, |
| { |
| "name": "non_vec4_odd_hidden_bridge", |
| "inputs": { |
| "x": { |
| "dtype": "float32", |
| "shape": [2049], |
| "data": { |
| "kind": "cycle", |
| "values": [-1.0, -2.1, -1.3, 2.5, 3.34, 4.0, -0.25, 7.75, -0.001, 6.5, -2.75, 5.125, -3.5] |
| } |
| } |
| }, |
| "outputs": { |
| "y": { "dtype": "uint8", "shape": [2049], "tolerance": 0 }, |
| "y_scale": { "dtype": "float32", "shape": [], "tolerance": 0.000001 }, |
| "y_zero_point": { "dtype": "uint8", "shape": [], "tolerance": 0 } |
| } |
| }, |
| { |
| "name": "symmetric_half_step_tie_vec4_boundary", |
| "provenance": { |
| "notes": "The scale 2/255 puts the zero-point quotient just below 127.5 after correctly-rounded f32 division. Intel D3D exposed an over-correction that changed zero_point 127 to 128." |
| }, |
| "inputs": { |
| "x": { "dtype": "float32", "shape": [4], "data": { "kind": "values", "values": [-1.0, -0.5, 0.5, 1.0] } } |
| }, |
| "outputs": { |
| "y": { "dtype": "uint8", "shape": [4], "tolerance": 0 }, |
| "y_scale": { "dtype": "float32", "shape": [], "tolerance": 0.000001 }, |
| "y_zero_point": { "dtype": "uint8", "shape": [], "tolerance": 0 } |
| } |
| }, |
| { |
| "name": "intel_d3d_compensated_zero_point_regression", |
| "provenance": { |
| "notes": "Explicit golden companion to symmetric_half_step_tie_vec4_boundary. It catches backend excess-precision or residual-division compensation shifting the correctly-rounded zero point from 127 to 128." |
| }, |
| "inputs": { |
| "x": { |
| "dtype": "float32", |
| "shape": [8], |
| "data": { "kind": "values", "values": [-2.0, -1.0, -0.5, 0.0, 0.5, 1.0, 1.5, 2.0] } |
| } |
| }, |
| "outputs": { |
| "y": { |
| "dtype": "uint8", |
| "shape": [8], |
| "data": { "kind": "values", "values": [0, 63, 95, 127, 159, 191, 223, 254] }, |
| "tolerance": 0 |
| }, |
| "y_scale": { |
| "dtype": "float32", |
| "shape": [], |
| "data": { "kind": "values", "values": [0.01568627543747425] }, |
| "tolerance": 0 |
| }, |
| "y_zero_point": { "dtype": "uint8", "shape": [], "data": { "kind": "values", "values": [127] }, "tolerance": 0 } |
| } |
| }, |
| { |
| "name": "grid_stride_threshold_boundary_vec4_262144", |
| "inputs": { |
| "x": { |
| "dtype": "float32", |
| "shape": [262144], |
| "data": { "kind": "fillFloat32", "sinStep": 0.013, "cosStep": 0.017, "scale": 3.0 } |
| } |
| }, |
| "outputs": { |
| "y": { "dtype": "uint8", "shape": [262144], "tolerance": 0 }, |
| "y_scale": { "dtype": "float32", "shape": [], "tolerance": 0.000001 }, |
| "y_zero_point": { "dtype": "uint8", "shape": [], "tolerance": 0 } |
| } |
| }, |
| { |
| "name": "multidim_non_vec4_parallel_reduce_2d", |
| "inputs": { |
| "x": { |
| "dtype": "float32", |
| "shape": [17, 120], |
| "data": { "kind": "fillFloat32", "sinStep": 0.031, "cosStep": 0.023, "scale": 2.0 } |
| } |
| }, |
| "outputs": { |
| "y": { "dtype": "uint8", "shape": [17, 120], "tolerance": 0 }, |
| "y_scale": { "dtype": "float32", "shape": [], "tolerance": 0.000001 }, |
| "y_zero_point": { "dtype": "uint8", "shape": [], "tolerance": 0 } |
| } |
| } |
| ] |
| } |
|
|