fusionops-env / src /tasks.py
AnishaRoy5555's picture
Add multi-stage MatMul task with skip connection
ef84d90 unverified
Raw
History Blame Contribute Delete
6.89 kB
"""
FusionOps Task Definitions
Three fixed tasks with increasing difficulty.
Each returns a Graph ready for the environment.
"""
from __future__ import annotations
from .models import Graph
# ============================================================
# TASK 1: Linear Fusion Chain (Easy)
# ============================================================
# 6 Pointwise ops in a linear chain: T0 -> Op0 -> T1 -> Op1 -> T2 -> ... -> T6
# Optimal: fuse all into one mega-subgraph.
# Naive: 6 separate subgraphs, each loading and evicting.
# Tests: basic fusion understanding.
# Expected baseline score: 0.6-0.8
TASK_1_DATA = {
"widths": [128, 128, 128, 128, 128, 128, 128],
"heights": [128, 128, 128, 128, 128, 128, 128],
"inputs": [[0], [1], [2], [3], [4], [5]],
"outputs": [[1], [2], [3], [4], [5], [6]],
"base_costs": [800, 600, 900, 500, 700, 400],
"op_types": ["Pointwise", "Pointwise", "Pointwise",
"Pointwise", "Pointwise", "Pointwise"],
"fast_memory_capacity": 40000,
"slow_memory_bandwidth": 10,
"native_granularity": [128, 128],
}
# ============================================================
# TASK 2: Diamond with Branching (Medium)
# ============================================================
# Graph structure:
# T0 -> Op0 -> T1
# T1 -> Op1 -> T2
# T1 -> Op2 -> T3
# T2, T3 -> Op3 -> T4
# T4 -> Op4 -> T5
# T1, T5 -> Op5 -> T6
#
# Key challenges:
# - T1 has 3 consumers (Op1, Op2, Op5) = high fan-out, retain decision critical
# - Diamond: Op1 and Op2 branch from T1, merge at Op3
# - Skip connection: T1 feeds Op5 directly (late consumer)
# - Agent must decide: retain T1 throughout? Or recompute Op0?
# Expected baseline score: 0.3-0.5
TASK_2_DATA = {
"widths": [128, 128, 128, 128, 128, 128, 128],
"heights": [128, 128, 128, 128, 128, 128, 128],
"inputs": [
[0], # Op0: T0 -> T1
[1], # Op1: T1 -> T2
[1], # Op2: T1 -> T3
[2, 3], # Op3: T2, T3 -> T4
[4], # Op4: T4 -> T5
[1, 5], # Op5: T1, T5 -> T6 (skip connection)
],
"outputs": [[1], [2], [3], [4], [5], [6]],
"base_costs": [1200, 1000, 1000, 1500, 800, 1100],
"op_types": ["Pointwise", "Pointwise", "Pointwise",
"Pointwise", "Pointwise", "Pointwise"],
"fast_memory_capacity": 50000,
"slow_memory_bandwidth": 10,
"native_granularity": [128, 128],
}
# ============================================================
# TASK 3: Chained MatMul with Memory Pressure (Hard)
# ============================================================
# Graph structure:
# T0 (128x128), T1 (128x128) -> Op0 (MatMul) -> T4 (128x128)
# T4 (128x128), T2 (128x128) -> Op1 (MatMul) -> T5 (128x128)
# T5 (128x128) -> Op2 (Pointwise) -> T6 (128x128)
# T6 (128x128), T3 (128x128) -> Op3 (MatMul) -> T7 (128x128)
#
# Key challenges:
# - All tensors 128x128, fast memory = 50000
# - Single MatMul at native: WS = 3 * 16384 = 49152 < 50000 = OK (barely)
# - But fusing 2 MatMuls at native K: WS >> 50000 = OOM, needs split-K
# - Op2 (Pointwise) breaks the MatMul chain: fusion boundary decision
# - Mixed op types
# Expected baseline score: 0.1-0.3
TASK_3_DATA = {
"widths": [128, 128, 128, 128, 128, 128, 128, 128],
"heights": [128, 128, 128, 128, 128, 128, 128, 128],
"inputs": [
[0, 1], # Op0 (MatMul): T0 @ T1 -> T4
[4, 2], # Op1 (MatMul): T4 @ T2 -> T5
[5], # Op2 (Pointwise): T5 -> T6
[6, 3], # Op3 (MatMul): T6 @ T3 -> T7
],
"outputs": [[4], [5], [6], [7]],
"base_costs": [2000, 2000, 500, 2000],
"op_types": ["MatMul", "MatMul", "Pointwise", "MatMul"],
"fast_memory_capacity": 50000,
"slow_memory_bandwidth": 10,
"native_granularity": [128, 128],
}
# ============================================================
# TASK 4: Multi-Stage MatMul with Skip Connection (Hardest)
# ============================================================
# Graph structure (8 ops, 16 tensors):
# T0(128x128), T1(128x128) -> Op0 (MatMul) -> T8
# T8 -> Op1 (Pointwise) -> T9
# T9, T2(128x128) -> Op2 (MatMul) -> T10
# T10 -> Op3 (Pointwise) -> T11
# T11, T3(128x128) -> Op4 (MatMul) -> T12
# T12 -> Op5 (Pointwise) -> T13
# T13, T8 -> Op6 (Pointwise) -> T14 [skip connection from T8]
# T14 -> Op7 (Pointwise) -> T15
#
# Key challenges:
# - 3 MatMul ops, each needs split-K when fused with subsequent Pointwise
# - T8 has 2 consumers far apart (Op1 and Op6) - tests retention reasoning
# - 8-op chain requires planning horizon
# - Naive scoring ~0.0, basic fusion ~0.12, smart fusion ~0.25, optimal ~0.30
# Expected baseline score: 0.05-0.20
TASK_4_DATA = {
"widths": [128] * 16,
"heights": [128] * 16,
"inputs": [
[0, 1], # Op0 (MatMul): T0 @ T1 -> T8
[8], # Op1 (Pointwise): T8 -> T9
[9, 2], # Op2 (MatMul): T9 @ T2 -> T10
[10], # Op3 (Pointwise): T10 -> T11
[11, 3], # Op4 (MatMul): T11 @ T3 -> T12
[12], # Op5 (Pointwise): T12 -> T13
[13, 8], # Op6 (Pointwise): T13 + T8 -> T14 [skip connection]
[14], # Op7 (Pointwise): T14 -> T15
],
"outputs": [[8], [9], [10], [11], [12], [13], [14], [15]],
"base_costs": [2000, 400, 2000, 400, 2000, 400, 600, 400],
"op_types": ["MatMul", "Pointwise", "MatMul", "Pointwise",
"MatMul", "Pointwise", "Pointwise", "Pointwise"],
"fast_memory_capacity": 60000,
"slow_memory_bandwidth": 10,
"native_granularity": [128, 128],
}
# ============================================================
# Task registry
# ============================================================
TASKS = {
"task1_linear": TASK_1_DATA,
"task2_diamond": TASK_2_DATA,
"task3_matmul": TASK_3_DATA,
"task4_multistage": TASK_4_DATA,
}
def load_task(task_name: str) -> Graph:
"""Load a task by name. Returns a Graph."""
if task_name not in TASKS:
raise ValueError(f"Unknown task: {task_name}. Available: {list(TASKS.keys())}")
return Graph.from_json(TASKS[task_name])
def get_task_config(task_name: str) -> dict:
"""Get task metadata for environment configuration."""
configs = {
"task1_linear": {"max_steps": 10, "description": "Linear chain of 6 Pointwise ops. Test basic fusion."},
"task2_diamond": {"max_steps": 12, "description": "Diamond graph with skip connections. Test retention decisions."},
"task3_matmul": {"max_steps": 15, "description": "Chained MatMuls with tight memory. Test split-K and memory management."},
"task4_multistage": {"max_steps": 20, "description": "Multi-stage MatMul with skip connection. Test long-horizon planning, split-K, and selective retention."},
}
return configs[task_name]
def list_tasks() -> list[str]:
return list(TASKS.keys())