| """Time each component of vision tower forward to find the actual bottleneck.""" |
| import sys, time |
| sys.path.insert(0, ".") |
|
|
| import torch |
| import torch.nn.functional as F |
| from peft import PeftModel |
| from transformers import AutoModelForImageTextToText, AutoProcessor |
|
|
| from training.Policy.policy_dataset import PolicyDataset, _load_frames |
| from training.Policy import make_cot_belief_cache as M |
|
|
|
|
| def main(): |
| print("=" * 70) |
| print("Per-component timing of vision tower forward") |
| print("=" * 70) |
| proc = AutoProcessor.from_pretrained( |
| "checkpoints/VLA/qwen3vl4b_cot_belief_perframe/best") |
| ds = PolicyDataset( |
| manifests=["data/policy_labels/val.json"], |
| split="val", n_frames=8, sampling="last_biased", source_filter="all", |
| ) |
| all_imgs = [ |
| _load_frames(ds.samples[i]["source_dir"], |
| ds.samples[i]["frame_indices"], n_frames=8) |
| for i in range(8) |
| ] |
|
|
| print("\n[load]") |
| model = AutoModelForImageTextToText.from_pretrained( |
| "models/Qwen3-VL-4B-Instruct", |
| dtype=torch.bfloat16, |
| attn_implementation="sdpa", |
| ) |
| model.resize_token_embeddings(151674) |
| model = PeftModel.from_pretrained( |
| model, "checkpoints/VLA/qwen3vl4b_cot_belief_perframe/best" |
| ).merge_and_unload() |
| model.cuda().eval() |
|
|
| |
| print("\n[device check] ALL submodules of vision tower:") |
| cpu_modules = [] |
| for name, mod in model.visual.named_modules(): |
| try: |
| ps = list(mod.parameters(recurse=False)) |
| if not ps: |
| continue |
| d = ps[0].device |
| t = ps[0].dtype |
| if d.type != "cuda": |
| cpu_modules.append((name, str(d), str(t))) |
| except Exception: |
| pass |
| if cpu_modules: |
| print(f" ⚠️ {len(cpu_modules)} submodules NOT on cuda:") |
| for n, d, t in cpu_modules[:10]: |
| print(f" {n} {d} {t}") |
| else: |
| print(" ✓ all on cuda") |
|
|
| |
| print("\n[prep inputs bs=1]") |
| inputs = M._build_inputs(proc, [all_imgs[0]], [{}], resize_short=336) |
| pv = inputs["pixel_values"].cuda().to(torch.bfloat16) |
| grid_thw = inputs["image_grid_thw"].cuda() |
| print(f" pixel_values: {tuple(pv.shape)}") |
| print(f" grid_thw: {tuple(grid_thw.shape)}, values:\n{grid_thw}") |
|
|
| vt = model.visual |
| n_blocks = len(list(vt.blocks)) |
| print(f" vision tower has {n_blocks} blocks") |
|
|
| |
| with torch.no_grad(): |
| torch.cuda.synchronize(); t0 = time.time() |
| h = vt.patch_embed(pv) |
| torch.cuda.synchronize(); print(f" patch_embed: {(time.time()-t0)*1000:.1f} ms, shape={tuple(h.shape)}") |
|
|
| t0 = time.time() |
| pos_embeds = vt.fast_pos_embed_interpolate(grid_thw) |
| torch.cuda.synchronize(); print(f" pos_embed_interpolate: {(time.time()-t0)*1000:.1f} ms") |
| h = h + pos_embeds |
|
|
| t0 = time.time() |
| rope = vt.rot_pos_emb(grid_thw) |
| torch.cuda.synchronize(); print(f" rot_pos_emb: {(time.time()-t0)*1000:.1f} ms") |
|
|
| seq_len = h.size(0) |
| h = h.reshape(seq_len, -1) |
| rope = rope.reshape(seq_len, -1) |
| emb = torch.cat((rope, rope), dim=-1) |
| position_embeddings = (emb.cos(), emb.sin()) |
|
|
| cu_seqlens = torch.repeat_interleave( |
| grid_thw[:, 1] * grid_thw[:, 2], grid_thw[:, 0] |
| ).cumsum(dim=0, dtype=torch.int32) |
| cu_seqlens = F.pad(cu_seqlens, (1, 0), value=0) |
|
|
| |
| block_times = [] |
| for i, blk in enumerate(vt.blocks): |
| torch.cuda.synchronize() |
| t0 = time.time() |
| h = blk(h, cu_seqlens=cu_seqlens, |
| position_embeddings=position_embeddings) |
| torch.cuda.synchronize() |
| t = (time.time() - t0) * 1000 |
| block_times.append(t) |
| if i < 3 or i == n_blocks - 1: |
| print(f" block[{i}]: {t:.1f} ms") |
| print(f" block 0-2 mean: {sum(block_times[:3])/3:.1f} ms") |
| print(f" block ALL mean: {sum(block_times)/len(block_times):.1f} ms") |
| print(f" block ALL total: {sum(block_times):.1f} ms") |
|
|
| torch.cuda.synchronize(); t0 = time.time() |
| out = vt.merger(h) |
| torch.cuda.synchronize(); print(f" merger: {(time.time()-t0)*1000:.1f} ms") |
|
|
| |
| print("\n[zoom: block[0] attn vs mlp]") |
| with torch.no_grad(): |
| blk = vt.blocks[0] |
| h_in = h.detach().clone().requires_grad_(False) |
| torch.cuda.synchronize(); t0 = time.time() |
| for _ in range(3): |
| ho = blk.attn(blk.norm1(h_in), cu_seqlens=cu_seqlens, |
| position_embeddings=position_embeddings) |
| torch.cuda.synchronize() |
| print(f" attn (3 reps): {(time.time()-t0)*1000:.1f} ms total = {(time.time()-t0)/3*1000:.1f} ms/call") |
|
|
| torch.cuda.synchronize(); t0 = time.time() |
| for _ in range(3): |
| mo = blk.mlp(blk.norm2(h_in)) |
| torch.cuda.synchronize() |
| print(f" mlp (3 reps): {(time.time()-t0)*1000:.1f} ms total = {(time.time()-t0)/3*1000:.1f} ms/call") |
|
|
|
|
| if __name__ == "__main__": |
| main() |
|
|