sync 6fdf6301e2bb
Browse files
README.md
CHANGED
|
@@ -68,7 +68,7 @@ Some implementation variants require `subgroup-matrix` and `subgroups`. These ar
|
|
| 68 |
- [`metadata.json`](build/webgpu/metadata.json) — kernel metadata (id, digests, per-variant templates, provenance)
|
| 69 |
- [`manifest.json`](build/webgpu/manifest.json) — the op contract (source of truth)
|
| 70 |
- [`test.json`](build/webgpu/test.json) — correctness cases
|
| 71 |
-
- [`bench.json`](build/webgpu/bench.json) — benchmark
|
| 72 |
- [`cast-scalar-x4.wgsl.jinja`](build/webgpu/cast-scalar-x4.wgsl.jinja)
|
| 73 |
- [`matmul-bnb4-gemv.wgsl.jinja`](build/webgpu/matmul-bnb4-gemv.wgsl.jinja)
|
| 74 |
- [`matmul-bnb4-sgmat.wgsl.jinja`](build/webgpu/matmul-bnb4-sgmat.wgsl.jinja)
|
|
@@ -78,7 +78,7 @@ Some implementation variants require `subgroup-matrix` and `subgroups`. These ar
|
|
| 78 |
## Use with `@huggingface/kernels`
|
| 79 |
|
| 80 |
```sh
|
| 81 |
-
npm install --save-exact @huggingface/kernels@0.0.1-preview.
|
| 82 |
```
|
| 83 |
|
| 84 |
Required output shapes and logical data types are inferred from the supplied inputs and attributes; result tensors are allocated automatically.
|
|
|
|
| 68 |
- [`metadata.json`](build/webgpu/metadata.json) — kernel metadata (id, digests, per-variant templates, provenance)
|
| 69 |
- [`manifest.json`](build/webgpu/manifest.json) — the op contract (source of truth)
|
| 70 |
- [`test.json`](build/webgpu/test.json) — correctness cases
|
| 71 |
+
- [`bench.json`](build/webgpu/bench.json) — benchmark cases
|
| 72 |
- [`cast-scalar-x4.wgsl.jinja`](build/webgpu/cast-scalar-x4.wgsl.jinja)
|
| 73 |
- [`matmul-bnb4-gemv.wgsl.jinja`](build/webgpu/matmul-bnb4-gemv.wgsl.jinja)
|
| 74 |
- [`matmul-bnb4-sgmat.wgsl.jinja`](build/webgpu/matmul-bnb4-sgmat.wgsl.jinja)
|
|
|
|
| 78 |
## Use with `@huggingface/kernels`
|
| 79 |
|
| 80 |
```sh
|
| 81 |
+
npm install --save-exact @huggingface/kernels@0.0.1-preview.3
|
| 82 |
```
|
| 83 |
|
| 84 |
Required output shapes and logical data types are inferred from the supplied inputs and attributes; result tensors are allocated automatically.
|
build/webgpu/bench.json
CHANGED
|
@@ -122,7 +122,7 @@
|
|
| 122 |
{
|
| 123 |
"name": "bnb4-nf4-speculative-m15-k4096-n4096-b64-band",
|
| 124 |
"provenance": {
|
| 125 |
-
"notes": "
|
| 126 |
},
|
| 127 |
"preset": "model",
|
| 128 |
"vars": { "M": 15, "K": 4096, "N": 4096, "blockSize": 64 },
|
|
|
|
| 122 |
{
|
| 123 |
"name": "bnb4-nf4-speculative-m15-k4096-n4096-b64-band",
|
| 124 |
"provenance": {
|
| 125 |
+
"notes": "Measures a 15-row NF4 multiply (K=4096, N=4096, block size 64), the verification width of a speculative decoder. `bnb4-nf4-speculative-m16-k4096-n4096-b64-tile-floor-control` is the same multiply with 16 rows."
|
| 126 |
},
|
| 127 |
"preset": "model",
|
| 128 |
"vars": { "M": 15, "K": 4096, "N": 4096, "blockSize": 64 },
|
build/webgpu/manifest.json
CHANGED
|
@@ -72,6 +72,21 @@
|
|
| 72 |
"sgmatWidenOutBytes": "dim(shapes.aT, 0) * attrs.N * 4",
|
| 73 |
"sgmatWidenFits": "sgmatWidenBytes <= device.limits.maxStorageBufferBindingSize and sgmatWidenBytes <= device.limits.maxBufferSize and sgmatWidenOutBytes <= device.limits.maxStorageBufferBindingSize and sgmatWidenOutBytes <= device.limits.maxBufferSize",
|
| 74 |
"quantType": "attrs.quant_type",
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 75 |
"ABSMAX_LEN": "ceilDiv(attrs.N * attrs.K, attrs.block_size)",
|
| 76 |
"stagedGeometryValid": "tunables.SGMAT_TILE_COLS >= sgmatSubCols and tunables.SGMAT_TILE_COLS % sgmatSubCols == 0 and tunables.SGMAT_TILE_K >= sgmatMatrixSize and tunables.SGMAT_TILE_K % sgmatMatrixSize == 0",
|
| 77 |
"stagedRowSubtiles": "max(1, min(sgmatRowSubtiles, pow2ceil(ceilDiv(dim(shapes.aT, 0), sgmatMatrixSize)), floor(deviceWorkgroupCap / (32 * max(1, sgmatColSubtiles))), floor(tunables.SGMAT_TILE_K / sgmatMatrixSize), floor((device.limits.maxComputeWorkgroupStorageSize - sgmatWorkgroupStorageBytes) / (4 * sgmatMatrixSize * max(1, tunables.SGMAT_TILE_K)))))",
|
|
@@ -98,17 +113,11 @@
|
|
| 98 |
"hybridResourcesFit": "prefixResourcesFit and hybridStorageBytes <= device.limits.maxComputeWorkgroupStorageSize and hybridDispatchRows <= min(device.limits.maxComputeWorkgroupsPerDimension, 65535)"
|
| 99 |
},
|
| 100 |
"bindings": {
|
| 101 |
-
"a": { "arg": "aT", "
|
| 102 |
-
"b": { "arg": "bT", "
|
| 103 |
-
"absmax": {
|
| 104 |
-
|
| 105 |
-
"buffer": "read-only-storage",
|
| 106 |
-
"elementType": "$absmaxScalar",
|
| 107 |
-
"length": "$ABSMAX_LEN"
|
| 108 |
-
},
|
| 109 |
-
"y": { "arg": "yT", "buffer": "storage", "elementType": "$aScalar" },
|
| 110 |
"params": {
|
| 111 |
-
"buffer": "uniform",
|
| 112 |
"struct": [
|
| 113 |
{ "name": "rows", "type": "u32", "value": "dim(shapes.aT, 0)" },
|
| 114 |
{ "name": "K", "type": "u32", "value": "attrs.K" },
|
|
@@ -128,24 +137,9 @@
|
|
| 128 |
"subgroupMatrixConfigs": [{ "componentType": "f32", "resultComponentType": "f32", "M": 8, "N": 8, "K": 8 }]
|
| 129 |
},
|
| 130 |
"derive": {
|
| 131 |
-
"K": "attrs.K",
|
| 132 |
-
"N": "attrs.N",
|
| 133 |
-
"blockSize": "attrs.block_size",
|
| 134 |
"tileRows": "prefixTileRows",
|
| 135 |
-
"tileCols": "tunables.SGMAT_TILE_COLS",
|
| 136 |
-
"tileK": "tunables.SGMAT_TILE_K",
|
| 137 |
"subRows": "prefixTileRows / sgmatRowSubtiles",
|
| 138 |
-
"subCols": "sgmatSubCols",
|
| 139 |
-
"matrixSize": "sgmatMatrixSize",
|
| 140 |
"rowMatrices": "prefixTileRows / (sgmatRowSubtiles * sgmatMatrixSize)",
|
| 141 |
-
"colMatrices": "sgmatSubCols / sgmatMatrixSize",
|
| 142 |
-
"loadWidth": "sgmatLoadWidth",
|
| 143 |
-
"rowSubtiles": "sgmatRowSubtiles",
|
| 144 |
-
"workgroupSize": "sgmatWorkgroupSize",
|
| 145 |
-
"bLoadsPerRow": "sgmatBLoadsPerRow",
|
| 146 |
-
"aScalar": "\"f32\"",
|
| 147 |
-
"usesF16": false,
|
| 148 |
-
"absmaxScalar": "\"f16\" if tensorDtypes.absmaxT == \"float16\" else \"f32\"",
|
| 149 |
"hybridRows": true,
|
| 150 |
"rowCount": "dim(shapes.aT, 0)",
|
| 151 |
"fullDispatchRows": "sgmatFullRows / prefixTileRows",
|
|
@@ -170,28 +164,12 @@
|
|
| 170 |
"subgroupMatrixConfigs": [{ "componentType": "f32", "resultComponentType": "f32", "M": 8, "N": 8, "K": 8 }]
|
| 171 |
},
|
| 172 |
"derive": {
|
| 173 |
-
"K": "attrs.K",
|
| 174 |
-
"N": "attrs.N",
|
| 175 |
-
"blockSize": "attrs.block_size",
|
| 176 |
"tileRows": "prefixTileRows",
|
| 177 |
-
"tileCols": "tunables.SGMAT_TILE_COLS",
|
| 178 |
-
"tileK": "tunables.SGMAT_TILE_K",
|
| 179 |
"subRows": "prefixTileRows / sgmatRowSubtiles",
|
| 180 |
-
"subCols": "sgmatSubCols",
|
| 181 |
-
"matrixSize": "sgmatMatrixSize",
|
| 182 |
"rowMatrices": "prefixTileRows / (sgmatRowSubtiles * sgmatMatrixSize)",
|
| 183 |
-
"colMatrices": "sgmatSubCols / sgmatMatrixSize",
|
| 184 |
-
"loadWidth": "sgmatLoadWidth",
|
| 185 |
-
"rowSubtiles": "sgmatRowSubtiles",
|
| 186 |
-
"workgroupSize": "sgmatWorkgroupSize",
|
| 187 |
-
"bLoadsPerRow": "sgmatBLoadsPerRow",
|
| 188 |
"aScalar": "\"f32\"",
|
| 189 |
-
"usesF16": true,
|
| 190 |
-
"absmaxScalar": "\"f16\" if tensorDtypes.absmaxT == \"float16\" else \"f32\"",
|
| 191 |
"srcScalar": "\"f16\"",
|
| 192 |
"outScalar": "\"f32\"",
|
| 193 |
-
"wrapNarrowInt": false,
|
| 194 |
-
"wrapSigned": false,
|
| 195 |
"hybridRows": true,
|
| 196 |
"rowCount": "dim(shapes.aT, 0)",
|
| 197 |
"fullDispatchRows": "sgmatFullRows / prefixTileRows",
|
|
@@ -256,24 +234,13 @@
|
|
| 256 |
"subgroupMatrixConfigs": [{ "componentType": "f32", "resultComponentType": "f32", "M": 8, "N": 8, "K": 8 }]
|
| 257 |
},
|
| 258 |
"derive": {
|
| 259 |
-
"K": "attrs.K",
|
| 260 |
-
"N": "attrs.N",
|
| 261 |
-
"blockSize": "attrs.block_size",
|
| 262 |
"tileRows": "stagedTileRows",
|
| 263 |
-
"tileCols": "tunables.SGMAT_TILE_COLS",
|
| 264 |
-
"tileK": "tunables.SGMAT_TILE_K",
|
| 265 |
"subRows": "sgmatMatrixSize",
|
| 266 |
"subCols": "stagedSubCols",
|
| 267 |
-
"matrixSize": "sgmatMatrixSize",
|
| 268 |
"rowMatrices": 1,
|
| 269 |
"colMatrices": "stagedColumnMatrices",
|
| 270 |
-
"loadWidth": "sgmatLoadWidth",
|
| 271 |
"rowSubtiles": "stagedRowSubtiles",
|
| 272 |
"workgroupSize": "stagedWorkgroupSize",
|
| 273 |
-
"bLoadsPerRow": "sgmatBLoadsPerRow",
|
| 274 |
-
"aScalar": "\"f16\" if tensorDtypes.aT == \"float16\" else \"f32\"",
|
| 275 |
-
"usesF16": "tensorDtypes.aT == \"float16\"",
|
| 276 |
-
"absmaxScalar": "\"f16\" if tensorDtypes.absmaxT == \"float16\" else \"f32\"",
|
| 277 |
"stageActivations": true,
|
| 278 |
"rowCount": "dim(shapes.aT, 0)"
|
| 279 |
},
|
|
@@ -290,12 +257,7 @@
|
|
| 290 |
"id": "gemv",
|
| 291 |
"priority": 20,
|
| 292 |
"when": ["gemvShapeValid", "portableWorkgroupFits"],
|
| 293 |
-
"derive": {
|
| 294 |
-
"workgroupSize": "portableWorkgroupSize",
|
| 295 |
-
"aScalar": "\"f16\" if tensorDtypes.aT == \"float16\" else \"f32\"",
|
| 296 |
-
"usesF16": "tensorDtypes.aT == \"float16\"",
|
| 297 |
-
"absmaxScalar": "\"f16\" if tensorDtypes.absmaxT == \"float16\" else \"f32\""
|
| 298 |
-
},
|
| 299 |
"passes": [
|
| 300 |
{
|
| 301 |
"id": "main",
|
|
@@ -328,24 +290,9 @@
|
|
| 328 |
"subgroupMatrixConfigs": [{ "componentType": "f32", "resultComponentType": "f32", "M": 8, "N": 8, "K": 8 }]
|
| 329 |
},
|
| 330 |
"derive": {
|
| 331 |
-
"K": "attrs.K",
|
| 332 |
-
"N": "attrs.N",
|
| 333 |
-
"blockSize": "attrs.block_size",
|
| 334 |
"tileRows": "sgmatTileRows",
|
| 335 |
-
"tileCols": "tunables.SGMAT_TILE_COLS",
|
| 336 |
-
"tileK": "tunables.SGMAT_TILE_K",
|
| 337 |
"subRows": "sgmatSubRows",
|
| 338 |
-
"
|
| 339 |
-
"matrixSize": "sgmatMatrixSize",
|
| 340 |
-
"rowMatrices": "sgmatSubRows / sgmatMatrixSize",
|
| 341 |
-
"colMatrices": "sgmatSubCols / sgmatMatrixSize",
|
| 342 |
-
"loadWidth": "sgmatLoadWidth",
|
| 343 |
-
"rowSubtiles": "sgmatRowSubtiles",
|
| 344 |
-
"workgroupSize": "sgmatWorkgroupSize",
|
| 345 |
-
"bLoadsPerRow": "sgmatBLoadsPerRow",
|
| 346 |
-
"aScalar": "\"f32\"",
|
| 347 |
-
"usesF16": false,
|
| 348 |
-
"absmaxScalar": "\"f16\" if tensorDtypes.absmaxT == \"float16\" else \"f32\""
|
| 349 |
},
|
| 350 |
"passes": [
|
| 351 |
{
|
|
@@ -366,28 +313,12 @@
|
|
| 366 |
"subgroupMatrixConfigs": [{ "componentType": "f32", "resultComponentType": "f32", "M": 8, "N": 8, "K": 8 }]
|
| 367 |
},
|
| 368 |
"derive": {
|
| 369 |
-
"K": "attrs.K",
|
| 370 |
-
"N": "attrs.N",
|
| 371 |
-
"blockSize": "attrs.block_size",
|
| 372 |
"tileRows": "sgmatTileRows",
|
| 373 |
-
"tileCols": "tunables.SGMAT_TILE_COLS",
|
| 374 |
-
"tileK": "tunables.SGMAT_TILE_K",
|
| 375 |
"subRows": "sgmatSubRows",
|
| 376 |
-
"subCols": "sgmatSubCols",
|
| 377 |
-
"matrixSize": "sgmatMatrixSize",
|
| 378 |
"rowMatrices": "sgmatSubRows / sgmatMatrixSize",
|
| 379 |
-
"colMatrices": "sgmatSubCols / sgmatMatrixSize",
|
| 380 |
-
"loadWidth": "sgmatLoadWidth",
|
| 381 |
-
"rowSubtiles": "sgmatRowSubtiles",
|
| 382 |
-
"workgroupSize": "sgmatWorkgroupSize",
|
| 383 |
-
"bLoadsPerRow": "sgmatBLoadsPerRow",
|
| 384 |
"aScalar": "\"f32\"",
|
| 385 |
-
"usesF16": true,
|
| 386 |
-
"absmaxScalar": "\"f16\" if tensorDtypes.absmaxT == \"float16\" else \"f32\"",
|
| 387 |
"srcScalar": "\"f16\"",
|
| 388 |
-
"outScalar": "\"f32\""
|
| 389 |
-
"wrapNarrowInt": false,
|
| 390 |
-
"wrapSigned": false
|
| 391 |
},
|
| 392 |
"intermediates": [
|
| 393 |
{ "id": "aF32", "dtype": "float32", "shape": "[numel(shapes.aT)]" },
|
|
@@ -443,13 +374,7 @@
|
|
| 443 |
"id": "tiled",
|
| 444 |
"priority": 10,
|
| 445 |
"when": ["tileEligible", "tileWorkgroupFits"],
|
| 446 |
-
"derive": {
|
| 447 |
-
"tileK": "tunables.PORTABLE_TILE_K",
|
| 448 |
-
"aScalar": "\"f16\" if tensorDtypes.aT == \"float16\" else \"f32\"",
|
| 449 |
-
"usesF16": "tensorDtypes.aT == \"float16\"",
|
| 450 |
-
"absmaxScalar": "\"f16\" if tensorDtypes.absmaxT == \"float16\" else \"f32\"",
|
| 451 |
-
"tileRows": "portableTileRows"
|
| 452 |
-
},
|
| 453 |
"passes": [
|
| 454 |
{
|
| 455 |
"id": "main",
|
|
@@ -463,12 +388,7 @@
|
|
| 463 |
"id": "scalar",
|
| 464 |
"priority": 0,
|
| 465 |
"when": ["commonShapeValid", "portableWorkgroupSize > 0"],
|
| 466 |
-
"derive": {
|
| 467 |
-
"workgroupSize": "portableWorkgroupSize",
|
| 468 |
-
"aScalar": "\"f16\" if tensorDtypes.aT == \"float16\" else \"f32\"",
|
| 469 |
-
"usesF16": "tensorDtypes.aT == \"float16\"",
|
| 470 |
-
"absmaxScalar": "\"f16\" if tensorDtypes.absmaxT == \"float16\" else \"f32\""
|
| 471 |
-
},
|
| 472 |
"passes": [
|
| 473 |
{
|
| 474 |
"id": "main",
|
|
|
|
| 72 |
"sgmatWidenOutBytes": "dim(shapes.aT, 0) * attrs.N * 4",
|
| 73 |
"sgmatWidenFits": "sgmatWidenBytes <= device.limits.maxStorageBufferBindingSize and sgmatWidenBytes <= device.limits.maxBufferSize and sgmatWidenOutBytes <= device.limits.maxStorageBufferBindingSize and sgmatWidenOutBytes <= device.limits.maxBufferSize",
|
| 74 |
"quantType": "attrs.quant_type",
|
| 75 |
+
"K": "attrs.K",
|
| 76 |
+
"N": "attrs.N",
|
| 77 |
+
"blockSize": "attrs.block_size",
|
| 78 |
+
"tileCols": "tunables.SGMAT_TILE_COLS",
|
| 79 |
+
"tileK": "tunables.SGMAT_TILE_K",
|
| 80 |
+
"matrixSize": "sgmatMatrixSize",
|
| 81 |
+
"subCols": "sgmatSubCols",
|
| 82 |
+
"colMatrices": "sgmatSubCols / sgmatMatrixSize",
|
| 83 |
+
"loadWidth": "sgmatLoadWidth",
|
| 84 |
+
"rowSubtiles": "sgmatRowSubtiles",
|
| 85 |
+
"workgroupSize": "sgmatWorkgroupSize",
|
| 86 |
+
"bLoadsPerRow": "sgmatBLoadsPerRow",
|
| 87 |
+
"aScalar": "\"f16\" if tensorDtypes.aT == \"float16\" else \"f32\"",
|
| 88 |
+
"usesF16": "tensorDtypes.aT == \"float16\"",
|
| 89 |
+
"absmaxScalar": "\"f16\" if tensorDtypes.absmaxT == \"float16\" else \"f32\"",
|
| 90 |
"ABSMAX_LEN": "ceilDiv(attrs.N * attrs.K, attrs.block_size)",
|
| 91 |
"stagedGeometryValid": "tunables.SGMAT_TILE_COLS >= sgmatSubCols and tunables.SGMAT_TILE_COLS % sgmatSubCols == 0 and tunables.SGMAT_TILE_K >= sgmatMatrixSize and tunables.SGMAT_TILE_K % sgmatMatrixSize == 0",
|
| 92 |
"stagedRowSubtiles": "max(1, min(sgmatRowSubtiles, pow2ceil(ceilDiv(dim(shapes.aT, 0), sgmatMatrixSize)), floor(deviceWorkgroupCap / (32 * max(1, sgmatColSubtiles))), floor(tunables.SGMAT_TILE_K / sgmatMatrixSize), floor((device.limits.maxComputeWorkgroupStorageSize - sgmatWorkgroupStorageBytes) / (4 * sgmatMatrixSize * max(1, tunables.SGMAT_TILE_K)))))",
|
|
|
|
| 113 |
"hybridResourcesFit": "prefixResourcesFit and hybridStorageBytes <= device.limits.maxComputeWorkgroupStorageSize and hybridDispatchRows <= min(device.limits.maxComputeWorkgroupsPerDimension, 65535)"
|
| 114 |
},
|
| 115 |
"bindings": {
|
| 116 |
+
"a": { "arg": "aT", "elementType": "$aScalar" },
|
| 117 |
+
"b": { "arg": "bT", "elementType": "u32" },
|
| 118 |
+
"absmax": { "arg": "absmaxT", "elementType": "$absmaxScalar", "length": "$ABSMAX_LEN" },
|
| 119 |
+
"y": { "arg": "yT", "elementType": "$aScalar" },
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 120 |
"params": {
|
|
|
|
| 121 |
"struct": [
|
| 122 |
{ "name": "rows", "type": "u32", "value": "dim(shapes.aT, 0)" },
|
| 123 |
{ "name": "K", "type": "u32", "value": "attrs.K" },
|
|
|
|
| 137 |
"subgroupMatrixConfigs": [{ "componentType": "f32", "resultComponentType": "f32", "M": 8, "N": 8, "K": 8 }]
|
| 138 |
},
|
| 139 |
"derive": {
|
|
|
|
|
|
|
|
|
|
| 140 |
"tileRows": "prefixTileRows",
|
|
|
|
|
|
|
| 141 |
"subRows": "prefixTileRows / sgmatRowSubtiles",
|
|
|
|
|
|
|
| 142 |
"rowMatrices": "prefixTileRows / (sgmatRowSubtiles * sgmatMatrixSize)",
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 143 |
"hybridRows": true,
|
| 144 |
"rowCount": "dim(shapes.aT, 0)",
|
| 145 |
"fullDispatchRows": "sgmatFullRows / prefixTileRows",
|
|
|
|
| 164 |
"subgroupMatrixConfigs": [{ "componentType": "f32", "resultComponentType": "f32", "M": 8, "N": 8, "K": 8 }]
|
| 165 |
},
|
| 166 |
"derive": {
|
|
|
|
|
|
|
|
|
|
| 167 |
"tileRows": "prefixTileRows",
|
|
|
|
|
|
|
| 168 |
"subRows": "prefixTileRows / sgmatRowSubtiles",
|
|
|
|
|
|
|
| 169 |
"rowMatrices": "prefixTileRows / (sgmatRowSubtiles * sgmatMatrixSize)",
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 170 |
"aScalar": "\"f32\"",
|
|
|
|
|
|
|
| 171 |
"srcScalar": "\"f16\"",
|
| 172 |
"outScalar": "\"f32\"",
|
|
|
|
|
|
|
| 173 |
"hybridRows": true,
|
| 174 |
"rowCount": "dim(shapes.aT, 0)",
|
| 175 |
"fullDispatchRows": "sgmatFullRows / prefixTileRows",
|
|
|
|
| 234 |
"subgroupMatrixConfigs": [{ "componentType": "f32", "resultComponentType": "f32", "M": 8, "N": 8, "K": 8 }]
|
| 235 |
},
|
| 236 |
"derive": {
|
|
|
|
|
|
|
|
|
|
| 237 |
"tileRows": "stagedTileRows",
|
|
|
|
|
|
|
| 238 |
"subRows": "sgmatMatrixSize",
|
| 239 |
"subCols": "stagedSubCols",
|
|
|
|
| 240 |
"rowMatrices": 1,
|
| 241 |
"colMatrices": "stagedColumnMatrices",
|
|
|
|
| 242 |
"rowSubtiles": "stagedRowSubtiles",
|
| 243 |
"workgroupSize": "stagedWorkgroupSize",
|
|
|
|
|
|
|
|
|
|
|
|
|
| 244 |
"stageActivations": true,
|
| 245 |
"rowCount": "dim(shapes.aT, 0)"
|
| 246 |
},
|
|
|
|
| 257 |
"id": "gemv",
|
| 258 |
"priority": 20,
|
| 259 |
"when": ["gemvShapeValid", "portableWorkgroupFits"],
|
| 260 |
+
"derive": { "workgroupSize": "portableWorkgroupSize" },
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 261 |
"passes": [
|
| 262 |
{
|
| 263 |
"id": "main",
|
|
|
|
| 290 |
"subgroupMatrixConfigs": [{ "componentType": "f32", "resultComponentType": "f32", "M": 8, "N": 8, "K": 8 }]
|
| 291 |
},
|
| 292 |
"derive": {
|
|
|
|
|
|
|
|
|
|
| 293 |
"tileRows": "sgmatTileRows",
|
|
|
|
|
|
|
| 294 |
"subRows": "sgmatSubRows",
|
| 295 |
+
"rowMatrices": "sgmatSubRows / sgmatMatrixSize"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 296 |
},
|
| 297 |
"passes": [
|
| 298 |
{
|
|
|
|
| 313 |
"subgroupMatrixConfigs": [{ "componentType": "f32", "resultComponentType": "f32", "M": 8, "N": 8, "K": 8 }]
|
| 314 |
},
|
| 315 |
"derive": {
|
|
|
|
|
|
|
|
|
|
| 316 |
"tileRows": "sgmatTileRows",
|
|
|
|
|
|
|
| 317 |
"subRows": "sgmatSubRows",
|
|
|
|
|
|
|
| 318 |
"rowMatrices": "sgmatSubRows / sgmatMatrixSize",
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 319 |
"aScalar": "\"f32\"",
|
|
|
|
|
|
|
| 320 |
"srcScalar": "\"f16\"",
|
| 321 |
+
"outScalar": "\"f32\""
|
|
|
|
|
|
|
| 322 |
},
|
| 323 |
"intermediates": [
|
| 324 |
{ "id": "aF32", "dtype": "float32", "shape": "[numel(shapes.aT)]" },
|
|
|
|
| 374 |
"id": "tiled",
|
| 375 |
"priority": 10,
|
| 376 |
"when": ["tileEligible", "tileWorkgroupFits"],
|
| 377 |
+
"derive": { "tileK": "tunables.PORTABLE_TILE_K", "tileRows": "portableTileRows" },
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 378 |
"passes": [
|
| 379 |
{
|
| 380 |
"id": "main",
|
|
|
|
| 388 |
"id": "scalar",
|
| 389 |
"priority": 0,
|
| 390 |
"when": ["commonShapeValid", "portableWorkgroupSize > 0"],
|
| 391 |
+
"derive": { "workgroupSize": "portableWorkgroupSize" },
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 392 |
"passes": [
|
| 393 |
{
|
| 394 |
"id": "main",
|
build/webgpu/matmul-bnb4-gemv.wgsl.jinja
CHANGED
|
@@ -21,14 +21,14 @@ var<private> quant_map: array<f32, 16> = array<f32, 16>(
|
|
| 21 |
-0.0, -5.208333333e-03, -0.66666667, -1.0,
|
| 22 |
-0.33333333, -0.5, -0.16666667, -0.25
|
| 23 |
);
|
| 24 |
-
{%
|
| 25 |
var<private> quant_map: array<f32, 16> = array<f32, 16>(
|
| 26 |
-1.0, -0.6961928009986877, -0.5250730514526367, -0.39491748809814453,
|
| 27 |
-0.28444138169288635, -0.18477343022823334, -0.09105003625154495, 0.0,
|
| 28 |
0.07958029955625534, 0.16093020141124725, 0.24611230194568634, 0.33791524171829224,
|
| 29 |
0.44070982933044434, 0.5626170039176941, 0.7229568362236023, 1.0
|
| 30 |
);
|
| 31 |
-
{%
|
| 32 |
|
| 33 |
// One dequantized weight at flat index `flat` into the [N, K] weight.
|
| 34 |
fn dequant_weight(flat: u32) -> f32 {
|
|
@@ -37,8 +37,6 @@ fn dequant_weight(flat: u32) -> f32 {
|
|
| 37 |
return quant_map[code] * f32(absmax[flat / params.blockSize]);
|
| 38 |
}
|
| 39 |
|
| 40 |
-
|
| 41 |
-
|
| 42 |
// Decode (M == 1): one workgroup owns each output column, with lanes striding K.
|
| 43 |
// Each lane keeps one accumulator and the workgroup closes with a tree reduction.
|
| 44 |
@compute @workgroup_size(WG, 1, 1)
|
|
|
|
| 21 |
-0.0, -5.208333333e-03, -0.66666667, -1.0,
|
| 22 |
-0.33333333, -0.5, -0.16666667, -0.25
|
| 23 |
);
|
| 24 |
+
{% else %}
|
| 25 |
var<private> quant_map: array<f32, 16> = array<f32, 16>(
|
| 26 |
-1.0, -0.6961928009986877, -0.5250730514526367, -0.39491748809814453,
|
| 27 |
-0.28444138169288635, -0.18477343022823334, -0.09105003625154495, 0.0,
|
| 28 |
0.07958029955625534, 0.16093020141124725, 0.24611230194568634, 0.33791524171829224,
|
| 29 |
0.44070982933044434, 0.5626170039176941, 0.7229568362236023, 1.0
|
| 30 |
);
|
| 31 |
+
{% endif %}
|
| 32 |
|
| 33 |
// One dequantized weight at flat index `flat` into the [N, K] weight.
|
| 34 |
fn dequant_weight(flat: u32) -> f32 {
|
|
|
|
| 37 |
return quant_map[code] * f32(absmax[flat / params.blockSize]);
|
| 38 |
}
|
| 39 |
|
|
|
|
|
|
|
| 40 |
// Decode (M == 1): one workgroup owns each output column, with lanes striding K.
|
| 41 |
// Each lane keeps one accumulator and the workgroup closes with a tree reduction.
|
| 42 |
@compute @workgroup_size(WG, 1, 1)
|
build/webgpu/matmul-bnb4-sgmat.wgsl.jinja
CHANGED
|
@@ -9,7 +9,6 @@
|
|
| 9 |
{% if usesF16 %}
|
| 10 |
// The widened path keeps the activations and the output in f32 for the matrix
|
| 11 |
// units, but the quantization scales stay in the request's own dtype.
|
| 12 |
-
enable f16;
|
| 13 |
{% endif %}
|
| 14 |
enable subgroups;
|
| 15 |
{% if pinSubgroupSize32 %}
|
|
@@ -18,7 +17,6 @@ enable subgroup_size_control;
|
|
| 18 |
enable chromium_experimental_subgroup_matrix;
|
| 19 |
diagnostic(off, chromium.subgroup_matrix_uniformity);
|
| 20 |
|
| 21 |
-
|
| 22 |
{{ env.wgsl.resourceDeclarations }}
|
| 23 |
|
| 24 |
const K: u32 = {{ K }}u;
|
|
@@ -59,17 +57,14 @@ var<private> quant_map: array<f32, 16> = array<f32, 16>(
|
|
| 59 |
-0.0, -5.208333333e-03, -0.66666667, -1.0,
|
| 60 |
-0.33333333, -0.5, -0.16666667, -0.25
|
| 61 |
);
|
| 62 |
-
{%
|
| 63 |
var<private> quant_map: array<f32, 16> = array<f32, 16>(
|
| 64 |
-1.0, -0.6961928009986877, -0.5250730514526367, -0.39491748809814453,
|
| 65 |
-0.28444138169288635, -0.18477343022823334, -0.09105003625154495, 0.0,
|
| 66 |
0.07958029955625534, 0.16093020141124725, 0.24611230194568634, 0.33791524171829224,
|
| 67 |
0.44070982933044434, 0.5626170039176941, 0.7229568362236023, 1.0
|
| 68 |
);
|
| 69 |
-
{%
|
| 70 |
-
|
| 71 |
-
|
| 72 |
-
|
| 73 |
|
| 74 |
fn load_b(tile_base: u32, k_base: u32, row: u32, col_group: u32) {
|
| 75 |
let col = col_group * LOAD_WIDTH;
|
|
|
|
| 9 |
{% if usesF16 %}
|
| 10 |
// The widened path keeps the activations and the output in f32 for the matrix
|
| 11 |
// units, but the quantization scales stay in the request's own dtype.
|
|
|
|
| 12 |
{% endif %}
|
| 13 |
enable subgroups;
|
| 14 |
{% if pinSubgroupSize32 %}
|
|
|
|
| 17 |
enable chromium_experimental_subgroup_matrix;
|
| 18 |
diagnostic(off, chromium.subgroup_matrix_uniformity);
|
| 19 |
|
|
|
|
| 20 |
{{ env.wgsl.resourceDeclarations }}
|
| 21 |
|
| 22 |
const K: u32 = {{ K }}u;
|
|
|
|
| 57 |
-0.0, -5.208333333e-03, -0.66666667, -1.0,
|
| 58 |
-0.33333333, -0.5, -0.16666667, -0.25
|
| 59 |
);
|
| 60 |
+
{% else %}
|
| 61 |
var<private> quant_map: array<f32, 16> = array<f32, 16>(
|
| 62 |
-1.0, -0.6961928009986877, -0.5250730514526367, -0.39491748809814453,
|
| 63 |
-0.28444138169288635, -0.18477343022823334, -0.09105003625154495, 0.0,
|
| 64 |
0.07958029955625534, 0.16093020141124725, 0.24611230194568634, 0.33791524171829224,
|
| 65 |
0.44070982933044434, 0.5626170039176941, 0.7229568362236023, 1.0
|
| 66 |
);
|
| 67 |
+
{% endif %}
|
|
|
|
|
|
|
|
|
|
| 68 |
|
| 69 |
fn load_b(tile_base: u32, k_base: u32, row: u32, col_group: u32) {
|
| 70 |
let col = col_group * LOAD_WIDTH;
|
build/webgpu/matmul-bnb4-tiled.wgsl.jinja
CHANGED
|
@@ -41,15 +41,14 @@ var<private> quant_map: array<f32, 16> = array<f32, 16>(
|
|
| 41 |
-0.0, -5.208333333e-03, -0.66666667, -1.0,
|
| 42 |
-0.33333333, -0.5, -0.16666667, -0.25
|
| 43 |
);
|
| 44 |
-
{%
|
| 45 |
var<private> quant_map: array<f32, 16> = array<f32, 16>(
|
| 46 |
-1.0, -0.6961928009986877, -0.5250730514526367, -0.39491748809814453,
|
| 47 |
-0.28444138169288635, -0.18477343022823334, -0.09105003625154495, 0.0,
|
| 48 |
0.07958029955625534, 0.16093020141124725, 0.24611230194568634, 0.33791524171829224,
|
| 49 |
0.44070982933044434, 0.5626170039176941, 0.7229568362236023, 1.0
|
| 50 |
);
|
| 51 |
-
{%
|
| 52 |
-
|
| 53 |
|
| 54 |
// Four consecutive dequantized weights starting at flat index `flat` into the
|
| 55 |
// [N, K] weight. Consecutive indices share a stored byte, so the run costs two
|
|
@@ -82,7 +81,6 @@ fn dequant_weight4(flat: u32) -> vec4<f32> {
|
|
| 82 |
return vec4<f32>(quant_map[codes.x], quant_map[codes.y], quant_map[codes.z], quant_map[codes.w]) * scales;
|
| 83 |
}
|
| 84 |
|
| 85 |
-
|
| 86 |
@compute @workgroup_size(16, 8, 1)
|
| 87 |
fn main(
|
| 88 |
@builtin(workgroup_id) wg: vec3<u32>,
|
|
|
|
| 41 |
-0.0, -5.208333333e-03, -0.66666667, -1.0,
|
| 42 |
-0.33333333, -0.5, -0.16666667, -0.25
|
| 43 |
);
|
| 44 |
+
{% else %}
|
| 45 |
var<private> quant_map: array<f32, 16> = array<f32, 16>(
|
| 46 |
-1.0, -0.6961928009986877, -0.5250730514526367, -0.39491748809814453,
|
| 47 |
-0.28444138169288635, -0.18477343022823334, -0.09105003625154495, 0.0,
|
| 48 |
0.07958029955625534, 0.16093020141124725, 0.24611230194568634, 0.33791524171829224,
|
| 49 |
0.44070982933044434, 0.5626170039176941, 0.7229568362236023, 1.0
|
| 50 |
);
|
| 51 |
+
{% endif %}
|
|
|
|
| 52 |
|
| 53 |
// Four consecutive dequantized weights starting at flat index `flat` into the
|
| 54 |
// [N, K] weight. Consecutive indices share a stored byte, so the run costs two
|
|
|
|
| 81 |
return vec4<f32>(quant_map[codes.x], quant_map[codes.y], quant_map[codes.z], quant_map[codes.w]) * scales;
|
| 82 |
}
|
| 83 |
|
|
|
|
| 84 |
@compute @workgroup_size(16, 8, 1)
|
| 85 |
fn main(
|
| 86 |
@builtin(workgroup_id) wg: vec3<u32>,
|
build/webgpu/matmul-bnb4.wgsl.jinja
CHANGED
|
@@ -1,3 +1,8 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
{{ env.wgsl.resourceDeclarations }}
|
| 2 |
|
| 3 |
const WG: u32 = {{ workgroupSize }}u;
|
|
@@ -19,14 +24,14 @@ var<private> quant_map: array<f32, 16> = array<f32, 16>(
|
|
| 19 |
-0.0, -5.208333333e-03, -0.66666667, -1.0,
|
| 20 |
-0.33333333, -0.5, -0.16666667, -0.25
|
| 21 |
);
|
| 22 |
-
{%
|
| 23 |
var<private> quant_map: array<f32, 16> = array<f32, 16>(
|
| 24 |
-1.0, -0.6961928009986877, -0.5250730514526367, -0.39491748809814453,
|
| 25 |
-0.28444138169288635, -0.18477343022823334, -0.09105003625154495, 0.0,
|
| 26 |
0.07958029955625534, 0.16093020141124725, 0.24611230194568634, 0.33791524171829224,
|
| 27 |
0.44070982933044434, 0.5626170039176941, 0.7229568362236023, 1.0
|
| 28 |
);
|
| 29 |
-
{%
|
| 30 |
|
| 31 |
// One dequantized weight at flat index `flat` into the [N, K] weight.
|
| 32 |
fn dequant_weight(flat: u32) -> f32 {
|
|
@@ -35,14 +40,9 @@ fn dequant_weight(flat: u32) -> f32 {
|
|
| 35 |
return quant_map[code] * f32(absmax[flat / params.blockSize]);
|
| 36 |
}
|
| 37 |
|
| 38 |
-
|
| 39 |
-
|
| 40 |
@compute @workgroup_size(WG, 1, 1)
|
| 41 |
fn main(@builtin(global_invocation_id) gid: vec3<u32>) {
|
| 42 |
-
|
| 43 |
-
// per-axis dispatch fold width. With no fold this
|
| 44 |
-
// reduces to gid.x; the index >= total guard drops the tail.
|
| 45 |
-
let index = gid.x + gid.y * {{ DISPATCH_FOLD_WIDTH }}u * WG;
|
| 46 |
let total = params.rows * params.N;
|
| 47 |
|
| 48 |
if (index >= total) {
|
|
|
|
| 1 |
+
{% macro flat_index_2d(workgroupSize, name="i", bound="params.count", guardInline=false) %}
|
| 2 |
+
{% set wgTerm = workgroupSize ~ "u" if workgroupSize is number else workgroupSize %}
|
| 3 |
+
// 2D-folded flat index: gid.y carries the high bits past the dispatch's
|
| 4 |
+
// per-axis workgroup fold width.
|
| 5 |
+
let {{ name }} = gid.x + gid.y * {{ DISPATCH_FOLD_WIDTH }}u * {{ wgTerm }};{% endmacro %}
|
| 6 |
{{ env.wgsl.resourceDeclarations }}
|
| 7 |
|
| 8 |
const WG: u32 = {{ workgroupSize }}u;
|
|
|
|
| 24 |
-0.0, -5.208333333e-03, -0.66666667, -1.0,
|
| 25 |
-0.33333333, -0.5, -0.16666667, -0.25
|
| 26 |
);
|
| 27 |
+
{% else %}
|
| 28 |
var<private> quant_map: array<f32, 16> = array<f32, 16>(
|
| 29 |
-1.0, -0.6961928009986877, -0.5250730514526367, -0.39491748809814453,
|
| 30 |
-0.28444138169288635, -0.18477343022823334, -0.09105003625154495, 0.0,
|
| 31 |
0.07958029955625534, 0.16093020141124725, 0.24611230194568634, 0.33791524171829224,
|
| 32 |
0.44070982933044434, 0.5626170039176941, 0.7229568362236023, 1.0
|
| 33 |
);
|
| 34 |
+
{% endif %}
|
| 35 |
|
| 36 |
// One dequantized weight at flat index `flat` into the [N, K] weight.
|
| 37 |
fn dequant_weight(flat: u32) -> f32 {
|
|
|
|
| 40 |
return quant_map[code] * f32(absmax[flat / params.blockSize]);
|
| 41 |
}
|
| 42 |
|
|
|
|
|
|
|
| 43 |
@compute @workgroup_size(WG, 1, 1)
|
| 44 |
fn main(@builtin(global_invocation_id) gid: vec3<u32>) {
|
| 45 |
+
{{ flat_index_2d("WG", "index", "") }}
|
|
|
|
|
|
|
|
|
|
| 46 |
let total = params.rows * params.N;
|
| 47 |
|
| 48 |
if (index >= total) {
|
build/webgpu/metadata.json
CHANGED
|
@@ -1,25 +1,25 @@
|
|
| 1 |
{
|
| 2 |
"name": "com.microsoft.MatMulBnb4",
|
| 3 |
-
"id": "
|
| 4 |
"version": 1,
|
| 5 |
"license": "Apache-2.0",
|
| 6 |
"backend": { "type": "webgpu" },
|
| 7 |
"digest": {
|
| 8 |
"algorithm": "sha256",
|
| 9 |
"files": {
|
| 10 |
-
"bench.json": "/
|
| 11 |
"cast-scalar-x4.wgsl.jinja": "s8Y9E2+D7cFgYTUEJhiuPsUzvHjv2mXVoiRmv0A0vTU=",
|
| 12 |
-
"manifest.json": "
|
| 13 |
-
"matmul-bnb4-gemv.wgsl.jinja": "
|
| 14 |
-
"matmul-bnb4-sgmat.wgsl.jinja": "
|
| 15 |
-
"matmul-bnb4-tiled.wgsl.jinja": "
|
| 16 |
-
"matmul-bnb4.wgsl.jinja": "
|
| 17 |
"test.json": "KPAf0hjucty64auyD+xOS5RAGDEPYeAlUSJPhbig7CA="
|
| 18 |
}
|
| 19 |
},
|
| 20 |
-
"provenance": { "kernel": { "sha": "
|
| 21 |
"webgpu": {
|
| 22 |
-
"manifestSpec": "2.
|
| 23 |
"variants": {
|
| 24 |
"sgmat_hybrid_rows": ["matmul-bnb4-sgmat.wgsl.jinja"],
|
| 25 |
"sgmat_hybrid_rows_widened": ["cast-scalar-x4.wgsl.jinja", "matmul-bnb4-sgmat.wgsl.jinja"],
|
|
|
|
| 1 |
{
|
| 2 |
"name": "com.microsoft.MatMulBnb4",
|
| 3 |
+
"id": "_com_microsoft_matmulbnb4_webgpu_2efe1ae",
|
| 4 |
"version": 1,
|
| 5 |
"license": "Apache-2.0",
|
| 6 |
"backend": { "type": "webgpu" },
|
| 7 |
"digest": {
|
| 8 |
"algorithm": "sha256",
|
| 9 |
"files": {
|
| 10 |
+
"bench.json": "Ixtu6FBToeEWEbpbM/+lGVS3jt0IPtrmZrxRfxo7Uj8=",
|
| 11 |
"cast-scalar-x4.wgsl.jinja": "s8Y9E2+D7cFgYTUEJhiuPsUzvHjv2mXVoiRmv0A0vTU=",
|
| 12 |
+
"manifest.json": "TTpD+bhv4VB93QlNQ4Z2xGHvG4ClFxnokPMIbKMH2Bc=",
|
| 13 |
+
"matmul-bnb4-gemv.wgsl.jinja": "5mV78S/5vyeTFu8anlXAsKA+OVz7iy3fmo990lgf/yU=",
|
| 14 |
+
"matmul-bnb4-sgmat.wgsl.jinja": "A0jgHcIQrjdodubOI3bgHSYU9SsGew+/3IJwkMMr6eo=",
|
| 15 |
+
"matmul-bnb4-tiled.wgsl.jinja": "auoAXKsuYOXVbPmzjXMm6IQ5L1HxzjDWaPTSxD+Wd/s=",
|
| 16 |
+
"matmul-bnb4.wgsl.jinja": "81lKMMKBPnPeNbcFXiZZe4KBGefTeBfNaHH1LSgP/6U=",
|
| 17 |
"test.json": "KPAf0hjucty64auyD+xOS5RAGDEPYeAlUSJPhbig7CA="
|
| 18 |
}
|
| 19 |
},
|
| 20 |
+
"provenance": { "kernel": { "sha": "6fdf6301e2bbcc2f03bf1eaf493b7ad55ef33afc", "dirty": false } },
|
| 21 |
"webgpu": {
|
| 22 |
+
"manifestSpec": "2.1",
|
| 23 |
"variants": {
|
| 24 |
"sgmat_hybrid_rows": ["matmul-bnb4-sgmat.wgsl.jinja"],
|
| 25 |
"sgmat_hybrid_rows_widened": ["cast-scalar-x4.wgsl.jinja", "matmul-bnb4-sgmat.wgsl.jinja"],
|