-
Notifications
You must be signed in to change notification settings - Fork 22
Expand file tree
/
Copy pathdtype.h
More file actions
113 lines (101 loc) · 4.74 KB
/
Copy pathdtype.h
File metadata and controls
113 lines (101 loc) · 4.74 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
// vllm.cpp original (vt runtime, inventory deviation §9.1); no upstream mirror.
#pragma once
#include <cmath>
#include <cstddef>
#include <cstdint>
#include <limits>
#include <stdexcept>
#include <string>
#define VT_CHECK(cond, msg) \
do { \
if (!(cond)) { \
throw std::runtime_error(std::string("vt: ") + (msg) + " at " + __FILE__ + \
":" + std::to_string(__LINE__)); \
} \
} while (0)
namespace vt {
// Storage dtypes. The first six are ELEMENTWISE (one scalar per element, a
// well-defined SizeOf); the trailing entries are BLOCK-QUANTIZED ggml
// encodings, where a fixed group of `BlockElems` scalars shares one packed
// `BlockBytes` record and there is NO per-element size.
//
// Block dtypes live in the enum (rather than a parallel `QuantTensor`) to
// mirror ggml's "the type carries the layout" model: a `Tensor` stays
// self-describing and quant dispatch keys on `b.dtype` instead of forking
// every op signature (spec `.agents/specs/gguf-compute-in-quant-gemm.md`
// § Risks/decisions). The consequence is enforced here: block dtypes are
// STORAGE-ONLY — `SizeOf` on one is a `VT_CHECK` failure, so any elementwise
// kernel that reaches one fails loudly instead of reading garbage.
//
// Ids/geometry mirror llama.cpp @ 237ad9b96:
// ggml/include/ggml.h:390-432 (enum ggml_type)
// ggml/src/ggml-common.h:288-299 (block_q2_K), :242-245 (block_q8_0),
// :305-310 (block_q3_K), :317-327 (block_q4_K), :334-345 (block_q5_K),
// :352-357 (block_q6_K), :361-365 (block_q8_K), :371-374 (block_iq2_xxs),
// :385-400 (block_iq3_xxs)
// kQ8_K is ACTIVATION-ONLY: it is the `vec_dot_type` of the K-quants and never
// appears as a weight/storage type in a GGUF file.
//
// kQ2_K, kIQ2_XXS and kIQ3_XXS are the ~2-3-bit storage encodings the `unsloth/
// DeepSeek-V4-Flash-GGUF UD-IQ2_XXS/UD-Q2_K_XL` checkpoints use (the real
// UD-IQ2_XXS routed experts are IQ2_XXS gate/up + IQ3_XXS down; Q2_K is the
// UD-Q2_K_XL sibling vehicle). As of DeepSeek-V4 W8 (CLAIM-DEEPSEEK-V4-W8) all
// three carry a keep-quant `vec_dot` against the Q8_K activation encoding
// (cpu_quant_dot.cpp), so `HasQuantDotKernel` is TRUE and the GGUF loader keeps
// their blocks COMPRESSED and dots them directly — the memory enabler that lets
// a 158 B DeepSeek-V4 stay ~91 GiB instead of OOM-expanding to bf16. See
// `.agents/specs/gguf-iquant-dsv4.md` and `.agents/specs/deepseek-v4-flash.md`.
//
// kIQ2_S (2.5625 bpw, Q8_K-activation) and kMXFP4 (OCP micro-scaling fp4, 32-elem
// blocks, Q8_0-activation) are the extra per-tensor "dynamic" encodings the
// `unsloth/DeepSeek-V4-Flash-GGUF UD-IQ2_M` checkpoint mixes into a handful of
// routed-expert slabs (IQ2_S ffn_gate/up + MXFP4 ffn_down). Both carry a
// keep-quant `vec_dot` (IQ2_S vs Q8_K, MXFP4 vs Q8_0) so they load COMPRESSED
// on the same memory-safe path — expanding them to bf16 would OOM the box.
enum class DType : uint8_t {
kF32,
kF16,
kBF16,
kI8,
kI32,
kI64,
// --- block-quantized (storage-only) ---
kQ4_0,
kQ8_0,
kQ2_K,
kQ3_K,
kQ4_K,
kQ5_K,
kQ6_K,
kQ8_K,
kIQ2_XXS,
kIQ3_XXS,
kIQ2_S,
kMXFP4,
};
// Bytes per ELEMENT. Throws for block-quantized dtypes (they have no
// per-element size) — see IsBlockQuant/BlockBytes/RowSizeBytes.
size_t SizeOf(DType dtype);
const char* Name(DType dtype);
// True for the ggml block-quantized encodings above.
bool IsBlockQuant(DType dtype);
// Block geometry for a block-quantized dtype (throws for elementwise dtypes).
// `BlockElems` = ggml's blck_size, `BlockBytes` = ggml's type_size.
int64_t BlockElems(DType dtype);
int64_t BlockBytes(DType dtype);
// ggml_row_size (ggml/src/ggml.c): bytes occupied by `k` contiguous elements.
// `k` must be a whole number of blocks — rows are whole blocks, which is also
// the keep-quant eligibility rule for a GEMM weight (K % BlockElems == 0).
// Defined for elementwise dtypes too (k * SizeOf) so callers stay uniform.
size_t RowSizeBytes(DType dtype, int64_t k);
// The ggml type id (ggml.h:390-432) a block dtype corresponds to, so callers
// can cross-check against the GGUF reader's independent `GgmlTraits` table.
uint32_t GgmlTypeId(DType dtype);
// Inverse of GgmlTypeId for the block dtypes we execute; returns false when
// the id is not one of them (F32/F16/BF16 and every unported encoding).
bool BlockDTypeFromGgmlTypeId(uint32_t ggml_type, DType* out);
float F16ToF32(uint16_t h);
uint16_t F32ToF16(float f);
float BF16ToF32(uint16_t b);
uint16_t F32ToBF16(float f);
} // namespace vt