File size: 3,936 Bytes
46b9eea
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
import os
import sys
import time
import torch

# Add recipe path to sys.path
_RECIPE_ROOT = os.path.dirname(os.path.abspath(__file__))
sys.path.insert(0, _RECIPE_ROOT)

from modeling_aha_qwen3 import AHAQwen3ForCausalLM, AHAQwen3Config
from router_training_utils import RowWiseAdamW

def main():
    AHAQwen3Config.register_for_auto_class()
    AHAQwen3ForCausalLM.register_for_auto_class("AutoModelForCausalLM")

    # The repo root is the parent directory of recipe
    model_path = os.path.dirname(_RECIPE_ROOT)

    print("Loading model in BF16...", flush=True)
    model = AHAQwen3ForCausalLM.from_pretrained_qwen3(
        model_path,
        aha_window_size=128,
        aha_lambda=3e-4,
        aha_distill_weight=0.0,
        aha_ce_weight=1.0,
        aha_gate_target=1.0,
        aha_reg_weight=0.01,
        aha_mode="dynamic",
        aha_router_granularity="token",
        duo_sink_size=64,
        duo_recent_size=256,
        duo_alpha_init=1.0,
        torch_dtype=torch.bfloat16,
        attn_implementation="sdpa",
    )

    # Freeze embeddings and LM head as in stage 2 SFT training
    for param in model.model.embed_tokens.parameters():
        param.requires_grad = False
    for param in model.lm_head.parameters():
        param.requires_grad = False

    print("Moving model to CUDA...", flush=True)
    model = model.to("cuda")

    # Configure RowWiseAdamW optimizer
    num_heads = model.config.num_attention_heads
    head_dim = getattr(model.config, "head_dim", model.config.hidden_size // num_heads)
    q_rows = num_heads * head_dim
    q_row_scale = 3e-7 / 3e-6  # backbone_lr / gate_lr

    gate_params = []
    gate_param_ids = set()
    row_scales = []
    for layer in model.model.layers:
        q_proj = layer.self_attn.q_proj
        for p in (q_proj.weight, q_proj.bias):
            if p is None or not p.requires_grad:
                continue
            gate_params.append(p)
            gate_param_ids.add(id(p))
            row_scales.append((p, q_rows, q_row_scale))

    backbone_params = [
        p for p in model.parameters()
        if p.requires_grad and id(p) not in gate_param_ids
    ]

    param_groups = [{"params": gate_params, "lr": 3e-6}]
    if backbone_params:
        param_groups.append({"params": backbone_params, "lr": 3e-7})

    optimizer = RowWiseAdamW(
        param_groups,
        row_scales=row_scales,
        weight_decay=0.0,
    )

    # Allocate a batch of seq_len=8192
    seq_len = 8192
    print(f"Allocating dummy batch: batch_size=1, seq_len={seq_len}", flush=True)
    input_ids = torch.randint(0, model.config.vocab_size, (1, seq_len), device="cuda")
    labels = input_ids.clone()

    # Enable gradient checkpointing
    model.gradient_checkpointing_enable(gradient_checkpointing_kwargs={"use_reentrant": False})

    # Warmup step (GPU caching, model trace creation, etc.)
    print("Warmup step...", flush=True)
    outputs = model(input_ids=input_ids, labels=labels)
    loss = outputs.loss
    loss.backward()
    optimizer.step()
    optimizer.zero_grad()

    # Reset peak memory stats and time the next step
    print("Starting measured smoke test step...", flush=True)
    torch.cuda.reset_peak_memory_stats()
    torch.cuda.synchronize()
    start_time = time.time()

    outputs = model(input_ids=input_ids, labels=labels)
    loss = outputs.loss
    loss.backward()
    optimizer.step()
    optimizer.zero_grad()

    torch.cuda.synchronize()
    step_time = time.time() - start_time

    peak_mem = torch.cuda.max_memory_allocated() / (1024 ** 3)
    reserved_mem = torch.cuda.memory_reserved() / (1024 ** 3)

    print("=== SMOKE TEST RESULTS ===", flush=True)
    print(f"Peak VRAM: {peak_mem:.4f} GB", flush=True)
    print(f"Reserved VRAM: {reserved_mem:.4f} GB", flush=True)
    print(f"Step time: {step_time:.4f} seconds", flush=True)
    print("==========================", flush=True)

if __name__ == '__main__':
    main()