bihmoe-poc / scripts /probe_vram.py
Throstur
probe: unify CLS objective + add compute-matching helper
4604f3b
Raw
History Blame Contribute Delete
4.41 kB
from __future__ import annotations
import argparse
import time
import torch
import torch.nn.functional as F
from bihmoe.models.dense import DenseModel
from bihmoe.models.structured import StructuredBiHMoE
from bihmoe.utils.misc import set_seed, count_params, fmt_bytes
def cuda_mem(label: str) -> None:
if not torch.cuda.is_available():
print(f"{label}: cuda not available")
return
alloc = torch.cuda.memory_allocated()
reserv = torch.cuda.memory_reserved()
peak = torch.cuda.max_memory_allocated()
print(f"{label}: alloc={fmt_bytes(alloc)} reserved={fmt_bytes(reserv)} peak={fmt_bytes(peak)}")
def main():
ap = argparse.ArgumentParser()
ap.add_argument("--seed", type=int, default=123)
ap.add_argument("--vocab", type=int, default=2048)
ap.add_argument("--d_model", type=int, default=384)
ap.add_argument("--heads", type=int, default=6)
ap.add_argument("--seq", type=int, default=128)
ap.add_argument("--batch", type=int, default=8)
# Dense baseline
ap.add_argument("--dense_layers", type=int, default=6)
ap.add_argument("--dense_dff", type=int, default=1536)
ap.add_argument("--dense_pool", type=str, default="mean", choices=["mean","first"])
# Structured
ap.add_argument("--stem_layers", type=int, default=1)
ap.add_argument("--hemi_layers", type=int, default=4)
ap.add_argument("--expert_dff", type=int, default=1024)
ap.add_argument("--experts", type=int, default=8)
ap.add_argument("--topk", type=int, default=1)
ap.add_argument("--workspace", type=int, default=4)
ap.add_argument("--reconcile_every", type=int, default=2)
ap.add_argument("--steps", type=int, default=1)
ap.add_argument("--dtype", type=str, default="fp16", choices=["fp16","bf16","fp32"])
args = ap.parse_args()
set_seed(args.seed)
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
if torch.cuda.is_available():
torch.backends.cuda.matmul.allow_tf32 = True
torch.cuda.reset_peak_memory_stats()
def pick_dtype():
if args.dtype == "fp16":
return torch.float16
if args.dtype == "bf16":
return torch.bfloat16
return torch.float32
dt = pick_dtype()
print("device:", device)
if torch.cuda.is_available():
print("gpu:", torch.cuda.get_device_name(0))
print("dtype:", dt)
dense = DenseModel(
vocab_size=args.vocab,
d_model=args.d_model,
n_heads=args.heads,
n_layers=args.dense_layers,
d_ff=args.dense_dff,
dropout=0.0,
head_mode="cls",
pool=args.dense_pool,
).to(device).to(dtype=dt)
struct = StructuredBiHMoE(
vocab_size=args.vocab,
d_model=args.d_model,
n_heads=args.heads,
n_layers_stem=args.stem_layers,
n_layers_hemi=args.hemi_layers,
d_ff_dense=args.dense_dff, # NOTE: for probe we reuse dense_dff here; compute_match will override later
d_ff_expert=args.expert_dff,
n_experts=args.experts,
top_k=args.topk,
workspace_tokens=args.workspace,
reconcile_every=args.reconcile_every,
dropout=0.0,
).to(device).to(dtype=dt)
print("params_dense:", count_params(dense))
print("params_struct:", count_params(struct))
opt_d = torch.optim.AdamW(dense.parameters(), lr=1e-4)
opt_s = torch.optim.AdamW(struct.parameters(), lr=1e-4)
cuda_mem("after_init")
inp = torch.randint(0, args.vocab, (args.batch, args.seq), device=device)
tgt_cls = torch.randint(0, args.vocab, (args.batch,), device=device)
for step in range(args.steps):
t0 = time.time()
if torch.cuda.is_available():
torch.cuda.reset_peak_memory_stats()
opt_s.zero_grad(set_to_none=True)
logits_s = struct(inp) # (B,V)
loss_s = F.cross_entropy(logits_s.float(), tgt_cls)
loss_s.backward()
opt_s.step()
cuda_mem(f"after_struct_step{step}")
opt_d.zero_grad(set_to_none=True)
logits_d = dense(inp) # (B,V)
loss_d = F.cross_entropy(logits_d.float(), tgt_cls)
loss_d.backward()
opt_d.step()
cuda_mem(f"after_dense_step{step}")
t1 = time.time()
print(f"step{step}: loss_s={loss_s.item():.4f} loss_d={loss_d.item():.4f} dt={t1-t0:.3f}s")
if __name__ == "__main__":
main()