marcsun13 HF Staff commited on
Commit
2c20074
·
verified ·
1 Parent(s): 06a029e

GGUF kernels: dequantize + fused gemv over packed blocks, 9 CUDA variants

Browse files
This view is limited to 50 files because it contains too many changes.   See raw diff
Files changed (50) hide show
  1. .gitattributes +9 -0
  2. .pytest_cache/.gitignore +2 -0
  3. .pytest_cache/CACHEDIR.TAG +4 -0
  4. .pytest_cache/README.md +8 -0
  5. .pytest_cache/v/cache/lastfailed +1 -0
  6. .pytest_cache/v/cache/nodeids +23 -0
  7. README.md +62 -0
  8. build.toml +74 -0
  9. build/torch210-cxx11-cu126-x86_64-linux/__init__.py +55 -0
  10. build/torch210-cxx11-cu126-x86_64-linux/_gguf_kernels_20260805124229.abi3.so +3 -0
  11. build/torch210-cxx11-cu126-x86_64-linux/_ops.py +9 -0
  12. build/torch210-cxx11-cu126-x86_64-linux/gguf_kernels/__init__.py +26 -0
  13. build/torch210-cxx11-cu126-x86_64-linux/metadata.json +4 -0
  14. build/torch210-cxx11-cu128-x86_64-linux/__init__.py +55 -0
  15. build/torch210-cxx11-cu128-x86_64-linux/_gguf_kernels_20260805124229.abi3.so +3 -0
  16. build/torch210-cxx11-cu128-x86_64-linux/_ops.py +9 -0
  17. build/torch210-cxx11-cu128-x86_64-linux/gguf_kernels/__init__.py +26 -0
  18. build/torch210-cxx11-cu128-x86_64-linux/metadata.json +4 -0
  19. build/torch210-cxx11-cu130-x86_64-linux/__init__.py +55 -0
  20. build/torch210-cxx11-cu130-x86_64-linux/_gguf_kernels_20260805124229.abi3.so +3 -0
  21. build/torch210-cxx11-cu130-x86_64-linux/_ops.py +9 -0
  22. build/torch210-cxx11-cu130-x86_64-linux/gguf_kernels/__init__.py +26 -0
  23. build/torch210-cxx11-cu130-x86_64-linux/metadata.json +4 -0
  24. build/torch28-cxx11-cu126-x86_64-linux/__init__.py +55 -0
  25. build/torch28-cxx11-cu126-x86_64-linux/_gguf_kernels_20260805124229.abi3.so +3 -0
  26. build/torch28-cxx11-cu126-x86_64-linux/_ops.py +9 -0
  27. build/torch28-cxx11-cu126-x86_64-linux/gguf_kernels/__init__.py +26 -0
  28. build/torch28-cxx11-cu126-x86_64-linux/metadata.json +4 -0
  29. build/torch28-cxx11-cu128-x86_64-linux/__init__.py +55 -0
  30. build/torch28-cxx11-cu128-x86_64-linux/_gguf_kernels_20260805124229.abi3.so +3 -0
  31. build/torch28-cxx11-cu128-x86_64-linux/_ops.py +9 -0
  32. build/torch28-cxx11-cu128-x86_64-linux/gguf_kernels/__init__.py +26 -0
  33. build/torch28-cxx11-cu128-x86_64-linux/metadata.json +4 -0
  34. build/torch28-cxx11-cu129-x86_64-linux/__init__.py +55 -0
  35. build/torch28-cxx11-cu129-x86_64-linux/_gguf_kernels_20260805124229.abi3.so +3 -0
  36. build/torch28-cxx11-cu129-x86_64-linux/_ops.py +9 -0
  37. build/torch28-cxx11-cu129-x86_64-linux/gguf_kernels/__init__.py +26 -0
  38. build/torch28-cxx11-cu129-x86_64-linux/metadata.json +4 -0
  39. build/torch29-cxx11-cu126-x86_64-linux/__init__.py +55 -0
  40. build/torch29-cxx11-cu126-x86_64-linux/_gguf_kernels_20260805124229.abi3.so +3 -0
  41. build/torch29-cxx11-cu126-x86_64-linux/_ops.py +9 -0
  42. build/torch29-cxx11-cu126-x86_64-linux/gguf_kernels/__init__.py +26 -0
  43. build/torch29-cxx11-cu126-x86_64-linux/metadata.json +4 -0
  44. build/torch29-cxx11-cu128-x86_64-linux/__init__.py +55 -0
  45. build/torch29-cxx11-cu128-x86_64-linux/_gguf_kernels_20260805124229.abi3.so +3 -0
  46. build/torch29-cxx11-cu128-x86_64-linux/_ops.py +9 -0
  47. build/torch29-cxx11-cu128-x86_64-linux/gguf_kernels/__init__.py +26 -0
  48. build/torch29-cxx11-cu128-x86_64-linux/metadata.json +4 -0
  49. build/torch29-cxx11-cu130-x86_64-linux/__init__.py +55 -0
  50. build/torch29-cxx11-cu130-x86_64-linux/_gguf_kernels_20260805124229.abi3.so +3 -0
.gitattributes CHANGED
@@ -33,3 +33,12 @@ saved_model/**/* filter=lfs diff=lfs merge=lfs -text
33
  *.zip filter=lfs diff=lfs merge=lfs -text
34
  *.zst filter=lfs diff=lfs merge=lfs -text
35
  *tfevents* filter=lfs diff=lfs merge=lfs -text
 
 
 
 
 
 
 
 
 
 
33
  *.zip filter=lfs diff=lfs merge=lfs -text
34
  *.zst filter=lfs diff=lfs merge=lfs -text
35
  *tfevents* filter=lfs diff=lfs merge=lfs -text
36
+ build/torch210-cxx11-cu126-x86_64-linux/_gguf_kernels_20260805124229.abi3.so filter=lfs diff=lfs merge=lfs -text
37
+ build/torch210-cxx11-cu128-x86_64-linux/_gguf_kernels_20260805124229.abi3.so filter=lfs diff=lfs merge=lfs -text
38
+ build/torch210-cxx11-cu130-x86_64-linux/_gguf_kernels_20260805124229.abi3.so filter=lfs diff=lfs merge=lfs -text
39
+ build/torch28-cxx11-cu126-x86_64-linux/_gguf_kernels_20260805124229.abi3.so filter=lfs diff=lfs merge=lfs -text
40
+ build/torch28-cxx11-cu128-x86_64-linux/_gguf_kernels_20260805124229.abi3.so filter=lfs diff=lfs merge=lfs -text
41
+ build/torch28-cxx11-cu129-x86_64-linux/_gguf_kernels_20260805124229.abi3.so filter=lfs diff=lfs merge=lfs -text
42
+ build/torch29-cxx11-cu126-x86_64-linux/_gguf_kernels_20260805124229.abi3.so filter=lfs diff=lfs merge=lfs -text
43
+ build/torch29-cxx11-cu128-x86_64-linux/_gguf_kernels_20260805124229.abi3.so filter=lfs diff=lfs merge=lfs -text
44
+ build/torch29-cxx11-cu130-x86_64-linux/_gguf_kernels_20260805124229.abi3.so filter=lfs diff=lfs merge=lfs -text
.pytest_cache/.gitignore ADDED
@@ -0,0 +1,2 @@
 
 
 
1
+ # Created by pytest automatically.
2
+ *
.pytest_cache/CACHEDIR.TAG ADDED
@@ -0,0 +1,4 @@
 
 
 
 
 
1
+ Signature: 8a477f597d28d172789f06886806bc55
2
+ # This file is a cache directory tag created by pytest.
3
+ # For information about cache directory tags, see:
4
+ # https://bford.info/cachedir/spec.html
.pytest_cache/README.md ADDED
@@ -0,0 +1,8 @@
 
 
 
 
 
 
 
 
 
1
+ # pytest cache directory #
2
+
3
+ This directory contains data from the pytest's cache plugin,
4
+ which provides the `--lf` and `--ff` options, as well as the `cache` fixture.
5
+
6
+ **Do not** commit this to version control.
7
+
8
+ See [the docs](https://docs.pytest.org/en/stable/how-to/cache.html) for more information.
.pytest_cache/v/cache/lastfailed ADDED
@@ -0,0 +1 @@
 
 
1
+ {}
.pytest_cache/v/cache/nodeids ADDED
@@ -0,0 +1,23 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ [
2
+ "tests/test_gguf_kernels.py::test_dequantize_matches_reference[dtype0-Q4_K]",
3
+ "tests/test_gguf_kernels.py::test_dequantize_matches_reference[dtype0-Q5_K]",
4
+ "tests/test_gguf_kernels.py::test_dequantize_matches_reference[dtype0-Q6_K]",
5
+ "tests/test_gguf_kernels.py::test_dequantize_matches_reference[dtype0-Q8_0]",
6
+ "tests/test_gguf_kernels.py::test_dequantize_matches_reference[dtype1-Q4_K]",
7
+ "tests/test_gguf_kernels.py::test_dequantize_matches_reference[dtype1-Q5_K]",
8
+ "tests/test_gguf_kernels.py::test_dequantize_matches_reference[dtype1-Q6_K]",
9
+ "tests/test_gguf_kernels.py::test_dequantize_matches_reference[dtype1-Q8_0]",
10
+ "tests/test_gguf_kernels.py::test_dequantize_matches_reference[dtype2-Q4_K]",
11
+ "tests/test_gguf_kernels.py::test_dequantize_matches_reference[dtype2-Q5_K]",
12
+ "tests/test_gguf_kernels.py::test_dequantize_matches_reference[dtype2-Q6_K]",
13
+ "tests/test_gguf_kernels.py::test_dequantize_matches_reference[dtype2-Q8_0]",
14
+ "tests/test_gguf_kernels.py::test_gemv_is_compileable",
15
+ "tests/test_gguf_kernels.py::test_mul_mat_vec_matches_matmul[1-Q4_K]",
16
+ "tests/test_gguf_kernels.py::test_mul_mat_vec_matches_matmul[1-Q5_K]",
17
+ "tests/test_gguf_kernels.py::test_mul_mat_vec_matches_matmul[1-Q6_K]",
18
+ "tests/test_gguf_kernels.py::test_mul_mat_vec_matches_matmul[1-Q8_0]",
19
+ "tests/test_gguf_kernels.py::test_mul_mat_vec_matches_matmul[8-Q4_K]",
20
+ "tests/test_gguf_kernels.py::test_mul_mat_vec_matches_matmul[8-Q5_K]",
21
+ "tests/test_gguf_kernels.py::test_mul_mat_vec_matches_matmul[8-Q6_K]",
22
+ "tests/test_gguf_kernels.py::test_mul_mat_vec_matches_matmul[8-Q8_0]"
23
+ ]
README.md ADDED
@@ -0,0 +1,62 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ---
2
+ license: mit
3
+ tags:
4
+ - kernel
5
+ - gguf
6
+ - quantization
7
+ ---
8
+
9
+ # GGUF kernels
10
+
11
+ Compute directly on the packed blocks of a GGUF checkpoint.
12
+
13
+ A GGUF weight is stored as blocks of 32 or 256 values that share a scale. These kernels read that
14
+ layout as it is, so a quantized model runs without ever materializing a dense copy of its weights —
15
+ which is where the memory saving comes from. A 4B model at Q4_K_M stays at 3.1 GB instead of the
16
+ 8.4 GB it would take unpacked.
17
+
18
+ Ported from [llama.cpp](https://github.com/ggml-org/llama.cpp)'s `ggml-cuda`. `vendor/UPSTREAM`
19
+ pins the revision the sources come from; `vendor.py` refreshes them.
20
+
21
+ ## Usage
22
+
23
+ ```python
24
+ import torch
25
+ from kernels import get_kernel
26
+
27
+ gguf_kernels = get_kernel("marcsun13/gguf-kernels")
28
+
29
+ # `blocks` is a GGUF weight exactly as stored: (out_features, bytes_per_row) uint8
30
+ out = gguf_kernels.mul_mat_vec(blocks, x, ggml_type=12, out_features=4096) # x @ blocks.T
31
+ dense = gguf_kernels.dequantize(blocks, ggml_type=12, rows=4096, cols=2560, dtype=torch.bfloat16)
32
+ ```
33
+
34
+ | | |
35
+ | --- | --- |
36
+ | `mul_mat_vec(blocks, x, ggml_type, out_features)` | Fused dequantize-gemv, for `x` of at most `MAX_GEMV_ROWS` rows (decode). Returns f32 whatever `x` was: the kernel writes an f32 destination, and casting at the call site lets the cast fuse into the consumer. |
37
+ | `dequantize(blocks, ggml_type, rows, cols, dtype)` | Blocks to values, in `dtype` directly. For more rows than the gemv handles (prefill), unpack and use an ordinary matmul. |
38
+ | `MAX_GEMV_ROWS` | Upstream's `MMVQ_MAX_BATCH_SIZE`. Beyond this the gemv has no implementation. |
39
+ | `GEMV_TYPES` | The ggml type ids `mul_mat_vec` implements. `dequantize` covers more, so check this before choosing the fused path. |
40
+
41
+ Both ops carry `register_fake` implementations, so they trace under `torch.compile` instead of
42
+ breaking the graph — which matters, since a break at every quantized linear costs more than the
43
+ kernels save.
44
+
45
+ ## Backends
46
+
47
+ CUDA today. The ops are named for what they do rather than for a backend: the schema is declared
48
+ once in `torch-ext/torch_binding.cpp` and each backend registers its own implementation of it, so
49
+ adding Metal means adding a `[kernel.*]` section and a source directory — no change to the schema or
50
+ to the Python API, and callers dispatch on the tensor's device as usual.
51
+
52
+ `mmq` (quantized gemm) and `mmf` (dense gemm) are deliberately not ported: both take a
53
+ `ggml_backend_cuda_context` for their pool allocator, which would pull in the whole ggml backend.
54
+ Above the gemv's row limit, unpacking and using cuBLAS measures at parity with llama.cpp anyway.
55
+
56
+ ## Building
57
+
58
+ ```bash
59
+ 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
+ ```
build.toml ADDED
@@ -0,0 +1,74 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # One backend per `[kernel.*]` section, all implementing the same two entry points declared in
2
+ # torch-ext/torch_binding.h. Adding Metal means adding a section and a `gguf_metal/` directory —
3
+ # no change to the bindings' schema or to the Python API.
4
+ #
5
+ # `vendor/` is a pinned subset of llama.cpp (revision in vendor/UPSTREAM); refresh it with
6
+ # `python vendor.py --rev <sha>`.
7
+
8
+ [general]
9
+ name = "gguf-kernels"
10
+ version = 1
11
+ backends = ["cuda"]
12
+
13
+ [torch]
14
+ src = [
15
+ "torch-ext/torch_binding.cpp",
16
+ "torch-ext/torch_binding.h",
17
+ ]
18
+
19
+ [kernel.gguf_cuda]
20
+ backend = "cuda"
21
+ depends = ["torch"]
22
+ cuda-capabilities = ["7.5", "8.0", "8.6", "8.9", "9.0", "10.0", "12.0"]
23
+ include = ["gguf_cuda", "torch-ext", "vendor/include", "vendor/src", "vendor/src/ggml-cuda"]
24
+ src = [
25
+ "gguf_cuda/gguf_cuda.cu",
26
+ "gguf_cuda/ggml_dispatch.cu",
27
+ "gguf_cuda/ggml_stubs.cu",
28
+ "vendor/src/ggml-cuda/convert.cu",
29
+ "vendor/src/ggml-cuda/quantize.cu",
30
+ # headers are listed so the builder stages them; only the files above are compiled
31
+ "vendor/include/ggml-alloc.h",
32
+ "vendor/include/ggml-backend.h",
33
+ "vendor/include/ggml-cuda.h",
34
+ "vendor/include/ggml.h",
35
+ "vendor/include/gguf.h",
36
+ "vendor/src/ggml-common.h",
37
+ "vendor/src/ggml-cuda/common.cuh",
38
+ "vendor/src/ggml-cuda/convert.cuh",
39
+ "vendor/src/ggml-cuda/dequantize.cuh",
40
+ "vendor/src/ggml-cuda/mma.cuh",
41
+ "vendor/src/ggml-cuda/mmq-config-ampere.cuh",
42
+ "vendor/src/ggml-cuda/mmq-config-blackwell.cuh",
43
+ "vendor/src/ggml-cuda/mmq-config-cdna.cuh",
44
+ "vendor/src/ggml-cuda/mmq-config-pascal.cuh",
45
+ "vendor/src/ggml-cuda/mmq-config-rdna2.cuh",
46
+ "vendor/src/ggml-cuda/mmq-config-rdna3-5.cuh",
47
+ "vendor/src/ggml-cuda/mmq-config-rdna3.cuh",
48
+ "vendor/src/ggml-cuda/mmq-config-rdna4.cuh",
49
+ "vendor/src/ggml-cuda/mmq-load-tiles.cuh",
50
+ "vendor/src/ggml-cuda/mmq-vec-dot.cuh",
51
+ "vendor/src/ggml-cuda/mmq.cuh",
52
+ "vendor/src/ggml-cuda/mmvf.cuh",
53
+ "vendor/src/ggml-cuda/mmvq.cuh",
54
+ "vendor/src/ggml-cuda/mmvq-impl.cuh",
55
+ "vendor/src/ggml-cuda/quantize.cuh",
56
+ "vendor/src/ggml-cuda/unary.cuh",
57
+ "vendor/src/ggml-cuda/vecdotq.cuh",
58
+ "vendor/src/ggml-cuda/vendors/cuda.h",
59
+ "vendor/src/ggml-impl.h",
60
+ ]
61
+ # ggml's half/bfloat16 arithmetic needs the operators torch's build disables
62
+ cuda-flags = [
63
+ "-DGGML_USE_CUDA",
64
+ "-DNDEBUG",
65
+ "-U__CUDA_NO_HALF_OPERATORS__",
66
+ "-U__CUDA_NO_HALF_CONVERSIONS__",
67
+ "-U__CUDA_NO_HALF2_OPERATORS__",
68
+ "-U__CUDA_NO_BFLOAT16_CONVERSIONS__",
69
+ "-U__CUDA_NO_BFLOAT16_OPERATORS__",
70
+ "-U__CUDA_NO_BFLOAT162_OPERATORS__",
71
+ "--expt-relaxed-constexpr",
72
+ "--expt-extended-lambda",
73
+ ]
74
+ cxx-flags = ["-DGGML_USE_CUDA", "-DNDEBUG"]
build/torch210-cxx11-cu126-x86_64-linux/__init__.py ADDED
@@ -0,0 +1,55 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Compute directly on the packed blocks of a GGUF checkpoint.
2
+
3
+ A GGUF weight is stored as blocks of 32 or 256 values sharing a scale. These kernels read that
4
+ layout as it is, so a quantized model can be loaded and run without ever materializing a dense
5
+ copy — which is the whole memory saving.
6
+
7
+ Ported from llama.cpp's ggml-cuda; `vendor/UPSTREAM` pins the revision. The ops are named for what
8
+ they do rather than for a backend: each backend registers its own implementation of the same
9
+ schema, so calls dispatch on the tensor's device.
10
+ """
11
+
12
+ import torch
13
+
14
+ from ._ops import add_op_namespace_prefix, ops
15
+
16
+
17
+ __all__ = ["GEMV_TYPES", "MAX_GEMV_ROWS", "dequantize", "mul_mat_vec"]
18
+
19
+ # Upstream's MMVQ_MAX_BATCH_SIZE: `mul_mat_vec` has no implementation beyond this many rows, so a
20
+ # caller with more (prefill) dequantizes and uses an ordinary matmul.
21
+ MAX_GEMV_ROWS = 8
22
+
23
+ # ggml type ids `mul_mat_vec` implements: Q4_0/Q4_1/Q5_0/Q5_1/Q8_0, the K quants, and the IQ quants.
24
+ # `dequantize` covers more, so check this one before choosing the fused path.
25
+ GEMV_TYPES = frozenset({2, 3, 6, 7, 8, 10, 11, 12, 13, 14, 16, 17, 18, 19, 20, 21, 22, 23, 29, 39, 40, 41, 42})
26
+
27
+
28
+ def dequantize(
29
+ blocks: torch.Tensor, ggml_type: int, rows: int, cols: int, dtype: torch.dtype
30
+ ) -> torch.Tensor:
31
+ """`(rows, bytes_per_row)` uint8 blocks -> `(rows, cols)` values of `dtype`."""
32
+ return ops.dequantize(blocks, ggml_type, rows, cols, dtype)
33
+
34
+
35
+ def mul_mat_vec(
36
+ blocks: torch.Tensor, x: torch.Tensor, ggml_type: int, out_features: int
37
+ ) -> torch.Tensor:
38
+ """Fused dequantize-gemv: `x @ blocks.T` without unpacking `blocks`.
39
+
40
+ `x` is `(rows, in_features)` and `rows` must be at most `MAX_GEMV_ROWS`. The result is f32
41
+ whatever `x`'s dtype was, since the kernel writes an f32 destination; cast it at the call site,
42
+ where the cast can be fused into whatever consumes it.
43
+ """
44
+ return ops.mul_mat_vec(blocks, x, ggml_type, out_features)
45
+
46
+
47
+ # Without these, torch.compile cannot trace the ops and breaks the graph at every call.
48
+ @torch.library.register_fake(add_op_namespace_prefix("dequantize"))
49
+ def _dequantize_fake(blocks, ggml_type, rows, cols, dtype):
50
+ return blocks.new_empty((rows, cols), dtype=dtype)
51
+
52
+
53
+ @torch.library.register_fake(add_op_namespace_prefix("mul_mat_vec"))
54
+ def _mul_mat_vec_fake(blocks, x, ggml_type, out_features):
55
+ return x.new_empty((x.shape[0], out_features), dtype=torch.float32)
build/torch210-cxx11-cu126-x86_64-linux/_gguf_kernels_20260805124229.abi3.so ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:deef7081403683a708ba874d97321243281a1b6e9e1f23ae06c930f06459f3b1
3
+ size 26692640
build/torch210-cxx11-cu126-x86_64-linux/_ops.py ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
 
1
+ import torch
2
+ from . import _gguf_kernels_20260805124229
3
+ ops = torch.ops._gguf_kernels_20260805124229
4
+
5
+ def add_op_namespace_prefix(op_name: str):
6
+ """
7
+ Prefix op by namespace.
8
+ """
9
+ return f"_gguf_kernels_20260805124229::{op_name}"
build/torch210-cxx11-cu126-x86_64-linux/gguf_kernels/__init__.py ADDED
@@ -0,0 +1,26 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import ctypes
2
+ import sys
3
+
4
+ import importlib
5
+ from pathlib import Path
6
+ from types import ModuleType
7
+
8
+ def _import_from_path(file_path: Path) -> ModuleType:
9
+ # We cannot use the module name as-is, after adding it to `sys.modules`,
10
+ # it would also be used for other imports. So, we make a module name that
11
+ # depends on the path for it to be unique using the hex-encoded hash of
12
+ # the path.
13
+ path_hash = "{:x}".format(ctypes.c_size_t(hash(file_path.absolute())).value)
14
+ module_name = path_hash
15
+ spec = importlib.util.spec_from_file_location(module_name, file_path)
16
+ if spec is None:
17
+ raise ImportError(f"Cannot load spec for {module_name} from {file_path}")
18
+ module = importlib.util.module_from_spec(spec)
19
+ if module is None:
20
+ raise ImportError(f"Cannot load module {module_name} from spec")
21
+ sys.modules[module_name] = module
22
+ spec.loader.exec_module(module) # type: ignore
23
+ return module
24
+
25
+
26
+ globals().update(vars(_import_from_path(Path(__file__).parent.parent / "__init__.py")))
build/torch210-cxx11-cu126-x86_64-linux/metadata.json ADDED
@@ -0,0 +1,4 @@
 
 
 
 
 
1
+ {
2
+ "version": 1,
3
+ "python-depends": []
4
+ }
build/torch210-cxx11-cu128-x86_64-linux/__init__.py ADDED
@@ -0,0 +1,55 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Compute directly on the packed blocks of a GGUF checkpoint.
2
+
3
+ A GGUF weight is stored as blocks of 32 or 256 values sharing a scale. These kernels read that
4
+ layout as it is, so a quantized model can be loaded and run without ever materializing a dense
5
+ copy — which is the whole memory saving.
6
+
7
+ Ported from llama.cpp's ggml-cuda; `vendor/UPSTREAM` pins the revision. The ops are named for what
8
+ they do rather than for a backend: each backend registers its own implementation of the same
9
+ schema, so calls dispatch on the tensor's device.
10
+ """
11
+
12
+ import torch
13
+
14
+ from ._ops import add_op_namespace_prefix, ops
15
+
16
+
17
+ __all__ = ["GEMV_TYPES", "MAX_GEMV_ROWS", "dequantize", "mul_mat_vec"]
18
+
19
+ # Upstream's MMVQ_MAX_BATCH_SIZE: `mul_mat_vec` has no implementation beyond this many rows, so a
20
+ # caller with more (prefill) dequantizes and uses an ordinary matmul.
21
+ MAX_GEMV_ROWS = 8
22
+
23
+ # ggml type ids `mul_mat_vec` implements: Q4_0/Q4_1/Q5_0/Q5_1/Q8_0, the K quants, and the IQ quants.
24
+ # `dequantize` covers more, so check this one before choosing the fused path.
25
+ GEMV_TYPES = frozenset({2, 3, 6, 7, 8, 10, 11, 12, 13, 14, 16, 17, 18, 19, 20, 21, 22, 23, 29, 39, 40, 41, 42})
26
+
27
+
28
+ def dequantize(
29
+ blocks: torch.Tensor, ggml_type: int, rows: int, cols: int, dtype: torch.dtype
30
+ ) -> torch.Tensor:
31
+ """`(rows, bytes_per_row)` uint8 blocks -> `(rows, cols)` values of `dtype`."""
32
+ return ops.dequantize(blocks, ggml_type, rows, cols, dtype)
33
+
34
+
35
+ def mul_mat_vec(
36
+ blocks: torch.Tensor, x: torch.Tensor, ggml_type: int, out_features: int
37
+ ) -> torch.Tensor:
38
+ """Fused dequantize-gemv: `x @ blocks.T` without unpacking `blocks`.
39
+
40
+ `x` is `(rows, in_features)` and `rows` must be at most `MAX_GEMV_ROWS`. The result is f32
41
+ whatever `x`'s dtype was, since the kernel writes an f32 destination; cast it at the call site,
42
+ where the cast can be fused into whatever consumes it.
43
+ """
44
+ return ops.mul_mat_vec(blocks, x, ggml_type, out_features)
45
+
46
+
47
+ # Without these, torch.compile cannot trace the ops and breaks the graph at every call.
48
+ @torch.library.register_fake(add_op_namespace_prefix("dequantize"))
49
+ def _dequantize_fake(blocks, ggml_type, rows, cols, dtype):
50
+ return blocks.new_empty((rows, cols), dtype=dtype)
51
+
52
+
53
+ @torch.library.register_fake(add_op_namespace_prefix("mul_mat_vec"))
54
+ def _mul_mat_vec_fake(blocks, x, ggml_type, out_features):
55
+ return x.new_empty((x.shape[0], out_features), dtype=torch.float32)
build/torch210-cxx11-cu128-x86_64-linux/_gguf_kernels_20260805124229.abi3.so ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:b6cba7d21629a2a2269bd06de30ace18b373266c7e74e75e11f093cc27eec066
3
+ size 39064328
build/torch210-cxx11-cu128-x86_64-linux/_ops.py ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
 
1
+ import torch
2
+ from . import _gguf_kernels_20260805124229
3
+ ops = torch.ops._gguf_kernels_20260805124229
4
+
5
+ def add_op_namespace_prefix(op_name: str):
6
+ """
7
+ Prefix op by namespace.
8
+ """
9
+ return f"_gguf_kernels_20260805124229::{op_name}"
build/torch210-cxx11-cu128-x86_64-linux/gguf_kernels/__init__.py ADDED
@@ -0,0 +1,26 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import ctypes
2
+ import sys
3
+
4
+ import importlib
5
+ from pathlib import Path
6
+ from types import ModuleType
7
+
8
+ def _import_from_path(file_path: Path) -> ModuleType:
9
+ # We cannot use the module name as-is, after adding it to `sys.modules`,
10
+ # it would also be used for other imports. So, we make a module name that
11
+ # depends on the path for it to be unique using the hex-encoded hash of
12
+ # the path.
13
+ path_hash = "{:x}".format(ctypes.c_size_t(hash(file_path.absolute())).value)
14
+ module_name = path_hash
15
+ spec = importlib.util.spec_from_file_location(module_name, file_path)
16
+ if spec is None:
17
+ raise ImportError(f"Cannot load spec for {module_name} from {file_path}")
18
+ module = importlib.util.module_from_spec(spec)
19
+ if module is None:
20
+ raise ImportError(f"Cannot load module {module_name} from spec")
21
+ sys.modules[module_name] = module
22
+ spec.loader.exec_module(module) # type: ignore
23
+ return module
24
+
25
+
26
+ globals().update(vars(_import_from_path(Path(__file__).parent.parent / "__init__.py")))
build/torch210-cxx11-cu128-x86_64-linux/metadata.json ADDED
@@ -0,0 +1,4 @@
 
 
 
 
 
1
+ {
2
+ "version": 1,
3
+ "python-depends": []
4
+ }
build/torch210-cxx11-cu130-x86_64-linux/__init__.py ADDED
@@ -0,0 +1,55 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Compute directly on the packed blocks of a GGUF checkpoint.
2
+
3
+ A GGUF weight is stored as blocks of 32 or 256 values sharing a scale. These kernels read that
4
+ layout as it is, so a quantized model can be loaded and run without ever materializing a dense
5
+ copy — which is the whole memory saving.
6
+
7
+ Ported from llama.cpp's ggml-cuda; `vendor/UPSTREAM` pins the revision. The ops are named for what
8
+ they do rather than for a backend: each backend registers its own implementation of the same
9
+ schema, so calls dispatch on the tensor's device.
10
+ """
11
+
12
+ import torch
13
+
14
+ from ._ops import add_op_namespace_prefix, ops
15
+
16
+
17
+ __all__ = ["GEMV_TYPES", "MAX_GEMV_ROWS", "dequantize", "mul_mat_vec"]
18
+
19
+ # Upstream's MMVQ_MAX_BATCH_SIZE: `mul_mat_vec` has no implementation beyond this many rows, so a
20
+ # caller with more (prefill) dequantizes and uses an ordinary matmul.
21
+ MAX_GEMV_ROWS = 8
22
+
23
+ # ggml type ids `mul_mat_vec` implements: Q4_0/Q4_1/Q5_0/Q5_1/Q8_0, the K quants, and the IQ quants.
24
+ # `dequantize` covers more, so check this one before choosing the fused path.
25
+ GEMV_TYPES = frozenset({2, 3, 6, 7, 8, 10, 11, 12, 13, 14, 16, 17, 18, 19, 20, 21, 22, 23, 29, 39, 40, 41, 42})
26
+
27
+
28
+ def dequantize(
29
+ blocks: torch.Tensor, ggml_type: int, rows: int, cols: int, dtype: torch.dtype
30
+ ) -> torch.Tensor:
31
+ """`(rows, bytes_per_row)` uint8 blocks -> `(rows, cols)` values of `dtype`."""
32
+ return ops.dequantize(blocks, ggml_type, rows, cols, dtype)
33
+
34
+
35
+ def mul_mat_vec(
36
+ blocks: torch.Tensor, x: torch.Tensor, ggml_type: int, out_features: int
37
+ ) -> torch.Tensor:
38
+ """Fused dequantize-gemv: `x @ blocks.T` without unpacking `blocks`.
39
+
40
+ `x` is `(rows, in_features)` and `rows` must be at most `MAX_GEMV_ROWS`. The result is f32
41
+ whatever `x`'s dtype was, since the kernel writes an f32 destination; cast it at the call site,
42
+ where the cast can be fused into whatever consumes it.
43
+ """
44
+ return ops.mul_mat_vec(blocks, x, ggml_type, out_features)
45
+
46
+
47
+ # Without these, torch.compile cannot trace the ops and breaks the graph at every call.
48
+ @torch.library.register_fake(add_op_namespace_prefix("dequantize"))
49
+ def _dequantize_fake(blocks, ggml_type, rows, cols, dtype):
50
+ return blocks.new_empty((rows, cols), dtype=dtype)
51
+
52
+
53
+ @torch.library.register_fake(add_op_namespace_prefix("mul_mat_vec"))
54
+ def _mul_mat_vec_fake(blocks, x, ggml_type, out_features):
55
+ return x.new_empty((x.shape[0], out_features), dtype=torch.float32)
build/torch210-cxx11-cu130-x86_64-linux/_gguf_kernels_20260805124229.abi3.so ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:b4e935328add4b20b3761b3ab018967f2b61030491865b841c455e6a25702e4e
3
+ size 39318224
build/torch210-cxx11-cu130-x86_64-linux/_ops.py ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
 
1
+ import torch
2
+ from . import _gguf_kernels_20260805124229
3
+ ops = torch.ops._gguf_kernels_20260805124229
4
+
5
+ def add_op_namespace_prefix(op_name: str):
6
+ """
7
+ Prefix op by namespace.
8
+ """
9
+ return f"_gguf_kernels_20260805124229::{op_name}"
build/torch210-cxx11-cu130-x86_64-linux/gguf_kernels/__init__.py ADDED
@@ -0,0 +1,26 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import ctypes
2
+ import sys
3
+
4
+ import importlib
5
+ from pathlib import Path
6
+ from types import ModuleType
7
+
8
+ def _import_from_path(file_path: Path) -> ModuleType:
9
+ # We cannot use the module name as-is, after adding it to `sys.modules`,
10
+ # it would also be used for other imports. So, we make a module name that
11
+ # depends on the path for it to be unique using the hex-encoded hash of
12
+ # the path.
13
+ path_hash = "{:x}".format(ctypes.c_size_t(hash(file_path.absolute())).value)
14
+ module_name = path_hash
15
+ spec = importlib.util.spec_from_file_location(module_name, file_path)
16
+ if spec is None:
17
+ raise ImportError(f"Cannot load spec for {module_name} from {file_path}")
18
+ module = importlib.util.module_from_spec(spec)
19
+ if module is None:
20
+ raise ImportError(f"Cannot load module {module_name} from spec")
21
+ sys.modules[module_name] = module
22
+ spec.loader.exec_module(module) # type: ignore
23
+ return module
24
+
25
+
26
+ globals().update(vars(_import_from_path(Path(__file__).parent.parent / "__init__.py")))
build/torch210-cxx11-cu130-x86_64-linux/metadata.json ADDED
@@ -0,0 +1,4 @@
 
 
 
 
 
1
+ {
2
+ "version": 1,
3
+ "python-depends": []
4
+ }
build/torch28-cxx11-cu126-x86_64-linux/__init__.py ADDED
@@ -0,0 +1,55 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Compute directly on the packed blocks of a GGUF checkpoint.
2
+
3
+ A GGUF weight is stored as blocks of 32 or 256 values sharing a scale. These kernels read that
4
+ layout as it is, so a quantized model can be loaded and run without ever materializing a dense
5
+ copy — which is the whole memory saving.
6
+
7
+ Ported from llama.cpp's ggml-cuda; `vendor/UPSTREAM` pins the revision. The ops are named for what
8
+ they do rather than for a backend: each backend registers its own implementation of the same
9
+ schema, so calls dispatch on the tensor's device.
10
+ """
11
+
12
+ import torch
13
+
14
+ from ._ops import add_op_namespace_prefix, ops
15
+
16
+
17
+ __all__ = ["GEMV_TYPES", "MAX_GEMV_ROWS", "dequantize", "mul_mat_vec"]
18
+
19
+ # Upstream's MMVQ_MAX_BATCH_SIZE: `mul_mat_vec` has no implementation beyond this many rows, so a
20
+ # caller with more (prefill) dequantizes and uses an ordinary matmul.
21
+ MAX_GEMV_ROWS = 8
22
+
23
+ # ggml type ids `mul_mat_vec` implements: Q4_0/Q4_1/Q5_0/Q5_1/Q8_0, the K quants, and the IQ quants.
24
+ # `dequantize` covers more, so check this one before choosing the fused path.
25
+ GEMV_TYPES = frozenset({2, 3, 6, 7, 8, 10, 11, 12, 13, 14, 16, 17, 18, 19, 20, 21, 22, 23, 29, 39, 40, 41, 42})
26
+
27
+
28
+ def dequantize(
29
+ blocks: torch.Tensor, ggml_type: int, rows: int, cols: int, dtype: torch.dtype
30
+ ) -> torch.Tensor:
31
+ """`(rows, bytes_per_row)` uint8 blocks -> `(rows, cols)` values of `dtype`."""
32
+ return ops.dequantize(blocks, ggml_type, rows, cols, dtype)
33
+
34
+
35
+ def mul_mat_vec(
36
+ blocks: torch.Tensor, x: torch.Tensor, ggml_type: int, out_features: int
37
+ ) -> torch.Tensor:
38
+ """Fused dequantize-gemv: `x @ blocks.T` without unpacking `blocks`.
39
+
40
+ `x` is `(rows, in_features)` and `rows` must be at most `MAX_GEMV_ROWS`. The result is f32
41
+ whatever `x`'s dtype was, since the kernel writes an f32 destination; cast it at the call site,
42
+ where the cast can be fused into whatever consumes it.
43
+ """
44
+ return ops.mul_mat_vec(blocks, x, ggml_type, out_features)
45
+
46
+
47
+ # Without these, torch.compile cannot trace the ops and breaks the graph at every call.
48
+ @torch.library.register_fake(add_op_namespace_prefix("dequantize"))
49
+ def _dequantize_fake(blocks, ggml_type, rows, cols, dtype):
50
+ return blocks.new_empty((rows, cols), dtype=dtype)
51
+
52
+
53
+ @torch.library.register_fake(add_op_namespace_prefix("mul_mat_vec"))
54
+ def _mul_mat_vec_fake(blocks, x, ggml_type, out_features):
55
+ return x.new_empty((x.shape[0], out_features), dtype=torch.float32)
build/torch28-cxx11-cu126-x86_64-linux/_gguf_kernels_20260805124229.abi3.so ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:6708d42e7390b3a6fe316852e3857716defd991e5861031c8d04a1e7b4e0260f
3
+ size 26686512
build/torch28-cxx11-cu126-x86_64-linux/_ops.py ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
 
1
+ import torch
2
+ from . import _gguf_kernels_20260805124229
3
+ ops = torch.ops._gguf_kernels_20260805124229
4
+
5
+ def add_op_namespace_prefix(op_name: str):
6
+ """
7
+ Prefix op by namespace.
8
+ """
9
+ return f"_gguf_kernels_20260805124229::{op_name}"
build/torch28-cxx11-cu126-x86_64-linux/gguf_kernels/__init__.py ADDED
@@ -0,0 +1,26 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import ctypes
2
+ import sys
3
+
4
+ import importlib
5
+ from pathlib import Path
6
+ from types import ModuleType
7
+
8
+ def _import_from_path(file_path: Path) -> ModuleType:
9
+ # We cannot use the module name as-is, after adding it to `sys.modules`,
10
+ # it would also be used for other imports. So, we make a module name that
11
+ # depends on the path for it to be unique using the hex-encoded hash of
12
+ # the path.
13
+ path_hash = "{:x}".format(ctypes.c_size_t(hash(file_path.absolute())).value)
14
+ module_name = path_hash
15
+ spec = importlib.util.spec_from_file_location(module_name, file_path)
16
+ if spec is None:
17
+ raise ImportError(f"Cannot load spec for {module_name} from {file_path}")
18
+ module = importlib.util.module_from_spec(spec)
19
+ if module is None:
20
+ raise ImportError(f"Cannot load module {module_name} from spec")
21
+ sys.modules[module_name] = module
22
+ spec.loader.exec_module(module) # type: ignore
23
+ return module
24
+
25
+
26
+ globals().update(vars(_import_from_path(Path(__file__).parent.parent / "__init__.py")))
build/torch28-cxx11-cu126-x86_64-linux/metadata.json ADDED
@@ -0,0 +1,4 @@
 
 
 
 
 
1
+ {
2
+ "version": 1,
3
+ "python-depends": []
4
+ }
build/torch28-cxx11-cu128-x86_64-linux/__init__.py ADDED
@@ -0,0 +1,55 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Compute directly on the packed blocks of a GGUF checkpoint.
2
+
3
+ A GGUF weight is stored as blocks of 32 or 256 values sharing a scale. These kernels read that
4
+ layout as it is, so a quantized model can be loaded and run without ever materializing a dense
5
+ copy — which is the whole memory saving.
6
+
7
+ Ported from llama.cpp's ggml-cuda; `vendor/UPSTREAM` pins the revision. The ops are named for what
8
+ they do rather than for a backend: each backend registers its own implementation of the same
9
+ schema, so calls dispatch on the tensor's device.
10
+ """
11
+
12
+ import torch
13
+
14
+ from ._ops import add_op_namespace_prefix, ops
15
+
16
+
17
+ __all__ = ["GEMV_TYPES", "MAX_GEMV_ROWS", "dequantize", "mul_mat_vec"]
18
+
19
+ # Upstream's MMVQ_MAX_BATCH_SIZE: `mul_mat_vec` has no implementation beyond this many rows, so a
20
+ # caller with more (prefill) dequantizes and uses an ordinary matmul.
21
+ MAX_GEMV_ROWS = 8
22
+
23
+ # ggml type ids `mul_mat_vec` implements: Q4_0/Q4_1/Q5_0/Q5_1/Q8_0, the K quants, and the IQ quants.
24
+ # `dequantize` covers more, so check this one before choosing the fused path.
25
+ GEMV_TYPES = frozenset({2, 3, 6, 7, 8, 10, 11, 12, 13, 14, 16, 17, 18, 19, 20, 21, 22, 23, 29, 39, 40, 41, 42})
26
+
27
+
28
+ def dequantize(
29
+ blocks: torch.Tensor, ggml_type: int, rows: int, cols: int, dtype: torch.dtype
30
+ ) -> torch.Tensor:
31
+ """`(rows, bytes_per_row)` uint8 blocks -> `(rows, cols)` values of `dtype`."""
32
+ return ops.dequantize(blocks, ggml_type, rows, cols, dtype)
33
+
34
+
35
+ def mul_mat_vec(
36
+ blocks: torch.Tensor, x: torch.Tensor, ggml_type: int, out_features: int
37
+ ) -> torch.Tensor:
38
+ """Fused dequantize-gemv: `x @ blocks.T` without unpacking `blocks`.
39
+
40
+ `x` is `(rows, in_features)` and `rows` must be at most `MAX_GEMV_ROWS`. The result is f32
41
+ whatever `x`'s dtype was, since the kernel writes an f32 destination; cast it at the call site,
42
+ where the cast can be fused into whatever consumes it.
43
+ """
44
+ return ops.mul_mat_vec(blocks, x, ggml_type, out_features)
45
+
46
+
47
+ # Without these, torch.compile cannot trace the ops and breaks the graph at every call.
48
+ @torch.library.register_fake(add_op_namespace_prefix("dequantize"))
49
+ def _dequantize_fake(blocks, ggml_type, rows, cols, dtype):
50
+ return blocks.new_empty((rows, cols), dtype=dtype)
51
+
52
+
53
+ @torch.library.register_fake(add_op_namespace_prefix("mul_mat_vec"))
54
+ def _mul_mat_vec_fake(blocks, x, ggml_type, out_features):
55
+ return x.new_empty((x.shape[0], out_features), dtype=torch.float32)
build/torch28-cxx11-cu128-x86_64-linux/_gguf_kernels_20260805124229.abi3.so ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:964ea6025655311cfebe2fb58eca589ace6d208222d793134a48925309ccf910
3
+ size 39054016
build/torch28-cxx11-cu128-x86_64-linux/_ops.py ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
 
1
+ import torch
2
+ from . import _gguf_kernels_20260805124229
3
+ ops = torch.ops._gguf_kernels_20260805124229
4
+
5
+ def add_op_namespace_prefix(op_name: str):
6
+ """
7
+ Prefix op by namespace.
8
+ """
9
+ return f"_gguf_kernels_20260805124229::{op_name}"
build/torch28-cxx11-cu128-x86_64-linux/gguf_kernels/__init__.py ADDED
@@ -0,0 +1,26 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import ctypes
2
+ import sys
3
+
4
+ import importlib
5
+ from pathlib import Path
6
+ from types import ModuleType
7
+
8
+ def _import_from_path(file_path: Path) -> ModuleType:
9
+ # We cannot use the module name as-is, after adding it to `sys.modules`,
10
+ # it would also be used for other imports. So, we make a module name that
11
+ # depends on the path for it to be unique using the hex-encoded hash of
12
+ # the path.
13
+ path_hash = "{:x}".format(ctypes.c_size_t(hash(file_path.absolute())).value)
14
+ module_name = path_hash
15
+ spec = importlib.util.spec_from_file_location(module_name, file_path)
16
+ if spec is None:
17
+ raise ImportError(f"Cannot load spec for {module_name} from {file_path}")
18
+ module = importlib.util.module_from_spec(spec)
19
+ if module is None:
20
+ raise ImportError(f"Cannot load module {module_name} from spec")
21
+ sys.modules[module_name] = module
22
+ spec.loader.exec_module(module) # type: ignore
23
+ return module
24
+
25
+
26
+ globals().update(vars(_import_from_path(Path(__file__).parent.parent / "__init__.py")))
build/torch28-cxx11-cu128-x86_64-linux/metadata.json ADDED
@@ -0,0 +1,4 @@
 
 
 
 
 
1
+ {
2
+ "version": 1,
3
+ "python-depends": []
4
+ }
build/torch28-cxx11-cu129-x86_64-linux/__init__.py ADDED
@@ -0,0 +1,55 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Compute directly on the packed blocks of a GGUF checkpoint.
2
+
3
+ A GGUF weight is stored as blocks of 32 or 256 values sharing a scale. These kernels read that
4
+ layout as it is, so a quantized model can be loaded and run without ever materializing a dense
5
+ copy — which is the whole memory saving.
6
+
7
+ Ported from llama.cpp's ggml-cuda; `vendor/UPSTREAM` pins the revision. The ops are named for what
8
+ they do rather than for a backend: each backend registers its own implementation of the same
9
+ schema, so calls dispatch on the tensor's device.
10
+ """
11
+
12
+ import torch
13
+
14
+ from ._ops import add_op_namespace_prefix, ops
15
+
16
+
17
+ __all__ = ["GEMV_TYPES", "MAX_GEMV_ROWS", "dequantize", "mul_mat_vec"]
18
+
19
+ # Upstream's MMVQ_MAX_BATCH_SIZE: `mul_mat_vec` has no implementation beyond this many rows, so a
20
+ # caller with more (prefill) dequantizes and uses an ordinary matmul.
21
+ MAX_GEMV_ROWS = 8
22
+
23
+ # ggml type ids `mul_mat_vec` implements: Q4_0/Q4_1/Q5_0/Q5_1/Q8_0, the K quants, and the IQ quants.
24
+ # `dequantize` covers more, so check this one before choosing the fused path.
25
+ GEMV_TYPES = frozenset({2, 3, 6, 7, 8, 10, 11, 12, 13, 14, 16, 17, 18, 19, 20, 21, 22, 23, 29, 39, 40, 41, 42})
26
+
27
+
28
+ def dequantize(
29
+ blocks: torch.Tensor, ggml_type: int, rows: int, cols: int, dtype: torch.dtype
30
+ ) -> torch.Tensor:
31
+ """`(rows, bytes_per_row)` uint8 blocks -> `(rows, cols)` values of `dtype`."""
32
+ return ops.dequantize(blocks, ggml_type, rows, cols, dtype)
33
+
34
+
35
+ def mul_mat_vec(
36
+ blocks: torch.Tensor, x: torch.Tensor, ggml_type: int, out_features: int
37
+ ) -> torch.Tensor:
38
+ """Fused dequantize-gemv: `x @ blocks.T` without unpacking `blocks`.
39
+
40
+ `x` is `(rows, in_features)` and `rows` must be at most `MAX_GEMV_ROWS`. The result is f32
41
+ whatever `x`'s dtype was, since the kernel writes an f32 destination; cast it at the call site,
42
+ where the cast can be fused into whatever consumes it.
43
+ """
44
+ return ops.mul_mat_vec(blocks, x, ggml_type, out_features)
45
+
46
+
47
+ # Without these, torch.compile cannot trace the ops and breaks the graph at every call.
48
+ @torch.library.register_fake(add_op_namespace_prefix("dequantize"))
49
+ def _dequantize_fake(blocks, ggml_type, rows, cols, dtype):
50
+ return blocks.new_empty((rows, cols), dtype=dtype)
51
+
52
+
53
+ @torch.library.register_fake(add_op_namespace_prefix("mul_mat_vec"))
54
+ def _mul_mat_vec_fake(blocks, x, ggml_type, out_features):
55
+ return x.new_empty((x.shape[0], out_features), dtype=torch.float32)
build/torch28-cxx11-cu129-x86_64-linux/_gguf_kernels_20260805124229.abi3.so ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:51b5f28bd29d9373e0a9a5046e7314af5061350b340646ab98dfa391fd4f8670
3
+ size 38993592
build/torch28-cxx11-cu129-x86_64-linux/_ops.py ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
 
1
+ import torch
2
+ from . import _gguf_kernels_20260805124229
3
+ ops = torch.ops._gguf_kernels_20260805124229
4
+
5
+ def add_op_namespace_prefix(op_name: str):
6
+ """
7
+ Prefix op by namespace.
8
+ """
9
+ return f"_gguf_kernels_20260805124229::{op_name}"
build/torch28-cxx11-cu129-x86_64-linux/gguf_kernels/__init__.py ADDED
@@ -0,0 +1,26 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import ctypes
2
+ import sys
3
+
4
+ import importlib
5
+ from pathlib import Path
6
+ from types import ModuleType
7
+
8
+ def _import_from_path(file_path: Path) -> ModuleType:
9
+ # We cannot use the module name as-is, after adding it to `sys.modules`,
10
+ # it would also be used for other imports. So, we make a module name that
11
+ # depends on the path for it to be unique using the hex-encoded hash of
12
+ # the path.
13
+ path_hash = "{:x}".format(ctypes.c_size_t(hash(file_path.absolute())).value)
14
+ module_name = path_hash
15
+ spec = importlib.util.spec_from_file_location(module_name, file_path)
16
+ if spec is None:
17
+ raise ImportError(f"Cannot load spec for {module_name} from {file_path}")
18
+ module = importlib.util.module_from_spec(spec)
19
+ if module is None:
20
+ raise ImportError(f"Cannot load module {module_name} from spec")
21
+ sys.modules[module_name] = module
22
+ spec.loader.exec_module(module) # type: ignore
23
+ return module
24
+
25
+
26
+ globals().update(vars(_import_from_path(Path(__file__).parent.parent / "__init__.py")))
build/torch28-cxx11-cu129-x86_64-linux/metadata.json ADDED
@@ -0,0 +1,4 @@
 
 
 
 
 
1
+ {
2
+ "version": 1,
3
+ "python-depends": []
4
+ }
build/torch29-cxx11-cu126-x86_64-linux/__init__.py ADDED
@@ -0,0 +1,55 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Compute directly on the packed blocks of a GGUF checkpoint.
2
+
3
+ A GGUF weight is stored as blocks of 32 or 256 values sharing a scale. These kernels read that
4
+ layout as it is, so a quantized model can be loaded and run without ever materializing a dense
5
+ copy — which is the whole memory saving.
6
+
7
+ Ported from llama.cpp's ggml-cuda; `vendor/UPSTREAM` pins the revision. The ops are named for what
8
+ they do rather than for a backend: each backend registers its own implementation of the same
9
+ schema, so calls dispatch on the tensor's device.
10
+ """
11
+
12
+ import torch
13
+
14
+ from ._ops import add_op_namespace_prefix, ops
15
+
16
+
17
+ __all__ = ["GEMV_TYPES", "MAX_GEMV_ROWS", "dequantize", "mul_mat_vec"]
18
+
19
+ # Upstream's MMVQ_MAX_BATCH_SIZE: `mul_mat_vec` has no implementation beyond this many rows, so a
20
+ # caller with more (prefill) dequantizes and uses an ordinary matmul.
21
+ MAX_GEMV_ROWS = 8
22
+
23
+ # ggml type ids `mul_mat_vec` implements: Q4_0/Q4_1/Q5_0/Q5_1/Q8_0, the K quants, and the IQ quants.
24
+ # `dequantize` covers more, so check this one before choosing the fused path.
25
+ GEMV_TYPES = frozenset({2, 3, 6, 7, 8, 10, 11, 12, 13, 14, 16, 17, 18, 19, 20, 21, 22, 23, 29, 39, 40, 41, 42})
26
+
27
+
28
+ def dequantize(
29
+ blocks: torch.Tensor, ggml_type: int, rows: int, cols: int, dtype: torch.dtype
30
+ ) -> torch.Tensor:
31
+ """`(rows, bytes_per_row)` uint8 blocks -> `(rows, cols)` values of `dtype`."""
32
+ return ops.dequantize(blocks, ggml_type, rows, cols, dtype)
33
+
34
+
35
+ def mul_mat_vec(
36
+ blocks: torch.Tensor, x: torch.Tensor, ggml_type: int, out_features: int
37
+ ) -> torch.Tensor:
38
+ """Fused dequantize-gemv: `x @ blocks.T` without unpacking `blocks`.
39
+
40
+ `x` is `(rows, in_features)` and `rows` must be at most `MAX_GEMV_ROWS`. The result is f32
41
+ whatever `x`'s dtype was, since the kernel writes an f32 destination; cast it at the call site,
42
+ where the cast can be fused into whatever consumes it.
43
+ """
44
+ return ops.mul_mat_vec(blocks, x, ggml_type, out_features)
45
+
46
+
47
+ # Without these, torch.compile cannot trace the ops and breaks the graph at every call.
48
+ @torch.library.register_fake(add_op_namespace_prefix("dequantize"))
49
+ def _dequantize_fake(blocks, ggml_type, rows, cols, dtype):
50
+ return blocks.new_empty((rows, cols), dtype=dtype)
51
+
52
+
53
+ @torch.library.register_fake(add_op_namespace_prefix("mul_mat_vec"))
54
+ def _mul_mat_vec_fake(blocks, x, ggml_type, out_features):
55
+ return x.new_empty((x.shape[0], out_features), dtype=torch.float32)
build/torch29-cxx11-cu126-x86_64-linux/_gguf_kernels_20260805124229.abi3.so ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:d7435e6aeaab83f149782dd9d4dd926012315c0e9162b2a141dcbc961da18ea9
3
+ size 26690648
build/torch29-cxx11-cu126-x86_64-linux/_ops.py ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
 
1
+ import torch
2
+ from . import _gguf_kernels_20260805124229
3
+ ops = torch.ops._gguf_kernels_20260805124229
4
+
5
+ def add_op_namespace_prefix(op_name: str):
6
+ """
7
+ Prefix op by namespace.
8
+ """
9
+ return f"_gguf_kernels_20260805124229::{op_name}"
build/torch29-cxx11-cu126-x86_64-linux/gguf_kernels/__init__.py ADDED
@@ -0,0 +1,26 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import ctypes
2
+ import sys
3
+
4
+ import importlib
5
+ from pathlib import Path
6
+ from types import ModuleType
7
+
8
+ def _import_from_path(file_path: Path) -> ModuleType:
9
+ # We cannot use the module name as-is, after adding it to `sys.modules`,
10
+ # it would also be used for other imports. So, we make a module name that
11
+ # depends on the path for it to be unique using the hex-encoded hash of
12
+ # the path.
13
+ path_hash = "{:x}".format(ctypes.c_size_t(hash(file_path.absolute())).value)
14
+ module_name = path_hash
15
+ spec = importlib.util.spec_from_file_location(module_name, file_path)
16
+ if spec is None:
17
+ raise ImportError(f"Cannot load spec for {module_name} from {file_path}")
18
+ module = importlib.util.module_from_spec(spec)
19
+ if module is None:
20
+ raise ImportError(f"Cannot load module {module_name} from spec")
21
+ sys.modules[module_name] = module
22
+ spec.loader.exec_module(module) # type: ignore
23
+ return module
24
+
25
+
26
+ globals().update(vars(_import_from_path(Path(__file__).parent.parent / "__init__.py")))
build/torch29-cxx11-cu126-x86_64-linux/metadata.json ADDED
@@ -0,0 +1,4 @@
 
 
 
 
 
1
+ {
2
+ "version": 1,
3
+ "python-depends": []
4
+ }
build/torch29-cxx11-cu128-x86_64-linux/__init__.py ADDED
@@ -0,0 +1,55 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Compute directly on the packed blocks of a GGUF checkpoint.
2
+
3
+ A GGUF weight is stored as blocks of 32 or 256 values sharing a scale. These kernels read that
4
+ layout as it is, so a quantized model can be loaded and run without ever materializing a dense
5
+ copy — which is the whole memory saving.
6
+
7
+ Ported from llama.cpp's ggml-cuda; `vendor/UPSTREAM` pins the revision. The ops are named for what
8
+ they do rather than for a backend: each backend registers its own implementation of the same
9
+ schema, so calls dispatch on the tensor's device.
10
+ """
11
+
12
+ import torch
13
+
14
+ from ._ops import add_op_namespace_prefix, ops
15
+
16
+
17
+ __all__ = ["GEMV_TYPES", "MAX_GEMV_ROWS", "dequantize", "mul_mat_vec"]
18
+
19
+ # Upstream's MMVQ_MAX_BATCH_SIZE: `mul_mat_vec` has no implementation beyond this many rows, so a
20
+ # caller with more (prefill) dequantizes and uses an ordinary matmul.
21
+ MAX_GEMV_ROWS = 8
22
+
23
+ # ggml type ids `mul_mat_vec` implements: Q4_0/Q4_1/Q5_0/Q5_1/Q8_0, the K quants, and the IQ quants.
24
+ # `dequantize` covers more, so check this one before choosing the fused path.
25
+ GEMV_TYPES = frozenset({2, 3, 6, 7, 8, 10, 11, 12, 13, 14, 16, 17, 18, 19, 20, 21, 22, 23, 29, 39, 40, 41, 42})
26
+
27
+
28
+ def dequantize(
29
+ blocks: torch.Tensor, ggml_type: int, rows: int, cols: int, dtype: torch.dtype
30
+ ) -> torch.Tensor:
31
+ """`(rows, bytes_per_row)` uint8 blocks -> `(rows, cols)` values of `dtype`."""
32
+ return ops.dequantize(blocks, ggml_type, rows, cols, dtype)
33
+
34
+
35
+ def mul_mat_vec(
36
+ blocks: torch.Tensor, x: torch.Tensor, ggml_type: int, out_features: int
37
+ ) -> torch.Tensor:
38
+ """Fused dequantize-gemv: `x @ blocks.T` without unpacking `blocks`.
39
+
40
+ `x` is `(rows, in_features)` and `rows` must be at most `MAX_GEMV_ROWS`. The result is f32
41
+ whatever `x`'s dtype was, since the kernel writes an f32 destination; cast it at the call site,
42
+ where the cast can be fused into whatever consumes it.
43
+ """
44
+ return ops.mul_mat_vec(blocks, x, ggml_type, out_features)
45
+
46
+
47
+ # Without these, torch.compile cannot trace the ops and breaks the graph at every call.
48
+ @torch.library.register_fake(add_op_namespace_prefix("dequantize"))
49
+ def _dequantize_fake(blocks, ggml_type, rows, cols, dtype):
50
+ return blocks.new_empty((rows, cols), dtype=dtype)
51
+
52
+
53
+ @torch.library.register_fake(add_op_namespace_prefix("mul_mat_vec"))
54
+ def _mul_mat_vec_fake(blocks, x, ggml_type, out_features):
55
+ return x.new_empty((x.shape[0], out_features), dtype=torch.float32)
build/torch29-cxx11-cu128-x86_64-linux/_gguf_kernels_20260805124229.abi3.so ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:1c141779c8750668e8681e6b803bdac2b6105ee861ff3331b59c0375493392a8
3
+ size 39058144
build/torch29-cxx11-cu128-x86_64-linux/_ops.py ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
 
1
+ import torch
2
+ from . import _gguf_kernels_20260805124229
3
+ ops = torch.ops._gguf_kernels_20260805124229
4
+
5
+ def add_op_namespace_prefix(op_name: str):
6
+ """
7
+ Prefix op by namespace.
8
+ """
9
+ return f"_gguf_kernels_20260805124229::{op_name}"
build/torch29-cxx11-cu128-x86_64-linux/gguf_kernels/__init__.py ADDED
@@ -0,0 +1,26 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import ctypes
2
+ import sys
3
+
4
+ import importlib
5
+ from pathlib import Path
6
+ from types import ModuleType
7
+
8
+ def _import_from_path(file_path: Path) -> ModuleType:
9
+ # We cannot use the module name as-is, after adding it to `sys.modules`,
10
+ # it would also be used for other imports. So, we make a module name that
11
+ # depends on the path for it to be unique using the hex-encoded hash of
12
+ # the path.
13
+ path_hash = "{:x}".format(ctypes.c_size_t(hash(file_path.absolute())).value)
14
+ module_name = path_hash
15
+ spec = importlib.util.spec_from_file_location(module_name, file_path)
16
+ if spec is None:
17
+ raise ImportError(f"Cannot load spec for {module_name} from {file_path}")
18
+ module = importlib.util.module_from_spec(spec)
19
+ if module is None:
20
+ raise ImportError(f"Cannot load module {module_name} from spec")
21
+ sys.modules[module_name] = module
22
+ spec.loader.exec_module(module) # type: ignore
23
+ return module
24
+
25
+
26
+ globals().update(vars(_import_from_path(Path(__file__).parent.parent / "__init__.py")))
build/torch29-cxx11-cu128-x86_64-linux/metadata.json ADDED
@@ -0,0 +1,4 @@
 
 
 
 
 
1
+ {
2
+ "version": 1,
3
+ "python-depends": []
4
+ }
build/torch29-cxx11-cu130-x86_64-linux/__init__.py ADDED
@@ -0,0 +1,55 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Compute directly on the packed blocks of a GGUF checkpoint.
2
+
3
+ A GGUF weight is stored as blocks of 32 or 256 values sharing a scale. These kernels read that
4
+ layout as it is, so a quantized model can be loaded and run without ever materializing a dense
5
+ copy — which is the whole memory saving.
6
+
7
+ Ported from llama.cpp's ggml-cuda; `vendor/UPSTREAM` pins the revision. The ops are named for what
8
+ they do rather than for a backend: each backend registers its own implementation of the same
9
+ schema, so calls dispatch on the tensor's device.
10
+ """
11
+
12
+ import torch
13
+
14
+ from ._ops import add_op_namespace_prefix, ops
15
+
16
+
17
+ __all__ = ["GEMV_TYPES", "MAX_GEMV_ROWS", "dequantize", "mul_mat_vec"]
18
+
19
+ # Upstream's MMVQ_MAX_BATCH_SIZE: `mul_mat_vec` has no implementation beyond this many rows, so a
20
+ # caller with more (prefill) dequantizes and uses an ordinary matmul.
21
+ MAX_GEMV_ROWS = 8
22
+
23
+ # ggml type ids `mul_mat_vec` implements: Q4_0/Q4_1/Q5_0/Q5_1/Q8_0, the K quants, and the IQ quants.
24
+ # `dequantize` covers more, so check this one before choosing the fused path.
25
+ GEMV_TYPES = frozenset({2, 3, 6, 7, 8, 10, 11, 12, 13, 14, 16, 17, 18, 19, 20, 21, 22, 23, 29, 39, 40, 41, 42})
26
+
27
+
28
+ def dequantize(
29
+ blocks: torch.Tensor, ggml_type: int, rows: int, cols: int, dtype: torch.dtype
30
+ ) -> torch.Tensor:
31
+ """`(rows, bytes_per_row)` uint8 blocks -> `(rows, cols)` values of `dtype`."""
32
+ return ops.dequantize(blocks, ggml_type, rows, cols, dtype)
33
+
34
+
35
+ def mul_mat_vec(
36
+ blocks: torch.Tensor, x: torch.Tensor, ggml_type: int, out_features: int
37
+ ) -> torch.Tensor:
38
+ """Fused dequantize-gemv: `x @ blocks.T` without unpacking `blocks`.
39
+
40
+ `x` is `(rows, in_features)` and `rows` must be at most `MAX_GEMV_ROWS`. The result is f32
41
+ whatever `x`'s dtype was, since the kernel writes an f32 destination; cast it at the call site,
42
+ where the cast can be fused into whatever consumes it.
43
+ """
44
+ return ops.mul_mat_vec(blocks, x, ggml_type, out_features)
45
+
46
+
47
+ # Without these, torch.compile cannot trace the ops and breaks the graph at every call.
48
+ @torch.library.register_fake(add_op_namespace_prefix("dequantize"))
49
+ def _dequantize_fake(blocks, ggml_type, rows, cols, dtype):
50
+ return blocks.new_empty((rows, cols), dtype=dtype)
51
+
52
+
53
+ @torch.library.register_fake(add_op_namespace_prefix("mul_mat_vec"))
54
+ def _mul_mat_vec_fake(blocks, x, ggml_type, out_features):
55
+ return x.new_empty((x.shape[0], out_features), dtype=torch.float32)
build/torch29-cxx11-cu130-x86_64-linux/_gguf_kernels_20260805124229.abi3.so ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:41f95273f40f722f1e7e64d5a9784f769ff48cbce511f383e88bd89b70495a8b
3
+ size 39312040