Marc Sun commited on
Commit
77f577c
·
1 Parent(s): e9319be

drop the cuda kernel: metal is the only backend built for now

Browse files

The cuda variants were shipped from a build nobody was running, and each rebuild had to keep them
alive to avoid committing stale artifacts. `git log -- gguf_cuda` still has the sources, and
`vendor/` keeps ggml's cuda tree, so re-adding the backend is a `build.toml` section again.

Files changed (46) hide show
  1. README.md +7 -5
  2. build.toml +4 -59
  3. build/torch211-cxx11-cu126-x86_64-linux/__init__.py +0 -55
  4. build/torch211-cxx11-cu126-x86_64-linux/_gguf_kernels_cuda_e4e2164.abi3.so +0 -3
  5. build/torch211-cxx11-cu126-x86_64-linux/_ops.py +0 -9
  6. build/torch211-cxx11-cu126-x86_64-linux/gguf_kernels/__init__.py +0 -26
  7. build/torch211-cxx11-cu126-x86_64-linux/metadata.json +0 -17
  8. build/torch211-cxx11-cu128-x86_64-linux/__init__.py +0 -55
  9. build/torch211-cxx11-cu128-x86_64-linux/_gguf_kernels_cuda_e4e2164.abi3.so +0 -3
  10. build/torch211-cxx11-cu128-x86_64-linux/_ops.py +0 -9
  11. build/torch211-cxx11-cu128-x86_64-linux/gguf_kernels/__init__.py +0 -26
  12. build/torch211-cxx11-cu128-x86_64-linux/metadata.json +0 -19
  13. build/torch211-cxx11-cu130-x86_64-linux/__init__.py +0 -55
  14. build/torch211-cxx11-cu130-x86_64-linux/_gguf_kernels_cuda_e4e2164.abi3.so +0 -3
  15. build/torch211-cxx11-cu130-x86_64-linux/_ops.py +0 -9
  16. build/torch211-cxx11-cu130-x86_64-linux/gguf_kernels/__init__.py +0 -26
  17. build/torch211-cxx11-cu130-x86_64-linux/metadata.json +0 -19
  18. build/torch212-cxx11-cu126-x86_64-linux/__init__.py +0 -62
  19. build/torch212-cxx11-cu126-x86_64-linux/_gguf_kernels_cuda_1df3b99.abi3.so +0 -3
  20. build/torch212-cxx11-cu126-x86_64-linux/_ops.py +0 -9
  21. build/torch212-cxx11-cu126-x86_64-linux/metadata.json +0 -36
  22. build/torch212-cxx11-cu130-x86_64-linux/__init__.py +0 -62
  23. build/torch212-cxx11-cu130-x86_64-linux/__pycache__/__init__.cpython-311.pyc +0 -0
  24. build/torch212-cxx11-cu130-x86_64-linux/__pycache__/_ops.cpython-311.pyc +0 -0
  25. build/torch212-cxx11-cu130-x86_64-linux/_gguf_kernels_cuda_1df3b99.abi3.so +0 -3
  26. build/torch212-cxx11-cu130-x86_64-linux/_ops.py +0 -9
  27. build/torch212-cxx11-cu130-x86_64-linux/metadata.json +0 -38
  28. build/torch212-cxx11-cu132-x86_64-linux/__init__.py +0 -62
  29. build/torch212-cxx11-cu132-x86_64-linux/_gguf_kernels_cuda_1df3b99.abi3.so +0 -3
  30. build/torch212-cxx11-cu132-x86_64-linux/_ops.py +0 -9
  31. build/torch212-cxx11-cu132-x86_64-linux/metadata.json +0 -38
  32. build/torch213-cxx11-cu126-x86_64-linux/__init__.py +0 -62
  33. build/torch213-cxx11-cu126-x86_64-linux/_gguf_kernels_cuda_1df3b99.abi3.so +0 -3
  34. build/torch213-cxx11-cu126-x86_64-linux/_ops.py +0 -9
  35. build/torch213-cxx11-cu126-x86_64-linux/metadata.json +0 -36
  36. build/torch213-cxx11-cu130-x86_64-linux/__init__.py +0 -62
  37. build/torch213-cxx11-cu130-x86_64-linux/_gguf_kernels_cuda_1df3b99.abi3.so +0 -3
  38. build/torch213-cxx11-cu130-x86_64-linux/_ops.py +0 -9
  39. build/torch213-cxx11-cu130-x86_64-linux/metadata.json +0 -38
  40. build/torch213-cxx11-cu132-x86_64-linux/__init__.py +0 -62
  41. build/torch213-cxx11-cu132-x86_64-linux/_gguf_kernels_cuda_1df3b99.abi3.so +0 -3
  42. build/torch213-cxx11-cu132-x86_64-linux/_ops.py +0 -9
  43. build/torch213-cxx11-cu132-x86_64-linux/metadata.json +0 -38
  44. gguf_cuda/ggml_dispatch.cu +0 -157
  45. gguf_cuda/ggml_stubs.cu +0 -192
  46. gguf_cuda/gguf_cuda.cu +0 -84
README.md CHANGED
@@ -16,6 +16,7 @@ materializing a dense copy of its weights.
16
  | op | signature |
17
  | --- | --- |
18
  | `dequantize` | `(blocks, ggml_type, rows, cols, dtype) -> (rows, cols)` |
 
19
  | `mul_mat_vec` | `(blocks, x, ggml_type, out_features) -> (rows, out_features)` f32, fused dequant-gemv |
20
 
21
  `blocks` is a GGUF weight exactly as stored: `(out_features, bytes_per_row)` uint8. `mul_mat_vec`
@@ -26,15 +27,16 @@ matmul. The quant types each backend implements a gemv for are in `GEMV_TYPES`.
26
 
27
  | backend | torch | targets |
28
  | --- | --- | --- |
29
- | CUDA | 2.11, 2.12 | x86_64-linux, cu126/128/130/132, sm 7.5–12.0 |
30
  | Metal | 2.12, 2.13 | aarch64-darwin |
31
 
 
 
32
  ## Where the kernels come from
33
 
34
  [llama.cpp](https://github.com/ggml-org/llama.cpp)'s ggml, vendored rather than reimplemented.
35
  `vendor/UPSTREAM` records the revision.
36
 
37
- CUDA compiles `ggml-cuda`'s sources; Metal compiles `ggml-metal.metal` into the embedded metallib.
38
  Only the files listed in `build.toml`'s `src` are built — the rest of the tree rides along so a pin
39
  bump cannot leave a dangling include.
40
 
@@ -45,6 +47,6 @@ python vendor.py --rev <llama.cpp commit> # re-vendor, updates vendor/UPSTREAM
45
  nix run .#build-and-copy # rebuild every variant into build/
46
  ```
47
 
48
- `vendor.py` copies whole trees plus one rename: upstream's `mmvq.cu` lands as `mmvq-impl.cuh`,
49
- because `gguf_cuda/ggml_dispatch.cu` `#include`s it instead of compiling it as its own translation
50
- unit.
 
16
  | op | signature |
17
  | --- | --- |
18
  | `dequantize` | `(blocks, ggml_type, rows, cols, dtype) -> (rows, cols)` |
19
+ | `get_rows` | `(blocks, indices, ggml_type, cols, dtype) -> (len(indices), cols)`, unpacks as it gathers |
20
  | `mul_mat_vec` | `(blocks, x, ggml_type, out_features) -> (rows, out_features)` f32, fused dequant-gemv |
21
 
22
  `blocks` is a GGUF weight exactly as stored: `(out_features, bytes_per_row)` uint8. `mul_mat_vec`
 
27
 
28
  | backend | torch | targets |
29
  | --- | --- | --- |
 
30
  | Metal | 2.12, 2.13 | aarch64-darwin |
31
 
32
+ Metal only for now: the cuda kernel is in `git log -- gguf_cuda`, not in this build.
33
+
34
  ## Where the kernels come from
35
 
36
  [llama.cpp](https://github.com/ggml-org/llama.cpp)'s ggml, vendored rather than reimplemented.
37
  `vendor/UPSTREAM` records the revision.
38
 
39
+ Metal compiles `ggml-metal.metal` into the embedded metallib.
40
  Only the files listed in `build.toml`'s `src` are built — the rest of the tree rides along so a pin
41
  bump cannot leave a dangling include.
42
 
 
47
  nix run .#build-and-copy # rebuild every variant into build/
48
  ```
49
 
50
+ `vendor.py` copies whole trees plus one rename: upstream's `mmvq.cu` lands as `mmvq-impl.cuh`, for a
51
+ cuda dispatch that `#include`s it instead of compiling it as its own translation unit. `vendor/` still
52
+ carries ggml's cuda sources, so the rename stays even with the cuda kernel gone.
build.toml CHANGED
@@ -9,7 +9,9 @@
9
  name = "ggml-quantization"
10
  version = 1
11
  license = "MIT"
12
- backends = ["cuda", "metal"]
 
 
13
 
14
  [general.hub]
15
  repo-id = "marcsun13/ggml-quantization"
@@ -20,68 +22,11 @@ src = [
20
  "torch-ext/torch_binding.h",
21
  ]
22
 
23
- [kernel.gguf_cuda]
24
- backend = "cuda"
25
- depends = ["torch"]
26
- cuda-capabilities = ["7.5", "8.0", "8.6", "8.9", "9.0", "10.0", "12.0"]
27
- include = ["gguf_cuda", "torch-ext", "vendor/include", "vendor/src", "vendor/src/ggml-cuda"]
28
- src = [
29
- "gguf_cuda/gguf_cuda.cu",
30
- "gguf_cuda/ggml_dispatch.cu",
31
- "gguf_cuda/ggml_stubs.cu",
32
- "vendor/src/ggml-cuda/convert.cu",
33
- "vendor/src/ggml-cuda/quantize.cu",
34
- # headers are listed so the builder stages them; only the files above are compiled
35
- "vendor/include/ggml-alloc.h",
36
- "vendor/include/ggml-backend.h",
37
- "vendor/include/ggml-cuda.h",
38
- "vendor/include/ggml.h",
39
- "vendor/include/gguf.h",
40
- "vendor/src/ggml-common.h",
41
- "vendor/src/ggml-cuda/common.cuh",
42
- "vendor/src/ggml-cuda/convert.cuh",
43
- "vendor/src/ggml-cuda/dequantize.cuh",
44
- "vendor/src/ggml-cuda/mma.cuh",
45
- "vendor/src/ggml-cuda/mmq-config-ampere.cuh",
46
- "vendor/src/ggml-cuda/mmq-config-blackwell.cuh",
47
- "vendor/src/ggml-cuda/mmq-config-cdna.cuh",
48
- "vendor/src/ggml-cuda/mmq-config-pascal.cuh",
49
- "vendor/src/ggml-cuda/mmq-config-rdna2.cuh",
50
- "vendor/src/ggml-cuda/mmq-config-rdna3-5.cuh",
51
- "vendor/src/ggml-cuda/mmq-config-rdna3.cuh",
52
- "vendor/src/ggml-cuda/mmq-config-rdna4.cuh",
53
- "vendor/src/ggml-cuda/mmq-load-tiles.cuh",
54
- "vendor/src/ggml-cuda/mmq-vec-dot.cuh",
55
- "vendor/src/ggml-cuda/mmq.cuh",
56
- "vendor/src/ggml-cuda/mmvf.cuh",
57
- "vendor/src/ggml-cuda/mmvq.cuh",
58
- "vendor/src/ggml-cuda/mmvq-impl.cuh",
59
- "vendor/src/ggml-cuda/quantize.cuh",
60
- "vendor/src/ggml-cuda/unary.cuh",
61
- "vendor/src/ggml-cuda/vecdotq.cuh",
62
- "vendor/src/ggml-cuda/vendors/cuda.h",
63
- "vendor/src/ggml-impl.h",
64
- ]
65
- # ggml's half/bfloat16 arithmetic needs the operators torch's build disables
66
- cuda-flags = [
67
- "-DGGML_USE_CUDA",
68
- "-DNDEBUG",
69
- "-U__CUDA_NO_HALF_OPERATORS__",
70
- "-U__CUDA_NO_HALF_CONVERSIONS__",
71
- "-U__CUDA_NO_HALF2_OPERATORS__",
72
- "-U__CUDA_NO_BFLOAT16_CONVERSIONS__",
73
- "-U__CUDA_NO_BFLOAT16_OPERATORS__",
74
- "-U__CUDA_NO_BFLOAT162_OPERATORS__",
75
- "--expt-relaxed-constexpr",
76
- "--expt-extended-lambda",
77
- ]
78
- cxx-flags = ["-DGGML_USE_CUDA", "-DNDEBUG"]
79
-
80
  [kernel.gguf_metal]
81
  backend = "metal"
82
  depends = ["torch"]
83
  # ggml-metal.metal includes "ggml-common.h" from vendor/src, so the shader compile needs it
84
- # on its include path just as the cuda sources do.
85
  include = ["gguf_metal", "torch-ext", "vendor/include", "vendor/src", "vendor/src/ggml-metal"]
86
  src = [
87
  "gguf_metal/gguf_metal.cpp",
 
9
  name = "ggml-quantization"
10
  version = 1
11
  license = "MIT"
12
+ # Metal only for now. The cuda kernel and its build section were dropped rather than kept building
13
+ # untested -- `git log -- gguf_cuda` has them, and `vendor/` still carries ggml's cuda sources.
14
+ backends = ["metal"]
15
 
16
  [general.hub]
17
  repo-id = "marcsun13/ggml-quantization"
 
22
  "torch-ext/torch_binding.h",
23
  ]
24
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
25
  [kernel.gguf_metal]
26
  backend = "metal"
27
  depends = ["torch"]
28
  # ggml-metal.metal includes "ggml-common.h" from vendor/src, so the shader compile needs it
29
+ # on its include path.
30
  include = ["gguf_metal", "torch-ext", "vendor/include", "vendor/src", "vendor/src/ggml-metal"]
31
  src = [
32
  "gguf_metal/gguf_metal.cpp",
build/torch211-cxx11-cu126-x86_64-linux/__init__.py DELETED
@@ -1,55 +0,0 @@
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/torch211-cxx11-cu126-x86_64-linux/_gguf_kernels_cuda_e4e2164.abi3.so DELETED
@@ -1,3 +0,0 @@
1
- version https://git-lfs.github.com/spec/v1
2
- oid sha256:4bc09a45aabd708b54f9ce83b5ec9627ed185826b64aeb2b5673f46cad4c508e
3
- size 24799632
 
 
 
 
build/torch211-cxx11-cu126-x86_64-linux/_ops.py DELETED
@@ -1,9 +0,0 @@
1
- import torch
2
- from . import _gguf_kernels_cuda_e4e2164
3
- ops = torch.ops._gguf_kernels_cuda_e4e2164
4
-
5
- def add_op_namespace_prefix(op_name: str):
6
- """
7
- Prefix op by namespace.
8
- """
9
- return f"_gguf_kernels_cuda_e4e2164::{op_name}"
 
 
 
 
 
 
 
 
 
 
build/torch211-cxx11-cu126-x86_64-linux/gguf_kernels/__init__.py DELETED
@@ -1,26 +0,0 @@
1
- import ctypes
2
- import importlib.util
3
- import sys
4
- from pathlib import Path
5
- from types import ModuleType
6
-
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/torch211-cxx11-cu126-x86_64-linux/metadata.json DELETED
@@ -1,17 +0,0 @@
1
- {
2
- "name": "gguf-kernels",
3
- "id": "_gguf_kernels_cuda_e4e2164",
4
- "version": 1,
5
- "license": "MIT",
6
- "python-depends": [],
7
- "backend": {
8
- "type": "cuda",
9
- "archs": [
10
- "7.5",
11
- "8.0",
12
- "8.6",
13
- "8.9",
14
- "9.0"
15
- ]
16
- }
17
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
build/torch211-cxx11-cu128-x86_64-linux/__init__.py DELETED
@@ -1,55 +0,0 @@
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/torch211-cxx11-cu128-x86_64-linux/_gguf_kernels_cuda_e4e2164.abi3.so DELETED
@@ -1,3 +0,0 @@
1
- version https://git-lfs.github.com/spec/v1
2
- oid sha256:b71394062f24b9601e17ee704b313494487bbe77b8d20f54adbfd52665d9f300
3
- size 37124624
 
 
 
 
build/torch211-cxx11-cu128-x86_64-linux/_ops.py DELETED
@@ -1,9 +0,0 @@
1
- import torch
2
- from . import _gguf_kernels_cuda_e4e2164
3
- ops = torch.ops._gguf_kernels_cuda_e4e2164
4
-
5
- def add_op_namespace_prefix(op_name: str):
6
- """
7
- Prefix op by namespace.
8
- """
9
- return f"_gguf_kernels_cuda_e4e2164::{op_name}"
 
 
 
 
 
 
 
 
 
 
build/torch211-cxx11-cu128-x86_64-linux/gguf_kernels/__init__.py DELETED
@@ -1,26 +0,0 @@
1
- import ctypes
2
- import importlib.util
3
- import sys
4
- from pathlib import Path
5
- from types import ModuleType
6
-
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/torch211-cxx11-cu128-x86_64-linux/metadata.json DELETED
@@ -1,19 +0,0 @@
1
- {
2
- "name": "gguf-kernels",
3
- "id": "_gguf_kernels_cuda_e4e2164",
4
- "version": 1,
5
- "license": "MIT",
6
- "python-depends": [],
7
- "backend": {
8
- "type": "cuda",
9
- "archs": [
10
- "10.0",
11
- "12.0",
12
- "7.5",
13
- "8.0",
14
- "8.6",
15
- "8.9",
16
- "9.0"
17
- ]
18
- }
19
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
build/torch211-cxx11-cu130-x86_64-linux/__init__.py DELETED
@@ -1,55 +0,0 @@
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/torch211-cxx11-cu130-x86_64-linux/_gguf_kernels_cuda_e4e2164.abi3.so DELETED
@@ -1,3 +0,0 @@
1
- version https://git-lfs.github.com/spec/v1
2
- oid sha256:5b19aec224f81561100e3133d414393779bacfabf2c703040e64b95fe0b69cef
3
- size 37378504
 
 
 
 
build/torch211-cxx11-cu130-x86_64-linux/_ops.py DELETED
@@ -1,9 +0,0 @@
1
- import torch
2
- from . import _gguf_kernels_cuda_e4e2164
3
- ops = torch.ops._gguf_kernels_cuda_e4e2164
4
-
5
- def add_op_namespace_prefix(op_name: str):
6
- """
7
- Prefix op by namespace.
8
- """
9
- return f"_gguf_kernels_cuda_e4e2164::{op_name}"
 
 
 
 
 
 
 
 
 
 
build/torch211-cxx11-cu130-x86_64-linux/gguf_kernels/__init__.py DELETED
@@ -1,26 +0,0 @@
1
- import ctypes
2
- import importlib.util
3
- import sys
4
- from pathlib import Path
5
- from types import ModuleType
6
-
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/torch211-cxx11-cu130-x86_64-linux/metadata.json DELETED
@@ -1,19 +0,0 @@
1
- {
2
- "name": "gguf-kernels",
3
- "id": "_gguf_kernels_cuda_e4e2164",
4
- "version": 1,
5
- "license": "MIT",
6
- "python-depends": [],
7
- "backend": {
8
- "type": "cuda",
9
- "archs": [
10
- "10.0",
11
- "12.0",
12
- "7.5",
13
- "8.0",
14
- "8.6",
15
- "8.9",
16
- "9.0"
17
- ]
18
- }
19
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
build/torch212-cxx11-cu126-x86_64-linux/__init__.py DELETED
@@ -1,62 +0,0 @@
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, as this build reports them -- it is backend-specific, and
24
- # a type routed into a gemv that has no kernel for it is a fault, not a fallback. CUDA covers
25
- # Q4_0/Q4_1/Q5_0/Q5_1/Q8_0, the K quants, the IQ quants, MXFP4/NVFP4 and Q1_0/Q2_0; Metal is the
26
- # same minus NVFP4/Q1_0/Q2_0, which its metallib has no kernels for. `dequantize` covers more, so
27
- # check this before choosing the fused path.
28
- try:
29
- GEMV_TYPES = frozenset(ops.gemv_types())
30
- except AttributeError:
31
- # A build published before `gemv_types` existed; those are CUDA-only, so its list is theirs.
32
- 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})
33
-
34
-
35
- def dequantize(
36
- blocks: torch.Tensor, ggml_type: int, rows: int, cols: int, dtype: torch.dtype
37
- ) -> torch.Tensor:
38
- """`(rows, bytes_per_row)` uint8 blocks -> `(rows, cols)` values of `dtype`."""
39
- return ops.dequantize(blocks, ggml_type, rows, cols, dtype)
40
-
41
-
42
- def mul_mat_vec(
43
- blocks: torch.Tensor, x: torch.Tensor, ggml_type: int, out_features: int
44
- ) -> torch.Tensor:
45
- """Fused dequantize-gemv: `x @ blocks.T` without unpacking `blocks`.
46
-
47
- `x` is `(rows, in_features)` and `rows` must be at most `MAX_GEMV_ROWS`. The result is f32
48
- whatever `x`'s dtype was, since the kernel writes an f32 destination; cast it at the call site,
49
- where the cast can be fused into whatever consumes it.
50
- """
51
- return ops.mul_mat_vec(blocks, x, ggml_type, out_features)
52
-
53
-
54
- # Without these, torch.compile cannot trace the ops and breaks the graph at every call.
55
- @torch.library.register_fake(add_op_namespace_prefix("dequantize"))
56
- def _dequantize_fake(blocks, ggml_type, rows, cols, dtype):
57
- return blocks.new_empty((rows, cols), dtype=dtype)
58
-
59
-
60
- @torch.library.register_fake(add_op_namespace_prefix("mul_mat_vec"))
61
- def _mul_mat_vec_fake(blocks, x, ggml_type, out_features):
62
- return x.new_empty((x.shape[0], out_features), dtype=torch.float32)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
build/torch212-cxx11-cu126-x86_64-linux/_gguf_kernels_cuda_1df3b99.abi3.so DELETED
@@ -1,3 +0,0 @@
1
- version https://git-lfs.github.com/spec/v1
2
- oid sha256:a0dcdaf3e54554158476036dad0d2e6412aa42d4d1bfefa8d68e019e841283da
3
- size 24822056
 
 
 
 
build/torch212-cxx11-cu126-x86_64-linux/_ops.py DELETED
@@ -1,9 +0,0 @@
1
- import torch
2
- from . import _gguf_kernels_cuda_1df3b99
3
- ops = torch.ops._gguf_kernels_cuda_1df3b99
4
-
5
- def add_op_namespace_prefix(op_name: str):
6
- """
7
- Prefix op by namespace.
8
- """
9
- return f"_gguf_kernels_cuda_1df3b99::{op_name}"
 
 
 
 
 
 
 
 
 
 
build/torch212-cxx11-cu126-x86_64-linux/metadata.json DELETED
@@ -1,36 +0,0 @@
1
- {
2
- "name": "gguf-kernels",
3
- "id": "_gguf_kernels_cuda_1df3b99",
4
- "version": 1,
5
- "license": "MIT",
6
- "python-depends": [],
7
- "backend": {
8
- "type": "cuda",
9
- "archs": [
10
- "7.5",
11
- "8.0",
12
- "8.6",
13
- "8.9",
14
- "9.0"
15
- ]
16
- },
17
- "digest": {
18
- "algorithm": "sha256",
19
- "files": {
20
- "__init__.py": "GoFcHJbbJ9C8b40XNznMxsTcC+CV9kaFE8a1DP763kU=",
21
- "_gguf_kernels_cuda_1df3b99.abi3.so": "oNza8+VFVBWEdgNtrQ0uZBKqQtTRv++o1o4BnoQSg9o=",
22
- "_ops.py": "dRIZkil9x8IS6KhIwXlRzO6qzQoGYUQkGL87Z3gpEzY="
23
- }
24
- },
25
- "provenance": {
26
- "kernel-builder": {
27
- "version": "0.17.0-dev0",
28
- "sha": "81f55ea30fd8f819dcf93a3c934dd584c895bd2f",
29
- "dirty": false
30
- },
31
- "kernel": {
32
- "sha": "1df3b999686b77ef298ae13d066a39958503164c",
33
- "dirty": false
34
- }
35
- }
36
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
build/torch212-cxx11-cu130-x86_64-linux/__init__.py DELETED
@@ -1,62 +0,0 @@
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, as this build reports them -- it is backend-specific, and
24
- # a type routed into a gemv that has no kernel for it is a fault, not a fallback. CUDA covers
25
- # Q4_0/Q4_1/Q5_0/Q5_1/Q8_0, the K quants, the IQ quants, MXFP4/NVFP4 and Q1_0/Q2_0; Metal is the
26
- # same minus NVFP4/Q1_0/Q2_0, which its metallib has no kernels for. `dequantize` covers more, so
27
- # check this before choosing the fused path.
28
- try:
29
- GEMV_TYPES = frozenset(ops.gemv_types())
30
- except AttributeError:
31
- # A build published before `gemv_types` existed; those are CUDA-only, so its list is theirs.
32
- 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})
33
-
34
-
35
- def dequantize(
36
- blocks: torch.Tensor, ggml_type: int, rows: int, cols: int, dtype: torch.dtype
37
- ) -> torch.Tensor:
38
- """`(rows, bytes_per_row)` uint8 blocks -> `(rows, cols)` values of `dtype`."""
39
- return ops.dequantize(blocks, ggml_type, rows, cols, dtype)
40
-
41
-
42
- def mul_mat_vec(
43
- blocks: torch.Tensor, x: torch.Tensor, ggml_type: int, out_features: int
44
- ) -> torch.Tensor:
45
- """Fused dequantize-gemv: `x @ blocks.T` without unpacking `blocks`.
46
-
47
- `x` is `(rows, in_features)` and `rows` must be at most `MAX_GEMV_ROWS`. The result is f32
48
- whatever `x`'s dtype was, since the kernel writes an f32 destination; cast it at the call site,
49
- where the cast can be fused into whatever consumes it.
50
- """
51
- return ops.mul_mat_vec(blocks, x, ggml_type, out_features)
52
-
53
-
54
- # Without these, torch.compile cannot trace the ops and breaks the graph at every call.
55
- @torch.library.register_fake(add_op_namespace_prefix("dequantize"))
56
- def _dequantize_fake(blocks, ggml_type, rows, cols, dtype):
57
- return blocks.new_empty((rows, cols), dtype=dtype)
58
-
59
-
60
- @torch.library.register_fake(add_op_namespace_prefix("mul_mat_vec"))
61
- def _mul_mat_vec_fake(blocks, x, ggml_type, out_features):
62
- return x.new_empty((x.shape[0], out_features), dtype=torch.float32)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
build/torch212-cxx11-cu130-x86_64-linux/__pycache__/__init__.cpython-311.pyc DELETED
Binary file (3.26 kB)
 
build/torch212-cxx11-cu130-x86_64-linux/__pycache__/_ops.cpython-311.pyc DELETED
Binary file (574 Bytes)
 
build/torch212-cxx11-cu130-x86_64-linux/_gguf_kernels_cuda_1df3b99.abi3.so DELETED
@@ -1,3 +0,0 @@
1
- version https://git-lfs.github.com/spec/v1
2
- oid sha256:7355d69df74e88b5163248a7ada198f95c5310b2b182268e951ee7da67f4a537
3
- size 37396976
 
 
 
 
build/torch212-cxx11-cu130-x86_64-linux/_ops.py DELETED
@@ -1,9 +0,0 @@
1
- import torch
2
- from . import _gguf_kernels_cuda_1df3b99
3
- ops = torch.ops._gguf_kernels_cuda_1df3b99
4
-
5
- def add_op_namespace_prefix(op_name: str):
6
- """
7
- Prefix op by namespace.
8
- """
9
- return f"_gguf_kernels_cuda_1df3b99::{op_name}"
 
 
 
 
 
 
 
 
 
 
build/torch212-cxx11-cu130-x86_64-linux/metadata.json DELETED
@@ -1,38 +0,0 @@
1
- {
2
- "name": "gguf-kernels",
3
- "id": "_gguf_kernels_cuda_1df3b99",
4
- "version": 1,
5
- "license": "MIT",
6
- "python-depends": [],
7
- "backend": {
8
- "type": "cuda",
9
- "archs": [
10
- "10.0",
11
- "12.0",
12
- "7.5",
13
- "8.0",
14
- "8.6",
15
- "8.9",
16
- "9.0"
17
- ]
18
- },
19
- "digest": {
20
- "algorithm": "sha256",
21
- "files": {
22
- "__init__.py": "GoFcHJbbJ9C8b40XNznMxsTcC+CV9kaFE8a1DP763kU=",
23
- "_gguf_kernels_cuda_1df3b99.abi3.so": "c1XWnfdOiLUWMkinraGY+VxTELKxgiaOlR7n2mf0pTc=",
24
- "_ops.py": "dRIZkil9x8IS6KhIwXlRzO6qzQoGYUQkGL87Z3gpEzY="
25
- }
26
- },
27
- "provenance": {
28
- "kernel-builder": {
29
- "version": "0.17.0-dev0",
30
- "sha": "81f55ea30fd8f819dcf93a3c934dd584c895bd2f",
31
- "dirty": false
32
- },
33
- "kernel": {
34
- "sha": "1df3b999686b77ef298ae13d066a39958503164c",
35
- "dirty": false
36
- }
37
- }
38
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
build/torch212-cxx11-cu132-x86_64-linux/__init__.py DELETED
@@ -1,62 +0,0 @@
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, as this build reports them -- it is backend-specific, and
24
- # a type routed into a gemv that has no kernel for it is a fault, not a fallback. CUDA covers
25
- # Q4_0/Q4_1/Q5_0/Q5_1/Q8_0, the K quants, the IQ quants, MXFP4/NVFP4 and Q1_0/Q2_0; Metal is the
26
- # same minus NVFP4/Q1_0/Q2_0, which its metallib has no kernels for. `dequantize` covers more, so
27
- # check this before choosing the fused path.
28
- try:
29
- GEMV_TYPES = frozenset(ops.gemv_types())
30
- except AttributeError:
31
- # A build published before `gemv_types` existed; those are CUDA-only, so its list is theirs.
32
- 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})
33
-
34
-
35
- def dequantize(
36
- blocks: torch.Tensor, ggml_type: int, rows: int, cols: int, dtype: torch.dtype
37
- ) -> torch.Tensor:
38
- """`(rows, bytes_per_row)` uint8 blocks -> `(rows, cols)` values of `dtype`."""
39
- return ops.dequantize(blocks, ggml_type, rows, cols, dtype)
40
-
41
-
42
- def mul_mat_vec(
43
- blocks: torch.Tensor, x: torch.Tensor, ggml_type: int, out_features: int
44
- ) -> torch.Tensor:
45
- """Fused dequantize-gemv: `x @ blocks.T` without unpacking `blocks`.
46
-
47
- `x` is `(rows, in_features)` and `rows` must be at most `MAX_GEMV_ROWS`. The result is f32
48
- whatever `x`'s dtype was, since the kernel writes an f32 destination; cast it at the call site,
49
- where the cast can be fused into whatever consumes it.
50
- """
51
- return ops.mul_mat_vec(blocks, x, ggml_type, out_features)
52
-
53
-
54
- # Without these, torch.compile cannot trace the ops and breaks the graph at every call.
55
- @torch.library.register_fake(add_op_namespace_prefix("dequantize"))
56
- def _dequantize_fake(blocks, ggml_type, rows, cols, dtype):
57
- return blocks.new_empty((rows, cols), dtype=dtype)
58
-
59
-
60
- @torch.library.register_fake(add_op_namespace_prefix("mul_mat_vec"))
61
- def _mul_mat_vec_fake(blocks, x, ggml_type, out_features):
62
- return x.new_empty((x.shape[0], out_features), dtype=torch.float32)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
build/torch212-cxx11-cu132-x86_64-linux/_gguf_kernels_cuda_1df3b99.abi3.so DELETED
@@ -1,3 +0,0 @@
1
- version https://git-lfs.github.com/spec/v1
2
- oid sha256:50a408d91abc14355e1b1666ac6aa591f61271f8333dc863f1e9395822f0b1a1
3
- size 37415488
 
 
 
 
build/torch212-cxx11-cu132-x86_64-linux/_ops.py DELETED
@@ -1,9 +0,0 @@
1
- import torch
2
- from . import _gguf_kernels_cuda_1df3b99
3
- ops = torch.ops._gguf_kernels_cuda_1df3b99
4
-
5
- def add_op_namespace_prefix(op_name: str):
6
- """
7
- Prefix op by namespace.
8
- """
9
- return f"_gguf_kernels_cuda_1df3b99::{op_name}"
 
 
 
 
 
 
 
 
 
 
build/torch212-cxx11-cu132-x86_64-linux/metadata.json DELETED
@@ -1,38 +0,0 @@
1
- {
2
- "name": "gguf-kernels",
3
- "id": "_gguf_kernels_cuda_1df3b99",
4
- "version": 1,
5
- "license": "MIT",
6
- "python-depends": [],
7
- "backend": {
8
- "type": "cuda",
9
- "archs": [
10
- "10.0",
11
- "12.0",
12
- "7.5",
13
- "8.0",
14
- "8.6",
15
- "8.9",
16
- "9.0"
17
- ]
18
- },
19
- "digest": {
20
- "algorithm": "sha256",
21
- "files": {
22
- "__init__.py": "GoFcHJbbJ9C8b40XNznMxsTcC+CV9kaFE8a1DP763kU=",
23
- "_gguf_kernels_cuda_1df3b99.abi3.so": "UKQI2Rq8FDVeGxZmrGqlkfYScfgzPchj8ek5WCLwsaE=",
24
- "_ops.py": "dRIZkil9x8IS6KhIwXlRzO6qzQoGYUQkGL87Z3gpEzY="
25
- }
26
- },
27
- "provenance": {
28
- "kernel-builder": {
29
- "version": "0.17.0-dev0",
30
- "sha": "81f55ea30fd8f819dcf93a3c934dd584c895bd2f",
31
- "dirty": false
32
- },
33
- "kernel": {
34
- "sha": "1df3b999686b77ef298ae13d066a39958503164c",
35
- "dirty": false
36
- }
37
- }
38
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
build/torch213-cxx11-cu126-x86_64-linux/__init__.py DELETED
@@ -1,62 +0,0 @@
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, as this build reports them -- it is backend-specific, and
24
- # a type routed into a gemv that has no kernel for it is a fault, not a fallback. CUDA covers
25
- # Q4_0/Q4_1/Q5_0/Q5_1/Q8_0, the K quants, the IQ quants, MXFP4/NVFP4 and Q1_0/Q2_0; Metal is the
26
- # same minus NVFP4/Q1_0/Q2_0, which its metallib has no kernels for. `dequantize` covers more, so
27
- # check this before choosing the fused path.
28
- try:
29
- GEMV_TYPES = frozenset(ops.gemv_types())
30
- except AttributeError:
31
- # A build published before `gemv_types` existed; those are CUDA-only, so its list is theirs.
32
- 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})
33
-
34
-
35
- def dequantize(
36
- blocks: torch.Tensor, ggml_type: int, rows: int, cols: int, dtype: torch.dtype
37
- ) -> torch.Tensor:
38
- """`(rows, bytes_per_row)` uint8 blocks -> `(rows, cols)` values of `dtype`."""
39
- return ops.dequantize(blocks, ggml_type, rows, cols, dtype)
40
-
41
-
42
- def mul_mat_vec(
43
- blocks: torch.Tensor, x: torch.Tensor, ggml_type: int, out_features: int
44
- ) -> torch.Tensor:
45
- """Fused dequantize-gemv: `x @ blocks.T` without unpacking `blocks`.
46
-
47
- `x` is `(rows, in_features)` and `rows` must be at most `MAX_GEMV_ROWS`. The result is f32
48
- whatever `x`'s dtype was, since the kernel writes an f32 destination; cast it at the call site,
49
- where the cast can be fused into whatever consumes it.
50
- """
51
- return ops.mul_mat_vec(blocks, x, ggml_type, out_features)
52
-
53
-
54
- # Without these, torch.compile cannot trace the ops and breaks the graph at every call.
55
- @torch.library.register_fake(add_op_namespace_prefix("dequantize"))
56
- def _dequantize_fake(blocks, ggml_type, rows, cols, dtype):
57
- return blocks.new_empty((rows, cols), dtype=dtype)
58
-
59
-
60
- @torch.library.register_fake(add_op_namespace_prefix("mul_mat_vec"))
61
- def _mul_mat_vec_fake(blocks, x, ggml_type, out_features):
62
- return x.new_empty((x.shape[0], out_features), dtype=torch.float32)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
build/torch213-cxx11-cu126-x86_64-linux/_gguf_kernels_cuda_1df3b99.abi3.so DELETED
@@ -1,3 +0,0 @@
1
- version https://git-lfs.github.com/spec/v1
2
- oid sha256:9a7b5651497660db8a6b4cbe857610fc5ac448d52c36ad44b16c6e199d0d09e6
3
- size 24821896
 
 
 
 
build/torch213-cxx11-cu126-x86_64-linux/_ops.py DELETED
@@ -1,9 +0,0 @@
1
- import torch
2
- from . import _gguf_kernels_cuda_1df3b99
3
- ops = torch.ops._gguf_kernels_cuda_1df3b99
4
-
5
- def add_op_namespace_prefix(op_name: str):
6
- """
7
- Prefix op by namespace.
8
- """
9
- return f"_gguf_kernels_cuda_1df3b99::{op_name}"
 
 
 
 
 
 
 
 
 
 
build/torch213-cxx11-cu126-x86_64-linux/metadata.json DELETED
@@ -1,36 +0,0 @@
1
- {
2
- "name": "gguf-kernels",
3
- "id": "_gguf_kernels_cuda_1df3b99",
4
- "version": 1,
5
- "license": "MIT",
6
- "python-depends": [],
7
- "backend": {
8
- "type": "cuda",
9
- "archs": [
10
- "7.5",
11
- "8.0",
12
- "8.6",
13
- "8.9",
14
- "9.0"
15
- ]
16
- },
17
- "digest": {
18
- "algorithm": "sha256",
19
- "files": {
20
- "__init__.py": "GoFcHJbbJ9C8b40XNznMxsTcC+CV9kaFE8a1DP763kU=",
21
- "_gguf_kernels_cuda_1df3b99.abi3.so": "mntWUUl2YNuKa0y+hXYQ/FrESNUsNq1EsWxuGZ0NCeY=",
22
- "_ops.py": "dRIZkil9x8IS6KhIwXlRzO6qzQoGYUQkGL87Z3gpEzY="
23
- }
24
- },
25
- "provenance": {
26
- "kernel-builder": {
27
- "version": "0.17.0-dev0",
28
- "sha": "81f55ea30fd8f819dcf93a3c934dd584c895bd2f",
29
- "dirty": false
30
- },
31
- "kernel": {
32
- "sha": "1df3b999686b77ef298ae13d066a39958503164c",
33
- "dirty": false
34
- }
35
- }
36
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
build/torch213-cxx11-cu130-x86_64-linux/__init__.py DELETED
@@ -1,62 +0,0 @@
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, as this build reports them -- it is backend-specific, and
24
- # a type routed into a gemv that has no kernel for it is a fault, not a fallback. CUDA covers
25
- # Q4_0/Q4_1/Q5_0/Q5_1/Q8_0, the K quants, the IQ quants, MXFP4/NVFP4 and Q1_0/Q2_0; Metal is the
26
- # same minus NVFP4/Q1_0/Q2_0, which its metallib has no kernels for. `dequantize` covers more, so
27
- # check this before choosing the fused path.
28
- try:
29
- GEMV_TYPES = frozenset(ops.gemv_types())
30
- except AttributeError:
31
- # A build published before `gemv_types` existed; those are CUDA-only, so its list is theirs.
32
- 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})
33
-
34
-
35
- def dequantize(
36
- blocks: torch.Tensor, ggml_type: int, rows: int, cols: int, dtype: torch.dtype
37
- ) -> torch.Tensor:
38
- """`(rows, bytes_per_row)` uint8 blocks -> `(rows, cols)` values of `dtype`."""
39
- return ops.dequantize(blocks, ggml_type, rows, cols, dtype)
40
-
41
-
42
- def mul_mat_vec(
43
- blocks: torch.Tensor, x: torch.Tensor, ggml_type: int, out_features: int
44
- ) -> torch.Tensor:
45
- """Fused dequantize-gemv: `x @ blocks.T` without unpacking `blocks`.
46
-
47
- `x` is `(rows, in_features)` and `rows` must be at most `MAX_GEMV_ROWS`. The result is f32
48
- whatever `x`'s dtype was, since the kernel writes an f32 destination; cast it at the call site,
49
- where the cast can be fused into whatever consumes it.
50
- """
51
- return ops.mul_mat_vec(blocks, x, ggml_type, out_features)
52
-
53
-
54
- # Without these, torch.compile cannot trace the ops and breaks the graph at every call.
55
- @torch.library.register_fake(add_op_namespace_prefix("dequantize"))
56
- def _dequantize_fake(blocks, ggml_type, rows, cols, dtype):
57
- return blocks.new_empty((rows, cols), dtype=dtype)
58
-
59
-
60
- @torch.library.register_fake(add_op_namespace_prefix("mul_mat_vec"))
61
- def _mul_mat_vec_fake(blocks, x, ggml_type, out_features):
62
- return x.new_empty((x.shape[0], out_features), dtype=torch.float32)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
build/torch213-cxx11-cu130-x86_64-linux/_gguf_kernels_cuda_1df3b99.abi3.so DELETED
@@ -1,3 +0,0 @@
1
- version https://git-lfs.github.com/spec/v1
2
- oid sha256:aa7b02e5b0e1976c3d244e697710bf692943a598e9a56fee5c475cbd0d63015c
3
- size 37396824
 
 
 
 
build/torch213-cxx11-cu130-x86_64-linux/_ops.py DELETED
@@ -1,9 +0,0 @@
1
- import torch
2
- from . import _gguf_kernels_cuda_1df3b99
3
- ops = torch.ops._gguf_kernels_cuda_1df3b99
4
-
5
- def add_op_namespace_prefix(op_name: str):
6
- """
7
- Prefix op by namespace.
8
- """
9
- return f"_gguf_kernels_cuda_1df3b99::{op_name}"
 
 
 
 
 
 
 
 
 
 
build/torch213-cxx11-cu130-x86_64-linux/metadata.json DELETED
@@ -1,38 +0,0 @@
1
- {
2
- "name": "gguf-kernels",
3
- "id": "_gguf_kernels_cuda_1df3b99",
4
- "version": 1,
5
- "license": "MIT",
6
- "python-depends": [],
7
- "backend": {
8
- "type": "cuda",
9
- "archs": [
10
- "10.0",
11
- "12.0",
12
- "7.5",
13
- "8.0",
14
- "8.6",
15
- "8.9",
16
- "9.0"
17
- ]
18
- },
19
- "digest": {
20
- "algorithm": "sha256",
21
- "files": {
22
- "__init__.py": "GoFcHJbbJ9C8b40XNznMxsTcC+CV9kaFE8a1DP763kU=",
23
- "_gguf_kernels_cuda_1df3b99.abi3.so": "qnsC5bDhl2w9JE5pdxC/aSlDpZjppW/uXEdcvQ1jAVw=",
24
- "_ops.py": "dRIZkil9x8IS6KhIwXlRzO6qzQoGYUQkGL87Z3gpEzY="
25
- }
26
- },
27
- "provenance": {
28
- "kernel-builder": {
29
- "version": "0.17.0-dev0",
30
- "sha": "81f55ea30fd8f819dcf93a3c934dd584c895bd2f",
31
- "dirty": false
32
- },
33
- "kernel": {
34
- "sha": "1df3b999686b77ef298ae13d066a39958503164c",
35
- "dirty": false
36
- }
37
- }
38
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
build/torch213-cxx11-cu132-x86_64-linux/__init__.py DELETED
@@ -1,62 +0,0 @@
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, as this build reports them -- it is backend-specific, and
24
- # a type routed into a gemv that has no kernel for it is a fault, not a fallback. CUDA covers
25
- # Q4_0/Q4_1/Q5_0/Q5_1/Q8_0, the K quants, the IQ quants, MXFP4/NVFP4 and Q1_0/Q2_0; Metal is the
26
- # same minus NVFP4/Q1_0/Q2_0, which its metallib has no kernels for. `dequantize` covers more, so
27
- # check this before choosing the fused path.
28
- try:
29
- GEMV_TYPES = frozenset(ops.gemv_types())
30
- except AttributeError:
31
- # A build published before `gemv_types` existed; those are CUDA-only, so its list is theirs.
32
- 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})
33
-
34
-
35
- def dequantize(
36
- blocks: torch.Tensor, ggml_type: int, rows: int, cols: int, dtype: torch.dtype
37
- ) -> torch.Tensor:
38
- """`(rows, bytes_per_row)` uint8 blocks -> `(rows, cols)` values of `dtype`."""
39
- return ops.dequantize(blocks, ggml_type, rows, cols, dtype)
40
-
41
-
42
- def mul_mat_vec(
43
- blocks: torch.Tensor, x: torch.Tensor, ggml_type: int, out_features: int
44
- ) -> torch.Tensor:
45
- """Fused dequantize-gemv: `x @ blocks.T` without unpacking `blocks`.
46
-
47
- `x` is `(rows, in_features)` and `rows` must be at most `MAX_GEMV_ROWS`. The result is f32
48
- whatever `x`'s dtype was, since the kernel writes an f32 destination; cast it at the call site,
49
- where the cast can be fused into whatever consumes it.
50
- """
51
- return ops.mul_mat_vec(blocks, x, ggml_type, out_features)
52
-
53
-
54
- # Without these, torch.compile cannot trace the ops and breaks the graph at every call.
55
- @torch.library.register_fake(add_op_namespace_prefix("dequantize"))
56
- def _dequantize_fake(blocks, ggml_type, rows, cols, dtype):
57
- return blocks.new_empty((rows, cols), dtype=dtype)
58
-
59
-
60
- @torch.library.register_fake(add_op_namespace_prefix("mul_mat_vec"))
61
- def _mul_mat_vec_fake(blocks, x, ggml_type, out_features):
62
- return x.new_empty((x.shape[0], out_features), dtype=torch.float32)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
build/torch213-cxx11-cu132-x86_64-linux/_gguf_kernels_cuda_1df3b99.abi3.so DELETED
@@ -1,3 +0,0 @@
1
- version https://git-lfs.github.com/spec/v1
2
- oid sha256:732504ad19d3eb0692fca0a1085cd27eeb838c068c6f27b657d9b8224504f629
3
- size 37415328
 
 
 
 
build/torch213-cxx11-cu132-x86_64-linux/_ops.py DELETED
@@ -1,9 +0,0 @@
1
- import torch
2
- from . import _gguf_kernels_cuda_1df3b99
3
- ops = torch.ops._gguf_kernels_cuda_1df3b99
4
-
5
- def add_op_namespace_prefix(op_name: str):
6
- """
7
- Prefix op by namespace.
8
- """
9
- return f"_gguf_kernels_cuda_1df3b99::{op_name}"
 
 
 
 
 
 
 
 
 
 
build/torch213-cxx11-cu132-x86_64-linux/metadata.json DELETED
@@ -1,38 +0,0 @@
1
- {
2
- "name": "gguf-kernels",
3
- "id": "_gguf_kernels_cuda_1df3b99",
4
- "version": 1,
5
- "license": "MIT",
6
- "python-depends": [],
7
- "backend": {
8
- "type": "cuda",
9
- "archs": [
10
- "10.0",
11
- "12.0",
12
- "7.5",
13
- "8.0",
14
- "8.6",
15
- "8.9",
16
- "9.0"
17
- ]
18
- },
19
- "digest": {
20
- "algorithm": "sha256",
21
- "files": {
22
- "__init__.py": "GoFcHJbbJ9C8b40XNznMxsTcC+CV9kaFE8a1DP763kU=",
23
- "_gguf_kernels_cuda_1df3b99.abi3.so": "cyUErRnT6waS/KChCFzSfuuDjAaMbye2V9m4IkUE9ik=",
24
- "_ops.py": "dRIZkil9x8IS6KhIwXlRzO6qzQoGYUQkGL87Z3gpEzY="
25
- }
26
- },
27
- "provenance": {
28
- "kernel-builder": {
29
- "version": "0.17.0-dev0",
30
- "sha": "81f55ea30fd8f819dcf93a3c934dd584c895bd2f",
31
- "dirty": false
32
- },
33
- "kernel": {
34
- "sha": "1df3b999686b77ef298ae13d066a39958503164c",
35
- "dirty": false
36
- }
37
- }
38
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
gguf_cuda/ggml_dispatch.cu DELETED
@@ -1,157 +0,0 @@
1
- /* Thin raw-pointer wrappers around llama.cpp's ggml-cuda kernels.
2
- *
3
- * This file is the only place that sees ggml headers; the torch bindings call these
4
- * extern "C" entry points, so torch and ggml headers never meet. Upstream sources are
5
- * used unmodified: mmvq.cu is #include'd because its raw-pointer dispatch
6
- * (mul_mat_vec_q_switch_type) is static, and patching upstream would make syncing harder.
7
- *
8
- * Scratch buffers (q8_1 activations) are allocated by the caller so they come from torch's
9
- * caching allocator and stay capturable in a CUDA graph.
10
- */
11
-
12
- #include "common.cuh"
13
- #include "convert.cuh"
14
- #include "quantize.cuh"
15
-
16
- #include "mmvq-impl.cuh" // upstream mmvq.cu, renamed by vendor.py: #include’d, never its own TU
17
-
18
- #include <cstdint>
19
-
20
- enum gguf_dtype { GGUF_DTYPE_F32 = 0, GGUF_DTYPE_F16 = 1, GGUF_DTYPE_BF16 = 2 };
21
-
22
- // ---------------------------------------------------------------------------
23
- // q8_1 activation quantization, templated on the input dtype.
24
- //
25
- // Upstream's quantize_row_q8_1_cuda only accepts f32 (llama.cpp's graph always feeds f32
26
- // activations). Ours are bf16, and at M=1 a separate .to(float) pass costs more than the
27
- // matmul itself — everything here is launch-bound, so the win is in doing fewer kernels.
28
- // Same math and same block_q8_1 layout as upstream, restricted to the contiguous 2D case.
29
- // ---------------------------------------------------------------------------
30
-
31
- template <typename src_t>
32
- static __global__ void quantize_q8_1_typed(const src_t * __restrict__ x, void * __restrict__ vy,
33
- const int64_t ne00, const int64_t ne0) {
34
- const int64_t i0 = (int64_t) blockDim.x * blockIdx.x + threadIdx.x;
35
- if (i0 >= ne0) {
36
- return;
37
- }
38
- const int64_t i1 = blockIdx.y; // row
39
- const int64_t i_cont = i1 * ne0 + i0;
40
-
41
- block_q8_1 * y = (block_q8_1 *) vy;
42
-
43
- const int64_t ib = i_cont / QK8_1;
44
- const int64_t iqs = i_cont % QK8_1;
45
-
46
- const float xi = i0 < ne00 ? ggml_cuda_cast<float>(x[i1 * ne00 + i0]) : 0.0f;
47
- float amax = fabsf(xi);
48
- float sum = xi;
49
-
50
- amax = warp_reduce_max<QK8_1>(amax);
51
- sum = warp_reduce_sum<QK8_1>(sum);
52
-
53
- const float d = amax / 127.0f;
54
- const int8_t q = amax == 0.0f ? 0 : roundf(xi / d);
55
-
56
- y[ib].qs[iqs] = q;
57
-
58
- if (iqs > 0) {
59
- return;
60
- }
61
- y[ib].ds = make_half2(d, sum);
62
- }
63
-
64
- template <typename src_t>
65
- static void launch_quantize_q8_1(const void * x, void * vy, int64_t K, int64_t k_padded, int64_t M,
66
- cudaStream_t stream) {
67
- const dim3 num_blocks((k_padded + CUDA_QUANTIZE_BLOCK_SIZE - 1) / CUDA_QUANTIZE_BLOCK_SIZE, M, 1);
68
- const dim3 block_size(CUDA_QUANTIZE_BLOCK_SIZE, 1, 1);
69
- quantize_q8_1_typed<src_t><<<num_blocks, block_size, 0, stream>>>((const src_t *) x, vy, K, k_padded);
70
- }
71
-
72
- extern "C" {
73
-
74
- // ---------------------------------------------------------------------------
75
- // dequantize: packed blocks -> dense f32/f16/bf16
76
- // ---------------------------------------------------------------------------
77
-
78
- int gguf_dequantize_cuda(const void * w, void * out, int type, int64_t n_elems, int out_dtype,
79
- cudaStream_t stream) {
80
- const ggml_type t = (ggml_type) type;
81
- switch (out_dtype) {
82
- case GGUF_DTYPE_F32: {
83
- to_fp32_cuda_t f = ggml_get_to_fp32_cuda(t);
84
- if (!f) return -1;
85
- f(w, (float *) out, n_elems, stream);
86
- return 0;
87
- }
88
- case GGUF_DTYPE_F16: {
89
- to_fp16_cuda_t f = ggml_get_to_fp16_cuda(t);
90
- if (!f) return -1;
91
- f(w, (half *) out, n_elems, stream);
92
- return 0;
93
- }
94
- case GGUF_DTYPE_BF16: {
95
- to_bf16_cuda_t f = ggml_get_to_bf16_cuda(t);
96
- if (!f) return -1;
97
- f(w, (nv_bfloat16 *) out, n_elems, stream);
98
- return 0;
99
- }
100
- default:
101
- return -1;
102
- }
103
- }
104
-
105
- // ---------------------------------------------------------------------------
106
- // mmvq: fused dequant-gemv over packed blocks. M (ncols_dst) must be <= 8.
107
- // W is (N rows, K cols) quantized row-major; x is (M, K) f32/f16/bf16; dst is (M, N) f32
108
- // (the upstream kernel hard-codes a float dst; casting is left to the caller, where
109
- // torch.compile can fuse it into the consumer).
110
- // ---------------------------------------------------------------------------
111
-
112
- // bytes of q8_1 scratch needed for the quantized activations
113
- size_t gguf_q8_1_scratch_bytes(int64_t K, int64_t M) {
114
- const int64_t k_padded = GGML_PAD(K, MATRIX_ROW_PADDING);
115
- return (size_t) (M * k_padded) * sizeof(block_q8_1) / QK8_1;
116
- }
117
-
118
- int gguf_mul_mat_vec_q_cuda(const void * w, const void * x, int x_dtype, float * dst,
119
- void * q8_scratch, int type, int64_t K, int64_t N, int64_t M,
120
- cudaStream_t stream) {
121
- const ggml_type t = (ggml_type) type;
122
- if (M > MMVQ_MAX_BATCH_SIZE) return -1;
123
- const int64_t blck = ggml_blck_size(t);
124
- if (blck <= 0 || K % blck != 0) return -1;
125
-
126
- const int64_t k_padded = GGML_PAD(K, MATRIX_ROW_PADDING);
127
-
128
- switch (x_dtype) {
129
- case GGUF_DTYPE_F32: launch_quantize_q8_1<float> (x, q8_scratch, K, k_padded, M, stream); break;
130
- case GGUF_DTYPE_F16: launch_quantize_q8_1<half> (x, q8_scratch, K, k_padded, M, stream); break;
131
- case GGUF_DTYPE_BF16: launch_quantize_q8_1<nv_bfloat16> (x, q8_scratch, K, k_padded, M, stream); break;
132
- default: return -1;
133
- }
134
-
135
- const int64_t s01 = K / blck; // src0 row stride, in blocks
136
- const int64_t s11 = k_padded / QK8_1; // q8_1 row stride, in blocks
137
- const int64_t s1 = N; // dst row stride, in floats
138
-
139
- ggml_cuda_mm_fusion_args_device fusion{};
140
-
141
- mul_mat_vec_q_switch_type(
142
- w, t, q8_scratch, /*ids=*/nullptr, fusion, dst,
143
- /*ncols_x=*/K, /*nrows_x=*/N, /*ncols_dst=*/M,
144
- /*stride_row_x=*/s01, /*stride_col_y=*/s11, /*stride_col_dst=*/s1,
145
- /*nchannels_x=*/1, /*nchannels_y=*/1, /*nchannels_dst=*/1,
146
- /*stride_channel_x=*/N * s01, /*stride_channel_y=*/M * s11, /*stride_channel_dst=*/M * s1,
147
- /*nsamples_x=*/1, /*nsamples_dst=*/1,
148
- /*stride_sample_x=*/N * s01, /*stride_sample_y=*/M * s11, /*stride_sample_dst=*/M * s1,
149
- /*ids_stride=*/0, stream);
150
- return 0;
151
- }
152
-
153
- // NOTE: mmq (quantized gemm) and mmf (dense gemm) are deliberately not ported: both take a
154
- // ggml_backend_cuda_context for their pool allocator, which would pull in the whole ggml backend.
155
- // Above MMVQ_MAX_BATCH_SIZE rows the caller dequantizes and uses an ordinary matmul.
156
-
157
- } // extern "C"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
gguf_cuda/ggml_stubs.cu DELETED
@@ -1,192 +0,0 @@
1
- /* Minimal replacements for the ggml symbols that llama.cpp's ggml-cuda kernels reference,
2
- * so those kernels can be built as a standalone torch extension with no libggml and no
3
- * ggml backend/scheduler runtime.
4
- *
5
- * The kernels only need:
6
- * - ggml_cuda_info() / ggml_cuda_get_device() / ggml_cuda_set_device() (declared in common.cuh,
7
- * defined in ggml-cuda.cu, which would drag in the entire backend)
8
- * - a few ggml core type traits from ggml.c
9
- *
10
- * Everything else in common.cuh is inline/template.
11
- */
12
-
13
- #include "common.cuh"
14
-
15
- #include <cstdio>
16
- #include <cstdlib>
17
- #include <mutex>
18
-
19
- // ---------------------------------------------------------------------------
20
- // device info
21
- // ---------------------------------------------------------------------------
22
-
23
- static ggml_cuda_device_info build_device_info() {
24
- ggml_cuda_device_info info = {};
25
-
26
- int device_count = 0;
27
- if (cudaGetDeviceCount(&device_count) != cudaSuccess) {
28
- fprintf(stderr, "%s: cudaGetDeviceCount failed\n", __func__);
29
- return info;
30
- }
31
- info.device_count = device_count;
32
- info.physical_device_count = device_count;
33
-
34
- for (int id = 0; id < device_count; ++id) {
35
- cudaDeviceProp prop;
36
- CUDA_CHECK(cudaGetDeviceProperties(&prop, id));
37
-
38
- info.default_tensor_split[id] = float(id) / float(device_count);
39
-
40
- info.devices[id].nsm = prop.multiProcessorCount;
41
- info.devices[id].smpb = prop.sharedMemPerBlock;
42
- info.devices[id].smpbo = prop.sharedMemPerBlockOptin;
43
- info.devices[id].warp_size = prop.warpSize;
44
- info.devices[id].integrated = prop.integrated;
45
- info.devices[id].vmm = false; // no virtual memory pool here
46
- info.devices[id].vmm_granularity = 0;
47
- info.devices[id].total_vram = prop.totalGlobalMem;
48
- info.devices[id].supports_cooperative_launch = prop.cooperativeLaunch;
49
- info.devices[id].physical_device = id;
50
- info.devices[id].physical_share_count = 1;
51
- info.devices[id].virtual_index = 0;
52
- info.devices[id].cc = 100 * prop.major + 10 * prop.minor;
53
- }
54
- return info;
55
- }
56
-
57
- const ggml_cuda_device_info & ggml_cuda_info() {
58
- static ggml_cuda_device_info info = build_device_info();
59
- return info;
60
- }
61
-
62
- int ggml_cuda_get_device() {
63
- int id = 0;
64
- CUDA_CHECK(cudaGetDevice(&id));
65
- return id;
66
- }
67
-
68
- void ggml_cuda_set_device(int device) {
69
- int current = 0;
70
- CUDA_CHECK(cudaGetDevice(&current));
71
- if (current == device) {
72
- return;
73
- }
74
- CUDA_CHECK(cudaSetDevice(device));
75
- }
76
-
77
- // ---------------------------------------------------------------------------
78
- // ggml core type traits (subset of ggml.c). Values come from the block structs and QK_*
79
- // macros in ggml-common.h, so they cannot drift from the kernels that consume them.
80
- // ---------------------------------------------------------------------------
81
-
82
- #define GGML_TRAIT(t, blck_, size_, quant_) \
83
- case GGML_TYPE_##t: return trait{ blck_, size_, quant_ };
84
-
85
- namespace {
86
- struct trait {
87
- int64_t blck;
88
- size_t size;
89
- bool quantized;
90
- };
91
-
92
- trait type_trait(ggml_type type) {
93
- switch (type) {
94
- GGML_TRAIT(F32, 1, sizeof(float), false)
95
- GGML_TRAIT(F16, 1, sizeof(half), false)
96
- GGML_TRAIT(BF16, 1, sizeof(nv_bfloat16), false)
97
- GGML_TRAIT(I8, 1, sizeof(int8_t), false)
98
- GGML_TRAIT(I16, 1, sizeof(int16_t), false)
99
- GGML_TRAIT(I32, 1, sizeof(int32_t), false)
100
- GGML_TRAIT(I64, 1, sizeof(int64_t), false)
101
- GGML_TRAIT(F64, 1, sizeof(double), false)
102
- GGML_TRAIT(Q1_0, QK1_0, sizeof(block_q1_0), true)
103
- GGML_TRAIT(Q2_0, QK2_0, sizeof(block_q2_0), true)
104
- GGML_TRAIT(Q4_0, QK4_0, sizeof(block_q4_0), true)
105
- GGML_TRAIT(Q4_1, QK4_1, sizeof(block_q4_1), true)
106
- GGML_TRAIT(Q5_0, QK5_0, sizeof(block_q5_0), true)
107
- GGML_TRAIT(Q5_1, QK5_1, sizeof(block_q5_1), true)
108
- GGML_TRAIT(Q8_0, QK8_0, sizeof(block_q8_0), true)
109
- GGML_TRAIT(Q8_1, QK8_1, sizeof(block_q8_1), true)
110
- GGML_TRAIT(Q2_K, QK_K, sizeof(block_q2_K), true)
111
- GGML_TRAIT(Q3_K, QK_K, sizeof(block_q3_K), true)
112
- GGML_TRAIT(Q4_K, QK_K, sizeof(block_q4_K), true)
113
- GGML_TRAIT(Q5_K, QK_K, sizeof(block_q5_K), true)
114
- GGML_TRAIT(Q6_K, QK_K, sizeof(block_q6_K), true)
115
- GGML_TRAIT(Q8_K, QK_K, sizeof(block_q8_K), true)
116
- GGML_TRAIT(IQ1_S, QK_K, sizeof(block_iq1_s), true)
117
- GGML_TRAIT(IQ1_M, QK_K, sizeof(block_iq1_m), true)
118
- GGML_TRAIT(IQ2_XXS, QK_K, sizeof(block_iq2_xxs), true)
119
- GGML_TRAIT(IQ2_XS, QK_K, sizeof(block_iq2_xs), true)
120
- GGML_TRAIT(IQ2_S, QK_K, sizeof(block_iq2_s), true)
121
- GGML_TRAIT(IQ3_XXS, QK_K, sizeof(block_iq3_xxs), true)
122
- GGML_TRAIT(IQ3_S, QK_K, sizeof(block_iq3_s), true)
123
- GGML_TRAIT(IQ4_NL, QK4_NL, sizeof(block_iq4_nl), true)
124
- GGML_TRAIT(IQ4_XS, QK_K, sizeof(block_iq4_xs), true)
125
- GGML_TRAIT(TQ1_0, QK_K, sizeof(block_tq1_0), true)
126
- GGML_TRAIT(TQ2_0, QK_K, sizeof(block_tq2_0), true)
127
- GGML_TRAIT(MXFP4, QK_MXFP4, sizeof(block_mxfp4), true)
128
- GGML_TRAIT(NVFP4, QK_NVFP4, sizeof(block_nvfp4), true)
129
- default: return trait{ 0, 0, false }; // callers must reject blck == 0
130
- }
131
- }
132
- } // namespace
133
-
134
- extern "C" {
135
-
136
- int64_t ggml_blck_size(enum ggml_type type) { return type_trait(type).blck; }
137
- size_t ggml_type_size(enum ggml_type type) { return type_trait(type).size; }
138
- bool ggml_is_quantized(enum ggml_type type) { return type_trait(type).quantized; }
139
-
140
- // Referenced only by ggml's own error/abort messages.
141
- const char * ggml_type_name(enum ggml_type type) {
142
- switch (type) {
143
- case GGML_TYPE_F32: return "f32";
144
- case GGML_TYPE_F16: return "f16";
145
- case GGML_TYPE_BF16: return "bf16";
146
- case GGML_TYPE_Q4_K: return "q4_K";
147
- case GGML_TYPE_Q5_K: return "q5_K";
148
- case GGML_TYPE_Q6_K: return "q6_K";
149
- case GGML_TYPE_Q8_0: return "q8_0";
150
- default: return "unknown";
151
- }
152
- }
153
-
154
- void ggml_abort(const char * file, int line, const char * fmt, ...) {
155
- fprintf(stderr, "ggml abort at %s:%d: %s\n", file, line, fmt ? fmt : "");
156
- abort();
157
- }
158
-
159
- } // extern "C"
160
-
161
- [[noreturn]] void ggml_cuda_error(const char * stmt, const char * func, const char * file, int line,
162
- const char * msg) {
163
- fprintf(stderr, "CUDA error: %s\n %s at %s:%d\n %s\n", msg, func, file, line, stmt);
164
- abort();
165
- }
166
-
167
- // ---------------------------------------------------------------------------
168
- // Stubs. These are referenced only by the ggml_tensor-based entry points in mmvq.cu
169
- // (ggml_cuda_mul_mat_vec_q / ggml_cuda_op_mul_mat_vec_q), which get compiled but are never
170
- // called — we go straight to the raw-pointer dispatch. If one of them ever runs, abort loudly
171
- // rather than silently misbehave.
172
- // ---------------------------------------------------------------------------
173
-
174
- #define GGML_SHIM_UNREACHABLE(name) \
175
- do { \
176
- fprintf(stderr, "ggml-quantization: %s is a stub and must not be called\n", name); \
177
- abort(); \
178
- } while (0)
179
-
180
- extern "C" {
181
- int64_t ggml_nelements(const ggml_tensor *) { GGML_SHIM_UNREACHABLE("ggml_nelements"); }
182
- size_t ggml_nbytes(const ggml_tensor *) { GGML_SHIM_UNREACHABLE("ggml_nbytes"); }
183
- bool ggml_is_contiguous(const ggml_tensor *) { GGML_SHIM_UNREACHABLE("ggml_is_contiguous"); }
184
- bool ggml_is_contiguously_allocated(const ggml_tensor *) { GGML_SHIM_UNREACHABLE("ggml_is_contiguously_allocated"); }
185
- bool ggml_are_same_stride(const ggml_tensor *, const ggml_tensor *) { GGML_SHIM_UNREACHABLE("ggml_are_same_stride"); }
186
- enum ggml_backend_buffer_usage ggml_backend_buffer_get_usage(ggml_backend_buffer_t) { GGML_SHIM_UNREACHABLE("ggml_backend_buffer_get_usage"); }
187
- size_t ggml_backend_buffer_get_alloc_size(ggml_backend_buffer_t, const ggml_tensor *) { GGML_SHIM_UNREACHABLE("ggml_backend_buffer_get_alloc_size"); }
188
- }
189
-
190
- std::unique_ptr<ggml_cuda_pool> ggml_backend_cuda_context::new_pool_for_device(int, int) {
191
- GGML_SHIM_UNREACHABLE("ggml_backend_cuda_context::new_pool_for_device");
192
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
gguf_cuda/gguf_cuda.cu DELETED
@@ -1,84 +0,0 @@
1
- /* CUDA implementation of the two entry points.
2
- *
3
- * Deliberately includes no ggml header: all ggml contact is behind the extern "C" boundary in
4
- * ggml_dispatch.cu, so torch and ggml headers never meet. Outputs and scratch come from torch's
5
- * caching allocator and everything runs on torch's current stream, which keeps the ops
6
- * CUDA-graph capturable.
7
- */
8
-
9
- #include <ATen/cuda/CUDAContext.h>
10
- #include <c10/cuda/CUDAGuard.h>
11
- #include <torch/torch.h>
12
-
13
- #include "torch_binding.h"
14
-
15
- extern "C" {
16
- int gguf_dequantize_cuda(const void *w, void *out, int type, int64_t n_elems, int out_dtype,
17
- cudaStream_t stream);
18
- size_t gguf_q8_1_scratch_bytes(int64_t K, int64_t M);
19
- int gguf_mul_mat_vec_q_cuda(const void *w, const void *x, int x_dtype, float *dst,
20
- void *q8_scratch, int type, int64_t K, int64_t N, int64_t M,
21
- cudaStream_t stream);
22
- }
23
-
24
- namespace {
25
-
26
- // mirrors gguf_dtype in ggml_dispatch.cu
27
- int dtype_code(at::ScalarType t) {
28
- switch (t) {
29
- case at::kFloat: return 0;
30
- case at::kHalf: return 1;
31
- case at::kBFloat16: return 2;
32
- default: TORCH_CHECK(false, "ggml-quantization: unsupported dtype ", t);
33
- }
34
- }
35
-
36
- } // namespace
37
-
38
- // The cases upstream's `mul_mat_vec_q_switch_type` dispatches (mmvq.cu): Q4_0/Q4_1/Q5_0/Q5_1/Q8_0,
39
- // the K quants, the IQ quants, MXFP4/NVFP4 and Q1_0/Q2_0. Kept as a literal because that switch is
40
- // static and exposes no way to enumerate it; a type added upstream shows up here when the pin moves.
41
- std::vector<int64_t> gemv_types() {
42
- return {2, 3, 6, 7, 8, 10, 11, 12, 13, 14, 16, 17, 18, 19, 20, 21, 22, 23, 29, 39, 40, 41, 42};
43
- }
44
-
45
- at::Tensor dequantize(const at::Tensor &blocks, int64_t ggml_type, int64_t rows, int64_t cols,
46
- at::ScalarType dtype) {
47
- TORCH_CHECK(blocks.is_cuda() && blocks.scalar_type() == at::kByte, "blocks must be cuda uint8");
48
- TORCH_CHECK(blocks.is_contiguous(), "blocks must be contiguous");
49
- const at::cuda::OptionalCUDAGuard guard(at::device_of(blocks));
50
-
51
- auto out = at::empty({rows, cols}, blocks.options().dtype(dtype));
52
- const int rc = gguf_dequantize_cuda(blocks.data_ptr(), out.data_ptr(), (int)ggml_type, rows * cols,
53
- dtype_code(dtype), at::cuda::getCurrentCUDAStream());
54
- TORCH_CHECK(rc == 0, "ggml-quantization: dequantize has no implementation for ggml type ", ggml_type);
55
- return out;
56
- }
57
-
58
- at::Tensor get_rows(const at::Tensor &blocks, const at::Tensor &indices, int64_t ggml_type,
59
- int64_t cols, at::ScalarType dtype) {
60
- // Upstream's CUDA dequantize walks a whole tensor and takes no indices, so the rows are gathered
61
- // first and unpacked after -- correct, but without Metal's saving of never touching the rest.
62
- return dequantize(blocks.index_select(0, indices), ggml_type, indices.numel(), cols, dtype);
63
- }
64
-
65
- at::Tensor mul_mat_vec(const at::Tensor &blocks, const at::Tensor &x, int64_t ggml_type,
66
- int64_t out_features) {
67
- TORCH_CHECK(blocks.is_cuda() && blocks.scalar_type() == at::kByte, "blocks must be cuda uint8");
68
- TORCH_CHECK(x.is_cuda() && x.dim() == 2, "x must be a 2D cuda tensor");
69
- const at::cuda::OptionalCUDAGuard guard(at::device_of(blocks));
70
-
71
- const int64_t rows = x.size(0), in_features = x.size(1);
72
- const auto xc = x.contiguous();
73
- // The activations are quantized to q8_1 first; that scratch is a tensor so it comes from torch's
74
- // allocator rather than a pool of ggml's own.
75
- auto scratch = at::empty({(int64_t)gguf_q8_1_scratch_bytes(in_features, rows)}, blocks.options());
76
- auto out = at::empty({rows, out_features}, x.options().dtype(at::kFloat));
77
-
78
- const int rc = gguf_mul_mat_vec_q_cuda(blocks.data_ptr(), xc.data_ptr(),
79
- dtype_code(xc.scalar_type()), out.data_ptr<float>(),
80
- scratch.data_ptr(), (int)ggml_type, in_features,
81
- out_features, rows, at::cuda::getCurrentCUDAStream());
82
- TORCH_CHECK(rc == 0, "ggml-quantization: no gemv for ggml type ", ggml_type, " at ", rows, " rows");
83
- return out;
84
- }