AbstractPhil commited on
Commit
f3ecd1e
·
verified ·
1 Parent(s): 79a9dee

mirror attention.py (batched multi-book scan + batched governor)

Browse files
Files changed (1) hide show
  1. attention.py +35 -10
attention.py CHANGED
@@ -137,6 +137,25 @@ class CausalSplatHUB(nn.Module):
137
  return m
138
 
139
  # ------------------------------------------------ constellation access
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
140
  def _units(self):
141
  """Uniform view: [(addr, q, k)] whether single- or multi-book."""
142
  if self.n_const == 1:
@@ -185,16 +204,22 @@ class CausalSplatHUB(nn.Module):
185
  nc = (n + pad) // C
186
  vc = vp.view(B, nc, C, d)
187
  mask = self._mask(C, x.device, v.dtype)
188
- num = den = None
189
- for addr, q, k in self._units():
190
- qc = addr.oriented_cat(q(x)) # (B, n, 2K)
191
- kc = addr.oriented_cat(k(x))
192
- if pad:
193
- qc = F.pad(qc, (0, 0, 0, pad))
194
- kc = F.pad(kc, (0, 0, 0, pad))
195
- nu, de = self._scan_cat(qc, kc, vc, mask, B, n, nc, C, d)
196
- num = nu if num is None else num + nu
197
- den = de if den is None else den + de
 
 
 
 
 
 
198
  cl = dtype_floor(den)
199
  self._den_raw = (den.detach(), cl)
200
  self._den_stats = None
 
137
  return m
138
 
139
  # ------------------------------------------------ constellation access
140
+ def _books_cat(self, x, which: str):
141
+ """All books' oriented codes in one batched pass: stack the frame
142
+ weights (H, D, d) and codebooks (H, K, D) — a few-MB copy — then a
143
+ single projection einsum, one address einsum, and the per-book 2K
144
+ softmax batched over the H axis. Returns (B, n, H*2K)."""
145
+ W = torch.stack([(c.q if which == "q" else c.k).weight
146
+ for c in self.consts]) # (H, D, d)
147
+ A = torch.stack([F.normalize(c.addr.codebook, dim=-1)
148
+ for c in self.consts]) # (H, K, D)
149
+ tau = self.consts[0].addr.tau
150
+ xh = torch.einsum("bnd,hkd->bnhk", x, W) # (B, n, H, D)
151
+ u = torch.einsum("bnhd,hkd->bnhk",
152
+ F.normalize(xh, dim=-1), A) / tau
153
+ m = u.abs().amax(dim=-1, keepdim=True)
154
+ e = torch.exp(torch.cat([u - m, -u - m], dim=-1)) # (B, n, H, 2K)
155
+ e = e / e.sum(dim=-1, keepdim=True) # per-book softmax
156
+ B, n = x.shape[:2]
157
+ return e.reshape(B, n, -1)
158
+
159
  def _units(self):
160
  """Uniform view: [(addr, q, k)] whether single- or multi-book."""
161
  if self.n_const == 1:
 
204
  nc = (n + pad) // C
205
  vc = vp.view(B, nc, C, d)
206
  mask = self._mask(C, x.device, v.dtype)
207
+ if self.n_const == 1:
208
+ qc = self.addr.oriented_cat(self.q(x)) # (B, n, 2K)
209
+ kc = self.addr.oriented_cat(self.k(x))
210
+ else:
211
+ # BATCHED multi-book path (2026-08-26 Blackwell verdict: the
212
+ # per-book Python loop was 512 sequential little scans per
213
+ # forward — launch-bound). Budget composition is algebraically
214
+ # ONE scan over the concatenated code: num and den are sums of
215
+ # per-book bilinear forms, so scanning cat_h(qc_h) against
216
+ # cat_h(kc_h) equals summing 16 separate scans (fp reorder).
217
+ qc = self._books_cat(x, "q") # (B, n, H*2K)
218
+ kc = self._books_cat(x, "k")
219
+ if pad:
220
+ qc = F.pad(qc, (0, 0, 0, pad))
221
+ kc = F.pad(kc, (0, 0, 0, pad))
222
+ num, den = self._scan_cat(qc, kc, vc, mask, B, n, nc, C, d)
223
  cl = dtype_floor(den)
224
  self._den_raw = (den.detach(), cl)
225
  self._den_stats = None