OpenTransformer commited on
Commit
7357217
·
verified ·
1 Parent(s): 809b6cd

Upload fused CE helper

Browse files
Files changed (1) hide show
  1. fused_ce.py +57 -0
fused_ce.py ADDED
@@ -0,0 +1,57 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Fused cross-entropy: streams over the VOCAB dimension (online-softmax) so the
2
+ [N x V] logit matrix is NEVER materialized -- only [N x vchunk]. Custom backward
3
+ recomputes softmax per vocab-chunk (grad = softmax - onehot). This is the
4
+ DiffusionBlocks 'process in chunks, don't hold the whole thing' idea applied to
5
+ the output head instead of network depth."""
6
+ import torch
7
+
8
+ class FusedCE(torch.autograd.Function):
9
+ @staticmethod
10
+ def forward(ctx, h, W, tgt, vchunk=16384):
11
+ with torch.cuda.amp.autocast(enabled=False):
12
+ hf = h.float()
13
+ Wf = W.float()
14
+ N, d = h.shape
15
+ V = W.shape[0]
16
+ m = torch.full((N,), -1e30, device=h.device, dtype=torch.float32)
17
+ s = torch.zeros(N, device=h.device, dtype=torch.float32)
18
+ zt = torch.zeros(N, device=h.device, dtype=torch.float32)
19
+ for c in range(0, V, vchunk):
20
+ lg = hf @ Wf[c:c+vchunk].T # [N,vchunk] transient only
21
+ cm = lg.max(1).values
22
+ nm = torch.maximum(m, cm)
23
+ s = s * torch.exp(m - nm) + torch.exp(lg - nm[:, None]).sum(1)
24
+ m = nm
25
+ ic = (tgt >= c) & (tgt < c+vchunk)
26
+ if ic.any():
27
+ zt[ic] = lg[ic, tgt[ic] - c].float()
28
+ lse = m + torch.log(s)
29
+ ctx.save_for_backward(h, W, tgt, lse)
30
+ ctx.vchunk = vchunk
31
+ return (lse - zt).mean()
32
+
33
+ @staticmethod
34
+ def backward(ctx, go):
35
+ h, W, tgt, lse = ctx.saved_tensors
36
+ vc = ctx.vchunk
37
+ N, d = h.shape
38
+ V = W.shape[0]
39
+ with torch.cuda.amp.autocast(enabled=False):
40
+ hf = h.float()
41
+ Wc_all = W.float()
42
+ gh = torch.zeros_like(hf)
43
+ gW = torch.zeros(W.shape, device=W.device, dtype=torch.float32)
44
+ sc = float(go) / N
45
+ for c in range(0, V, vc):
46
+ Wc = Wc_all[c:c+vc]
47
+ p = torch.exp(hf @ Wc.T - lse[:, None]) # softmax chunk [N,vchunk]
48
+ ic = (tgt >= c) & (tgt < c+vc)
49
+ if ic.any():
50
+ p[ic, tgt[ic] - c] -= 1.0
51
+ p *= sc
52
+ gh += p @ Wc
53
+ gW[c:c+vc] += p.T @ hf
54
+ return gh.to(h.dtype), gW.to(W.dtype), None, None
55
+
56
+ def fused_ce(h, W, tgt, vchunk=16384):
57
+ return FusedCE.apply(h.reshape(-1, h.size(-1)), W, tgt.reshape(-1), vchunk)