"""Fase 0: verifica qué attn_implementation usar y si flash-linear-attention compila en SM121. No bloqueante: flash_attn y flash-linear-attention son "nice to have"; si fallan, el resultado documentado es usar el fallback correspondiente (sdpa / PyTorch puro). """ import sys import time import torch RESULTS = {} def test_flash_attn(): try: from flash_attn import flash_attn_func except ImportError as e: return False, f"import failed: {e}" try: device = "cuda" dtype = torch.bfloat16 batch, seqlen, nheads, headdim = 2, 128, 8, 64 q = torch.randn(batch, seqlen, nheads, headdim, device=device, dtype=dtype) k = torch.randn(batch, seqlen, nheads, headdim, device=device, dtype=dtype) v = torch.randn(batch, seqlen, nheads, headdim, device=device, dtype=dtype) out = flash_attn_func(q, k, v, causal=True) torch.cuda.synchronize() assert out.shape == (batch, seqlen, nheads, headdim) return True, f"forward ok, output shape {tuple(out.shape)}" except Exception as e: return False, f"forward failed: {type(e).__name__}: {e}" def test_sdpa(): try: device = "cuda" dtype = torch.bfloat16 batch, nheads, seqlen, headdim = 2, 8, 128, 64 q = torch.randn(batch, nheads, seqlen, headdim, device=device, dtype=dtype) k = torch.randn(batch, nheads, seqlen, headdim, device=device, dtype=dtype) v = torch.randn(batch, nheads, seqlen, headdim, device=device, dtype=dtype) out = torch.nn.functional.scaled_dot_product_attention(q, k, v, is_causal=True) torch.cuda.synchronize() assert out.shape == (batch, nheads, seqlen, headdim) return True, f"forward ok, output shape {tuple(out.shape)}" except Exception as e: return False, f"forward failed: {type(e).__name__}: {e}" def test_flash_linear_attention(timeout_s=1200): start = time.time() try: import fla # noqa: F401 from fla.ops.gated_delta_rule import chunk_gated_delta_rule except ImportError as e: return False, f"import failed (package not installed): {e}" try: device = "cuda" dtype = torch.bfloat16 batch, seqlen, nheads, headdim = 2, 64, 4, 64 q = torch.randn(batch, seqlen, nheads, headdim, device=device, dtype=dtype, requires_grad=True) k = torch.randn(batch, seqlen, nheads, headdim, device=device, dtype=dtype, requires_grad=True) v = torch.randn(batch, seqlen, nheads, headdim, device=device, dtype=dtype, requires_grad=True) beta = torch.rand(batch, seqlen, nheads, device=device, dtype=dtype).sigmoid() g = -torch.rand(batch, seqlen, nheads, device=device, dtype=torch.float32) out, _ = chunk_gated_delta_rule(q, k, v, g, beta) loss = out.sum() loss.backward() torch.cuda.synchronize() if time.time() - start > timeout_s: return False, "compiled/ran but exceeded time budget" return True, f"forward+backward ok, output shape {tuple(out.shape)}" except Exception as e: elapsed = time.time() - start return False, f"failed after {elapsed:.0f}s: {type(e).__name__}: {e}" def main(): if not torch.cuda.is_available(): print("CUDA not available — aborting.") sys.exit(1) print(f"torch {torch.__version__}, CUDA {torch.version.cuda}, device: {torch.cuda.get_device_name(0)}") print() ok, msg = test_flash_attn() RESULTS["flash_attn"] = {"ok": ok, "detail": msg} print(f"[flash_attn] {'OK' if ok else 'FAIL'} — {msg}") ok, msg = test_sdpa() RESULTS["sdpa"] = {"ok": ok, "detail": msg} print(f"[sdpa] {'OK' if ok else 'FAIL'} — {msg}") recommended = "flash_attention_2" if RESULTS["flash_attn"]["ok"] else "sdpa" print(f"\n>>> attn_implementation recomendado para el training: {recommended}\n") print("Probando flash-linear-attention (opcional, acotado)...") ok, msg = test_flash_linear_attention() RESULTS["flash_linear_attention"] = {"ok": ok, "detail": msg} print(f"[flash-linear-attention] {'OK' if ok else 'FAIL (se descarta, no bloqueante)'} — {msg}") print("\n=== Resumen ===") for k, v in RESULTS.items(): print(f" {k}: {'OK' if v['ok'] else 'FAIL'} — {v['detail']}") if __name__ == "__main__": main()