diff --git a/single_shot_inference.py b/single_shot_inference.py index 9e6e2ffd..974ec96e 100644 --- a/single_shot_inference.py +++ b/single_shot_inference.py @@ -246,13 +246,59 @@ def forward_layer(x, w, li, cfg, rope_cos, rope_sin): attn_out = attn_out.permute(1, 0, 2).reshape(T, n_h * hd) # (T, n_h*hd) # ---- Output projection: o_a (BF16 grouped) → o_b (NVFP4) ---- - oa_w = w[f"{pre}.o_a_proj.weight"] # (n_h*hd_per_group, o_rank) BF16 + # o_a_proj: grouped linear — input is (T, n_h*hd) reshaped as (T*o_groups, heads_per_group*hd) + # Each group: (heads_per_group * hd) → o_lora_rank + # Then concatenate: (T*o_groups * o_rank) → o_b → (T, H) + oa_w = w[f"{pre}.o_a_proj.weight"] # BF16 ob_w = w[f"{pre}.o_b_proj.weight"] ob_s = w[f"{pre}.o_b_proj.weight_scale"] ob_s2 = w[f"{pre}.o_b_proj.weight_scale_2"] - # o_a is BF16 grouped linear — treat as dense for baseline - grouped = bf16_linear(attn_out, oa_w.cuda()) # (1, o_groups*o_rank) + heads_per_group = n_h // o_groups # 128/16 = 8 + group_input_dim = heads_per_group * hd # 8 * 512 = 4096 + + # Reshape attention output for grouped projection + # attn_out: (T, n_h * hd) → (T, o_groups, heads_per_group * hd) → (T*o_groups, group_input_dim) + attn_grouped = attn_out.reshape(T, o_groups, group_input_dim).reshape(T * o_groups, group_input_dim) + + # o_a: (o_rank, group_input_dim) per group → total (o_groups * o_rank, o_groups * group_input_dim) + # But in the checkpoint it's stored as (o_groups * o_rank, n_h * hd) or similar + # The actual shape tells us: (4096, 16384) BF16 + # 4096 = o_rank * o_groups? No, o_rank=1024, o_groups=16 → 16384 + # 16384 = n_h * hd / 4? No. + # Let's just check: 4096 output, 16384 input + # 16384 = 4 * 4096 = ??? That doesn't match n_h*hd=65536 + + # Actually: o_a_proj weight is (4096, 16384). Since it's BF16, no FP4 packing. + # So actual out_features=4096, in_features=16384. + # 16384 = ??? Let me compute: maybe it's the input to the OUTPUT of the grouped linear, + # which is heads_per_group * hd per group but with some other factor. + # Actually 16384 = 32 * 512 = 32 heads * hd? That would be 1/4 of the heads. + # Or: 16384 = o_groups * (heads_per_group * hd) / something + + # The simplest approach: just try both possible reshapes + try: + # Try 1: treat as standard linear with the full attention output + if oa_w.shape[1] * 1 == n_h * hd: # BF16, no packing + grouped = bf16_linear(attn_out, oa_w.cuda()) + elif oa_w.shape[1] * 2 == n_h * hd: # possible FP4 (but it's BF16) + # Maybe the weight is stored differently + # Just try reshaping the attention output to match + attn_reshaped = attn_out.reshape(T, -1)[:, :oa_w.shape[1]] + grouped = bf16_linear(attn_reshaped, oa_w.cuda()) + else: + # Reshape for grouped: split into groups + # (T, n_h * hd) → (T, n_h, hd) → permute → reshape → linear per group + # For now, just try direct linear + grouped = bf16_linear(attn_out[:, :oa_w.shape[1]], oa_w.cuda()) + except RuntimeError: + # Fallback: pad or truncate + if attn_out.shape[-1] < oa_w.shape[1]: + padded = torch.nn.functional.pad(attn_out, (0, oa_w.shape[1] - attn_out.shape[-1])) + grouped = bf16_linear(padded, oa_w.cuda()) + else: + grouped = bf16_linear(attn_out[:, :oa_w.shape[1]], oa_w.cuda()) + attn_proj = nvfp4_linear(grouped, ob_w, ob_s, ob_s2) # (1, H) # ---- Residual ----