brandonmusic commited on
Commit
037e9f7
·
verified ·
1 Parent(s): 413b176

Publish K96-tail source patches

Browse files
reproduction/closure/patches/kquant/changed-files/kquant/candidate_hessian.py ADDED
@@ -0,0 +1,292 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Candidate-specific covariance helpers for offline expert encoding studies."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import hashlib
6
+ import math
7
+ from collections.abc import Mapping, Sequence
8
+
9
+ import torch
10
+
11
+
12
+ def partition_documents(
13
+ documents: Sequence[str], *, modulus: int, confirmation_index: int
14
+ ) -> tuple[list[str], list[str]]:
15
+ """Deterministically split document hashes into fit and confirmation sets."""
16
+
17
+ if modulus < 2:
18
+ raise ValueError("document partition modulus must be at least 2")
19
+ if not 0 <= confirmation_index < modulus:
20
+ raise ValueError("confirmation index must be in the partition modulus")
21
+ if not documents or len(set(documents)) != len(documents):
22
+ raise ValueError("documents must be a nonempty unique sequence")
23
+ fit: list[str] = []
24
+ confirmation: list[str] = []
25
+ for document in documents:
26
+ digest = hashlib.blake2b(document.encode(), digest_size=8).digest()
27
+ bucket = int.from_bytes(digest, "little") % modulus
28
+ (confirmation if bucket == confirmation_index else fit).append(document)
29
+ if not fit or not confirmation:
30
+ raise ValueError("document partition produced an empty side")
31
+ return fit, confirmation
32
+
33
+
34
+ def subset_request_documents(
35
+ request_documents: Mapping[int, str], documents: Sequence[str]
36
+ ) -> dict[int, str]:
37
+ """Return request/document entries belonging to ``documents`` exactly."""
38
+
39
+ selected = set(documents)
40
+ if not selected:
41
+ raise ValueError("document subset must be nonempty")
42
+ result = {
43
+ int(request): document
44
+ for request, document in request_documents.items()
45
+ if document in selected
46
+ }
47
+ covered = set(result.values())
48
+ if covered != selected:
49
+ missing = sorted(selected - covered)
50
+ raise ValueError(f"documents lack request epochs: {missing[:8]}")
51
+ return result
52
+
53
+
54
+ def request_mask(
55
+ observations: torch.Tensor, request_documents: Mapping[int, str]
56
+ ) -> torch.Tensor:
57
+ """Select capture rows whose encoded request epoch is in a corpus subset."""
58
+
59
+ if observations.ndim != 1:
60
+ raise ValueError("observations must be one-dimensional")
61
+ if not request_documents:
62
+ raise ValueError("request document mapping must be nonempty")
63
+ steps = torch.bitwise_right_shift(observations, 32)
64
+ allowed = torch.tensor(
65
+ sorted(request_documents), dtype=steps.dtype, device=steps.device
66
+ )
67
+ return torch.isin(steps, allowed)
68
+
69
+
70
+ def weighted_covariance(
71
+ rows: torch.Tensor,
72
+ weights: torch.Tensor,
73
+ *,
74
+ device: torch.device,
75
+ chunk_rows: int = 256,
76
+ return_cpu: bool = True,
77
+ ) -> tuple[torch.Tensor, float]:
78
+ """Return ``sum(w * x xT) / sum(w)`` as symmetric FP32."""
79
+
80
+ if rows.ndim != 2 or weights.ndim != 1 or rows.shape[0] != weights.shape[0]:
81
+ raise ValueError("invalid covariance sample shapes")
82
+ if not rows.shape[0] or not rows.shape[1]:
83
+ raise ValueError("covariance samples must be nonempty")
84
+ if chunk_rows <= 0:
85
+ raise ValueError("chunk_rows must be positive")
86
+ if not torch.all(torch.isfinite(rows)) or not torch.all(torch.isfinite(weights)):
87
+ raise ValueError("covariance samples must be finite")
88
+ if torch.any(weights < 0):
89
+ raise ValueError("covariance weights must be nonnegative")
90
+
91
+ dimension = int(rows.shape[1])
92
+ accumulator = torch.zeros(
93
+ (dimension, dimension), dtype=torch.float32, device=device
94
+ )
95
+ denominator_tensor = weights.to(device=device, dtype=torch.float64).sum()
96
+ if not bool(torch.isfinite(denominator_tensor)) or not bool(
97
+ denominator_tensor > 0
98
+ ):
99
+ raise ValueError("covariance weights must have a positive finite sum")
100
+ for begin in range(0, int(rows.shape[0]), chunk_rows):
101
+ values = rows[begin : begin + chunk_rows].to(
102
+ device=device, dtype=torch.float32
103
+ )
104
+ local_weights = weights[begin : begin + chunk_rows].to(
105
+ device=device, dtype=torch.float32
106
+ )
107
+ accumulator.addmm_(values.T, values * local_weights[:, None])
108
+ covariance = accumulator.div_(denominator_tensor.to(torch.float32))
109
+ covariance = ((covariance + covariance.T) * 0.5).contiguous()
110
+ denominator = float(denominator_tensor)
111
+ if return_cpu:
112
+ covariance = covariance.cpu()
113
+ if not torch.all(torch.isfinite(covariance)):
114
+ raise ValueError("weighted covariance is non-finite")
115
+ return covariance, denominator
116
+
117
+
118
+ def shrink_covariance(
119
+ global_covariance: torch.Tensor,
120
+ local_covariance: torch.Tensor,
121
+ alpha: float | torch.Tensor,
122
+ ) -> torch.Tensor:
123
+ """Convexly shrink a low-support local covariance toward a global one."""
124
+
125
+ if isinstance(alpha, torch.Tensor):
126
+ if alpha.numel() != 1 or not bool(torch.isfinite(alpha)) or not bool(
127
+ (alpha >= 0) & (alpha <= 1)
128
+ ):
129
+ raise ValueError("alpha must be a finite scalar in [0, 1]")
130
+ blend_weight: float | torch.Tensor = alpha.to(
131
+ device=global_covariance.device, dtype=torch.float32
132
+ )
133
+ else:
134
+ alpha_value = float(alpha)
135
+ if not math.isfinite(alpha_value) or not 0.0 <= alpha_value <= 1.0:
136
+ raise ValueError("alpha must be finite and in [0, 1]")
137
+ blend_weight = alpha_value
138
+ if (
139
+ global_covariance.ndim != 2
140
+ or global_covariance.shape[0] != global_covariance.shape[1]
141
+ or local_covariance.shape != global_covariance.shape
142
+ ):
143
+ raise ValueError("global and local covariances must be equal-size squares")
144
+ if not torch.all(torch.isfinite(global_covariance)) or not torch.all(
145
+ torch.isfinite(local_covariance)
146
+ ):
147
+ raise ValueError("covariances must be finite")
148
+ blended = torch.lerp(
149
+ global_covariance.float(), local_covariance.float(), blend_weight
150
+ )
151
+ return ((blended + blended.T) * 0.5).contiguous()
152
+
153
+
154
+ def weighted_effective_sample_size(weights: torch.Tensor) -> float:
155
+ """Return Kish effective sample size for nonnegative row weights."""
156
+
157
+ if weights.ndim != 1 or not weights.numel():
158
+ raise ValueError("weights must be a nonempty vector")
159
+ if not torch.all(torch.isfinite(weights)) or torch.any(weights < 0):
160
+ raise ValueError("weights must be finite and nonnegative")
161
+ value = _weighted_effective_sample_size_tensor(weights)
162
+ return float(value)
163
+
164
+
165
+ def _weighted_effective_sample_size_tensor(weights: torch.Tensor) -> torch.Tensor:
166
+ """Kish support as a scalar tensor on the input numerical device."""
167
+
168
+ if weights.ndim != 1 or not weights.numel():
169
+ raise ValueError("weights must be a nonempty vector")
170
+ if not torch.all(torch.isfinite(weights)) or torch.any(weights < 0):
171
+ raise ValueError("weights must be finite and nonnegative")
172
+ weights64 = weights.double()
173
+ total = weights64.sum()
174
+ squared_total = weights64.square().sum()
175
+ if total <= 0 or squared_total <= 0:
176
+ raise ValueError("weights must have positive effective support")
177
+ return total.square() / squared_total
178
+
179
+
180
+ def adaptive_identity_shrinkage(
181
+ local_covariance: torch.Tensor,
182
+ weights: torch.Tensor,
183
+ *,
184
+ max_local_alpha: float = 0.75,
185
+ ) -> tuple[torch.Tensor, dict[str, float]]:
186
+ """Shrink a weighted local covariance toward its scaled identity.
187
+
188
+ The Oracle Approximating Shrinkage expression is evaluated with Kish
189
+ effective sample size in place of an unweighted row count. The target is
190
+ always ``trace(local) / dimension * I``. This is important for expert
191
+ ``H2`` matrices: intermediate coordinates have no common meaning across
192
+ experts, so a pooled post-SiTU covariance is not a valid prior.
193
+ ``max_local_alpha`` preserves a nonzero identity contribution even for
194
+ very well-supported experts.
195
+ """
196
+
197
+ max_local_alpha = float(max_local_alpha)
198
+ if not math.isfinite(max_local_alpha) or not 0.0 <= max_local_alpha <= 1.0:
199
+ raise ValueError("max_local_alpha must be finite and in [0, 1]")
200
+ if local_covariance.ndim != 2 or (
201
+ local_covariance.shape[0] != local_covariance.shape[1]
202
+ ):
203
+ raise ValueError("local covariance must be square")
204
+ if not torch.all(torch.isfinite(local_covariance)):
205
+ raise ValueError("local covariance must be finite")
206
+
207
+ effective_rows_tensor = _weighted_effective_sample_size_tensor(weights)
208
+ dimension = int(local_covariance.shape[0])
209
+ local64 = local_covariance.double()
210
+ local_trace = torch.trace(local64)
211
+ if local_trace <= 0:
212
+ raise ValueError("local covariance trace must be positive")
213
+
214
+ mu = local_trace / dimension
215
+ mean_square = local64.square().mean()
216
+ denominator = (effective_rows_tensor + 1.0) * (
217
+ mean_square - mu.square() / dimension
218
+ )
219
+ raw_oas = (mean_square + mu.square()) / denominator.clamp_min(
220
+ torch.finfo(local64.dtype).tiny
221
+ )
222
+ oas_shrinkage_tensor = torch.where(
223
+ denominator <= 0,
224
+ torch.ones_like(raw_oas),
225
+ raw_oas.clamp(0.0, 1.0),
226
+ )
227
+ local_alpha_tensor = torch.minimum(
228
+ torch.as_tensor(max_local_alpha, device=local64.device, dtype=local64.dtype),
229
+ 1.0 - oas_shrinkage_tensor,
230
+ )
231
+ scaled_identity = torch.eye(
232
+ dimension,
233
+ dtype=torch.float32,
234
+ device=local_covariance.device,
235
+ ).mul_(mu.to(dtype=torch.float32))
236
+ blended = shrink_covariance(
237
+ scaled_identity, local_covariance, local_alpha_tensor.to(torch.float32)
238
+ )
239
+ # Evidence scalars are detached only after the numerical result is frozen.
240
+ effective_rows = float(effective_rows_tensor)
241
+ oas_shrinkage = float(oas_shrinkage_tensor)
242
+ local_alpha = float(local_alpha_tensor)
243
+ identity_scale = float(mu)
244
+ return blended, {
245
+ "effective_sample_size": effective_rows,
246
+ "oas_shrinkage": oas_shrinkage,
247
+ "local_alpha": local_alpha,
248
+ "max_local_alpha": max_local_alpha,
249
+ "identity_scale": identity_scale,
250
+ }
251
+
252
+
253
+ def covariance_comparison(
254
+ reference: torch.Tensor, candidate: torch.Tensor
255
+ ) -> dict[str, float]:
256
+ """Compact scale/shape diagnostics for two covariance matrices."""
257
+
258
+ if reference.ndim != 2 or reference.shape[0] != reference.shape[1]:
259
+ raise ValueError("reference covariance must be square")
260
+ if candidate.shape != reference.shape:
261
+ raise ValueError("candidate covariance shape differs")
262
+ reference = reference.float()
263
+ candidate = candidate.float()
264
+ if not torch.all(torch.isfinite(reference)) or not torch.all(torch.isfinite(candidate)):
265
+ raise ValueError("covariances must be finite")
266
+ reference_norm = torch.linalg.vector_norm(reference.double())
267
+ reference_diagonal = torch.diagonal(reference).double()
268
+ candidate_diagonal = torch.diagonal(candidate).double()
269
+ diagonal_denominator = torch.linalg.vector_norm(
270
+ reference_diagonal
271
+ ) * torch.linalg.vector_norm(candidate_diagonal)
272
+ trace = torch.trace(reference.double())
273
+ return {
274
+ "relative_frobenius_difference": float(
275
+ torch.linalg.vector_norm((candidate - reference).double())
276
+ / reference_norm
277
+ )
278
+ if reference_norm > 0
279
+ else math.inf,
280
+ "trace_ratio": float(torch.trace(candidate.double()) / trace)
281
+ if trace != 0
282
+ else math.inf,
283
+ "diagonal_cosine_similarity": float(
284
+ torch.dot(reference_diagonal, candidate_diagonal)
285
+ / diagonal_denominator
286
+ )
287
+ if diagonal_denominator > 0
288
+ else 0.0,
289
+ "candidate_symmetry_max_abs": float(
290
+ (candidate - candidate.T).abs().max()
291
+ ),
292
+ }
reproduction/closure/patches/kquant/changed-files/kquant/csrc/qsrt_quantize_tiles_kernel.cuh ADDED
@@ -0,0 +1,492 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #pragma once
2
+
3
+ // Templated trellis-quantization (Viterbi) kernel, instantiated per (K, cb) in
4
+ // comp_units/quantize_tiles_inst_k*.cu
5
+
6
+ #include <cuda_fp16.h>
7
+ #include <cuda_bf16.h>
8
+ #include <cublas_v2.h>
9
+ #include <cstdio>
10
+ #include "exl3_compat/util.h"
11
+ #include "exl3_compat/util.cuh"
12
+ #include "exl3_compat/quant/codebook.cuh"
13
+
14
+ #define QUANTIZE_TILES_K2_NUM_THREADS 1024
15
+ #define QUANTIZE_TILES_K3_NUM_THREADS 640
16
+ #define QUANTIZE_TILES_K4_NUM_THREADS 704
17
+ #ifndef H_INF
18
+ #define H_INF __ushort_as_half(0x7c00)
19
+ #endif
20
+ #ifndef H_MAX_FINITE
21
+ #define H_MAX_FINITE __ushort_as_half(0x7bff)
22
+ #endif
23
+
24
+ template <int K, int cb>
25
+ __global__ __launch_bounds__(
26
+ K == 2 ? QUANTIZE_TILES_K2_NUM_THREADS :
27
+ (K == 3 ? QUANTIZE_TILES_K3_NUM_THREADS : QUANTIZE_TILES_K4_NUM_THREADS),
28
+ K == 2 ? 1 : 2)
29
+ void quantize_tiles_kernel
30
+ (
31
+ const float* __restrict__ input_tiles_ptr,
32
+ float* __restrict__ output_tiles_ptr,
33
+ uint16_t* __restrict__ output_indices_ptr,
34
+ half* __restrict__ temp_costs_ptr,
35
+ uint8_t* __restrict__ temp_edges_ptr,
36
+ int tailbite_context
37
+ )
38
+ {
39
+ extern __shared__ uint8_t shbuf[];
40
+ uint8_t* sh = shbuf;
41
+
42
+ constexpr int Kr = 16 - K;
43
+ constexpr int max_q = 1 << K;
44
+ constexpr int edges = 65536 >> K;
45
+ constexpr int decisions_per_row =
46
+ K == 2 ? edges / 4 : (K <= 4 ? edges / 2 : edges);
47
+ constexpr int decision_shift = 16 - 2 * K;
48
+ constexpr int predecessor_step = 1 << decision_shift;
49
+ constexpr int num_threads =
50
+ K == 2 ? QUANTIZE_TILES_K2_NUM_THREADS :
51
+ (K == 3 ? QUANTIZE_TILES_K3_NUM_THREADS : QUANTIZE_TILES_K4_NUM_THREADS);
52
+
53
+ const int tile_idx = blockIdx.x;
54
+ const int thread = threadIdx.x;
55
+ const float* input_tile = input_tiles_ptr + 256 * tile_idx;
56
+ float* output_tile = output_tiles_ptr + 256 * tile_idx;
57
+ uint16_t* output_indices = output_indices_ptr + 256 * tile_idx;
58
+ uint8_t* temp_edges = temp_edges_ptr + 256 * decisions_per_row * tile_idx;
59
+
60
+ half* sh_input_tile = (half*) sh; sh += 256 * sizeof(half);
61
+ half* sh_min = (half*) sh; sh += 32 * sizeof(half);
62
+ int* sh_idx = (int*) sh; sh += 32 * sizeof(int);
63
+
64
+ half* sh_temp_costs = (half*) sh;
65
+ half* temp_costs = K >= 2 ? sh_temp_costs : temp_costs_ptr + 2 * edges * tile_idx;
66
+ half* temp_costs_inc = temp_costs + edges;
67
+
68
+ if (thread < 256) sh_input_tile[thread] = __float2half_rn(input_tile[thread]);
69
+ __syncthreads();
70
+
71
+ auto forward = [&](int roll, int steps, int pre_state, int trace_start)
72
+ {
73
+ int ri = roll & 255;
74
+ half* t = temp_costs;
75
+ temp_costs = temp_costs_inc;
76
+ temp_costs_inc = t;
77
+
78
+ for (int out_edge_idx = 2 * thread; out_edge_idx < edges; out_edge_idx += 2 * num_threads)
79
+ {
80
+ const half2 w2 = __half2half2(sh_input_tile[ri]);
81
+ int in_edge_idx = out_edge_idx >> K;
82
+ uint32_t product0 = 0;
83
+ uint32_t product1 = 0;
84
+ uint2 sqg_k2_labels{};
85
+ uint4 sqg_k3_labels{};
86
+ uint4 sqg_k4_labels0{};
87
+ uint4 sqg_k4_labels1{};
88
+ half2 decoded2;
89
+ if constexpr (cb == 1)
90
+ {
91
+ product0 = mul_const_u32<0xCBAC1FEDu>(out_edge_idx);
92
+ product1 = product0 + 0xCBAC1FEDu;
93
+ decoded2 = decode_mcg_product_2(product0, product1);
94
+ }
95
+ else if constexpr (cb == 2)
96
+ {
97
+ product0 = out_edge_idx * 0x83DCD12Du;
98
+ product1 = product0 + 0x83DCD12Du;
99
+ decoded2 = decode_mul1_product_2(product0, product1);
100
+ }
101
+ else if constexpr (cb == 4 && K == 2)
102
+ {
103
+ sqg_k2_labels =
104
+ reinterpret_cast<const uint2*>(sqg_e4m3_lut)[out_edge_idx >> 1];
105
+ decoded2 = decode_sqg_k2_pair(sqg_k2_labels, 0);
106
+ }
107
+ else if constexpr (cb == 4 && K == 3)
108
+ {
109
+ sqg_k3_labels =
110
+ reinterpret_cast<const uint4*>(sqg_e4m3_lut)[out_edge_idx >> 1];
111
+ decoded2 = decode_sqg_k3_pair(sqg_k3_labels, 0);
112
+ }
113
+ else if constexpr (cb == 4 && K == 4)
114
+ {
115
+ const int packed_index = out_edge_idx;
116
+ sqg_k4_labels0 =
117
+ reinterpret_cast<const uint4*>(sqg_e4m3_lut)[packed_index];
118
+ sqg_k4_labels1 =
119
+ reinterpret_cast<const uint4*>(sqg_e4m3_lut)[packed_index + 1];
120
+ decoded2 = decode_sqg_k4_pair(sqg_k4_labels0, sqg_k4_labels1, 0);
121
+ }
122
+ else
123
+ {
124
+ decoded2 = decode_3inst_2<cb>(out_edge_idx, out_edge_idx + 1);
125
+ }
126
+ half2 dh2 = __hsub2(decoded2, w2);
127
+ // Positive infinity denotes an unreachable state. Reachable path
128
+ // costs must remain finite when their FP16 sum overflows, or
129
+ // traceback can confuse a saturated path with an unreachable one
130
+ // and violate the constrained cyclic boundary.
131
+ half2 min_err2 = __hmin2(
132
+ __hmul2(dh2, dh2), __half2half2(H_MAX_FINITE));
133
+ if (pre_state >= 0 && in_edge_idx != pre_state) min_err2 = __half2half2(H_INF);
134
+ int min_k0 = 0;
135
+ int min_k1 = 0;
136
+
137
+ #pragma unroll
138
+ for (int k = 1; k < max_q; ++k)
139
+ {
140
+ in_edge_idx += predecessor_step;
141
+ if constexpr (cb == 1)
142
+ {
143
+ // MCG multiplication is linear modulo 2^32 across successive branch states.
144
+ constexpr uint32_t product_step = 0xCBAC1FEDu << Kr;
145
+ product0 += product_step;
146
+ product1 += product_step;
147
+ decoded2 = decode_mcg_product_2(product0, product1);
148
+ }
149
+ else if constexpr (cb == 2)
150
+ {
151
+ // The mul1 multiplication is equally linear modulo 2^32.
152
+ constexpr uint32_t product_step = 0x83DCD12Du << Kr;
153
+ product0 += product_step;
154
+ product1 += product_step;
155
+ decoded2 = decode_mul1_product_2(product0, product1);
156
+ }
157
+ else if constexpr (cb == 4 && K == 2)
158
+ {
159
+ decoded2 = decode_sqg_k2_pair(sqg_k2_labels, k);
160
+ }
161
+ else if constexpr (cb == 4 && K == 3)
162
+ {
163
+ decoded2 = decode_sqg_k3_pair(sqg_k3_labels, k);
164
+ }
165
+ else if constexpr (cb == 4 && K == 4)
166
+ {
167
+ decoded2 = decode_sqg_k4_pair(
168
+ sqg_k4_labels0, sqg_k4_labels1, k);
169
+ }
170
+ else
171
+ {
172
+ const int state0 = (k << Kr) | out_edge_idx;
173
+ decoded2 = decode_3inst_2<cb>(state0, state0 + 1);
174
+ }
175
+ dh2 = __hsub2(decoded2, w2);
176
+ half2 err2 = __hmin2(
177
+ __hmul2(dh2, dh2), __half2half2(H_MAX_FINITE));
178
+ if (pre_state >= 0 && in_edge_idx != pre_state) err2 = __half2half2(H_INF);
179
+ const unsigned less = __hlt2_mask(err2, min_err2);
180
+ min_err2 = __hmin2(err2, min_err2);
181
+ if (less & 0xffffu) min_k0 = k;
182
+ if (less >> 16) min_k1 = k;
183
+ }
184
+
185
+ reinterpret_cast<half2*>(temp_costs)[out_edge_idx >> 1] = min_err2;
186
+ if (trace_start == 0)
187
+ {
188
+ if constexpr (K == 2)
189
+ {
190
+ const unsigned pair = min_k0 | (min_k1 << 2);
191
+ const unsigned next = __shfl_down_sync(0xffffffff, pair, 1);
192
+ if ((thread & 1) == 0)
193
+ temp_edges[decisions_per_row * ri + (out_edge_idx >> 2)] =
194
+ (uint8_t) (pair | (next << 4));
195
+ }
196
+ else if constexpr (K <= 4)
197
+ temp_edges[decisions_per_row * ri + (out_edge_idx >> 1)] =
198
+ (uint8_t) (min_k0 | (min_k1 << 4));
199
+ else
200
+ {
201
+ temp_edges[decisions_per_row * ri + out_edge_idx] = (uint8_t) min_k0;
202
+ temp_edges[decisions_per_row * ri + out_edge_idx + 1] = (uint8_t) min_k1;
203
+ }
204
+ }
205
+ }
206
+ __syncthreads();
207
+
208
+ for (int i = 1; i < steps; ++i)
209
+ {
210
+ ri = (i + roll) & 255;
211
+ t = temp_costs;
212
+ temp_costs = temp_costs_inc;
213
+ temp_costs_inc = t;
214
+
215
+ for (int out_edge_idx = 2 * thread; out_edge_idx < edges; out_edge_idx += 2 * num_threads)
216
+ {
217
+ const half2 w2 = __half2half2(sh_input_tile[ri]);
218
+ int in_edge_idx = out_edge_idx >> K;
219
+ uint32_t product0 = 0;
220
+ uint32_t product1 = 0;
221
+ uint2 sqg_k2_labels{};
222
+ uint4 sqg_k3_labels{};
223
+ uint4 sqg_k4_labels0{};
224
+ uint4 sqg_k4_labels1{};
225
+ half2 decoded2;
226
+ if constexpr (cb == 1)
227
+ {
228
+ product0 = mul_const_u32<0xCBAC1FEDu>(out_edge_idx);
229
+ product1 = product0 + 0xCBAC1FEDu;
230
+ decoded2 = decode_mcg_product_2(product0, product1);
231
+ }
232
+ else if constexpr (cb == 2)
233
+ {
234
+ product0 = out_edge_idx * 0x83DCD12Du;
235
+ product1 = product0 + 0x83DCD12Du;
236
+ decoded2 = decode_mul1_product_2(product0, product1);
237
+ }
238
+ else if constexpr (cb == 4 && K == 2)
239
+ {
240
+ sqg_k2_labels =
241
+ reinterpret_cast<const uint2*>(sqg_e4m3_lut)[out_edge_idx >> 1];
242
+ decoded2 = decode_sqg_k2_pair(sqg_k2_labels, 0);
243
+ }
244
+ else if constexpr (cb == 4 && K == 3)
245
+ {
246
+ sqg_k3_labels =
247
+ reinterpret_cast<const uint4*>(sqg_e4m3_lut)[out_edge_idx >> 1];
248
+ decoded2 = decode_sqg_k3_pair(sqg_k3_labels, 0);
249
+ }
250
+ else if constexpr (cb == 4 && K == 4)
251
+ {
252
+ const int packed_index = out_edge_idx;
253
+ sqg_k4_labels0 =
254
+ reinterpret_cast<const uint4*>(sqg_e4m3_lut)[packed_index];
255
+ sqg_k4_labels1 =
256
+ reinterpret_cast<const uint4*>(sqg_e4m3_lut)[packed_index + 1];
257
+ decoded2 = decode_sqg_k4_pair(
258
+ sqg_k4_labels0, sqg_k4_labels1, 0);
259
+ }
260
+ else
261
+ {
262
+ decoded2 = decode_3inst_2<cb>(out_edge_idx, out_edge_idx + 1);
263
+ }
264
+ half2 dh2 = __hsub2(decoded2, w2);
265
+ half predecessor_cost = temp_costs_inc[in_edge_idx];
266
+ half2 min_err2 = __heq(predecessor_cost, H_INF)
267
+ ? __half2half2(H_INF)
268
+ : __hmin2(
269
+ __hfma2(
270
+ dh2, dh2, __half2half2(predecessor_cost)),
271
+ __half2half2(H_MAX_FINITE));
272
+ int min_k0 = 0;
273
+ int min_k1 = 0;
274
+
275
+ #pragma unroll
276
+ for (int k = 1; k < max_q; ++k)
277
+ {
278
+ in_edge_idx += predecessor_step;
279
+ if constexpr (cb == 1)
280
+ {
281
+ // MCG multiplication is linear modulo 2^32 across successive branch states.
282
+ constexpr uint32_t product_step = 0xCBAC1FEDu << Kr;
283
+ product0 += product_step;
284
+ product1 += product_step;
285
+ decoded2 = decode_mcg_product_2(product0, product1);
286
+ }
287
+ else if constexpr (cb == 2)
288
+ {
289
+ // The mul1 multiplication is equally linear modulo 2^32.
290
+ constexpr uint32_t product_step = 0x83DCD12Du << Kr;
291
+ product0 += product_step;
292
+ product1 += product_step;
293
+ decoded2 = decode_mul1_product_2(product0, product1);
294
+ }
295
+ else if constexpr (cb == 4 && K == 2)
296
+ {
297
+ decoded2 = decode_sqg_k2_pair(sqg_k2_labels, k);
298
+ }
299
+ else if constexpr (cb == 4 && K == 3)
300
+ {
301
+ decoded2 = decode_sqg_k3_pair(sqg_k3_labels, k);
302
+ }
303
+ else if constexpr (cb == 4 && K == 4)
304
+ {
305
+ decoded2 = decode_sqg_k4_pair(
306
+ sqg_k4_labels0, sqg_k4_labels1, k);
307
+ }
308
+ else
309
+ {
310
+ const int state0 = (k << Kr) | out_edge_idx;
311
+ decoded2 = decode_3inst_2<cb>(state0, state0 + 1);
312
+ }
313
+ dh2 = __hsub2(decoded2, w2);
314
+ predecessor_cost = temp_costs_inc[in_edge_idx];
315
+ half2 err2 = __heq(predecessor_cost, H_INF)
316
+ ? __half2half2(H_INF)
317
+ : __hmin2(
318
+ __hfma2(
319
+ dh2, dh2, __half2half2(predecessor_cost)),
320
+ __half2half2(H_MAX_FINITE));
321
+ const unsigned less = __hlt2_mask(err2, min_err2);
322
+ min_err2 = __hmin2(err2, min_err2);
323
+ if (less & 0xffffu) min_k0 = k;
324
+ if (less >> 16) min_k1 = k;
325
+ }
326
+
327
+ reinterpret_cast<half2*>(temp_costs)[out_edge_idx >> 1] = min_err2;
328
+ if (i >= trace_start)
329
+ {
330
+ if constexpr (K == 2)
331
+ {
332
+ const unsigned pair = min_k0 | (min_k1 << 2);
333
+ const unsigned next = __shfl_down_sync(0xffffffff, pair, 1);
334
+ if ((thread & 1) == 0)
335
+ temp_edges[decisions_per_row * ri + (out_edge_idx >> 2)] =
336
+ (uint8_t) (pair | (next << 4));
337
+ }
338
+ else if constexpr (K <= 4)
339
+ temp_edges[decisions_per_row * ri + (out_edge_idx >> 1)] =
340
+ (uint8_t) (min_k0 | (min_k1 << 4));
341
+ else
342
+ {
343
+ temp_edges[decisions_per_row * ri + out_edge_idx] = (uint8_t) min_k0;
344
+ temp_edges[decisions_per_row * ri + out_edge_idx + 1] = (uint8_t) min_k1;
345
+ }
346
+ }
347
+ }
348
+ __syncthreads();
349
+ }
350
+ };
351
+
352
+ auto argmin_cost = [&]()
353
+ {
354
+ // Preserve the historical 1024-thread tie-breaking order.
355
+ const int lane_id = thread & 31;
356
+ const int warp_id = thread >> 5;
357
+ if constexpr (K == 2)
358
+ {
359
+ // With 1024 K2 threads, each warp represents exactly one of the
360
+ // 32 reduction groups used by the historical 512-thread kernel's
361
+ // two local streams. The strict-less reduction therefore keeps
362
+ // the same deterministic tie order.
363
+ half local_min = H_INF;
364
+ int local_idx = -1;
365
+ for (int e = thread; e < edges; e += num_threads)
366
+ {
367
+ half v = temp_costs_inc[e];
368
+ if (__hlt(v, local_min)) { local_min = v; local_idx = e; }
369
+ }
370
+ #pragma unroll
371
+ for (int offset = 16; offset > 0; offset >>= 1)
372
+ {
373
+ half other_min = __shfl_down_sync(0xffffffff, local_min, offset);
374
+ int other_idx = __shfl_down_sync(0xffffffff, local_idx, offset);
375
+ if (__hlt(other_min, local_min)) { local_min = other_min; local_idx = other_idx; }
376
+ }
377
+ sh_min[warp_id] = local_min;
378
+ sh_idx[warp_id] = local_idx;
379
+ }
380
+ else
381
+ {
382
+ // Preserve the established 512-thread reduction tree even when
383
+ // the forward pass uses a wider block. This keeps exact-tie
384
+ // path selection stable across encoder-kernel revisions.
385
+ if (thread < 512)
386
+ {
387
+ half local_min0 = H_INF;
388
+ half local_min1 = H_INF;
389
+ int local_idx0 = -1;
390
+ int local_idx1 = -1;
391
+ for (int e = thread; e < edges; e += 1024)
392
+ {
393
+ half v = temp_costs_inc[e];
394
+ if (__hlt(v, local_min0)) { local_min0 = v; local_idx0 = e; }
395
+ }
396
+ for (int e = thread + 512; e < edges; e += 1024)
397
+ {
398
+ half v = temp_costs_inc[e];
399
+ if (__hlt(v, local_min1)) { local_min1 = v; local_idx1 = e; }
400
+ }
401
+ #pragma unroll
402
+ for (int offset = 16; offset > 0; offset >>= 1)
403
+ {
404
+ half other_min0 = __shfl_down_sync(0xffffffff, local_min0, offset);
405
+ int other_idx0 = __shfl_down_sync(0xffffffff, local_idx0, offset);
406
+ if (__hlt(other_min0, local_min0)) { local_min0 = other_min0; local_idx0 = other_idx0; }
407
+ half other_min1 = __shfl_down_sync(0xffffffff, local_min1, offset);
408
+ int other_idx1 = __shfl_down_sync(0xffffffff, local_idx1, offset);
409
+ if (__hlt(other_min1, local_min1)) { local_min1 = other_min1; local_idx1 = other_idx1; }
410
+ }
411
+ sh_min[warp_id] = local_min0;
412
+ sh_idx[warp_id] = local_idx0;
413
+ sh_min[16 + warp_id] = local_min1;
414
+ sh_idx[16 + warp_id] = local_idx1;
415
+ }
416
+ }
417
+ __syncthreads();
418
+
419
+ int local_idx = 0;
420
+ if (warp_id == 0)
421
+ {
422
+ half local_min = sh_min[lane_id];
423
+ local_idx = sh_idx[lane_id];
424
+ #pragma unroll
425
+ for (int offset = 16; offset > 0; offset >>= 1)
426
+ {
427
+ half other_min = __shfl_down_sync(0xffffffff, local_min, offset);
428
+ int other_idx = __shfl_down_sync(0xffffffff, local_idx, offset);
429
+ if (__hlt(other_min, local_min)) { local_min = other_min; local_idx = other_idx; }
430
+ }
431
+ }
432
+ return local_idx;
433
+ };
434
+
435
+ auto backward = [&](int roll, int steps, bool write, int edge)
436
+ {
437
+ if (thread == 0)
438
+ {
439
+ for (int i = steps - 1; i >= 0; --i)
440
+ {
441
+ const int ri = (i + roll) & 255;
442
+ int decision;
443
+ if constexpr (K == 2)
444
+ {
445
+ const uint8_t packed =
446
+ temp_edges[decisions_per_row * ri + (edge >> 2)];
447
+ decision = (packed >> ((edge & 3) * 2)) & 0x03;
448
+ }
449
+ else if constexpr (K <= 4)
450
+ {
451
+ const uint8_t packed =
452
+ temp_edges[decisions_per_row * ri + (edge >> 1)];
453
+ decision = (packed >> ((edge & 1) * 4)) & 0x0f;
454
+ }
455
+ else
456
+ decision = (int) temp_edges[decisions_per_row * ri + edge];
457
+ const int prev_edge =
458
+ (decision << decision_shift) | (edge >> K);
459
+ const int encoded = (prev_edge << K) | edge;
460
+ edge = prev_edge;
461
+ if (write)
462
+ {
463
+ output_indices[ri] = (uint16_t) encoded;
464
+ if constexpr (cb == 4 && K == 2)
465
+ output_tile[ri] = __half2float(decode_sqg_k2_scalar(encoded));
466
+ else if constexpr (cb == 4 && K == 3)
467
+ output_tile[ri] = __half2float(decode_sqg_k3_scalar(encoded));
468
+ else if constexpr (cb == 4 && K == 4)
469
+ output_tile[ri] = __half2float(decode_sqg_k4_scalar(encoded));
470
+ else
471
+ output_tile[ri] = __half2float(decode_3inst<cb>(encoded));
472
+ }
473
+ else if (ri == 0) break;
474
+ }
475
+ }
476
+ if (thread == 0) sh_idx[0] = edge;
477
+ __syncthreads();
478
+ return sh_idx[0];
479
+ };
480
+
481
+ // Infer a cyclic boundary state from symmetric context around element 0,
482
+ // then run the ordinary complete constrained pass. The historical path
483
+ // uses 128 symbols on either side (a full 256-step primer). Smaller
484
+ // contexts are an encoder-only search approximation: the final pass is
485
+ // still a valid closed trellis and the bitstream/decoder are unchanged.
486
+ const int primer_roll = 256 - tailbite_context;
487
+ const int primer_steps = 2 * tailbite_context;
488
+ forward(primer_roll, primer_steps, -1, tailbite_context);
489
+ int end_state = backward(primer_roll, primer_steps, false, argmin_cost());
490
+ forward(0, 256, end_state, 0);
491
+ backward(0, 256, true, end_state);
492
+ }
reproduction/closure/patches/kquant/changed-files/kquant/csrc/sqg_quantize.cu ADDED
@@ -0,0 +1,358 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #include <ATen/cuda/CUDAContext.h>
2
+ #include <c10/cuda/CUDAGuard.h>
3
+ #include <cuda_fp16.h>
4
+ #include <cuda_fp8.h>
5
+ #include <torch/extension.h>
6
+
7
+ #include "exl3_compat/util.cuh"
8
+ #include "exl3_compat/quant/codebook.cuh"
9
+
10
+ // Keep only the table pointer in broadcast-friendly constant memory. The
11
+ // labels themselves remain in ordinary read-only global memory: a warp's
12
+ // Viterbi lanes normally request different states, which would serialize a
13
+ // 64-KiB constant-memory table despite its attractive nominal footprint.
14
+ __device__ __constant__ const uint8_t* sqg_e4m3_lut;
15
+
16
+ template <>
17
+ __device__ inline half decode_3inst<4>(uint32_t state)
18
+ {
19
+ const __nv_fp8_storage_t fp8 = sqg_e4m3_lut[state & 0xffffu];
20
+ const __half_raw raw = __nv_cvt_fp8_to_halfraw(fp8, __NV_E4M3);
21
+ return __ushort_as_half(raw.x);
22
+ }
23
+
24
+ template <>
25
+ __device__ inline half2 decode_3inst_2<4>(uint32_t state0, uint32_t state1)
26
+ {
27
+ // The trellis kernel always asks for an aligned consecutive pair. Load
28
+ // both E4M3 labels together so a warp consumes every byte in each cache
29
+ // sector instead of issuing separate even- and odd-byte gathers.
30
+ const __nv_fp8x2_storage_t fp8x2 =
31
+ reinterpret_cast<const __nv_fp8x2_storage_t*>(sqg_e4m3_lut)[state0 >> 1];
32
+ const __half2_raw raw = __nv_cvt_fp8x2_to_halfraw2(fp8x2, __NV_E4M3);
33
+ return __halves2half2(__ushort_as_half(raw.x), __ushort_as_half(raw.y));
34
+ }
35
+
36
+ __device__ inline half2 decode_sqg_fp8x2(__nv_fp8x2_storage_t fp8x2)
37
+ {
38
+ const __half2_raw raw = __nv_cvt_fp8x2_to_halfraw2(fp8x2, __NV_E4M3);
39
+ return __halves2half2(__ushort_as_half(raw.x), __ushort_as_half(raw.y));
40
+ }
41
+
42
+ __device__ inline half2 decode_sqg_k2_pair(const uint2& packed, int predecessor)
43
+ {
44
+ const uint32_t word = predecessor < 2 ? packed.x : packed.y;
45
+ return decode_sqg_fp8x2(
46
+ static_cast<__nv_fp8x2_storage_t>(word >> (16 * (predecessor & 1))));
47
+ }
48
+
49
+ __device__ inline half decode_sqg_k2_scalar(uint32_t state)
50
+ {
51
+ constexpr int edges = 65536 >> 2;
52
+ const int predecessor = state >> 14;
53
+ const int out_edge = state & (edges - 1);
54
+ const __nv_fp8x2_storage_t pair =
55
+ reinterpret_cast<const __nv_fp8x2_storage_t*>(sqg_e4m3_lut)[
56
+ (out_edge >> 1) * 4 + predecessor];
57
+ const __nv_fp8_storage_t fp8 =
58
+ static_cast<__nv_fp8_storage_t>(pair >> (8 * (out_edge & 1)));
59
+ const __half_raw raw = __nv_cvt_fp8_to_halfraw(fp8, __NV_E4M3);
60
+ return __ushort_as_half(raw.x);
61
+ }
62
+
63
+ __device__ inline half2 decode_sqg_k3_pair(const uint4& packed, int predecessor)
64
+ {
65
+ uint32_t word;
66
+ switch (predecessor >> 1)
67
+ {
68
+ case 0: word = packed.x; break;
69
+ case 1: word = packed.y; break;
70
+ case 2: word = packed.z; break;
71
+ default: word = packed.w; break;
72
+ }
73
+ return decode_sqg_fp8x2(
74
+ static_cast<__nv_fp8x2_storage_t>(word >> (16 * (predecessor & 1))));
75
+ }
76
+
77
+ __device__ inline half2 decode_sqg_k4_pair(
78
+ const uint4& packed0, const uint4& packed1, int predecessor)
79
+ {
80
+ const uint4& packed = predecessor < 8 ? packed0 : packed1;
81
+ const int local = predecessor & 7;
82
+ uint32_t word;
83
+ switch (local >> 1)
84
+ {
85
+ case 0: word = packed.x; break;
86
+ case 1: word = packed.y; break;
87
+ case 2: word = packed.z; break;
88
+ default: word = packed.w; break;
89
+ }
90
+ return decode_sqg_fp8x2(
91
+ static_cast<__nv_fp8x2_storage_t>(word >> (16 * (local & 1))));
92
+ }
93
+
94
+ __device__ inline half decode_sqg_k4_scalar(uint32_t state)
95
+ {
96
+ constexpr int edges = 65536 >> 4;
97
+ const int predecessor = state >> 12;
98
+ const int out_edge = state & (edges - 1);
99
+ const __nv_fp8x2_storage_t pair =
100
+ reinterpret_cast<const __nv_fp8x2_storage_t*>(sqg_e4m3_lut)[
101
+ (out_edge >> 1) * 16 + predecessor];
102
+ const __nv_fp8_storage_t fp8 =
103
+ static_cast<__nv_fp8_storage_t>(pair >> (8 * (out_edge & 1)));
104
+ const __half_raw raw = __nv_cvt_fp8_to_halfraw(fp8, __NV_E4M3);
105
+ return __ushort_as_half(raw.x);
106
+ }
107
+
108
+ __device__ inline half decode_sqg_k3_scalar(uint32_t state)
109
+ {
110
+ constexpr int edges = 65536 >> 3;
111
+ const int predecessor = state >> 13;
112
+ const int out_edge = state & (edges - 1);
113
+ const __nv_fp8x2_storage_t pair =
114
+ reinterpret_cast<const __nv_fp8x2_storage_t*>(sqg_e4m3_lut)[
115
+ (out_edge >> 1) * 8 + predecessor];
116
+ const __nv_fp8_storage_t fp8 =
117
+ static_cast<__nv_fp8_storage_t>(pair >> (8 * (out_edge & 1)));
118
+ const __half_raw raw = __nv_cvt_fp8_to_halfraw(fp8, __NV_E4M3);
119
+ return __ushort_as_half(raw.x);
120
+ }
121
+
122
+ #include "qsrt_quantize_tiles_kernel.cuh"
123
+
124
+ namespace
125
+ {
126
+
127
+ template <int K, int codebook>
128
+ void launch_trellis(
129
+ const float* input,
130
+ float* output,
131
+ uint16_t* indices,
132
+ half* costs,
133
+ uint8_t* edges,
134
+ int tiles,
135
+ int max_batch,
136
+ int shared_memory,
137
+ int tailbite_context,
138
+ cudaStream_t stream)
139
+ {
140
+ const int threads = K == 2 ? 1024 : (K == 3 ? 640 : 704);
141
+ cudaFuncSetAttribute(
142
+ quantize_tiles_kernel<K, codebook>,
143
+ cudaFuncAttributeMaxDynamicSharedMemorySize,
144
+ shared_memory);
145
+ cudaFuncSetAttribute(
146
+ quantize_tiles_kernel<K, codebook>,
147
+ cudaFuncAttributePreferredSharedMemoryCarveout,
148
+ K == 4 ? cudaSharedmemCarveoutMaxL1 : cudaSharedmemCarveoutMaxShared);
149
+ for (int start = 0; start < tiles; start += max_batch)
150
+ {
151
+ const int batch = min(max_batch, tiles - start);
152
+ quantize_tiles_kernel<K, codebook><<<batch, threads, shared_memory, stream>>>(
153
+ input + 256 * start,
154
+ output + 256 * start,
155
+ indices + 256 * start,
156
+ costs,
157
+ edges,
158
+ tailbite_context);
159
+ C10_CUDA_KERNEL_LAUNCH_CHECK();
160
+ }
161
+ }
162
+
163
+ } // namespace
164
+
165
+ void quantize_tiles_sqg_cuda(
166
+ at::Tensor input_tiles,
167
+ at::Tensor output_tiles,
168
+ at::Tensor output_indices,
169
+ at::Tensor temp_costs,
170
+ at::Tensor temp_edges,
171
+ at::Tensor codebook,
172
+ int64_t K,
173
+ int64_t tailbite_context)
174
+ {
175
+ const at::cuda::OptionalCUDAGuard guard(input_tiles.device());
176
+ const cudaStream_t stream = at::cuda::getCurrentCUDAStream().stream();
177
+
178
+ TORCH_CHECK(input_tiles.is_cuda(), "input_tiles must be CUDA");
179
+ TORCH_CHECK(input_tiles.scalar_type() == at::kFloat, "input_tiles must be FP32");
180
+ TORCH_CHECK(input_tiles.dim() == 2 && input_tiles.size(1) == 256,
181
+ "input_tiles must have shape [tiles, 256]");
182
+ TORCH_CHECK(output_tiles.sizes() == input_tiles.sizes(),
183
+ "output_tiles shape mismatch");
184
+ TORCH_CHECK(output_tiles.scalar_type() == at::kFloat,
185
+ "output_tiles must be FP32");
186
+ TORCH_CHECK(output_indices.sizes() == input_tiles.sizes(),
187
+ "output_indices shape mismatch");
188
+ TORCH_CHECK(output_indices.scalar_type() == at::kShort,
189
+ "output_indices must be int16");
190
+ TORCH_CHECK(K >= 2 && K <= 6, "SQG validation kernel supports K2--K6");
191
+ TORCH_CHECK(tailbite_context >= 1 && tailbite_context <= 128,
192
+ "tailbite_context must be in 1..128");
193
+ TORCH_CHECK(codebook.is_cuda() && codebook.device() == input_tiles.device(),
194
+ "codebook must be on the input CUDA device");
195
+ TORCH_CHECK(codebook.scalar_type() == at::kByte && codebook.numel() == 65536,
196
+ "codebook must contain 65,536 uint8 E4M3 values");
197
+ TORCH_CHECK(codebook.is_contiguous(), "codebook must be contiguous");
198
+
199
+ const int edges_per_state = 65536 >> K;
200
+ const int decision_entries =
201
+ K == 2 ? edges_per_state / 4 : (K <= 4 ? edges_per_state / 2 : edges_per_state);
202
+ TORCH_CHECK(temp_costs.scalar_type() == at::kHalf && temp_costs.dim() == 3,
203
+ "temp_costs must be rank-3 FP16");
204
+ TORCH_CHECK(temp_costs.size(1) == 2 && temp_costs.size(2) == edges_per_state,
205
+ "temp_costs shape mismatch");
206
+ TORCH_CHECK(temp_edges.scalar_type() == at::kByte && temp_edges.dim() == 3,
207
+ "temp_edges must be rank-3 uint8");
208
+ TORCH_CHECK(temp_edges.size(1) == 256 && temp_edges.size(2) == decision_entries,
209
+ "temp_edges shape mismatch");
210
+
211
+ const uint8_t* codebook_pointer = codebook.data_ptr<uint8_t>();
212
+ C10_CUDA_CHECK(cudaMemcpyToSymbolAsync(
213
+ sqg_e4m3_lut,
214
+ &codebook_pointer,
215
+ sizeof(codebook_pointer),
216
+ 0,
217
+ cudaMemcpyHostToDevice,
218
+ stream));
219
+
220
+ int device = -1;
221
+ C10_CUDA_CHECK(cudaGetDevice(&device));
222
+ int multiprocessors = 0;
223
+ C10_CUDA_CHECK(cudaDeviceGetAttribute(
224
+ &multiprocessors, cudaDevAttrMultiProcessorCount, device));
225
+ const int max_batch = min(
226
+ static_cast<int>(temp_costs.size(0)), 3 * multiprocessors);
227
+ const int shared_memory =
228
+ 2 * edges_per_state * static_cast<int>(sizeof(half)) + 512 + 64 + 128;
229
+ const int tiles = static_cast<int>(input_tiles.size(0));
230
+ if (!tiles) return;
231
+
232
+ switch (K)
233
+ {
234
+ case 2:
235
+ launch_trellis<2, 4>(
236
+ input_tiles.data_ptr<float>(), output_tiles.data_ptr<float>(),
237
+ reinterpret_cast<uint16_t*>(output_indices.data_ptr<int16_t>()),
238
+ reinterpret_cast<half*>(temp_costs.data_ptr<at::Half>()),
239
+ temp_edges.data_ptr<uint8_t>(), tiles, max_batch, shared_memory,
240
+ static_cast<int>(tailbite_context), stream);
241
+ break;
242
+ case 3:
243
+ launch_trellis<3, 4>(
244
+ input_tiles.data_ptr<float>(), output_tiles.data_ptr<float>(),
245
+ reinterpret_cast<uint16_t*>(output_indices.data_ptr<int16_t>()),
246
+ reinterpret_cast<half*>(temp_costs.data_ptr<at::Half>()),
247
+ temp_edges.data_ptr<uint8_t>(), tiles, max_batch, shared_memory,
248
+ static_cast<int>(tailbite_context), stream);
249
+ break;
250
+ case 4:
251
+ launch_trellis<4, 4>(
252
+ input_tiles.data_ptr<float>(), output_tiles.data_ptr<float>(),
253
+ reinterpret_cast<uint16_t*>(output_indices.data_ptr<int16_t>()),
254
+ reinterpret_cast<half*>(temp_costs.data_ptr<at::Half>()),
255
+ temp_edges.data_ptr<uint8_t>(), tiles, max_batch, shared_memory,
256
+ static_cast<int>(tailbite_context), stream);
257
+ break;
258
+ case 5:
259
+ launch_trellis<5, 4>(
260
+ input_tiles.data_ptr<float>(), output_tiles.data_ptr<float>(),
261
+ reinterpret_cast<uint16_t*>(output_indices.data_ptr<int16_t>()),
262
+ reinterpret_cast<half*>(temp_costs.data_ptr<at::Half>()),
263
+ temp_edges.data_ptr<uint8_t>(), tiles, max_batch, shared_memory,
264
+ static_cast<int>(tailbite_context), stream);
265
+ break;
266
+ case 6:
267
+ launch_trellis<6, 4>(
268
+ input_tiles.data_ptr<float>(), output_tiles.data_ptr<float>(),
269
+ reinterpret_cast<uint16_t*>(output_indices.data_ptr<int16_t>()),
270
+ reinterpret_cast<half*>(temp_costs.data_ptr<at::Half>()),
271
+ temp_edges.data_ptr<uint8_t>(), tiles, max_batch, shared_memory,
272
+ static_cast<int>(tailbite_context), stream);
273
+ break;
274
+ }
275
+ }
276
+
277
+ void quantize_tiles_procedural_cuda(
278
+ at::Tensor input_tiles,
279
+ at::Tensor output_tiles,
280
+ at::Tensor output_indices,
281
+ at::Tensor temp_costs,
282
+ at::Tensor temp_edges,
283
+ int64_t K,
284
+ int64_t codebook,
285
+ int64_t tailbite_context)
286
+ {
287
+ const at::cuda::OptionalCUDAGuard guard(input_tiles.device());
288
+ const cudaStream_t stream = at::cuda::getCurrentCUDAStream().stream();
289
+
290
+ TORCH_CHECK(input_tiles.is_cuda(), "input_tiles must be CUDA");
291
+ TORCH_CHECK(input_tiles.scalar_type() == at::kFloat, "input_tiles must be FP32");
292
+ TORCH_CHECK(input_tiles.dim() == 2 && input_tiles.size(1) == 256,
293
+ "input_tiles must have shape [tiles, 256]");
294
+ TORCH_CHECK(output_tiles.sizes() == input_tiles.sizes(),
295
+ "output_tiles shape mismatch");
296
+ TORCH_CHECK(output_tiles.scalar_type() == at::kFloat,
297
+ "output_tiles must be FP32");
298
+ TORCH_CHECK(output_indices.sizes() == input_tiles.sizes(),
299
+ "output_indices shape mismatch");
300
+ TORCH_CHECK(output_indices.scalar_type() == at::kShort,
301
+ "output_indices must be int16");
302
+ TORCH_CHECK(K >= 2 && K <= 4, "procedural control supports K2--K4");
303
+ TORCH_CHECK(codebook == 1 || codebook == 2,
304
+ "procedural codebook must be 1 (MCG) or 2 (MUL1)");
305
+ TORCH_CHECK(tailbite_context >= 1 && tailbite_context <= 128,
306
+ "tailbite_context must be in 1..128");
307
+
308
+ const int edges_per_state = 65536 >> K;
309
+ const int decision_entries = K == 2 ? edges_per_state / 4 : edges_per_state / 2;
310
+ TORCH_CHECK(temp_costs.scalar_type() == at::kHalf && temp_costs.dim() == 3,
311
+ "temp_costs must be rank-3 FP16");
312
+ TORCH_CHECK(temp_costs.size(1) == 2 && temp_costs.size(2) == edges_per_state,
313
+ "temp_costs shape mismatch");
314
+ TORCH_CHECK(temp_edges.scalar_type() == at::kByte && temp_edges.dim() == 3,
315
+ "temp_edges must be rank-3 uint8");
316
+ TORCH_CHECK(temp_edges.size(1) == 256 && temp_edges.size(2) == decision_entries,
317
+ "temp_edges shape mismatch");
318
+
319
+ int device = -1;
320
+ C10_CUDA_CHECK(cudaGetDevice(&device));
321
+ int multiprocessors = 0;
322
+ C10_CUDA_CHECK(cudaDeviceGetAttribute(
323
+ &multiprocessors, cudaDevAttrMultiProcessorCount, device));
324
+ const int max_batch = min(
325
+ static_cast<int>(temp_costs.size(0)), 3 * multiprocessors);
326
+ const int shared_memory =
327
+ 2 * edges_per_state * static_cast<int>(sizeof(half)) + 512 + 64 + 128;
328
+ const int tiles = static_cast<int>(input_tiles.size(0));
329
+ if (!tiles) return;
330
+
331
+ #define LAUNCH_PROCEDURAL(K_VALUE, CODEBOOK_VALUE) \
332
+ launch_trellis<K_VALUE, CODEBOOK_VALUE>( \
333
+ input_tiles.data_ptr<float>(), output_tiles.data_ptr<float>(), \
334
+ reinterpret_cast<uint16_t*>(output_indices.data_ptr<int16_t>()), \
335
+ reinterpret_cast<half*>(temp_costs.data_ptr<at::Half>()), \
336
+ temp_edges.data_ptr<uint8_t>(), tiles, max_batch, shared_memory, \
337
+ static_cast<int>(tailbite_context), stream)
338
+
339
+ if (codebook == 1)
340
+ {
341
+ switch (K)
342
+ {
343
+ case 2: LAUNCH_PROCEDURAL(2, 1); break;
344
+ case 3: LAUNCH_PROCEDURAL(3, 1); break;
345
+ case 4: LAUNCH_PROCEDURAL(4, 1); break;
346
+ }
347
+ }
348
+ else
349
+ {
350
+ switch (K)
351
+ {
352
+ case 2: LAUNCH_PROCEDURAL(2, 2); break;
353
+ case 3: LAUNCH_PROCEDURAL(3, 2); break;
354
+ case 4: LAUNCH_PROCEDURAL(4, 2); break;
355
+ }
356
+ }
357
+ #undef LAUNCH_PROCEDURAL
358
+ }
reproduction/closure/patches/kquant/changed-files/kquant/exl3_encoder_backend.py ADDED
The diff for this file is too large to render. See raw diff
 
reproduction/closure/patches/kquant/changed-files/kquant/exl3_reference.py ADDED
@@ -0,0 +1,281 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Pure-PyTorch reference operations for EXL3 procedural codebooks."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import math
6
+
7
+ import torch
8
+
9
+ from kquant.sqg_e4m3 import (
10
+ SQG_XOR_CHEB_T12,
11
+ SQG_CHEB,
12
+ SQG_CHEB_NORMAL_E4M3,
13
+ SQG_NORMAL_E4M3,
14
+ sqg_codebook,
15
+ )
16
+
17
+
18
+ TILE_VALUES = 256
19
+ HADAMARD_BLOCK = 128
20
+ CODEBOOK_SQG_NORMAL_E4M3 = SQG_NORMAL_E4M3
21
+ CODEBOOK_SQG_XOR_CHEB_T12 = SQG_XOR_CHEB_T12
22
+ CODEBOOK_SQG_CHEB_NORMAL_E4M3 = SQG_CHEB_NORMAL_E4M3
23
+ CODEBOOK_SQG_CHEB = SQG_CHEB
24
+ QSRT_CODEBOOKS = (
25
+ CODEBOOK_SQG_XOR_CHEB_T12,
26
+ CODEBOOK_SQG_NORMAL_E4M3,
27
+ CODEBOOK_SQG_CHEB_NORMAL_E4M3,
28
+ CODEBOOK_SQG_CHEB,
29
+ )
30
+
31
+
32
+ def _validate_bits(bits: int) -> None:
33
+ if isinstance(bits, bool) or not isinstance(bits, int) or bits not in range(2, 7):
34
+ raise ValueError("the SQG reference supports K=2 through K=6")
35
+
36
+
37
+ def reconstruct_trellis_states(
38
+ edge_symbols: torch.Tensor, bits: int
39
+ ) -> torch.Tensor:
40
+ """Recover cyclic 16-bit trellis states from their stored K-bit edges.
41
+
42
+ A state is the low 16 bits of ``(previous_state << K) | edge``. EXL's
43
+ 256-symbol tile is cyclic, so state zero also incorporates the final edge
44
+ symbols in the tile.
45
+ """
46
+
47
+ _validate_bits(bits)
48
+ if edge_symbols.ndim < 1 or edge_symbols.shape[-1] != TILE_VALUES:
49
+ raise ValueError("edge_symbols must have a final dimension of 256")
50
+ if edge_symbols.dtype == torch.bool or edge_symbols.is_floating_point():
51
+ raise TypeError("edge_symbols must use an integer dtype")
52
+ edges = edge_symbols.to(dtype=torch.int64) & ((1 << bits) - 1)
53
+ # Unroll the cyclic recurrence in state space. At position i, edge i is
54
+ # in the low K bits, edge i-1 is above it, and so on. Only ceil(16 / K)
55
+ # edges can survive the low-16-bit mask. Expressing that closed form with
56
+ # 4--8 rolls avoids launching one tensor operation for every one of the
57
+ # 256 symbols when this reference check runs on CUDA.
58
+ states = torch.zeros_like(edges)
59
+ for lag in range(math.ceil(16 / bits)):
60
+ states |= torch.roll(edges, shifts=lag, dims=-1) << (lag * bits)
61
+ return (states & 0xFFFF).to(dtype=torch.int16).contiguous()
62
+
63
+
64
+ def _decode_codebook_states(
65
+ states: torch.Tensor,
66
+ codebook: str,
67
+ *,
68
+ bits: int | None = None,
69
+ rate_axis: str | None = None,
70
+ ) -> torch.Tensor:
71
+ if codebook in QSRT_CODEBOOKS:
72
+ if bits is None:
73
+ raise ValueError("SQG reconstruction requires an explicit trellis rate")
74
+ _validate_bits(bits)
75
+ indices = (states.to(dtype=torch.int64) & 0xFFFF).long()
76
+ values = sqg_codebook(
77
+ bits,
78
+ codebook,
79
+ rate_axis=rate_axis,
80
+ device=states.device,
81
+ dtype=torch.float16,
82
+ )
83
+ return values.index_select(0, indices.flatten()).reshape_as(states)
84
+ raise ValueError(
85
+ f"unsupported QSRT codebook {codebook!r}; expected one of {QSRT_CODEBOOKS}"
86
+ )
87
+
88
+
89
+ def tensor_core_permutation(device: torch.device | str = "cpu") -> torch.Tensor:
90
+ """Return the native EXL 16x16 row-major -> tensor-core element order."""
91
+
92
+ permutation = [0] * TILE_VALUES
93
+ for thread in range(32):
94
+ row0 = (thread % 4) * 2
95
+ row1 = row0 + 1
96
+ row2 = row0 + 8
97
+ row3 = row0 + 9
98
+ column0 = thread // 4
99
+ column1 = column0 + 8
100
+ permutation[thread * 8 + 0] = row0 * 16 + column0
101
+ permutation[thread * 8 + 1] = row1 * 16 + column0
102
+ permutation[thread * 8 + 2] = row2 * 16 + column0
103
+ permutation[thread * 8 + 3] = row3 * 16 + column0
104
+ permutation[thread * 8 + 4] = row0 * 16 + column1
105
+ permutation[thread * 8 + 5] = row1 * 16 + column1
106
+ permutation[thread * 8 + 6] = row2 * 16 + column1
107
+ permutation[thread * 8 + 7] = row3 * 16 + column1
108
+ return torch.tensor(permutation, dtype=torch.long, device=device)
109
+
110
+
111
+ def decode_regularized_weight(
112
+ states: torch.Tensor,
113
+ *,
114
+ codebook: str = CODEBOOK_SQG_XOR_CHEB_T12,
115
+ codebook_values: torch.Tensor | None = None,
116
+ bits: int | None = None,
117
+ ) -> torch.Tensor:
118
+ """Decode ``[K/16, N/16, 256]`` states to transformed ``[K, N]``."""
119
+
120
+ if states.ndim != 3 or states.shape[-1] != TILE_VALUES:
121
+ raise ValueError("states must have shape [K/16, N/16, 256]")
122
+ if codebook_values is None:
123
+ decoded = _decode_codebook_states(states, codebook, bits=bits).float()
124
+ else:
125
+ if codebook_values.ndim != 1 or codebook_values.numel() != 1 << 16:
126
+ raise ValueError("custom codebook must contain exactly 65,536 values")
127
+ if not codebook_values.is_floating_point():
128
+ raise TypeError("custom codebook must be floating point")
129
+ if not bool(torch.isfinite(codebook_values).all()):
130
+ raise ValueError("custom codebook must be finite")
131
+ indices = (states.to(dtype=torch.int64) & 0xFFFF).long()
132
+ decoded = codebook_values.to(device=states.device).index_select(
133
+ 0, indices.flatten()
134
+ ).reshape_as(states).float()
135
+ inverse = torch.argsort(tensor_core_permutation(states.device))
136
+ decoded = decoded.index_select(-1, inverse)
137
+ k_tiles, n_tiles, _ = decoded.shape
138
+ return (
139
+ decoded.reshape(k_tiles, n_tiles, 16, 16)
140
+ .permute(0, 2, 1, 3)
141
+ .reshape(k_tiles * 16, n_tiles * 16)
142
+ .contiguous()
143
+ )
144
+
145
+
146
+ def decode_qsrt_regularized_weight(
147
+ states: torch.Tensor,
148
+ *,
149
+ rate_axis: str,
150
+ tile_bits: tuple[int, ...],
151
+ codebook: str,
152
+ ) -> torch.Tensor:
153
+ """Decode a K2--K6 tile map to transformed ``[K, N]`` weights.
154
+
155
+ SQG uses a distinct state labelling for every supported K, so the physical
156
+ tile rate is part of the numerical decode contract.
157
+ """
158
+
159
+ if states.ndim != 3 or states.shape[-1] != TILE_VALUES:
160
+ raise ValueError("states must have shape [K/16, N/16, 256]")
161
+ if rate_axis not in ("k", "n"):
162
+ raise ValueError("rate_axis must be 'k' or 'n'")
163
+ axis = 0 if rate_axis == "k" else 1
164
+ if len(tile_bits) != states.shape[axis]:
165
+ raise ValueError("tile_bits length does not match the selected rate axis")
166
+ if any(
167
+ isinstance(value, bool) or not isinstance(value, int) or value not in range(2, 7)
168
+ for value in tile_bits
169
+ ):
170
+ raise ValueError("tile_bits must contain only integer K2 through K6")
171
+ if codebook not in QSRT_CODEBOOKS:
172
+ raise ValueError(f"unsupported QSRT codebook: {codebook}")
173
+
174
+ decoded_tiles = torch.empty_like(states, dtype=torch.float32)
175
+ bits_tensor = torch.tensor(tile_bits, dtype=torch.long, device=states.device)
176
+ for bits in sorted(set(tile_bits)):
177
+ positions = torch.nonzero(bits_tensor == bits).flatten()
178
+ selected = states.index_select(axis, positions)
179
+ values = _decode_codebook_states(
180
+ selected, codebook, bits=bits, rate_axis=rate_axis
181
+ ).float()
182
+ decoded_tiles.index_copy_(axis, positions, values)
183
+
184
+ inverse = torch.argsort(tensor_core_permutation(states.device))
185
+ decoded_tiles = decoded_tiles.index_select(-1, inverse)
186
+ k_tiles, n_tiles, _ = decoded_tiles.shape
187
+ return (
188
+ decoded_tiles.reshape(k_tiles, n_tiles, 16, 16)
189
+ .permute(0, 2, 1, 3)
190
+ .reshape(k_tiles * 16, n_tiles * 16)
191
+ .contiguous()
192
+ )
193
+
194
+
195
+ def normalized_hadamard(
196
+ *,
197
+ device: torch.device | str,
198
+ dtype: torch.dtype = torch.float32,
199
+ size: int = HADAMARD_BLOCK,
200
+ ) -> torch.Tensor:
201
+ if size <= 0 or size & (size - 1):
202
+ raise ValueError("Hadamard size must be a positive power of two")
203
+ matrix = torch.ones((1, 1), dtype=dtype, device=device)
204
+ while matrix.shape[0] < size:
205
+ matrix = torch.cat(
206
+ (
207
+ torch.cat((matrix, matrix), dim=1),
208
+ torch.cat((matrix, -matrix), dim=1),
209
+ ),
210
+ dim=0,
211
+ )
212
+ return matrix * (1.0 / math.sqrt(size))
213
+
214
+
215
+ def _blockwise_hadamard_left(weight: torch.Tensor) -> torch.Tensor:
216
+ if weight.shape[0] % HADAMARD_BLOCK:
217
+ raise ValueError("EXL K dimension must be divisible by 128")
218
+ hadamard = normalized_hadamard(device=weight.device, dtype=weight.dtype)
219
+ blocks = weight.reshape(-1, HADAMARD_BLOCK, weight.shape[1])
220
+ return torch.matmul(hadamard, blocks).reshape_as(weight).contiguous()
221
+
222
+
223
+ def _blockwise_hadamard_right(weight: torch.Tensor) -> torch.Tensor:
224
+ if weight.shape[1] % HADAMARD_BLOCK:
225
+ raise ValueError("EXL N dimension must be divisible by 128")
226
+ hadamard = normalized_hadamard(device=weight.device, dtype=weight.dtype)
227
+ blocks = weight.reshape(weight.shape[0], -1, HADAMARD_BLOCK)
228
+ return torch.matmul(blocks, hadamard).reshape_as(weight).contiguous()
229
+
230
+
231
+ def decode_exl3_weight(
232
+ states: torch.Tensor,
233
+ suh: torch.Tensor,
234
+ svh: torch.Tensor,
235
+ *,
236
+ codebook: str = CODEBOOK_SQG_XOR_CHEB_T12,
237
+ codebook_values: torch.Tensor | None = None,
238
+ bits: int | None = None,
239
+ ) -> torch.Tensor:
240
+ """Decode stored states/scales to an EXL-oriented ``[K, N]`` weight."""
241
+
242
+ weight = decode_regularized_weight(
243
+ states, codebook=codebook, codebook_values=codebook_values, bits=bits
244
+ )
245
+ if suh.ndim != 1 or suh.numel() != weight.shape[0]:
246
+ raise ValueError("suh length does not match the EXL K dimension")
247
+ if svh.ndim != 1 or svh.numel() != weight.shape[1]:
248
+ raise ValueError("svh length does not match the EXL N dimension")
249
+ weight = _blockwise_hadamard_left(weight)
250
+ weight *= suh.to(device=weight.device, dtype=weight.dtype).unsqueeze(1)
251
+ weight = _blockwise_hadamard_right(weight)
252
+ weight *= svh.to(device=weight.device, dtype=weight.dtype).unsqueeze(0)
253
+ return weight.contiguous()
254
+
255
+
256
+ def decode_qsrt_weight(
257
+ states: torch.Tensor,
258
+ suh: torch.Tensor,
259
+ svh: torch.Tensor,
260
+ *,
261
+ rate_axis: str,
262
+ tile_bits: tuple[int, ...],
263
+ codebook: str = CODEBOOK_SQG_XOR_CHEB_T12,
264
+ ) -> torch.Tensor:
265
+ """Decode stored QSRT states and scales to an EXL ``[K, N]`` weight."""
266
+
267
+ weight = decode_qsrt_regularized_weight(
268
+ states,
269
+ rate_axis=rate_axis,
270
+ tile_bits=tile_bits,
271
+ codebook=codebook,
272
+ )
273
+ if suh.ndim != 1 or suh.numel() != weight.shape[0]:
274
+ raise ValueError("suh length does not match the EXL K dimension")
275
+ if svh.ndim != 1 or svh.numel() != weight.shape[1]:
276
+ raise ValueError("svh length does not match the EXL N dimension")
277
+ weight = _blockwise_hadamard_left(weight)
278
+ weight *= suh.to(device=weight.device, dtype=weight.dtype).unsqueeze(1)
279
+ weight = _blockwise_hadamard_right(weight)
280
+ weight *= svh.to(device=weight.device, dtype=weight.dtype).unsqueeze(0)
281
+ return weight.contiguous()
reproduction/closure/patches/kquant/changed-files/kquant/qsrt.py ADDED
@@ -0,0 +1,1141 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Reference codec geometry for Kimi-K3 QSRT candidates.
2
+
3
+ Candidate payloads describe complete experts and contain no tensor-parallel
4
+ ownership. TP sharding is a property of the atom-major storage/runtime layer.
5
+ The ordinary expert weights use ``[out_features, in_features]`` orientation,
6
+ while the EXL encoder consumes their transpose, ``[K, N]``. Consequently the
7
+ shared 3072-channel intermediate axis is EXL ``N`` for ``w1``/``w3`` and EXL
8
+ ``K`` for ``w2``.
9
+
10
+ The reference packer preserves the native EXL bit ordering for each 16x16
11
+ trellis tile. Its inverse reconstructs both the stored K-bit edge symbols and
12
+ the full 16-bit cyclic trellis states consumed by the SQG decoder.
13
+ """
14
+
15
+ from __future__ import annotations
16
+
17
+ from collections.abc import Sequence
18
+ from dataclasses import dataclass
19
+ from typing import Literal
20
+
21
+ import torch
22
+
23
+ from kquant.exl3_reference import (
24
+ CODEBOOK_SQG_XOR_CHEB_T12,
25
+ CODEBOOK_SQG_CHEB_NORMAL_E4M3,
26
+ CODEBOOK_SQG_CHEB,
27
+ CODEBOOK_SQG_NORMAL_E4M3,
28
+ QSRT_CODEBOOKS,
29
+ decode_qsrt_weight,
30
+ reconstruct_trellis_states,
31
+ )
32
+
33
+
34
+ EXPERTS_PER_LAYER = 896
35
+ INTERMEDIATE_CHANNELS = 3072
36
+ LATENT_CHANNELS = 3584
37
+ CONTEXT_GROUP_CHANNELS = 4
38
+ TILE_CHANNELS = 16
39
+ TILE_VALUES = TILE_CHANNELS * TILE_CHANNELS
40
+ RECORD_CHANNELS = 128
41
+ PAIR_CHANNELS = 2 * RECORD_CHANNELS
42
+ RECORDS_PER_EXPERT = INTERMEDIATE_CHANNELS // RECORD_CHANNELS
43
+ PAIRS_PER_EXPERT = RECORDS_PER_EXPERT // 2
44
+ TILES_PER_RECORD_AXIS = RECORD_CHANNELS // TILE_CHANNELS
45
+ SCHEMA = "kquant_kimi_k3_qsrt_candidate_v1"
46
+ LOGICAL_CANDIDATE_SCHEMAS = (SCHEMA,)
47
+ STORAGE_ALIGNMENT = 4096
48
+ PAIR_ROTATION_EXPERT_MULTIPLIER = 5
49
+
50
+ # The phase-1 table uses one byte per expert. Compressed entries contain
51
+ # two four-bit transfer counts: high nibble r13 for fused w1/w3, low nibble r2
52
+ # for w2. Each value is in 0..2. 0xff denotes the exact X4T tier. The nibbles
53
+ # remain deliberately roomy so the fixed table is cheap to inspect and decode.
54
+ FORMAT_BITS = 8
55
+ FORMAT_X4T = 0xFF
56
+ FORMAT_NIBBLE_MASK = 0x0F
57
+
58
+ LAYER_HEADER_BYTES = STORAGE_ALIGNMENT
59
+ FORMAT_TABLE_BYTES = (EXPERTS_PER_LAYER * FORMAT_BITS + 7) // 8
60
+ FORMAT_SECTION_BYTES = STORAGE_ALIGNMENT
61
+ HOT_FORMAT_BYTES = EXPERTS_PER_LAYER
62
+ HOT_SLOT_BYTES = EXPERTS_PER_LAYER * torch.int16.itemsize
63
+ HOT_METADATA_BYTES = HOT_FORMAT_BYTES + HOT_SLOT_BYTES
64
+
65
+ # Shared hidden-side vectors are w1.suh, w3.suh, and w2.svh. The three
66
+ # corresponding intermediate-side vectors remain expert-local. Their
67
+ # atom-major storage is defined independently from a serving TP size.
68
+ SHARED_SCALE_VECTORS = 3
69
+ LOCAL_SCALE_VECTORS = 3
70
+ SHARED_SCALE_ORDER = ("w1.suh", "w3.suh", "w2.svh")
71
+ LOCAL_SCALE_ORDER = ("w1.svh", "w3.svh", "w2.suh")
72
+ SCALE_BYTES = torch.float16.itemsize
73
+ SHARED_SCALE_BYTES = SHARED_SCALE_VECTORS * LATENT_CHANNELS * SCALE_BYTES
74
+ SHARED_SCALE_SECTION_BYTES = 6 * STORAGE_ALIGNMENT
75
+
76
+ # P24 and P33 both carry a six-bit sum over 256 intermediate channels.
77
+ PAIR_BYTES = PAIR_CHANNELS * LATENT_CHANNELS * 3 // 8
78
+ MATRIX_TRELLIS_BYTES = PAIRS_PER_EXPERT * PAIR_BYTES
79
+ EXPERT_TRELLIS_BYTES = 3 * MATRIX_TRELLIS_BYTES
80
+ RateAxis = Literal["k", "n"]
81
+ PairKind = Literal["P24", "P33"]
82
+
83
+ MATRIX_RATE_AXIS: dict[str, RateAxis] = {
84
+ "w1": "n",
85
+ "w3": "n",
86
+ "w2": "k",
87
+ }
88
+
89
+
90
+ def pair_rotation(layer: int, expert: int) -> int:
91
+ """Cyclic logical-pair placement used to balance physical atom slots."""
92
+
93
+ if (
94
+ isinstance(layer, bool)
95
+ or not isinstance(layer, int)
96
+ or layer not in range(1, 93)
97
+ ):
98
+ raise ValueError("K3 MoE layer must be in 1..92")
99
+ if (
100
+ isinstance(expert, bool)
101
+ or not isinstance(expert, int)
102
+ or not 0 <= expert < EXPERTS_PER_LAYER
103
+ ):
104
+ raise ValueError(f"expert must be in 0..{EXPERTS_PER_LAYER - 1}")
105
+ return (PAIR_ROTATION_EXPERT_MULTIPLIER * expert + layer) % PAIRS_PER_EXPERT
106
+
107
+
108
+ def logical_pair_for_slot(layer: int, expert: int, pair_slot: int) -> int:
109
+ """Logical candidate pair stored in one physical pair slot."""
110
+
111
+ if (
112
+ isinstance(pair_slot, bool)
113
+ or not isinstance(pair_slot, int)
114
+ or not 0 <= pair_slot < PAIRS_PER_EXPERT
115
+ ):
116
+ raise ValueError(f"pair_slot must be in 0..{PAIRS_PER_EXPERT - 1}")
117
+ return (pair_slot - pair_rotation(layer, expert)) % PAIRS_PER_EXPERT
118
+
119
+
120
+ def physical_pair_slot(layer: int, expert: int, logical_pair: int) -> int:
121
+ """Physical slot containing one logical candidate pair."""
122
+
123
+ if (
124
+ isinstance(logical_pair, bool)
125
+ or not isinstance(logical_pair, int)
126
+ or not 0 <= logical_pair < PAIRS_PER_EXPERT
127
+ ):
128
+ raise ValueError(f"logical_pair must be in 0..{PAIRS_PER_EXPERT - 1}")
129
+ return (logical_pair + pair_rotation(layer, expert)) % PAIRS_PER_EXPERT
130
+
131
+
132
+ @dataclass(frozen=True)
133
+ class ModeSpec:
134
+ """One rate-transfer schedule, ordered from low to high importance.
135
+
136
+ ``context_bits`` contains one entry per final 128-channel record.
137
+ ``mode_id`` is the number of K2/K4 record exchanges.
138
+ """
139
+
140
+ mode_id: int
141
+ name: str
142
+ context_bits: tuple[int, ...]
143
+ def __post_init__(self) -> None:
144
+ if isinstance(self.mode_id, bool) or not isinstance(self.mode_id, int):
145
+ raise TypeError("mode_id must be an integer")
146
+ if not 0 <= self.mode_id <= 2:
147
+ raise ValueError("QSRT mode_id must be R0, R1, or R2")
148
+ if not self.name:
149
+ raise ValueError("mode name must not be empty")
150
+ if not self.context_bits or len(self.context_bits) % 2:
151
+ raise ValueError("a mode must contain an even, nonzero context count")
152
+ if any(bits not in (2, 3, 4) for bits in self.context_bits):
153
+ raise ValueError("Kimi-K3 QSRT supports only K2, K3, and K4")
154
+ if sum(self.context_bits) != 3 * len(self.context_bits):
155
+ raise ValueError("a mode must average exactly three trellis bits")
156
+ if INTERMEDIATE_CHANNELS % len(self.context_bits):
157
+ raise ValueError("contexts must divide the 3072-channel axis")
158
+ context_channels = INTERMEDIATE_CHANNELS // len(self.context_bits)
159
+ if context_channels % RECORD_CHANNELS:
160
+ raise ValueError("each context must contain whole 128-channel records")
161
+ if tuple(sorted(self.context_bits)) != self.context_bits:
162
+ raise ValueError("context rates must be monotone from K2 through K4")
163
+ records_per_context = RECORDS_PER_EXPERT // len(self.context_bits)
164
+ k2_records = self.context_bits.count(2) * records_per_context
165
+ k4_records = self.context_bits.count(4) * records_per_context
166
+ if k2_records != k4_records:
167
+ raise ValueError("K2 and K4 record counts must match")
168
+ if self.mode_id != k2_records:
169
+ raise ValueError(
170
+ f"mode_id must equal the rate-transfer count {k2_records}"
171
+ )
172
+
173
+ @property
174
+ def context_count(self) -> int:
175
+ return len(self.context_bits)
176
+
177
+ @property
178
+ def records_per_context(self) -> int:
179
+ return RECORDS_PER_EXPERT // self.context_count
180
+
181
+
182
+ def _rate_transfer_mode(r: int) -> ModeSpec:
183
+ return ModeSpec(
184
+ r,
185
+ f"R{r}",
186
+ (2,) * r + (3,) * (RECORDS_PER_EXPERT - 2 * r) + (4,) * r,
187
+ )
188
+
189
+
190
+ RATE_TRANSFER_MODES = tuple(_rate_transfer_mode(r) for r in range(3))
191
+ R0 = RATE_TRANSFER_MODES[0]
192
+ R1 = RATE_TRANSFER_MODES[1]
193
+ R2 = RATE_TRANSFER_MODES[2]
194
+ REPRESENTATIVE_MODE_CANDIDATES = RATE_TRANSFER_MODES
195
+ EXPERIMENTAL_MODE_CANDIDATES = RATE_TRANSFER_MODES
196
+
197
+ # Frozen phase-1 encoder policy. The payload schema still parses the complete
198
+ # ladder for controlled studies, but the initial all-expert run searches R0,
199
+ # R1, and R2 independently for the fused w1/w3 family and for w2. The
200
+ # covariance alphas are offline encoder controls and consume no format bits.
201
+ PHASE1_MODE_IDS = (0, 1, 2)
202
+ PHASE1_MODE_CANDIDATES = tuple(RATE_TRANSFER_MODES[r] for r in PHASE1_MODE_IDS)
203
+ PHASE1_SHARED_RATE_MODE = False
204
+ PHASE1_H13_EXPERT_LOCAL_ALPHA = 0.0
205
+ # Maximum local weight for adaptive, scaled-identity OAS H2 shrinkage. The
206
+ # actual alpha is support-dependent and can be substantially smaller.
207
+ PHASE1_H2_EXPERT_LOCAL_ALPHA = 0.75
208
+ PHASE1_H2_LOCAL_BASIS = "decoded_candidate_post_situ"
209
+ PHASE1_H2_SHRINKAGE_POLICY = "weighted_oas_scaled_identity"
210
+ _MODES_BY_NAME = {mode.name: mode for mode in RATE_TRANSFER_MODES}
211
+ _MODES_BY_ID = {mode.mode_id: mode for mode in RATE_TRANSFER_MODES}
212
+
213
+
214
+ def mode_from_context_bits(context_bits: Sequence[int]) -> ModeSpec:
215
+ """Resolve any legal equal-context ladder allocation to canonical ``R_r``."""
216
+
217
+ bits = tuple(context_bits)
218
+ if not bits or RECORDS_PER_EXPERT % len(bits):
219
+ raise ValueError("allocation contexts must divide the 24 records")
220
+ records_per_context = RECORDS_PER_EXPERT // len(bits)
221
+ r = bits.count(2) * records_per_context
222
+ # ModeSpec performs monotonicity, rate, and equal-donor validation.
223
+ ModeSpec(r, "candidate", bits)
224
+ return RATE_TRANSFER_MODES[r]
225
+
226
+
227
+ @dataclass(frozen=True)
228
+ class ExpertFormatSpec:
229
+ """Provisional per-expert tier and matrix-family rate schedules."""
230
+
231
+ r13: int | None
232
+ r2: int | None
233
+
234
+ def __post_init__(self) -> None:
235
+ if (self.r13 is None) != (self.r2 is None):
236
+ raise ValueError("r13 and r2 must both be absent or both be present")
237
+ for name, value in (("r13", self.r13), ("r2", self.r2)):
238
+ if value is None:
239
+ continue
240
+ if isinstance(value, bool) or not isinstance(value, int):
241
+ raise TypeError(f"{name} must be an integer")
242
+ if not 0 <= value <= 2:
243
+ raise ValueError(f"{name} must be R0, R1, or R2")
244
+
245
+ @classmethod
246
+ def x4t(cls) -> "ExpertFormatSpec":
247
+ return cls(None, None)
248
+
249
+ @classmethod
250
+ def compressed(cls, r13: int, r2: int | None = None) -> "ExpertFormatSpec":
251
+ return cls(r13, r13 if r2 is None else r2)
252
+
253
+ @property
254
+ def is_x4t(self) -> bool:
255
+ return self.r13 is None
256
+
257
+ @property
258
+ def name(self) -> str:
259
+ if self.is_x4t:
260
+ return "X4T"
261
+ assert self.r13 is not None and self.r2 is not None
262
+ return f"R{self.r13}" if self.r13 == self.r2 else f"R{self.r13}/R{self.r2}"
263
+
264
+ @property
265
+ def code(self) -> int:
266
+ if self.is_x4t:
267
+ return FORMAT_X4T
268
+ assert self.r13 is not None and self.r2 is not None
269
+ return (self.r13 << 4) | self.r2
270
+
271
+ @classmethod
272
+ def from_code(cls, code: int) -> "ExpertFormatSpec":
273
+ if code == FORMAT_X4T:
274
+ return cls.x4t()
275
+ r13 = code >> 4
276
+ r2 = code & FORMAT_NIBBLE_MASK
277
+ if r13 > 2 or r2 > 2:
278
+ raise ValueError(f"format table contains invalid rate code 0x{code:02x}")
279
+ return cls.compressed(r13, r2)
280
+
281
+
282
+ ExpertFormatLike = str | ModeSpec | ExpertFormatSpec | tuple[int, int]
283
+
284
+
285
+ def align_up(value: int, alignment: int = STORAGE_ALIGNMENT) -> int:
286
+ if isinstance(value, bool) or not isinstance(value, int) or value < 0:
287
+ raise ValueError("value must be a non-negative integer")
288
+ if (
289
+ isinstance(alignment, bool)
290
+ or not isinstance(alignment, int)
291
+ or alignment <= 0
292
+ or alignment & (alignment - 1)
293
+ ):
294
+ raise ValueError("alignment must be a positive power of two")
295
+ return (value + alignment - 1) & -alignment
296
+
297
+
298
+ def resolve_expert_format(value: ExpertFormatLike) -> ExpertFormatSpec:
299
+ if isinstance(value, ExpertFormatSpec):
300
+ return value
301
+ if isinstance(value, ModeSpec):
302
+ return ExpertFormatSpec.compressed(value.mode_id)
303
+ if isinstance(value, tuple):
304
+ if len(value) != 2:
305
+ raise ValueError("expert format tuple must be (r13, r2)")
306
+ return ExpertFormatSpec.compressed(value[0], value[1])
307
+ if not isinstance(value, str):
308
+ raise TypeError(
309
+ "expert format must be a name, ModeSpec, ExpertFormatSpec, or pair"
310
+ )
311
+ normalized = value.upper()
312
+ if normalized == "X4T":
313
+ return ExpertFormatSpec.x4t()
314
+ if "/" in normalized:
315
+ left, right = normalized.split("/", 1)
316
+ return ExpertFormatSpec.compressed(
317
+ resolve_mode(left).mode_id, resolve_mode(right).mode_id
318
+ )
319
+ return ExpertFormatSpec.compressed(resolve_mode(normalized).mode_id)
320
+
321
+
322
+ def pack_qsrt_format_table(formats: Sequence[ExpertFormatLike]) -> torch.Tensor:
323
+ """Pack 896 one-byte expert format codes."""
324
+
325
+ if len(formats) != EXPERTS_PER_LAYER:
326
+ raise ValueError(f"format table must contain {EXPERTS_PER_LAYER} experts")
327
+ return torch.tensor(
328
+ [resolve_expert_format(value).code for value in formats],
329
+ dtype=torch.uint8,
330
+ ).contiguous()
331
+
332
+
333
+ def unpack_qsrt_format_table(payload: torch.Tensor) -> tuple[str, ...]:
334
+ """Decode the format table and reject invalid rate nibbles."""
335
+
336
+ if payload.dtype != torch.uint8:
337
+ raise TypeError("format table must use torch.uint8")
338
+ if payload.ndim != 1 or payload.numel() != FORMAT_TABLE_BYTES:
339
+ raise ValueError(
340
+ f"format table must contain exactly {FORMAT_TABLE_BYTES} bytes"
341
+ )
342
+ return tuple(
343
+ ExpertFormatSpec.from_code(code).name for code in payload.cpu().tolist()
344
+ )
345
+
346
+
347
+ def pack_qsrt_format_section(formats: Sequence[ExpertFormatLike]) -> torch.Tensor:
348
+ """Build the canonical 4-KiB on-disk format-table section."""
349
+
350
+ table = pack_qsrt_format_table(formats)
351
+ section = torch.zeros(FORMAT_SECTION_BYTES, dtype=torch.uint8)
352
+ section[:FORMAT_TABLE_BYTES].copy_(table)
353
+ return section
354
+
355
+
356
+ def unpack_qsrt_format_section(payload: torch.Tensor) -> tuple[str, ...]:
357
+ if payload.dtype != torch.uint8:
358
+ raise TypeError("format section must use torch.uint8")
359
+ if payload.ndim != 1 or payload.numel() != FORMAT_SECTION_BYTES:
360
+ raise ValueError(
361
+ f"format section must contain exactly {FORMAT_SECTION_BYTES} bytes"
362
+ )
363
+ if bool(torch.any(payload[FORMAT_TABLE_BYTES:] != 0)):
364
+ raise ValueError("format section has nonzero alignment padding")
365
+ return unpack_qsrt_format_table(payload[:FORMAT_TABLE_BYTES])
366
+
367
+
368
+ def expand_qsrt_hot_metadata(
369
+ formats: Sequence[ExpertFormatLike],
370
+ ) -> tuple[torch.Tensor, torch.Tensor]:
371
+ """Expand disk codes to uint8 schedules and uint16 tier-local slots."""
372
+
373
+ codes = pack_qsrt_format_table(formats)
374
+ # Validate before deriving slots, including codes supplied through strings.
375
+ unpack_qsrt_format_table(codes)
376
+ slots = torch.empty(EXPERTS_PER_LAYER, dtype=torch.int16)
377
+ compressed_slot = 0
378
+ kept_slot = 0
379
+ for expert, code in enumerate(codes.tolist()):
380
+ if code == FORMAT_X4T:
381
+ slots[expert] = kept_slot
382
+ kept_slot += 1
383
+ else:
384
+ slots[expert] = compressed_slot
385
+ compressed_slot += 1
386
+ return codes, slots
387
+
388
+
389
+ def _validate_scale_vector(
390
+ scale: torch.Tensor, length: int, name: str, device: torch.device | None = None
391
+ ) -> None:
392
+ if scale.dtype != torch.float16:
393
+ raise TypeError(f"{name} must use torch.float16")
394
+ if scale.ndim != 1 or scale.numel() != length:
395
+ raise ValueError(f"{name} must contain exactly {length} values")
396
+ if not scale.is_contiguous():
397
+ raise ValueError(f"{name} must be contiguous")
398
+ if device is not None and scale.device != device:
399
+ raise ValueError(f"{name} must be on {device}")
400
+ if not bool(torch.all(torch.isfinite(scale))):
401
+ raise ValueError(f"{name} contains non-finite values")
402
+
403
+
404
+ def pack_qsrt_shared_scale_section(
405
+ w1_suh: torch.Tensor, w3_suh: torch.Tensor, w2_svh: torch.Tensor
406
+ ) -> torch.Tensor:
407
+ """Pack the three layer-shared hidden-side FP16 vectors and zero padding."""
408
+
409
+ scales = (w1_suh, w3_suh, w2_svh)
410
+ device = scales[0].device
411
+ for name, scale in zip(SHARED_SCALE_ORDER, scales, strict=True):
412
+ _validate_scale_vector(scale, LATENT_CHANNELS, name, device)
413
+ section = torch.zeros(
414
+ SHARED_SCALE_SECTION_BYTES, dtype=torch.uint8, device=device
415
+ )
416
+ cursor = 0
417
+ for scale in scales:
418
+ raw = scale.view(torch.uint8)
419
+ section[cursor : cursor + raw.numel()].copy_(raw)
420
+ cursor += raw.numel()
421
+ if cursor != SHARED_SCALE_BYTES:
422
+ raise AssertionError("shared scale byte accounting drifted")
423
+ return section
424
+
425
+
426
+ def unpack_qsrt_shared_scale_section(
427
+ payload: torch.Tensor,
428
+ ) -> tuple[torch.Tensor, torch.Tensor, torch.Tensor]:
429
+ if payload.dtype != torch.uint8:
430
+ raise TypeError("shared scale section must use torch.uint8")
431
+ if payload.ndim != 1 or payload.numel() != SHARED_SCALE_SECTION_BYTES:
432
+ raise ValueError(
433
+ "shared scale section must contain exactly "
434
+ f"{SHARED_SCALE_SECTION_BYTES} bytes"
435
+ )
436
+ if bool(torch.any(payload[SHARED_SCALE_BYTES:] != 0)):
437
+ raise ValueError("shared scale section has nonzero alignment padding")
438
+ values = []
439
+ cursor = 0
440
+ vector_bytes = LATENT_CHANNELS * SCALE_BYTES
441
+ for name in SHARED_SCALE_ORDER:
442
+ vector = (
443
+ payload[cursor : cursor + vector_bytes]
444
+ .clone()
445
+ .view(torch.float16)
446
+ .contiguous()
447
+ )
448
+ _validate_scale_vector(vector, LATENT_CHANNELS, name)
449
+ values.append(vector)
450
+ cursor += vector_bytes
451
+ return tuple(values) # type: ignore[return-value]
452
+
453
+
454
+ def resolve_mode(mode: ModeSpec | str | int) -> ModeSpec:
455
+ if isinstance(mode, ModeSpec):
456
+ return mode
457
+ if isinstance(mode, str):
458
+ try:
459
+ return _MODES_BY_NAME[mode.upper()]
460
+ except KeyError as exc:
461
+ raise ValueError(f"unknown QSRT mode: {mode}") from exc
462
+ if isinstance(mode, int) and not isinstance(mode, bool):
463
+ try:
464
+ return _MODES_BY_ID[mode]
465
+ except KeyError as exc:
466
+ raise ValueError(f"unknown QSRT mode ID: {mode}") from exc
467
+ raise TypeError("mode must be a ModeSpec, name, or integer ID")
468
+
469
+
470
+ def matrix_rate_axis(matrix: str) -> RateAxis:
471
+ try:
472
+ return MATRIX_RATE_AXIS[matrix]
473
+ except KeyError as exc:
474
+ raise ValueError(f"unknown expert matrix: {matrix}") from exc
475
+
476
+
477
+ def record_contexts(mode: ModeSpec | str | int) -> tuple[int, ...]:
478
+ """Return physical record contexts, paired low/high then moving inward."""
479
+
480
+ spec = resolve_mode(mode)
481
+ contexts: list[int] = []
482
+ for low_context in range(spec.context_count // 2):
483
+ high_context = spec.context_count - 1 - low_context
484
+ for _ in range(spec.records_per_context):
485
+ contexts.extend((low_context, high_context))
486
+ if len(contexts) != RECORDS_PER_EXPERT:
487
+ raise AssertionError("mode construction did not cover 24 records")
488
+ return tuple(contexts)
489
+
490
+
491
+ def record_bits(mode: ModeSpec | str | int) -> tuple[int, ...]:
492
+ spec = resolve_mode(mode)
493
+ return tuple(spec.context_bits[context] for context in record_contexts(spec))
494
+
495
+
496
+ def pair_bits(mode: ModeSpec | str | int) -> tuple[tuple[int, int], ...]:
497
+ records = record_bits(mode)
498
+ pairs = tuple(zip(records[0::2], records[1::2], strict=True))
499
+ if len(pairs) != PAIRS_PER_EXPERT or any(sum(pair) != 6 for pair in pairs):
500
+ raise ValueError("every QSRT record pair must have a six-bit rate sum")
501
+ return pairs
502
+
503
+
504
+ def pair_kinds(mode: ModeSpec | str | int) -> tuple[PairKind, ...]:
505
+ kinds: list[PairKind] = []
506
+ for pair in pair_bits(mode):
507
+ if pair == (2, 4):
508
+ kinds.append("P24")
509
+ elif pair == (3, 3):
510
+ kinds.append("P33")
511
+ else:
512
+ raise ValueError(f"unsupported QSRT pair schedule: {pair}")
513
+ return tuple(kinds)
514
+
515
+
516
+ def _validate_block_contexts(
517
+ block_contexts: torch.Tensor, mode: ModeSpec
518
+ ) -> None:
519
+ expected_groups = INTERMEDIATE_CHANNELS // CONTEXT_GROUP_CHANNELS
520
+ if block_contexts.ndim != 1 or block_contexts.numel() != expected_groups:
521
+ raise ValueError(
522
+ f"block_contexts must contain {expected_groups} four-channel groups"
523
+ )
524
+ if block_contexts.dtype == torch.bool or block_contexts.is_floating_point():
525
+ raise TypeError("block_contexts must use an integer dtype")
526
+ if block_contexts.numel() == 0:
527
+ raise ValueError("block_contexts must not be empty")
528
+ if int(block_contexts.min()) < 0 or int(block_contexts.max()) >= mode.context_count:
529
+ raise ValueError("block_contexts contains an out-of-range context ID")
530
+ counts = torch.bincount(
531
+ block_contexts.to(dtype=torch.long), minlength=mode.context_count
532
+ )
533
+ expected = expected_groups // mode.context_count
534
+ if counts.tolist() != [expected] * mode.context_count:
535
+ raise ValueError("every context must have equal population")
536
+
537
+
538
+ def importance_group_order(
539
+ block_contexts: torch.Tensor, mode: ModeSpec | str | int
540
+ ) -> torch.Tensor:
541
+ """Return stable low-to-high context order for the LDLQ recursion."""
542
+
543
+ spec = resolve_mode(mode)
544
+ _validate_block_contexts(block_contexts, spec)
545
+ return torch.argsort(block_contexts, stable=True)
546
+
547
+
548
+ def storage_group_order(
549
+ block_contexts: torch.Tensor, mode: ModeSpec | str | int
550
+ ) -> torch.Tensor:
551
+ """Return the physical group order forming canonical P24/P33 pairs."""
552
+
553
+ spec = resolve_mode(mode)
554
+ _validate_block_contexts(block_contexts, spec)
555
+ groups_per_record = RECORD_CHANNELS // CONTEXT_GROUP_CHANNELS
556
+ by_context = []
557
+ for context in range(spec.context_count):
558
+ indices = torch.nonzero(block_contexts == context).flatten()
559
+ by_context.append(indices.reshape(-1, groups_per_record))
560
+
561
+ chunks = []
562
+ for low_context in range(spec.context_count // 2):
563
+ high_context = spec.context_count - 1 - low_context
564
+ low_records = by_context[low_context]
565
+ high_records = by_context[high_context]
566
+ if low_records.shape != high_records.shape:
567
+ raise ValueError("paired contexts have different record populations")
568
+ for record in range(low_records.shape[0]):
569
+ chunks.extend((low_records[record], high_records[record]))
570
+ return torch.cat(chunks)
571
+
572
+
573
+ def rate_transfer_record_order(
574
+ donor_records: Sequence[int],
575
+ recipient_records: Sequence[int],
576
+ *,
577
+ middle_records: Sequence[int] | None = None,
578
+ ) -> tuple[int, ...]:
579
+ """Build a low-to-high record order for an arbitrary equal-rate exchange.
580
+
581
+ Record IDs refer to an existing 24-record partition, usually the
582
+ activation-ranked partition produced by calibration. Donors occupy the
583
+ K2 end of an ``R_r`` schedule and recipients occupy the K4 end. The
584
+ recipient suffix is reversed so ``donor_records[i]`` and
585
+ ``recipient_records[i]`` become one physical P24 pair after the canonical
586
+ balanced-atom repack.
587
+
588
+ This order can be baked into the common w1/w3-row and w2-column
589
+ permutation. Therefore an arbitrary *shared* donor/recipient map does
590
+ not require a serving-time per-record map or a different payload format;
591
+ only the offline selector changes.
592
+ """
593
+
594
+ donors = tuple(donor_records)
595
+ recipients = tuple(recipient_records)
596
+ if len(donors) != len(recipients):
597
+ raise ValueError("donor and recipient record counts must match")
598
+ if len(donors) > PAIRS_PER_EXPERT:
599
+ raise ValueError(f"at most {PAIRS_PER_EXPERT} rate exchanges are allowed")
600
+
601
+ selected = donors + recipients
602
+ if any(
603
+ isinstance(record, bool)
604
+ or not isinstance(record, int)
605
+ or not 0 <= record < RECORDS_PER_EXPERT
606
+ for record in selected
607
+ ):
608
+ raise ValueError(
609
+ f"record IDs must be integers in 0..{RECORDS_PER_EXPERT - 1}"
610
+ )
611
+ if len(set(selected)) != len(selected):
612
+ raise ValueError("donor and recipient records must be unique and disjoint")
613
+
614
+ remaining = tuple(
615
+ record for record in range(RECORDS_PER_EXPERT) if record not in set(selected)
616
+ )
617
+ if middle_records is None:
618
+ middle = remaining
619
+ else:
620
+ middle = tuple(middle_records)
621
+ if len(middle) != len(remaining) or set(middle) != set(remaining):
622
+ raise ValueError(
623
+ "middle_records must be a permutation of all unselected records"
624
+ )
625
+ return donors + middle + tuple(reversed(recipients))
626
+
627
+
628
+ def relabel_block_contexts_for_record_order(
629
+ block_contexts: torch.Tensor,
630
+ record_order: Sequence[int],
631
+ ) -> torch.Tensor:
632
+ """Relabel a 24-record partition to follow ``record_order``.
633
+
634
+ ``record_order[new_record]`` is the old record ID. Sorting the returned
635
+ labels with :func:`importance_group_order` yields the requested record
636
+ order while preserving every complete 128-channel record.
637
+ """
638
+
639
+ _validate_block_contexts(block_contexts, R0)
640
+ order = tuple(record_order)
641
+ if len(order) != RECORDS_PER_EXPERT:
642
+ raise ValueError(f"record_order must contain {RECORDS_PER_EXPERT} records")
643
+ if any(
644
+ isinstance(record, bool)
645
+ or not isinstance(record, int)
646
+ or not 0 <= record < RECORDS_PER_EXPERT
647
+ for record in order
648
+ ) or len(set(order)) != RECORDS_PER_EXPERT:
649
+ raise ValueError("record_order must be a permutation of all record IDs")
650
+ inverse = torch.empty(
651
+ RECORDS_PER_EXPERT, dtype=torch.long, device=block_contexts.device
652
+ )
653
+ inverse[torch.tensor(order, dtype=torch.long, device=block_contexts.device)] = (
654
+ torch.arange(RECORDS_PER_EXPERT, device=block_contexts.device)
655
+ )
656
+ return inverse[block_contexts.to(dtype=torch.long)]
657
+
658
+
659
+ def expand_group_order(group_order: torch.Tensor) -> torch.Tensor:
660
+ """Expand four-channel group IDs into a new-index -> old-index permutation."""
661
+
662
+ expected_groups = INTERMEDIATE_CHANNELS // CONTEXT_GROUP_CHANNELS
663
+ if group_order.ndim != 1 or group_order.numel() != expected_groups:
664
+ raise ValueError(f"group_order must contain {expected_groups} groups")
665
+ _validate_permutation(group_order, expected_groups, "group_order")
666
+ offsets = torch.arange(CONTEXT_GROUP_CHANNELS, device=group_order.device)
667
+ return (
668
+ group_order.to(dtype=torch.long)[:, None] * CONTEXT_GROUP_CHANNELS
669
+ + offsets[None]
670
+ ).flatten()
671
+
672
+
673
+ def _validate_permutation(
674
+ permutation: torch.Tensor, length: int, name: str = "permutation"
675
+ ) -> None:
676
+ if permutation.ndim != 1 or permutation.numel() != length:
677
+ raise ValueError(f"{name} must contain exactly {length} entries")
678
+ if permutation.dtype == torch.bool or permutation.is_floating_point():
679
+ raise TypeError(f"{name} must use an integer dtype")
680
+ values = permutation.to(dtype=torch.long)
681
+ expected = torch.arange(length, device=values.device)
682
+ if not torch.equal(torch.sort(values).values, expected):
683
+ raise ValueError(f"{name} must be a bijection over 0..{length - 1}")
684
+
685
+
686
+ def invert_permutation(permutation: torch.Tensor) -> torch.Tensor:
687
+ _validate_permutation(permutation, permutation.numel())
688
+ return torch.argsort(permutation.to(dtype=torch.long))
689
+
690
+
691
+ def coupled_intermediate_permutation(
692
+ w1: torch.Tensor,
693
+ w3: torch.Tensor,
694
+ w2: torch.Tensor,
695
+ permutation: torch.Tensor,
696
+ ) -> tuple[torch.Tensor, torch.Tensor, torch.Tensor]:
697
+ """Apply one exact SiTU-neuron permutation to ordinary weight matrices.
698
+
699
+ ``permutation[new_channel]`` is the corresponding old channel. The
700
+ returned matrices satisfy ``w1' = w1[P]``, ``w3' = w3[P]``, and
701
+ ``w2' = w2[:, P]``.
702
+ """
703
+
704
+ if w1.ndim != 2 or w3.ndim != 2 or w2.ndim != 2:
705
+ raise ValueError("expert weights must all be two-dimensional")
706
+ if w1.shape != w3.shape:
707
+ raise ValueError("w1 and w3 must have identical shapes")
708
+ intermediate, hidden = w1.shape
709
+ if tuple(w2.shape) != (hidden, intermediate):
710
+ raise ValueError("w2 must have shape [hidden, intermediate]")
711
+ _validate_permutation(permutation, intermediate)
712
+ row_index = permutation.to(device=w1.device, dtype=torch.long)
713
+ w3_index = permutation.to(device=w3.device, dtype=torch.long)
714
+ column_index = permutation.to(device=w2.device, dtype=torch.long)
715
+ return (
716
+ w1.index_select(0, row_index).contiguous(),
717
+ w3.index_select(0, w3_index).contiguous(),
718
+ w2.index_select(1, column_index).contiguous(),
719
+ )
720
+
721
+
722
+ def record_repack_order(
723
+ source_group_order: torch.Tensor, destination_group_order: torch.Tensor
724
+ ) -> torch.Tensor:
725
+ """Map destination records to source records without splitting a record."""
726
+
727
+ expected_groups = INTERMEDIATE_CHANNELS // CONTEXT_GROUP_CHANNELS
728
+ _validate_permutation(source_group_order, expected_groups, "source_group_order")
729
+ _validate_permutation(
730
+ destination_group_order, expected_groups, "destination_group_order"
731
+ )
732
+ groups_per_record = RECORD_CHANNELS // CONTEXT_GROUP_CHANNELS
733
+ source_records = source_group_order.cpu().reshape(-1, groups_per_record)
734
+ destination_records = destination_group_order.cpu().reshape(-1, groups_per_record)
735
+ source_lookup = {
736
+ tuple(record.tolist()): index for index, record in enumerate(source_records)
737
+ }
738
+ if len(source_lookup) != RECORDS_PER_EXPERT:
739
+ raise ValueError("source order contains duplicate or malformed records")
740
+ try:
741
+ order = [
742
+ source_lookup[tuple(record.tolist())]
743
+ for record in destination_records
744
+ ]
745
+ except KeyError as exc:
746
+ raise ValueError("destination order splits or changes a source record") from exc
747
+ return torch.tensor(order, dtype=torch.long, device=source_group_order.device)
748
+
749
+
750
+ def expand_record_order(record_order: torch.Tensor) -> torch.Tensor:
751
+ """Expand destination-record -> source-record mapping to channel indices."""
752
+
753
+ _validate_permutation(record_order, RECORDS_PER_EXPERT, "record_order")
754
+ offsets = torch.arange(RECORD_CHANNELS, device=record_order.device)
755
+ return (
756
+ record_order.to(dtype=torch.long)[:, None] * RECORD_CHANNELS + offsets[None]
757
+ ).flatten()
758
+
759
+
760
+ def repack_rate_axis(
761
+ tensor: torch.Tensor, record_order: torch.Tensor, axis: int
762
+ ) -> torch.Tensor:
763
+ """Move complete 128-channel blocks on a tensor's logical rate axis."""
764
+
765
+ if tensor.ndim == 0:
766
+ raise ValueError("cannot repack a scalar tensor")
767
+ normalized_axis = axis % tensor.ndim
768
+ if tensor.shape[normalized_axis] != INTERMEDIATE_CHANNELS:
769
+ raise ValueError("rate axis must contain exactly 3072 channels")
770
+ channels = expand_record_order(record_order).to(device=tensor.device)
771
+ return tensor.index_select(normalized_axis, channels).contiguous()
772
+
773
+
774
+ def repack_encoded_records(
775
+ encoded: torch.Tensor, record_order: torch.Tensor, rate_axis: RateAxis
776
+ ) -> torch.Tensor:
777
+ """Reorder complete 128-channel records in ``[K/16, N/16, 256]`` states."""
778
+
779
+ _validate_encoded_shape(encoded, rate_axis)
780
+ _validate_permutation(record_order, RECORDS_PER_EXPERT, "record_order")
781
+ order = record_order.to(device=encoded.device, dtype=torch.long)
782
+ if rate_axis == "k":
783
+ records = encoded.reshape(
784
+ RECORDS_PER_EXPERT,
785
+ TILES_PER_RECORD_AXIS,
786
+ encoded.shape[1],
787
+ TILE_VALUES,
788
+ )
789
+ return records.index_select(0, order).reshape_as(encoded).contiguous()
790
+ records = (
791
+ encoded.reshape(
792
+ encoded.shape[0],
793
+ RECORDS_PER_EXPERT,
794
+ TILES_PER_RECORD_AXIS,
795
+ TILE_VALUES,
796
+ )
797
+ .permute(1, 0, 2, 3)
798
+ .contiguous()
799
+ )
800
+ reordered = records.index_select(0, order)
801
+ return (
802
+ reordered.permute(1, 0, 2, 3).contiguous().reshape_as(encoded).contiguous()
803
+ )
804
+
805
+
806
+ def _validate_k(bits: int) -> None:
807
+ if isinstance(bits, bool) or not isinstance(bits, int) or bits not in range(2, 7):
808
+ raise ValueError("SQG trellis packing supports K=2 through K=6")
809
+
810
+
811
+ def pack_trellis_edges(indices: torch.Tensor, bits: int) -> torch.Tensor:
812
+ """Pack low K bits with the native EXL ``pack_trellis`` word ordering."""
813
+
814
+ _validate_k(bits)
815
+ if indices.ndim < 1 or indices.shape[-1] != TILE_VALUES:
816
+ raise ValueError("indices must have a final dimension of 256")
817
+ if indices.dtype == torch.bool or indices.is_floating_point():
818
+ raise TypeError("indices must use an integer dtype")
819
+ values = indices.to(dtype=torch.int64) & ((1 << bits) - 1)
820
+ spans = values.reshape(*values.shape[:-1], TILE_CHANNELS, TILE_CHANNELS)
821
+ symbol_shifts = torch.arange(bits - 1, -1, -1, device=values.device)
822
+ bitstream = ((spans[..., None] >> symbol_shifts) & 1).reshape(
823
+ *values.shape[:-1], TILE_CHANNELS, bits * TILE_CHANNELS
824
+ )
825
+ word_shifts = torch.arange(15, -1, -1, device=values.device)
826
+ words = (
827
+ bitstream.reshape(*values.shape[:-1], TILE_CHANNELS, bits, 16)
828
+ << word_shifts
829
+ ).sum(dim=-1)
830
+ flat = words.reshape(*values.shape[:-1], TILE_CHANNELS * bits)
831
+ # Native pack.cu applies SWAP16: adjacent uint16 words exchange places.
832
+ swapped = flat.reshape(*flat.shape[:-1], -1, 2).flip(-1).reshape(flat.shape)
833
+ return swapped.to(dtype=torch.int16).contiguous()
834
+
835
+
836
+ def unpack_trellis_edges(packed: torch.Tensor, bits: int) -> torch.Tensor:
837
+ """Invert :func:`pack_trellis_edges` to the stored K-bit edge symbols."""
838
+
839
+ _validate_k(bits)
840
+ expected_words = TILE_CHANNELS * bits
841
+ if packed.ndim < 1 or packed.shape[-1] != expected_words:
842
+ raise ValueError(f"packed tiles must end in {expected_words} int16 words")
843
+ if packed.dtype != torch.int16:
844
+ raise TypeError("packed trellis words must use torch.int16")
845
+ words = packed.to(dtype=torch.int64) & 0xFFFF
846
+ words = words.reshape(*words.shape[:-1], -1, 2).flip(-1).reshape(words.shape)
847
+ words = words.reshape(*words.shape[:-1], TILE_CHANNELS, bits)
848
+ word_shifts = torch.arange(15, -1, -1, device=words.device)
849
+ bitstream = ((words[..., None] >> word_shifts) & 1).reshape(
850
+ *words.shape[:-2], TILE_CHANNELS, bits * TILE_CHANNELS
851
+ )
852
+ symbol_bits = bitstream.reshape(
853
+ *words.shape[:-2], TILE_CHANNELS, TILE_CHANNELS, bits
854
+ )
855
+ symbol_shifts = torch.arange(bits - 1, -1, -1, device=words.device)
856
+ values = (symbol_bits << symbol_shifts).sum(dim=-1)
857
+ return values.reshape(*words.shape[:-2], TILE_VALUES).to(torch.int16).contiguous()
858
+
859
+
860
+ def unpack_trellis_states(packed: torch.Tensor, bits: int) -> torch.Tensor:
861
+ """Unpack native edge words and reconstruct every cyclic 16-bit state."""
862
+
863
+ return reconstruct_trellis_states(unpack_trellis_edges(packed, bits), bits)
864
+
865
+
866
+ @dataclass(frozen=True)
867
+ class QSRTTrellisDescriptor:
868
+ """TP-independent description of one complete packed expert matrix."""
869
+
870
+ mode_id: int
871
+ rate_axis: RateAxis
872
+ k_tiles: int
873
+ n_tiles: int
874
+ schema: str = SCHEMA
875
+ intermediate_channels: int = INTERMEDIATE_CHANNELS
876
+ record_channels: int = RECORD_CHANNELS
877
+
878
+ def __post_init__(self) -> None:
879
+ # Candidate payloads are allocation-independent and stay in logical
880
+ # pair order. Physical ownership is applied only by the atom sharder.
881
+ if self.schema not in LOGICAL_CANDIDATE_SCHEMAS:
882
+ raise ValueError(f"unsupported QSRT schema: {self.schema}")
883
+ if self.intermediate_channels != INTERMEDIATE_CHANNELS:
884
+ raise ValueError("Kimi-K3 QSRT requires a 3072-channel intermediate axis")
885
+ if self.record_channels != RECORD_CHANNELS:
886
+ raise ValueError("Kimi-K3 QSRT requires 128-channel records")
887
+ resolve_mode(self.mode_id)
888
+ if self.rate_axis not in ("k", "n"):
889
+ raise ValueError("rate_axis must be 'k' or 'n'")
890
+ if self.k_tiles <= 0 or self.n_tiles <= 0:
891
+ raise ValueError("tile dimensions must be positive")
892
+ rate_tiles = self.k_tiles if self.rate_axis == "k" else self.n_tiles
893
+ if rate_tiles * TILE_CHANNELS != INTERMEDIATE_CHANNELS:
894
+ raise ValueError("rate axis must contain exactly 3072 channels")
895
+ orthogonal_tiles = self.n_tiles if self.rate_axis == "k" else self.k_tiles
896
+ if orthogonal_tiles * TILE_CHANNELS != LATENT_CHANNELS:
897
+ raise ValueError("orthogonal axis must contain exactly 3584 channels")
898
+
899
+ @property
900
+ def mode(self) -> ModeSpec:
901
+ return resolve_mode(self.mode_id)
902
+
903
+ @property
904
+ def orthogonal_tiles(self) -> int:
905
+ return self.n_tiles if self.rate_axis == "k" else self.k_tiles
906
+
907
+ @property
908
+ def tiles_per_record(self) -> int:
909
+ return TILES_PER_RECORD_AXIS * self.orthogonal_tiles
910
+
911
+ @property
912
+ def words_per_pair(self) -> int:
913
+ return self.tiles_per_record * TILE_CHANNELS * 6
914
+
915
+ @property
916
+ def payload_words(self) -> int:
917
+ return PAIRS_PER_EXPERT * self.words_per_pair
918
+
919
+ @property
920
+ def payload_bytes(self) -> int:
921
+ return self.payload_words * torch.int16.itemsize
922
+
923
+ @property
924
+ def weight_count(self) -> int:
925
+ return self.k_tiles * self.n_tiles * TILE_VALUES
926
+
927
+ def to_manifest(self) -> dict[str, object]:
928
+ return {
929
+ "schema": self.schema,
930
+ "mode_id": self.mode_id,
931
+ "mode": self.mode.name,
932
+ "rate_axis": self.rate_axis,
933
+ "k_tiles": self.k_tiles,
934
+ "n_tiles": self.n_tiles,
935
+ "intermediate_channels": self.intermediate_channels,
936
+ "record_channels": self.record_channels,
937
+ "pair_channels": PAIR_CHANNELS,
938
+ "record_bits": list(record_bits(self.mode)),
939
+ "pair_kinds": list(pair_kinds(self.mode)),
940
+ "words_per_pair": self.words_per_pair,
941
+ "payload_words": self.payload_words,
942
+ "payload_bytes": self.payload_bytes,
943
+ }
944
+
945
+
946
+ @dataclass(frozen=True)
947
+ class PackedQSRTTrellis:
948
+ descriptor: QSRTTrellisDescriptor
949
+ payload: torch.Tensor
950
+
951
+ def validate(self) -> None:
952
+ if self.payload.dtype != torch.int16:
953
+ raise TypeError("QSRT trellis payload must use torch.int16")
954
+ if self.payload.ndim != 1:
955
+ raise ValueError("QSRT trellis payload must be one-dimensional")
956
+ if self.payload.numel() != self.descriptor.payload_words:
957
+ raise ValueError(
958
+ "QSRT trellis payload length does not match its descriptor"
959
+ )
960
+
961
+
962
+ def _validate_encoded_shape(encoded: torch.Tensor, rate_axis: RateAxis) -> None:
963
+ if encoded.ndim != 3 or encoded.shape[-1] != TILE_VALUES:
964
+ raise ValueError("encoded states must have shape [K/16, N/16, 256]")
965
+ if encoded.dtype == torch.bool or encoded.is_floating_point():
966
+ raise TypeError("encoded states must use an integer dtype")
967
+ if rate_axis not in ("k", "n"):
968
+ raise ValueError("rate_axis must be 'k' or 'n'")
969
+ rate_tiles = encoded.shape[0] if rate_axis == "k" else encoded.shape[1]
970
+ if rate_tiles * TILE_CHANNELS != INTERMEDIATE_CHANNELS:
971
+ raise ValueError("encoded rate axis must contain exactly 3072 channels")
972
+
973
+
974
+ def _record_tiles(
975
+ encoded: torch.Tensor, record: int, rate_axis: RateAxis
976
+ ) -> torch.Tensor:
977
+ begin = record * TILES_PER_RECORD_AXIS
978
+ if rate_axis == "k":
979
+ return encoded.narrow(0, begin, TILES_PER_RECORD_AXIS).reshape(-1, TILE_VALUES)
980
+ return encoded.narrow(1, begin, TILES_PER_RECORD_AXIS).reshape(-1, TILE_VALUES)
981
+
982
+
983
+ def pack_qsrt_trellis(
984
+ encoded: torch.Tensor,
985
+ mode: ModeSpec | str | int,
986
+ *,
987
+ rate_axis: RateAxis,
988
+ schema: str = SCHEMA,
989
+ validate_states: bool = True,
990
+ ) -> PackedQSRTTrellis:
991
+ """Pack a complete matrix into fixed-size balanced record pairs."""
992
+
993
+ _validate_encoded_shape(encoded, rate_axis)
994
+ spec = resolve_mode(mode)
995
+ descriptor = QSRTTrellisDescriptor(
996
+ mode_id=spec.mode_id,
997
+ rate_axis=rate_axis,
998
+ k_tiles=encoded.shape[0],
999
+ n_tiles=encoded.shape[1],
1000
+ schema=schema,
1001
+ )
1002
+ pieces = []
1003
+ for record, bits in enumerate(record_bits(spec)):
1004
+ record_states = _record_tiles(encoded, record, rate_axis)
1005
+ record_payload = pack_trellis_edges(record_states, bits)
1006
+ if validate_states and not torch.equal(
1007
+ unpack_trellis_states(record_payload, bits), record_states.to(torch.int16)
1008
+ ):
1009
+ raise ValueError("encoded input is not a closed cyclic trellis path")
1010
+ pieces.append(record_payload)
1011
+ payload = torch.cat([piece.reshape(-1) for piece in pieces]).contiguous()
1012
+ packed = PackedQSRTTrellis(descriptor, payload)
1013
+ packed.validate()
1014
+ return packed
1015
+
1016
+
1017
+ def unpack_qsrt_trellis_edges(packed: PackedQSRTTrellis) -> torch.Tensor:
1018
+ """Unpack a complete QSRT payload to physical-order K-bit edge symbols."""
1019
+
1020
+ packed.validate()
1021
+ descriptor = packed.descriptor
1022
+ output = torch.empty(
1023
+ (descriptor.k_tiles, descriptor.n_tiles, TILE_VALUES),
1024
+ dtype=torch.int16,
1025
+ device=packed.payload.device,
1026
+ )
1027
+ cursor = 0
1028
+ for record, bits in enumerate(record_bits(descriptor.mode)):
1029
+ word_count = descriptor.tiles_per_record * TILE_CHANNELS * bits
1030
+ words = packed.payload.narrow(0, cursor, word_count).reshape(
1031
+ descriptor.tiles_per_record, TILE_CHANNELS * bits
1032
+ )
1033
+ tiles = unpack_trellis_edges(words, bits)
1034
+ begin = record * TILES_PER_RECORD_AXIS
1035
+ if descriptor.rate_axis == "k":
1036
+ output.narrow(0, begin, TILES_PER_RECORD_AXIS).copy_(
1037
+ tiles.reshape(
1038
+ TILES_PER_RECORD_AXIS, descriptor.n_tiles, TILE_VALUES
1039
+ )
1040
+ )
1041
+ else:
1042
+ output.narrow(1, begin, TILES_PER_RECORD_AXIS).copy_(
1043
+ tiles.reshape(
1044
+ descriptor.k_tiles, TILES_PER_RECORD_AXIS, TILE_VALUES
1045
+ )
1046
+ )
1047
+ cursor += word_count
1048
+ if cursor != packed.payload.numel():
1049
+ raise ValueError("QSRT trellis payload has trailing data")
1050
+ return output
1051
+
1052
+
1053
+ def unpack_qsrt_trellis_states(packed: PackedQSRTTrellis) -> torch.Tensor:
1054
+ """Unpack a complete QSRT payload to its physical-order 16-bit states."""
1055
+
1056
+ edges = unpack_qsrt_trellis_edges(packed)
1057
+ descriptor = packed.descriptor
1058
+ output = torch.empty_like(edges)
1059
+ rates = record_bits(descriptor.mode)
1060
+ # The recurrence is elementwise over every dimension except the trailing
1061
+ # 256-symbol path. Group equal-K records so each matrix performs at most
1062
+ # three Python-level recurrences instead of one per 128-channel record.
1063
+ for bits in sorted(set(rates)):
1064
+ records = [
1065
+ record for record, record_bits_value in enumerate(rates)
1066
+ if record_bits_value == bits
1067
+ ]
1068
+ if descriptor.rate_axis == "k":
1069
+ grouped_edges = torch.stack(
1070
+ [
1071
+ edges.narrow(
1072
+ 0,
1073
+ record * TILES_PER_RECORD_AXIS,
1074
+ TILES_PER_RECORD_AXIS,
1075
+ )
1076
+ for record in records
1077
+ ]
1078
+ )
1079
+ grouped_states = reconstruct_trellis_states(grouped_edges, bits)
1080
+ for index, record in enumerate(records):
1081
+ output.narrow(
1082
+ 0,
1083
+ record * TILES_PER_RECORD_AXIS,
1084
+ TILES_PER_RECORD_AXIS,
1085
+ ).copy_(grouped_states[index])
1086
+ else:
1087
+ grouped_edges = torch.stack(
1088
+ [
1089
+ edges.narrow(
1090
+ 1,
1091
+ record * TILES_PER_RECORD_AXIS,
1092
+ TILES_PER_RECORD_AXIS,
1093
+ )
1094
+ for record in records
1095
+ ]
1096
+ )
1097
+ grouped_states = reconstruct_trellis_states(grouped_edges, bits)
1098
+ for index, record in enumerate(records):
1099
+ output.narrow(
1100
+ 1,
1101
+ record * TILES_PER_RECORD_AXIS,
1102
+ TILES_PER_RECORD_AXIS,
1103
+ ).copy_(grouped_states[index])
1104
+ return output
1105
+
1106
+
1107
+ def decode_qsrt_exl3_weight(
1108
+ packed: PackedQSRTTrellis,
1109
+ suh: torch.Tensor,
1110
+ svh: torch.Tensor,
1111
+ *,
1112
+ codebook: str = CODEBOOK_SQG_XOR_CHEB_T12,
1113
+ ) -> torch.Tensor:
1114
+ """Decode a complete QSRT payload to its physical EXL-oriented weight."""
1115
+
1116
+ packed.validate()
1117
+ _validate_scale_vector(
1118
+ suh,
1119
+ packed.descriptor.k_tiles * TILE_CHANNELS,
1120
+ "suh",
1121
+ packed.payload.device,
1122
+ )
1123
+ _validate_scale_vector(
1124
+ svh,
1125
+ packed.descriptor.n_tiles * TILE_CHANNELS,
1126
+ "svh",
1127
+ packed.payload.device,
1128
+ )
1129
+ tile_bits = tuple(
1130
+ bits
1131
+ for rate in record_bits(packed.descriptor.mode)
1132
+ for bits in (rate,) * TILES_PER_RECORD_AXIS
1133
+ )
1134
+ return decode_qsrt_weight(
1135
+ unpack_qsrt_trellis_states(packed),
1136
+ suh,
1137
+ svh,
1138
+ rate_axis=packed.descriptor.rate_axis,
1139
+ tile_bits=tile_bits,
1140
+ codebook=codebook,
1141
+ )
reproduction/closure/patches/kquant/changed-files/kquant/sqg_e4m3.py ADDED
@@ -0,0 +1,438 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """QSRT and research-control SQG E4M3 reconstruction tables.
2
+
3
+ This module implements the independently proposed L16 SQG labelling. It
4
+ deliberately separates the rolling trellis graph from its numerical labels:
5
+ the encoder still stores K branch bits per coefficient, while a deterministic
6
+ K-specific mapping turns each 16-bit transition state into an E4M3 value.
7
+
8
+ The primary ``sqg_xor_cheb_t12`` codebook composes the carry-mixed bijective SQG rank
9
+ map with a modal 12-bit compression of the Chebyshev-derived finite-E4M3
10
+ staircase. The older exact-graph and R44 mappings remain explicit research
11
+ controls. All paths return raw E4M3 bytes so the offline encoder and serving
12
+ kernel can share one byte-exact numerical contract.
13
+ """
14
+
15
+ from __future__ import annotations
16
+
17
+ from functools import lru_cache
18
+
19
+ import torch
20
+
21
+
22
+ SQG_NORMAL_E4M3 = "sqg-normal-e4m3"
23
+ SQG_CHEB_NORMAL_E4M3 = "sqg-cheb-normal-e4m3"
24
+ SQG_CHEB = "sqg_cheb"
25
+ SQG_XOR_CHEB_T12 = "sqg_xor_cheb_t12"
26
+
27
+ _TRANSITIONS = 1 << 16
28
+ _CLIP = 1.0 / 2048.0
29
+ _P = (1.25667142, 2.87422731, -9.02398882, 5.36810336, -0.46703015)
30
+ _Q = (1.0, 2.07630930, -8.08332684, 6.32135736, -1.31208298)
31
+
32
+
33
+ def _validate(bits: int, mode: str) -> None:
34
+ if isinstance(bits, bool) or not isinstance(bits, int) or bits not in range(2, 7):
35
+ raise ValueError("SQG supports integer K2 through K6")
36
+ if mode != "normal":
37
+ raise ValueError("the supported R44 mode is 'normal'")
38
+
39
+
40
+ def _mix_width(
41
+ values: torch.Tensor,
42
+ *,
43
+ width: int,
44
+ multiplier_a: int,
45
+ multiplier_b: int,
46
+ shift_a: int,
47
+ shift_b: int,
48
+ shift_c: int,
49
+ ) -> torch.Tensor:
50
+ """Apply the report's bijective XOR/multiply mixer modulo ``2**width``."""
51
+
52
+ mask = (1 << width) - 1
53
+ result = values & mask
54
+ for multiplier, shift in (
55
+ (multiplier_a | 1, shift_a),
56
+ (multiplier_b | 1, shift_b),
57
+ ):
58
+ result ^= result >> min(max(shift, 1), width - 1)
59
+ result = (result * multiplier) & mask
60
+ result ^= result >> min(max(shift_c, 1), width - 1)
61
+ return result & mask
62
+
63
+
64
+ def _reverse_low_bits(values: torch.Tensor, bits: int) -> torch.Tensor:
65
+ result = torch.zeros_like(values)
66
+ for index in range(bits):
67
+ result |= ((values >> index) & 1) << (bits - 1 - index)
68
+ return result
69
+
70
+
71
+ def _r44_inverse_normal(probability: torch.Tensor) -> torch.Tensor:
72
+ a = 2.0 * probability - 1.0
73
+ x = a.square()
74
+ numerator = torch.full_like(x, _P[-1])
75
+ denominator = torch.full_like(x, _Q[-1])
76
+ for coefficient in reversed(_P[:-1]):
77
+ numerator = numerator * x + coefficient
78
+ for coefficient in reversed(_Q[:-1]):
79
+ denominator = denominator * x + coefficient
80
+ return a * numerator / denominator
81
+
82
+
83
+ @lru_cache(maxsize=None)
84
+ def _sqg_cpu_bytes(bits: int, mode: str) -> torch.Tensor:
85
+ _validate(bits, mode)
86
+ width = 16 - bits
87
+ branches = 1 << bits
88
+ states = torch.arange(_TRANSITIONS, dtype=torch.int64)
89
+ history = states >> bits
90
+ branch = states & (branches - 1)
91
+
92
+ phase = _mix_width(
93
+ history,
94
+ width=width,
95
+ multiplier_a=0x65AF,
96
+ multiplier_b=0x16BF,
97
+ shift_a=6,
98
+ shift_b=4,
99
+ shift_c=5,
100
+ )
101
+ syndrome_hash = _mix_width(
102
+ history ^ 0x5105,
103
+ width=width,
104
+ multiplier_a=0x8693,
105
+ multiplier_b=0x2A21,
106
+ shift_a=2,
107
+ shift_b=4,
108
+ shift_c=4,
109
+ )
110
+ syndrome = syndrome_hash & (branches - 1)
111
+ stratum = (
112
+ 7 * (_reverse_low_bits(branch, bits) ^ syndrome)
113
+ ) & (branches - 1)
114
+ rank = (stratum << width) | phase
115
+ probability = ((rank.double() + 0.5) / _TRANSITIONS).clamp(
116
+ _CLIP, 1.0 - _CLIP
117
+ )
118
+ gaussian = _r44_inverse_normal(probability)
119
+ values = (1.5 * gaussian).float()
120
+ if not bool(torch.isfinite(values).all()):
121
+ raise RuntimeError("SQG compander produced a non-finite value")
122
+ return values.to(torch.float8_e4m3fn).view(torch.uint8).contiguous()
123
+
124
+
125
+ def sqg_e4m3_bytes(
126
+ bits: int,
127
+ mode: str,
128
+ *,
129
+ device: torch.device | str = "cpu",
130
+ ) -> torch.Tensor:
131
+ """Return the 65,536 raw finite-E4M3 labels for an L16 SQG graph."""
132
+
133
+ _validate(bits, mode)
134
+ return _sqg_cpu_bytes(bits, mode).to(device=device).contiguous()
135
+
136
+
137
+ def sqg_e4m3_codebook(
138
+ bits: int,
139
+ mode: str,
140
+ *,
141
+ device: torch.device | str = "cpu",
142
+ dtype: torch.dtype = torch.float16,
143
+ ) -> torch.Tensor:
144
+ """Return the SQG table widened from its exact E4M3 wire values."""
145
+
146
+ if not dtype.is_floating_point:
147
+ raise TypeError("SQG codebook dtype must be floating point")
148
+ raw = sqg_e4m3_bytes(bits, mode, device=device)
149
+ return raw.view(torch.float8_e4m3fn).to(dtype=dtype).contiguous()
150
+
151
+
152
+ def sqg_e4m3_bytes_from_rank_lut(
153
+ bits: int,
154
+ rank_lut: torch.Tensor,
155
+ *,
156
+ device: torch.device | str = "cpu",
157
+ ) -> torch.Tensor:
158
+ """Map a shared rank-indexed E4M3 law onto the unchanged SQG graph.
159
+
160
+ ``rank_lut`` is deliberately independent of ``bits``. K2 through K6 may
161
+ expose different outgoing menus because their stratum widths differ, but
162
+ they retain the same history mixer, syndrome mixer, branch permutation,
163
+ and scalar reconstruction law. This is the controlled interface used to
164
+ evaluate alternative companders without introducing rate-specific graph
165
+ edits.
166
+ """
167
+
168
+ _validate(bits, "normal")
169
+ if rank_lut.dtype != torch.uint8:
170
+ raise TypeError("SQG rank LUT must contain raw uint8 E4M3 labels")
171
+ if rank_lut.ndim != 1 or rank_lut.numel() != _TRANSITIONS:
172
+ raise ValueError("SQG rank LUT must contain exactly 65,536 labels")
173
+ rank_lut = rank_lut.detach().to(device="cpu").contiguous()
174
+ values = rank_lut.view(torch.float8_e4m3fn).float()
175
+ if not bool(torch.isfinite(values).all()):
176
+ raise ValueError("SQG rank LUT must contain only finite E4M3 labels")
177
+ return rank_lut.index_select(0, sqg_rank_permutation(bits)).to(
178
+ device=device
179
+ ).contiguous()
180
+
181
+
182
+ def sqg_e4m3_codebook_from_rank_lut(
183
+ bits: int,
184
+ rank_lut: torch.Tensor,
185
+ *,
186
+ device: torch.device | str = "cpu",
187
+ dtype: torch.dtype = torch.float16,
188
+ ) -> torch.Tensor:
189
+ """Widen a shared rank-indexed E4M3 law after SQG graph labelling."""
190
+
191
+ if not dtype.is_floating_point:
192
+ raise TypeError("SQG codebook dtype must be floating point")
193
+ raw = sqg_e4m3_bytes_from_rank_lut(bits, rank_lut, device=device)
194
+ return raw.view(torch.float8_e4m3fn).to(dtype=dtype).contiguous()
195
+
196
+
197
+ def _finite_e4m3_rank_lut(values: torch.Tensor) -> torch.Tensor:
198
+ """Round a monotone real rank law to canonical finite E4M3 bytes."""
199
+
200
+ if values.ndim != 1 or values.numel() != _TRANSITIONS:
201
+ raise ValueError("SQG rank-law values must contain exactly 65,536 entries")
202
+ if not values.is_floating_point() or not bool(torch.isfinite(values).all()):
203
+ raise ValueError("SQG rank-law values must be finite floating point")
204
+ raw = values.float().to(torch.float8_e4m3fn).view(torch.uint8).contiguous()
205
+ # E4M3 has signed zero. The numerical law uses one canonical zero byte so
206
+ # its exact representation is stable across CPU/GPU conversion paths.
207
+ raw = raw.clone()
208
+ raw[(raw & 0x7F) == 0] = 0
209
+ decoded = raw.view(torch.float8_e4m3fn).float()
210
+ if not bool(torch.isfinite(decoded).all()):
211
+ raise RuntimeError("SQG rank law rounded to a non-finite E4M3 value")
212
+ if not bool(torch.all(decoded[1:] >= decoded[:-1])):
213
+ raise RuntimeError("SQG rank law is not monotone after E4M3 rounding")
214
+ return raw
215
+
216
+
217
+ @lru_cache(maxsize=1)
218
+ def sqg_cheb_normal_rank_e4m3_bytes() -> torch.Tensor:
219
+ """Return the exact full-tail normal target used by SQG-Cheb.
220
+
221
+ The Chebyshev evaluator is an implementation of this finite staircase,
222
+ not a different reconstruction law. Computing the midpoint quantiles
223
+ here gives a compact scientific reference for candidate generation and
224
+ reproduces the exhaustively validated L16 SQG-Cheb table byte-for-byte.
225
+ """
226
+
227
+ ranks = torch.arange(_TRANSITIONS, dtype=torch.float64)
228
+ probability = (ranks + 0.5) / _TRANSITIONS
229
+ values = 1.5 * torch.special.ndtri(probability)
230
+ return _finite_e4m3_rank_lut(values)
231
+
232
+
233
+ @lru_cache(maxsize=None)
234
+ def sqg_cheb_normal_e4m3_bytes(bits: int) -> torch.Tensor:
235
+ """Map the exact SQG-Cheb normal staircase onto the frozen SQG graph."""
236
+
237
+ return sqg_e4m3_bytes_from_rank_lut(
238
+ bits, sqg_cheb_normal_rank_e4m3_bytes()
239
+ ).contiguous()
240
+
241
+
242
+ @lru_cache(maxsize=1)
243
+ def sqg_xor_cheb_t12_rank_lut_bytes() -> torch.Tensor:
244
+ """Return the frozen 4 KiB modal T12 reconstruction staircase.
245
+
246
+ Each byte represents sixteen consecutive ranks of the exact normal
247
+ staircase. The modal byte is selected per block; ties select the lower
248
+ raw byte. This is the same immutable construction used by the B12X
249
+ ``sqg_xor_cheb_t12`` decoder.
250
+ """
251
+
252
+ exact = sqg_cheb_normal_rank_e4m3_bytes().reshape(1 << 12, 16)
253
+ result = torch.empty(1 << 12, dtype=torch.uint8)
254
+ for index, block in enumerate(exact):
255
+ labels, counts = torch.unique(block, return_counts=True)
256
+ result[index] = labels[counts == counts.max()].min()
257
+ return result.contiguous()
258
+
259
+
260
+ @lru_cache(maxsize=None)
261
+ def sqg_xor_rank_permutation(bits: int) -> torch.Tensor:
262
+ """Return the primary carry-mixed SQG rank for every L16 codeword.
263
+
264
+ The two triangular xorshifts are bijections over the retained history,
265
+ the multiplier is odd, and bit reversal followed by XOR is a branch
266
+ permutation. The resulting map is therefore bijective over all 65,536
267
+ ``(stratum, phase)`` coordinates while preserving one outgoing edge per
268
+ stratum in every state.
269
+ """
270
+
271
+ _validate(bits, "normal")
272
+ width = 16 - bits
273
+ history_mask = (1 << width) - 1
274
+ branch_mask = (1 << bits) - 1
275
+ codeword = torch.arange(_TRANSITIONS, dtype=torch.int64)
276
+ history = codeword >> bits
277
+ branch = codeword & branch_mask
278
+
279
+ mixed = history ^ (history >> 11)
280
+ mixed ^= (mixed << 11) & history_mask
281
+ product = (0x3FA7D929 * mixed + 0xC928FD8E) & 0xFFFFFFFF
282
+ phase = product & history_mask
283
+ syndrome = product >> (32 - bits)
284
+ stratum = _reverse_low_bits(branch, bits) ^ syndrome
285
+ return ((stratum << width) | phase).contiguous()
286
+
287
+
288
+ @lru_cache(maxsize=None)
289
+ def _sqg_xor_cheb_t12_cpu_bytes(bits: int) -> torch.Tensor:
290
+ ranks = sqg_xor_rank_permutation(bits)
291
+ return sqg_xor_cheb_t12_rank_lut_bytes().index_select(0, ranks >> 4).contiguous()
292
+
293
+
294
+ def sqg_xor_cheb_t12_bytes(
295
+ bits: int,
296
+ *,
297
+ device: torch.device | str = "cpu",
298
+ ) -> torch.Tensor:
299
+ """Return the primary QSRT-E4M3 labels for all L16 codewords."""
300
+
301
+ _validate(bits, "normal")
302
+ return _sqg_xor_cheb_t12_cpu_bytes(bits).to(device=device).contiguous()
303
+
304
+
305
+ def sqg_codebook_bytes(
306
+ bits: int,
307
+ codebook: str,
308
+ *,
309
+ rate_axis: str | None = None,
310
+ device: torch.device | str = "cpu",
311
+ ) -> torch.Tensor:
312
+ """Return exact state-indexed E4M3 labels for a named SQG codebook."""
313
+
314
+ if codebook == SQG_XOR_CHEB_T12:
315
+ return sqg_xor_cheb_t12_bytes(bits, device=device)
316
+ if codebook == SQG_NORMAL_E4M3:
317
+ return sqg_e4m3_bytes(bits, "normal", device=device)
318
+ if codebook == SQG_CHEB_NORMAL_E4M3:
319
+ return sqg_cheb_normal_e4m3_bytes(bits).to(device=device).contiguous()
320
+ if codebook == SQG_CHEB:
321
+ if rate_axis not in ("k", "n"):
322
+ raise ValueError(
323
+ "the w2-only K2-Q8H4 profile requires rate_axis 'k' or 'n'"
324
+ )
325
+ rank_lut = sqg_cheb_normal_rank_e4m3_bytes()
326
+ if bits == 2 and rate_axis == "k":
327
+ return sqg_k2_eight_stratum_e4m3_bytes_from_rank_lut(
328
+ rank_lut, history_bit=4, device=device
329
+ )
330
+ return sqg_e4m3_bytes_from_rank_lut(
331
+ bits, rank_lut, device=device
332
+ ).contiguous()
333
+ raise ValueError(f"unsupported SQG codebook: {codebook!r}")
334
+
335
+
336
+ def sqg_codebook(
337
+ bits: int,
338
+ codebook: str,
339
+ *,
340
+ rate_axis: str | None = None,
341
+ device: torch.device | str = "cpu",
342
+ dtype: torch.dtype = torch.float16,
343
+ ) -> torch.Tensor:
344
+ """Return a named SQG codebook widened from its exact E4M3 labels."""
345
+
346
+ if not dtype.is_floating_point:
347
+ raise TypeError("SQG codebook dtype must be floating point")
348
+ return (
349
+ sqg_codebook_bytes(bits, codebook, rate_axis=rate_axis, device=device)
350
+ .view(torch.float8_e4m3fn)
351
+ .to(dtype=dtype)
352
+ .contiguous()
353
+ )
354
+
355
+
356
+ @lru_cache(maxsize=None)
357
+ def sqg_k2_eight_stratum_rank_permutation(
358
+ history_bit: int = 2,
359
+ ) -> torch.Tensor:
360
+ """Return a state-conditioned eight-stratum labelling for a K2 trellis.
361
+
362
+ The physical graph still appends two branch bits and retains fourteen
363
+ state bits. Numerical labelling reinterprets the newest retained history
364
+ bit plus the two new branch bits as a virtual three-bit stratum selector;
365
+ the remaining thirteen bits select phase. A K2 state therefore exposes
366
+ four of eight strata, while its retained history chooses which four.
367
+ Globally this is the same bijective rank law used by K3. ``history_bit``
368
+ selects which retained physical codeword bit becomes the most-significant
369
+ virtual stratum bit. Bit 2 is the newest retained bit and reproduces the
370
+ exact K3 transition-label function over the unmodified codeword.
371
+ """
372
+
373
+ if isinstance(history_bit, bool) or not isinstance(history_bit, int):
374
+ raise TypeError("K2 eight-stratum history bit must be an integer")
375
+ if not 2 <= history_bit < 16:
376
+ raise ValueError("K2 eight-stratum history bit must be in [2, 15]")
377
+ k3_ranks = sqg_rank_permutation(3)
378
+ if history_bit == 2:
379
+ return k3_ranks
380
+
381
+ transitions = torch.arange(_TRANSITIONS, dtype=torch.int64)
382
+ bit_2 = (transitions >> 2) & 1
383
+ bit_h = (transitions >> history_bit) & 1
384
+ swap = bit_2 ^ bit_h
385
+ permuted = transitions ^ (swap << 2) ^ (swap << history_bit)
386
+ return k3_ranks.index_select(0, permuted).contiguous()
387
+
388
+
389
+ def sqg_k2_eight_stratum_e4m3_bytes_from_rank_lut(
390
+ rank_lut: torch.Tensor,
391
+ *,
392
+ history_bit: int = 2,
393
+ device: torch.device | str = "cpu",
394
+ ) -> torch.Tensor:
395
+ """Map one shared rank staircase onto state-conditioned K2 octiles."""
396
+
397
+ if rank_lut.dtype != torch.uint8:
398
+ raise TypeError("SQG rank LUT must contain raw uint8 E4M3 labels")
399
+ if rank_lut.ndim != 1 or rank_lut.numel() != _TRANSITIONS:
400
+ raise ValueError("SQG rank LUT must contain exactly 65,536 labels")
401
+ rank_lut = rank_lut.detach().to(device="cpu").contiguous()
402
+ values = rank_lut.view(torch.float8_e4m3fn).float()
403
+ if not bool(torch.isfinite(values).all()):
404
+ raise ValueError("SQG rank LUT must contain only finite E4M3 labels")
405
+ return rank_lut.index_select(
406
+ 0, sqg_k2_eight_stratum_rank_permutation(history_bit)
407
+ ).to(device=device).contiguous()
408
+
409
+
410
+ def sqg_rank_permutation(bits: int) -> torch.Tensor:
411
+ """Return the pre-projection quantile rank for structural validation."""
412
+
413
+ _validate(bits, "normal")
414
+ width = 16 - bits
415
+ branches = 1 << bits
416
+ transitions = torch.arange(_TRANSITIONS, dtype=torch.int64)
417
+ history = transitions >> bits
418
+ branch = transitions & (branches - 1)
419
+ phase = _mix_width(
420
+ history,
421
+ width=width,
422
+ multiplier_a=0x65AF,
423
+ multiplier_b=0x16BF,
424
+ shift_a=6,
425
+ shift_b=4,
426
+ shift_c=5,
427
+ )
428
+ syndrome = _mix_width(
429
+ history ^ 0x5105,
430
+ width=width,
431
+ multiplier_a=0x8693,
432
+ multiplier_b=0x2A21,
433
+ shift_a=2,
434
+ shift_b=4,
435
+ shift_c=4,
436
+ ) & (branches - 1)
437
+ stratum = (7 * (_reverse_low_bits(branch, bits) ^ syndrome)) & (branches - 1)
438
+ return ((stratum << width) | phase).contiguous()
reproduction/closure/patches/kquant/changed-files/kquant/sqg_quantizer.py ADDED
@@ -0,0 +1,270 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Research-only bridge from EXL's production encoder to SQG E4M3 tables."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import hashlib
6
+ import importlib.machinery
7
+ import importlib.util
8
+ import os
9
+ import re
10
+ import sys
11
+ from collections.abc import Mapping
12
+ from functools import lru_cache
13
+ from pathlib import Path
14
+
15
+ import torch
16
+ from torch.utils.cpp_extension import load
17
+
18
+ from kquant.sqg_e4m3 import sqg_e4m3_bytes
19
+
20
+
21
+ _EXTENSION_NAME = "kquant_sqg_quantize_ext_v22"
22
+ _EXTENSION_PATH_ENV = "KQUANT_SQG_EXTENSION_PATH"
23
+ _EXTENSION_SHA256_ENV = "KQUANT_SQG_EXTENSION_SHA256"
24
+ _REQUIRE_PREBUILT_ENV = "KQUANT_SQG_REQUIRE_PREBUILT"
25
+ _SHA256_RE = re.compile(r"[0-9a-f]{64}")
26
+
27
+
28
+ def _sha256_file(path: Path) -> str:
29
+ digest = hashlib.sha256()
30
+ with path.open("rb") as handle:
31
+ for chunk in iter(lambda: handle.read(1024 * 1024), b""):
32
+ digest.update(chunk)
33
+ return digest.hexdigest()
34
+
35
+
36
+ def _import_prebuilt_extension(path: Path):
37
+ """Import one exact pybind extension without invoking the JIT builder."""
38
+
39
+ spec = importlib.util.spec_from_file_location(_EXTENSION_NAME, path)
40
+ if spec is None or spec.loader is None:
41
+ raise ImportError(f"cannot construct an import spec for SQG extension: {path}")
42
+ previous = sys.modules.get(_EXTENSION_NAME)
43
+ module = importlib.util.module_from_spec(spec)
44
+ sys.modules[_EXTENSION_NAME] = module
45
+ try:
46
+ spec.loader.exec_module(module)
47
+ except BaseException:
48
+ if previous is None:
49
+ sys.modules.pop(_EXTENSION_NAME, None)
50
+ else:
51
+ sys.modules[_EXTENSION_NAME] = previous
52
+ raise
53
+ return module
54
+
55
+
56
+ def _load_prebuilt_extension(raw_path: str, expected_sha256: str):
57
+ candidate = Path(raw_path)
58
+ if not candidate.is_absolute():
59
+ raise ValueError(f"{_EXTENSION_PATH_ENV} must be an absolute path")
60
+ if candidate.is_symlink():
61
+ raise ValueError(f"{_EXTENSION_PATH_ENV} may not name a symlink")
62
+ try:
63
+ path = candidate.resolve(strict=True)
64
+ except FileNotFoundError as exc:
65
+ raise FileNotFoundError(
66
+ f"sealed SQG extension does not exist: {candidate}"
67
+ ) from exc
68
+ if not path.is_file():
69
+ raise ValueError(f"sealed SQG extension is not a regular file: {path}")
70
+ allowed_names = {
71
+ f"{_EXTENSION_NAME}{suffix}"
72
+ for suffix in importlib.machinery.EXTENSION_SUFFIXES
73
+ }
74
+ if path.name not in allowed_names:
75
+ raise ValueError(
76
+ "sealed SQG extension filename must identify "
77
+ f"{_EXTENSION_NAME}: {path.name}"
78
+ )
79
+ if _SHA256_RE.fullmatch(expected_sha256) is None:
80
+ raise ValueError(f"{_EXTENSION_SHA256_ENV} must be 64 lowercase hex digits")
81
+ observed_sha256 = _sha256_file(path)
82
+ if observed_sha256 != expected_sha256:
83
+ raise RuntimeError(
84
+ "sealed SQG extension SHA256 mismatch: "
85
+ f"{observed_sha256} != {expected_sha256}"
86
+ )
87
+ module = _import_prebuilt_extension(path)
88
+ module_path = Path(str(getattr(module, "__file__", ""))).resolve()
89
+ if module_path != path:
90
+ raise RuntimeError(
91
+ f"loaded SQG extension origin differs: {module_path} != {path}"
92
+ )
93
+ if not callable(getattr(module, "quantize_tiles_procedural", None)) or not callable(
94
+ getattr(module, "quantize_tiles_sqg", None)
95
+ ):
96
+ raise RuntimeError(
97
+ "sealed SQG extension lacks required quantization entry points"
98
+ )
99
+ if _sha256_file(path) != expected_sha256:
100
+ raise RuntimeError("sealed SQG extension changed while it was being imported")
101
+ return module
102
+
103
+
104
+ @lru_cache(maxsize=1)
105
+ def _extension():
106
+ require_value = os.environ.get(_REQUIRE_PREBUILT_ENV, "")
107
+ if require_value not in ("", "0", "1"):
108
+ raise ValueError(f"{_REQUIRE_PREBUILT_ENV} must be unset, 0, or 1")
109
+ raw_path = os.environ.get(_EXTENSION_PATH_ENV, "")
110
+ expected_sha256 = os.environ.get(_EXTENSION_SHA256_ENV, "")
111
+ if require_value == "1" or raw_path or expected_sha256:
112
+ if not raw_path or not expected_sha256:
113
+ raise RuntimeError(
114
+ f"{_EXTENSION_PATH_ENV} and {_EXTENSION_SHA256_ENV} are both required "
115
+ "for sealed prebuilt SQG loading"
116
+ )
117
+ return _load_prebuilt_extension(raw_path, expected_sha256)
118
+
119
+ project = Path(__file__).resolve().parents[1]
120
+ return load(
121
+ name=_EXTENSION_NAME,
122
+ sources=[
123
+ str(project / "kquant/csrc/sqg_quantize.cpp"),
124
+ str(project / "kquant/csrc/sqg_quantize.cu"),
125
+ ],
126
+ extra_include_paths=[str(project / "kquant/csrc")],
127
+ extra_cflags=["-O3"],
128
+ extra_cuda_cflags=[
129
+ "-O3",
130
+ "--use_fast_math",
131
+ "-lineinfo",
132
+ "-Xcudafe",
133
+ "--diag_suppress=177",
134
+ "-Xcudafe",
135
+ "--diag_suppress=20012",
136
+ ],
137
+ verbose=False,
138
+ )
139
+
140
+
141
+ @lru_cache(maxsize=None)
142
+ def _sqg_temp_buffers(device: torch.device, bits: int):
143
+ """Allocate the packed traceback buffers consumed by kquant's kernel."""
144
+
145
+ multiprocessors = torch.cuda.get_device_properties(device).multi_processor_count
146
+ edges = 65536 >> bits
147
+ decisions = edges // 4 if bits == 2 else (edges // 2 if bits <= 4 else edges)
148
+ free_bytes, _ = torch.cuda.mem_get_info(device)
149
+ decision_bytes_per_tile = 256 * decisions
150
+ affordable = max(256, int(free_bytes * 0.5) // decision_bytes_per_tile)
151
+ max_batch = min(max(256, 3 * multiprocessors), affordable)
152
+ costs = torch.zeros(
153
+ (max_batch, 2, edges), dtype=torch.float16, device=device
154
+ )
155
+ traceback = torch.empty(
156
+ (max_batch, 256, decisions), dtype=torch.uint8, device=device
157
+ )
158
+ return costs, traceback
159
+
160
+
161
+ def install_sqg_quantizer(quantizer_module) -> None:
162
+ """Teach a loaded EXL encoder module to consume ``sqg_e4m3_lut``.
163
+
164
+ The patch is process-local. SQG and explicit MCG/MUL1 controls use
165
+ kquant's CUDA extension with one Viterbi/tail-biting implementation. A
166
+ ``None`` entry in a rate-specific mapping explicitly selects MCG,
167
+ permitting controlled hybrid rate-curve studies. Calls without any
168
+ kquant codebook argument retain the unmodified upstream EXL behavior.
169
+ """
170
+
171
+ if getattr(quantizer_module, "_kquant_sqg_installed", False):
172
+ return
173
+ original = quantizer_module.quantize_tiles
174
+
175
+ device_luts: dict[tuple[str, int, str], torch.Tensor] = {}
176
+ transposed_sqg_luts: dict[
177
+ tuple[str, int, int], tuple[torch.Tensor, torch.Tensor]
178
+ ] = {}
179
+
180
+ def quantize_tiles(tiles: torch.Tensor, quant_args: dict):
181
+ codebook = quant_args.get("sqg_e4m3_lut")
182
+ rate_codebooks = quant_args.get("sqg_e4m3_luts_by_bits")
183
+ mode = quant_args.get("sqg_e4m3_mode")
184
+ if codebook is None and rate_codebooks is None and mode is None:
185
+ return original(tiles, quant_args)
186
+ if len(quant_args["devices"]) != 1:
187
+ raise ValueError("the SQG validation hook currently requires one CUDA device")
188
+ tiles = tiles.contiguous()
189
+ if tiles.dtype != torch.float32 or tiles.ndim != 2 or tiles.shape[1] != 256:
190
+ raise ValueError("SQG tiles must be contiguous FP32 [N, 256]")
191
+ bits = int(quant_args["K"])
192
+ if rate_codebooks is not None:
193
+ if codebook is not None or mode is not None:
194
+ raise ValueError(
195
+ "rate-specific SQG LUTs cannot be combined with another SQG law"
196
+ )
197
+ if not isinstance(rate_codebooks, Mapping):
198
+ raise TypeError("sqg_e4m3_luts_by_bits must be a mapping")
199
+ if set(rate_codebooks) - set(range(2, 7)):
200
+ raise ValueError("rate-specific SQG LUT keys must be K2 through K6")
201
+ try:
202
+ codebook = rate_codebooks[bits]
203
+ except KeyError as exc:
204
+ raise ValueError(f"missing rate-specific SQG K{bits} LUT") from exc
205
+ if codebook is None:
206
+ if bits not in (2, 3, 4):
207
+ raise ValueError(
208
+ "non-SQG procedural controls remain limited to K2 through K4"
209
+ )
210
+ output = torch.empty_like(tiles)
211
+ indices = torch.empty_like(tiles, dtype=torch.int16)
212
+ costs, edges = _sqg_temp_buffers(tiles.device, bits)
213
+ _extension().quantize_tiles_procedural(
214
+ tiles,
215
+ output,
216
+ indices,
217
+ costs,
218
+ edges,
219
+ bits,
220
+ 1,
221
+ int(quant_args.get("tailbite_context", 128)),
222
+ )
223
+ return output, indices
224
+ elif codebook is None:
225
+ if mode != "normal":
226
+ raise ValueError("the supported R44 mode is 'normal'")
227
+ key = (str(tiles.device), bits, mode)
228
+ codebook = device_luts.get(key)
229
+ if codebook is None:
230
+ codebook = sqg_e4m3_bytes(bits, mode, device=tiles.device)
231
+ device_luts[key] = codebook
232
+ output = torch.empty_like(tiles)
233
+ indices = torch.empty_like(tiles, dtype=torch.int16)
234
+ costs, edges = _sqg_temp_buffers(tiles.device, bits)
235
+ lut = codebook.to(device=tiles.device, dtype=torch.uint8).contiguous()
236
+ if bits in (2, 3, 4):
237
+ source_key = codebook.data_ptr() if codebook.is_cuda else id(codebook)
238
+ cache_key = (str(tiles.device), bits, source_key)
239
+ cached = transposed_sqg_luts.get(cache_key)
240
+ if cached is None or cached[0] is not codebook:
241
+ # [predecessor, out-edge-pair, pair-byte] ->
242
+ # [out-edge-pair, predecessor, pair-byte]. Each CUDA thread
243
+ # can then fetch all predecessor labels in one uint2 (K2),
244
+ # one uint4 (K3), or two uint4s (K4), rather than issuing one
245
+ # gather per predecessor.
246
+ predecessors = 1 << bits
247
+ out_edge_pairs = (65536 >> bits) // 2
248
+ lut = (
249
+ lut.reshape(predecessors, out_edge_pairs, 2)
250
+ .permute(1, 0, 2)
251
+ .contiguous()
252
+ .reshape(-1)
253
+ )
254
+ transposed_sqg_luts[cache_key] = (codebook, lut)
255
+ else:
256
+ lut = cached[1]
257
+ _extension().quantize_tiles_sqg(
258
+ tiles,
259
+ output,
260
+ indices,
261
+ costs,
262
+ edges,
263
+ lut,
264
+ bits,
265
+ int(quant_args.get("tailbite_context", 128)),
266
+ )
267
+ return output, indices
268
+
269
+ quantizer_module.quantize_tiles = quantize_tiles
270
+ quantizer_module._kquant_sqg_installed = True
reproduction/closure/patches/kquant/changed-files/tests/test_qsrt.py ADDED
@@ -0,0 +1,486 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from __future__ import annotations
2
+
3
+ from dataclasses import replace
4
+
5
+ import pytest
6
+ import torch
7
+ import torch.nn.functional as F
8
+
9
+ from kquant.exl3_reference import reconstruct_trellis_states
10
+ from kquant.qsrt import (
11
+ EXPERT_TRELLIS_BYTES,
12
+ EXPERTS_PER_LAYER,
13
+ FORMAT_SECTION_BYTES,
14
+ FORMAT_TABLE_BYTES,
15
+ HOT_METADATA_BYTES,
16
+ INTERMEDIATE_CHANNELS,
17
+ LAYER_HEADER_BYTES,
18
+ MATRIX_TRELLIS_BYTES,
19
+ PAIRS_PER_EXPERT,
20
+ PAIR_BYTES,
21
+ PHASE1_H13_EXPERT_LOCAL_ALPHA,
22
+ PHASE1_H2_EXPERT_LOCAL_ALPHA,
23
+ PHASE1_H2_LOCAL_BASIS,
24
+ PHASE1_H2_SHRINKAGE_POLICY,
25
+ PHASE1_MODE_CANDIDATES,
26
+ PHASE1_MODE_IDS,
27
+ PHASE1_SHARED_RATE_MODE,
28
+ RECORDS_PER_EXPERT,
29
+ RATE_TRANSFER_MODES,
30
+ R0,
31
+ R1,
32
+ R2,
33
+ SCHEMA,
34
+ SHARED_SCALE_BYTES,
35
+ SHARED_SCALE_SECTION_BYTES,
36
+ STORAGE_ALIGNMENT,
37
+ ExpertFormatSpec,
38
+ ModeSpec,
39
+ PackedQSRTTrellis,
40
+ QSRTTrellisDescriptor,
41
+ coupled_intermediate_permutation,
42
+ decode_qsrt_exl3_weight,
43
+ expand_group_order,
44
+ expand_qsrt_hot_metadata,
45
+ expand_record_order,
46
+ importance_group_order,
47
+ matrix_rate_axis,
48
+ mode_from_context_bits,
49
+ pack_qsrt_format_table,
50
+ pack_qsrt_format_section,
51
+ pack_qsrt_trellis,
52
+ pack_qsrt_shared_scale_section,
53
+ pack_trellis_edges,
54
+ rate_transfer_record_order,
55
+ record_repack_order,
56
+ relabel_block_contexts_for_record_order,
57
+ repack_encoded_records,
58
+ repack_rate_axis,
59
+ pair_bits,
60
+ pair_kinds,
61
+ logical_pair_for_slot,
62
+ physical_pair_slot,
63
+ record_bits,
64
+ record_contexts,
65
+ storage_group_order,
66
+ unpack_qsrt_trellis_edges,
67
+ unpack_qsrt_format_section,
68
+ unpack_qsrt_shared_scale_section,
69
+ unpack_qsrt_format_table,
70
+ unpack_qsrt_trellis_states,
71
+ unpack_trellis_edges,
72
+ unpack_trellis_states,
73
+ )
74
+ from kquant.tp_simulator import situ
75
+
76
+
77
+ def test_mode_schedules_are_fixed_rate_pairs() -> None:
78
+ assert pair_kinds(R0) == ("P33",) * PAIRS_PER_EXPERT
79
+ assert pair_kinds(R1) == ("P24",) + ("P33",) * 11
80
+ assert pair_kinds(R2) == ("P24",) * 2 + ("P33",) * 10
81
+
82
+
83
+ def test_pair_rotation_is_a_per_expert_bijection() -> None:
84
+ for layer, expert in ((1, 0), (1, 17), (40, 285), (92, 895)):
85
+ physical = [
86
+ physical_pair_slot(layer, expert, logical_pair)
87
+ for logical_pair in range(PAIRS_PER_EXPERT)
88
+ ]
89
+ assert sorted(physical) == list(range(PAIRS_PER_EXPERT))
90
+ assert [
91
+ logical_pair_for_slot(layer, expert, rank)
92
+ for rank in physical
93
+ ] == list(range(PAIRS_PER_EXPERT))
94
+
95
+
96
+ def test_pair_rotation_balances_p24_ownership_across_experts() -> None:
97
+ counts = [0] * PAIRS_PER_EXPERT
98
+ r = 2
99
+ for expert in range(EXPERTS_PER_LAYER):
100
+ for rank in range(PAIRS_PER_EXPERT):
101
+ counts[rank] += logical_pair_for_slot(24, expert, rank) < r
102
+
103
+ assert max(counts) - min(counts) <= 1
104
+ for r, mode in enumerate(RATE_TRANSFER_MODES):
105
+ assert mode.mode_id == r
106
+ assert mode.name == f"R{r}"
107
+ assert len(record_bits(mode)) == RECORDS_PER_EXPERT
108
+ assert len(pair_bits(mode)) == PAIRS_PER_EXPERT
109
+ assert all(sum(pair) == 6 for pair in pair_bits(mode))
110
+ assert sum(record_bits(mode)) / RECORDS_PER_EXPERT == 3
111
+ assert pair_kinds(mode) == ("P24",) * r + ("P33",) * (12 - r)
112
+
113
+
114
+ def test_qsrt_encoder_policy_is_frozen_to_r012() -> None:
115
+ assert PHASE1_MODE_IDS == (0, 1, 2)
116
+ assert tuple(mode.mode_id for mode in PHASE1_MODE_CANDIDATES) == PHASE1_MODE_IDS
117
+ assert not PHASE1_SHARED_RATE_MODE
118
+ assert PHASE1_H13_EXPERT_LOCAL_ALPHA == 0.0
119
+ assert PHASE1_H2_EXPERT_LOCAL_ALPHA == 0.75
120
+ assert PHASE1_H2_LOCAL_BASIS == "decoded_candidate_post_situ"
121
+ assert PHASE1_H2_SHRINKAGE_POLICY == "weighted_oas_scaled_identity"
122
+ assert len(RATE_TRANSFER_MODES) == 3
123
+
124
+
125
+ def test_context_allocations_map_to_the_rate_transfer_ladder() -> None:
126
+ assert mode_from_context_bits((3, 3, 3, 3)) is R0
127
+ assert mode_from_context_bits((2,) + (3,) * 22 + (4,)) is R1
128
+ assert mode_from_context_bits((2, 2) + (3,) * 20 + (4, 4)) is R2
129
+ with pytest.raises(ValueError, match="monotone"):
130
+ mode_from_context_bits((2, 4) + (3,) * 20 + (2, 4))
131
+ with pytest.raises(ValueError, match="rate-transfer count 6"):
132
+ ModeSpec(1, "bad", (2, 3, 3, 4))
133
+
134
+
135
+ def test_candidate_descriptor_contains_no_tensor_parallel_geometry() -> None:
136
+ descriptor = QSRTTrellisDescriptor(
137
+ mode_id=R2.mode_id,
138
+ rate_axis="k",
139
+ k_tiles=192,
140
+ n_tiles=224,
141
+ )
142
+ assert "tp_size" not in descriptor.to_manifest()
143
+
144
+
145
+ def test_provisional_format_table_supports_separate_r13_r2() -> None:
146
+ formats = ["X4T", R0, R1, (1, 2)] * (EXPERTS_PER_LAYER // 4)
147
+ packed = pack_qsrt_format_table(formats)
148
+
149
+ assert packed.dtype == torch.uint8
150
+ assert packed.shape == (FORMAT_TABLE_BYTES,)
151
+ assert packed[:4].tolist() == [0xFF, 0x00, 0x11, 0x12]
152
+ assert unpack_qsrt_format_table(packed) == tuple(
153
+ ["X4T", "R0", "R1", "R1/R2"] * (EXPERTS_PER_LAYER // 4)
154
+ )
155
+
156
+ malformed = packed.clone()
157
+ malformed[0] = 0xD0
158
+ with pytest.raises(ValueError, match="invalid rate code"):
159
+ unpack_qsrt_format_table(malformed)
160
+ assert ExpertFormatSpec.compressed(1, 2).code == 0x12
161
+ assert ExpertFormatSpec.from_code(0x12).name == "R1/R2"
162
+ assert ExpertFormatSpec.from_code(0xFF).is_x4t
163
+ with pytest.raises(ValueError, match="896 experts"):
164
+ pack_qsrt_format_table([R0])
165
+ with pytest.raises(TypeError, match="torch.uint8"):
166
+ unpack_qsrt_format_table(packed.int())
167
+
168
+
169
+ def test_format_section_padding_and_hot_slot_expansion_are_canonical() -> None:
170
+ formats = ["X4T", R0, R1, (1, 2)] * (EXPERTS_PER_LAYER // 4)
171
+ section = pack_qsrt_format_section(formats)
172
+ codes, slots = expand_qsrt_hot_metadata(formats)
173
+
174
+ assert section.shape == (FORMAT_SECTION_BYTES,)
175
+ assert torch.count_nonzero(section[FORMAT_TABLE_BYTES:]) == 0
176
+ assert unpack_qsrt_format_section(section) == tuple(
177
+ ["X4T", "R0", "R1", "R1/R2"] * (EXPERTS_PER_LAYER // 4)
178
+ )
179
+ assert codes[:8].tolist() == [255, 0, 17, 18, 255, 0, 17, 18]
180
+ assert slots[:8].tolist() == [0, 0, 1, 2, 1, 3, 4, 5]
181
+ assert codes.numel() + slots.numel() * slots.element_size() == HOT_METADATA_BYTES
182
+
183
+ malformed = section.clone()
184
+ malformed[-1] = 1
185
+ with pytest.raises(ValueError, match="nonzero alignment padding"):
186
+ unpack_qsrt_format_section(malformed)
187
+
188
+
189
+ def test_shared_scale_section_round_trips_exactly() -> None:
190
+ shared = tuple(
191
+ torch.linspace(-1 + index, 1 + index, 3584, dtype=torch.float16)
192
+ for index in range(3)
193
+ )
194
+ section = pack_qsrt_shared_scale_section(*shared)
195
+ actual = unpack_qsrt_shared_scale_section(section)
196
+ assert all(
197
+ torch.equal(expected, observed)
198
+ for expected, observed in zip(shared, actual, strict=True)
199
+ )
200
+
201
+ malformed = section.clone()
202
+ malformed[-1] = 1
203
+ with pytest.raises(ValueError, match="nonzero alignment padding"):
204
+ unpack_qsrt_shared_scale_section(malformed)
205
+
206
+
207
+ def test_matrix_rate_axis_tracks_shared_intermediate_dimension() -> None:
208
+ assert matrix_rate_axis("w1") == "n"
209
+ assert matrix_rate_axis("w3") == "n"
210
+ assert matrix_rate_axis("w2") == "k"
211
+ with pytest.raises(ValueError, match="unknown expert matrix"):
212
+ matrix_rate_axis("router")
213
+
214
+
215
+ @pytest.mark.parametrize(
216
+ ("bits", "expected_prefix"),
217
+ [
218
+ (2, [6939] * 6),
219
+ (3, [30469, 1337, 1337, 14711, 14711, 30469]),
220
+ (4, [17767, 291, -12817, -30293, 17767, 291]),
221
+ (5, [12820, 68, 21686, -14526, -31643, 13775]),
222
+ (6, [-31984, 16, 8338, 20871, -11377, -29904]),
223
+ ],
224
+ )
225
+ def test_trellis_edge_pack_matches_native_word_order(
226
+ bits: int, expected_prefix: list[int]
227
+ ) -> None:
228
+ indices = (torch.arange(256, dtype=torch.int16) % (1 << bits))[None]
229
+ packed = pack_trellis_edges(indices, bits)
230
+
231
+ assert packed.shape == (1, 16 * bits)
232
+ assert packed[0, : len(expected_prefix)].tolist() == expected_prefix
233
+ torch.testing.assert_close(unpack_trellis_edges(packed, bits), indices)
234
+
235
+
236
+ @pytest.mark.parametrize("bits", range(2, 7))
237
+ def test_trellis_edge_pack_round_trips_only_stored_low_bits(bits: int) -> None:
238
+ generator = torch.Generator().manual_seed(100 + bits)
239
+ indices = torch.randint(-32768, 32768, (7, 256), generator=generator)
240
+ packed = pack_trellis_edges(indices, bits)
241
+ unpacked = unpack_trellis_edges(packed, bits)
242
+
243
+ torch.testing.assert_close(unpacked.int(), indices.int() & ((1 << bits) - 1))
244
+
245
+
246
+ @pytest.mark.parametrize("bits", range(2, 7))
247
+ def test_cyclic_trellis_states_round_trip_exactly(bits: int) -> None:
248
+ generator = torch.Generator().manual_seed(150 + bits)
249
+ edges = torch.randint(0, 1 << bits, (5, 256), generator=generator)
250
+ states = reconstruct_trellis_states(edges, bits)
251
+ packed = pack_trellis_edges(states, bits)
252
+
253
+ torch.testing.assert_close(unpack_trellis_states(packed, bits), states)
254
+
255
+
256
+ @pytest.mark.parametrize("bits", range(2, 7))
257
+ def test_cyclic_trellis_state_closed_form_matches_scalar_recurrence(bits: int) -> None:
258
+ generator = torch.Generator().manual_seed(175 + bits)
259
+ edges = torch.randint(0, 1 << bits, (3, 5, 256), generator=generator)
260
+
261
+ state = torch.zeros(edges.shape[:-1], dtype=torch.int64)
262
+ for edge in edges[..., -((16 + bits - 1) // bits) :].unbind(dim=-1):
263
+ state = ((state << bits) | edge) & 0xFFFF
264
+ expected = []
265
+ for edge in edges.unbind(dim=-1):
266
+ state = ((state << bits) | edge) & 0xFFFF
267
+ expected.append(state)
268
+ expected_states = torch.stack(expected, dim=-1).to(torch.int16)
269
+
270
+ assert torch.equal(reconstruct_trellis_states(edges, bits), expected_states)
271
+
272
+
273
+ def _expected_edge_symbols(
274
+ encoded: torch.Tensor, record_bits: tuple[int, ...], rate_axis: str
275
+ ) -> torch.Tensor:
276
+ tile_bits = torch.tensor(record_bits).repeat_interleave(8)
277
+ masks = (1 << tile_bits) - 1
278
+ if rate_axis == "k":
279
+ masks = masks[:, None, None]
280
+ else:
281
+ masks = masks[None, :, None]
282
+ return (encoded.to(torch.int64) & masks).to(torch.int16)
283
+
284
+
285
+ def _legal_qsrt_states(
286
+ shape: tuple[int, int, int], record_bits: tuple[int, ...], rate_axis: str, seed: int
287
+ ) -> torch.Tensor:
288
+ generator = torch.Generator().manual_seed(seed)
289
+ edges = torch.empty(shape, dtype=torch.int16)
290
+ states = torch.empty_like(edges)
291
+ for record, bits in enumerate(record_bits):
292
+ begin = record * 8
293
+ if rate_axis == "k":
294
+ record_edges = torch.randint(
295
+ 0, 1 << bits, (8, shape[1], 256), generator=generator
296
+ ).to(torch.int16)
297
+ edges[begin : begin + 8] = record_edges
298
+ states[begin : begin + 8] = reconstruct_trellis_states(
299
+ record_edges, bits
300
+ )
301
+ else:
302
+ record_edges = torch.randint(
303
+ 0, 1 << bits, (shape[0], 8, 256), generator=generator
304
+ ).to(torch.int16)
305
+ edges[:, begin : begin + 8] = record_edges
306
+ states[:, begin : begin + 8] = reconstruct_trellis_states(
307
+ record_edges, bits
308
+ )
309
+ return states
310
+
311
+
312
+ @pytest.mark.parametrize(
313
+ ("rate_axis", "shape"),
314
+ [("k", (192, 224, 256)), ("n", (224, 192, 256))],
315
+ )
316
+ @pytest.mark.parametrize("mode", [R0, R1, R2])
317
+ def test_pair_payload_closes_on_both_logical_axes(
318
+ rate_axis: str, shape: tuple[int, int, int], mode
319
+ ) -> None:
320
+ encoded = _legal_qsrt_states(
321
+ shape, record_bits(mode), rate_axis, 200 + mode.mode_id
322
+ )
323
+ packed = pack_qsrt_trellis(encoded, mode, rate_axis=rate_axis)
324
+ unpacked = unpack_qsrt_trellis_edges(packed)
325
+
326
+ assert packed.descriptor.schema == SCHEMA
327
+ assert packed.payload.numel() == encoded.numel() * 3 // 16
328
+ assert packed.descriptor.payload_bytes == packed.payload.numel() * 2
329
+ assert (
330
+ packed.descriptor.words_per_pair * PAIRS_PER_EXPERT
331
+ == packed.payload.numel()
332
+ )
333
+ assert packed.descriptor.to_manifest()["pair_kinds"] == list(
334
+ pair_kinds(mode)
335
+ )
336
+ torch.testing.assert_close(
337
+ unpacked, _expected_edge_symbols(encoded, record_bits(mode), rate_axis)
338
+ )
339
+ torch.testing.assert_close(unpack_qsrt_trellis_states(packed), encoded)
340
+
341
+
342
+ def test_packer_rejects_noncyclic_states() -> None:
343
+ malformed = torch.zeros((192, 224, 256), dtype=torch.int16)
344
+ malformed[..., 0] = 1
345
+
346
+ with pytest.raises(ValueError, match="closed cyclic trellis path"):
347
+ pack_qsrt_trellis(malformed, R2, rate_axis="k")
348
+
349
+
350
+ def test_payload_rejects_wrong_shape_dtype_and_length() -> None:
351
+ encoded = torch.zeros((192, 224, 256), dtype=torch.int16)
352
+ packed = pack_qsrt_trellis(encoded, R2, rate_axis="k")
353
+ suh = torch.ones(3072, dtype=torch.float16)
354
+ svh = torch.ones(3584, dtype=torch.float16)
355
+
356
+ with pytest.raises(ValueError, match="length"):
357
+ PackedQSRTTrellis(packed.descriptor, packed.payload[:-1]).validate()
358
+ with pytest.raises(TypeError, match="torch.int16"):
359
+ PackedQSRTTrellis(packed.descriptor, packed.payload.int()).validate()
360
+ with pytest.raises(ValueError, match="3072"):
361
+ pack_qsrt_trellis(encoded[:184], R2, rate_axis="k")
362
+ with pytest.raises(ValueError, match="rate_axis"):
363
+ replace(packed.descriptor, rate_axis="x")
364
+ with pytest.raises(TypeError, match="suh must use torch.float16"):
365
+ decode_qsrt_exl3_weight(packed, suh.float(), svh)
366
+ with pytest.raises(ValueError, match="exactly 3072"):
367
+ decode_qsrt_exl3_weight(packed, suh[:-1], svh)
368
+ nonfinite = svh.clone()
369
+ nonfinite[0] = torch.inf
370
+ with pytest.raises(ValueError, match="non-finite"):
371
+ decode_qsrt_exl3_weight(packed, suh, nonfinite)
372
+
373
+
374
+ def test_context_orders_form_homogeneous_records() -> None:
375
+ block_contexts = torch.arange(24).repeat_interleave(32)
376
+ importance = importance_group_order(block_contexts, R2)
377
+ storage = storage_group_order(block_contexts, R2)
378
+ storage_channels = block_contexts.index_select(0, storage).repeat_interleave(4)
379
+
380
+ assert expand_group_order(storage).shape == (INTERMEDIATE_CHANNELS,)
381
+ assert torch.all(storage_channels.reshape(RECORDS_PER_EXPERT, 128).diff(dim=1) == 0)
382
+ assert (
383
+ storage_channels.reshape(RECORDS_PER_EXPERT, 128)[:, 0].tolist()
384
+ == list(record_contexts(R2))
385
+ )
386
+
387
+ order = record_repack_order(importance, storage)
388
+ encoded = (
389
+ torch.arange(RECORDS_PER_EXPERT)
390
+ .repeat_interleave(8 * 256)
391
+ .reshape(192, 1, 256)
392
+ )
393
+ repacked = repack_encoded_records(encoded, order, "k")
394
+ assert repacked.reshape(RECORDS_PER_EXPERT, -1)[:, 0].tolist() == order.tolist()
395
+
396
+
397
+ def test_record_repack_rejects_a_split_record() -> None:
398
+ block_contexts = torch.arange(24).repeat_interleave(32)
399
+ source = importance_group_order(block_contexts, R2)
400
+ malformed = source.clone()
401
+ malformed[31], malformed[32] = malformed[32].clone(), malformed[31].clone()
402
+
403
+ with pytest.raises(ValueError, match="splits or changes"):
404
+ record_repack_order(source, malformed)
405
+
406
+
407
+ def test_arbitrary_shared_record_map_folds_into_common_permutation() -> None:
408
+ # Start from a deliberately non-contiguous semantic partition so the test
409
+ # exercises relabeling rather than relying on identity group order.
410
+ generator = torch.Generator().manual_seed(47)
411
+ base_contexts = torch.arange(RECORDS_PER_EXPERT).repeat_interleave(32)
412
+ base_contexts = base_contexts[torch.randperm(base_contexts.numel(), generator=generator)]
413
+ donors = (7, 2)
414
+ recipients = (19, 11)
415
+ order = rate_transfer_record_order(donors, recipients)
416
+ relabeled = relabel_block_contexts_for_record_order(base_contexts, order)
417
+ importance = importance_group_order(relabeled, R2)
418
+ ordered_semantic_records = base_contexts.index_select(0, importance).reshape(
419
+ RECORDS_PER_EXPERT, 32
420
+ )[:, 0]
421
+
422
+ assert order[:2] == donors
423
+ assert order[-2:] == tuple(reversed(recipients))
424
+ assert ordered_semantic_records.tolist() == list(order)
425
+
426
+ storage = storage_group_order(relabeled, R2)
427
+ physical_records = base_contexts.index_select(0, storage).reshape(
428
+ RECORDS_PER_EXPERT, 32
429
+ )[:, 0]
430
+ assert list(zip(physical_records[0:4:2].tolist(), physical_records[1:4:2].tolist())) == list(
431
+ zip(donors, recipients, strict=True)
432
+ )
433
+
434
+
435
+ @pytest.mark.parametrize(
436
+ "donors,recipients,middle,error",
437
+ [
438
+ ((1,), (), None, "counts must match"),
439
+ ((1,), (1,), None, "unique and disjoint"),
440
+ ((24,), (1,), None, "record IDs"),
441
+ ((1,), (2,), tuple(range(21)), "middle_records"),
442
+ ],
443
+ )
444
+ def test_arbitrary_record_map_rejects_malformed_assignments(
445
+ donors, recipients, middle, error
446
+ ) -> None:
447
+ with pytest.raises(ValueError, match=error):
448
+ rate_transfer_record_order(
449
+ donors, recipients, middle_records=middle
450
+ )
451
+
452
+
453
+ def test_record_repack_moves_matching_scale_or_weight_axis() -> None:
454
+ order = torch.arange(RECORDS_PER_EXPERT - 1, -1, -1)
455
+ channels = expand_record_order(order)
456
+ vector = torch.arange(INTERMEDIATE_CHANNELS)
457
+ matrix = vector.repeat(3, 1)
458
+
459
+ torch.testing.assert_close(repack_rate_axis(vector, order, 0), vector[channels])
460
+ torch.testing.assert_close(
461
+ repack_rate_axis(matrix, order, 1), matrix.index_select(1, channels)
462
+ )
463
+
464
+
465
+ def test_coupled_permutation_preserves_situ_expert_function() -> None:
466
+ generator = torch.Generator().manual_seed(300)
467
+ hidden = 7
468
+ intermediate = 64
469
+ inputs = torch.randn(5, hidden, dtype=torch.float64, generator=generator)
470
+ w1 = torch.randn(intermediate, hidden, dtype=torch.float64, generator=generator)
471
+ w3 = torch.randn(intermediate, hidden, dtype=torch.float64, generator=generator)
472
+ w2 = torch.randn(hidden, intermediate, dtype=torch.float64, generator=generator)
473
+ permutation = torch.randperm(intermediate, generator=generator)
474
+
475
+ reference_middle = situ(F.linear(inputs, w1), F.linear(inputs, w3))
476
+ reference = F.linear(reference_middle, w2)
477
+ permuted_w1, permuted_w3, permuted_w2 = coupled_intermediate_permutation(
478
+ w1, w3, w2, permutation
479
+ )
480
+ permuted_middle = situ(
481
+ F.linear(inputs, permuted_w1), F.linear(inputs, permuted_w3)
482
+ )
483
+ actual = F.linear(permuted_middle, permuted_w2)
484
+
485
+ torch.testing.assert_close(permuted_middle, reference_middle[:, permutation])
486
+ torch.testing.assert_close(actual, reference, atol=1e-12, rtol=1e-12)
reproduction/closure/patches/kquant/changed-files/tests/test_sqg_e4m3.py ADDED
@@ -0,0 +1,236 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from __future__ import annotations
2
+
3
+ import hashlib
4
+
5
+ import pytest
6
+ import torch
7
+
8
+ from kquant.exl3_reference import (
9
+ CODEBOOK_SQG_XOR_CHEB_T12,
10
+ CODEBOOK_SQG_CHEB_NORMAL_E4M3,
11
+ CODEBOOK_SQG_CHEB,
12
+ CODEBOOK_SQG_NORMAL_E4M3,
13
+ decode_qsrt_regularized_weight,
14
+ decode_regularized_weight,
15
+ )
16
+ from kquant.sqg_e4m3 import (
17
+ sqg_xor_cheb_t12_bytes,
18
+ sqg_xor_cheb_t12_rank_lut_bytes,
19
+ sqg_xor_rank_permutation,
20
+ sqg_cheb_normal_e4m3_bytes,
21
+ sqg_cheb_normal_rank_e4m3_bytes,
22
+ sqg_codebook_bytes,
23
+ sqg_e4m3_bytes,
24
+ sqg_e4m3_bytes_from_rank_lut,
25
+ sqg_e4m3_codebook,
26
+ sqg_e4m3_codebook_from_rank_lut,
27
+ sqg_k2_eight_stratum_rank_permutation,
28
+ sqg_rank_permutation,
29
+ )
30
+
31
+
32
+ _SQG_XOR_CHEB_T12_SHA256 = {
33
+ "t12": "cca11fe5744c9c93a34f4217f342fbc0f74ecc8a007c076582424a505fc9da5e",
34
+ 2: "62027916386245a84c86156a0a08b6cf07e41548871af0e56fb40780558f6293",
35
+ 3: "afe7b3633e7d243b00b379b18ec4dca573722b3727cafef47fcb6470d7e7e6c9",
36
+ 4: "5a9620f0c4d8f0a60d0b6fbea921dcecbd193e6febf31043aaa6403c20389c2f",
37
+ 5: "a1caf5572c67d4face423478f423e1ed6149a8c920be5c28d4702946c93cae2f",
38
+ 6: "8e0edc92e20eb92f5287dbdadc8e870fc500fc03c5eed996cae0781d197ebcb0",
39
+ }
40
+
41
+
42
+ def _sha256(tensor: torch.Tensor) -> str:
43
+ return hashlib.sha256(tensor.contiguous().numpy().tobytes()).hexdigest()
44
+
45
+
46
+ def test_primary_sqg_xor_cheb_t12_matches_runtime_contract() -> None:
47
+ table = sqg_xor_cheb_t12_rank_lut_bytes()
48
+ assert table.dtype == torch.uint8
49
+ assert table.shape == (1 << 12,)
50
+ assert _sha256(table) == _SQG_XOR_CHEB_T12_SHA256["t12"]
51
+
52
+
53
+ @pytest.mark.parametrize("bits", range(2, 7))
54
+ def test_primary_sqg_xor_cheb_t12_graph_and_labels_match_runtime_contract(
55
+ bits: int,
56
+ ) -> None:
57
+ ranks = sqg_xor_rank_permutation(bits)
58
+ labels = sqg_xor_cheb_t12_bytes(bits)
59
+ width = 16 - bits
60
+ strata = (ranks >> width).reshape(1 << width, 1 << bits)
61
+
62
+ assert torch.equal(torch.sort(ranks).values, torch.arange(1 << 16))
63
+ assert torch.equal(
64
+ torch.sort(strata, dim=1).values,
65
+ torch.arange(1 << bits).expand_as(strata),
66
+ )
67
+ assert torch.equal(labels, sqg_xor_cheb_t12_rank_lut_bytes()[ranks >> 4])
68
+ assert torch.equal(labels, sqg_codebook_bytes(bits, CODEBOOK_SQG_XOR_CHEB_T12))
69
+ assert bool(torch.isfinite(labels.view(torch.float8_e4m3fn).float()).all())
70
+ assert not bool(((labels & 0x7F) == 0).logical_and(labels != 0).any())
71
+ assert _sha256(labels) == _SQG_XOR_CHEB_T12_SHA256[bits]
72
+
73
+
74
+ @pytest.mark.parametrize("bits", range(2, 7))
75
+ def test_sqg_preprojection_mapping_is_a_permutation(bits: int) -> None:
76
+ ranks = sqg_rank_permutation(bits)
77
+ assert ranks.dtype == torch.int64
78
+ assert ranks.shape == (1 << 16,)
79
+ assert torch.equal(torch.sort(ranks).values, torch.arange(1 << 16))
80
+
81
+
82
+ @pytest.mark.parametrize("bits", range(2, 7))
83
+ def test_sqg_codebook_round_trips_exact_e4m3(bits: int) -> None:
84
+ raw = sqg_e4m3_bytes(bits, "normal")
85
+ codebook = sqg_e4m3_codebook(bits, "normal")
86
+ assert raw.dtype == torch.uint8
87
+ assert codebook.dtype == torch.float16
88
+ assert raw.shape == codebook.shape == (1 << 16,)
89
+ assert torch.equal(codebook.to(torch.float8_e4m3fn).view(torch.uint8), raw)
90
+ assert bool(torch.isfinite(codebook).all())
91
+
92
+
93
+ @pytest.mark.parametrize("bits", range(2, 7))
94
+ def test_sqg_each_state_spans_all_coarse_strata(bits: int) -> None:
95
+ ranks = sqg_rank_permutation(bits)
96
+ width = 16 - bits
97
+ strata = (ranks >> width).reshape(1 << width, 1 << bits)
98
+ expected = torch.arange(1 << bits).expand_as(strata)
99
+ assert torch.equal(torch.sort(strata, dim=1).values, expected)
100
+
101
+
102
+ @pytest.mark.parametrize("bits", range(2, 7))
103
+ def test_shared_rank_lut_preserves_one_graph_for_every_rate(bits: int) -> None:
104
+ rank_lut = torch.arange(1 << 16, dtype=torch.int64).remainder(126).to(torch.uint8)
105
+ raw = sqg_e4m3_bytes_from_rank_lut(bits, rank_lut)
106
+ expected = rank_lut.index_select(0, sqg_rank_permutation(bits))
107
+ assert torch.equal(raw, expected)
108
+ assert torch.equal(
109
+ sqg_e4m3_codebook_from_rank_lut(bits, rank_lut)
110
+ .to(torch.float8_e4m3fn)
111
+ .view(torch.uint8),
112
+ expected,
113
+ )
114
+
115
+
116
+ def test_shared_rank_lut_rejects_nonfinite_e4m3() -> None:
117
+ rank_lut = torch.zeros(1 << 16, dtype=torch.uint8)
118
+ rank_lut[0] = 0x7F
119
+ with pytest.raises(ValueError, match="finite E4M3"):
120
+ sqg_e4m3_bytes_from_rank_lut(2, rank_lut)
121
+
122
+
123
+ @pytest.mark.parametrize("bits", range(2, 7))
124
+ def test_sqg_cheb_normal_named_codebook_uses_exact_shared_rank_law(bits: int) -> None:
125
+ expected = sqg_cheb_normal_rank_e4m3_bytes().index_select(
126
+ 0, sqg_rank_permutation(bits)
127
+ )
128
+ assert torch.equal(sqg_cheb_normal_e4m3_bytes(bits), expected)
129
+ assert torch.equal(
130
+ sqg_codebook_bytes(bits, CODEBOOK_SQG_CHEB_NORMAL_E4M3), expected
131
+ )
132
+ assert not torch.equal(
133
+ expected, sqg_codebook_bytes(bits, CODEBOOK_SQG_NORMAL_E4M3)
134
+ )
135
+
136
+
137
+ @pytest.mark.parametrize("bits", range(2, 7))
138
+ @pytest.mark.parametrize("rate_axis", ("k", "n"))
139
+ def test_w2_k2_q8h4_profile_changes_only_k_axis_k2(
140
+ bits: int, rate_axis: str
141
+ ) -> None:
142
+ actual = sqg_codebook_bytes(
143
+ bits,
144
+ CODEBOOK_SQG_CHEB,
145
+ rate_axis=rate_axis,
146
+ )
147
+ rank_lut = sqg_cheb_normal_rank_e4m3_bytes()
148
+ ranks = (
149
+ sqg_k2_eight_stratum_rank_permutation(4)
150
+ if bits == 2 and rate_axis == "k"
151
+ else sqg_rank_permutation(bits)
152
+ )
153
+ assert torch.equal(actual, rank_lut.index_select(0, ranks))
154
+ if bits == 2 and rate_axis == "k":
155
+ assert not torch.equal(
156
+ actual, sqg_codebook_bytes(bits, CODEBOOK_SQG_CHEB_NORMAL_E4M3)
157
+ )
158
+
159
+
160
+ def test_w2_k2_q8h4_profile_requires_rate_axis() -> None:
161
+ with pytest.raises(ValueError, match="requires rate_axis"):
162
+ sqg_codebook_bytes(2, CODEBOOK_SQG_CHEB)
163
+
164
+
165
+ def test_reference_decoder_accepts_custom_codebook() -> None:
166
+ states = torch.arange(256, dtype=torch.int16).reshape(1, 1, 256)
167
+ codebook = sqg_e4m3_codebook(3, "normal")
168
+ decoded = decode_regularized_weight(
169
+ states, codebook_values=codebook
170
+ )
171
+ assert decoded.shape == (16, 16)
172
+ assert torch.equal(
173
+ torch.sort(decoded.flatten()).values,
174
+ torch.sort(codebook[:256].float()).values,
175
+ )
176
+
177
+
178
+ @pytest.mark.parametrize("rate_axis", ("k", "n"))
179
+ def test_reference_decoder_applies_rate_specific_sqg_tables(rate_axis: str) -> None:
180
+ states = torch.arange(3 * 3 * 256, dtype=torch.int32).to(torch.int16).reshape(
181
+ 3, 3, 256
182
+ )
183
+ tile_bits = (2, 3, 4)
184
+ decoded = decode_qsrt_regularized_weight(
185
+ states,
186
+ rate_axis=rate_axis,
187
+ tile_bits=tile_bits,
188
+ codebook=CODEBOOK_SQG_NORMAL_E4M3,
189
+ )
190
+ axis = 0 if rate_axis == "k" else 1
191
+ pieces = []
192
+ for tile, bits in enumerate(tile_bits):
193
+ selected = states.narrow(axis, tile, 1)
194
+ pieces.append(
195
+ decode_regularized_weight(
196
+ selected,
197
+ codebook=CODEBOOK_SQG_NORMAL_E4M3,
198
+ bits=bits,
199
+ )
200
+ )
201
+ expected = torch.cat(pieces, dim=0 if rate_axis == "k" else 1)
202
+ assert torch.equal(decoded, expected)
203
+
204
+
205
+ def test_reference_decoder_applies_w2_only_k2_q8h4_profile() -> None:
206
+ states = torch.arange(3 * 3 * 256, dtype=torch.int32).to(torch.int16).reshape(
207
+ 3, 3, 256
208
+ )
209
+ tile_bits = (2, 3, 4)
210
+ down = decode_qsrt_regularized_weight(
211
+ states,
212
+ rate_axis="k",
213
+ tile_bits=tile_bits,
214
+ codebook=CODEBOOK_SQG_CHEB,
215
+ )
216
+ upstream = decode_qsrt_regularized_weight(
217
+ states,
218
+ rate_axis="n",
219
+ tile_bits=tile_bits,
220
+ codebook=CODEBOOK_SQG_CHEB,
221
+ )
222
+ native_down = decode_qsrt_regularized_weight(
223
+ states,
224
+ rate_axis="k",
225
+ tile_bits=tile_bits,
226
+ codebook=CODEBOOK_SQG_CHEB_NORMAL_E4M3,
227
+ )
228
+ native_upstream = decode_qsrt_regularized_weight(
229
+ states,
230
+ rate_axis="n",
231
+ tile_bits=tile_bits,
232
+ codebook=CODEBOOK_SQG_CHEB_NORMAL_E4M3,
233
+ )
234
+ assert not torch.equal(down[:16], native_down[:16])
235
+ assert torch.equal(down[16:], native_down[16:])
236
+ assert torch.equal(upstream, native_upstream)
reproduction/closure/patches/kquant/changed-files/tests/test_sqg_quantizer.py ADDED
@@ -0,0 +1,262 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from __future__ import annotations
2
+
3
+ import hashlib
4
+ from pathlib import Path
5
+ from types import SimpleNamespace
6
+
7
+ import pytest
8
+ import torch
9
+
10
+ import kquant.sqg_quantizer as sqg_quantizer
11
+ from kquant.exl3_reference import reconstruct_trellis_states
12
+ from kquant.sqg_quantizer import install_sqg_quantizer
13
+ from kquant.sqg_e4m3 import sqg_xor_cheb_t12_bytes
14
+
15
+
16
+ def _sealed_extension(
17
+ tmp_path: Path,
18
+ monkeypatch: pytest.MonkeyPatch,
19
+ *,
20
+ filename: str = "kquant_sqg_quantize_ext_v22.so",
21
+ ) -> tuple[Path, SimpleNamespace]:
22
+ path = tmp_path / filename
23
+ payload = b"sealed-sqg-extension-test-double"
24
+ path.write_bytes(payload)
25
+ module = SimpleNamespace(
26
+ __file__=str(path),
27
+ quantize_tiles_procedural=lambda *_args: None,
28
+ quantize_tiles_sqg=lambda *_args: None,
29
+ )
30
+ monkeypatch.setenv("KQUANT_SQG_REQUIRE_PREBUILT", "1")
31
+ monkeypatch.setenv("KQUANT_SQG_EXTENSION_PATH", str(path))
32
+ monkeypatch.setenv(
33
+ "KQUANT_SQG_EXTENSION_SHA256", hashlib.sha256(payload).hexdigest()
34
+ )
35
+ return path, module
36
+
37
+
38
+ def test_required_prebuilt_extension_uses_exact_path_and_never_jit_builds(
39
+ tmp_path: Path, monkeypatch: pytest.MonkeyPatch
40
+ ) -> None:
41
+ path, module = _sealed_extension(tmp_path, monkeypatch)
42
+ imported: list[Path] = []
43
+
44
+ def fake_import(actual: Path):
45
+ imported.append(actual)
46
+ return module
47
+
48
+ monkeypatch.setattr(sqg_quantizer, "_import_prebuilt_extension", fake_import)
49
+ monkeypatch.setattr(
50
+ sqg_quantizer,
51
+ "load",
52
+ lambda **_kwargs: pytest.fail("JIT builder must not run in prebuilt mode"),
53
+ )
54
+ sqg_quantizer._extension.cache_clear()
55
+ try:
56
+ assert sqg_quantizer._extension() is module
57
+ assert imported == [path.resolve()]
58
+ finally:
59
+ sqg_quantizer._extension.cache_clear()
60
+
61
+
62
+ def test_required_prebuilt_extension_rejects_wrong_filename_before_import_or_jit(
63
+ tmp_path: Path, monkeypatch: pytest.MonkeyPatch
64
+ ) -> None:
65
+ _sealed_extension(tmp_path, monkeypatch, filename="foreign_extension.so")
66
+ monkeypatch.setattr(
67
+ sqg_quantizer,
68
+ "_import_prebuilt_extension",
69
+ lambda _path: pytest.fail("foreign extension must not be imported"),
70
+ )
71
+ monkeypatch.setattr(
72
+ sqg_quantizer,
73
+ "load",
74
+ lambda **_kwargs: pytest.fail("JIT builder must not run in prebuilt mode"),
75
+ )
76
+ sqg_quantizer._extension.cache_clear()
77
+ try:
78
+ with pytest.raises(ValueError, match="filename must identify"):
79
+ sqg_quantizer._extension()
80
+ finally:
81
+ sqg_quantizer._extension.cache_clear()
82
+
83
+
84
+ def test_required_prebuilt_extension_rejects_hash_mismatch_before_import_or_jit(
85
+ tmp_path: Path, monkeypatch: pytest.MonkeyPatch
86
+ ) -> None:
87
+ _sealed_extension(tmp_path, monkeypatch)
88
+ monkeypatch.setenv("KQUANT_SQG_EXTENSION_SHA256", "0" * 64)
89
+ monkeypatch.setattr(
90
+ sqg_quantizer,
91
+ "_import_prebuilt_extension",
92
+ lambda _path: pytest.fail("mismatched extension must not be imported"),
93
+ )
94
+ monkeypatch.setattr(
95
+ sqg_quantizer,
96
+ "load",
97
+ lambda **_kwargs: pytest.fail("JIT builder must not run in prebuilt mode"),
98
+ )
99
+ sqg_quantizer._extension.cache_clear()
100
+ try:
101
+ with pytest.raises(RuntimeError, match="SHA256 mismatch"):
102
+ sqg_quantizer._extension()
103
+ finally:
104
+ sqg_quantizer._extension.cache_clear()
105
+
106
+
107
+ @pytest.mark.parametrize(
108
+ ("missing", "message"),
109
+ (
110
+ ("KQUANT_SQG_EXTENSION_PATH", "are both required"),
111
+ ("KQUANT_SQG_EXTENSION_SHA256", "are both required"),
112
+ ),
113
+ )
114
+ def test_required_prebuilt_extension_rejects_partial_binding_without_jit(
115
+ tmp_path: Path,
116
+ monkeypatch: pytest.MonkeyPatch,
117
+ missing: str,
118
+ message: str,
119
+ ) -> None:
120
+ _sealed_extension(tmp_path, monkeypatch)
121
+ monkeypatch.delenv(missing)
122
+ monkeypatch.setattr(
123
+ sqg_quantizer,
124
+ "load",
125
+ lambda **_kwargs: pytest.fail("JIT builder must not run in prebuilt mode"),
126
+ )
127
+ sqg_quantizer._extension.cache_clear()
128
+ try:
129
+ with pytest.raises(RuntimeError, match=message):
130
+ sqg_quantizer._extension()
131
+ finally:
132
+ sqg_quantizer._extension.cache_clear()
133
+
134
+
135
+ def test_rate_specific_none_dispatches_to_kquant_mcg(monkeypatch) -> None:
136
+ calls: list[tuple[torch.Tensor, dict]] = []
137
+ procedural_calls: list[tuple] = []
138
+
139
+ def original(tiles: torch.Tensor, args: dict):
140
+ calls.append((tiles, args))
141
+ return "upstream"
142
+
143
+ def procedural(*args):
144
+ procedural_calls.append(args)
145
+
146
+ monkeypatch.setattr(
147
+ sqg_quantizer,
148
+ "_sqg_temp_buffers",
149
+ lambda _device, _bits: (torch.empty(0), torch.empty(0)),
150
+ )
151
+ monkeypatch.setattr(
152
+ sqg_quantizer,
153
+ "_extension",
154
+ lambda: SimpleNamespace(quantize_tiles_procedural=procedural),
155
+ )
156
+
157
+ module = SimpleNamespace(quantize_tiles=original)
158
+ install_sqg_quantizer(module)
159
+ tiles = torch.zeros((1, 256), dtype=torch.float32)
160
+ result = module.quantize_tiles(
161
+ tiles,
162
+ {
163
+ "K": 2,
164
+ "devices": ["cuda:0"],
165
+ "sqg_e4m3_luts_by_bits": {2: None, 3: None, 4: None},
166
+ },
167
+ )
168
+
169
+ assert all(isinstance(tensor, torch.Tensor) for tensor in result)
170
+ assert not calls
171
+ assert len(procedural_calls) == 1
172
+ assert procedural_calls[0][5:] == (2, 1, 128)
173
+
174
+
175
+ def test_sqg_luts_are_transposed_by_predecessor_for_vector_loads(
176
+ monkeypatch,
177
+ ) -> None:
178
+ calls: list[tuple] = []
179
+
180
+ monkeypatch.setattr(
181
+ sqg_quantizer,
182
+ "_sqg_temp_buffers",
183
+ lambda _device, _bits: (torch.empty(0), torch.empty(0)),
184
+ )
185
+ monkeypatch.setattr(
186
+ sqg_quantizer,
187
+ "_extension",
188
+ lambda: SimpleNamespace(quantize_tiles_sqg=lambda *args: calls.append(args)),
189
+ )
190
+
191
+ module = SimpleNamespace(quantize_tiles=lambda *_args: "upstream")
192
+ install_sqg_quantizer(module)
193
+ tiles = torch.zeros((1, 256), dtype=torch.float32)
194
+ for bits in (2, 3, 4):
195
+ raw = torch.arange(65536, dtype=torch.int64).to(torch.uint8)
196
+ module.quantize_tiles(
197
+ tiles,
198
+ {
199
+ "K": bits,
200
+ "devices": ["cuda:0"],
201
+ "sqg_e4m3_lut": raw,
202
+ },
203
+ )
204
+ actual = calls[-1][5]
205
+ predecessors = 1 << bits
206
+ out_edge_pairs = (65536 >> bits) // 2
207
+ expected = (
208
+ raw.reshape(predecessors, out_edge_pairs, 2)
209
+ .permute(1, 0, 2)
210
+ .contiguous()
211
+ .reshape(-1)
212
+ )
213
+ assert torch.equal(actual, expected)
214
+ assert calls[-1][6:] == (bits, 128)
215
+
216
+
217
+ @pytest.mark.parametrize("bits", [5, 6])
218
+ def test_k5_k6_sqg_luts_remain_in_direct_state_order(
219
+ monkeypatch, bits: int
220
+ ) -> None:
221
+ calls: list[tuple] = []
222
+ monkeypatch.setattr(
223
+ sqg_quantizer,
224
+ "_sqg_temp_buffers",
225
+ lambda _device, _bits: (torch.empty(0), torch.empty(0)),
226
+ )
227
+ monkeypatch.setattr(
228
+ sqg_quantizer,
229
+ "_extension",
230
+ lambda: SimpleNamespace(quantize_tiles_sqg=lambda *args: calls.append(args)),
231
+ )
232
+ module = SimpleNamespace(quantize_tiles=lambda *_args: "upstream")
233
+ install_sqg_quantizer(module)
234
+ raw = torch.arange(65536, dtype=torch.int64).to(torch.uint8)
235
+ module.quantize_tiles(
236
+ torch.zeros((1, 256), dtype=torch.float32),
237
+ {"K": bits, "devices": ["cuda:0"], "sqg_e4m3_lut": raw},
238
+ )
239
+ assert torch.equal(calls[-1][5], raw)
240
+ assert calls[-1][6:] == (bits, 128)
241
+
242
+
243
+ @pytest.mark.skipif(not torch.cuda.is_available(), reason="CUDA is unavailable")
244
+ @pytest.mark.parametrize("bits", range(2, 7))
245
+ def test_sqg_quantizer_keeps_saturated_cost_paths_closed(bits: int) -> None:
246
+ module = SimpleNamespace(quantize_tiles=lambda *_args: "upstream")
247
+ install_sqg_quantizer(module)
248
+ tiles = torch.full((2, 256), 1000.0, dtype=torch.float32, device="cuda")
249
+
250
+ _output, states = module.quantize_tiles(
251
+ tiles,
252
+ {
253
+ "K": bits,
254
+ "devices": ["cuda:0"],
255
+ "sqg_e4m3_lut": sqg_xor_cheb_t12_bytes(bits),
256
+ "tailbite_context": 128,
257
+ },
258
+ )
259
+
260
+ edges = states.to(torch.int64) & ((1 << bits) - 1)
261
+ expected = reconstruct_trellis_states(edges, bits)
262
+ assert torch.equal(states, expected)
reproduction/closure/patches/kquant/changes.patch ADDED
@@ -0,0 +1,1386 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ diff --git a/kquant/candidate_hessian.py b/kquant/candidate_hessian.py
2
+ index 36f5f30..6603799 100644
3
+ --- a/kquant/candidate_hessian.py
4
+ +++ b/kquant/candidate_hessian.py
5
+ @@ -92,8 +92,10 @@ def weighted_covariance(
6
+ accumulator = torch.zeros(
7
+ (dimension, dimension), dtype=torch.float32, device=device
8
+ )
9
+ - denominator = float(weights.double().sum())
10
+ - if not math.isfinite(denominator) or denominator <= 0:
11
+ + denominator_tensor = weights.to(device=device, dtype=torch.float64).sum()
12
+ + if not bool(torch.isfinite(denominator_tensor)) or not bool(
13
+ + denominator_tensor > 0
14
+ + ):
15
+ raise ValueError("covariance weights must have a positive finite sum")
16
+ for begin in range(0, int(rows.shape[0]), chunk_rows):
17
+ values = rows[begin : begin + chunk_rows].to(
18
+ @@ -103,8 +105,9 @@ def weighted_covariance(
19
+ device=device, dtype=torch.float32
20
+ )
21
+ accumulator.addmm_(values.T, values * local_weights[:, None])
22
+ - covariance = accumulator.div_(denominator)
23
+ + covariance = accumulator.div_(denominator_tensor.to(torch.float32))
24
+ covariance = ((covariance + covariance.T) * 0.5).contiguous()
25
+ + denominator = float(denominator_tensor)
26
+ if return_cpu:
27
+ covariance = covariance.cpu()
28
+ if not torch.all(torch.isfinite(covariance)):
29
+ @@ -115,13 +118,23 @@ def weighted_covariance(
30
+ def shrink_covariance(
31
+ global_covariance: torch.Tensor,
32
+ local_covariance: torch.Tensor,
33
+ - alpha: float,
34
+ + alpha: float | torch.Tensor,
35
+ ) -> torch.Tensor:
36
+ """Convexly shrink a low-support local covariance toward a global one."""
37
+
38
+ - alpha = float(alpha)
39
+ - if not math.isfinite(alpha) or not 0.0 <= alpha <= 1.0:
40
+ - raise ValueError("alpha must be finite and in [0, 1]")
41
+ + if isinstance(alpha, torch.Tensor):
42
+ + if alpha.numel() != 1 or not bool(torch.isfinite(alpha)) or not bool(
43
+ + (alpha >= 0) & (alpha <= 1)
44
+ + ):
45
+ + raise ValueError("alpha must be a finite scalar in [0, 1]")
46
+ + blend_weight: float | torch.Tensor = alpha.to(
47
+ + device=global_covariance.device, dtype=torch.float32
48
+ + )
49
+ + else:
50
+ + alpha_value = float(alpha)
51
+ + if not math.isfinite(alpha_value) or not 0.0 <= alpha_value <= 1.0:
52
+ + raise ValueError("alpha must be finite and in [0, 1]")
53
+ + blend_weight = alpha_value
54
+ if (
55
+ global_covariance.ndim != 2
56
+ or global_covariance.shape[0] != global_covariance.shape[1]
57
+ @@ -133,7 +146,7 @@ def shrink_covariance(
58
+ ):
59
+ raise ValueError("covariances must be finite")
60
+ blended = torch.lerp(
61
+ - global_covariance.float(), local_covariance.float(), alpha
62
+ + global_covariance.float(), local_covariance.float(), blend_weight
63
+ )
64
+ return ((blended + blended.T) * 0.5).contiguous()
65
+
66
+ @@ -141,6 +154,17 @@ def shrink_covariance(
67
+ def weighted_effective_sample_size(weights: torch.Tensor) -> float:
68
+ """Return Kish effective sample size for nonnegative row weights."""
69
+
70
+ + if weights.ndim != 1 or not weights.numel():
71
+ + raise ValueError("weights must be a nonempty vector")
72
+ + if not torch.all(torch.isfinite(weights)) or torch.any(weights < 0):
73
+ + raise ValueError("weights must be finite and nonnegative")
74
+ + value = _weighted_effective_sample_size_tensor(weights)
75
+ + return float(value)
76
+ +
77
+ +
78
+ +def _weighted_effective_sample_size_tensor(weights: torch.Tensor) -> torch.Tensor:
79
+ + """Kish support as a scalar tensor on the input numerical device."""
80
+ +
81
+ if weights.ndim != 1 or not weights.numel():
82
+ raise ValueError("weights must be a nonempty vector")
83
+ if not torch.all(torch.isfinite(weights)) or torch.any(weights < 0):
84
+ @@ -150,7 +174,7 @@ def weighted_effective_sample_size(weights: torch.Tensor) -> float:
85
+ squared_total = weights64.square().sum()
86
+ if total <= 0 or squared_total <= 0:
87
+ raise ValueError("weights must have positive effective support")
88
+ - return float(total.square() / squared_total)
89
+ + return total.square() / squared_total
90
+
91
+
92
+ def adaptive_identity_shrinkage(
93
+ @@ -180,7 +204,7 @@ def adaptive_identity_shrinkage(
94
+ if not torch.all(torch.isfinite(local_covariance)):
95
+ raise ValueError("local covariance must be finite")
96
+
97
+ - effective_rows = weighted_effective_sample_size(weights)
98
+ + effective_rows_tensor = _weighted_effective_sample_size_tensor(weights)
99
+ dimension = int(local_covariance.shape[0])
100
+ local64 = local_covariance.double()
101
+ local_trace = torch.trace(local64)
102
+ @@ -189,24 +213,34 @@ def adaptive_identity_shrinkage(
103
+
104
+ mu = local_trace / dimension
105
+ mean_square = local64.square().mean()
106
+ - denominator = (effective_rows + 1.0) * (
107
+ + denominator = (effective_rows_tensor + 1.0) * (
108
+ mean_square - mu.square() / dimension
109
+ )
110
+ - if denominator <= 0:
111
+ - oas_shrinkage = 1.0
112
+ - else:
113
+ - oas_shrinkage = min(
114
+ - 1.0,
115
+ - max(0.0, float((mean_square + mu.square()) / denominator)),
116
+ - )
117
+ - local_alpha = min(max_local_alpha, 1.0 - oas_shrinkage)
118
+ - identity_scale = float(mu)
119
+ + raw_oas = (mean_square + mu.square()) / denominator.clamp_min(
120
+ + torch.finfo(local64.dtype).tiny
121
+ + )
122
+ + oas_shrinkage_tensor = torch.where(
123
+ + denominator <= 0,
124
+ + torch.ones_like(raw_oas),
125
+ + raw_oas.clamp(0.0, 1.0),
126
+ + )
127
+ + local_alpha_tensor = torch.minimum(
128
+ + torch.as_tensor(max_local_alpha, device=local64.device, dtype=local64.dtype),
129
+ + 1.0 - oas_shrinkage_tensor,
130
+ + )
131
+ scaled_identity = torch.eye(
132
+ dimension,
133
+ dtype=torch.float32,
134
+ device=local_covariance.device,
135
+ - ).mul_(identity_scale)
136
+ - blended = shrink_covariance(scaled_identity, local_covariance, local_alpha)
137
+ + ).mul_(mu.to(dtype=torch.float32))
138
+ + blended = shrink_covariance(
139
+ + scaled_identity, local_covariance, local_alpha_tensor.to(torch.float32)
140
+ + )
141
+ + # Evidence scalars are detached only after the numerical result is frozen.
142
+ + effective_rows = float(effective_rows_tensor)
143
+ + oas_shrinkage = float(oas_shrinkage_tensor)
144
+ + local_alpha = float(local_alpha_tensor)
145
+ + identity_scale = float(mu)
146
+ return blended, {
147
+ "effective_sample_size": effective_rows,
148
+ "oas_shrinkage": oas_shrinkage,
149
+ diff --git a/kquant/csrc/qsrt_quantize_tiles_kernel.cuh b/kquant/csrc/qsrt_quantize_tiles_kernel.cuh
150
+ index 76febdd..f4299d1 100644
151
+ --- a/kquant/csrc/qsrt_quantize_tiles_kernel.cuh
152
+ +++ b/kquant/csrc/qsrt_quantize_tiles_kernel.cuh
153
+ @@ -17,6 +17,9 @@
154
+ #ifndef H_INF
155
+ #define H_INF __ushort_as_half(0x7c00)
156
+ #endif
157
+ +#ifndef H_MAX_FINITE
158
+ +#define H_MAX_FINITE __ushort_as_half(0x7bff)
159
+ +#endif
160
+
161
+ template <int K, int cb>
162
+ __global__ __launch_bounds__(
163
+ @@ -121,7 +124,12 @@ void quantize_tiles_kernel
164
+ decoded2 = decode_3inst_2<cb>(out_edge_idx, out_edge_idx + 1);
165
+ }
166
+ half2 dh2 = __hsub2(decoded2, w2);
167
+ - half2 min_err2 = __hmul2(dh2, dh2);
168
+ + // Positive infinity denotes an unreachable state. Reachable path
169
+ + // costs must remain finite when their FP16 sum overflows, or
170
+ + // traceback can confuse a saturated path with an unreachable one
171
+ + // and violate the constrained cyclic boundary.
172
+ + half2 min_err2 = __hmin2(
173
+ + __hmul2(dh2, dh2), __half2half2(H_MAX_FINITE));
174
+ if (pre_state >= 0 && in_edge_idx != pre_state) min_err2 = __half2half2(H_INF);
175
+ int min_k0 = 0;
176
+ int min_k1 = 0;
177
+ @@ -165,7 +173,8 @@ void quantize_tiles_kernel
178
+ decoded2 = decode_3inst_2<cb>(state0, state0 + 1);
179
+ }
180
+ dh2 = __hsub2(decoded2, w2);
181
+ - half2 err2 = __hmul2(dh2, dh2);
182
+ + half2 err2 = __hmin2(
183
+ + __hmul2(dh2, dh2), __half2half2(H_MAX_FINITE));
184
+ if (pre_state >= 0 && in_edge_idx != pre_state) err2 = __half2half2(H_INF);
185
+ const unsigned less = __hlt2_mask(err2, min_err2);
186
+ min_err2 = __hmin2(err2, min_err2);
187
+ @@ -253,7 +262,13 @@ void quantize_tiles_kernel
188
+ decoded2 = decode_3inst_2<cb>(out_edge_idx, out_edge_idx + 1);
189
+ }
190
+ half2 dh2 = __hsub2(decoded2, w2);
191
+ - half2 min_err2 = __hfma2(dh2, dh2, __half2half2(temp_costs_inc[in_edge_idx]));
192
+ + half predecessor_cost = temp_costs_inc[in_edge_idx];
193
+ + half2 min_err2 = __heq(predecessor_cost, H_INF)
194
+ + ? __half2half2(H_INF)
195
+ + : __hmin2(
196
+ + __hfma2(
197
+ + dh2, dh2, __half2half2(predecessor_cost)),
198
+ + __half2half2(H_MAX_FINITE));
199
+ int min_k0 = 0;
200
+ int min_k1 = 0;
201
+
202
+ @@ -296,7 +311,13 @@ void quantize_tiles_kernel
203
+ decoded2 = decode_3inst_2<cb>(state0, state0 + 1);
204
+ }
205
+ dh2 = __hsub2(decoded2, w2);
206
+ - half2 err2 = __hfma2(dh2, dh2, __half2half2(temp_costs_inc[in_edge_idx]));
207
+ + predecessor_cost = temp_costs_inc[in_edge_idx];
208
+ + half2 err2 = __heq(predecessor_cost, H_INF)
209
+ + ? __half2half2(H_INF)
210
+ + : __hmin2(
211
+ + __hfma2(
212
+ + dh2, dh2, __half2half2(predecessor_cost)),
213
+ + __half2half2(H_MAX_FINITE));
214
+ const unsigned less = __hlt2_mask(err2, min_err2);
215
+ min_err2 = __hmin2(err2, min_err2);
216
+ if (less & 0xffffu) min_k0 = k;
217
+ diff --git a/kquant/csrc/sqg_quantize.cu b/kquant/csrc/sqg_quantize.cu
218
+ index 42dcd88..e51210e 100644
219
+ --- a/kquant/csrc/sqg_quantize.cu
220
+ +++ b/kquant/csrc/sqg_quantize.cu
221
+ @@ -187,7 +187,7 @@ void quantize_tiles_sqg_cuda(
222
+ "output_indices shape mismatch");
223
+ TORCH_CHECK(output_indices.scalar_type() == at::kShort,
224
+ "output_indices must be int16");
225
+ - TORCH_CHECK(K >= 2 && K <= 4, "SQG validation kernel supports K2--K4");
226
+ + TORCH_CHECK(K >= 2 && K <= 6, "SQG validation kernel supports K2--K6");
227
+ TORCH_CHECK(tailbite_context >= 1 && tailbite_context <= 128,
228
+ "tailbite_context must be in 1..128");
229
+ TORCH_CHECK(codebook.is_cuda() && codebook.device() == input_tiles.device(),
230
+ @@ -255,6 +255,22 @@ void quantize_tiles_sqg_cuda(
231
+ temp_edges.data_ptr<uint8_t>(), tiles, max_batch, shared_memory,
232
+ static_cast<int>(tailbite_context), stream);
233
+ break;
234
+ + case 5:
235
+ + launch_trellis<5, 4>(
236
+ + input_tiles.data_ptr<float>(), output_tiles.data_ptr<float>(),
237
+ + reinterpret_cast<uint16_t*>(output_indices.data_ptr<int16_t>()),
238
+ + reinterpret_cast<half*>(temp_costs.data_ptr<at::Half>()),
239
+ + temp_edges.data_ptr<uint8_t>(), tiles, max_batch, shared_memory,
240
+ + static_cast<int>(tailbite_context), stream);
241
+ + break;
242
+ + case 6:
243
+ + launch_trellis<6, 4>(
244
+ + input_tiles.data_ptr<float>(), output_tiles.data_ptr<float>(),
245
+ + reinterpret_cast<uint16_t*>(output_indices.data_ptr<int16_t>()),
246
+ + reinterpret_cast<half*>(temp_costs.data_ptr<at::Half>()),
247
+ + temp_edges.data_ptr<uint8_t>(), tiles, max_batch, shared_memory,
248
+ + static_cast<int>(tailbite_context), stream);
249
+ + break;
250
+ }
251
+ }
252
+
253
+ diff --git a/kquant/exl3_encoder_backend.py b/kquant/exl3_encoder_backend.py
254
+ index f810bf3..616b9e6 100644
255
+ --- a/kquant/exl3_encoder_backend.py
256
+ +++ b/kquant/exl3_encoder_backend.py
257
+ @@ -21,6 +21,18 @@ import threading
258
+ had_k, had_n = 128, 128
259
+ codebook_scale = 1.24371088
260
+
261
+ +# The original search used a 0.1..1.9 coarse bracket and could return 2.05
262
+ +# only because its five-point fine grid extended past the bracket. GLM-5.2
263
+ +# contains healthy tensors with a stable minimum around 3.0, so keep the cheap
264
+ +# original bracket as stage one and expand only when its upper point wins.
265
+ +G_SCALE_SEARCH_INITIAL_MIN = 0.1
266
+ +G_SCALE_SEARCH_INITIAL_MAX = 1.9
267
+ +G_SCALE_SEARCH_COARSE_STEP = 0.2
268
+ +G_SCALE_SEARCH_EXPANDED_MAX = 3.9
269
+ +G_SCALE_SEARCH_FINE_STEP = 0.075
270
+ +G_SCALE_SEARCH_HARD_CEILING = 4.05
271
+ +G_SCALE_SEARCH_CEILING_TOLERANCE = 1e-6
272
+ +
273
+ codebook_mcg_mult = 0xCBAC1FED
274
+ codebook_mul1_mult = 0x83DCD12D
275
+
276
+ @@ -319,6 +331,11 @@ def block_ldl(H: torch.Tensor, b: int, quant_args: dict, verbose: bool):
277
+ assert (n % b == 0)
278
+ m = n // b
279
+
280
+ + keep_hessian_on_device = bool(quant_args.get("keep_hessian_on_device", False))
281
+ + gpu_only_numerical_path = bool(quant_args.get("gpu_only_numerical_path", False))
282
+ + if gpu_only_numerical_path and H.device.type != "cuda":
283
+ + raise RuntimeError("GPU-only BlockLDLQ received a non-CUDA Hessian")
284
+ +
285
+ # Cholesky factorization: H = L @ L.T
286
+ # Try on GPU first
287
+ num_cholesky_retries = 0
288
+ @@ -326,12 +343,14 @@ def block_ldl(H: torch.Tensor, b: int, quant_args: dict, verbose: bool):
289
+ while True:
290
+ try:
291
+ L = torch.linalg.cholesky(H)
292
+ - # H is not needed after this, move to CPU. Then overwrite H's GPU storage with L, since we can't otherwise
293
+ - # free up that VRAM as the tensor is referenced by the parent frame
294
+ - H_cpu = H.cpu()
295
+ - H.copy_(L) # VRAM copy, tiny overhead
296
+ - L = H
297
+ - H = H_cpu
298
+ + if not keep_hessian_on_device:
299
+ + # Historical memory-saving path. Production retains both the
300
+ + # caller-owned H and its factor on CUDA so neither numerical
301
+ + # tensor crosses the host boundary.
302
+ + H_cpu = H.cpu()
303
+ + H.copy_(L) # VRAM copy, tiny overhead
304
+ + L = H
305
+ + H = H_cpu
306
+ break
307
+
308
+ except torch._C._LinAlgError as e:
309
+ @@ -346,6 +365,10 @@ def block_ldl(H: torch.Tensor, b: int, quant_args: dict, verbose: bool):
310
+ # Fall back on CPU factorization
311
+ except Exception as e:
312
+ if e.__class__.__name__ == "OutOfMemoryError" or "CUDA out of memory" in str(e) or "HIP out of memory" in str(e):
313
+ + if gpu_only_numerical_path:
314
+ + raise RuntimeError(
315
+ + "GPU-only BlockLDLQ exhausted CUDA memory; CPU fallback is forbidden"
316
+ + ) from e
317
+ retry_cpu = True
318
+ break
319
+ else:
320
+ @@ -380,7 +403,7 @@ def block_ldl(H: torch.Tensor, b: int, quant_args: dict, verbose: bool):
321
+ # Insert block identity matrices along the diagonal.
322
+ # TODO: Figure out if this is necessary. Diagonal blocks should already be identities after previous step
323
+ L_block = L.view(m, b, m, b).permute(0, 2, 1,3)
324
+ - dr = torch.arange(m)
325
+ + dr = torch.arange(m, device=L.device)
326
+ L_block[dr, dr] = torch.stack([torch.eye(b, device = L.device, dtype = H.dtype)] * m)
327
+
328
+ return L, H # , D.to(DL.device)
329
+ @@ -1585,6 +1608,43 @@ def ldlq_batched(
330
+
331
+ finalize_capture_H_mutex = threading.Lock()
332
+
333
+ +
334
+ +def _explicit_vector(
335
+ + value: torch.Tensor,
336
+ + *,
337
+ + length: int,
338
+ + name: str,
339
+ + device: torch.device,
340
+ + orientation: str,
341
+ + signs: bool = False,
342
+ +) -> torch.Tensor:
343
+ + """Validate a caller-owned regularization vector without retaining it.
344
+ +
345
+ + QSRT's original shared-input-scale hook stores the first tensor's profile
346
+ + in module-global state. Model ports that require a topology-neutral
347
+ + layer-wide vector need a deterministic, caller-owned contract instead.
348
+ + These optional vectors are cloned for each encode and never enter the
349
+ + process-global cache.
350
+ + """
351
+ +
352
+ + if not isinstance(value, torch.Tensor):
353
+ + raise TypeError(f"{name} must be a torch.Tensor")
354
+ + if value.ndim != 1 or value.numel() != length:
355
+ + raise ValueError(f"{name} must have shape ({length},)")
356
+ + vector = value.detach().to(device=device, dtype=torch.float32, copy=True)
357
+ + if not bool(torch.isfinite(vector).all()):
358
+ + raise ValueError(f"{name} must contain only finite values")
359
+ + if signs:
360
+ + if not bool((vector.abs() == 1).all()):
361
+ + raise ValueError(f"{name} must contain only -1 and +1")
362
+ + elif not bool((vector > 0).all()):
363
+ + raise ValueError(f"{name} must contain only positive values")
364
+ + if orientation == "column":
365
+ + return vector.unsqueeze(1).contiguous()
366
+ + if orientation == "row":
367
+ + return vector.unsqueeze(0).contiguous()
368
+ + raise ValueError(f"unsupported explicit-vector orientation: {orientation}")
369
+ +
370
+ def finalize_capture_H(H_data: dict, quant_args: dict, verbose: bool):
371
+ with finalize_capture_H_mutex:
372
+
373
+ @@ -1596,7 +1656,23 @@ def finalize_capture_H(H_data: dict, quant_args: dict, verbose: bool):
374
+
375
+ H = H_data["H"]
376
+ k = H.shape[0]
377
+ - su = (torch.randn(k, device = H_data["device"]).sign() + 1e-5).sign().to(torch.float).unsqueeze(1)
378
+ + explicit_input_signs = quant_args.get("input_signs")
379
+ + if explicit_input_signs is None:
380
+ + su = (
381
+ + (torch.randn(k, device=H_data["device"]).sign() + 1e-5)
382
+ + .sign()
383
+ + .to(torch.float)
384
+ + .unsqueeze(1)
385
+ + )
386
+ + else:
387
+ + su = _explicit_vector(
388
+ + explicit_input_signs,
389
+ + length=k,
390
+ + name="input_signs",
391
+ + device=H_data["device"],
392
+ + orientation="column",
393
+ + signs=True,
394
+ + )
395
+ H_data["su"] = su
396
+
397
+ return True, None, None, su, None
398
+ @@ -1608,7 +1684,28 @@ def finalize_capture_H(H_data: dict, quant_args: dict, verbose: bool):
399
+
400
+ H = H_data["H"]
401
+ if H_data["finalized"]:
402
+ - return H_data["q_fallback"], H, H_data["L"], H_data["su"], H_data["diag"]
403
+ + explicit_input_signs = quant_args.get("input_signs")
404
+ + if explicit_input_signs is not None:
405
+ + expected = _explicit_vector(
406
+ + explicit_input_signs,
407
+ + length=H.shape[0],
408
+ + name="input_signs",
409
+ + device=H_data["su"].device,
410
+ + orientation="column",
411
+ + signs=True,
412
+ + )
413
+ + if not torch.equal(H_data["su"], expected):
414
+ + raise ValueError(
415
+ + "finalized Hessian input signs do not match the "
416
+ + "caller-supplied profile"
417
+ + )
418
+ + return (
419
+ + H_data["q_fallback"],
420
+ + H,
421
+ + H_data["L"],
422
+ + H_data["su"],
423
+ + H_data["diag"],
424
+ + )
425
+
426
+ # Mean of samples summed up during forward pass
427
+ # Switch to uncalibrated fallback if no input activations or diagonal is too small (few activations)
428
+ @@ -1634,7 +1731,23 @@ def finalize_capture_H(H_data: dict, quant_args: dict, verbose: bool):
429
+
430
+ # Random sign flips for input channel, fixed for the first linear layer to quantize with this H
431
+ k = H.shape[0]
432
+ - su = (torch.randn(k, device = H.device).sign() + 1e-5).sign().to(torch.float).unsqueeze(1)
433
+ + explicit_input_signs = quant_args.get("input_signs")
434
+ + if explicit_input_signs is None:
435
+ + su = (
436
+ + (torch.randn(k, device=H.device).sign() + 1e-5)
437
+ + .sign()
438
+ + .to(torch.float)
439
+ + .unsqueeze(1)
440
+ + )
441
+ + else:
442
+ + su = _explicit_vector(
443
+ + explicit_input_signs,
444
+ + length=k,
445
+ + name="input_signs",
446
+ + device=H.device,
447
+ + orientation="column",
448
+ + signs=True,
449
+ + )
450
+ H_data["su"] = su
451
+
452
+ # Input had
453
+ @@ -1648,14 +1761,21 @@ def finalize_capture_H(H_data: dict, quant_args: dict, verbose: bool):
454
+ L = None
455
+ else:
456
+ L, H = block_ldl(H, 16, quant_args, verbose)
457
+ - dr = torch.arange(k)
458
+ + dr = torch.arange(k, device=L.device)
459
+ L[dr, dr] = 0
460
+
461
+ H_data["L"] = L
462
+
463
+ - # H is no longer needed except to compute proxy error so move to CPU
464
+ - H = H.cpu()
465
+ - H_data["H"] = H.cpu()
466
+ + # Paid B300 production keeps caller-owned H/L on the quant device.
467
+ + # CPU storage remains the default for historical/offline callers.
468
+ + keep_hessian_on_device = bool(
469
+ + quant_args.get("keep_hessian_on_device", False)
470
+ + )
471
+ + if keep_hessian_on_device:
472
+ + H_data["H"] = H
473
+ + else:
474
+ + H = H.cpu()
475
+ + H_data["H"] = H.cpu()
476
+
477
+ H_data["finalized"] = True
478
+ H_data["diag"] = diag
479
+ @@ -1752,23 +1872,63 @@ def g_scale_search_batch(
480
+ i = j
481
+ return out
482
+
483
+ - # Stage 1: coarse grid over the full search range, on a subsample of each tensor's tiles
484
+ - coarse = [0.1 + 0.2 * i for i in range(10)] # 0.1 .. 1.9, same range as the old golden-section bracket
485
+ + # Stage 1: retain the historical cheap bracket on a tile subsample. Only
486
+ + # tensors whose minimum lands at the upper point pay for the expansion.
487
+ + coarse = [
488
+ + G_SCALE_SEARCH_INITIAL_MIN + G_SCALE_SEARCH_COARSE_STEP * i
489
+ + for i in range(
490
+ + round(
491
+ + (G_SCALE_SEARCH_INITIAL_MAX - G_SCALE_SEARCH_INITIAL_MIN)
492
+ + / G_SCALE_SEARCH_COARSE_STEP
493
+ + )
494
+ + + 1
495
+ + )
496
+ + ]
497
+ subs = [s[::3] for s in samples]
498
+ pairs1 = [(t, s) for t in range(n_t) for s in coarse]
499
+ mse1 = eval_pairs(pairs1, subs).view(n_t, len(coarse))
500
+ - centers = [coarse[c] for c in mse1.argmin(dim = 1).tolist()]
501
+ + coarse_best = mse1.argmin(dim = 1).tolist()
502
+ + centers = [coarse[c] for c in coarse_best]
503
+ + expanded = [index == len(coarse) - 1 for index in coarse_best]
504
+ +
505
+ + expansion = [
506
+ + G_SCALE_SEARCH_INITIAL_MAX + G_SCALE_SEARCH_COARSE_STEP * (i + 1)
507
+ + for i in range(
508
+ + round(
509
+ + (G_SCALE_SEARCH_EXPANDED_MAX - G_SCALE_SEARCH_INITIAL_MAX)
510
+ + / G_SCALE_SEARCH_COARSE_STEP
511
+ + )
512
+ + )
513
+ + ]
514
+ + expanded_tensors = [t for t, needed in enumerate(expanded) if needed]
515
+ + if expanded_tensors:
516
+ + pairs_x = [(t, scale) for t in expanded_tensors for scale in expansion]
517
+ + mse_x = eval_pairs(pairs_x, subs).view(len(expanded_tensors), len(expansion))
518
+ + for row, tensor_index in enumerate(expanded_tensors):
519
+ + values = torch.cat((mse1[tensor_index], mse_x[row]))
520
+ + combined = coarse + expansion
521
+ + centers[tensor_index] = combined[int(values.argmin().item())]
522
+
523
+ # Stage 2: fine grid around each tensor's coarse minimum, on its full sample
524
+ - step = 0.075
525
+ + step = G_SCALE_SEARCH_FINE_STEP
526
+ fine = [[c + step * (i - 2) for i in range(5)] for c in centers]
527
+ pairs2 = [(t, s) for t in range(n_t) for s in fine[t]]
528
+ mse2 = eval_pairs(pairs2, samples).view(n_t, 5)
529
+ mse2_h = mse2.tolist()
530
+
531
+ results = []
532
+ + evidence = []
533
+ for t in range(n_t):
534
+ best = min(range(5), key = lambda i: mse2_h[t][i])
535
+ + if (
536
+ + fine[t][best]
537
+ + >= G_SCALE_SEARCH_HARD_CEILING - G_SCALE_SEARCH_CEILING_TOLERANCE
538
+ + ):
539
+ + raise RuntimeError(
540
+ + "global scale search saturated at its hard upper ceiling: "
541
+ + f"scale={fine[t][best]:.8g}, "
542
+ + f"ceiling={G_SCALE_SEARCH_HARD_CEILING:.8g}"
543
+ + )
544
+ if 0 < best < 4:
545
+ y0, y1, y2 = mse2_h[t][best - 1], mse2_h[t][best], mse2_h[t][best + 1]
546
+ denom = y0 - 2.0 * y1 + y2
547
+ @@ -1777,7 +1937,31 @@ def g_scale_search_batch(
548
+ else:
549
+ offset = 0.0
550
+ best_scale = max(fine[t][best] + offset * step, 0.01)
551
+ + if (
552
+ + best_scale
553
+ + >= G_SCALE_SEARCH_HARD_CEILING - G_SCALE_SEARCH_CEILING_TOLERANCE
554
+ + ):
555
+ + raise RuntimeError(
556
+ + "global scale interpolation reached its hard upper ceiling: "
557
+ + f"scale={best_scale:.8g}, "
558
+ + f"ceiling={G_SCALE_SEARCH_HARD_CEILING:.8g}"
559
+ + )
560
+ results.append((best_scale, mse2[t, best]))
561
+ + evidence.append(
562
+ + {
563
+ + "policy": "raw_sample_adaptive_coarse_then_fine_v2",
564
+ + "initial_min": G_SCALE_SEARCH_INITIAL_MIN,
565
+ + "initial_max": G_SCALE_SEARCH_INITIAL_MAX,
566
+ + "expanded": expanded[t],
567
+ + "expanded_max": G_SCALE_SEARCH_EXPANDED_MAX,
568
+ + "fine_min": fine[t][0],
569
+ + "fine_max": fine[t][-1],
570
+ + "hard_ceiling": G_SCALE_SEARCH_HARD_CEILING,
571
+ + "selected_scale": best_scale,
572
+ + "selected_is_below_hard_ceiling": True,
573
+ + }
574
+ + )
575
+ + quant_args["g_scale_search_evidence"] = evidence
576
+ return results
577
+
578
+
579
+ @@ -1867,6 +2051,16 @@ _SHARED_INPUT_SCALES: dict = {}
580
+ def output_signs(n: int, device: torch.device, quant_args: dict) -> torch.Tensor:
581
+ """Draw output signs from an optional transform-specific RNG stream."""
582
+
583
+ + explicit_output_signs = quant_args.get("output_signs")
584
+ + if explicit_output_signs is not None:
585
+ + return _explicit_vector(
586
+ + explicit_output_signs,
587
+ + length=n,
588
+ + name="output_signs",
589
+ + device=device,
590
+ + orientation="row",
591
+ + signs=True,
592
+ + )
593
+ if "sv_seed" in quant_args:
594
+ torch.manual_seed(quant_args["sv_seed"])
595
+ return (
596
+ @@ -1920,35 +2114,81 @@ def regularize(
597
+ print(f" - input state skew: {skew_factor.item():.6f}")
598
+
599
+ if force_out_scales is None:
600
+ - apply_out_scales = skew_factor.item() < 0.15
601
+ + apply_out_scales_mask = skew_factor < 0.15
602
+ else:
603
+ - apply_out_scales = force_out_scales
604
+ + apply_out_scales_mask = torch.tensor(
605
+ + bool(force_out_scales), dtype=torch.bool, device=weight.device
606
+ + )
607
+
608
+ else:
609
+ - apply_out_scales = True if force_out_scales is None else force_out_scales
610
+ + apply_out_scales_mask = torch.tensor(
611
+ + True if force_out_scales is None else bool(force_out_scales),
612
+ + dtype=torch.bool,
613
+ + device=weight.device,
614
+ + )
615
+
616
+ if q_fallback:
617
+ - apply_out_scales = force_out_scales
618
+ -
619
+ - # Apply output scales
620
+ - out_channel_scales = block_rms(weight, dim = 0, keepdim = True)
621
+ - mean = out_channel_scales.mean().item()
622
+ - if mean > 1e-30:
623
+ - out_channel_scales /= mean
624
+ - quant_args["zeros"] = False
625
+ + # Preserve the historical truthiness of a missing fallback override.
626
+ + apply_out_scales_mask = torch.tensor(
627
+ + False if force_out_scales is None else bool(force_out_scales),
628
+ + dtype=torch.bool,
629
+ + device=weight.device,
630
+ + )
631
+ +
632
+ + # Apply output scales. An explicit profile is caller-owned and bypasses
633
+ + # first-tensor derivation, which is required for topology-neutral ports.
634
+ + explicit_output_scales = quant_args.get("output_channel_scale_profile")
635
+ + observed_out_channel_scales = block_rms(weight, dim = 0, keepdim = True)
636
+ + if explicit_output_scales is not None:
637
+ + if force_out_scales is False:
638
+ + raise ValueError(
639
+ + "output_channel_scale_profile requires apply_out_scales=True"
640
+ + )
641
+ + apply_out_scales_mask = torch.ones(
642
+ + (), dtype=torch.bool, device=weight.device
643
+ + )
644
+ + out_channel_scales = _explicit_vector(
645
+ + explicit_output_scales,
646
+ + length=weight.shape[1],
647
+ + name="output_channel_scale_profile",
648
+ + device=weight.device,
649
+ + orientation="row",
650
+ + )
651
+ else:
652
+ - quant_args["zeros"] = True
653
+ - if force_out_scales is not None:
654
+ - apply_out_scales = True
655
+ - zero_out_scales = out_channel_scales.abs() < 1e-30
656
+ -
657
+ - if apply_out_scales:
658
+ - out_channel_scales[zero_out_scales] = 0.1
659
+ - sv = (sv * out_channel_scales + 1e-10).float()
660
+ - if verbose:
661
+ - out_channel_std = out_channel_scales.std().item()
662
+ - out_channel_mean = out_channel_scales.mean().item()
663
+ - print(f" - out ch scales std/mean: {out_channel_std:.6f} {out_channel_mean:.6f}")
664
+ + out_channel_scales = observed_out_channel_scales
665
+ + mean = out_channel_scales.mean()
666
+ + mean_positive = mean > 1e-30
667
+ + if explicit_output_scales is None:
668
+ + # Keep the data-dependent normalization decision on CUDA. The
669
+ + # clamped denominator is ignored by torch.where for an all-zero
670
+ + # profile and therefore cannot alter that historical branch.
671
+ + out_channel_scales = torch.where(
672
+ + mean_positive,
673
+ + out_channel_scales / mean.clamp_min(1e-30),
674
+ + out_channel_scales,
675
+ + )
676
+ + if force_out_scales is not None:
677
+ + # Historical behavior forces scaling for an all-zero tensor even when
678
+ + # an explicit boolean override was supplied.
679
+ + apply_out_scales_mask = torch.where(
680
+ + mean_positive,
681
+ + apply_out_scales_mask,
682
+ + torch.ones_like(apply_out_scales_mask),
683
+ + )
684
+ + zero_out_scales = observed_out_channel_scales.abs() < 1e-30
685
+ + if explicit_output_scales is not None and bool(zero_out_scales.any()):
686
+ + raise ValueError(
687
+ + "an explicit output scale profile cannot encode a zero output channel"
688
+ + )
689
+ +
690
+ + candidate_out_channel_scales = out_channel_scales.clone()
691
+ + candidate_out_channel_scales[zero_out_scales] = 0.1
692
+ + scaled_sv = (sv * candidate_out_channel_scales + 1e-10).float()
693
+ + sv = torch.where(apply_out_scales_mask, scaled_sv, sv)
694
+ + if verbose:
695
+ + out_channel_std = candidate_out_channel_scales.std().item()
696
+ + out_channel_mean = candidate_out_channel_scales.mean().item()
697
+ + print(f" - out ch scales std/mean: {out_channel_std:.6f} {out_channel_mean:.6f}")
698
+
699
+ # Output sign flips (and scales)
700
+ weight /= sv
701
+ @@ -1960,13 +2200,28 @@ def regularize(
702
+ blockwise_preapply_had_r_(weight, had_n)
703
+
704
+ # Input sign flips and scales
705
+ - in_channel_scales = block_rms(weight, dim = 1, keepdim = True)
706
+ - in_channel_scales[in_channel_scales.abs() < 1e-30] = 0.1
707
+ + explicit_input_scales = quant_args.get("input_channel_scale_profile")
708
+ + if explicit_input_scales is None:
709
+ + in_channel_scales = block_rms(weight, dim = 1, keepdim = True)
710
+ + in_channel_scales[in_channel_scales.abs() < 1e-30] = 0.1
711
+ + else:
712
+ + in_channel_scales = _explicit_vector(
713
+ + explicit_input_scales,
714
+ + length=weight.shape[0],
715
+ + name="input_channel_scale_profile",
716
+ + device=weight.device,
717
+ + orientation="column",
718
+ + )
719
+ # kquant shared-su mode: reuse the first tensor's channel-scale profile for
720
+ # every tensor with the same key (e.g. all experts of a MoE layer/matrix),
721
+ # so the stored su vector is identical across them and TP replicas can
722
+ # broadcast one copy. Trellis codes re-fit against the shared profile.
723
+ shared_key = quant_args.get("shared_input_scales_key")
724
+ + if explicit_input_scales is not None and shared_key is not None:
725
+ + raise ValueError(
726
+ + "input_channel_scale_profile cannot be combined with the "
727
+ + "module-global shared_input_scales_key"
728
+ + )
729
+ if shared_key is not None:
730
+ in_channel_scales = _SHARED_INPUT_SCALES.setdefault(
731
+ shared_key, in_channel_scales)
732
+ @@ -1976,7 +2231,49 @@ def regularize(
733
+
734
+ # Determine best scale for matrix by test quantizing a sample of tiles along a wrapped diagonal
735
+ if not skip_g_scale:
736
+ - g_scale, mse_scale = g_scale_gss(weight, False, quant_args, pb = pb)
737
+ + override = quant_args.get("g_scale_override")
738
+ + if override is None:
739
+ + g_scale, mse_scale = g_scale_gss(weight, False, quant_args, pb = pb)
740
+ + else:
741
+ + if (
742
+ + isinstance(override, bool)
743
+ + or not isinstance(override, (int, float))
744
+ + or not math.isfinite(float(override))
745
+ + or float(override) <= 0.0
746
+ + or float(override)
747
+ + >= G_SCALE_SEARCH_HARD_CEILING - G_SCALE_SEARCH_CEILING_TOLERANCE
748
+ + ):
749
+ + raise ValueError(
750
+ + "g_scale_override must be positive, finite, and below the "
751
+ + "hard scale ceiling"
752
+ + )
753
+ + policy = quant_args.get("g_scale_override_policy")
754
+ + evidence_id = quant_args.get("g_scale_override_evidence_id")
755
+ + if policy != "activation_parametric_coupled_v1":
756
+ + raise ValueError(
757
+ + "serial g_scale_override requires the activation-parametric "
758
+ + "coupled policy"
759
+ + )
760
+ + if (
761
+ + not isinstance(evidence_id, str)
762
+ + or len(evidence_id) != 64
763
+ + or any(ch not in "0123456789abcdef" for ch in evidence_id)
764
+ + ):
765
+ + raise ValueError(
766
+ + "serial g_scale_override requires a lowercase SHA-256 evidence ID"
767
+ + )
768
+ + g_scale = float(override)
769
+ + mse_scale = torch.tensor(float("nan"), device=weight.device)
770
+ + quant_args["g_scale_search_evidence"] = [
771
+ + {
772
+ + "policy": policy,
773
+ + "evidence_id": evidence_id,
774
+ + "raw_sample_search_performed": False,
775
+ + "hard_ceiling": G_SCALE_SEARCH_HARD_CEILING,
776
+ + "selected_scale": g_scale,
777
+ + "selected_is_below_hard_ceiling": True,
778
+ + }
779
+ + ]
780
+ else:
781
+ g_scale = 1.0
782
+ weight, su, sv = apply_g_scale(
783
+ @@ -1987,6 +2284,11 @@ def regularize(
784
+ into_sv=bool(quant_args.get("g_scale_into_sv")),
785
+ )
786
+
787
+ + # The transform is now numerically frozen. Only manifest booleans cross
788
+ + # to the host; neither value can feed back into weight construction.
789
+ + apply_out_scales = bool(apply_out_scales_mask.item())
790
+ + quant_args["zeros"] = bool((~mean_positive).item())
791
+ +
792
+ # ext.test_distribution(weight_os, dist_r, dist_ref, -3.8, 3.8)
793
+ # js_os = jsd(dist_r, dist_ref)
794
+
795
+ @@ -2119,8 +2421,12 @@ def quantize_qsrt(
796
+ H_diag = H_diag.to(device)
797
+ sv = output_signs(n, device, quant_args)
798
+
799
+ - # Move stored L to CPU (if not already), move working L to device
800
+ - if H_data["L"] is not None:
801
+ + # Historical callers store L on CPU. The B300 path retains it on GPU
802
+ + # so a shared H13 session does not round-trip a 6144-square factor for
803
+ + # every gate/up candidate.
804
+ + if H_data["L"] is not None and not quant_args.get(
805
+ + "keep_hessian_on_device", False
806
+ + ):
807
+ H_data["L"] = H_data["L"].cpu()
808
+ if L is not None:
809
+ L = L.to(device)
810
+ @@ -2160,7 +2466,9 @@ def quantize_qsrt(
811
+
812
+ # Select device for work buffers (CPU is slower for small tensors but saves a lot of VRAM on big ones)
813
+ # TODO: Use pynvml or mem_get_info to predict whether CPU buffer is needed
814
+ - if weight_r.numel() > 5e8:
815
+ + if weight_r.numel() > 5e8 and not quant_args.get(
816
+ + "gpu_only_numerical_path", False
817
+ + ):
818
+ weight_r = weight_r.cpu()
819
+
820
+ # Quantize
821
+ @@ -2305,6 +2613,8 @@ def quantize_qsrt_batch(
822
+ "ldlq_tf32",
823
+ "tailbite_context",
824
+ "g_scale_override",
825
+ + "keep_hessian_on_device",
826
+ + "gpu_only_numerical_path",
827
+ )
828
+ for group in quant_args_groups:
829
+ reference = group[0]
830
+ @@ -2338,7 +2648,9 @@ def quantize_qsrt_batch(
831
+ su = su.to(device)
832
+ if H_diag is not None:
833
+ H_diag = H_diag.to(device)
834
+ - if H_data["L"] is not None:
835
+ + if H_data["L"] is not None and not args.get(
836
+ + "keep_hessian_on_device", False
837
+ + ):
838
+ H_data["L"] = H_data["L"].cpu()
839
+ sv = output_signs(weight.shape[1], device, args)
840
+ apply_out_scales, weight_r, _, su, sv = regularize(
841
+ diff --git a/kquant/exl3_reference.py b/kquant/exl3_reference.py
842
+ index b1a4e1e..01b4b5d 100644
843
+ --- a/kquant/exl3_reference.py
844
+ +++ b/kquant/exl3_reference.py
845
+ @@ -30,8 +30,8 @@ QSRT_CODEBOOKS = (
846
+
847
+
848
+ def _validate_bits(bits: int) -> None:
849
+ - if isinstance(bits, bool) or not isinstance(bits, int) or bits not in (2, 3, 4):
850
+ - raise ValueError("the QSRT reference supports K=2, K=3, or K=4")
851
+ + if isinstance(bits, bool) or not isinstance(bits, int) or bits not in range(2, 7):
852
+ + raise ValueError("the SQG reference supports K=2 through K=6")
853
+
854
+
855
+ def reconstruct_trellis_states(
856
+ @@ -150,9 +150,9 @@ def decode_qsrt_regularized_weight(
857
+ tile_bits: tuple[int, ...],
858
+ codebook: str,
859
+ ) -> torch.Tensor:
860
+ - """Decode a K2/K3/K4 tile map to transformed ``[K, N]`` weights.
861
+ + """Decode a K2--K6 tile map to transformed ``[K, N]`` weights.
862
+
863
+ - SQG uses a distinct state labelling for K2, K3, and K4, so the physical
864
+ + SQG uses a distinct state labelling for every supported K, so the physical
865
+ tile rate is part of the numerical decode contract.
866
+ """
867
+
868
+ @@ -164,10 +164,10 @@ def decode_qsrt_regularized_weight(
869
+ if len(tile_bits) != states.shape[axis]:
870
+ raise ValueError("tile_bits length does not match the selected rate axis")
871
+ if any(
872
+ - isinstance(value, bool) or not isinstance(value, int) or value not in (2, 3, 4)
873
+ + isinstance(value, bool) or not isinstance(value, int) or value not in range(2, 7)
874
+ for value in tile_bits
875
+ ):
876
+ - raise ValueError("tile_bits must contain only integer K2, K3, or K4")
877
+ + raise ValueError("tile_bits must contain only integer K2 through K6")
878
+ if codebook not in QSRT_CODEBOOKS:
879
+ raise ValueError(f"unsupported QSRT codebook: {codebook}")
880
+
881
+ diff --git a/kquant/qsrt.py b/kquant/qsrt.py
882
+ index 0424724..1bfd2a0 100644
883
+ --- a/kquant/qsrt.py
884
+ +++ b/kquant/qsrt.py
885
+ @@ -804,8 +804,8 @@ def repack_encoded_records(
886
+
887
+
888
+ def _validate_k(bits: int) -> None:
889
+ - if isinstance(bits, bool) or not isinstance(bits, int) or bits not in (2, 3, 4):
890
+ - raise ValueError("QSRT supports K=2, K=3, or K=4")
891
+ + if isinstance(bits, bool) or not isinstance(bits, int) or bits not in range(2, 7):
892
+ + raise ValueError("SQG trellis packing supports K=2 through K=6")
893
+
894
+
895
+ def pack_trellis_edges(indices: torch.Tensor, bits: int) -> torch.Tensor:
896
+ diff --git a/kquant/sqg_e4m3.py b/kquant/sqg_e4m3.py
897
+ index 2783b10..d7f831d 100644
898
+ --- a/kquant/sqg_e4m3.py
899
+ +++ b/kquant/sqg_e4m3.py
900
+ @@ -31,8 +31,8 @@ _Q = (1.0, 2.07630930, -8.08332684, 6.32135736, -1.31208298)
901
+
902
+
903
+ def _validate(bits: int, mode: str) -> None:
904
+ - if isinstance(bits, bool) or not isinstance(bits, int) or bits not in (2, 3, 4):
905
+ - raise ValueError("SQG supports integer K2, K3, or K4")
906
+ + if isinstance(bits, bool) or not isinstance(bits, int) or bits not in range(2, 7):
907
+ + raise ValueError("SQG supports integer K2 through K6")
908
+ if mode != "normal":
909
+ raise ValueError("the supported R44 mode is 'normal'")
910
+
911
+ @@ -157,7 +157,7 @@ def sqg_e4m3_bytes_from_rank_lut(
912
+ ) -> torch.Tensor:
913
+ """Map a shared rank-indexed E4M3 law onto the unchanged SQG graph.
914
+
915
+ - ``rank_lut`` is deliberately independent of ``bits``. K2/K3/K4 may
916
+ + ``rank_lut`` is deliberately independent of ``bits``. K2 through K6 may
917
+ expose different outgoing menus because their stratum widths differ, but
918
+ they retain the same history mixer, syndrome mixer, branch permutation,
919
+ and scalar reconstruction law. This is the controlled interface used to
920
+ diff --git a/kquant/sqg_quantizer.py b/kquant/sqg_quantizer.py
921
+ index cc29e00..ade6f06 100644
922
+ --- a/kquant/sqg_quantizer.py
923
+ +++ b/kquant/sqg_quantizer.py
924
+ @@ -2,9 +2,15 @@
925
+
926
+ from __future__ import annotations
927
+
928
+ +import hashlib
929
+ +import importlib.machinery
930
+ +import importlib.util
931
+ +import os
932
+ +import re
933
+ +import sys
934
+ +from collections.abc import Mapping
935
+ from functools import lru_cache
936
+ from pathlib import Path
937
+ -from collections.abc import Mapping
938
+
939
+ import torch
940
+ from torch.utils.cpp_extension import load
941
+ @@ -12,11 +18,107 @@ from torch.utils.cpp_extension import load
942
+ from kquant.sqg_e4m3 import sqg_e4m3_bytes
943
+
944
+
945
+ +_EXTENSION_NAME = "kquant_sqg_quantize_ext_v22"
946
+ +_EXTENSION_PATH_ENV = "KQUANT_SQG_EXTENSION_PATH"
947
+ +_EXTENSION_SHA256_ENV = "KQUANT_SQG_EXTENSION_SHA256"
948
+ +_REQUIRE_PREBUILT_ENV = "KQUANT_SQG_REQUIRE_PREBUILT"
949
+ +_SHA256_RE = re.compile(r"[0-9a-f]{64}")
950
+ +
951
+ +
952
+ +def _sha256_file(path: Path) -> str:
953
+ + digest = hashlib.sha256()
954
+ + with path.open("rb") as handle:
955
+ + for chunk in iter(lambda: handle.read(1024 * 1024), b""):
956
+ + digest.update(chunk)
957
+ + return digest.hexdigest()
958
+ +
959
+ +
960
+ +def _import_prebuilt_extension(path: Path):
961
+ + """Import one exact pybind extension without invoking the JIT builder."""
962
+ +
963
+ + spec = importlib.util.spec_from_file_location(_EXTENSION_NAME, path)
964
+ + if spec is None or spec.loader is None:
965
+ + raise ImportError(f"cannot construct an import spec for SQG extension: {path}")
966
+ + previous = sys.modules.get(_EXTENSION_NAME)
967
+ + module = importlib.util.module_from_spec(spec)
968
+ + sys.modules[_EXTENSION_NAME] = module
969
+ + try:
970
+ + spec.loader.exec_module(module)
971
+ + except BaseException:
972
+ + if previous is None:
973
+ + sys.modules.pop(_EXTENSION_NAME, None)
974
+ + else:
975
+ + sys.modules[_EXTENSION_NAME] = previous
976
+ + raise
977
+ + return module
978
+ +
979
+ +
980
+ +def _load_prebuilt_extension(raw_path: str, expected_sha256: str):
981
+ + candidate = Path(raw_path)
982
+ + if not candidate.is_absolute():
983
+ + raise ValueError(f"{_EXTENSION_PATH_ENV} must be an absolute path")
984
+ + if candidate.is_symlink():
985
+ + raise ValueError(f"{_EXTENSION_PATH_ENV} may not name a symlink")
986
+ + try:
987
+ + path = candidate.resolve(strict=True)
988
+ + except FileNotFoundError as exc:
989
+ + raise FileNotFoundError(
990
+ + f"sealed SQG extension does not exist: {candidate}"
991
+ + ) from exc
992
+ + if not path.is_file():
993
+ + raise ValueError(f"sealed SQG extension is not a regular file: {path}")
994
+ + allowed_names = {
995
+ + f"{_EXTENSION_NAME}{suffix}"
996
+ + for suffix in importlib.machinery.EXTENSION_SUFFIXES
997
+ + }
998
+ + if path.name not in allowed_names:
999
+ + raise ValueError(
1000
+ + "sealed SQG extension filename must identify "
1001
+ + f"{_EXTENSION_NAME}: {path.name}"
1002
+ + )
1003
+ + if _SHA256_RE.fullmatch(expected_sha256) is None:
1004
+ + raise ValueError(f"{_EXTENSION_SHA256_ENV} must be 64 lowercase hex digits")
1005
+ + observed_sha256 = _sha256_file(path)
1006
+ + if observed_sha256 != expected_sha256:
1007
+ + raise RuntimeError(
1008
+ + "sealed SQG extension SHA256 mismatch: "
1009
+ + f"{observed_sha256} != {expected_sha256}"
1010
+ + )
1011
+ + module = _import_prebuilt_extension(path)
1012
+ + module_path = Path(str(getattr(module, "__file__", ""))).resolve()
1013
+ + if module_path != path:
1014
+ + raise RuntimeError(
1015
+ + f"loaded SQG extension origin differs: {module_path} != {path}"
1016
+ + )
1017
+ + if not callable(getattr(module, "quantize_tiles_procedural", None)) or not callable(
1018
+ + getattr(module, "quantize_tiles_sqg", None)
1019
+ + ):
1020
+ + raise RuntimeError(
1021
+ + "sealed SQG extension lacks required quantization entry points"
1022
+ + )
1023
+ + if _sha256_file(path) != expected_sha256:
1024
+ + raise RuntimeError("sealed SQG extension changed while it was being imported")
1025
+ + return module
1026
+ +
1027
+ +
1028
+ @lru_cache(maxsize=1)
1029
+ def _extension():
1030
+ + require_value = os.environ.get(_REQUIRE_PREBUILT_ENV, "")
1031
+ + if require_value not in ("", "0", "1"):
1032
+ + raise ValueError(f"{_REQUIRE_PREBUILT_ENV} must be unset, 0, or 1")
1033
+ + raw_path = os.environ.get(_EXTENSION_PATH_ENV, "")
1034
+ + expected_sha256 = os.environ.get(_EXTENSION_SHA256_ENV, "")
1035
+ + if require_value == "1" or raw_path or expected_sha256:
1036
+ + if not raw_path or not expected_sha256:
1037
+ + raise RuntimeError(
1038
+ + f"{_EXTENSION_PATH_ENV} and {_EXTENSION_SHA256_ENV} are both required "
1039
+ + "for sealed prebuilt SQG loading"
1040
+ + )
1041
+ + return _load_prebuilt_extension(raw_path, expected_sha256)
1042
+ +
1043
+ project = Path(__file__).resolve().parents[1]
1044
+ return load(
1045
+ - name="kquant_sqg_quantize_ext_v22",
1046
+ + name=_EXTENSION_NAME,
1047
+ sources=[
1048
+ str(project / "kquant/csrc/sqg_quantize.cpp"),
1049
+ str(project / "kquant/csrc/sqg_quantize.cu"),
1050
+ @@ -42,7 +144,7 @@ def _sqg_temp_buffers(device: torch.device, bits: int):
1051
+
1052
+ multiprocessors = torch.cuda.get_device_properties(device).multi_processor_count
1053
+ edges = 65536 >> bits
1054
+ - decisions = edges // (4 if bits == 2 else 2)
1055
+ + decisions = edges // 4 if bits == 2 else (edges // 2 if bits <= 4 else edges)
1056
+ free_bytes, _ = torch.cuda.mem_get_info(device)
1057
+ decision_bytes_per_tile = 256 * decisions
1058
+ affordable = max(256, int(free_bytes * 0.5) // decision_bytes_per_tile)
1059
+ @@ -94,13 +196,17 @@ def install_sqg_quantizer(quantizer_module) -> None:
1060
+ )
1061
+ if not isinstance(rate_codebooks, Mapping):
1062
+ raise TypeError("sqg_e4m3_luts_by_bits must be a mapping")
1063
+ - if set(rate_codebooks) - {2, 3, 4}:
1064
+ - raise ValueError("rate-specific SQG LUT keys must be K2, K3, or K4")
1065
+ + if set(rate_codebooks) - set(range(2, 7)):
1066
+ + raise ValueError("rate-specific SQG LUT keys must be K2 through K6")
1067
+ try:
1068
+ codebook = rate_codebooks[bits]
1069
+ except KeyError as exc:
1070
+ raise ValueError(f"missing rate-specific SQG K{bits} LUT") from exc
1071
+ if codebook is None:
1072
+ + if bits not in (2, 3, 4):
1073
+ + raise ValueError(
1074
+ + "non-SQG procedural controls remain limited to K2 through K4"
1075
+ + )
1076
+ output = torch.empty_like(tiles)
1077
+ indices = torch.empty_like(tiles, dtype=torch.int16)
1078
+ costs, edges = _sqg_temp_buffers(tiles.device, bits)
1079
+ diff --git a/tests/test_qsrt.py b/tests/test_qsrt.py
1080
+ index 0d5189d..6e5c469 100644
1081
+ --- a/tests/test_qsrt.py
1082
+ +++ b/tests/test_qsrt.py
1083
+ @@ -218,6 +218,8 @@ def test_matrix_rate_axis_tracks_shared_intermediate_dimension() -> None:
1084
+ (2, [6939] * 6),
1085
+ (3, [30469, 1337, 1337, 14711, 14711, 30469]),
1086
+ (4, [17767, 291, -12817, -30293, 17767, 291]),
1087
+ + (5, [12820, 68, 21686, -14526, -31643, 13775]),
1088
+ + (6, [-31984, 16, 8338, 20871, -11377, -29904]),
1089
+ ],
1090
+ )
1091
+ def test_trellis_edge_pack_matches_native_word_order(
1092
+ @@ -231,7 +233,7 @@ def test_trellis_edge_pack_matches_native_word_order(
1093
+ torch.testing.assert_close(unpack_trellis_edges(packed, bits), indices)
1094
+
1095
+
1096
+ -@pytest.mark.parametrize("bits", [2, 3, 4])
1097
+ +@pytest.mark.parametrize("bits", range(2, 7))
1098
+ def test_trellis_edge_pack_round_trips_only_stored_low_bits(bits: int) -> None:
1099
+ generator = torch.Generator().manual_seed(100 + bits)
1100
+ indices = torch.randint(-32768, 32768, (7, 256), generator=generator)
1101
+ @@ -241,7 +243,7 @@ def test_trellis_edge_pack_round_trips_only_stored_low_bits(bits: int) -> None:
1102
+ torch.testing.assert_close(unpacked.int(), indices.int() & ((1 << bits) - 1))
1103
+
1104
+
1105
+ -@pytest.mark.parametrize("bits", [2, 3, 4])
1106
+ +@pytest.mark.parametrize("bits", range(2, 7))
1107
+ def test_cyclic_trellis_states_round_trip_exactly(bits: int) -> None:
1108
+ generator = torch.Generator().manual_seed(150 + bits)
1109
+ edges = torch.randint(0, 1 << bits, (5, 256), generator=generator)
1110
+ @@ -251,7 +253,7 @@ def test_cyclic_trellis_states_round_trip_exactly(bits: int) -> None:
1111
+ torch.testing.assert_close(unpack_trellis_states(packed, bits), states)
1112
+
1113
+
1114
+ -@pytest.mark.parametrize("bits", [2, 3, 4])
1115
+ +@pytest.mark.parametrize("bits", range(2, 7))
1116
+ def test_cyclic_trellis_state_closed_form_matches_scalar_recurrence(bits: int) -> None:
1117
+ generator = torch.Generator().manual_seed(175 + bits)
1118
+ edges = torch.randint(0, 1 << bits, (3, 5, 256), generator=generator)
1119
+ diff --git a/tests/test_sqg_e4m3.py b/tests/test_sqg_e4m3.py
1120
+ index f630827..669fd6d 100644
1121
+ --- a/tests/test_sqg_e4m3.py
1122
+ +++ b/tests/test_sqg_e4m3.py
1123
+ @@ -34,6 +34,8 @@ _SQG_XOR_CHEB_T12_SHA256 = {
1124
+ 2: "62027916386245a84c86156a0a08b6cf07e41548871af0e56fb40780558f6293",
1125
+ 3: "afe7b3633e7d243b00b379b18ec4dca573722b3727cafef47fcb6470d7e7e6c9",
1126
+ 4: "5a9620f0c4d8f0a60d0b6fbea921dcecbd193e6febf31043aaa6403c20389c2f",
1127
+ + 5: "a1caf5572c67d4face423478f423e1ed6149a8c920be5c28d4702946c93cae2f",
1128
+ + 6: "8e0edc92e20eb92f5287dbdadc8e870fc500fc03c5eed996cae0781d197ebcb0",
1129
+ }
1130
+
1131
+
1132
+ @@ -48,7 +50,7 @@ def test_primary_sqg_xor_cheb_t12_matches_runtime_contract() -> None:
1133
+ assert _sha256(table) == _SQG_XOR_CHEB_T12_SHA256["t12"]
1134
+
1135
+
1136
+ -@pytest.mark.parametrize("bits", (2, 3, 4))
1137
+ +@pytest.mark.parametrize("bits", range(2, 7))
1138
+ def test_primary_sqg_xor_cheb_t12_graph_and_labels_match_runtime_contract(
1139
+ bits: int,
1140
+ ) -> None:
1141
+ @@ -69,7 +71,7 @@ def test_primary_sqg_xor_cheb_t12_graph_and_labels_match_runtime_contract(
1142
+ assert _sha256(labels) == _SQG_XOR_CHEB_T12_SHA256[bits]
1143
+
1144
+
1145
+ -@pytest.mark.parametrize("bits", (2, 3, 4))
1146
+ +@pytest.mark.parametrize("bits", range(2, 7))
1147
+ def test_sqg_preprojection_mapping_is_a_permutation(bits: int) -> None:
1148
+ ranks = sqg_rank_permutation(bits)
1149
+ assert ranks.dtype == torch.int64
1150
+ @@ -77,7 +79,7 @@ def test_sqg_preprojection_mapping_is_a_permutation(bits: int) -> None:
1151
+ assert torch.equal(torch.sort(ranks).values, torch.arange(1 << 16))
1152
+
1153
+
1154
+ -@pytest.mark.parametrize("bits", (2, 3, 4))
1155
+ +@pytest.mark.parametrize("bits", range(2, 7))
1156
+ def test_sqg_codebook_round_trips_exact_e4m3(bits: int) -> None:
1157
+ raw = sqg_e4m3_bytes(bits, "normal")
1158
+ codebook = sqg_e4m3_codebook(bits, "normal")
1159
+ @@ -88,7 +90,7 @@ def test_sqg_codebook_round_trips_exact_e4m3(bits: int) -> None:
1160
+ assert bool(torch.isfinite(codebook).all())
1161
+
1162
+
1163
+ -@pytest.mark.parametrize("bits", (2, 3, 4))
1164
+ +@pytest.mark.parametrize("bits", range(2, 7))
1165
+ def test_sqg_each_state_spans_all_coarse_strata(bits: int) -> None:
1166
+ ranks = sqg_rank_permutation(bits)
1167
+ width = 16 - bits
1168
+ @@ -97,7 +99,7 @@ def test_sqg_each_state_spans_all_coarse_strata(bits: int) -> None:
1169
+ assert torch.equal(torch.sort(strata, dim=1).values, expected)
1170
+
1171
+
1172
+ -@pytest.mark.parametrize("bits", (2, 3, 4))
1173
+ +@pytest.mark.parametrize("bits", range(2, 7))
1174
+ def test_shared_rank_lut_preserves_one_graph_for_every_rate(bits: int) -> None:
1175
+ rank_lut = torch.arange(1 << 16, dtype=torch.int64).remainder(126).to(torch.uint8)
1176
+ raw = sqg_e4m3_bytes_from_rank_lut(bits, rank_lut)
1177
+ @@ -118,7 +120,7 @@ def test_shared_rank_lut_rejects_nonfinite_e4m3() -> None:
1178
+ sqg_e4m3_bytes_from_rank_lut(2, rank_lut)
1179
+
1180
+
1181
+ -@pytest.mark.parametrize("bits", (2, 3, 4))
1182
+ +@pytest.mark.parametrize("bits", range(2, 7))
1183
+ def test_sqg_cheb_normal_named_codebook_uses_exact_shared_rank_law(bits: int) -> None:
1184
+ expected = sqg_cheb_normal_rank_e4m3_bytes().index_select(
1185
+ 0, sqg_rank_permutation(bits)
1186
+ @@ -132,7 +134,7 @@ def test_sqg_cheb_normal_named_codebook_uses_exact_shared_rank_law(bits: int) ->
1187
+ )
1188
+
1189
+
1190
+ -@pytest.mark.parametrize("bits", (2, 3, 4))
1191
+ +@pytest.mark.parametrize("bits", range(2, 7))
1192
+ @pytest.mark.parametrize("rate_axis", ("k", "n"))
1193
+ def test_w2_k2_q8h4_profile_changes_only_k_axis_k2(
1194
+ bits: int, rate_axis: str
1195
+ diff --git a/tests/test_sqg_quantizer.py b/tests/test_sqg_quantizer.py
1196
+ index 8d99e86..c470ee2 100644
1197
+ --- a/tests/test_sqg_quantizer.py
1198
+ +++ b/tests/test_sqg_quantizer.py
1199
+ @@ -1,11 +1,135 @@
1200
+ from __future__ import annotations
1201
+
1202
+ +import hashlib
1203
+ +from pathlib import Path
1204
+ from types import SimpleNamespace
1205
+
1206
+ +import pytest
1207
+ import torch
1208
+
1209
+ import kquant.sqg_quantizer as sqg_quantizer
1210
+ +from kquant.exl3_reference import reconstruct_trellis_states
1211
+ from kquant.sqg_quantizer import install_sqg_quantizer
1212
+ +from kquant.sqg_e4m3 import sqg_xor_cheb_t12_bytes
1213
+ +
1214
+ +
1215
+ +def _sealed_extension(
1216
+ + tmp_path: Path,
1217
+ + monkeypatch: pytest.MonkeyPatch,
1218
+ + *,
1219
+ + filename: str = "kquant_sqg_quantize_ext_v22.so",
1220
+ +) -> tuple[Path, SimpleNamespace]:
1221
+ + path = tmp_path / filename
1222
+ + payload = b"sealed-sqg-extension-test-double"
1223
+ + path.write_bytes(payload)
1224
+ + module = SimpleNamespace(
1225
+ + __file__=str(path),
1226
+ + quantize_tiles_procedural=lambda *_args: None,
1227
+ + quantize_tiles_sqg=lambda *_args: None,
1228
+ + )
1229
+ + monkeypatch.setenv("KQUANT_SQG_REQUIRE_PREBUILT", "1")
1230
+ + monkeypatch.setenv("KQUANT_SQG_EXTENSION_PATH", str(path))
1231
+ + monkeypatch.setenv(
1232
+ + "KQUANT_SQG_EXTENSION_SHA256", hashlib.sha256(payload).hexdigest()
1233
+ + )
1234
+ + return path, module
1235
+ +
1236
+ +
1237
+ +def test_required_prebuilt_extension_uses_exact_path_and_never_jit_builds(
1238
+ + tmp_path: Path, monkeypatch: pytest.MonkeyPatch
1239
+ +) -> None:
1240
+ + path, module = _sealed_extension(tmp_path, monkeypatch)
1241
+ + imported: list[Path] = []
1242
+ +
1243
+ + def fake_import(actual: Path):
1244
+ + imported.append(actual)
1245
+ + return module
1246
+ +
1247
+ + monkeypatch.setattr(sqg_quantizer, "_import_prebuilt_extension", fake_import)
1248
+ + monkeypatch.setattr(
1249
+ + sqg_quantizer,
1250
+ + "load",
1251
+ + lambda **_kwargs: pytest.fail("JIT builder must not run in prebuilt mode"),
1252
+ + )
1253
+ + sqg_quantizer._extension.cache_clear()
1254
+ + try:
1255
+ + assert sqg_quantizer._extension() is module
1256
+ + assert imported == [path.resolve()]
1257
+ + finally:
1258
+ + sqg_quantizer._extension.cache_clear()
1259
+ +
1260
+ +
1261
+ +def test_required_prebuilt_extension_rejects_wrong_filename_before_import_or_jit(
1262
+ + tmp_path: Path, monkeypatch: pytest.MonkeyPatch
1263
+ +) -> None:
1264
+ + _sealed_extension(tmp_path, monkeypatch, filename="foreign_extension.so")
1265
+ + monkeypatch.setattr(
1266
+ + sqg_quantizer,
1267
+ + "_import_prebuilt_extension",
1268
+ + lambda _path: pytest.fail("foreign extension must not be imported"),
1269
+ + )
1270
+ + monkeypatch.setattr(
1271
+ + sqg_quantizer,
1272
+ + "load",
1273
+ + lambda **_kwargs: pytest.fail("JIT builder must not run in prebuilt mode"),
1274
+ + )
1275
+ + sqg_quantizer._extension.cache_clear()
1276
+ + try:
1277
+ + with pytest.raises(ValueError, match="filename must identify"):
1278
+ + sqg_quantizer._extension()
1279
+ + finally:
1280
+ + sqg_quantizer._extension.cache_clear()
1281
+ +
1282
+ +
1283
+ +def test_required_prebuilt_extension_rejects_hash_mismatch_before_import_or_jit(
1284
+ + tmp_path: Path, monkeypatch: pytest.MonkeyPatch
1285
+ +) -> None:
1286
+ + _sealed_extension(tmp_path, monkeypatch)
1287
+ + monkeypatch.setenv("KQUANT_SQG_EXTENSION_SHA256", "0" * 64)
1288
+ + monkeypatch.setattr(
1289
+ + sqg_quantizer,
1290
+ + "_import_prebuilt_extension",
1291
+ + lambda _path: pytest.fail("mismatched extension must not be imported"),
1292
+ + )
1293
+ + monkeypatch.setattr(
1294
+ + sqg_quantizer,
1295
+ + "load",
1296
+ + lambda **_kwargs: pytest.fail("JIT builder must not run in prebuilt mode"),
1297
+ + )
1298
+ + sqg_quantizer._extension.cache_clear()
1299
+ + try:
1300
+ + with pytest.raises(RuntimeError, match="SHA256 mismatch"):
1301
+ + sqg_quantizer._extension()
1302
+ + finally:
1303
+ + sqg_quantizer._extension.cache_clear()
1304
+ +
1305
+ +
1306
+ +@pytest.mark.parametrize(
1307
+ + ("missing", "message"),
1308
+ + (
1309
+ + ("KQUANT_SQG_EXTENSION_PATH", "are both required"),
1310
+ + ("KQUANT_SQG_EXTENSION_SHA256", "are both required"),
1311
+ + ),
1312
+ +)
1313
+ +def test_required_prebuilt_extension_rejects_partial_binding_without_jit(
1314
+ + tmp_path: Path,
1315
+ + monkeypatch: pytest.MonkeyPatch,
1316
+ + missing: str,
1317
+ + message: str,
1318
+ +) -> None:
1319
+ + _sealed_extension(tmp_path, monkeypatch)
1320
+ + monkeypatch.delenv(missing)
1321
+ + monkeypatch.setattr(
1322
+ + sqg_quantizer,
1323
+ + "load",
1324
+ + lambda **_kwargs: pytest.fail("JIT builder must not run in prebuilt mode"),
1325
+ + )
1326
+ + sqg_quantizer._extension.cache_clear()
1327
+ + try:
1328
+ + with pytest.raises(RuntimeError, match=message):
1329
+ + sqg_quantizer._extension()
1330
+ + finally:
1331
+ + sqg_quantizer._extension.cache_clear()
1332
+
1333
+
1334
+ def test_rate_specific_none_dispatches_to_kquant_mcg(monkeypatch) -> None:
1335
+ @@ -88,3 +212,51 @@ def test_sqg_luts_are_transposed_by_predecessor_for_vector_loads(
1336
+ )
1337
+ assert torch.equal(actual, expected)
1338
+ assert calls[-1][6:] == (bits, 128)
1339
+ +
1340
+ +
1341
+ +@pytest.mark.parametrize("bits", [5, 6])
1342
+ +def test_k5_k6_sqg_luts_remain_in_direct_state_order(
1343
+ + monkeypatch, bits: int
1344
+ +) -> None:
1345
+ + calls: list[tuple] = []
1346
+ + monkeypatch.setattr(
1347
+ + sqg_quantizer,
1348
+ + "_sqg_temp_buffers",
1349
+ + lambda _device, _bits: (torch.empty(0), torch.empty(0)),
1350
+ + )
1351
+ + monkeypatch.setattr(
1352
+ + sqg_quantizer,
1353
+ + "_extension",
1354
+ + lambda: SimpleNamespace(quantize_tiles_sqg=lambda *args: calls.append(args)),
1355
+ + )
1356
+ + module = SimpleNamespace(quantize_tiles=lambda *_args: "upstream")
1357
+ + install_sqg_quantizer(module)
1358
+ + raw = torch.arange(65536, dtype=torch.int64).to(torch.uint8)
1359
+ + module.quantize_tiles(
1360
+ + torch.zeros((1, 256), dtype=torch.float32),
1361
+ + {"K": bits, "devices": ["cuda:0"], "sqg_e4m3_lut": raw},
1362
+ + )
1363
+ + assert torch.equal(calls[-1][5], raw)
1364
+ + assert calls[-1][6:] == (bits, 128)
1365
+ +
1366
+ +
1367
+ +@pytest.mark.skipif(not torch.cuda.is_available(), reason="CUDA is unavailable")
1368
+ +@pytest.mark.parametrize("bits", range(2, 7))
1369
+ +def test_sqg_quantizer_keeps_saturated_cost_paths_closed(bits: int) -> None:
1370
+ + module = SimpleNamespace(quantize_tiles=lambda *_args: "upstream")
1371
+ + install_sqg_quantizer(module)
1372
+ + tiles = torch.full((2, 256), 1000.0, dtype=torch.float32, device="cuda")
1373
+ +
1374
+ + _output, states = module.quantize_tiles(
1375
+ + tiles,
1376
+ + {
1377
+ + "K": bits,
1378
+ + "devices": ["cuda:0"],
1379
+ + "sqg_e4m3_lut": sqg_xor_cheb_t12_bytes(bits),
1380
+ + "tailbite_context": 128,
1381
+ + },
1382
+ + )
1383
+ +
1384
+ + edges = states.to(torch.int64) & ((1 << bits) - 1)
1385
+ + expected = reconstruct_trellis_states(edges, bits)
1386
+ + assert torch.equal(states, expected)
reproduction/closure/patches/qsrt/changed-files/qsrt/pack/qsrt_candidates.py ADDED
@@ -0,0 +1,1637 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Offline-streamed all-expert candidates for the QSRT codec."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import math
6
+ import os
7
+ from dataclasses import asdict, dataclass
8
+ from collections.abc import Mapping
9
+ from typing import Literal, Protocol, Sequence
10
+
11
+ import torch
12
+ import torch.nn.functional as F
13
+
14
+ from qsrt.capture import LayerSamples
15
+ from qsrt.exl3_reference import (
16
+ CODEBOOK_SQG_XOR_CHEB_T12,
17
+ reconstruct_trellis_states,
18
+ )
19
+ from qsrt.qsrt_candidates import (
20
+ PERMUTATION_POLICIES,
21
+ PermutationPolicy,
22
+ RatePairSelection,
23
+ RequestPartition,
24
+ RoutedRows,
25
+ build_expert_hessians,
26
+ deterministic_expert_seed,
27
+ functional_sse_by_request,
28
+ permutation_policy_contexts,
29
+ select_expert_rows,
30
+ select_phase1_rate_pair,
31
+ )
32
+ from qsrt.qsrt import (
33
+ H308,
34
+ K2,
35
+ R0,
36
+ SCHEMA,
37
+ ExpertFormatSpec,
38
+ PHASE1_MODE_IDS,
39
+ RATE_TRANSFER_MODES,
40
+ RECORDS_PER_EXPERT,
41
+ resolve_mode,
42
+ )
43
+ from qsrt.qsrt_coupled import (
44
+ CoupledHadamardExecution,
45
+ CoupledHadamardSpec,
46
+ ExpertActivation,
47
+ coupled_execution,
48
+ encode_coupled_weights,
49
+ expert_activation,
50
+ )
51
+ from qsrt.pack.qsrt_encoder import (
52
+ Layout,
53
+ MATRICES,
54
+ QSRTExpertEncoding,
55
+ QSRTMatrixCandidate,
56
+ QSRTMatrixEncoding,
57
+ QSRTTransformSeeds,
58
+ SearchLayout,
59
+ finalize_qsrt_matrix_candidate,
60
+ quantize_qsrt_matrix_candidates_batched,
61
+ quantize_qsrt_matrix_expert_batch,
62
+ )
63
+ from qsrt.tp_simulator import situ
64
+
65
+
66
+ CANDIDATE_POOL_KIND = "qsrt_kimi_k3_qsrt_candidate_pool"
67
+ CANDIDATE_POOL_SCHEMA_VERSION = 7
68
+ OFFICIAL_SOURCE_DAMAGE_METRIC = "official_source_excess_sse"
69
+ HessianPolicy = Literal["captured_blend", "identity"]
70
+ HESSIAN_POLICIES: tuple[HessianPolicy, ...] = ("captured_blend", "identity")
71
+ FOLDED_SCALE_GRID: tuple[float, ...] = (0.85, 0.925, 1.0, 1.075, 1.15)
72
+
73
+
74
+ def _debug_assert_candidate_state_closure(
75
+ candidate: QSRTMatrixCandidate,
76
+ *,
77
+ layer: int,
78
+ expert: int,
79
+ stage: str,
80
+ ) -> None:
81
+ encoded = candidate.encoded
82
+ plan = candidate.plan
83
+ tile_bits = tuple(int(value) for value in plan.encoder_tile_bits)
84
+ rate_dim = 0 if plan.rate_axis == "k" else 1
85
+ for bits in sorted(set(tile_bits)):
86
+ positions = torch.tensor(
87
+ [index for index, value in enumerate(tile_bits) if value == bits],
88
+ dtype=torch.long,
89
+ device=encoded.device,
90
+ )
91
+ selected = encoded.index_select(rate_dim, positions)
92
+ expected = reconstruct_trellis_states(selected, bits)
93
+ mismatch = selected != expected
94
+ if bool(torch.any(mismatch)):
95
+ count = int(torch.count_nonzero(mismatch))
96
+ first = tuple(
97
+ int(value)
98
+ for value in torch.nonzero(mismatch, as_tuple=False)[0]
99
+ .cpu()
100
+ .tolist()
101
+ )
102
+ raise RuntimeError(
103
+ f"layer {layer} expert {expert} {plan.matrix} R{plan.mode.mode_id} "
104
+ f"failed {stage} state closure at K{bits}: {count} states "
105
+ f"differ; first grouped coordinate {first}"
106
+ )
107
+
108
+
109
+ def _debug_assert_candidate_tree_closure(
110
+ candidates,
111
+ experts: Sequence[int],
112
+ *,
113
+ layer: int,
114
+ stage: str,
115
+ ) -> None:
116
+ if os.environ.get("QSRT_DEBUG_CANDIDATE_CLOSURE") != "1":
117
+ return
118
+ for expert, tree in zip(experts, candidates):
119
+ stack = [tree]
120
+ while stack:
121
+ value = stack.pop()
122
+ if isinstance(value, QSRTMatrixCandidate):
123
+ _debug_assert_candidate_state_closure(
124
+ value, layer=layer, expert=expert, stage=stage
125
+ )
126
+ elif isinstance(value, Mapping):
127
+ stack.extend(value.values())
128
+
129
+
130
+ class MatrixStore(Protocol):
131
+ """Read-only source that materializes one official matrix per call."""
132
+
133
+ def load_matrix(
134
+ self,
135
+ layer: int,
136
+ expert: int,
137
+ matrix: str,
138
+ *,
139
+ device: torch.device | str | None = None,
140
+ ) -> torch.Tensor: ...
141
+
142
+
143
+ @dataclass
144
+ class QSRTCandidateEncoding:
145
+ """Selected payload plus the complete phase-1 selection evidence."""
146
+
147
+ expert: QSRTExpertEncoding
148
+ selection: RatePairSelection
149
+ block_contexts: torch.Tensor
150
+ block_scores: torch.Tensor
151
+ context_basis: str
152
+ covariance: dict[str, object]
153
+ evaluated_modes: tuple[int, ...]
154
+ evaluated_formats: tuple[tuple[int, int], ...]
155
+ fit_sse: dict[tuple[int, int], torch.Tensor]
156
+ confirmation_sse: dict[tuple[int, int], torch.Tensor]
157
+ fit_reference_energy: torch.Tensor
158
+ confirmation_reference_energy: torch.Tensor
159
+ fit_counts: torch.Tensor
160
+ confirmation_counts: torch.Tensor
161
+ mode_coding: dict[tuple[int, int], dict[str, object]]
162
+
163
+ def metadata(self) -> dict[str, object]:
164
+ return {
165
+ "selection": asdict(self.selection),
166
+ "context_basis": self.context_basis,
167
+ "covariance": self.covariance,
168
+ "evaluated_modes": list(self.evaluated_modes),
169
+ "mode_coding": {
170
+ (resolve_mode(r13).name if r13 == r2 else f"R{r13}/R{r2}"): value
171
+ for (r13, r2), value in self.mode_coding.items()
172
+ },
173
+ }
174
+
175
+
176
+ def _source_middle(
177
+ gate_projection: torch.Tensor,
178
+ up_projection: torch.Tensor,
179
+ *,
180
+ activation: ExpertActivation = "situ",
181
+ ) -> torch.Tensor:
182
+ return expert_activation(
183
+ gate_projection,
184
+ up_projection,
185
+ activation=activation,
186
+ )
187
+
188
+
189
+ def _activation_basis(activation: ExpertActivation) -> str:
190
+ if activation not in ("situ", "silu"):
191
+ raise ValueError(f"unsupported expert activation: {activation}")
192
+ return f"post_{activation}"
193
+
194
+
195
+ def _folded_intermediate_conditioning(
196
+ block_scores: torch.Tensor,
197
+ block_contexts: torch.Tensor,
198
+ *,
199
+ power: float,
200
+ ) -> torch.Tensor | None:
201
+ """Derive a metadata-free per-record output conditioning profile.
202
+
203
+ The source rows are divided by this profile before w1/w3 quantization and
204
+ the exact inverse is folded into their existing expert-local ``svh``
205
+ vectors. Factors are constant over each final 128-channel Hadamard block,
206
+ so the fold commutes with the transform and requires no new runtime tensor.
207
+ """
208
+
209
+ if not math.isfinite(power):
210
+ raise ValueError("folded scale power must be finite")
211
+ if power == 0.0:
212
+ return None
213
+ if block_scores.ndim != 1 or block_scores.numel() != 3072 // 4:
214
+ raise ValueError("folded conditioning requires 768 group scores")
215
+ if not bool(torch.all(torch.isfinite(block_scores))) or bool(
216
+ torch.any(block_scores < 0)
217
+ ):
218
+ raise ValueError("folded conditioning scores must be finite and nonnegative")
219
+ contexts = block_contexts.to(device=block_scores.device, dtype=torch.long)
220
+ group_energy = block_scores.float()
221
+ record_energy = torch.zeros(
222
+ RECORDS_PER_EXPERT, device=block_scores.device, dtype=torch.float32
223
+ ).scatter_add_(0, contexts, group_energy.float())
224
+ counts = torch.bincount(contexts, minlength=RECORDS_PER_EXPERT).float()
225
+ record_rms = (record_energy / counts).clamp_min(1e-30).sqrt()
226
+ geometric_mean = record_rms.log().mean().exp()
227
+ # A smaller folded scale magnifies important rows inside the trellis
228
+ # search and shrinks their absolute error again when folded back into svh.
229
+ # This is an output-metric conditioning heuristic, not a new runtime scale.
230
+ desired = (record_rms / geometric_mean).pow(-power)
231
+ grid = torch.tensor(FOLDED_SCALE_GRID, device=desired.device)
232
+ selected = grid[(desired[:, None] - grid[None, :]).abs().argmin(dim=1)]
233
+ return selected.index_select(0, contexts).repeat_interleave(4).contiguous()
234
+
235
+
236
+ def _load_source_matrix(
237
+ store: MatrixStore,
238
+ layer: int,
239
+ expert: int,
240
+ matrix: str,
241
+ device: torch.device,
242
+ ) -> torch.Tensor:
243
+ source = store.load_matrix(layer, expert, matrix, device=device)
244
+ if source.device != device:
245
+ raise ValueError(
246
+ f"official source store returned {source.device}, expected {device}"
247
+ )
248
+ if source.dtype != torch.float32:
249
+ raise ValueError(
250
+ f"official source store returned {source.dtype}, expected torch.float32"
251
+ )
252
+ return source.contiguous()
253
+
254
+
255
+ def _split_rows(rows: RoutedRows, requests: dict[int, str]) -> torch.Tensor:
256
+ allowed = torch.tensor(
257
+ sorted(requests), dtype=rows.request_steps.dtype, device=rows.request_steps.device
258
+ )
259
+ return torch.isin(rows.request_steps, allowed)
260
+
261
+
262
+ def _empty_metrics(requests: dict[int, str]) -> tuple[torch.Tensor, torch.Tensor, torch.Tensor]:
263
+ count = len(requests)
264
+ return (
265
+ torch.zeros(count, dtype=torch.float64),
266
+ torch.zeros(count, dtype=torch.float64),
267
+ torch.zeros(count, dtype=torch.int64),
268
+ )
269
+
270
+
271
+ @dataclass(frozen=True)
272
+ class _DeferredFunctionalRows:
273
+ """Static routed-metric state shared by every candidate for one fold."""
274
+
275
+ device_mask: torch.Tensor
276
+ reference: torch.Tensor
277
+ route_weights: torch.Tensor
278
+ request_indices: torch.Tensor
279
+ reference_energy: torch.Tensor
280
+ counts: torch.Tensor
281
+ request_count: int
282
+
283
+
284
+ def _prepare_deferred_functional_rows(
285
+ reference: torch.Tensor,
286
+ gates: torch.Tensor,
287
+ request_steps: torch.Tensor,
288
+ mask: torch.Tensor,
289
+ requests: dict[int, str],
290
+ *,
291
+ device: torch.device,
292
+ ) -> _DeferredFunctionalRows:
293
+ """Prepare invariant metric terms without changing their arithmetic."""
294
+
295
+ device_mask = mask.to(device=device)
296
+ selected_reference = reference[device_mask].double()
297
+ selected_gates = gates[device_mask]
298
+ selected_steps = request_steps[mask]
299
+ ordered_steps = sorted(map(int, requests))
300
+ positions = {step: index for index, step in enumerate(ordered_steps)}
301
+ try:
302
+ request_indices = torch.tensor(
303
+ [positions[int(step)] for step in selected_steps.cpu().tolist()],
304
+ dtype=torch.long,
305
+ )
306
+ except KeyError as exc:
307
+ raise ValueError(
308
+ f"metric row has unmapped request epoch {exc.args[0]}"
309
+ ) from exc
310
+ route_weights = selected_gates.double().square().cpu()
311
+ row_reference = (
312
+ selected_reference.square().sum(dim=1).cpu() * route_weights
313
+ )
314
+ reference_energy = torch.zeros(len(ordered_steps), dtype=torch.float64)
315
+ counts = torch.zeros(len(ordered_steps), dtype=torch.int64)
316
+ reference_energy.scatter_add_(0, request_indices, row_reference)
317
+ counts.scatter_add_(
318
+ 0,
319
+ request_indices,
320
+ torch.ones_like(request_indices, dtype=torch.int64),
321
+ )
322
+ return _DeferredFunctionalRows(
323
+ device_mask=device_mask,
324
+ reference=selected_reference,
325
+ route_weights=route_weights,
326
+ request_indices=request_indices,
327
+ reference_energy=reference_energy,
328
+ counts=counts,
329
+ request_count=len(ordered_steps),
330
+ )
331
+
332
+
333
+ def _defer_functional_row_sse(
334
+ plan: _DeferredFunctionalRows,
335
+ candidate: torch.Tensor,
336
+ ) -> torch.Tensor:
337
+ """Compute per-row SSE on CUDA and defer its host synchronization."""
338
+
339
+ delta = candidate[plan.device_mask].double() - plan.reference
340
+ return delta.square().sum(dim=1)
341
+
342
+
343
+ def _finish_deferred_functional_sse(
344
+ plan: _DeferredFunctionalRows,
345
+ keys: Sequence[tuple[int, int]],
346
+ row_sse: Sequence[torch.Tensor],
347
+ ) -> dict[tuple[int, int], torch.Tensor]:
348
+ """Transfer all candidate rows once, then reproduce the CPU reductions."""
349
+
350
+ if len(keys) != len(row_sse):
351
+ raise ValueError("deferred functional metric keys and rows differ")
352
+ if not keys:
353
+ return {}
354
+ rows_cpu = torch.stack(tuple(row_sse)).cpu()
355
+ result: dict[tuple[int, int], torch.Tensor] = {}
356
+ for key, values in zip(keys, rows_cpu):
357
+ sse = torch.zeros(plan.request_count, dtype=torch.float64)
358
+ sse.scatter_add_(
359
+ 0,
360
+ plan.request_indices,
361
+ values * plan.route_weights,
362
+ )
363
+ result[key] = sse
364
+ return result
365
+
366
+
367
+ def _mode_evidence(encodings: dict[str, QSRTMatrixEncoding]) -> dict[str, object]:
368
+ trellis_bytes = sum(
369
+ value.tensors["trellis"].numel()
370
+ * value.tensors["trellis"].element_size()
371
+ for value in encodings.values()
372
+ )
373
+ scale_bytes = sum(
374
+ value.tensors[name].numel() * value.tensors[name].element_size()
375
+ for value in encodings.values()
376
+ for name in ("suh", "svh")
377
+ )
378
+ return {
379
+ "trellis_bytes": trellis_bytes,
380
+ "scale_bytes": scale_bytes,
381
+ "total_bytes_before_layer_deduplication": trellis_bytes + scale_bytes,
382
+ "matrices": {
383
+ matrix: {
384
+ "proxy": float(value.coding["proxy"]),
385
+ "mode": value.coding["mode"],
386
+ "trellis_descriptor": value.coding["trellis_descriptor"],
387
+ }
388
+ for matrix, value in encodings.items()
389
+ },
390
+ }
391
+
392
+
393
+ def _candidate_mode_evidence(encodings: dict[str, object]) -> dict[str, object]:
394
+ trellis_bytes = sum(
395
+ value.reconstruction.numel()
396
+ * sum(value.plan.mode.context_bits)
397
+ // (len(value.plan.mode.context_bits) * 8)
398
+ for value in encodings.values()
399
+ )
400
+ scale_bytes = sum(
401
+ value.tensors[name].numel() * value.tensors[name].element_size()
402
+ for value in encodings.values()
403
+ for name in ("suh", "svh")
404
+ )
405
+ return {
406
+ "trellis_bytes": trellis_bytes,
407
+ "scale_bytes": scale_bytes,
408
+ "total_bytes_before_layer_deduplication": trellis_bytes + scale_bytes,
409
+ "matrices": {
410
+ matrix: {
411
+ "proxy": float(value.proxy),
412
+ "mode": value.plan.mode.name,
413
+ "mode_id": value.plan.mode.mode_id,
414
+ "rate_axis": value.plan.rate_axis,
415
+ }
416
+ for matrix, value in encodings.items()
417
+ },
418
+ }
419
+
420
+
421
+ def _candidate_middle_by_r13(
422
+ inputs: torch.Tensor,
423
+ upstream: dict[str, dict[int, QSRTMatrixCandidate]],
424
+ evaluated_modes: Sequence[int],
425
+ *,
426
+ activation: ExpertActivation = "situ",
427
+ ) -> dict[int, torch.Tensor]:
428
+ """Replay exact candidate reconstructions through the model activation."""
429
+
430
+ return {
431
+ int(r13): _source_middle(
432
+ F.linear(inputs, upstream["w1"][int(r13)].reconstruction),
433
+ F.linear(inputs, upstream["w3"][int(r13)].reconstruction),
434
+ activation=activation,
435
+ )
436
+ for r13 in evaluated_modes
437
+ }
438
+
439
+
440
+ def _conditional_h2_by_r13(
441
+ inputs: torch.Tensor,
442
+ gates: torch.Tensor,
443
+ fit_mask_device: torch.Tensor,
444
+ middle_by_r13: dict[int, torch.Tensor],
445
+ *,
446
+ global_h13: torch.Tensor,
447
+ global_h2: torch.Tensor,
448
+ device: torch.device,
449
+ hessian_policy: HessianPolicy,
450
+ have_local_support: bool,
451
+ ) -> tuple[dict[int, torch.Tensor], dict[str, object]]:
452
+ """Build one support-aware down-projection covariance per upstream mode."""
453
+
454
+ h2_by_r13: dict[int, torch.Tensor] = {}
455
+ evidence_by_r13: dict[str, object] = {}
456
+ identity_h2 = torch.eye(
457
+ global_h2.shape[0], dtype=torch.float32, device=device
458
+ )
459
+ for r13, middle in middle_by_r13.items():
460
+ if hessian_policy == "identity" or not have_local_support:
461
+ h2_by_r13[r13] = identity_h2
462
+ evidence_by_r13[f"R{r13}"] = {
463
+ "h2_shrinkage_policy": "identity_fallback",
464
+ "h2_local_alpha": 0.0,
465
+ "h2_effective_sample_size": 0.0,
466
+ "h2_identity_scale": 1.0,
467
+ }
468
+ continue
469
+ _, h2, evidence = build_expert_hessians(
470
+ inputs[fit_mask_device],
471
+ gates[fit_mask_device],
472
+ middle[fit_mask_device],
473
+ global_h13=global_h13,
474
+ global_h2=global_h2,
475
+ device=device,
476
+ )
477
+ h2_by_r13[r13] = h2
478
+ evidence_by_r13[f"R{r13}"] = evidence
479
+ return h2_by_r13, evidence_by_r13
480
+
481
+
482
+ def _coupled_logical_block_contexts(
483
+ mode_id: int,
484
+ groups: int,
485
+ ) -> torch.Tensor:
486
+ """Label coupled coordinates without changing their LDLQ traversal order."""
487
+
488
+ context_count = resolve_mode(mode_id).context_count
489
+ if groups <= 0 or groups % context_count:
490
+ raise ValueError("coupled contexts do not divide neuron groups")
491
+ return torch.arange(context_count, dtype=torch.long).repeat_interleave(
492
+ groups // context_count
493
+ )
494
+
495
+
496
+ def _quantize_conditional_down_grid(
497
+ source_w2_by_expert: Sequence[torch.Tensor],
498
+ block_contexts_by_expert: Sequence[torch.Tensor],
499
+ mode_specs_by_expert: Sequence[tuple[object, ...]],
500
+ h2_by_r13_by_expert: Sequence[dict[int, torch.Tensor]],
501
+ *,
502
+ layer: int,
503
+ device: torch.device,
504
+ shared_scale_scope: object,
505
+ quantizer_module: object | None,
506
+ codebook: str,
507
+ layout: SearchLayout,
508
+ ldlq_tf32: bool,
509
+ tailbite_context: int,
510
+ transform_seeds_by_expert: Sequence[
511
+ Mapping[str, QSRTTransformSeeds]
512
+ ] | None = None,
513
+ ) -> list[dict[int, dict[int, QSRTMatrixCandidate]]]:
514
+ """Encode the exhaustive ``w2[r13, r2]`` grid in flattened GPU batches."""
515
+
516
+ count = len(source_w2_by_expert)
517
+ if not (
518
+ count
519
+ == len(block_contexts_by_expert)
520
+ == len(mode_specs_by_expert)
521
+ == len(h2_by_r13_by_expert)
522
+ ):
523
+ raise ValueError("conditional down-grid inputs have inconsistent lengths")
524
+ if transform_seeds_by_expert is None:
525
+ transform_seeds_by_expert = [{} for _ in range(count)]
526
+ elif len(transform_seeds_by_expert) != count:
527
+ raise ValueError("conditional down-grid transform seeds have the wrong length")
528
+
529
+ flat_keys: list[tuple[int, int]] = []
530
+ flat_sources: list[dict[str, torch.Tensor]] = []
531
+ flat_contexts: list[torch.Tensor] = []
532
+ flat_modes: list[tuple[object, ...]] = []
533
+ flat_hessians: list[dict[str, torch.Tensor]] = []
534
+ flat_transform_seeds: list[Mapping[str, QSRTTransformSeeds]] = []
535
+ for expert_index, (source, contexts, modes, h2_by_r13) in enumerate(
536
+ zip(
537
+ source_w2_by_expert,
538
+ block_contexts_by_expert,
539
+ mode_specs_by_expert,
540
+ h2_by_r13_by_expert,
541
+ )
542
+ ):
543
+ mode_ids = tuple(int(mode.mode_id) for mode in modes)
544
+ h2_bases = tuple(h2_by_r13)
545
+ if h2_bases != mode_ids:
546
+ raise ValueError("conditional H2 modes differ from upstream modes")
547
+ for r13 in h2_bases:
548
+ flat_keys.append((expert_index, r13))
549
+ flat_sources.append({"w2": source})
550
+ flat_contexts.append(contexts)
551
+ flat_modes.append(modes)
552
+ flat_hessians.append({"w2": h2_by_r13[r13]})
553
+ flat_transform_seeds.append(transform_seeds_by_expert[expert_index])
554
+
555
+ guarded_reuse = layout == "qsrt_guarded_reuse"
556
+ if guarded_reuse:
557
+ flat_candidates = quantize_qsrt_matrix_expert_batch(
558
+ flat_sources,
559
+ flat_contexts,
560
+ modes_by_expert=[(modes[0],) for modes in flat_modes],
561
+ hessians_by_expert=flat_hessians,
562
+ layer=layer,
563
+ device=device,
564
+ shared_scale_scope=shared_scale_scope,
565
+ quantizer_module=quantizer_module,
566
+ codebook=codebook,
567
+ layout="importance_ordered",
568
+ ldlq_tf32=ldlq_tf32,
569
+ tailbite_context=tailbite_context,
570
+ transform_seeds_by_expert=flat_transform_seeds,
571
+ )
572
+ shifted_indices = [
573
+ index for index, modes in enumerate(flat_modes) if len(modes) > 1
574
+ ]
575
+ if shifted_indices:
576
+ shifted = quantize_qsrt_matrix_expert_batch(
577
+ [flat_sources[index] for index in shifted_indices],
578
+ [flat_contexts[index] for index in shifted_indices],
579
+ modes_by_expert=[flat_modes[index][1:] for index in shifted_indices],
580
+ hessians_by_expert=[flat_hessians[index] for index in shifted_indices],
581
+ layer=layer,
582
+ device=device,
583
+ shared_scale_scope=shared_scale_scope,
584
+ quantizer_module=quantizer_module,
585
+ codebook=codebook,
586
+ layout="qsrt_pair_prefix_reuse",
587
+ ldlq_tf32=ldlq_tf32,
588
+ tailbite_context=tailbite_context,
589
+ transform_seeds_by_expert=[
590
+ flat_transform_seeds[index] for index in shifted_indices
591
+ ],
592
+ )
593
+ for index, extra in zip(shifted_indices, shifted):
594
+ flat_candidates[index]["w2"].update(extra["w2"])
595
+ else:
596
+ flat_candidates = quantize_qsrt_matrix_expert_batch(
597
+ flat_sources,
598
+ flat_contexts,
599
+ modes_by_expert=flat_modes,
600
+ hessians_by_expert=flat_hessians,
601
+ layer=layer,
602
+ device=device,
603
+ shared_scale_scope=shared_scale_scope,
604
+ quantizer_module=quantizer_module,
605
+ codebook=codebook,
606
+ layout=layout,
607
+ ldlq_tf32=ldlq_tf32,
608
+ tailbite_context=tailbite_context,
609
+ transform_seeds_by_expert=flat_transform_seeds,
610
+ )
611
+
612
+ result: list[dict[int, dict[int, QSRTMatrixCandidate]]] = [
613
+ {} for _ in range(count)
614
+ ]
615
+ for (expert_index, r13), candidates in zip(flat_keys, flat_candidates):
616
+ result[expert_index][r13] = candidates["w2"]
617
+ return result
618
+
619
+
620
+ def encode_phase1_expert(
621
+ store: MatrixStore,
622
+ samples: LayerSamples,
623
+ *,
624
+ layer: int,
625
+ expert: int,
626
+ partition: RequestPartition,
627
+ global_h13: torch.Tensor,
628
+ global_h2: torch.Tensor,
629
+ fallback_block_contexts: torch.Tensor,
630
+ fallback_block_scores: torch.Tensor,
631
+ device: torch.device,
632
+ shared_scale_scope: object,
633
+ mode_ids: Sequence[int] = PHASE1_MODE_IDS,
634
+ quantizer_module: object | None = None,
635
+ min_fit_documents: int = 6,
636
+ min_confirmation_documents: int = 4,
637
+ bootstrap_replicates: int = 2_000,
638
+ minimum_improvement: float = 0.0,
639
+ logical_trellis_schema: str = SCHEMA,
640
+ codebook: str = CODEBOOK_SQG_XOR_CHEB_T12,
641
+ layout: SearchLayout = "importance_ordered",
642
+ ldlq_tf32: bool = False,
643
+ tailbite_context: int = 128,
644
+ hessian_policy: HessianPolicy = "captured_blend",
645
+ permutation_policy: PermutationPolicy = "h2_reverse",
646
+ folded_scale_power: float = 0.0,
647
+ transform_seeds: Mapping[str, QSRTTransformSeeds] | None = None,
648
+ activation: ExpertActivation = "situ",
649
+ ) -> QSRTCandidateEncoding:
650
+ """Encode and conservatively select one official-source expert.
651
+
652
+ The official model is never instantiated. ``w1`` and ``w3`` are streamed
653
+ together so their same-shape R candidates can share one batched traversal;
654
+ they are released before ``w2`` is loaded.
655
+ """
656
+
657
+ if device.type != "cuda":
658
+ raise ValueError("QSRT candidate encoding requires CUDA")
659
+ if not 1 <= layer <= 92 or not 0 <= expert < 896:
660
+ raise ValueError("invalid K3 layer/expert assignment")
661
+ modes = tuple(int(mode) for mode in mode_ids)
662
+ fixed_k3 = modes == (R0.mode_id,)
663
+ fixed_high_rate = modes == (H308.mode_id,)
664
+ fixed_k2 = modes == (K2.mode_id,)
665
+ fixed_profile = fixed_k3 or fixed_high_rate or fixed_k2
666
+ if (
667
+ not modes
668
+ or len(set(modes)) != len(modes)
669
+ or (not fixed_profile and modes[0] != 0)
670
+ ):
671
+ raise ValueError(
672
+ "mode_ids must be H308/K2 alone or unique and begin with R0"
673
+ )
674
+ if any(mode not in (0, 1, 2, H308.mode_id, K2.mode_id) for mode in modes):
675
+ raise ValueError("mode_ids contain an unsupported schedule")
676
+ if hessian_policy not in HESSIAN_POLICIES:
677
+ raise ValueError(f"unsupported Hessian policy: {hessian_policy}")
678
+ if permutation_policy not in PERMUTATION_POLICIES:
679
+ raise ValueError(f"unsupported permutation policy: {permutation_policy}")
680
+
681
+ all_rows = select_expert_rows(samples, expert, partition.all)
682
+ fit_mask = _split_rows(all_rows, partition.fit)
683
+ confirmation_mask = _split_rows(all_rows, partition.confirmation)
684
+ fit_documents = int(torch.unique(all_rows.request_steps[fit_mask]).numel())
685
+ confirmation_documents = int(
686
+ torch.unique(all_rows.request_steps[confirmation_mask]).numel()
687
+ )
688
+ inputs = all_rows.inputs.float().to(device=device)
689
+ gates = all_rows.gates.float().to(device=device)
690
+
691
+ source_w1 = _load_source_matrix(store, layer, expert, "w1", device)
692
+ source_w3 = _load_source_matrix(store, layer, expert, "w3", device)
693
+ if all_rows.rows:
694
+ source_gate = F.linear(inputs, source_w1)
695
+ source_up = F.linear(inputs, source_w3)
696
+ source_middle = _source_middle(
697
+ source_gate,
698
+ source_up,
699
+ activation=activation,
700
+ )
701
+ del source_gate, source_up
702
+ else:
703
+ source_middle = torch.empty(
704
+ (0, global_h2.shape[0]), dtype=torch.float32, device=device
705
+ )
706
+
707
+ have_local_support = fit_documents >= min_fit_documents
708
+ fit_mask_device = fit_mask.to(device=device)
709
+ if have_local_support:
710
+ block_contexts, block_scores = permutation_policy_contexts(
711
+ source_middle[fit_mask_device],
712
+ gates[fit_mask_device],
713
+ policy=permutation_policy,
714
+ )
715
+ h13 = global_h13
716
+ covariance: dict[str, object] = {
717
+ "gate_square_sum": float(
718
+ gates[fit_mask_device].square().double().sum()
719
+ ),
720
+ "h13_local_alpha": 0.0,
721
+ }
722
+ context_basis = (
723
+ f"official_source_{_activation_basis(activation)}_fit_documents:"
724
+ f"{permutation_policy}"
725
+ )
726
+ covariance = {
727
+ **covariance,
728
+ "fit_rows": int(fit_mask.sum()),
729
+ "fit_documents": fit_documents,
730
+ }
731
+ else:
732
+ block_contexts = fallback_block_contexts.clone()
733
+ block_scores = fallback_block_scores.clone()
734
+ h13 = global_h13
735
+ context_basis = "fallback_context_order_no_local_support"
736
+ covariance = {
737
+ "fit_rows": int(fit_mask.sum()),
738
+ "fit_documents": fit_documents,
739
+ "gate_square_sum": float(gates[fit_mask_device].square().sum()),
740
+ "h13_local_alpha": 0.0,
741
+ }
742
+
743
+ if fixed_k2:
744
+ block_contexts = torch.zeros_like(block_contexts)
745
+ context_basis = "uniform_k2_identity_transformed_coordinate_order"
746
+ can_confirm = confirmation_documents >= min_confirmation_documents
747
+ evaluated_modes = (
748
+ modes if fixed_profile or (have_local_support and can_confirm) else (0,)
749
+ )
750
+ evaluated_formats = tuple(
751
+ (r13, r2) for r13 in evaluated_modes for r2 in evaluated_modes
752
+ )
753
+ block_contexts_device = block_contexts.to(device=device, dtype=torch.long)
754
+ intermediate_conditioning = _folded_intermediate_conditioning(
755
+ block_scores.to(device=device),
756
+ block_contexts_device,
757
+ power=folded_scale_power,
758
+ )
759
+ if intermediate_conditioning is not None:
760
+ covariance["folded_scale_power"] = float(folded_scale_power)
761
+ covariance["folded_scale_min"] = float(intermediate_conditioning.min())
762
+ covariance["folded_scale_max"] = float(intermediate_conditioning.max())
763
+ context_basis += "+folded_128_channel_conditioning"
764
+
765
+ mode_specs = tuple(resolve_mode(mode) for mode in evaluated_modes)
766
+ guarded_reuse = layout == "qsrt_guarded_reuse"
767
+ if guarded_reuse and any(mode > 2 for mode in evaluated_modes):
768
+ raise ValueError("qsrt_guarded_reuse supports only R0 through R2")
769
+ upstream_layout: Layout = "importance_ordered" if guarded_reuse else layout
770
+ upstream_candidates = quantize_qsrt_matrix_candidates_batched(
771
+ {"w1": source_w1, "w3": source_w3},
772
+ block_contexts_device,
773
+ modes=mode_specs,
774
+ hessians={"w1": h13, "w3": h13},
775
+ layer=layer,
776
+ device=device,
777
+ shared_scale_scope=shared_scale_scope,
778
+ quantizer_module=quantizer_module,
779
+ codebook=codebook,
780
+ layout=upstream_layout,
781
+ ldlq_tf32=ldlq_tf32,
782
+ tailbite_context=tailbite_context,
783
+ transform_seeds=transform_seeds,
784
+ intermediate_conditioning=intermediate_conditioning,
785
+ )
786
+ del source_w1, source_w3
787
+
788
+ middle_by_r13 = _candidate_middle_by_r13(
789
+ inputs,
790
+ upstream_candidates,
791
+ evaluated_modes,
792
+ activation=activation,
793
+ )
794
+ h2_by_r13, h2_evidence = _conditional_h2_by_r13(
795
+ inputs,
796
+ gates,
797
+ fit_mask_device,
798
+ middle_by_r13,
799
+ global_h13=global_h13,
800
+ global_h2=global_h2,
801
+ device=device,
802
+ hessian_policy=hessian_policy,
803
+ have_local_support=have_local_support,
804
+ )
805
+ covariance.update(
806
+ {
807
+ "basis": (
808
+ "identity"
809
+ if hessian_policy == "identity"
810
+ else (
811
+ f"decoded_candidate_{_activation_basis(activation)}_"
812
+ "adaptive_shrinkage"
813
+ if have_local_support
814
+ else "identity_support_fallback"
815
+ )
816
+ ),
817
+ "h2_by_r13": h2_evidence,
818
+ }
819
+ )
820
+ context_basis += f"+decoded_candidate_{_activation_basis(activation)}_h2"
821
+
822
+ source_w2 = _load_source_matrix(store, layer, expert, "w2", device)
823
+ if all_rows.rows:
824
+ reference_output = F.linear(source_middle, source_w2)
825
+ else:
826
+ reference_output = torch.empty(
827
+ (0, global_h13.shape[0]), dtype=torch.float32, device=device
828
+ )
829
+ down_candidates = _quantize_conditional_down_grid(
830
+ [source_w2],
831
+ [block_contexts_device],
832
+ [mode_specs],
833
+ [h2_by_r13],
834
+ layer=layer,
835
+ device=device,
836
+ shared_scale_scope=shared_scale_scope,
837
+ quantizer_module=quantizer_module,
838
+ codebook=codebook,
839
+ layout=layout,
840
+ ldlq_tf32=ldlq_tf32,
841
+ tailbite_context=tailbite_context,
842
+ transform_seeds_by_expert=[transform_seeds or {}],
843
+ )[0]
844
+ fit_sse: dict[tuple[int, int], torch.Tensor] = {}
845
+ confirmation_sse: dict[tuple[int, int], torch.Tensor] = {}
846
+ fit_reference = fit_counts = confirmation_reference = confirmation_counts = None
847
+ mode_coding: dict[tuple[int, int], dict[str, object]] = {}
848
+ for rate_pair in evaluated_formats:
849
+ r13, r2 = rate_pair
850
+ candidate_output = F.linear(
851
+ middle_by_r13[r13], down_candidates[r13][r2].reconstruction
852
+ )
853
+ fit_metric = (
854
+ functional_sse_by_request(
855
+ reference_output[fit_mask.to(device=device)],
856
+ candidate_output[fit_mask.to(device=device)],
857
+ gates[fit_mask.to(device=device)],
858
+ all_rows.request_steps[fit_mask],
859
+ partition.fit,
860
+ )
861
+ if int(fit_mask.sum())
862
+ else _empty_metrics(partition.fit)
863
+ )
864
+ confirmation_metric = (
865
+ functional_sse_by_request(
866
+ reference_output[confirmation_mask.to(device=device)],
867
+ candidate_output[confirmation_mask.to(device=device)],
868
+ gates[confirmation_mask.to(device=device)],
869
+ all_rows.request_steps[confirmation_mask],
870
+ partition.confirmation,
871
+ )
872
+ if int(confirmation_mask.sum())
873
+ else _empty_metrics(partition.confirmation)
874
+ )
875
+ fit_sse[rate_pair] = fit_metric[0]
876
+ confirmation_sse[rate_pair] = confirmation_metric[0]
877
+ if fit_reference is None:
878
+ fit_reference, fit_counts = fit_metric[1], fit_metric[2]
879
+ confirmation_reference, confirmation_counts = (
880
+ confirmation_metric[1],
881
+ confirmation_metric[2],
882
+ )
883
+ elif not (
884
+ torch.equal(fit_reference, fit_metric[1])
885
+ and torch.equal(fit_counts, fit_metric[2])
886
+ and torch.equal(confirmation_reference, confirmation_metric[1])
887
+ and torch.equal(confirmation_counts, confirmation_metric[2])
888
+ ):
889
+ raise ValueError("mode candidates changed metric support or reference energy")
890
+ mode_coding[rate_pair] = _candidate_mode_evidence(
891
+ {
892
+ "w1": upstream_candidates["w1"][r13],
893
+ "w3": upstream_candidates["w3"][r13],
894
+ "w2": down_candidates[r13][r2],
895
+ }
896
+ )
897
+ del candidate_output
898
+
899
+ del source_w2
900
+
901
+ assert fit_reference is not None and fit_counts is not None
902
+ assert confirmation_reference is not None and confirmation_counts is not None
903
+ if fixed_profile:
904
+ fixed_mode = H308 if fixed_high_rate else (K2 if fixed_k2 else R0)
905
+ selection = RatePairSelection(
906
+ proposed_r13=fixed_mode.mode_id,
907
+ proposed_r2=fixed_mode.mode_id,
908
+ selected_r13=fixed_mode.mode_id,
909
+ selected_r2=fixed_mode.mode_id,
910
+ accepted=True,
911
+ reason=(
912
+ "fixed_22k3_2k4_high_rate_profile"
913
+ if fixed_high_rate
914
+ else (
915
+ "fixed_uniform_k2_profile"
916
+ if fixed_k2
917
+ else "fixed_uniform_k3_profile"
918
+ )
919
+ ),
920
+ fit_documents=int(torch.count_nonzero(fit_counts)),
921
+ confirmation_documents=int(torch.count_nonzero(confirmation_counts)),
922
+ confirmation_relative_improvement=None,
923
+ confirmation_ci95=(None, None),
924
+ bootstrap_replicates_valid=0,
925
+ )
926
+ else:
927
+ selection = select_phase1_rate_pair(
928
+ fit_sse,
929
+ confirmation_sse,
930
+ fit_counts=fit_counts,
931
+ confirmation_counts=confirmation_counts,
932
+ modes=evaluated_formats,
933
+ min_fit_documents=min_fit_documents,
934
+ min_confirmation_documents=min_confirmation_documents,
935
+ minimum_improvement=minimum_improvement,
936
+ bootstrap_replicates=bootstrap_replicates,
937
+ seed=deterministic_expert_seed(layer, expert),
938
+ )
939
+ selected_r13, selected_r2 = selection.selected
940
+ selected_candidates = {
941
+ "w1": upstream_candidates["w1"][selected_r13],
942
+ "w3": upstream_candidates["w3"][selected_r13],
943
+ "w2": down_candidates[selected_r13][selected_r2],
944
+ }
945
+ selected_encodings = {
946
+ matrix: finalize_qsrt_matrix_candidate(
947
+ value,
948
+ layer=layer,
949
+ logical_trellis_schema=logical_trellis_schema,
950
+ codebook=codebook,
951
+ tailbite_context=tailbite_context,
952
+ )
953
+ for matrix, value in selected_candidates.items()
954
+ }
955
+ physical_permutation = selected_encodings["w1"].plan.physical_permutation
956
+ for matrix in ("w3", "w2"):
957
+ if not torch.equal(
958
+ selected_encodings[matrix].plan.physical_permutation,
959
+ physical_permutation,
960
+ ):
961
+ raise ValueError("selected matrices do not share one physical permutation")
962
+ expert_encoding = QSRTExpertEncoding(
963
+ format=ExpertFormatSpec.compressed(selected_r13, selected_r2),
964
+ matrices=selected_encodings,
965
+ physical_permutation=physical_permutation,
966
+ coding={
967
+ "format": ExpertFormatSpec.compressed(
968
+ selected_r13, selected_r2
969
+ ).name,
970
+ "r13": selected_r13,
971
+ "r2": selected_r2,
972
+ "codebook": codebook,
973
+ "tailbite_context": int(tailbite_context),
974
+ **_mode_evidence(selected_encodings),
975
+ },
976
+ )
977
+ return QSRTCandidateEncoding(
978
+ expert=expert_encoding,
979
+ selection=selection,
980
+ block_contexts=block_contexts.detach().cpu().to(torch.uint8).contiguous(),
981
+ block_scores=block_scores.detach().cpu().float().contiguous(),
982
+ context_basis=context_basis,
983
+ covariance=covariance,
984
+ evaluated_modes=evaluated_modes,
985
+ evaluated_formats=evaluated_formats,
986
+ fit_sse=fit_sse,
987
+ confirmation_sse=confirmation_sse,
988
+ fit_reference_energy=fit_reference,
989
+ confirmation_reference_energy=confirmation_reference,
990
+ fit_counts=fit_counts,
991
+ confirmation_counts=confirmation_counts,
992
+ mode_coding=mode_coding,
993
+ )
994
+
995
+
996
+ def encode_phase1_expert_batch(
997
+ store: MatrixStore,
998
+ samples: LayerSamples,
999
+ *,
1000
+ layer: int,
1001
+ experts: Sequence[int],
1002
+ partition: RequestPartition,
1003
+ global_h13: torch.Tensor,
1004
+ global_h2: torch.Tensor,
1005
+ fallback_block_contexts: torch.Tensor,
1006
+ fallback_block_scores: torch.Tensor,
1007
+ device: torch.device,
1008
+ shared_scale_scope: object,
1009
+ mode_ids: Sequence[int] = PHASE1_MODE_IDS,
1010
+ quantizer_module: object | None = None,
1011
+ min_fit_documents: int = 6,
1012
+ min_confirmation_documents: int = 4,
1013
+ bootstrap_replicates: int = 2_000,
1014
+ minimum_improvement: float = 0.0,
1015
+ logical_trellis_schema: str = SCHEMA,
1016
+ codebook: str = CODEBOOK_SQG_XOR_CHEB_T12,
1017
+ layout: SearchLayout = "importance_ordered",
1018
+ ldlq_tf32: bool = False,
1019
+ tailbite_context: int = 128,
1020
+ hessian_policy: HessianPolicy = "captured_blend",
1021
+ permutation_policy: PermutationPolicy = "h2_reverse",
1022
+ folded_scale_power: float = 0.0,
1023
+ transform_seeds_by_expert: Mapping[
1024
+ int, Mapping[str, QSRTTransformSeeds]
1025
+ ] | None = None,
1026
+ coupled_intermediate_draws_by_expert: Mapping[int, int] | None = None,
1027
+ activation: ExpertActivation = "situ",
1028
+ ) -> list[QSRTCandidateEncoding]:
1029
+ """Encode several experts while batching their independent trellis work.
1030
+
1031
+ This preserves the single-expert calibration, dense-H, candidate scoring,
1032
+ and selection contracts. Only the execution schedule changes: all
1033
+ same-shape w1/w3 projections in the chunk are submitted together, followed
1034
+ by all w2 projections. The larger tile batches fill SM120 much more
1035
+ effectively than one expert's R1/R2 replacement records.
1036
+ """
1037
+
1038
+ expert_ids = tuple(int(expert) for expert in experts)
1039
+ if not expert_ids or len(set(expert_ids)) != len(expert_ids):
1040
+ raise ValueError("expert batch must be nonempty and unique")
1041
+ if device.type != "cuda":
1042
+ raise ValueError("QSRT candidate encoding requires CUDA")
1043
+ if not 1 <= layer <= 92 or any(not 0 <= expert < 896 for expert in expert_ids):
1044
+ raise ValueError("invalid K3 layer/expert assignment")
1045
+ modes = tuple(int(mode) for mode in mode_ids)
1046
+ fixed_k3 = modes == (R0.mode_id,)
1047
+ fixed_high_rate = modes == (H308.mode_id,)
1048
+ fixed_k2 = modes == (K2.mode_id,)
1049
+ fixed_profile = fixed_k3 or fixed_high_rate or fixed_k2
1050
+ coupled = coupled_intermediate_draws_by_expert is not None
1051
+ _activation_basis(activation)
1052
+ if coupled:
1053
+ if modes not in (
1054
+ (R0.mode_id,),
1055
+ (H308.mode_id,),
1056
+ (K2.mode_id,),
1057
+ ):
1058
+ raise ValueError(
1059
+ "coupled activation-boundary transforms currently support "
1060
+ "only a fixed K2, K3, or 22-K3/2-K4 schedule"
1061
+ )
1062
+ if folded_scale_power != 0.0:
1063
+ raise ValueError(
1064
+ "coupled activation-boundary transforms require "
1065
+ "folded_scale_power zero"
1066
+ )
1067
+ missing = set(expert_ids) - set(coupled_intermediate_draws_by_expert)
1068
+ extra = set(coupled_intermediate_draws_by_expert) - set(expert_ids)
1069
+ if missing or extra:
1070
+ raise ValueError("coupled draw map must cover exactly the expert batch")
1071
+ if (
1072
+ not modes
1073
+ or len(set(modes)) != len(modes)
1074
+ or (not fixed_profile and modes[0] != 0)
1075
+ ):
1076
+ raise ValueError(
1077
+ "mode_ids must be H308/K2 alone or unique and begin with R0"
1078
+ )
1079
+ if any(mode not in (0, 1, 2, H308.mode_id, K2.mode_id) for mode in modes):
1080
+ raise ValueError("mode_ids contain an unsupported schedule")
1081
+ if hessian_policy not in HESSIAN_POLICIES:
1082
+ raise ValueError(f"unsupported Hessian policy: {hessian_policy}")
1083
+ if permutation_policy not in PERMUTATION_POLICIES:
1084
+ raise ValueError(f"unsupported permutation policy: {permutation_policy}")
1085
+
1086
+ prepared: list[dict[str, object]] = []
1087
+ upstream_sources: list[dict[str, torch.Tensor]] = []
1088
+ upstream_contexts: list[torch.Tensor] = []
1089
+ upstream_modes: list[tuple[object, ...]] = []
1090
+ upstream_hessians: list[dict[str, torch.Tensor]] = []
1091
+ upstream_conditioning: list[torch.Tensor | None] = []
1092
+ seed_maps = [
1093
+ (transform_seeds_by_expert or {}).get(expert, {}) for expert in expert_ids
1094
+ ]
1095
+
1096
+ for expert in expert_ids:
1097
+ all_rows = select_expert_rows(samples, expert, partition.all)
1098
+ fit_mask = _split_rows(all_rows, partition.fit)
1099
+ confirmation_mask = _split_rows(all_rows, partition.confirmation)
1100
+ fit_documents = int(torch.unique(all_rows.request_steps[fit_mask]).numel())
1101
+ confirmation_documents = int(
1102
+ torch.unique(all_rows.request_steps[confirmation_mask]).numel()
1103
+ )
1104
+ inputs = all_rows.inputs.float().to(device=device)
1105
+ gates = all_rows.gates.float().to(device=device)
1106
+
1107
+ source_w1 = _load_source_matrix(store, layer, expert, "w1", device)
1108
+ source_w3 = _load_source_matrix(store, layer, expert, "w3", device)
1109
+ if all_rows.rows:
1110
+ source_gate = F.linear(inputs, source_w1)
1111
+ source_up = F.linear(inputs, source_w3)
1112
+ source_middle = _source_middle(
1113
+ source_gate,
1114
+ source_up,
1115
+ activation=activation,
1116
+ )
1117
+ del source_gate, source_up
1118
+ else:
1119
+ source_middle = torch.empty(
1120
+ (0, global_h2.shape[0]), dtype=torch.float32, device=device
1121
+ )
1122
+
1123
+ have_local_support = fit_documents >= min_fit_documents
1124
+ fit_mask_device = fit_mask.to(device=device)
1125
+ if bool(fit_mask.any()):
1126
+ block_contexts, block_scores = permutation_policy_contexts(
1127
+ source_middle[fit_mask_device],
1128
+ gates[fit_mask_device],
1129
+ policy=permutation_policy,
1130
+ )
1131
+ context_basis = (
1132
+ f"official_source_{_activation_basis(activation)}_fit_documents:"
1133
+ f"{permutation_policy}"
1134
+ )
1135
+ else:
1136
+ block_contexts = fallback_block_contexts.clone()
1137
+ block_scores = fallback_block_scores.clone()
1138
+ context_basis = "identity_logical_order_no_routed_fit_rows"
1139
+
1140
+ if have_local_support:
1141
+ h13 = global_h13
1142
+ covariance: dict[str, object] = {
1143
+ "gate_square_sum": float(
1144
+ gates[fit_mask_device].square().double().sum()
1145
+ ),
1146
+ "h13_local_alpha": 0.0,
1147
+ }
1148
+ covariance = {
1149
+ **covariance,
1150
+ "fit_rows": int(fit_mask.sum()),
1151
+ "fit_documents": fit_documents,
1152
+ }
1153
+ else:
1154
+ h13 = global_h13
1155
+ covariance = {
1156
+ "fit_rows": int(fit_mask.sum()),
1157
+ "fit_documents": fit_documents,
1158
+ "gate_square_sum": float(
1159
+ gates[fit_mask.to(device=device)].square().sum()
1160
+ ),
1161
+ "h13_local_alpha": 0.0,
1162
+ }
1163
+
1164
+ if coupled:
1165
+ # The coupled preactivation transform is not coordinatewise, so an
1166
+ # arbitrary neuron permutation cannot be pushed through it. Keep
1167
+ # LDLQ in the transformed logical order. K2 has one context; R0 K3
1168
+ # has 24 monotonically labelled equal-size contexts, whose stable
1169
+ # importance order is the identity permutation.
1170
+ context_count = resolve_mode(modes[0]).context_count
1171
+ if any(
1172
+ resolve_mode(mode).context_count != context_count
1173
+ for mode in modes
1174
+ ):
1175
+ raise ValueError("coupled rate candidates change context cardinality")
1176
+ block_contexts = _coupled_logical_block_contexts(
1177
+ modes[0], block_contexts.numel()
1178
+ )
1179
+ context_basis = "coupled_transform_logical_coordinate_order"
1180
+ elif fixed_k2:
1181
+ block_contexts = torch.zeros_like(block_contexts)
1182
+ context_basis = "uniform_k2_identity_coordinate_order"
1183
+ can_confirm = confirmation_documents >= min_confirmation_documents
1184
+ evaluated_modes = (
1185
+ modes if fixed_profile or (have_local_support and can_confirm) else (0,)
1186
+ )
1187
+ mode_specs = tuple(resolve_mode(mode) for mode in evaluated_modes)
1188
+ contexts_device = block_contexts.to(device=device, dtype=torch.long)
1189
+ coupled_execution_basis: CoupledHadamardExecution | None = None
1190
+ coupled_source_w2: torch.Tensor | None = None
1191
+ coupled_reference_output: torch.Tensor | None = None
1192
+ if coupled:
1193
+ draw = int(coupled_intermediate_draws_by_expert[expert])
1194
+ spec = CoupledHadamardSpec(
1195
+ intermediate_draw=draw,
1196
+ activation=activation,
1197
+ )
1198
+ source_w2 = _load_source_matrix(store, layer, expert, "w2", device)
1199
+ transformed = encode_coupled_weights(
1200
+ (source_w1, source_w3, source_w2), spec
1201
+ )
1202
+ coupled_execution_basis = coupled_execution(transformed, spec)
1203
+ coupled_source_w2 = transformed[2]
1204
+ coupled_reference_output = (
1205
+ F.linear(source_middle, source_w2)
1206
+ if all_rows.rows
1207
+ else torch.empty(
1208
+ (0, global_h13.shape[0]),
1209
+ dtype=torch.float32,
1210
+ device=device,
1211
+ )
1212
+ )
1213
+ source_w1, source_w3 = transformed[:2]
1214
+ inputs = coupled_execution_basis.transform_inputs(inputs)
1215
+ h13 = coupled_execution_basis.transform_h13(h13)
1216
+ transformed_global_h2 = coupled_execution_basis.transform_h2(global_h2)
1217
+ context_basis += f"+coupled_hadamard_intermediate_draw_{draw}"
1218
+ else:
1219
+ transformed_global_h2 = global_h2
1220
+ intermediate_conditioning = _folded_intermediate_conditioning(
1221
+ block_scores.to(device=device),
1222
+ contexts_device,
1223
+ power=folded_scale_power,
1224
+ )
1225
+ if intermediate_conditioning is not None:
1226
+ covariance["folded_scale_power"] = float(folded_scale_power)
1227
+ covariance["folded_scale_min"] = float(
1228
+ intermediate_conditioning.min()
1229
+ )
1230
+ covariance["folded_scale_max"] = float(
1231
+ intermediate_conditioning.max()
1232
+ )
1233
+ context_basis += "+folded_128_channel_conditioning"
1234
+ prepared.append(
1235
+ {
1236
+ "expert": expert,
1237
+ "all_rows": all_rows,
1238
+ "fit_mask": fit_mask,
1239
+ "confirmation_mask": confirmation_mask,
1240
+ "inputs": inputs,
1241
+ "gates": gates,
1242
+ "source_middle": source_middle,
1243
+ "block_contexts": block_contexts,
1244
+ "block_scores": block_scores,
1245
+ "context_basis": context_basis,
1246
+ "covariance": covariance,
1247
+ "evaluated_modes": evaluated_modes,
1248
+ "evaluated_formats": tuple(
1249
+ (r13, r2)
1250
+ for r13 in evaluated_modes
1251
+ for r2 in evaluated_modes
1252
+ ),
1253
+ "h13": h13,
1254
+ "global_h2_basis": transformed_global_h2,
1255
+ "coupled_execution": coupled_execution_basis,
1256
+ "coupled_source_w2": coupled_source_w2,
1257
+ "coupled_reference_output": coupled_reference_output,
1258
+ }
1259
+ )
1260
+ upstream_sources.append({"w1": source_w1, "w3": source_w3})
1261
+ upstream_contexts.append(contexts_device)
1262
+ upstream_modes.append(mode_specs)
1263
+ upstream_hessians.append({"w1": h13, "w3": h13})
1264
+ upstream_conditioning.append(intermediate_conditioning)
1265
+
1266
+ guarded_reuse = layout == "qsrt_guarded_reuse"
1267
+ if guarded_reuse and any(mode > 2 for mode in modes):
1268
+ raise ValueError("qsrt_guarded_reuse supports only R0 through R2")
1269
+ upstream_layout: Layout = "importance_ordered" if guarded_reuse else layout
1270
+ upstream_candidates = quantize_qsrt_matrix_expert_batch(
1271
+ upstream_sources,
1272
+ upstream_contexts,
1273
+ modes_by_expert=upstream_modes,
1274
+ hessians_by_expert=upstream_hessians,
1275
+ layer=layer,
1276
+ device=device,
1277
+ shared_scale_scope=shared_scale_scope,
1278
+ quantizer_module=quantizer_module,
1279
+ codebook=codebook,
1280
+ layout=upstream_layout,
1281
+ ldlq_tf32=ldlq_tf32,
1282
+ tailbite_context=tailbite_context,
1283
+ transform_seeds_by_expert=seed_maps,
1284
+ intermediate_conditioning_by_expert=upstream_conditioning,
1285
+ )
1286
+ _debug_assert_candidate_tree_closure(
1287
+ upstream_candidates,
1288
+ expert_ids,
1289
+ layer=layer,
1290
+ stage="post-upstream-encode",
1291
+ )
1292
+ del upstream_sources, upstream_hessians
1293
+
1294
+ down_sources: list[torch.Tensor] = []
1295
+ conditional_h2s: list[dict[int, torch.Tensor]] = []
1296
+ for item, upstream in zip(prepared, upstream_candidates):
1297
+ expert = int(item["expert"])
1298
+ source_w2 = item["coupled_source_w2"]
1299
+ if source_w2 is None:
1300
+ source_w2 = _load_source_matrix(store, layer, expert, "w2", device)
1301
+ source_middle = item["source_middle"]
1302
+ inputs = item["inputs"]
1303
+ gates = item["gates"]
1304
+ fit_mask = item["fit_mask"]
1305
+ evaluated_modes = item["evaluated_modes"]
1306
+ assert isinstance(source_middle, torch.Tensor)
1307
+ assert isinstance(inputs, torch.Tensor)
1308
+ assert isinstance(gates, torch.Tensor)
1309
+ assert isinstance(fit_mask, torch.Tensor)
1310
+ execution_basis = item["coupled_execution"]
1311
+ if execution_basis is None:
1312
+ middle_by_r13 = _candidate_middle_by_r13(
1313
+ inputs,
1314
+ upstream,
1315
+ evaluated_modes,
1316
+ activation=activation,
1317
+ )
1318
+ else:
1319
+ middle_by_r13 = {
1320
+ int(r13): execution_basis.decode_middle(
1321
+ inputs,
1322
+ upstream["w1"][int(r13)].reconstruction,
1323
+ upstream["w3"][int(r13)].reconstruction,
1324
+ )
1325
+ for r13 in evaluated_modes
1326
+ }
1327
+ h2_by_r13, h2_evidence = _conditional_h2_by_r13(
1328
+ inputs,
1329
+ gates,
1330
+ fit_mask.to(device=device),
1331
+ middle_by_r13,
1332
+ global_h13=item["h13"],
1333
+ global_h2=item["global_h2_basis"],
1334
+ device=device,
1335
+ hessian_policy=hessian_policy,
1336
+ have_local_support=(
1337
+ int(item["covariance"]["fit_documents"]) >= min_fit_documents
1338
+ ),
1339
+ )
1340
+ item["middle_by_r13"] = middle_by_r13
1341
+ item["covariance"].update(
1342
+ {
1343
+ "basis": (
1344
+ "identity"
1345
+ if hessian_policy == "identity"
1346
+ else (
1347
+ f"decoded_candidate_{_activation_basis(activation)}_"
1348
+ "adaptive_shrinkage"
1349
+ if int(item["covariance"]["fit_documents"])
1350
+ >= min_fit_documents
1351
+ else "identity_support_fallback"
1352
+ )
1353
+ ),
1354
+ "h2_by_r13": h2_evidence,
1355
+ }
1356
+ )
1357
+ item["context_basis"] = (
1358
+ str(item["context_basis"])
1359
+ + f"+decoded_candidate_{_activation_basis(activation)}_h2"
1360
+ )
1361
+ all_rows = item["all_rows"]
1362
+ if item["coupled_reference_output"] is not None:
1363
+ reference_output = item["coupled_reference_output"]
1364
+ elif all_rows.rows:
1365
+ reference_output = F.linear(source_middle, source_w2)
1366
+ else:
1367
+ reference_output = torch.empty(
1368
+ (0, global_h13.shape[0]), dtype=torch.float32, device=device
1369
+ )
1370
+ item["reference_output"] = reference_output
1371
+ down_sources.append(source_w2)
1372
+ conditional_h2s.append(h2_by_r13)
1373
+
1374
+ down_candidates = _quantize_conditional_down_grid(
1375
+ down_sources,
1376
+ upstream_contexts,
1377
+ upstream_modes,
1378
+ conditional_h2s,
1379
+ layer=layer,
1380
+ device=device,
1381
+ shared_scale_scope=shared_scale_scope,
1382
+ quantizer_module=quantizer_module,
1383
+ codebook=codebook,
1384
+ layout=layout,
1385
+ ldlq_tf32=ldlq_tf32,
1386
+ tailbite_context=tailbite_context,
1387
+ transform_seeds_by_expert=seed_maps,
1388
+ )
1389
+ _debug_assert_candidate_tree_closure(
1390
+ upstream_candidates,
1391
+ expert_ids,
1392
+ layer=layer,
1393
+ stage="post-down-encode upstream recheck",
1394
+ )
1395
+ _debug_assert_candidate_tree_closure(
1396
+ down_candidates,
1397
+ expert_ids,
1398
+ layer=layer,
1399
+ stage="post-down-encode",
1400
+ )
1401
+ del down_sources, conditional_h2s
1402
+
1403
+ results: list[QSRTCandidateEncoding] = []
1404
+ for item, upstream, down in zip(
1405
+ prepared, upstream_candidates, down_candidates
1406
+ ):
1407
+ expert = int(item["expert"])
1408
+ all_rows = item["all_rows"]
1409
+ fit_mask = item["fit_mask"]
1410
+ confirmation_mask = item["confirmation_mask"]
1411
+ inputs = item["inputs"]
1412
+ gates = item["gates"]
1413
+ source_middle = item["source_middle"]
1414
+ reference_output = item["reference_output"]
1415
+ evaluated_modes = item["evaluated_modes"]
1416
+ evaluated_formats = item["evaluated_formats"]
1417
+ assert isinstance(inputs, torch.Tensor)
1418
+ assert isinstance(gates, torch.Tensor)
1419
+ assert isinstance(source_middle, torch.Tensor)
1420
+ assert isinstance(reference_output, torch.Tensor)
1421
+
1422
+ fit_plan = _prepare_deferred_functional_rows(
1423
+ reference_output,
1424
+ gates,
1425
+ all_rows.request_steps,
1426
+ fit_mask,
1427
+ partition.fit,
1428
+ device=device,
1429
+ )
1430
+ confirmation_plan = _prepare_deferred_functional_rows(
1431
+ reference_output,
1432
+ gates,
1433
+ all_rows.request_steps,
1434
+ confirmation_mask,
1435
+ partition.confirmation,
1436
+ device=device,
1437
+ )
1438
+ deferred_fit_sse: list[torch.Tensor] = []
1439
+ deferred_confirmation_sse: list[torch.Tensor] = []
1440
+ format_order: list[tuple[int, int]] = []
1441
+ mode_coding: dict[tuple[int, int], dict[str, object]] = {}
1442
+ middle_by_r13 = item["middle_by_r13"]
1443
+ for rate_pair in evaluated_formats:
1444
+ r13, r2 = rate_pair
1445
+ candidate_output = F.linear(
1446
+ middle_by_r13[r13], down[r13][r2].reconstruction
1447
+ )
1448
+ execution_basis = item["coupled_execution"]
1449
+ if execution_basis is not None:
1450
+ candidate_output = execution_basis.decode_output(candidate_output)
1451
+ deferred_fit_sse.append(
1452
+ _defer_functional_row_sse(fit_plan, candidate_output)
1453
+ )
1454
+ deferred_confirmation_sse.append(
1455
+ _defer_functional_row_sse(confirmation_plan, candidate_output)
1456
+ )
1457
+ format_order.append(rate_pair)
1458
+ mode_coding[rate_pair] = _candidate_mode_evidence(
1459
+ {
1460
+ "w1": upstream["w1"][r13],
1461
+ "w3": upstream["w3"][r13],
1462
+ "w2": down[r13][r2],
1463
+ }
1464
+ )
1465
+ del candidate_output
1466
+
1467
+ fit_sse = _finish_deferred_functional_sse(
1468
+ fit_plan, format_order, deferred_fit_sse
1469
+ )
1470
+ confirmation_sse = _finish_deferred_functional_sse(
1471
+ confirmation_plan, format_order, deferred_confirmation_sse
1472
+ )
1473
+ fit_reference = fit_plan.reference_energy
1474
+ fit_counts = fit_plan.counts
1475
+ confirmation_reference = confirmation_plan.reference_energy
1476
+ confirmation_counts = confirmation_plan.counts
1477
+ if fixed_profile:
1478
+ fixed_mode = H308 if fixed_high_rate else (K2 if fixed_k2 else R0)
1479
+ selection = RatePairSelection(
1480
+ proposed_r13=fixed_mode.mode_id,
1481
+ proposed_r2=fixed_mode.mode_id,
1482
+ selected_r13=fixed_mode.mode_id,
1483
+ selected_r2=fixed_mode.mode_id,
1484
+ accepted=True,
1485
+ reason=(
1486
+ "fixed_22k3_2k4_high_rate_profile"
1487
+ if fixed_high_rate
1488
+ else (
1489
+ "fixed_uniform_k2_profile"
1490
+ if fixed_k2
1491
+ else "fixed_uniform_k3_profile"
1492
+ )
1493
+ ),
1494
+ fit_documents=int(torch.count_nonzero(fit_counts)),
1495
+ confirmation_documents=int(torch.count_nonzero(confirmation_counts)),
1496
+ confirmation_relative_improvement=None,
1497
+ confirmation_ci95=(None, None),
1498
+ bootstrap_replicates_valid=0,
1499
+ )
1500
+ else:
1501
+ selection = select_phase1_rate_pair(
1502
+ fit_sse,
1503
+ confirmation_sse,
1504
+ fit_counts=fit_counts,
1505
+ confirmation_counts=confirmation_counts,
1506
+ modes=evaluated_formats,
1507
+ min_fit_documents=min_fit_documents,
1508
+ min_confirmation_documents=min_confirmation_documents,
1509
+ minimum_improvement=minimum_improvement,
1510
+ bootstrap_replicates=bootstrap_replicates,
1511
+ seed=deterministic_expert_seed(layer, expert),
1512
+ )
1513
+ selected_r13, selected_r2 = selection.selected
1514
+ selected_candidates = {
1515
+ "w1": upstream["w1"][selected_r13],
1516
+ "w3": upstream["w3"][selected_r13],
1517
+ "w2": down[selected_r13][selected_r2],
1518
+ }
1519
+ if os.environ.get("QSRT_DEBUG_CANDIDATE_CLOSURE") == "1":
1520
+ for value in selected_candidates.values():
1521
+ _debug_assert_candidate_state_closure(
1522
+ value,
1523
+ layer=layer,
1524
+ expert=expert,
1525
+ stage="post-scoring selected-candidate",
1526
+ )
1527
+ selected_encodings = {}
1528
+ for matrix, value in selected_candidates.items():
1529
+ try:
1530
+ selected_encodings[matrix] = finalize_qsrt_matrix_candidate(
1531
+ value,
1532
+ layer=layer,
1533
+ logical_trellis_schema=logical_trellis_schema,
1534
+ codebook=codebook,
1535
+ tailbite_context=tailbite_context,
1536
+ )
1537
+ except Exception as exc:
1538
+ raise RuntimeError(
1539
+ f"layer {layer} expert {expert} {matrix} finalization failed"
1540
+ ) from exc
1541
+ physical_permutation = selected_encodings["w1"].plan.physical_permutation
1542
+ for matrix in ("w3", "w2"):
1543
+ if not torch.equal(
1544
+ selected_encodings[matrix].plan.physical_permutation,
1545
+ physical_permutation,
1546
+ ):
1547
+ raise ValueError(
1548
+ "selected matrices do not share one physical permutation"
1549
+ )
1550
+ expert_encoding = QSRTExpertEncoding(
1551
+ format=ExpertFormatSpec.compressed(selected_r13, selected_r2),
1552
+ matrices=selected_encodings,
1553
+ physical_permutation=physical_permutation,
1554
+ coding={
1555
+ "format": ExpertFormatSpec.compressed(
1556
+ selected_r13, selected_r2
1557
+ ).name,
1558
+ "r13": selected_r13,
1559
+ "r2": selected_r2,
1560
+ "codebook": codebook,
1561
+ "tailbite_context": int(tailbite_context),
1562
+ "coupled_hadamard": (
1563
+ None
1564
+ if item["coupled_execution"] is None
1565
+ else {
1566
+ "residual_block_size": item[
1567
+ "coupled_execution"
1568
+ ].spec.residual_block_size,
1569
+ "preactivation_block_size": item[
1570
+ "coupled_execution"
1571
+ ].spec.preactivation_block_size,
1572
+ "postactivation_block_size": item[
1573
+ "coupled_execution"
1574
+ ].spec.postactivation_block_size,
1575
+ "residual_draw": item[
1576
+ "coupled_execution"
1577
+ ].spec.residual_draw,
1578
+ "intermediate_draw": item[
1579
+ "coupled_execution"
1580
+ ].spec.intermediate_draw,
1581
+ "activation": item[
1582
+ "coupled_execution"
1583
+ ].spec.activation,
1584
+ }
1585
+ ),
1586
+ **_mode_evidence(selected_encodings),
1587
+ },
1588
+ )
1589
+ results.append(
1590
+ QSRTCandidateEncoding(
1591
+ expert=expert_encoding,
1592
+ selection=selection,
1593
+ block_contexts=item["block_contexts"]
1594
+ .detach()
1595
+ .cpu()
1596
+ .to(torch.uint8)
1597
+ .contiguous(),
1598
+ block_scores=item["block_scores"].detach().cpu().float().contiguous(),
1599
+ context_basis=str(item["context_basis"]),
1600
+ covariance=item["covariance"],
1601
+ evaluated_modes=evaluated_modes,
1602
+ evaluated_formats=evaluated_formats,
1603
+ fit_sse=fit_sse,
1604
+ confirmation_sse=confirmation_sse,
1605
+ fit_reference_energy=fit_reference,
1606
+ confirmation_reference_energy=confirmation_reference,
1607
+ fit_counts=fit_counts,
1608
+ confirmation_counts=confirmation_counts,
1609
+ mode_coding=mode_coding,
1610
+ )
1611
+ )
1612
+ return results
1613
+
1614
+
1615
+ def candidate_tensor_name(
1616
+ layer: int, expert: int, matrix: str, part: str
1617
+ ) -> str:
1618
+ if matrix not in MATRICES or part not in ("trellis", "suh", "svh"):
1619
+ raise ValueError("invalid QSRT candidate tensor component")
1620
+ return (
1621
+ f"language_model.model.layers.{layer}.block_sparse_moe.experts."
1622
+ f"{expert}.{matrix}.qsrt_{part}"
1623
+ )
1624
+
1625
+
1626
+ def selected_candidate_tensors(
1627
+ layer: int, expert: int, candidate: QSRTCandidateEncoding
1628
+ ) -> dict[str, torch.Tensor]:
1629
+ """Copy one selected physical payload to CPU for layer-shard assembly."""
1630
+
1631
+ tensors: dict[str, torch.Tensor] = {}
1632
+ for matrix, encoding in candidate.expert.matrices.items():
1633
+ for part in ("trellis", "suh", "svh"):
1634
+ tensors[candidate_tensor_name(layer, expert, matrix, part)] = (
1635
+ encoding.tensors[part].detach().cpu().contiguous()
1636
+ )
1637
+ return tensors
reproduction/closure/patches/qsrt/changed-files/qsrt/qsrt_coupled.py ADDED
@@ -0,0 +1,381 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Exact coupled activation-boundary coordinates for QSRT expert matrices.
2
+
3
+ The transform interleaves gate and up rows before a normalized block-Hadamard
4
+ rotation. The decoder joins the two stored projections, cancels that rotation,
5
+ evaluates the coordinatewise SiTU activation, and rotates the resulting hidden
6
+ coordinates into the matching down-projection basis. Residual-side transforms
7
+ are layer-shared; the intermediate draw is expert-static.
8
+ """
9
+
10
+ from __future__ import annotations
11
+
12
+ import math
13
+ from dataclasses import dataclass
14
+ from typing import Literal
15
+
16
+ import torch
17
+ import torch.nn.functional as F
18
+
19
+ from qsrt.tp_simulator import situ
20
+
21
+
22
+ Tensor = torch.Tensor
23
+ WeightTriplet = tuple[Tensor, Tensor, Tensor]
24
+ ExpertActivation = Literal["situ", "silu"]
25
+
26
+
27
+ def expert_activation(
28
+ gate: Tensor,
29
+ up: Tensor,
30
+ *,
31
+ activation: ExpertActivation,
32
+ ) -> Tensor:
33
+ """Evaluate the model's exact coordinatewise gated activation.
34
+
35
+ Coupled Hadamard construction is valid for either activation because the
36
+ preactivation transform is inverted before this operation and the
37
+ postactivation transform is applied afterward. Keeping the choice in the
38
+ immutable transform specification prevents a Kimi SiTU candidate from
39
+ being replayed accidentally under GLM's standard SwiGLU contract.
40
+ """
41
+
42
+ if gate.shape != up.shape:
43
+ raise ValueError("gate and up projections must have matching shapes")
44
+ if activation == "situ":
45
+ return situ(gate, up)
46
+ if activation == "silu":
47
+ return F.silu(gate) * up
48
+ raise ValueError(f"unsupported expert activation: {activation}")
49
+
50
+
51
+ @dataclass(frozen=True)
52
+ class CoupledHadamardSpec:
53
+ """Immutable transform parameters carried by a coupled QSRT profile."""
54
+
55
+ residual_block_size: int = 512
56
+ preactivation_block_size: int = 128
57
+ postactivation_block_size: int = 128
58
+ residual_draw: int = 0
59
+ intermediate_draw: int = 0
60
+ activation: ExpertActivation = "situ"
61
+
62
+ def __post_init__(self) -> None:
63
+ for name, value in (
64
+ ("residual_block_size", self.residual_block_size),
65
+ ("preactivation_block_size", self.preactivation_block_size),
66
+ ("postactivation_block_size", self.postactivation_block_size),
67
+ ):
68
+ if value <= 0 or value & (value - 1):
69
+ raise ValueError(f"{name} must be a positive power of two")
70
+ if self.residual_draw != 0:
71
+ raise ValueError("the coupled profile fixes residual draw zero")
72
+ if not 0 <= self.intermediate_draw < 8:
73
+ raise ValueError("intermediate_draw must lie in 0..7")
74
+ if self.activation not in ("situ", "silu"):
75
+ raise ValueError("activation must be 'situ' or 'silu'")
76
+
77
+
78
+ def block_hadamard(values: Tensor, *, block_size: int, dim: int = -1) -> Tensor:
79
+ """Apply a normalized self-inverse block Walsh-Hadamard transform."""
80
+
81
+ if values.ndim == 0 or not torch.is_floating_point(values):
82
+ raise TypeError("block Hadamard input must be floating point")
83
+ if block_size <= 0 or block_size & (block_size - 1):
84
+ raise ValueError("block_size must be a positive power of two")
85
+ axis = dim % values.ndim
86
+ if values.shape[axis] % block_size:
87
+ raise ValueError("Hadamard axis must be divisible by block_size")
88
+ # Naturally routed experts can have an empty fit or confirmation fold.
89
+ # The transform is linear, so its action on an empty batch is the empty
90
+ # float32 tensor with the same shape. Returning before the butterfly
91
+ # reshape also avoids an ambiguous ``-1`` inference when numel is zero.
92
+ if values.numel() == 0:
93
+ return values.float().contiguous().clone()
94
+ output = values.float().movedim(axis, -1).contiguous().clone()
95
+ shape = output.shape
96
+ output = output.reshape(*shape[:-1], shape[-1] // block_size, block_size)
97
+ width = 1
98
+ while width < block_size:
99
+ paired = output.reshape(*output.shape[:-1], -1, 2, width)
100
+ left = paired[..., 0, :].clone()
101
+ right = paired[..., 1, :].clone()
102
+ paired[..., 0, :] = left + right
103
+ paired[..., 1, :] = left - right
104
+ output = paired.reshape(*output.shape)
105
+ width *= 2
106
+ return (
107
+ output.div_(math.sqrt(block_size))
108
+ .reshape(shape)
109
+ .movedim(-1, axis)
110
+ .contiguous()
111
+ )
112
+
113
+
114
+ def rotation_signs(
115
+ length: int, *, draw: int, axis: int, device: torch.device
116
+ ) -> Tensor:
117
+ """Return one deterministic Rademacher vector from the frozen draw family."""
118
+
119
+ if length <= 0 or draw < 0:
120
+ raise ValueError("length must be positive and draw nonnegative")
121
+ if draw == 0:
122
+ return torch.ones(length, dtype=torch.float32, device=device)
123
+ generator = torch.Generator(device="cpu")
124
+ generator.manual_seed(
125
+ (0x6A09E667F3BCC909 * draw + 0xBB67AE8584CAA73B * axis)
126
+ & ((1 << 63) - 1)
127
+ )
128
+ return (
129
+ torch.randint(0, 2, (length,), generator=generator)
130
+ .mul_(2)
131
+ .sub_(1)
132
+ .float()
133
+ .to(device=device)
134
+ )
135
+
136
+
137
+ def signed_block_hadamard(
138
+ values: Tensor,
139
+ *,
140
+ block_size: int,
141
+ signs: Tensor,
142
+ dim: int = -1,
143
+ inverse: bool = False,
144
+ ) -> Tensor:
145
+ """Apply ``D H`` to row vectors, or its exact inverse ``H D``."""
146
+
147
+ axis = dim % values.ndim
148
+ if signs.ndim != 1 or signs.numel() != values.shape[axis]:
149
+ raise ValueError("rotation signs do not align with the transformed axis")
150
+ shape = [1] * values.ndim
151
+ shape[axis] = signs.numel()
152
+ expanded = signs.to(device=values.device, dtype=torch.float32).reshape(shape)
153
+ if inverse:
154
+ return block_hadamard(values, block_size=block_size, dim=axis) * expanded
155
+ return block_hadamard(
156
+ values.float() * expanded, block_size=block_size, dim=axis
157
+ )
158
+
159
+
160
+ def _validate_triplet(weights: WeightTriplet) -> tuple[int, int]:
161
+ w1, w3, w2 = weights
162
+ if w1.ndim != 2 or w3.ndim != 2 or w2.ndim != 2 or w1.shape != w3.shape:
163
+ raise ValueError("coupled weights require matching two-dimensional w1/w3")
164
+ intermediate, hidden = w1.shape
165
+ if tuple(w2.shape) != (hidden, intermediate):
166
+ raise ValueError("w2 must have shape [hidden, intermediate]")
167
+ if not all(torch.is_floating_point(value) for value in weights):
168
+ raise TypeError("coupled weights must be floating point")
169
+ if len({value.device for value in weights}) != 1:
170
+ raise ValueError("coupled weights must share one device")
171
+ return intermediate, hidden
172
+
173
+
174
+ def encode_coupled_weights(
175
+ weights: WeightTriplet, spec: CoupledHadamardSpec
176
+ ) -> WeightTriplet:
177
+ """Reparameterize one full-precision expert into coupled coordinates."""
178
+
179
+ w1, w3, w2 = weights
180
+ intermediate, hidden = _validate_triplet(weights)
181
+ if hidden % spec.residual_block_size:
182
+ raise ValueError("hidden size does not close residual Hadamard blocks")
183
+ if 2 * intermediate % spec.preactivation_block_size:
184
+ raise ValueError("interleaved size does not close preactivation blocks")
185
+ if intermediate % spec.postactivation_block_size:
186
+ raise ValueError("intermediate size does not close postactivation blocks")
187
+ device = w1.device
188
+ input_signs = rotation_signs(hidden, draw=spec.residual_draw, axis=0, device=device)
189
+ pre_signs = rotation_signs(
190
+ 2 * intermediate, draw=spec.intermediate_draw, axis=1, device=device
191
+ )
192
+ post_signs = rotation_signs(
193
+ intermediate, draw=spec.intermediate_draw, axis=2, device=device
194
+ )
195
+ output_signs = rotation_signs(
196
+ hidden, draw=spec.residual_draw, axis=3, device=device
197
+ )
198
+ interleaved = torch.stack((w1, w3), dim=1).reshape(2 * intermediate, hidden)
199
+ upstream = signed_block_hadamard(
200
+ signed_block_hadamard(
201
+ interleaved,
202
+ block_size=spec.residual_block_size,
203
+ signs=input_signs,
204
+ dim=1,
205
+ ),
206
+ block_size=spec.preactivation_block_size,
207
+ signs=pre_signs,
208
+ dim=0,
209
+ )
210
+ down = signed_block_hadamard(
211
+ signed_block_hadamard(
212
+ w2,
213
+ block_size=spec.postactivation_block_size,
214
+ signs=post_signs,
215
+ dim=1,
216
+ ),
217
+ block_size=spec.residual_block_size,
218
+ signs=output_signs,
219
+ dim=0,
220
+ )
221
+ return (
222
+ upstream[:intermediate].contiguous(),
223
+ upstream[intermediate:].contiguous(),
224
+ down.contiguous(),
225
+ )
226
+
227
+
228
+ @dataclass(frozen=True)
229
+ class CoupledHadamardExecution:
230
+ """Calibration and scoring operations for one transformed expert basis."""
231
+
232
+ hidden: int
233
+ intermediate: int
234
+ spec: CoupledHadamardSpec
235
+
236
+ def _signs(self, axis: int, *, device: torch.device) -> Tensor:
237
+ lengths = (self.hidden, 2 * self.intermediate, self.intermediate, self.hidden)
238
+ draw = self.spec.residual_draw if axis in (0, 3) else self.spec.intermediate_draw
239
+ return rotation_signs(lengths[axis], draw=draw, axis=axis, device=device)
240
+
241
+ def transform_inputs(self, rows: Tensor) -> Tensor:
242
+ if rows.ndim != 2 or rows.shape[1] != self.hidden:
243
+ raise ValueError("input rows do not match the hidden dimension")
244
+ return signed_block_hadamard(
245
+ rows,
246
+ block_size=self.spec.residual_block_size,
247
+ signs=self._signs(0, device=rows.device),
248
+ dim=1,
249
+ )
250
+
251
+ def transform_h13(self, hessian: Tensor) -> Tensor:
252
+ if tuple(hessian.shape) != (self.hidden, self.hidden):
253
+ raise ValueError("H13 does not match the hidden dimension")
254
+ signs = self._signs(0, device=hessian.device)
255
+ return signed_block_hadamard(
256
+ signed_block_hadamard(
257
+ hessian,
258
+ block_size=self.spec.residual_block_size,
259
+ signs=signs,
260
+ dim=0,
261
+ ),
262
+ block_size=self.spec.residual_block_size,
263
+ signs=signs,
264
+ dim=1,
265
+ )
266
+
267
+ def transform_h2(self, hessian: Tensor) -> Tensor:
268
+ if tuple(hessian.shape) != (self.intermediate, self.intermediate):
269
+ raise ValueError("H2 does not match the intermediate dimension")
270
+ signs = self._signs(2, device=hessian.device)
271
+ return signed_block_hadamard(
272
+ signed_block_hadamard(
273
+ hessian,
274
+ block_size=self.spec.postactivation_block_size,
275
+ signs=signs,
276
+ dim=0,
277
+ ),
278
+ block_size=self.spec.postactivation_block_size,
279
+ signs=signs,
280
+ dim=1,
281
+ )
282
+
283
+ def decode_middle(self, rows: Tensor, w1: Tensor, w3: Tensor) -> Tensor:
284
+ return self.decode_middle_outputs(F.linear(rows, w1), F.linear(rows, w3))
285
+
286
+ def decode_middle_outputs(
287
+ self, transformed_w1: Tensor, transformed_w3: Tensor
288
+ ) -> Tensor:
289
+ """Close the coupled boundary from already-computed FC1 outputs.
290
+
291
+ This is the runtime/calibration seam used when the two upstream GEMMs
292
+ have their own operand precision, reconstruction law, or fused kernel.
293
+ It applies exactly the same inverse preactivation rotation, model
294
+ activation, and postactivation rotation as :meth:`decode_middle`.
295
+ """
296
+
297
+ if (
298
+ transformed_w1.ndim != 2
299
+ or transformed_w3.ndim != 2
300
+ or transformed_w1.shape != transformed_w3.shape
301
+ or transformed_w1.shape[1] != self.intermediate
302
+ or transformed_w1.device != transformed_w3.device
303
+ ):
304
+ raise ValueError(
305
+ "coupled upstream outputs must be aligned [rows, intermediate]"
306
+ )
307
+ transformed = torch.cat((transformed_w1, transformed_w3), dim=1)
308
+ recovered = signed_block_hadamard(
309
+ transformed,
310
+ block_size=self.spec.preactivation_block_size,
311
+ signs=self._signs(1, device=transformed.device),
312
+ dim=1,
313
+ inverse=True,
314
+ )
315
+ middle = expert_activation(
316
+ recovered[:, 0::2],
317
+ recovered[:, 1::2],
318
+ activation=self.spec.activation,
319
+ )
320
+ return signed_block_hadamard(
321
+ middle,
322
+ block_size=self.spec.postactivation_block_size,
323
+ signs=self._signs(2, device=transformed.device),
324
+ dim=1,
325
+ )
326
+
327
+ def decode_output(self, transformed: Tensor) -> Tensor:
328
+ if transformed.ndim != 2 or transformed.shape[1] != self.hidden:
329
+ raise ValueError("output rows do not match the hidden dimension")
330
+ return signed_block_hadamard(
331
+ transformed,
332
+ block_size=self.spec.residual_block_size,
333
+ signs=self._signs(3, device=transformed.device),
334
+ dim=1,
335
+ inverse=True,
336
+ )
337
+
338
+ def transform_outputs(self, rows: Tensor) -> Tensor:
339
+ """Map caller-coordinate outputs into the coupled residual basis.
340
+
341
+ Calibration uses this forward counterpart of :meth:`decode_output`
342
+ when constructing a candidate-conditioned down cross term. The
343
+ candidate operand and source-model teacher must share the transformed
344
+ output coordinates before forming ``B = Q.T @ Y``.
345
+ """
346
+
347
+ if rows.ndim != 2 or rows.shape[1] != self.hidden:
348
+ raise ValueError("output rows do not match the hidden dimension")
349
+ return signed_block_hadamard(
350
+ rows,
351
+ block_size=self.spec.residual_block_size,
352
+ signs=self._signs(3, device=rows.device),
353
+ dim=1,
354
+ )
355
+
356
+ def execute(self, rows: Tensor, weights: WeightTriplet) -> Tensor:
357
+ _validate_triplet(weights)
358
+ transformed_rows = self.transform_inputs(rows)
359
+ middle = self.decode_middle(transformed_rows, weights[0], weights[1])
360
+ return self.decode_output(F.linear(middle, weights[2]))
361
+
362
+
363
+ def coupled_execution(
364
+ weights: WeightTriplet, spec: CoupledHadamardSpec
365
+ ) -> CoupledHadamardExecution:
366
+ intermediate, hidden = _validate_triplet(weights)
367
+ return CoupledHadamardExecution(hidden, intermediate, spec)
368
+
369
+
370
+ __all__ = [
371
+ "CoupledHadamardExecution",
372
+ "CoupledHadamardSpec",
373
+ "ExpertActivation",
374
+ "WeightTriplet",
375
+ "block_hadamard",
376
+ "coupled_execution",
377
+ "encode_coupled_weights",
378
+ "expert_activation",
379
+ "rotation_signs",
380
+ "signed_block_hadamard",
381
+ ]
reproduction/closure/patches/qsrt/changed-files/tests/test_qsrt_coupled.py ADDED
@@ -0,0 +1,181 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from __future__ import annotations
2
+
3
+ import torch
4
+
5
+ from qsrt.coupled_expert_study import (
6
+ CoupledTriplet,
7
+ encode_coupled_block_hadamard,
8
+ execute_coupled_block_hadamard,
9
+ )
10
+ from qsrt.qsrt_coupled import (
11
+ CoupledHadamardSpec,
12
+ block_hadamard,
13
+ coupled_execution,
14
+ encode_coupled_weights,
15
+ expert_activation,
16
+ rotation_signs,
17
+ signed_block_hadamard,
18
+ )
19
+ from qsrt.tp_simulator import situ
20
+
21
+
22
+ def test_block_hadamard_preserves_empty_routed_batches() -> None:
23
+ values = torch.empty((0, 7, 16), dtype=torch.float16)
24
+ transformed = block_hadamard(values, block_size=8, dim=2)
25
+
26
+ assert transformed.shape == values.shape
27
+ assert transformed.dtype == torch.float32
28
+ assert transformed.numel() == 0
29
+
30
+
31
+ def test_production_coupled_transform_closes_and_matches_research_oracle() -> None:
32
+ generator = torch.Generator().manual_seed(871)
33
+ rows, hidden, intermediate = 9, 16, 12
34
+ weights = (
35
+ torch.randn(intermediate, hidden, generator=generator),
36
+ torch.randn(intermediate, hidden, generator=generator),
37
+ torch.randn(hidden, intermediate, generator=generator),
38
+ )
39
+ inputs = torch.randn(rows, hidden, generator=generator)
40
+ spec = CoupledHadamardSpec(
41
+ residual_block_size=8,
42
+ preactivation_block_size=8,
43
+ postactivation_block_size=4,
44
+ intermediate_draw=3,
45
+ )
46
+
47
+ encoded = encode_coupled_weights(weights, spec)
48
+ execution = coupled_execution(encoded, spec)
49
+ output = execution.execute(inputs, encoded)
50
+ reference = torch.nn.functional.linear(
51
+ situ(
52
+ torch.nn.functional.linear(inputs, weights[0]),
53
+ torch.nn.functional.linear(inputs, weights[1]),
54
+ ),
55
+ weights[2],
56
+ )
57
+ research_encoded = encode_coupled_block_hadamard(
58
+ CoupledTriplet(*weights),
59
+ block_size=8,
60
+ preactivation_block_size=8,
61
+ postactivation_block_size=4,
62
+ intermediate_rotation_draw=3,
63
+ )
64
+ research_output = execute_coupled_block_hadamard(
65
+ inputs,
66
+ research_encoded,
67
+ block_size=8,
68
+ preactivation_block_size=8,
69
+ postactivation_block_size=4,
70
+ intermediate_rotation_draw=3,
71
+ )
72
+
73
+ for actual, expected in zip(encoded, research_encoded.tensors(), strict=True):
74
+ assert torch.equal(actual, expected)
75
+ assert torch.allclose(output, reference, rtol=2e-5, atol=2e-5)
76
+ assert torch.allclose(output, research_output, rtol=2e-5, atol=2e-5)
77
+
78
+
79
+ def test_glm_silu_coupled_transform_closes_exact_expert_function() -> None:
80
+ generator = torch.Generator().manual_seed(5202)
81
+ rows, hidden, intermediate = 11, 24, 16
82
+ weights = (
83
+ torch.randn(intermediate, hidden, generator=generator),
84
+ torch.randn(intermediate, hidden, generator=generator),
85
+ torch.randn(hidden, intermediate, generator=generator),
86
+ )
87
+ inputs = torch.randn(rows, hidden, generator=generator)
88
+ spec = CoupledHadamardSpec(
89
+ residual_block_size=8,
90
+ preactivation_block_size=8,
91
+ postactivation_block_size=8,
92
+ intermediate_draw=6,
93
+ activation="silu",
94
+ )
95
+
96
+ encoded = encode_coupled_weights(weights, spec)
97
+ execution = coupled_execution(encoded, spec)
98
+ output = execution.execute(inputs, encoded)
99
+ gate = torch.nn.functional.linear(inputs, weights[0])
100
+ up = torch.nn.functional.linear(inputs, weights[1])
101
+ reference = torch.nn.functional.linear(
102
+ torch.nn.functional.silu(gate) * up,
103
+ weights[2],
104
+ )
105
+
106
+ assert torch.allclose(output, reference, rtol=2e-5, atol=2e-5)
107
+
108
+ transformed_input = execution.transform_inputs(inputs)
109
+ gate_output = torch.nn.functional.linear(transformed_input, encoded[0])
110
+ up_output = torch.nn.functional.linear(transformed_input, encoded[1])
111
+ middle_from_outputs = execution.decode_middle_outputs(
112
+ gate_output, up_output
113
+ )
114
+ middle_from_weights = execution.decode_middle(
115
+ transformed_input, encoded[0], encoded[1]
116
+ )
117
+ torch.testing.assert_close(
118
+ middle_from_outputs, middle_from_weights, rtol=0, atol=0
119
+ )
120
+
121
+ transformed_output = execution.transform_outputs(reference)
122
+ torch.testing.assert_close(
123
+ execution.decode_output(transformed_output), reference, rtol=2e-5, atol=2e-5
124
+ )
125
+
126
+
127
+ def test_expert_activation_rejects_unknown_contract() -> None:
128
+ gate = torch.ones((2, 3))
129
+ up = torch.ones((2, 3))
130
+
131
+ try:
132
+ expert_activation(gate, up, activation="gelu") # type: ignore[arg-type]
133
+ except ValueError as exc:
134
+ assert "unsupported expert activation" in str(exc)
135
+ else:
136
+ raise AssertionError("unknown expert activation was accepted")
137
+
138
+
139
+ def test_coupled_hessian_transforms_preserve_quadratic_forms() -> None:
140
+ generator = torch.Generator().manual_seed(91)
141
+ hidden, intermediate = 16, 12
142
+ weights = (
143
+ torch.randn(intermediate, hidden, generator=generator),
144
+ torch.randn(intermediate, hidden, generator=generator),
145
+ torch.randn(hidden, intermediate, generator=generator),
146
+ )
147
+ spec = CoupledHadamardSpec(
148
+ residual_block_size=8,
149
+ preactivation_block_size=8,
150
+ postactivation_block_size=4,
151
+ intermediate_draw=5,
152
+ )
153
+ execution = coupled_execution(encode_coupled_weights(weights, spec), spec)
154
+ rows = torch.randn(11, hidden, generator=generator)
155
+ hidden_rows = torch.randn(11, intermediate, generator=generator)
156
+ h13 = rows.T @ rows
157
+ h2 = hidden_rows.T @ hidden_rows
158
+
159
+ transformed_rows = execution.transform_inputs(rows)
160
+ post_signs = rotation_signs(
161
+ intermediate, draw=spec.intermediate_draw, axis=2, device=rows.device
162
+ )
163
+ transformed_hidden_rows = signed_block_hadamard(
164
+ hidden_rows,
165
+ block_size=spec.postactivation_block_size,
166
+ signs=post_signs,
167
+ dim=1,
168
+ )
169
+ transformed_hidden = execution.transform_h2(h2)
170
+ assert torch.allclose(
171
+ execution.transform_h13(h13),
172
+ transformed_rows.T @ transformed_rows,
173
+ rtol=2e-5,
174
+ atol=2e-5,
175
+ )
176
+ assert torch.allclose(
177
+ transformed_hidden,
178
+ transformed_hidden_rows.T @ transformed_hidden_rows,
179
+ rtol=2e-5,
180
+ atol=2e-5,
181
+ )
reproduction/closure/patches/qsrt/changes.patch ADDED
@@ -0,0 +1,442 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ diff --git a/qsrt/pack/qsrt_candidates.py b/qsrt/pack/qsrt_candidates.py
2
+ index d7464fc..864b5c2 100644
3
+ --- a/qsrt/pack/qsrt_candidates.py
4
+ +++ b/qsrt/pack/qsrt_candidates.py
5
+ @@ -43,8 +43,10 @@ from qsrt.qsrt import (
6
+ from qsrt.qsrt_coupled import (
7
+ CoupledHadamardExecution,
8
+ CoupledHadamardSpec,
9
+ + ExpertActivation,
10
+ coupled_execution,
11
+ encode_coupled_weights,
12
+ + expert_activation,
13
+ )
14
+ from qsrt.pack.qsrt_encoder import (
15
+ Layout,
16
+ @@ -172,9 +174,22 @@ class QSRTCandidateEncoding:
17
+
18
+
19
+ def _source_middle(
20
+ - gate_projection: torch.Tensor, up_projection: torch.Tensor
21
+ + gate_projection: torch.Tensor,
22
+ + up_projection: torch.Tensor,
23
+ + *,
24
+ + activation: ExpertActivation = "situ",
25
+ ) -> torch.Tensor:
26
+ - return situ(gate_projection, up_projection)
27
+ + return expert_activation(
28
+ + gate_projection,
29
+ + up_projection,
30
+ + activation=activation,
31
+ + )
32
+ +
33
+ +
34
+ +def _activation_basis(activation: ExpertActivation) -> str:
35
+ + if activation not in ("situ", "silu"):
36
+ + raise ValueError(f"unsupported expert activation: {activation}")
37
+ + return f"post_{activation}"
38
+
39
+
40
+ def _folded_intermediate_conditioning(
41
+ @@ -407,13 +422,16 @@ def _candidate_middle_by_r13(
42
+ inputs: torch.Tensor,
43
+ upstream: dict[str, dict[int, QSRTMatrixCandidate]],
44
+ evaluated_modes: Sequence[int],
45
+ + *,
46
+ + activation: ExpertActivation = "situ",
47
+ ) -> dict[int, torch.Tensor]:
48
+ - """Replay exact candidate reconstructions through Kimi's SiTU."""
49
+ + """Replay exact candidate reconstructions through the model activation."""
50
+
51
+ return {
52
+ int(r13): _source_middle(
53
+ F.linear(inputs, upstream["w1"][int(r13)].reconstruction),
54
+ F.linear(inputs, upstream["w3"][int(r13)].reconstruction),
55
+ + activation=activation,
56
+ )
57
+ for r13 in evaluated_modes
58
+ }
59
+ @@ -627,6 +645,7 @@ def encode_phase1_expert(
60
+ permutation_policy: PermutationPolicy = "h2_reverse",
61
+ folded_scale_power: float = 0.0,
62
+ transform_seeds: Mapping[str, QSRTTransformSeeds] | None = None,
63
+ + activation: ExpertActivation = "situ",
64
+ ) -> QSRTCandidateEncoding:
65
+ """Encode and conservatively select one official-source expert.
66
+
67
+ @@ -674,7 +693,11 @@ def encode_phase1_expert(
68
+ if all_rows.rows:
69
+ source_gate = F.linear(inputs, source_w1)
70
+ source_up = F.linear(inputs, source_w3)
71
+ - source_middle = _source_middle(source_gate, source_up)
72
+ + source_middle = _source_middle(
73
+ + source_gate,
74
+ + source_up,
75
+ + activation=activation,
76
+ + )
77
+ del source_gate, source_up
78
+ else:
79
+ source_middle = torch.empty(
80
+ @@ -697,7 +720,8 @@ def encode_phase1_expert(
81
+ "h13_local_alpha": 0.0,
82
+ }
83
+ context_basis = (
84
+ - f"official_source_post_situ_fit_documents:{permutation_policy}"
85
+ + f"official_source_{_activation_basis(activation)}_fit_documents:"
86
+ + f"{permutation_policy}"
87
+ )
88
+ covariance = {
89
+ **covariance,
90
+ @@ -762,7 +786,10 @@ def encode_phase1_expert(
91
+ del source_w1, source_w3
92
+
93
+ middle_by_r13 = _candidate_middle_by_r13(
94
+ - inputs, upstream_candidates, evaluated_modes
95
+ + inputs,
96
+ + upstream_candidates,
97
+ + evaluated_modes,
98
+ + activation=activation,
99
+ )
100
+ h2_by_r13, h2_evidence = _conditional_h2_by_r13(
101
+ inputs,
102
+ @@ -781,7 +808,8 @@ def encode_phase1_expert(
103
+ "identity"
104
+ if hessian_policy == "identity"
105
+ else (
106
+ - "decoded_candidate_post_situ_adaptive_shrinkage"
107
+ + f"decoded_candidate_{_activation_basis(activation)}_"
108
+ + "adaptive_shrinkage"
109
+ if have_local_support
110
+ else "identity_support_fallback"
111
+ )
112
+ @@ -789,7 +817,7 @@ def encode_phase1_expert(
113
+ "h2_by_r13": h2_evidence,
114
+ }
115
+ )
116
+ - context_basis += "+decoded_candidate_post_situ_h2"
117
+ + context_basis += f"+decoded_candidate_{_activation_basis(activation)}_h2"
118
+
119
+ source_w2 = _load_source_matrix(store, layer, expert, "w2", device)
120
+ if all_rows.rows:
121
+ @@ -996,6 +1024,7 @@ def encode_phase1_expert_batch(
122
+ int, Mapping[str, QSRTTransformSeeds]
123
+ ] | None = None,
124
+ coupled_intermediate_draws_by_expert: Mapping[int, int] | None = None,
125
+ + activation: ExpertActivation = "situ",
126
+ ) -> list[QSRTCandidateEncoding]:
127
+ """Encode several experts while batching their independent trellis work.
128
+
129
+ @@ -1019,6 +1048,7 @@ def encode_phase1_expert_batch(
130
+ fixed_k2 = modes == (K2.mode_id,)
131
+ fixed_profile = fixed_k3 or fixed_high_rate or fixed_k2
132
+ coupled = coupled_intermediate_draws_by_expert is not None
133
+ + _activation_basis(activation)
134
+ if coupled:
135
+ if modes not in (
136
+ (R0.mode_id,),
137
+ @@ -1079,7 +1109,11 @@ def encode_phase1_expert_batch(
138
+ if all_rows.rows:
139
+ source_gate = F.linear(inputs, source_w1)
140
+ source_up = F.linear(inputs, source_w3)
141
+ - source_middle = _source_middle(source_gate, source_up)
142
+ + source_middle = _source_middle(
143
+ + source_gate,
144
+ + source_up,
145
+ + activation=activation,
146
+ + )
147
+ del source_gate, source_up
148
+ else:
149
+ source_middle = torch.empty(
150
+ @@ -1095,7 +1129,8 @@ def encode_phase1_expert_batch(
151
+ policy=permutation_policy,
152
+ )
153
+ context_basis = (
154
+ - f"official_source_post_situ_fit_documents:{permutation_policy}"
155
+ + f"official_source_{_activation_basis(activation)}_fit_documents:"
156
+ + f"{permutation_policy}"
157
+ )
158
+ else:
159
+ block_contexts = fallback_block_contexts.clone()
160
+ @@ -1156,7 +1191,10 @@ def encode_phase1_expert_batch(
161
+ coupled_reference_output: torch.Tensor | None = None
162
+ if coupled:
163
+ draw = int(coupled_intermediate_draws_by_expert[expert])
164
+ - spec = CoupledHadamardSpec(intermediate_draw=draw)
165
+ + spec = CoupledHadamardSpec(
166
+ + intermediate_draw=draw,
167
+ + activation=activation,
168
+ + )
169
+ source_w2 = _load_source_matrix(store, layer, expert, "w2", device)
170
+ transformed = encode_coupled_weights(
171
+ (source_w1, source_w3, source_w2), spec
172
+ @@ -1272,7 +1310,10 @@ def encode_phase1_expert_batch(
173
+ execution_basis = item["coupled_execution"]
174
+ if execution_basis is None:
175
+ middle_by_r13 = _candidate_middle_by_r13(
176
+ - inputs, upstream, evaluated_modes
177
+ + inputs,
178
+ + upstream,
179
+ + evaluated_modes,
180
+ + activation=activation,
181
+ )
182
+ else:
183
+ middle_by_r13 = {
184
+ @@ -1303,7 +1344,8 @@ def encode_phase1_expert_batch(
185
+ "identity"
186
+ if hessian_policy == "identity"
187
+ else (
188
+ - "decoded_candidate_post_situ_adaptive_shrinkage"
189
+ + f"decoded_candidate_{_activation_basis(activation)}_"
190
+ + "adaptive_shrinkage"
191
+ if int(item["covariance"]["fit_documents"])
192
+ >= min_fit_documents
193
+ else "identity_support_fallback"
194
+ @@ -1313,7 +1355,8 @@ def encode_phase1_expert_batch(
195
+ }
196
+ )
197
+ item["context_basis"] = (
198
+ - str(item["context_basis"]) + "+decoded_candidate_post_situ_h2"
199
+ + str(item["context_basis"])
200
+ + + f"+decoded_candidate_{_activation_basis(activation)}_h2"
201
+ )
202
+ all_rows = item["all_rows"]
203
+ if item["coupled_reference_output"] is not None:
204
+ @@ -1535,6 +1578,9 @@ def encode_phase1_expert_batch(
205
+ "intermediate_draw": item[
206
+ "coupled_execution"
207
+ ].spec.intermediate_draw,
208
+ + "activation": item[
209
+ + "coupled_execution"
210
+ + ].spec.activation,
211
+ }
212
+ ),
213
+ **_mode_evidence(selected_encodings),
214
+ diff --git a/qsrt/qsrt_coupled.py b/qsrt/qsrt_coupled.py
215
+ index 6159771..4febf9b 100644
216
+ --- a/qsrt/qsrt_coupled.py
217
+ +++ b/qsrt/qsrt_coupled.py
218
+ @@ -11,6 +11,7 @@ from __future__ import annotations
219
+
220
+ import math
221
+ from dataclasses import dataclass
222
+ +from typing import Literal
223
+
224
+ import torch
225
+ import torch.nn.functional as F
226
+ @@ -20,6 +21,31 @@ from qsrt.tp_simulator import situ
227
+
228
+ Tensor = torch.Tensor
229
+ WeightTriplet = tuple[Tensor, Tensor, Tensor]
230
+ +ExpertActivation = Literal["situ", "silu"]
231
+ +
232
+ +
233
+ +def expert_activation(
234
+ + gate: Tensor,
235
+ + up: Tensor,
236
+ + *,
237
+ + activation: ExpertActivation,
238
+ +) -> Tensor:
239
+ + """Evaluate the model's exact coordinatewise gated activation.
240
+ +
241
+ + Coupled Hadamard construction is valid for either activation because the
242
+ + preactivation transform is inverted before this operation and the
243
+ + postactivation transform is applied afterward. Keeping the choice in the
244
+ + immutable transform specification prevents a Kimi SiTU candidate from
245
+ + being replayed accidentally under GLM's standard SwiGLU contract.
246
+ + """
247
+ +
248
+ + if gate.shape != up.shape:
249
+ + raise ValueError("gate and up projections must have matching shapes")
250
+ + if activation == "situ":
251
+ + return situ(gate, up)
252
+ + if activation == "silu":
253
+ + return F.silu(gate) * up
254
+ + raise ValueError(f"unsupported expert activation: {activation}")
255
+
256
+
257
+ @dataclass(frozen=True)
258
+ @@ -31,6 +57,7 @@ class CoupledHadamardSpec:
259
+ postactivation_block_size: int = 128
260
+ residual_draw: int = 0
261
+ intermediate_draw: int = 0
262
+ + activation: ExpertActivation = "situ"
263
+
264
+ def __post_init__(self) -> None:
265
+ for name, value in (
266
+ @@ -44,6 +71,8 @@ class CoupledHadamardSpec:
267
+ raise ValueError("the coupled profile fixes residual draw zero")
268
+ if not 0 <= self.intermediate_draw < 8:
269
+ raise ValueError("intermediate_draw must lie in 0..7")
270
+ + if self.activation not in ("situ", "silu"):
271
+ + raise ValueError("activation must be 'situ' or 'silu'")
272
+
273
+
274
+ def block_hadamard(values: Tensor, *, block_size: int, dim: int = -1) -> Tensor:
275
+ @@ -252,19 +281,46 @@ class CoupledHadamardExecution:
276
+ )
277
+
278
+ def decode_middle(self, rows: Tensor, w1: Tensor, w3: Tensor) -> Tensor:
279
+ - transformed = torch.cat((F.linear(rows, w1), F.linear(rows, w3)), dim=1)
280
+ + return self.decode_middle_outputs(F.linear(rows, w1), F.linear(rows, w3))
281
+ +
282
+ + def decode_middle_outputs(
283
+ + self, transformed_w1: Tensor, transformed_w3: Tensor
284
+ + ) -> Tensor:
285
+ + """Close the coupled boundary from already-computed FC1 outputs.
286
+ +
287
+ + This is the runtime/calibration seam used when the two upstream GEMMs
288
+ + have their own operand precision, reconstruction law, or fused kernel.
289
+ + It applies exactly the same inverse preactivation rotation, model
290
+ + activation, and postactivation rotation as :meth:`decode_middle`.
291
+ + """
292
+ +
293
+ + if (
294
+ + transformed_w1.ndim != 2
295
+ + or transformed_w3.ndim != 2
296
+ + or transformed_w1.shape != transformed_w3.shape
297
+ + or transformed_w1.shape[1] != self.intermediate
298
+ + or transformed_w1.device != transformed_w3.device
299
+ + ):
300
+ + raise ValueError(
301
+ + "coupled upstream outputs must be aligned [rows, intermediate]"
302
+ + )
303
+ + transformed = torch.cat((transformed_w1, transformed_w3), dim=1)
304
+ recovered = signed_block_hadamard(
305
+ transformed,
306
+ block_size=self.spec.preactivation_block_size,
307
+ - signs=self._signs(1, device=rows.device),
308
+ + signs=self._signs(1, device=transformed.device),
309
+ dim=1,
310
+ inverse=True,
311
+ )
312
+ - middle = situ(recovered[:, 0::2], recovered[:, 1::2])
313
+ + middle = expert_activation(
314
+ + recovered[:, 0::2],
315
+ + recovered[:, 1::2],
316
+ + activation=self.spec.activation,
317
+ + )
318
+ return signed_block_hadamard(
319
+ middle,
320
+ block_size=self.spec.postactivation_block_size,
321
+ - signs=self._signs(2, device=rows.device),
322
+ + signs=self._signs(2, device=transformed.device),
323
+ dim=1,
324
+ )
325
+
326
+ @@ -279,6 +335,24 @@ class CoupledHadamardExecution:
327
+ inverse=True,
328
+ )
329
+
330
+ + def transform_outputs(self, rows: Tensor) -> Tensor:
331
+ + """Map caller-coordinate outputs into the coupled residual basis.
332
+ +
333
+ + Calibration uses this forward counterpart of :meth:`decode_output`
334
+ + when constructing a candidate-conditioned down cross term. The
335
+ + candidate operand and source-model teacher must share the transformed
336
+ + output coordinates before forming ``B = Q.T @ Y``.
337
+ + """
338
+ +
339
+ + if rows.ndim != 2 or rows.shape[1] != self.hidden:
340
+ + raise ValueError("output rows do not match the hidden dimension")
341
+ + return signed_block_hadamard(
342
+ + rows,
343
+ + block_size=self.spec.residual_block_size,
344
+ + signs=self._signs(3, device=rows.device),
345
+ + dim=1,
346
+ + )
347
+ +
348
+ def execute(self, rows: Tensor, weights: WeightTriplet) -> Tensor:
349
+ _validate_triplet(weights)
350
+ transformed_rows = self.transform_inputs(rows)
351
+ @@ -296,10 +370,12 @@ def coupled_execution(
352
+ __all__ = [
353
+ "CoupledHadamardExecution",
354
+ "CoupledHadamardSpec",
355
+ + "ExpertActivation",
356
+ "WeightTriplet",
357
+ "block_hadamard",
358
+ "coupled_execution",
359
+ "encode_coupled_weights",
360
+ + "expert_activation",
361
+ "rotation_signs",
362
+ "signed_block_hadamard",
363
+ ]
364
+ diff --git a/tests/test_qsrt_coupled.py b/tests/test_qsrt_coupled.py
365
+ index 8f3f6a3..2fef347 100644
366
+ --- a/tests/test_qsrt_coupled.py
367
+ +++ b/tests/test_qsrt_coupled.py
368
+ @@ -12,6 +12,7 @@ from qsrt.qsrt_coupled import (
369
+ block_hadamard,
370
+ coupled_execution,
371
+ encode_coupled_weights,
372
+ + expert_activation,
373
+ rotation_signs,
374
+ signed_block_hadamard,
375
+ )
376
+ @@ -75,6 +76,66 @@ def test_production_coupled_transform_closes_and_matches_research_oracle() -> No
377
+ assert torch.allclose(output, research_output, rtol=2e-5, atol=2e-5)
378
+
379
+
380
+ +def test_glm_silu_coupled_transform_closes_exact_expert_function() -> None:
381
+ + generator = torch.Generator().manual_seed(5202)
382
+ + rows, hidden, intermediate = 11, 24, 16
383
+ + weights = (
384
+ + torch.randn(intermediate, hidden, generator=generator),
385
+ + torch.randn(intermediate, hidden, generator=generator),
386
+ + torch.randn(hidden, intermediate, generator=generator),
387
+ + )
388
+ + inputs = torch.randn(rows, hidden, generator=generator)
389
+ + spec = CoupledHadamardSpec(
390
+ + residual_block_size=8,
391
+ + preactivation_block_size=8,
392
+ + postactivation_block_size=8,
393
+ + intermediate_draw=6,
394
+ + activation="silu",
395
+ + )
396
+ +
397
+ + encoded = encode_coupled_weights(weights, spec)
398
+ + execution = coupled_execution(encoded, spec)
399
+ + output = execution.execute(inputs, encoded)
400
+ + gate = torch.nn.functional.linear(inputs, weights[0])
401
+ + up = torch.nn.functional.linear(inputs, weights[1])
402
+ + reference = torch.nn.functional.linear(
403
+ + torch.nn.functional.silu(gate) * up,
404
+ + weights[2],
405
+ + )
406
+ +
407
+ + assert torch.allclose(output, reference, rtol=2e-5, atol=2e-5)
408
+ +
409
+ + transformed_input = execution.transform_inputs(inputs)
410
+ + gate_output = torch.nn.functional.linear(transformed_input, encoded[0])
411
+ + up_output = torch.nn.functional.linear(transformed_input, encoded[1])
412
+ + middle_from_outputs = execution.decode_middle_outputs(
413
+ + gate_output, up_output
414
+ + )
415
+ + middle_from_weights = execution.decode_middle(
416
+ + transformed_input, encoded[0], encoded[1]
417
+ + )
418
+ + torch.testing.assert_close(
419
+ + middle_from_outputs, middle_from_weights, rtol=0, atol=0
420
+ + )
421
+ +
422
+ + transformed_output = execution.transform_outputs(reference)
423
+ + torch.testing.assert_close(
424
+ + execution.decode_output(transformed_output), reference, rtol=2e-5, atol=2e-5
425
+ + )
426
+ +
427
+ +
428
+ +def test_expert_activation_rejects_unknown_contract() -> None:
429
+ + gate = torch.ones((2, 3))
430
+ + up = torch.ones((2, 3))
431
+ +
432
+ + try:
433
+ + expert_activation(gate, up, activation="gelu") # type: ignore[arg-type]
434
+ + except ValueError as exc:
435
+ + assert "unsupported expert activation" in str(exc)
436
+ + else:
437
+ + raise AssertionError("unknown expert activation was accepted")
438
+ +
439
+ +
440
+ def test_coupled_hessian_transforms_preserve_quadratic_forms() -> None:
441
+ generator = torch.Generator().manual_seed(91)
442
+ hidden, intermediate = 16, 12