Files
1jehuang--jcode/scripts/benchmark_takehome.py
T
wehub-resource-sync a789495a98
FreeBSD Smoke / FreeBSD Smoke (x86_64) (push) Has been cancelled
CI / Quality Guardrails (push) Has been cancelled
CI / Build & Test (macos-latest) (push) Has been cancelled
CI / Build & Test (ubuntu-latest) (push) Has been cancelled
CI / Build & Test (windows-latest) (push) Has been cancelled
CI / Format (push) Has been cancelled
CI / PowerShell Syntax (push) Has been cancelled
CI / Windows Cross-Target Check (Linux) (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 13:10:34 +08:00

409 lines
13 KiB
Python
Executable File

#!/usr/bin/env python3
"""
Benchmark single agent vs swarm on the Anthropic Performance Take-Home.
Usage:
BENCHMARK_TIMEOUT=5 python scripts/benchmark_takehome.py single
BENCHMARK_TIMEOUT=10 python scripts/benchmark_takehome.py swarm
BENCHMARK_TIMEOUT=10 python scripts/benchmark_takehome.py both
"""
import socket
import json
import os
import sys
import time
import select
import shutil
import subprocess
import threading
from pathlib import Path
DEBUG_SOCKET = f"/run/user/{os.getuid()}/jcode-debug.sock"
TAKEHOME_SOURCE = os.environ.get(
"TAKEHOME_SOURCE", str(Path.home() / "original_performance_takehome")
)
BENCHMARK_DIR = "/tmp/takehome-benchmark"
TIMEOUT_MINUTES = int(os.environ.get('BENCHMARK_TIMEOUT', '10'))
BASELINE = 147734
def send_cmd(cmd: str, session_id: str = None, timeout: float = 300) -> tuple:
"""Send a debug command and get response."""
sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
sock.connect(DEBUG_SOCKET)
sock.setblocking(False)
req = {"type": "debug_command", "id": 1, "command": cmd}
if session_id:
req["session_id"] = session_id
sock.send((json.dumps(req) + '\n').encode())
start = time.time()
data = b""
while time.time() - start < timeout:
ready, _, _ = select.select([sock], [], [], 1.0)
if ready:
try:
chunk = sock.recv(65536)
if not chunk:
break
data += chunk
if b'\n' in data:
break
except BlockingIOError:
continue
sock.close()
if not data:
return False, "", "Timeout"
try:
resp = json.loads(data.decode().strip())
return resp.get('ok', False), resp.get('output', ''), resp.get('error', '')
except json.JSONDecodeError as e:
return False, "", f"JSON error: {e}"
def create_session(working_dir: str) -> tuple:
"""Create a session and return (session_id, friendly_name)."""
ok, output, err = send_cmd(f"create_session:{working_dir}", timeout=120)
if not ok:
raise RuntimeError(f"Failed to create session: {err}")
data = json.loads(output)
return data['session_id'], data.get('friendly_name', data['session_id'][:12])
def destroy_session(session_id: str):
"""Destroy a session."""
send_cmd(f"destroy_session:{session_id}")
def setup_workspace(name: str) -> str:
"""Create a clean copy of the take-home."""
workspace = os.path.join(BENCHMARK_DIR, name)
if os.path.exists(workspace):
shutil.rmtree(workspace)
shutil.copytree(TAKEHOME_SOURCE, workspace)
return workspace
def get_cycles(workspace: str) -> int:
"""Run tests and return cycle count."""
try:
result = subprocess.run(
["python", "tests/submission_tests.py", "-v"],
cwd=workspace,
capture_output=True,
text=True,
timeout=120
)
for line in (result.stdout + result.stderr).split('\n'):
if 'CYCLES:' in line:
return int(line.split('CYCLES:')[1].strip())
except Exception as e:
print(f"Error getting cycles: {e}")
return BASELINE
def make_single_prompt(workspace: str) -> str:
return f"""You are optimizing a VLIW SIMD kernel for Anthropic's performance take-home.
IMPORTANT: You MUST work in this directory: {workspace}
All file paths should be relative to or within this directory.
Goal: Reduce the cycle count from 147,734 to as low as possible.
Key files (in {workspace}):
- problem.py: Defines the Machine, instruction set (VLIW bundles, vector ops, VLEN=16)
- perf_takehome.py: Contains KernelBuilder.build_kernel() - this is what you optimize
- tests/submission_tests.py: Run to verify correctness and see cycle count
DO NOT modify tests/ folder.
Key optimizations to try:
1. VLIW parallelism - pack independent operations into single bundles
2. Vector operations - use VLEN=16 to process 16 elements at once
3. Reduce memory access latency - batch loads/stores
4. Optimize the hash function - it runs many times per element
Start by reading {workspace}/problem.py to understand the machine, then optimize build_kernel().
After each change, run `cd {workspace} && python tests/submission_tests.py` to check correctness and cycles.
Work efficiently - focus on the highest-impact optimizations first."""
def run_single_agent() -> dict:
"""Run a single agent benchmark using async messaging."""
print("\n" + "=" * 60)
print(f"SINGLE AGENT BENCHMARK (timeout: {TIMEOUT_MINUTES}m)")
print("=" * 60)
workspace = setup_workspace("single")
print(f"Workspace: {workspace}")
start_time = time.time()
session_id = None
best_cycles = BASELINE
try:
session_id, name = create_session(workspace)
print(f"Session: {name}")
# Initial cycles
cycles = get_cycles(workspace)
print(f"Baseline: {cycles} cycles")
# Send optimization task asynchronously
print("\nStarting optimization (async)...")
prompt = make_single_prompt(workspace)
# Use message_async to start the job
ok, output, err = send_cmd(f"message_async:{prompt}", session_id, timeout=30)
if not ok:
print(f"Failed to start async job: {err}")
return {"approach": "single", "cycles": BASELINE, "time_seconds": 0, "error": err}
job_data = json.loads(output)
job_id = job_data.get("job_id")
print(f"Job started: {job_id}")
timeout_seconds = TIMEOUT_MINUTES * 60
last_cycles = BASELINE
check_interval = 30 # Check every 30 seconds
while time.time() - start_time < timeout_seconds:
elapsed = time.time() - start_time
# Check job status
ok, status_output, _ = send_cmd(f"job_status:{job_id}", session_id, timeout=10)
if ok:
try:
status = json.loads(status_output)
job_status = status.get("status", "unknown")
if job_status in ["completed", "failed"]:
print(f"\n[{elapsed/60:.1f}m] Job {job_status}")
break
except:
pass
# Check current cycles in workspace
cycles = get_cycles(workspace)
if cycles < best_cycles:
best_cycles = cycles
print(f"[{elapsed/60:.1f}m] NEW BEST: {cycles} cycles ({BASELINE/cycles:.2f}x speedup)")
elif cycles != last_cycles:
print(f"[{elapsed/60:.1f}m] Cycles: {cycles}")
last_cycles = cycles
time.sleep(check_interval)
# Final check
cycles = get_cycles(workspace)
if cycles < best_cycles:
best_cycles = cycles
elapsed = time.time() - start_time
print(f"\nFinal: {best_cycles} cycles in {elapsed/60:.1f}m ({BASELINE/best_cycles:.2f}x)")
return {
"approach": "single",
"cycles": best_cycles,
"time_seconds": elapsed,
"workspace": workspace
}
except Exception as e:
print(f"Error: {e}")
return {
"approach": "single",
"cycles": BASELINE,
"time_seconds": time.time() - start_time,
"error": str(e)
}
finally:
if session_id:
destroy_session(session_id)
def run_swarm(n_agents: int = 2) -> dict:
"""Run autonomous swarm benchmark using swarm_message_async.
This uses the full swarm capability where ONE agent becomes coordinator,
creates a plan, and spawns subagents automatically.
"""
print("\n" + "=" * 60)
print(f"AUTONOMOUS SWARM BENCHMARK (timeout: {TIMEOUT_MINUTES}m)")
print("=" * 60)
workspace = setup_workspace("swarm")
print(f"Workspace: {workspace}")
start_time = time.time()
session_id = None
best_cycles = BASELINE
try:
# Create ONE session - it becomes coordinator and spawns agents
session_id, name = create_session(workspace)
print(f"Coordinator: {name}")
baseline = get_cycles(workspace)
print(f"Baseline: {baseline} cycles")
# Use swarm_message_async - this will:
# 1. Plan subtasks automatically
# 2. Spawn subagents to work in parallel
# 3. Integrate results
prompt = f"""Optimize the VLIW SIMD kernel in {workspace}/perf_takehome.py to minimize cycle count.
Current baseline: 147,734 cycles. Goal: as low as possible.
The problem:
- {workspace}/problem.py defines the machine (VLEN=16 vectors, VLIW bundles, slot limits)
- {workspace}/perf_takehome.py has build_kernel() which needs optimization
- Run `cd {workspace} && python tests/submission_tests.py` to verify correctness and check cycles
Key optimization strategies:
1. Vectorization - use VLEN=16 to process 16 elements at once
2. VLIW packing - bundle independent operations together
3. Reduce memory latency - batch loads/stores
4. Optimize hash function - it runs many times per element
Break this into parallel subtasks and spawn agents to work on different optimizations.
DO NOT modify tests/ folder."""
print("\nStarting autonomous swarm (swarm_message_async)...")
ok, output, err = send_cmd(f"swarm_message_async:{prompt}", session_id, timeout=30)
if not ok:
print(f"Failed to start swarm: {err}")
return {"approach": "swarm", "cycles": BASELINE, "time_seconds": 0, "error": err}
job_data = json.loads(output)
job_id = job_data.get("job_id")
print(f"Swarm job started: {job_id}")
timeout_seconds = TIMEOUT_MINUTES * 60
last_cycles = BASELINE
check_interval = 30
while time.time() - start_time < timeout_seconds:
elapsed = time.time() - start_time
# Check job status
ok, status_output, _ = send_cmd(f"job_status:{job_id}", session_id, timeout=10)
if ok:
try:
status = json.loads(status_output)
job_status = status.get("status", "unknown")
if job_status == "completed":
print(f"\n[{elapsed/60:.1f}m] Swarm completed!")
break
elif job_status == "failed":
print(f"\n[{elapsed/60:.1f}m] Swarm failed: {status.get('error', 'unknown')}")
break
except:
pass
# Check swarm members (to see how many agents were spawned)
ok, swarm_output, _ = send_cmd("swarm:members", session_id, timeout=10)
if ok and elapsed < 60: # Only print once early on
try:
print(f"[{elapsed/60:.1f}m] Swarm: {swarm_output[:100]}...")
except:
pass
# Check current cycles
cycles = get_cycles(workspace)
if cycles < best_cycles:
best_cycles = cycles
print(f"[{elapsed/60:.1f}m] NEW BEST: {cycles} cycles ({BASELINE/cycles:.2f}x)")
elif cycles != last_cycles:
print(f"[{elapsed/60:.1f}m] Cycles: {cycles}")
last_cycles = cycles
time.sleep(check_interval)
# Final check
cycles = get_cycles(workspace)
if cycles < best_cycles:
best_cycles = cycles
elapsed = time.time() - start_time
print(f"\nFinal: {best_cycles} cycles in {elapsed/60:.1f}m ({BASELINE/best_cycles:.2f}x)")
return {
"approach": "swarm",
"cycles": best_cycles,
"time_seconds": elapsed,
"workspace": workspace
}
except Exception as e:
print(f"Error: {e}")
return {
"approach": "swarm",
"cycles": BASELINE,
"time_seconds": time.time() - start_time,
"error": str(e)
}
finally:
if session_id:
destroy_session(session_id)
def print_results(results: dict):
"""Print comparison table."""
print("\n" + "=" * 60)
print("RESULTS")
print("=" * 60)
print(f"{'Approach':<15} {'Cycles':<12} {'Time':<10} {'Speedup':<10}")
print("-" * 60)
for name, data in results.items():
cycles = data['cycles']
time_m = data['time_seconds'] / 60
speedup = BASELINE / cycles
print(f"{name:<15} {cycles:<12} {time_m:<10.1f}m {speedup:<10.2f}x")
if len(results) > 1:
winner = min(results.items(), key=lambda x: x[1]['cycles'])
print(f"\nWinner: {winner[0]} ({winner[1]['cycles']} cycles)")
def main():
if len(sys.argv) < 2:
print(__doc__)
sys.exit(1)
mode = sys.argv[1].lower()
os.makedirs(BENCHMARK_DIR, exist_ok=True)
print(f"Benchmark timeout: {TIMEOUT_MINUTES} minutes per approach")
print(f"Set BENCHMARK_TIMEOUT env var to change (e.g., BENCHMARK_TIMEOUT=30)")
if mode == "single":
r = run_single_agent()
print_results({"single": r})
elif mode == "swarm":
r = run_swarm()
print_results({"swarm": r})
elif mode == "both":
results = {}
results['single'] = run_single_agent()
results['swarm'] = run_swarm()
print_results(results)
else:
print(f"Unknown mode: {mode}")
print(__doc__)
sys.exit(1)
if __name__ == "__main__":
main()