Mapika commited on
Commit
f5a4ed9
·
verified ·
1 Parent(s): 4535722

Upload folder using huggingface_hub

Browse files
decider/__pycache__/__init__.cpython-312.pyc DELETED
Binary file (174 Bytes)
 
decider/__pycache__/infer.cpython-312.pyc DELETED
Binary file (13.5 kB)
 
decider/__pycache__/model.cpython-312.pyc DELETED
Binary file (4.86 kB)
 
decider/__pycache__/prompt.cpython-312.pyc DELETED
Binary file (3.66 kB)
 
decider/engine.py CHANGED
@@ -19,25 +19,67 @@ def _bucket(x, buckets):
19
  return None
20
 
21
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
22
  class Engine:
23
- def __init__(self, path, device="cuda", dtype=torch.bfloat16, use_graphs=True, max_ctx_tokens=1536):
 
 
 
 
 
 
24
  self.m = DecisionModel(path, dtype=dtype, grad_ckpt=False).to(device).eval()
25
  self.tok = self.m.tok; self.dev = device; self.use_graphs = use_graphs; self.max_ctx = max_ctx_tokens
26
  self.core, self.W = self.m.lm.model, self.m.lm.lm_head.weight[self.m.letters].detach().clone()
 
 
 
 
 
 
 
 
 
 
27
  self.graphs = {} # (B, T) -> (static_ids, static_out, graph)
28
  self.pool = torch.cuda.graph_pool_handle() if use_graphs else None
29
  self.stats = dict(graph_captures=0, forwards=0)
30
 
 
 
 
 
31
  @torch.no_grad()
32
  def _fwd(self, ids):
33
- h = self.core(input_ids=ids).last_hidden_state
34
- return F.linear(h, self.W).float() # [B, T, K]
35
 
36
  def _capture(self, B, T):
37
  s_ids = torch.full((B, T), self.tok.pad_token_id, dtype=torch.long, device=self.dev)
38
  st = torch.cuda.Stream(); st.wait_stream(torch.cuda.current_stream())
39
  with torch.cuda.stream(st):
40
- for _ in range(2): self._fwd(s_ids) # warm-up: triton autotune etc.
41
  torch.cuda.current_stream().wait_stream(st)
42
  g = torch.cuda.CUDAGraph()
43
  with torch.cuda.graph(g, pool=self.pool):
@@ -89,8 +131,9 @@ if __name__ == "__main__":
89
  from . import data as D
90
  from .infer import Decider
91
  path = sys.argv[1] if len(sys.argv) > 1 else "runs/r3_v2/model"
 
92
  _, evals = D.load_cache("data/tasks.pkl")
93
- eng = Engine(path)
94
  rng = random.Random(0)
95
  exs = evals["support_tickets"][:64] + evals["clinc_oos"][:64] + evals["race"][:32]
96
  items = [build(e, eng.tok, rng, max_ctx_tokens=1536) for e in exs]
 
19
  return None
20
 
21
 
22
+ def fused_causal_conv1d_fn(hidden_states, weight, bias=None, activation=None, **kwargs):
23
+ """Depthwise causal conv (kernel k) as k shifted multiply-adds: fuses under torch.compile,
24
+ unlike the cuDNN grouped conv fallback (which was ~11% of batched GPU time)."""
25
+ B, C, T = hidden_states.shape; k = weight.shape[-1]
26
+ x = F.pad(hidden_states.to(weight.dtype), (k - 1, 0))
27
+ out = x[:, :, k - 1:k - 1 + T] * weight[:, k - 1][None, :, None]
28
+ for j in range(k - 1):
29
+ out = out + x[:, :, j:j + T] * weight[:, j][None, :, None]
30
+ if bias is not None:
31
+ out = out + bias[None, :, None]
32
+ if activation == "silu":
33
+ out = F.silu(out)
34
+ elif activation is not None:
35
+ from transformers.activations import ACT2FN
36
+ out = ACT2FN[activation](out)
37
+ return out.to(hidden_states.dtype)
38
+
39
+
40
+ def patch_conv():
41
+ from transformers.models.qwen3_5 import modeling_qwen3_5 as mq
42
+ mq.causal_conv1d_fn = fused_causal_conv1d_fn
43
+
44
+
45
  class Engine:
46
+ """compile: torch.compile the forward (needs use_cache=False; ~1.4x batched, fuses elementwise work).
47
+ fp8: e4m3 weights + per-token activation scaling on the big linears (Hopper tensor cores).
48
+ conv_patch: fusable depthwise causal conv instead of the cuDNN fallback."""
49
+ def __init__(self, path, device="cuda", dtype=torch.bfloat16, use_graphs=True, max_ctx_tokens=1536,
50
+ compile=True, fp8=False, conv_patch=True):
51
+ if conv_patch:
52
+ patch_conv()
53
  self.m = DecisionModel(path, dtype=dtype, grad_ckpt=False).to(device).eval()
54
  self.tok = self.m.tok; self.dev = device; self.use_graphs = use_graphs; self.max_ctx = max_ctx_tokens
55
  self.core, self.W = self.m.lm.model, self.m.lm.lm_head.weight[self.m.letters].detach().clone()
56
+ self.cfg = dict(compile=compile, fp8=fp8, conv_patch=conv_patch, graphs=use_graphs)
57
+ if fp8:
58
+ from .fp8 import convert_to_fp8
59
+ self.cfg["fp8_layers"] = convert_to_fp8(self.core)
60
+ if compile:
61
+ import torch._dynamo
62
+ torch._dynamo.config.cache_size_limit = 128
63
+ self._fwd_impl = torch.compile(self._fwd_eager, dynamic=False)
64
+ else:
65
+ self._fwd_impl = self._fwd_eager
66
  self.graphs = {} # (B, T) -> (static_ids, static_out, graph)
67
  self.pool = torch.cuda.graph_pool_handle() if use_graphs else None
68
  self.stats = dict(graph_captures=0, forwards=0)
69
 
70
+ def _fwd_eager(self, ids):
71
+ h = self.core(input_ids=ids, use_cache=False).last_hidden_state
72
+ return F.linear(h, self.W).float() # [B, T, K]
73
+
74
  @torch.no_grad()
75
  def _fwd(self, ids):
76
+ return self._fwd_impl(ids)
 
77
 
78
  def _capture(self, B, T):
79
  s_ids = torch.full((B, T), self.tok.pad_token_id, dtype=torch.long, device=self.dev)
80
  st = torch.cuda.Stream(); st.wait_stream(torch.cuda.current_stream())
81
  with torch.cuda.stream(st):
82
+ for _ in range(3): self._fwd(s_ids) # warm-up: compile / triton autotune
83
  torch.cuda.current_stream().wait_stream(st)
84
  g = torch.cuda.CUDAGraph()
85
  with torch.cuda.graph(g, pool=self.pool):
 
131
  from . import data as D
132
  from .infer import Decider
133
  path = sys.argv[1] if len(sys.argv) > 1 else "runs/r3_v2/model"
134
+ cfg = dict(compile="nocompile" not in sys.argv[2:], fp8="fp8" in sys.argv[2:], conv_patch="noconv" not in sys.argv[2:])
135
  _, evals = D.load_cache("data/tasks.pkl")
136
+ eng = Engine(path, **cfg); print("engine cfg", eng.cfg)
137
  rng = random.Random(0)
138
  exs = evals["support_tickets"][:64] + evals["clinc_oos"][:64] + evals["race"][:32]
139
  items = [build(e, eng.tok, rng, max_ctx_tokens=1536) for e in exs]
decider/fp8.py ADDED
@@ -0,0 +1,54 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """FP8 (e4m3) linear layers for Hopper via torch._scaled_mm.
2
+ Weights: per-output-channel scales, quantised once. Activations: per-token dynamic scales.
3
+ Under torch.compile the quantisation ops fuse into the surrounding elementwise work."""
4
+ import torch, torch.nn as nn
5
+
6
+ E4M3_MAX = 448.0
7
+
8
+
9
+ def _quant_rowwise(x):
10
+ s = x.abs().amax(dim=-1, keepdim=True).float().clamp(min=1e-12) / E4M3_MAX
11
+ return (x.float() / s).clamp(-E4M3_MAX, E4M3_MAX).to(torch.float8_e4m3fn), s
12
+
13
+
14
+ class FP8Linear(nn.Module):
15
+ def __init__(self, lin: nn.Linear):
16
+ super().__init__()
17
+ wq, sw = _quant_rowwise(lin.weight.detach()) # [N,K] fp8, [N,1]
18
+ self.register_buffer("wq", wq.contiguous()) # [N,K]; passed as wq.t() -> [K,N] column-major, as _scaled_mm wants
19
+ self.register_buffer("sw_t", sw.t().contiguous()) # [1,N]
20
+ self.bias = None if lin.bias is None else nn.Parameter(lin.bias.detach().clone(), requires_grad=False)
21
+ self.in_features, self.out_features = lin.in_features, lin.out_features
22
+ self.out_dtype = lin.weight.dtype
23
+
24
+ def forward(self, x):
25
+ shp = x.shape[:-1]
26
+ x2 = x.reshape(-1, self.in_features)
27
+ xq, sx = _quant_rowwise(x2)
28
+ y = torch._scaled_mm(xq, self.wq.t(), scale_a=sx, scale_b=self.sw_t, bias=self.bias, out_dtype=self.out_dtype)
29
+ return y.reshape(*shp, self.out_features)
30
+
31
+
32
+ def convert_to_fp8(model, skip=("lm_head",), min_dim=1024):
33
+ """Replace nn.Linear (with in/out >= min_dim) by FP8Linear in place. Returns count."""
34
+ n = 0
35
+ for name, mod in list(model.named_modules()):
36
+ for cname, child in list(mod.named_children()):
37
+ full = f"{name}.{cname}" if name else cname
38
+ if isinstance(child, nn.Linear) and not any(s in full for s in skip) and min(child.in_features, child.out_features) >= min_dim:
39
+ setattr(mod, cname, FP8Linear(child)); n += 1
40
+ return n
41
+
42
+
43
+ if __name__ == "__main__":
44
+ import time
45
+ lin = nn.Linear(2048, 6144, bias=False).cuda().to(torch.bfloat16)
46
+ f8 = FP8Linear(lin)
47
+ x = torch.randn(8192, 2048, device="cuda", dtype=torch.bfloat16)
48
+ ref = lin(x); got = f8(x)
49
+ print("rel err", ((ref.float() - got.float()).abs().mean() / ref.float().abs().mean()).item())
50
+ for f, name in [(lin, "bf16 linear"), (f8, "fp8 linear (eager)"), (torch.compile(f8), "fp8 linear (compiled)")]:
51
+ for _ in range(3): f(x)
52
+ torch.cuda.synchronize(); t = time.time()
53
+ for _ in range(20): f(x)
54
+ torch.cuda.synchronize(); print(f"{name:24s} {(time.time()-t)/20*1000:.3f} ms")
decider/infer.py CHANGED
@@ -24,8 +24,16 @@ class Example:
24
 
25
 
26
  class Decider:
27
- def __init__(self, path, device="cuda", dtype=torch.bfloat16, temperature=1.0, abstain_below=0.0):
28
- self.m = DecisionModel(path, dtype=dtype, grad_ckpt=False).to(device).eval()
 
 
 
 
 
 
 
 
29
  self.dev = device; self.T = temperature; self.abstain_below = abstain_below
30
 
31
  @torch.no_grad()
@@ -40,10 +48,13 @@ class Decider:
40
  def shuffle(self, x): pass
41
  def sample(self, xs, k): return xs[:k]
42
  items = [build(e, self.m.tok, _NoShuffle(), max_ctx_tokens=max_ctx_tokens) for e in exs]
43
- b = collate(items, self.m.tok.pad_token_id)
44
- logits = self.m.slot_logits(b["input_ids"].to(self.dev), b["attention_mask"].to(self.dev), b["slot_idx"].to(self.dev),
45
- b["slot_batch"].to(self.dev), b["nopts"].to(self.dev))
46
- probs = torch.softmax(logits / self.T, -1).cpu()
 
 
 
47
  out, k = [], 0
48
  for context, qs in requests:
49
  res = []
 
24
 
25
 
26
  class Decider:
27
+ """use_graphs=True (default on CUDA) routes scoring through decider.engine.Engine: shape-bucketed
28
+ CUDA graphs, ~7x lower single-request latency than eager. Set False for CPU or debugging."""
29
+ def __init__(self, path, device="cuda", dtype=torch.bfloat16, temperature=1.0, abstain_below=0.0, use_graphs=None):
30
+ if use_graphs is None:
31
+ use_graphs = str(device).startswith("cuda")
32
+ if use_graphs:
33
+ from .engine import Engine
34
+ self.eng = Engine(path, device=device, dtype=dtype); self.m = self.eng.m
35
+ else:
36
+ self.eng = None; self.m = DecisionModel(path, dtype=dtype, grad_ckpt=False).to(device).eval()
37
  self.dev = device; self.T = temperature; self.abstain_below = abstain_below
38
 
39
  @torch.no_grad()
 
48
  def shuffle(self, x): pass
49
  def sample(self, xs, k): return xs[:k]
50
  items = [build(e, self.m.tok, _NoShuffle(), max_ctx_tokens=max_ctx_tokens) for e in exs]
51
+ if self.eng is not None:
52
+ probs = torch.cat(self.eng.score_items(items, temperature=self.T))
53
+ else:
54
+ b = collate(items, self.m.tok.pad_token_id)
55
+ logits = self.m.slot_logits(b["input_ids"].to(self.dev), b["attention_mask"].to(self.dev), b["slot_idx"].to(self.dev),
56
+ b["slot_batch"].to(self.dev), b["nopts"].to(self.dev))
57
+ probs = torch.softmax(logits / self.T, -1).cpu()
58
  out, k = [], 0
59
  for context, qs in requests:
60
  res = []