Xenova HF Staff commited on
Commit
bb904f8
·
verified ·
1 Parent(s): e3afe0f

sync 91d990483a17

Browse files
README.md CHANGED
@@ -18,15 +18,15 @@ See the [ONNX `BitwiseNot` spec](https://onnx.ai/onnx/operators/onnx__BitwiseNot
18
 
19
  ## Inputs
20
 
21
- | Name | Bind key | Logical dtype | Rank | Shape | Description | Presence |
22
  | --- | --- | --- | --- | --- | --- | --- |
23
- | `X` | `x` | `T` | — | — | Input integer tensor. | required |
24
 
25
  ## Outputs
26
 
27
- | Name | Bind key | Logical dtype | Rank | Shape | Description | Presence |
28
  | --- | --- | --- | --- | --- | --- | --- |
29
- | `Y` | `y` | `T` | same as `X` | same as `X` | Output tensor with each element bitwise-negated; same shape and dtype as `X`. | required |
30
 
31
  ## Type constraints
32
 
@@ -36,7 +36,7 @@ See the [ONNX `BitwiseNot` spec](https://onnx.ai/onnx/operators/onnx__BitwiseNot
36
 
37
  ## Files
38
 
39
- - [`metadata.json`](build/webgpu/metadata.json) — kernel metadata (id, digests, provenance)
40
  - [`manifest.json`](build/webgpu/manifest.json) — the op contract (source of truth)
41
  - [`test.json`](build/webgpu/test.json) — correctness cases
42
  - [`bench.json`](build/webgpu/bench.json) — benchmark + tuning cases
@@ -44,10 +44,14 @@ See the [ONNX `BitwiseNot` spec](https://onnx.ai/onnx/operators/onnx__BitwiseNot
44
 
45
  ## Use with `@huggingface/kernels`
46
 
47
- The loader derives every required output's shape and logical dtype from the manifest contract and this call.
48
- It then allocates the result tensors automatically.
 
 
 
49
 
50
  The `version: 1` option selects the published kernel contract; it is independent of any operator opset, contrib `since_version`, or model version.
 
51
 
52
  Replace each `*Data` placeholder with a typed array containing the corresponding input data.
53
 
 
18
 
19
  ## Inputs
20
 
21
+ | Name | Upstream name | Logical dtype | Rank | Shape | Description | Presence |
22
  | --- | --- | --- | --- | --- | --- | --- |
23
+ | `x` | `X` | `T` | — | — | Input integer tensor. | required |
24
 
25
  ## Outputs
26
 
27
+ | Name | Upstream name | Logical dtype | Rank | Shape | Description | Presence |
28
  | --- | --- | --- | --- | --- | --- | --- |
29
+ | `y` | `Y` | `T` | same as `x` | same as `x` | Output tensor with each element bitwise-negated; same shape and dtype as `X`. | required |
30
 
31
  ## Type constraints
32
 
 
36
 
37
  ## Files
38
 
39
+ - [`metadata.json`](build/webgpu/metadata.json) — kernel metadata (id, digests, per-variant templates, provenance)
40
  - [`manifest.json`](build/webgpu/manifest.json) — the op contract (source of truth)
41
  - [`test.json`](build/webgpu/test.json) — correctness cases
42
  - [`bench.json`](build/webgpu/bench.json) — benchmark + tuning cases
 
44
 
45
  ## Use with `@huggingface/kernels`
46
 
47
+ ```sh
48
+ npm install --save-exact @huggingface/kernels@0.0.1-preview.2
49
+ ```
50
+
51
+ Required output shapes and logical data types are inferred from the supplied inputs and attributes; result tensors are allocated automatically.
52
 
53
  The `version: 1` option selects the published kernel contract; it is independent of any operator opset, contrib `since_version`, or model version.
54
+ It follows the `v1` branch as fixes land. To pin exact artifact bytes, pass a 40-character commit `revision` instead of `version`.
55
 
56
  Replace each `*Data` placeholder with a typed array containing the corresponding input data.
57
 
build/webgpu/bench.json CHANGED
@@ -1,5 +1,4 @@
1
  {
2
- "op": "ai.onnx.BitwiseNot",
3
  "cases": [
4
  {
5
  "name": "u32_33m",
 
1
  {
 
2
  "cases": [
3
  {
4
  "name": "u32_33m",
build/webgpu/bitwise-not.wgsl.jinja CHANGED
@@ -1,30 +1,30 @@
1
  {% macro flat_index_2d(name="i", bound="params.count", guardInline=false, note="dispatch-limit") %}
2
  {% if note == "dispatch-limit" %}
3
- // 2D-folded flat index: gid.y carries the high bits past the
4
- // maxComputeWorkgroupsPerDimension dispatch limit (outputs > 16.7M elements).
5
  {% elif note == "limit" %}
6
- // 2D-folded flat index: gid.y carries the high bits past the
7
- // maxComputeWorkgroupsPerDimension limit.
8
  {% elif note == "device-axis" %}
9
- // The flat dispatch is folded across x/y at the device's per-axis workgroup
10
- // limit; gid.y carries the high portion of the output index.
11
  {% elif note == "vec4-limit" %}
12
- // 2D-folded flat vec4 index: gid.y carries the high bits past the
13
- // maxComputeWorkgroupsPerDimension limit (the dispatch caps x and spills into y).
14
  {% elif note == "element-limit" %}
15
  // 2D-folded flat element index: gid.y carries the high bits past the
16
- // maxComputeWorkgroupsPerDimension limit.
17
  {% elif note == "dispatch" %}
18
- // 2D-folded flat index: gid.y carries the high bits past the
19
- // maxComputeWorkgroupsPerDimension dispatch limit.
20
  {% endif %}
21
  {% if bound == "" %}
22
- let {{ name }} = gid.x + gid.y * nwg.x * {{ tunables.WORKGROUP_SIZE }}u;
23
  {%- elif guardInline %}
24
- let {{ name }} = gid.x + gid.y * nwg.x * {{ tunables.WORKGROUP_SIZE }}u;
25
  if ({{ name }} >= {{ bound }}) { return; }
26
  {%- else %}
27
- let {{ name }} = gid.x + gid.y * nwg.x * {{ tunables.WORKGROUP_SIZE }}u;
28
  if ({{ name }} >= {{ bound }}) {
29
  return;
30
  }
@@ -34,11 +34,11 @@
34
  {{ env.wgsl.resourceDeclarations }}
35
 
36
  @compute @workgroup_size({{ tunables.WORKGROUP_SIZE }})
37
- fn main(@builtin(global_invocation_id) gid: vec3<u32>, @builtin(num_workgroups) nwg: vec3<u32>) {
38
  {{ flat_index_2d(note="element-limit") }}
39
  var value = ~x[i];
40
  {% if logicalDtype == "uint8" %}
41
- {% if source.vectorized %}
42
  value = value & vec4<u32>(0xffu);
43
  {% else %}
44
  value = value & 0xffu;
 
1
  {% macro flat_index_2d(name="i", bound="params.count", guardInline=false, note="dispatch-limit") %}
2
  {% if note == "dispatch-limit" %}
3
+ // 2D-folded flat index: gid.y carries the high bits past the dispatch's
4
+ // per-axis workgroup fold width (outputs > 16.7M elements).
5
  {% elif note == "limit" %}
6
+ // 2D-folded flat index: gid.y carries the high bits past the dispatch's
7
+ // per-axis workgroup fold width.
8
  {% elif note == "device-axis" %}
9
+ // The flat dispatch is folded across x/y at a fixed per-axis workgroup
10
+ // width; gid.y carries the high portion of the output index.
11
  {% elif note == "vec4-limit" %}
12
+ // 2D-folded flat vec4 index: gid.y carries the high bits past the dispatch's
13
+ // per-axis workgroup fold width (the dispatch caps x and spills into y).
14
  {% elif note == "element-limit" %}
15
  // 2D-folded flat element index: gid.y carries the high bits past the
16
+ // dispatch's per-axis workgroup fold width.
17
  {% elif note == "dispatch" %}
18
+ // 2D-folded flat index: gid.y carries the high bits past the dispatch's
19
+ // per-axis workgroup fold width.
20
  {% endif %}
21
  {% if bound == "" %}
22
+ let {{ name }} = gid.x + gid.y * {{ DISPATCH_FOLD_WIDTH }}u * {{ tunables.WORKGROUP_SIZE }}u;
23
  {%- elif guardInline %}
24
+ let {{ name }} = gid.x + gid.y * {{ DISPATCH_FOLD_WIDTH }}u * {{ tunables.WORKGROUP_SIZE }}u;
25
  if ({{ name }} >= {{ bound }}) { return; }
26
  {%- else %}
27
+ let {{ name }} = gid.x + gid.y * {{ DISPATCH_FOLD_WIDTH }}u * {{ tunables.WORKGROUP_SIZE }}u;
28
  if ({{ name }} >= {{ bound }}) {
29
  return;
30
  }
 
34
  {{ env.wgsl.resourceDeclarations }}
35
 
36
  @compute @workgroup_size({{ tunables.WORKGROUP_SIZE }})
37
+ fn main(@builtin(global_invocation_id) gid: vec3<u32>) {
38
  {{ flat_index_2d(note="element-limit") }}
39
  var value = ~x[i];
40
  {% if logicalDtype == "uint8" %}
41
+ {% if vectorizedSpec %}
42
  value = value & vec4<u32>(0xffu);
43
  {% else %}
44
  value = value & 0xffu;
build/webgpu/manifest.json CHANGED
@@ -2,73 +2,55 @@
2
  "domain": "ai.onnx",
3
  "name": "BitwiseNot",
4
  "sinceVersion": 18,
5
- "description": "Applies a bitwise NOT to each element of the input tensor, flipping every bit. The output has the same shape and integer dtype as the input.",
6
- "inputs": [{ "role": "X", "dtype": "T", "description": "Input integer tensor." }],
7
- "outputs": [
8
- {
9
- "role": "Y",
10
- "dtype": "T",
11
- "rank": "ranks.X",
12
- "description": "Output tensor with each element bitwise-negated; same shape and dtype as `X`.",
13
- "shape": "shapes.X"
14
- }
15
- ],
16
  "typeConstraints": { "T": ["uint32", "int32", "int16", "uint8", "int8"] },
17
- "args": {
18
- "x": { "kind": "tensor", "semantic": "X", "role": "input" },
19
- "y": { "kind": "tensor", "semantic": "Y", "role": "output" }
20
- },
21
- "tunables": { "WORKGROUP_SIZE": 256 },
22
- "derive": { "shapeContract": "numel(shapes.X) == numel(shapes.Y)" },
23
- "constants": { "logicalDtype": "tensorDtypes.Y" },
24
- "bindingSets": {
25
- "vector": [
26
- { "name": "x", "arg": "x", "buffer": { "type": "read-only-storage" }, "elementType": "$vectorScalar" },
27
- { "name": "y", "arg": "y", "buffer": { "type": "storage" }, "elementType": "$vectorScalar" },
28
- {
29
- "name": "params",
30
- "semantic": "kernel.params",
31
- "buffer": { "type": "uniform" },
32
- "struct": { "name": "Params", "fields": [{ "name": "count", "type": "u32", "value": "numel(shapes.y) / 4" }] }
33
- }
34
- ],
35
- "scalar": [
36
- { "name": "x", "arg": "x", "semantic": "X", "buffer": { "type": "read-only-storage" }, "elementType": "$T" },
37
- { "name": "y", "arg": "y", "semantic": "Y", "buffer": { "type": "storage" }, "elementType": "$T" },
38
- {
39
- "name": "params",
40
- "semantic": "kernel.params",
41
- "buffer": { "type": "uniform" },
42
- "struct": { "name": "Params", "fields": [{ "name": "count", "type": "u32", "value": "numel(shapes.Y)" }] }
43
- }
44
- ]
45
- },
46
  "variants": [
47
  {
48
  "id": "elementwise_vec4",
49
  "priority": 20,
50
- "when": ["numel(shapes.X) % 4 == 0", "shapeContract"],
51
- "constants": { "vectorScalar": "\"vec4<\" ~ dtypes.T ~ \">\"" },
52
  "passes": [
53
  {
54
  "id": "main",
55
  "name": "BitwiseNot.vec4",
56
- "source": { "shader": "bitwise-not.wgsl.jinja", "inputs": { "vectorized": true } },
57
- "bindings": "vector",
58
- "dispatch": { "threads": "numel(shapes.Y) / 4", "workgroupSize": "tunables.WORKGROUP_SIZE" }
 
 
 
 
 
 
 
 
 
59
  }
60
  ]
61
  },
62
  {
63
  "id": "elementwise",
64
- "when": "shapeContract",
65
  "passes": [
66
  {
67
  "id": "main",
68
  "name": "BitwiseNot",
69
- "source": { "shader": "bitwise-not.wgsl.jinja", "inputs": { "vectorized": false } },
70
- "bindings": "scalar",
71
- "dispatch": { "threads": "numel(shapes.Y)", "workgroupSize": "tunables.WORKGROUP_SIZE" }
 
 
 
 
 
 
 
 
 
72
  }
73
  ]
74
  }
 
2
  "domain": "ai.onnx",
3
  "name": "BitwiseNot",
4
  "sinceVersion": 18,
5
+ "inputs": { "x": { "onnx": "X", "dtype": "T" } },
6
+ "outputs": { "y": { "onnx": "Y", "dtype": "T", "rank": "ranks.x", "shape": "shapes.x" } },
 
 
 
 
 
 
 
 
 
7
  "typeConstraints": { "T": ["uint32", "int32", "int16", "uint8", "int8"] },
8
+ "tunables": { "WORKGROUP_SIZE": { "default": 256 } },
9
+ "derive": { "shapeContract": "numel(shapes.x) == numel(shapes.y)", "logicalDtype": "tensorDtypes.y" },
10
+ "when": ["shapeContract"],
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
11
  "variants": [
12
  {
13
  "id": "elementwise_vec4",
14
  "priority": 20,
15
+ "when": ["numel(shapes.x) % 4 == 0"],
16
+ "derive": { "vectorScalar": "\"vec4<\" ~ dtypes.T ~ \">\"" },
17
  "passes": [
18
  {
19
  "id": "main",
20
  "name": "BitwiseNot.vec4",
21
+ "shader": "bitwise-not.wgsl.jinja",
22
+ "derive": { "vectorizedSpec": true },
23
+ "bindings": [
24
+ { "arg": "x", "elementType": "$vectorScalar" },
25
+ { "arg": "y", "elementType": "$vectorScalar" },
26
+ { "name": "params", "struct": [{ "name": "count", "type": "u32", "value": "numel(shapes.y) / 4" }] }
27
+ ],
28
+ "dispatch": {
29
+ "x": "min(ceilDiv((numel(shapes.y) / 4), (tunables.WORKGROUP_SIZE)), 65535)",
30
+ "y": "ceilDiv(ceilDiv((numel(shapes.y) / 4), (tunables.WORKGROUP_SIZE)), 65535)",
31
+ "z": 1
32
+ }
33
  }
34
  ]
35
  },
36
  {
37
  "id": "elementwise",
 
38
  "passes": [
39
  {
40
  "id": "main",
41
  "name": "BitwiseNot",
42
+ "shader": "bitwise-not.wgsl.jinja",
43
+ "derive": { "vectorizedSpec": false },
44
+ "bindings": [
45
+ "x",
46
+ "y",
47
+ { "name": "params", "struct": [{ "name": "count", "type": "u32", "value": "numel(shapes.y)" }] }
48
+ ],
49
+ "dispatch": {
50
+ "x": "min(ceilDiv((numel(shapes.y)), (tunables.WORKGROUP_SIZE)), 65535)",
51
+ "y": "ceilDiv(ceilDiv((numel(shapes.y)), (tunables.WORKGROUP_SIZE)), 65535)",
52
+ "z": 1
53
+ }
54
  }
55
  ]
56
  }
build/webgpu/metadata.json CHANGED
@@ -1,18 +1,21 @@
1
  {
2
  "name": "ai.onnx.BitwiseNot",
3
- "id": "_ai_onnx_bitwisenot_webgpu_32a96bb",
4
  "version": 1,
5
  "license": "Apache-2.0",
6
  "backend": { "type": "webgpu" },
7
  "digest": {
8
  "algorithm": "sha256",
9
  "files": {
10
- "bench.json": "CczI58x8pA6aakhXdpmw14wRRq8CEArt333TMzvUE5I=",
11
- "bitwise-not.wgsl.jinja": "f8h+mARfRrpuDY+hBRyHRhegkFnDEct4lQBZx36dcos=",
12
- "manifest.json": "0dDdOkc503LzGY8f0BAs48R9B/tEFd/aiqfgfYE/5/Y=",
13
- "test.json": "XY7peYVfnFEA8/3VjLC1K8VgcdVQMfTvctow0rwlmTM="
14
  }
15
  },
16
- "provenance": { "kernel": { "sha": "2e7068faf55e7f43df740015f6d1ee49391a41c5", "dirty": false } },
17
- "webgpu": { "manifestSpec": "1.0", "specialized": true, "opPath": "ops/ai.onnx.BitwiseNot" }
 
 
 
18
  }
 
1
  {
2
  "name": "ai.onnx.BitwiseNot",
3
+ "id": "_ai_onnx_bitwisenot_webgpu_853bcee",
4
  "version": 1,
5
  "license": "Apache-2.0",
6
  "backend": { "type": "webgpu" },
7
  "digest": {
8
  "algorithm": "sha256",
9
  "files": {
10
+ "bench.json": "MD1dhXerFPrKL1pwLulPwQoIcIJYxQRi6DZEqLmoETg=",
11
+ "bitwise-not.wgsl.jinja": "ZtA3TBUEhXt39AUn36XrrbII2ndOJO6W+D3gVBiSMp8=",
12
+ "manifest.json": "ifbhqCLw5vH+vD1dd5GtcdijLT+JDK1N98R/WnGEiq8=",
13
+ "test.json": "o049sQp+WvVyGnQxzbNjh0At7j0Yn/3g6v73ROxa1iY="
14
  }
15
  },
16
+ "provenance": { "kernel": { "sha": "91d990483a174128daf7673f3f37a7c890493ae1", "dirty": false } },
17
+ "webgpu": {
18
+ "manifestSpec": "2.0",
19
+ "variants": { "elementwise_vec4": ["bitwise-not.wgsl.jinja"], "elementwise": ["bitwise-not.wgsl.jinja"] }
20
+ }
21
  }
build/webgpu/test.json CHANGED
@@ -1,5 +1,4 @@
1
  {
2
- "op": "ai.onnx.BitwiseNot",
3
  "cases": [
4
  {
5
  "name": "int32_signed_ort",
 
1
  {
 
2
  "cases": [
3
  {
4
  "name": "int32_signed_ort",