marcsun13 HF Staff commited on
Commit
e1c26fb
·
verified ·
1 Parent(s): 9534e0b
.gitattributes CHANGED
@@ -33,3 +33,5 @@ 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/torch212-metal-aarch64-darwin/_ggml_quantization_metal_9534e0b_dirty.abi3.so filter=lfs diff=lfs merge=lfs -text
37
+ build/torch213-metal-aarch64-darwin/_ggml_quantization_metal_9534e0b_dirty.abi3.so filter=lfs diff=lfs merge=lfs -text
build/torch212-metal-aarch64-darwin/__init__.py ADDED
@@ -0,0 +1,98 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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", "get_rows", "mul_mat_id", "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 get_rows(
36
+ blocks: torch.Tensor, indices: torch.Tensor, ggml_type: int, cols: int, dtype: torch.dtype
37
+ ) -> torch.Tensor:
38
+ """The rows `indices` names, unpacked: `(rows, bytes_per_row)` uint8 -> `(len(indices), cols)`.
39
+
40
+ ggml's `get_rows`, which dequantizes as it gathers -- so reading a few rows out of a large table
41
+ never touches the rest.
42
+ """
43
+ return ops.get_rows(blocks, indices, ggml_type, cols, dtype)
44
+
45
+
46
+ def dequantize(
47
+ blocks: torch.Tensor, ggml_type: int, rows: int, cols: int, dtype: torch.dtype
48
+ ) -> torch.Tensor:
49
+ """`(rows, bytes_per_row)` uint8 blocks -> `(rows, cols)` values of `dtype`."""
50
+ return ops.dequantize(blocks, ggml_type, rows, cols, dtype)
51
+
52
+
53
+ def mul_mat_vec(
54
+ blocks: torch.Tensor, x: torch.Tensor, ggml_type: int, out_features: int
55
+ ) -> torch.Tensor:
56
+ """Fused dequantize-gemv: `x @ blocks.T` without unpacking `blocks`.
57
+
58
+ `x` is `(rows, in_features)` and `rows` must be at most `MAX_GEMV_ROWS`. The result is f32
59
+ whatever `x`'s dtype was, since the kernel writes an f32 destination; cast it at the call site,
60
+ where the cast can be fused into whatever consumes it.
61
+ """
62
+ return ops.mul_mat_vec(blocks, x, ggml_type, out_features)
63
+
64
+
65
+ def mul_mat_id(
66
+ blocks: torch.Tensor, x: torch.Tensor, ids: torch.Tensor, ggml_type: int, out_features: int
67
+ ) -> torch.Tensor:
68
+ """One dispatch for a bank of routed experts: ggml's `mul_mv_id`.
69
+
70
+ `blocks` is `(n_experts, out_features, bytes_per_row)`, `x` is `(n_tokens, in_features)`, and
71
+ `ids` is `(n_tokens, n_used)` naming the expert each of a token's slots picked. The result is
72
+ `(n_tokens, n_used, out_features)` f32, one row per slot.
73
+
74
+ The alternative is a gemv per expert per layer, whose arithmetic is dwarfed by the dispatch
75
+ around it -- which is most of what a MoE decode step costs.
76
+ """
77
+ return ops.mul_mat_id(blocks, x, ids, ggml_type, out_features)
78
+
79
+
80
+ # Without these, torch.compile cannot trace the ops and breaks the graph at every call.
81
+ @torch.library.register_fake(add_op_namespace_prefix("get_rows"))
82
+ def _get_rows_fake(blocks, indices, ggml_type, cols, dtype):
83
+ return blocks.new_empty((indices.numel(), cols), dtype=dtype)
84
+
85
+
86
+ @torch.library.register_fake(add_op_namespace_prefix("dequantize"))
87
+ def _dequantize_fake(blocks, ggml_type, rows, cols, dtype):
88
+ return blocks.new_empty((rows, cols), dtype=dtype)
89
+
90
+
91
+ @torch.library.register_fake(add_op_namespace_prefix("mul_mat_vec"))
92
+ def _mul_mat_vec_fake(blocks, x, ggml_type, out_features):
93
+ return x.new_empty((x.shape[0], out_features), dtype=torch.float32)
94
+
95
+
96
+ @torch.library.register_fake(add_op_namespace_prefix("mul_mat_id"))
97
+ def _mul_mat_id_fake(blocks, x, ids, ggml_type, out_features):
98
+ return x.new_empty((x.shape[0], ids.shape[1], out_features), dtype=torch.float32)
build/torch212-metal-aarch64-darwin/_ggml_quantization_metal_9534e0b_dirty.abi3.so ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:5cfbd7846fed56165a528fdb29d0c3245bfd8a3d3f45c659232ffc92592b3f57
3
+ size 3347472
build/torch212-metal-aarch64-darwin/_ops.py ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
 
1
+ import torch
2
+ from . import _ggml_quantization_metal_9534e0b_dirty
3
+ ops = torch.ops._ggml_quantization_metal_9534e0b_dirty
4
+
5
+ def add_op_namespace_prefix(op_name: str):
6
+ """
7
+ Prefix op by namespace.
8
+ """
9
+ return f"_ggml_quantization_metal_9534e0b_dirty::{op_name}"
build/torch212-metal-aarch64-darwin/metadata.json ADDED
@@ -0,0 +1,29 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "name": "ggml-quantization",
3
+ "id": "_ggml_quantization_metal_9534e0b_dirty",
4
+ "version": 1,
5
+ "license": "MIT",
6
+ "python-depends": [],
7
+ "backend": {
8
+ "type": "metal"
9
+ },
10
+ "digest": {
11
+ "algorithm": "sha256",
12
+ "files": {
13
+ "__init__.py": "iPXgZXBgY3CzpNUSjmCovMVNPLBol1KBaNoTzkXp5mM=",
14
+ "_ggml_quantization_metal_9534e0b_dirty.abi3.so": "XPvXhG/tVhZaUo/bKdDDJFv9ij0/RcZZIy/8klkrP1c=",
15
+ "_ops.py": "e/VERCOzF+fbeuBbr0rD/FwcaQgotDQRKK9XD5G0Sqo="
16
+ }
17
+ },
18
+ "provenance": {
19
+ "kernel-builder": {
20
+ "version": "0.17.0-dev0",
21
+ "sha": "81f55ea30fd8f819dcf93a3c934dd584c895bd2f",
22
+ "dirty": false
23
+ },
24
+ "kernel": {
25
+ "sha": "9534e0b885d397dae61825fd15c158b94e815650",
26
+ "dirty": true
27
+ }
28
+ }
29
+ }
build/torch213-metal-aarch64-darwin/__init__.py ADDED
@@ -0,0 +1,98 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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", "get_rows", "mul_mat_id", "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 get_rows(
36
+ blocks: torch.Tensor, indices: torch.Tensor, ggml_type: int, cols: int, dtype: torch.dtype
37
+ ) -> torch.Tensor:
38
+ """The rows `indices` names, unpacked: `(rows, bytes_per_row)` uint8 -> `(len(indices), cols)`.
39
+
40
+ ggml's `get_rows`, which dequantizes as it gathers -- so reading a few rows out of a large table
41
+ never touches the rest.
42
+ """
43
+ return ops.get_rows(blocks, indices, ggml_type, cols, dtype)
44
+
45
+
46
+ def dequantize(
47
+ blocks: torch.Tensor, ggml_type: int, rows: int, cols: int, dtype: torch.dtype
48
+ ) -> torch.Tensor:
49
+ """`(rows, bytes_per_row)` uint8 blocks -> `(rows, cols)` values of `dtype`."""
50
+ return ops.dequantize(blocks, ggml_type, rows, cols, dtype)
51
+
52
+
53
+ def mul_mat_vec(
54
+ blocks: torch.Tensor, x: torch.Tensor, ggml_type: int, out_features: int
55
+ ) -> torch.Tensor:
56
+ """Fused dequantize-gemv: `x @ blocks.T` without unpacking `blocks`.
57
+
58
+ `x` is `(rows, in_features)` and `rows` must be at most `MAX_GEMV_ROWS`. The result is f32
59
+ whatever `x`'s dtype was, since the kernel writes an f32 destination; cast it at the call site,
60
+ where the cast can be fused into whatever consumes it.
61
+ """
62
+ return ops.mul_mat_vec(blocks, x, ggml_type, out_features)
63
+
64
+
65
+ def mul_mat_id(
66
+ blocks: torch.Tensor, x: torch.Tensor, ids: torch.Tensor, ggml_type: int, out_features: int
67
+ ) -> torch.Tensor:
68
+ """One dispatch for a bank of routed experts: ggml's `mul_mv_id`.
69
+
70
+ `blocks` is `(n_experts, out_features, bytes_per_row)`, `x` is `(n_tokens, in_features)`, and
71
+ `ids` is `(n_tokens, n_used)` naming the expert each of a token's slots picked. The result is
72
+ `(n_tokens, n_used, out_features)` f32, one row per slot.
73
+
74
+ The alternative is a gemv per expert per layer, whose arithmetic is dwarfed by the dispatch
75
+ around it -- which is most of what a MoE decode step costs.
76
+ """
77
+ return ops.mul_mat_id(blocks, x, ids, ggml_type, out_features)
78
+
79
+
80
+ # Without these, torch.compile cannot trace the ops and breaks the graph at every call.
81
+ @torch.library.register_fake(add_op_namespace_prefix("get_rows"))
82
+ def _get_rows_fake(blocks, indices, ggml_type, cols, dtype):
83
+ return blocks.new_empty((indices.numel(), cols), dtype=dtype)
84
+
85
+
86
+ @torch.library.register_fake(add_op_namespace_prefix("dequantize"))
87
+ def _dequantize_fake(blocks, ggml_type, rows, cols, dtype):
88
+ return blocks.new_empty((rows, cols), dtype=dtype)
89
+
90
+
91
+ @torch.library.register_fake(add_op_namespace_prefix("mul_mat_vec"))
92
+ def _mul_mat_vec_fake(blocks, x, ggml_type, out_features):
93
+ return x.new_empty((x.shape[0], out_features), dtype=torch.float32)
94
+
95
+
96
+ @torch.library.register_fake(add_op_namespace_prefix("mul_mat_id"))
97
+ def _mul_mat_id_fake(blocks, x, ids, ggml_type, out_features):
98
+ return x.new_empty((x.shape[0], ids.shape[1], out_features), dtype=torch.float32)
build/torch213-metal-aarch64-darwin/_ggml_quantization_metal_9534e0b_dirty.abi3.so ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:deae8683c779e9477721573ac7f0b3abccccd11aebef0a49c27d4ae7a8cd7f91
3
+ size 3347472
build/torch213-metal-aarch64-darwin/_ops.py ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
 
1
+ import torch
2
+ from . import _ggml_quantization_metal_9534e0b_dirty
3
+ ops = torch.ops._ggml_quantization_metal_9534e0b_dirty
4
+
5
+ def add_op_namespace_prefix(op_name: str):
6
+ """
7
+ Prefix op by namespace.
8
+ """
9
+ return f"_ggml_quantization_metal_9534e0b_dirty::{op_name}"
build/torch213-metal-aarch64-darwin/metadata.json ADDED
@@ -0,0 +1,29 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "name": "ggml-quantization",
3
+ "id": "_ggml_quantization_metal_9534e0b_dirty",
4
+ "version": 1,
5
+ "license": "MIT",
6
+ "python-depends": [],
7
+ "backend": {
8
+ "type": "metal"
9
+ },
10
+ "digest": {
11
+ "algorithm": "sha256",
12
+ "files": {
13
+ "__init__.py": "iPXgZXBgY3CzpNUSjmCovMVNPLBol1KBaNoTzkXp5mM=",
14
+ "_ggml_quantization_metal_9534e0b_dirty.abi3.so": "3q6Gg8d56Ud3IVc6x/Czq8zM0Rrr7wpJwn1K56jNf5E=",
15
+ "_ops.py": "e/VERCOzF+fbeuBbr0rD/FwcaQgotDQRKK9XD5G0Sqo="
16
+ }
17
+ },
18
+ "provenance": {
19
+ "kernel-builder": {
20
+ "version": "0.17.0-dev0",
21
+ "sha": "81f55ea30fd8f819dcf93a3c934dd584c895bd2f",
22
+ "dirty": false
23
+ },
24
+ "kernel": {
25
+ "sha": "9534e0b885d397dae61825fd15c158b94e815650",
26
+ "dirty": true
27
+ }
28
+ }
29
+ }
gguf_metal/ggml_dispatch.mm CHANGED
@@ -359,6 +359,7 @@ extern "C" int gguf_metal_mul_mat_id(void *blocks, size_t blocks_off, void *x, s
359
  return rc;
360
  }
361
 
 
362
  extern "C" int gguf_metal_get_rows(void *blocks, size_t blocks_off, void *indices,
363
  size_t indices_off, void *out, size_t out_off, int ggml_type,
364
  int64_t rows, int64_t cols, int out_dtype) {
 
359
  return rc;
360
  }
361
 
362
+
363
  extern "C" int gguf_metal_get_rows(void *blocks, size_t blocks_off, void *indices,
364
  size_t indices_off, void *out, size_t out_off, int ggml_type,
365
  int64_t rows, int64_t cols, int out_dtype) {
gguf_metal/gguf_metal.cpp CHANGED
@@ -92,3 +92,4 @@ at::Tensor mul_mat_id(const at::Tensor &blocks, const at::Tensor &x, const at::T
92
  TORCH_CHECK(rc == 0, "ggml-quantization: no mul_mat_id for ggml type ", ggml_type);
93
  return out;
94
  }
 
 
92
  TORCH_CHECK(rc == 0, "ggml-quantization: no mul_mat_id for ggml type ", ggml_type);
93
  return out;
94
  }
95
+