Skip to content

Commit 6dfe59c

Browse files
danieldkMekkCyber
andauthored
Add support for kernel versions (#209)
* Add support for kernel versions This change adds support for kernel versions branches as implemented by `kernel-builder`: * `kernels upload` will upload the branch corresponding to the kernel's version. * `get_kernel`, `LayerRepository`, etc. accept version branches through the `version` argument. * Kernel locking (e.g. `kernels lock`) support reading version branches from `pyproject.yaml` and correctly locking them. All the kernel functions and layers already supported a `version` argument for version specifiers (based on tags). These are now overloaded -- if `version` is a `str`, it is parsed as a version specifier. If it is an `int`, it is used as a version branch. This overloading is used to gradually move to version branches, deprecating version specifiers. For now, using version specifiers will emit a warning. * Documtenation updates * Some fixes in the docs about bumping the kernel version * Add basic `kernel versions` subcommand * Describe migration * Warn when trying to use without versions * Fixes Co-authored-by: Mohamed Mekkouri <93391238+MekkCyber@users.noreply.github.com> * black * Remove unnecessary `_get_available_versions` call * Add files for old locking tests * Remove spurious quotation * Revert build variant regex Get the full name by using the path in `kernels versions`. * `kernels versions`: sort versions --------- Co-authored-by: Mohamed Mekkouri <93391238+MekkCyber@users.noreply.github.com>
1 parent 23e8d9b commit 6dfe59c

35 files changed

Lines changed: 849 additions & 206 deletions

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ import torch
4545
from kernels import get_kernel
4646

4747
# Download optimized kernels from the Hugging Face hub
48-
activation = get_kernel("kernels-community/activation")
48+
activation = get_kernel("kernels-community/activation", version=1)
4949

5050
# Random tensor
5151
x = torch.randn((10, 10), dtype=torch.float16, device="cuda")
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
11
[tool.kernels.dependencies]
2-
"kernels-test/versions" = ">=0.1.0,<0.2.0"
2+
"kernels-test/versions" = 1

docs/source/_toctree.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,9 @@
1515
title: Environment Variables
1616
- local: faq
1717
title: FAQ
18+
- local: migration
19+
title: Migrating from older versions
20+
title: Usage Guide
1821
title: Using kernels
1922
- sections:
2023
- local: builder/writing-kernels

docs/source/basic-usage.md

Lines changed: 9 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import torch
99
from kernels import get_kernel
1010

1111
# Download optimized kernels from the Hugging Face hub
12-
activation = get_kernel("kernels-community/activation")
12+
activation = get_kernel("kernels-community/activation", version=1)
1313

1414
# Create a random tensor
1515
x = torch.randn((10, 10), dtype=torch.float16, device="cuda")
@@ -21,30 +21,22 @@ activation.gelu_fast(y, x)
2121
print(y)
2222
```
2323

24-
### Using version bounds
24+
This fetches version `1` of the kernel `kernels-community/activation`.
25+
Kernels are versioned using a major version number. Using `version=1` will
26+
get the latest kernel build from the `v1` branch.
2527

26-
Kernels are versioned using tags of the form `v<major>.<minor>.<patch>`.
27-
You can specify which version to download using Python version specifiers:
28-
29-
```python
30-
import torch
31-
from kernels import get_kernel
32-
33-
activation = get_kernel("kernels-community/activation", version=">=0.0.4,<0.1.0")
34-
```
35-
36-
This will get the latest kernel tagged `v0.0.z` where `z` is at least 4. It
37-
is strongly recommended to specify a version bound, since a kernel author
38-
might push incompatible changes to the `main` branch.
28+
Kernels within a version branch must never break the API or remove builds
29+
for older PyTorch versions. This ensures that your code will continue to work.
3930

4031
## Checking Kernel Availability
4132

42-
You can check if a specific kernel is available for your environment:
33+
You can check if a particular version of a kernel supports the environment
34+
that the program is running on:
4335

4436
```python
4537
from kernels import has_kernel
4638

4739
# Check if kernel is available for current environment
48-
is_available = has_kernel("kernels-community/activation")
40+
is_available = has_kernel("kernels-community/activation", version=1)
4941
print(f"Kernel available: {is_available}")
5042
```

docs/source/kernel-requirements.md

Lines changed: 24 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,14 @@ must be available for that combination.
3737
## Kernel metadata
3838

3939
The build variant directory can optionally contain a `metadata.json` file.
40-
Currently the only purpose of the metadata is to specify the kernel Python dependencies.
40+
Currently the metadata specifies the kernel's version and Python dependencies,
41+
for example:
42+
43+
```json
44+
{
45+
"python-depends": ["einops"],
46+
"version": 1
47+
```
4148

4249
### Python dependencies
4350

@@ -75,7 +82,8 @@ You can specify both general and backend-specific dependencies:
7582
"python-depends": ["einops"],
7683
"python-depends-backends": {
7784
"cuda": ["nvidia-cutlass-dsl"]
78-
}
85+
},
86+
"version": 1
7987
}
8088
```
8189

@@ -84,21 +92,31 @@ You can specify both general and backend-specific dependencies:
8492
The following dependencies are currently allowed:
8593

8694
**General dependencies:**
95+
8796
- `einops`
8897

8998
**Backend-specific dependencies:**
99+
90100
- CUDA: `nvidia-cutlass-dsl`
91101
- XPU: `onednn`
92102

93103
Dependencies are validated based on the backend being used. When a kernel is loaded, only the dependencies relevant to the active backend are checked.
94104

95105
## Versioning
96106

97-
Kernels are versioned on the Hub using Git tags. Version tags must be of
98-
the form `v<major>.<minor>.<patch>`. Versions are used by [locking](./locking.md)
99-
to resolve the version constraints.
107+
Kernels are versioned using a major version. The kernel revisions of a
108+
version are stored in a branch of the form `v<version>`. Each build
109+
variant will also have the kernel version in `metadata.json`.
110+
111+
The version **must** be bumped in the following cases:
112+
113+
- The kernel API is changed in an incompatible way.
114+
- The API is extended in a compatible way, but not all build variants
115+
receive the extension (e.g. because they are for older Torch versions
116+
that are not supported by `kernel-builder` anymore).
100117

101-
We recommend using [semver](https://semver.org/) to version kernels.
118+
In both cases, build variants that are not updated must be removed from
119+
the new version's branch.
102120

103121
## Native Python module
104122

docs/source/layers.md

Lines changed: 9 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -159,10 +159,12 @@ kernel_layer_mapping = {
159159
"cuda": LayerRepository(
160160
repo_id="kernels-community/activation",
161161
layer_name="SiluAndMul",
162+
version=1,
162163
),
163164
"rocm": LayerRepository(
164165
repo_id="kernels-community/activation",
165166
layer_name="SiluAndMul",
167+
version=1,
166168
)
167169
}
168170
}
@@ -202,33 +204,6 @@ kernel_layer_mapping = {
202204
}
203205
```
204206

205-
### Using version bounds
206-
207-
Kernels are versioned using tags of the form `v<major>.<minor>.<patch>`.
208-
You can specify which version of the kernel to download using Python version
209-
specifiers:
210-
211-
```python
212-
kernel_layer_mapping = {
213-
"SiluAndMul": {
214-
"cuda": LayerRepository(
215-
repo_id="kernels-community/activation",
216-
layer_name="SiluAndMul",
217-
version=">=0.0.4,<0.1.0",
218-
),
219-
"rocm": LayerRepository(
220-
repo_id="kernels-community/activation",
221-
layer_name="SiluAndMul",
222-
version=">=0.0.4,<0.1.0",
223-
)
224-
}
225-
}
226-
```
227-
228-
This will get the layer from latest kernel tagged `v0.0.z` where `z` is at
229-
least 4. It is strongly recommended to specify a version bound, since a
230-
kernel author might push incompatible changes to the `main` branch.
231-
232207
### Registering kernels for specific modes
233208

234209
You might want to register two different kernels for a particular layer,
@@ -242,10 +217,12 @@ kernel_layer_mapping = {
242217
Mode.INFERENCE: LayerRepository(
243218
repo_id="kernels-community/activation-inference-optimized",
244219
layer_name="SiluAndMul",
220+
version=1,
245221
),
246222
Mode.TRAINING | Mode.TORCH_COMPILE: LayerRepository(
247223
repo_id="kernels-community/activation-training-optimized",
248224
layer_name="SiluAndMul",
225+
version=1,
249226
),
250227
}
251228
}
@@ -273,14 +250,17 @@ kernel_layer_mapping = {
273250
Mode.FALLBACK: LayerRepository(
274251
repo_id="kernels-community/activation",
275252
layer_name="SiluAndMul",
253+
version=1,
276254
),
277255
Mode.INFERENCE: LayerRepository(
278256
repo_id="kernels-community/activation-inference-optimized",
279257
layer_name="SiluAndMul",
258+
version=1,
280259
),
281260
Mode.TRAINING: LayerRepository(
282261
repo_id="kernels-community/activation-training-optimized",
283262
layer_name="SiluAndMul",
263+
version=1,
284264
),
285265
}
286266
}
@@ -310,6 +290,7 @@ kernel_layer_mapping = {
310290
): LayerRepository(
311291
repo_id="kernels-community/activation",
312292
layer_name="SiluAndMul",
293+
version=1,
313294
),
314295
Device(
315296
type="cuda",
@@ -319,6 +300,7 @@ kernel_layer_mapping = {
319300
): LayerRepository(
320301
repo_id="kernels-community/activation-hopper",
321302
layer_name="SiluAndMul",
303+
version=1,
322304
),
323305
}
324306
}

docs/source/locking.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ requires = ["kernels", "setuptools"]
1010
build-backend = "setuptools.build_meta"
1111

1212
[tool.kernels.dependencies]
13-
"kernels-community/activation" = ">=0.0.1"
13+
"kernels-community/activation" = 1
1414
```
1515

1616
Then run `kernels lock .` in the project directory. This generates a `kernels.lock` file with

docs/source/migration.md

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
# Migrating from older versions
2+
3+
## 0.12
4+
5+
### Adopting kernel versions
6+
7+
Before `kernels` 0.12, kernels could be pulled from a repository
8+
without specifying a version. This is deprecated in kernels 0.12
9+
and will become an error in kernels 0.14. Instead, use of a kernel
10+
should always specify a version (except for local kernels).
11+
12+
Kernels only use a major version. The kernel maintainer is responsible
13+
for never breaking a kernel within a major version and should bump up
14+
the major version if the kernel API changes and/or when support for
15+
older Torch versions is removed.
16+
17+
You can find the versions that are supported by a kernel using the
18+
`kernels versions command`. For example:
19+
20+
```bash
21+
$ kernels versions kernels-community/activation
22+
Version 1: torch210-cxx11-cu126-x86_64-linux, torch210-cxx11-cu128-x86_64-linux, torch210-cxx11-cu130-x86_64-linux, torch27-cxx11-cu118-x86_64-linux, torch27-cxx11-cu126-x86_64-linux, torch27-cxx11-cu128-aarch64-linux, torch27-cxx11-cu128-x86_64-linux ✅, torch28-cxx11-cu126-aarch64-linux, torch28-cxx11-cu126-x86_64-linux, torch28-cxx11-cu128-aarch64-linux, torch28-cxx11-cu128-x86_64-linux, torch28-cxx11-cu129-aarch64-linux, torch28-cxx11-cu129-x86_64-linux, torch29-cxx11-cu126-aarch64-linux, torch29-cxx11-cu126-x86_64-linux, torch29-cxx11-cu128-aarch64-linux, torch29-cxx11-cu128-x86_64-linux, torch29-cxx11-cu130-aarch64-linux, torch29-cxx11-cu130-x86_64-linux
23+
```
24+
25+
The command lists all available versions (here only version 1) with
26+
all the variants that are supported. A check mark is printed after
27+
the variant that is compatible with your current environment.
28+
29+
Code that uses a kernel can be updated as follows:
30+
31+
```python
32+
# Old:
33+
activation = get_kernel("kernels-community/activation")
34+
activation = get_kernel("kernels-community/activation", version=">=0.0.2 && <0.1.0")
35+
36+
# New:
37+
activation = get_kernel("kernels-community/activation", version=1)
38+
39+
# Old:
40+
kernel_layer_mapping = {
41+
"SiluAndMul": {
42+
"cuda": LayerRepository(
43+
repo_id="kernels-community/activation",
44+
layer_name="SiluAndMul",
45+
),
46+
}
47+
}
48+
kernel_layer_mapping = {
49+
"SiluAndMul": {
50+
"cuda": LayerRepository(
51+
repo_id="kernels-community/activation",
52+
layer_name="SiluAndMul",
53+
version=">=0.0.2 && <0.1.0",
54+
),
55+
}
56+
}
57+
58+
# New:
59+
kernel_layer_mapping = {
60+
"SiluAndMul": {
61+
"cuda": LayerRepository(
62+
repo_id="kernels-community/activation",
63+
layer_name="SiluAndMul",
64+
version=1,
65+
),
66+
}
67+
}
68+
```

examples/basic.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
print("Starting examples/basic.py demo")
66

77
# Download optimized kernels from the Hugging Face hub
8-
activation = get_kernel("kernels-community/activation")
8+
activation = get_kernel("kernels-community/activation", version=1)
99

1010
print("Activation kernel fetched")
1111

kernels/src/kernels/__init__.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
import importlib.metadata
22

3-
43
__version__ = importlib.metadata.version("kernels")
54

65
from kernels.layer import (

0 commit comments

Comments
 (0)