marcsun13 HF Staff commited on
Commit
f79d690
·
verified ·
1 Parent(s): 97231ed

GGUF kernels: dequantize + fused gemv over packed blocks

Browse files
Files changed (4) hide show
  1. .pytest_cache/v/cache/lastfailed +3 -1
  2. README.md +5 -0
  3. SKILL.md +26 -6
  4. flake.nix +1 -1
.pytest_cache/v/cache/lastfailed CHANGED
@@ -1 +1,3 @@
1
- {}
 
 
 
1
+ {
2
+ "tests/test_gguf_kernels.py": true
3
+ }
README.md CHANGED
@@ -60,3 +60,8 @@ nix run .#build-and-copy -L # every variant, into build/
60
  nix build .#ci # just this system's variant
61
  pytest tests/ # against a built variant on PYTHONPATH
62
  ```
 
 
 
 
 
 
60
  nix build .#ci # just this system's variant
61
  pytest tests/ # against a built variant on PYTHONPATH
62
  ```
63
+
64
+ `flake.nix` tracks the builder's default branch, so CI builds the current variant matrix. The
65
+ `build/` directory here was produced against the builder release matching the `kernels` client it was
66
+ verified with (torch 2.11/2.12): both ops tested against `gguf.quants.dequantize` for Q4_K/Q5_K/Q6_K/
67
+ Q8_0 in f32/f16/bf16, the gemv against a dense matmul, and one `fullgraph=True` compile.
SKILL.md CHANGED
@@ -57,8 +57,9 @@ dispatch on the tensor's device as usual.
57
  ## 3. Which builder, and why it decides everything
58
 
59
  Use `github:huggingface/kernels` (the old `kernel-builder` repo is stale) with
60
- `lib.genKernelFlakeOutputs`. **Pin it to the same version as the `kernels` client you load with**,
61
- because the builder version decides two things at once:
 
62
 
63
  | | |
64
  | --- | --- |
@@ -66,7 +67,8 @@ because the builder version decides two things at once:
66
  | the `metadata.json` format | older builders omit `name`, and a current client refuses to load that |
67
 
68
  A mismatch surfaces as `Cannot parse metadata from ...: missing field 'name'`, or as a build with no
69
- variant your interpreter can import. Check what came out before debugging anything else:
 
70
 
71
  ```bash
72
  ls build/ && head -6 build/*/metadata.json
@@ -137,9 +139,13 @@ reproducible. Then, in increasing order of surprise:
137
  2. **Trust.** `get_kernel` loads unattended only from a publisher the Hub marks as a trusted kernel
138
  publisher (e.g. `kernels-community`). A personal repo needs `trust_remote_code=True`, i.e. the
139
  caller opting into running downloaded code — so a library should not pass it silently.
140
- 3. **Indexing.** The client resolves through `https://huggingface.co/api/kernels/<repo>/...`, which
141
- 401s for a repo the Hub has not indexed as a kernel. A correct repo can still be unfetchable;
142
- `kernels-community` repos work, so compare against one before suspecting your own build.
 
 
 
 
143
 
144
  Test without the Hub at all:
145
 
@@ -160,3 +166,17 @@ _MY_OP = module.my_op # NOT self.kernel.my_op
160
  Reaching an op through an attribute on an object makes dynamo graph-break at every call, which costs
161
  more than the kernel saves — the same reason the fakes matter. Treat "no kernel" as a normal outcome:
162
  return `None`, log why, and fall back to the dense path.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
57
  ## 3. Which builder, and why it decides everything
58
 
59
  Use `github:huggingface/kernels` (the old `kernel-builder` repo is stale) with
60
+ `lib.genKernelFlakeOutputs`. Leave it unpinned for a repo whose variants CI builds — that keeps the
61
+ matrix current. Pin it to the `kernels` client version only when *you* build the artifacts you will
62
+ load locally, because the builder version decides two things at once:
63
 
64
  | | |
65
  | --- | --- |
 
67
  | the `metadata.json` format | older builders omit `name`, and a current client refuses to load that |
68
 
69
  A mismatch surfaces as `Cannot parse metadata from ...: missing field 'name'`, or as a build with no
70
+ variant your interpreter can import — which is what unpinned costs locally: `main` targets torch
71
+ 2.12/2.13, so testing a local build needs a matching interpreter. Check what came out before debugging anything else:
72
 
73
  ```bash
74
  ls build/ && head -6 build/*/metadata.json
 
139
  2. **Trust.** `get_kernel` loads unattended only from a publisher the Hub marks as a trusted kernel
140
  publisher (e.g. `kernels-community`). A personal repo needs `trust_remote_code=True`, i.e. the
141
  caller opting into running downloaded code — so a library should not pass it silently.
142
+ 3. **The repo has to be under an organization.** The client resolves through
143
+ `https://huggingface.co/api/kernels/<repo>/...`, which 401s (404s with a token) for a repo in a
144
+ *user* namespace — no tag, metadata or `kernel` tag changes that. The trust check gives the same
145
+ hint: it calls `get_organization_overview(publisher)`, which a username has no answer for. So a
146
+ correct, fully published repo can still be unfetchable by id. Compare against a
147
+ `kernels-community` repo (`get_kernel("kernels-community/relu", version=1)`) before suspecting
148
+ your own build, and use the override below until the kernels live in an org.
149
 
150
  Test without the Hub at all:
151
 
 
166
  Reaching an op through an attribute on an object makes dynamo graph-break at every call, which costs
167
  more than the kernel saves — the same reason the fakes matter. Treat "no kernel" as a normal outcome:
168
  return `None`, log why, and fall back to the dense path.
169
+
170
+ ## 8. Sanity numbers
171
+
172
+ From this build, so you know what "working" looks like:
173
+
174
+ | | |
175
+ | --- | --- |
176
+ | compile, one variant | ~150 s (5 translation units, 5 SM archs) |
177
+ | all variants | ~8 min for 6 |
178
+ | the whole exercise | dominated by rebuilds after each build.toml/builder discovery, not by compiling |
179
+
180
+ End state worth reproducing: `pytest tests/` green against a built variant, `fullgraph=True` compile
181
+ green, and the calling library loading the same artifact through `get_kernel` — for GGUF that was a
182
+ 4B Q4_K_M model at 3.07 GB and 187 tok/s instead of 8.4 GB dequantized.
flake.nix CHANGED
@@ -1,7 +1,7 @@
1
  {
2
  description = "GGUF kernels: compute on the packed blocks of a GGUF checkpoint";
3
  inputs = {
4
- kernel-builder.url = "github:huggingface/kernels/v0.15.2";
5
  };
6
  outputs = { self, kernel-builder }:
7
  kernel-builder.lib.genKernelFlakeOutputs {
 
1
  {
2
  description = "GGUF kernels: compute on the packed blocks of a GGUF checkpoint";
3
  inputs = {
4
+ kernel-builder.url = "github:huggingface/kernels";
5
  };
6
  outputs = { self, kernel-builder }:
7
  kernel-builder.lib.genKernelFlakeOutputs {