import torch import time import os import sys import gc print(f'Device: {torch.cuda.get_device_name(0)}') print(f'Total Memory: {torch.cuda.get_device_properties(0).total_memory / 1e9:.1f} GB') print() def mem_info(): alloc = torch.cuda.memory_allocated() / 1e6 reserved = torch.cuda.memory_reserved() / 1e6 return f'alloc={alloc:.0f}MB, reserved={reserved:.0f}MB' def test_attention(heads, seq_len, head_dim, dtype=torch.float32): label = f'Attn h={heads} s={seq_len} d={head_dim} {"fp32" if dtype==torch.float32 else "fp16"}' print(f'=== {label} ===', flush=True) # Calculate memory needed attn_size = heads * seq_len * seq_len * (4 if dtype==torch.float32 else 2) qk_size = 2 * heads * seq_len * head_dim * (4 if dtype==torch.float32 else 2) total_est = (attn_size + qk_size) / 1e6 print(f' Est memory: {total_est:.0f}MB ({mem_info()})', flush=True) try: q = torch.randn(1, heads, seq_len, head_dim, device='cuda', dtype=dtype) k = torch.randn(1, heads, seq_len, head_dim, device='cuda', dtype=dtype) print(f' Q/K allocated ({mem_info()})', flush=True) torch.cuda.synchronize() t = time.time() scores = torch.matmul(q, k.transpose(-2, -1)) torch.cuda.synchronize() elapsed = time.time() - t print(f' OK: {elapsed:.3f}s, scores shape={list(scores.shape)} ({mem_info()})', flush=True) del q, k, scores gc.collect() torch.cuda.empty_cache() return True except Exception as e: print(f' FAIL: {e}', flush=True) gc.collect() torch.cuda.empty_cache() return False # Progressive attention scaling test_attention(4, 512, 64) test_attention(8, 1024, 64) test_attention(8, 1024, 128) test_attention(16, 2048, 128) test_attention(24, 2048, 128) test_attention(24, 4096, 128) # full Lumina2 scale! # If full scale fails in fp32, try fp16 print() print('=== fp16 ATTENTION TESTS ===', flush=True) test_attention(24, 4096, 128, torch.float16) # Test split attention approach (process in chunks) print() print('=== SPLIT ATTENTION (simulate ComfyUI split attn) ===', flush=True) try: heads = 24 seq = 4096 hd = 128 chunk = 512 # process 512 tokens at a time q = torch.randn(1, heads, seq, hd, device='cuda', dtype=torch.float32) k = torch.randn(1, heads, seq, hd, device='cuda', dtype=torch.float32) v = torch.randn(1, heads, seq, hd, device='cuda', dtype=torch.float32) out = torch.zeros(1, heads, seq, hd, device='cuda', dtype=torch.float32) torch.cuda.synchronize() t = time.time() for i in range(0, seq, chunk): q_chunk = q[:, :, i:i+chunk, :] scores = torch.matmul(q_chunk, k.transpose(-2, -1)) attn = torch.softmax(scores, dim=-1) out[:, :, i:i+chunk, :] = torch.matmul(attn, v) del scores, attn torch.cuda.synchronize() elapsed = time.time() - t print(f' Split attention OK: {elapsed:.3f}s', flush=True) del q, k, v, out gc.collect() torch.cuda.empty_cache() except Exception as e: print(f' Split attention FAIL: {e}', flush=True) print() print('=== DONE ===', flush=True) torch.cuda.synchronize() os._exit(0)