Gala-598M-MLX / bench.py
junafinity's picture
Gala-598M: weights, code, logs, report
76bbe95 verified
Raw History Blame Contribute Delete
1.73 kB
"""
Day-1 throughput test: forward+backward tokens/sec for a preset on this machine.
Use it to size the token budget before any real run.
python bench.py --config hoard_small --seq_len 1024 --batch 16 --iters 5
"""
import argparse, time
import mlx.core as mx
import mlx.nn as nn
import configs
from model import HOARD
def main():
ap = argparse.ArgumentParser()
ap.add_argument("--config", default="hoard_small")
ap.add_argument("--seq_len", type=int, default=1024)
ap.add_argument("--batch", type=int, default=16)
ap.add_argument("--iters", type=int, default=5)
ap.add_argument("--dtype", default="float32", choices=["float32", "bfloat16"])
a = ap.parse_args()
cfg = configs.get(a.config)
model = HOARD(cfg)
if a.dtype == "bfloat16":
model.set_dtype(mx.bfloat16)
c = model.param_counts()
print(f"{a.config}: total {c['total']/1e6:.1f}M, active/token/loop {c['active_per_token_per_loop']/1e6:.1f}M, loops {cfg.n_loops}")
def loss_fn(model, x):
logits = model(x[:, :-1])
return nn.losses.cross_entropy(logits.astype(mx.float32), x[:, 1:], reduction="mean")
grad_fn = nn.value_and_grad(model, loss_fn)
x = mx.random.randint(0, cfg.vocab_size, (a.batch, a.seq_len + 1))
# warmup
l, g = grad_fn(model, x); mx.eval(l, g)
t0 = time.time()
for _ in range(a.iters):
l, g = grad_fn(model, x); mx.eval(l, g)
dt = (time.time() - t0) / a.iters
toks = a.batch * a.seq_len
print(f"fwd+bwd: {dt*1000:.0f} ms/step, {toks/dt:,.0f} tok/s "
f"-> 1B tokens ~ {1e9/(toks/dt)/3600:.1f} h on this machine")
print(f"peak memory: {mx.get_peak_memory()/2**30:.2f} GB")
if __name__ == "__main__":
main()