{ "domain": "ai.onnx", "name": "DynamicQuantizeLinear", "sinceVersion": 11, "inputs": { "x": { "dtype": "T" } }, "outputs": { "y": { "dtype": "TQ", "rank": "ranks.x", "shape": "shapes.x" }, "y_scale": { "dtype": "T", "rank": 0, "shape": [] }, "y_zero_point": { "dtype": "TQ", "rank": 0, "shape": [] } }, "typeConstraints": { "T": ["float32"], "TQ": ["uint8"] }, "tunables": { "WORKGROUP_SIZE": { "default": 256 }, "ELEMENTS_PER_THREAD": { "default": 4 }, "GRID_STRIDE_MIN_ELEMENTS": { "default": 262144 }, "MAX_GRID_PARTIALS": { "default": 256 }, "SERIAL_MAX_ELEMENTS": { "default": 8192 } }, "derive": { "deviceWorkgroupCap": "min(device.limits.maxComputeInvocationsPerWorkgroup, device.limits.maxComputeWorkgroupSizeX)", "storageBufferLimit": "min(device.limits.maxStorageBufferBindingSize, device.limits.maxBufferSize)", "inputCount": "numel(shapes.x)", "elementsPerBlock": "tunables.WORKGROUP_SIZE * tunables.ELEMENTS_PER_THREAD", "fullPartials": "ceilDiv(inputCount, elementsPerBlock)", "gridPartials": "min(tunables.MAX_GRID_PARTIALS, fullPartials)", "baseContract": "ranks.x >= 1 and ranks.y == ranks.x and inputCount == numel(shapes.y) and ranks.y_scale == 0 and ranks.y_zero_point == 0", "serialContract": "ranks.x >= 0 and ranks.y == ranks.x and inputCount == numel(shapes.y) and ranks.y_scale == 0 and ranks.y_zero_point == 0", "parallelDeviceOk": "tunables.WORKGROUP_SIZE <= deviceWorkgroupCap and 8 * tunables.WORKGROUP_SIZE <= device.limits.maxComputeWorkgroupStorageSize", "fullScratchFits": "4 * fullPartials <= storageBufferLimit", "gridScratchFits": "4 * gridPartials <= storageBufferLimit", "fullDispatchFits": "ceilDiv(fullPartials, min(device.limits.maxComputeWorkgroupsPerDimension, 65535)) <= min(device.limits.maxComputeWorkgroupsPerDimension, 65535)", "gridDispatchFits": "gridPartials <= min(device.limits.maxComputeWorkgroupsPerDimension, 65535)", "parallelFullFits": "parallelDeviceOk and fullScratchFits and fullDispatchFits", "parallelGridFits": "parallelDeviceOk and gridScratchFits and gridDispatchFits and fullDispatchFits", "serialFallbackNeeded": "inputCount <= tunables.SERIAL_MAX_ELEMENTS or not parallelFullFits" }, "bindings": { "y": { "buffer": "storage", "elementType": "u32" }, "y_scale": { "buffer": "storage", "elementType": "f32", "length": 1 }, "y_zero_point": { "buffer": "storage", "elementType": "u32", "length": 1 }, "params": { "buffer": "uniform", "struct": [{ "name": "count", "type": "u32", "value": "numel(shapes.x)" }] }, "x_2": { "name": "x", "buffer": "read-only-storage", "elementType": "$inputElement" }, "partial_min": { "buffer": "storage", "elementType": "f32" }, "partial_max": { "buffer": "storage", "elementType": "f32" }, "partial_min_2": { "name": "partial_min", "buffer": "read-only-storage", "elementType": "f32" }, "partial_max_2": { "name": "partial_max", "buffer": "read-only-storage", "elementType": "f32" }, "y_scale_2": { "name": "y_scale", "buffer": "read-only-storage", "elementType": "f32", "length": 1 }, "y_zero_point_2": { "name": "y_zero_point", "buffer": "read-only-storage", "elementType": "u32", "length": 1 } }, "variants": [ { "id": "single_invocation", "when": ["serialContract", "serialFallbackNeeded"], "passes": [ { "id": "main", "name": "DynamicQuantizeLinear", "shader": "dynamic-quantize-linear.wgsl.jinja", "derive": { "fromPartials": false }, "bindings": [{ "arg": "x", "elementType": "f32" }, "y", "y_scale", "y_zero_point", "params"], "dispatch": { "x": 1 } } ] }, { "id": "parallel_subgroup_reduce_vec4", "priority": 11, "when": ["baseContract", "inputCount > 0", "inputCount % 4 == 0", "parallelFullFits"], "derive": { "workgroupSize": "tunables.WORKGROUP_SIZE", "elemsPerThread": "tunables.ELEMENTS_PER_THREAD", "vec4": true, "inputElement": "\"vec4\"", "useSubgroups": "device.features.has(\"subgroups\")" }, "intermediates": [ { "id": "partial_min", "dtype": "float32", "shape": "[fullPartials]" }, { "id": "partial_max", "dtype": "float32", "shape": "[fullPartials]" } ], "passes": [ { "id": "reduce", "name": "DynamicQuantizeLinear.ReduceMinMax", "shader": "dynamic-quantize-linear-reduce.wgsl.jinja", "subgroupCollectivesWidth": "portable", "bindings": ["x_2", "partial_min", "partial_max", "params"], "dispatch": { "x": "min(fullPartials, 65535)", "y": "ceilDiv(fullPartials, 65535)", "z": 1 } }, { "id": "finalize", "name": "DynamicQuantizeLinear.Finalize", "shader": "dynamic-quantize-linear.wgsl.jinja", "derive": { "fromPartials": true }, "bindings": [ "partial_min_2", "partial_max_2", "y_scale", "y_zero_point", { "name": "params", "struct": [{ "name": "numPartials", "type": "u32", "value": "fullPartials" }] } ], "dispatch": { "x": 1 } }, { "id": "quantize", "name": "DynamicQuantizeLinear.Quantize", "shader": "dynamic-quantize-linear-quantize.wgsl.jinja", "bindings": ["x_2", "y_scale_2", "y_zero_point_2", "y", "params"], "dispatch": { "x": "min(ceilDiv((ceilDiv(inputCount, tunables.ELEMENTS_PER_THREAD)), (tunables.WORKGROUP_SIZE)), 65535)", "y": "ceilDiv(ceilDiv((ceilDiv(inputCount, tunables.ELEMENTS_PER_THREAD)), (tunables.WORKGROUP_SIZE)), 65535)", "z": 1 } } ] }, { "id": "parallel_subgroup_reduce", "priority": 10, "when": ["baseContract", "inputCount > 0", "true", "parallelFullFits"], "derive": { "workgroupSize": "tunables.WORKGROUP_SIZE", "elemsPerThread": "tunables.ELEMENTS_PER_THREAD", "vec4": false, "inputElement": "\"f32\"", "useSubgroups": "device.features.has(\"subgroups\")" }, "intermediates": [ { "id": "partial_min", "dtype": "float32", "shape": "[fullPartials]" }, { "id": "partial_max", "dtype": "float32", "shape": "[fullPartials]" } ], "passes": [ { "id": "reduce", "name": "DynamicQuantizeLinear.ReduceMinMax", "shader": "dynamic-quantize-linear-reduce.wgsl.jinja", "subgroupCollectivesWidth": "portable", "bindings": ["x_2", "partial_min", "partial_max", "params"], "dispatch": { "x": "min(fullPartials, 65535)", "y": "ceilDiv(fullPartials, 65535)", "z": 1 } }, { "id": "finalize", "name": "DynamicQuantizeLinear.Finalize", "shader": "dynamic-quantize-linear.wgsl.jinja", "derive": { "fromPartials": true }, "bindings": [ "partial_min_2", "partial_max_2", "y_scale", "y_zero_point", { "name": "params", "struct": [{ "name": "numPartials", "type": "u32", "value": "fullPartials" }] } ], "dispatch": { "x": 1 } }, { "id": "quantize", "name": "DynamicQuantizeLinear.Quantize", "shader": "dynamic-quantize-linear-quantize.wgsl.jinja", "bindings": ["x_2", "y_scale_2", "y_zero_point_2", "y", "params"], "dispatch": { "x": "min(ceilDiv((ceilDiv(inputCount, tunables.ELEMENTS_PER_THREAD)), (tunables.WORKGROUP_SIZE)), 65535)", "y": "ceilDiv(ceilDiv((ceilDiv(inputCount, tunables.ELEMENTS_PER_THREAD)), (tunables.WORKGROUP_SIZE)), 65535)", "z": 1 } } ] }, { "id": "grid_stride_reduce_vec4", "priority": 12, "when": ["baseContract", "inputCount > 0", "inputCount % 4 == 0", "inputCount >= tunables.GRID_STRIDE_MIN_ELEMENTS", "parallelGridFits"], "derive": { "workgroupSize": "tunables.WORKGROUP_SIZE", "elemsPerThread": "tunables.ELEMENTS_PER_THREAD", "vec4": true, "inputElement": "\"vec4\"", "useSubgroups": "device.features.has(\"subgroups\")" }, "intermediates": [ { "id": "partial_min", "dtype": "float32", "shape": "[gridPartials]" }, { "id": "partial_max", "dtype": "float32", "shape": "[gridPartials]" } ], "passes": [ { "id": "reduce", "name": "DynamicQuantizeLinear.ReduceMinMax", "shader": "dynamic-quantize-linear-reduce.wgsl.jinja", "subgroupCollectivesWidth": "portable", "derive": { "gridStride": true }, "bindings": ["x_2", "partial_min", "partial_max", "params"], "dispatch": { "x": "gridPartials" } }, { "id": "finalize", "name": "DynamicQuantizeLinear.Finalize", "shader": "dynamic-quantize-linear.wgsl.jinja", "derive": { "fromPartials": true }, "bindings": [ "partial_min_2", "partial_max_2", "y_scale", "y_zero_point", { "name": "params", "struct": [{ "name": "numPartials", "type": "u32", "value": "gridPartials" }] } ], "dispatch": { "x": 1 } }, { "id": "quantize", "name": "DynamicQuantizeLinear.Quantize", "shader": "dynamic-quantize-linear-quantize.wgsl.jinja", "bindings": ["x_2", "y_scale_2", "y_zero_point_2", "y", "params"], "dispatch": { "x": "min(ceilDiv((ceilDiv(inputCount, tunables.ELEMENTS_PER_THREAD)), (tunables.WORKGROUP_SIZE)), 65535)", "y": "ceilDiv(ceilDiv((ceilDiv(inputCount, tunables.ELEMENTS_PER_THREAD)), (tunables.WORKGROUP_SIZE)), 65535)", "z": 1 } } ] }, { "id": "grid_stride_reduce", "priority": 12, "when": ["baseContract", "inputCount > 0", "inputCount % 4 != 0", "inputCount >= tunables.GRID_STRIDE_MIN_ELEMENTS", "parallelGridFits"], "derive": { "workgroupSize": "tunables.WORKGROUP_SIZE", "elemsPerThread": "tunables.ELEMENTS_PER_THREAD", "vec4": false, "inputElement": "\"f32\"", "useSubgroups": "device.features.has(\"subgroups\")" }, "intermediates": [ { "id": "partial_min", "dtype": "float32", "shape": "[gridPartials]" }, { "id": "partial_max", "dtype": "float32", "shape": "[gridPartials]" } ], "passes": [ { "id": "reduce", "name": "DynamicQuantizeLinear.ReduceMinMax", "shader": "dynamic-quantize-linear-reduce.wgsl.jinja", "subgroupCollectivesWidth": "portable", "derive": { "gridStride": true }, "bindings": ["x_2", "partial_min", "partial_max", "params"], "dispatch": { "x": "gridPartials" } }, { "id": "finalize", "name": "DynamicQuantizeLinear.Finalize", "shader": "dynamic-quantize-linear.wgsl.jinja", "derive": { "fromPartials": true }, "bindings": [ "partial_min_2", "partial_max_2", "y_scale", "y_zero_point", { "name": "params", "struct": [{ "name": "numPartials", "type": "u32", "value": "gridPartials" }] } ], "dispatch": { "x": 1 } }, { "id": "quantize", "name": "DynamicQuantizeLinear.Quantize", "shader": "dynamic-quantize-linear-quantize.wgsl.jinja", "bindings": ["x_2", "y_scale_2", "y_zero_point_2", "y", "params"], "dispatch": { "x": "min(ceilDiv((ceilDiv(inputCount, tunables.ELEMENTS_PER_THREAD)), (tunables.WORKGROUP_SIZE)), 65535)", "y": "ceilDiv(ceilDiv((ceilDiv(inputCount, tunables.ELEMENTS_PER_THREAD)), (tunables.WORKGROUP_SIZE)), 65535)", "z": 1 } } ] } ] }