{"slug": "deep-dive-anthropic-s-performance-take-home-the-one-claude-beat-humans-at", "title": "Deep Dive: Anthropic's Performance Take-Home (The One Claude Beat Humans At)", "summary": "Anthropic open-sourced its original performance engineering take-home, which asks candidates to optimize a kernel on a custom VLIW SIMD processor simulator. Claude Opus 4.5 achieved a 99x speedup, reducing the baseline from 147,734 cycles to 1,487 cycles, outperforming most human candidates. The task involves packing operations into instruction bundles to utilize the processor's 12 ALUs, 6 VALUs, and limited memory bandwidth.", "body_md": "Today, Anthropic [open-sourced their original performance engineering take-home](https://github.com/anthropics/original_performance_takehome). The task: optimize a kernel running on a custom [VLIW](https://en.wikipedia.org/wiki/Very_long_instruction_word) [SIMD](https://en.wikipedia.org/wiki/Single_instruction,_multiple_data) processor simulator. The baseline takes **147,734 cycles**. Claude Opus 4.5 got it down to **1,487 cycles** - a 99x speedup that beat most humans.\n\nI’m [Tristan](https://github.com/trirpi) ([@trirpi](https://twitter.com/trirpi)), and I work on AI kernels. Let’s break down how this whole system works.\n\n## The Architecture at a Glance[#](#the-architecture-at-a-glance)\n\nThis is a ** VLIW** (Very Long Instruction Word)\n\n**(Single Instruction Multiple Data) processor with a**\n\n[SIMD](https://en.wikipedia.org/wiki/Single_instruction,_multiple_data)**single core**(older versions of the take-home had multiple cores). Let me break down what that means.\n\n### VLIW: Compiler-Scheduled Parallelism[#](#vliw-compiler-scheduled-parallelism)\n\nIn a traditional processor, hardware figures out at runtime which instructions can run in parallel. In a **VLIW** processor, that job shifts to the **compiler** (or in this case, you).\n\nThe single core has multiple functional units that can all execute simultaneously:\n\n| Unit | Count | Operations |\n|---|---|---|\n| ALU | 12 | Scalar: `+` , `-` , `*` , `/` , `^` , `&` , `|` , `<<` , `>>` , `%` , `<` , `==` |\n| VALU | 6 | Vector (8 elements): same ops as ALU |\n| LOAD | 2 | `load` , `vload` (8 words), `const` |\n| STORE | 2 | `store` , `vstore` (8 words) |\n| FLOW | 1 | `select` , `jump` , `cond_jump` , `halt` |\n\nYou pack operations into **instruction bundles**. Each cycle, the processor executes one bundle, dispatching operations to all the units in parallel. If you only put one operation in a bundle, the other units sit idle. That’s why the baseline is so slow.\n\n**Example bundle** (executes in 1 cycle):\n\n```\n{\"alu\": [op1, op2, op3], \"valu\": [vop1, vop2], \"load\": [ld1, ld2]}\n```\n\nWith 12 ALUs and 6 VALUs (each processing 8 elements), this single core can theoretically do **12 + 6×8 = 60** arithmetic operations per cycle.\n\n### Memory Hierarchy[#](#memory-hierarchy)\n\n```\nflowchart LR\n    subgraph mem[\"💾 MAIN MEMORY\"]\n        DATA[\"Problem Data(tree, indices, values)\"]\n    end\n    \n    subgraph scratch[\"📦 SCRATCH SPACE (1536 words)\"]\n        REG[\"Works like registersAll ALU ops read/write here\"]\n    end\n    \n    mem <-->|\"LOAD/STORE⚠️ 2 each per cycle\"| scratch\n```\n\n**Main Memory**: Where the problem data lives. ALU/VALU can’t access it directly.** Scratch Space**: 1536 words of fast storage. All compute operations read/write scratch addresses.** Bottleneck**: Only** 2 loads**and** 2 stores**per cycle. This is often the limiting factor, not compute.\n\n## The Execution Engines[#](#the-execution-engines)\n\nThe processor has multiple **engines**, each capable of executing multiple **slots** per cycle. From [ problem.py](https://github.com/anthropics/original_performance_takehome/blob/main/problem.py#L48-L55):\n\n```\nSLOT_LIMITS = {\n    \"alu\": 12,      # 12 scalar ALU operations per cycle\n    \"valu\": 6,      # 6 vector ALU operations per cycle\n    \"load\": 2,      # 2 load operations per cycle\n    \"store\": 2,     # 2 store operations per cycle\n    \"flow\": 1,      # 1 flow control operation per cycle\n    \"debug\": 64,    # Debug operations (not counted)\n}\n```\n\n### What an Instruction Bundle Looks Like[#](#what-an-instruction-bundle-looks-like)\n\n```\nflowchart LR\n    subgraph bundle[\"📦 Instruction Bundle (1 clock cycle)\"]\n        subgraph compute[\"Compute\"]\n            ALU[\"alu:('+', dest, a, b)('-', dest, a, b)('*', dest, a, b)...up to 12\"]\n            VALU[\"valu:('*', vdest, va, vb)('+', vdest, va, vb)...up to 6\"]\n        end\n        subgraph memory[\"Memory\"]\n            LOAD[\"load:('load', dest, addr)('vload', vdest, addr)\"]\n            STORE[\"store:('store', addr, src)('vstore', addr, vsrc)\"]\n        end\n        subgraph control[\"Control\"]\n            FLOW[\"flow:('select', d, c, a, b)\"]\n            DEBUG[\"debug:('compare', loc, key)(not counted)\"]\n        end\n    end\n```\n\nAn instruction is a Python dict mapping engine names to lists of operations. Here’s a [real example](https://github.com/anthropics/original_performance_takehome/blob/main/problem.py#L86-L87):\n\n```\n{\"valu\": [(\"*\", 4, 0, 0), (\"+\", 8, 4, 0)], \"load\": [(\"load\", 16, 17)]}\n```\n\nThis executes **three operations in one cycle**:\n\n- Vector multiply:\n`scratch[4:12] = scratch[0:8] * scratch[0:8]`\n\n- Vector add:\n`scratch[8:16] = scratch[4:12] + scratch[0:8]`\n\n- Scalar load:\n`scratch[16] = memory[scratch[17]]`\n\n## The Problem: Batched Tree Traversal[#](#the-problem-batched-tree-traversal)\n\nThe kernel implements a batched tree traversal with hashing. Here’s the flow:\n\n``` php\nflowchart LR\n    subgraph rounds[\"🔄 16 Rounds\"]\n        R0[\"Round 0\"] --> R1[\"Round 1\"] --> R2[\"Round 2\"] --> RN[\"...\"]\n    end\n    \n    subgraph batch[\"📊 Batch of 256 items\"]\n        B0[\"Item 0\"]\n        B1[\"Item 1\"]\n        B2[\"Item 2\"]\n        BN[\"...\"]\n    end\n    \n    subgraph ALGO[\"⚙️ Per-item computation\"]\n        A1[\"idx = indices[i]\"] --> A2[\"val = values[i]\"]\n        A2 --> A3[\"node_val = tree[idx]\"]\n        A3 --> A4[\"val = hash(val ^ node_val)\"]\n        A4 --> A5[\"idx = 2*idx + (1 if even else 2)\"]\n        A5 --> A6[\"if idx >= n_nodes: idx = 0\"]\n    end\n    \n    rounds --> batch\n    batch --> ALGO\n```\n\nFrom the [reference kernel](https://github.com/anthropics/original_performance_takehome/blob/main/problem.py#L467-L484):\n\n``` python\ndef reference_kernel(t: Tree, inp: Input):\n    \"\"\"\n    A parallel tree traversal where at each node we set\n    cur_inp_val = myhash(cur_inp_val ^ node_val)\n    and then choose the left branch if cur_inp_val is even.\n    If we reach the bottom of the tree we wrap around to the top.\n    \"\"\"\n    for h in range(inp.rounds):\n        for i in range(len(inp.indices)):\n            idx = inp.indices[i]\n            val = inp.values[i]\n            val = myhash(val ^ t.values[idx])\n            idx = 2 * idx + (1 if val % 2 == 0 else 2)\n            idx = 0 if idx >= len(t.values) else idx\n            inp.values[i] = val\n            inp.indices[i] = idx\n```\n\nTest configuration:\n\n**Tree height**: 10 (2047 nodes in a[perfect binary tree](https://www.programiz.com/dsa/perfect-binary-tree))** Batch size**: 256 items processed** Rounds**: 16 iterations\n\nThat’s `256 × 16 = 4096`\n\ntraversal steps, each involving a hash computation.\n\n### The Hash Function[#](#the-hash-function)\n\nThe hash runs 6 stages, each doing `a = (a op1 const) op2 (a op3 shift)`\n\n:\n\n| Stage | Formula |\n|---|---|\n| 0 | `a = (a + 0x7ED55D16) + (a << 12)` |\n| 1 | `a = (a ^ 0xC761C23C) ^ (a >> 19)` |\n| 2 | `a = (a + 0x165667B1) + (a << 5)` |\n| 3 | `a = (a + 0xD3A2646C) ^ (a << 9)` |\n| 4 | `a = (a + 0xFD7046C5) + (a << 3)` |\n| 5 | `a = (a ^ 0xB55A4F09) ^ (a >> 16)` |\n\nEach stage = 3 ALU ops. **Total: 6 × 3 = 18 ALU operations per hash.**\n\nThe hash is defined [data-driven](https://github.com/anthropics/original_performance_takehome/blob/main/problem.py#L439-L464) for easy kernel implementation:\n\n```\nHASH_STAGES = [\n    (\"+\", 0x7ED55D16, \"+\", \"<<\", 12),\n    (\"^\", 0xC761C23C, \"^\", \">>\", 19),\n    (\"+\", 0x165667B1, \"+\", \"<<\", 5),\n    (\"+\", 0xD3A2646C, \"^\", \"<<\", 9),\n    (\"+\", 0xFD7046C5, \"+\", \"<<\", 3),\n    (\"^\", 0xB55A4F09, \"^\", \">>\", 16),\n]\n```\n\nSimilar to [Bob Jenkins’ hash](https://en.wikipedia.org/wiki/Jenkins_hash_function). Each stage: `a = (a op1 val1) op2 (a op3 val3)`\n\n## The Memory Model[#](#the-memory-model)\n\nTwo memory spaces:\n\n**Main Memory**(`self.mem`\n\n): Problem input/output**Scratch Space**(`core.scratch`\n\n): 1536 words - think of it as registers + constant memory + manually managed cache\n\nFrom the [constants](https://github.com/anthropics/original_performance_takehome/blob/main/problem.py#L57-L60):\n\n```\nVLEN = 8          # Vector length: 8 elements\nN_CORES = 1       # Single core (older versions had multiple)\nSCRATCH_SIZE = 1536  # 1536 words of scratch space\n```\n\nEvery ALU operation reads and writes scratch addresses. It’s like programming a [GPU with shared memory](https://developer.nvidia.com/blog/using-shared-memory-cuda-cc/), but more explicit.\n\n## The ALU Operations[#](#the-alu-operations)\n\n``` python\ndef alu(self, core, op, dest, a1, a2):\n    a1 = core.scratch[a1]\n    a2 = core.scratch[a2]\n    match op:\n        case \"+\":  res = a1 + a2\n        case \"-\":  res = a1 - a2\n        case \"*\":  res = a1 * a2\n        case \"//\": res = a1 // a2\n        case \"^\":  res = a1 ^ a2       # XOR\n        case \"&\":  res = a1 & a2       # AND\n        case \"|\":  res = a1 | a2       # OR\n        case \"<<\": res = a1 << a2      # Left shift\n        case \">>\": res = a1 >> a2      # Right shift\n        case \"%\":  res = a1 % a2       # Modulo\n        case \"<\":  res = int(a1 < a2)  # Comparison\n        case \"==\": res = int(a1 == a2)\n    res = res % (2**32)  # 32-bit unsigned wrap\n    self.scratch_write[dest] = res\n```\n\n[Vector ALU ops](https://github.com/anthropics/original_performance_takehome/blob/main/problem.py#L254-L267) - the SIMD part:\n\n``` python\ndef valu(self, core, *slot):\n    match slot:\n        case (\"vbroadcast\", dest, src):\n            # Broadcast scalar to all 8 vector lanes\n            for i in range(VLEN):\n                self.scratch_write[dest + i] = core.scratch[src]\n        case (\"multiply_add\", dest, a, b, c):\n            # Fused multiply-add: dest = a * b + c\n            for i in range(VLEN):\n                mul = (core.scratch[a + i] * core.scratch[b + i]) % (2**32)\n                self.scratch_write[dest + i] = (mul + core.scratch[c + i]) % (2**32)\n        case (op, dest, a1, a2):\n            # Any scalar op applied element-wise\n            for i in range(VLEN):\n                self.alu(core, op, dest + i, a1 + i, a2 + i)\n```\n\n## Memory Operations[#](#memory-operations)\n\n[Load/store](https://github.com/anthropics/original_performance_takehome/blob/main/problem.py#L269-L298) - only 2 of each per cycle:\n\n``` python\ndef load(self, core, *slot):\n    match slot:\n        case (\"load\", dest, addr):\n            self.scratch_write[dest] = self.mem[core.scratch[addr]]\n        case (\"vload\", dest, addr):  # 8 consecutive elements\n            addr = core.scratch[addr]\n            for vi in range(VLEN):\n                self.scratch_write[dest + vi] = self.mem[addr + vi]\n        case (\"const\", dest, val):\n            self.scratch_write[dest] = (val) % (2**32)\n```\n\nKey bottleneck: **only 2 loads per cycle**. Vector loads (`vload`\n\n) help - 8 elements in one slot!\n\n## Flow Control[#](#flow-control)\n\n[Flow ops](https://github.com/anthropics/original_performance_takehome/blob/main/problem.py#L300-L335) - crucial for [branchless programming](https://en.algorithmica.org/hpc/pipelining/branchless/):\n\n``` python\ndef flow(self, core, *slot):\n    match slot:\n        case (\"select\", dest, cond, a, b):\n            # Branchless: dest = cond ? a : b\n            self.scratch_write[dest] = (\n                core.scratch[a] if core.scratch[cond] != 0 else core.scratch[b]\n            )\n        case (\"vselect\", dest, cond, a, b):\n            # Vector version\n            for vi in range(VLEN):\n                self.scratch_write[dest + vi] = (\n                    core.scratch[a + vi]\n                    if core.scratch[cond + vi] != 0\n                    else core.scratch[b + vi]\n                )\n        case (\"cond_jump\", cond, addr):\n            if core.scratch[cond] != 0:\n                core.pc = addr\n        case (\"jump\", addr):\n            core.pc = addr\n```\n\n## Why the Baseline Is So Slow[#](#why-the-baseline-is-so-slow)\n\nThe [baseline kernel](https://github.com/anthropics/original_performance_takehome/blob/main/perf_takehome.py#L88-L175) deliberately uses **one operation per cycle**:\n\n``` python\ndef build(self, slots: list[tuple[Engine, tuple]], vliw: bool = False):\n    # Simple slot packing that just uses one slot per instruction bundle\n    instrs = []\n    for engine, slot in slots:\n        instrs.append({engine: [slot]})  # One op per bundle!\n    return instrs\n```\n\nSo instead of:\n\n```\n{\"alu\": [op1, op2, op3], \"load\": [load1]}  # 1 cycle\n```\n\nYou get:\n\n```\n{\"alu\": [op1]}    # Cycle 1\n{\"alu\": [op2]}    # Cycle 2\n{\"alu\": [op3]}    # Cycle 3\n{\"load\": [load1]} # Cycle 4\n```\n\n4 cycles instead of 1. The 12 ALU slots sit empty.\n\n## Debugging Tools[#](#debugging-tools)\n\n### Perfetto Trace Viewer[#](#perfetto-trace-viewer)\n\nThe simulator outputs [Chrome Trace Event Format](https://docs.google.com/document/d/1CvAClvFfyA5R-PhYUmn5OOQtYMH4h6I0nSsKchNAySU/preview) traces viewable in [Perfetto](https://ui.perfetto.dev/):\n\n```\npython perf_takehome.py Tests.test_kernel_trace\npython watch_trace.py  # Opens browser with live-reloading trace\n```\n\nThe [ watch_trace.py](https://github.com/anthropics/original_performance_takehome/blob/main/watch_trace.py) server auto-reloads traces when they change - great for iterating.\n\n### Debug Instructions[#](#debug-instructions)\n\n[Debug ops](https://github.com/anthropics/original_performance_takehome/blob/main/problem.py#L365-L382) verify intermediate values without counting cycles:\n\n```\nbody.append((\"debug\", (\"compare\", tmp_val, (round, i, \"hashed_val\"))))\n```\n\n## Optimization Strategies[#](#optimization-strategies)\n\nThe key techniques:\n\n### 1. VLIW Packing[#](#1-vliw-packing)\n\nPack independent operations into the same cycle:\n\n```\n{\"alu\": [op1, op2, op3], \"load\": [load1, load2]}  # 5 ops, 1 cycle\n```\n\n### 2. SIMD Vectorization[#](#2-simd-vectorization)\n\nProcess 8 batch items at once with `valu`\n\nand `vload`\n\n/`vstore`\n\n.\n\n### 3. [Software Pipelining](https://en.wikipedia.org/wiki/Software_pipelining)[#](#3-software-pipelining)\n\nOverlap computation of different iterations to keep all engines busy.\n\n### 4. Branchless with `select`\n\n[#](#4-branchless-with-select)\n\n```\n# Instead of conditional jumps:\noffset = select(val % 2 == 0, 1, 2)\nidx = 2*idx + offset\n```\n\n### The Hard Part: Data Dependencies[#](#the-hard-part-data-dependencies)\n\nYou can’t compute the next tree index until you’ve hashed the current value. That’s a serial [dependency chain](https://en.wikipedia.org/wiki/Instruction-level_parallelism#Data_dependency). The trick is finding parallelism *across* different batch items.\n\n## Further Reading[#](#further-reading)\n\n[VLIW Architecture - Wikipedia](https://en.wikipedia.org/wiki/Very_long_instruction_word)[SIMD Programming - Intel Intrinsics Guide](https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html)[Software Pipelining - Wikipedia](https://en.wikipedia.org/wiki/Software_pipelining)[Perfetto UI](https://ui.perfetto.dev/)[Chrome Trace Event Format](https://docs.google.com/document/d/1CvAClvFfyA5R-PhYUmn5OOQtYMH4h6I0nSsKchNAySU/preview)[Computer Architecture: A Quantitative Approach](https://www.amazon.com/Computer-Architecture-Quantitative-Approach-Kaufmann/dp/0128119055)[Branchless Programming](https://en.algorithmica.org/hpc/pipelining/branchless/)", "url": "https://wpnews.pro/news/deep-dive-anthropic-s-performance-take-home-the-one-claude-beat-humans-at", "canonical_source": "https://trirpi.github.io/posts/anthropic-performance-takehome/", "published_at": "2026-08-04 05:25:33+00:00", "updated_at": "2026-08-04 05:52:44.643693+00:00", "lang": "en", "topics": ["artificial-intelligence", "ai-research", "ai-products"], "entities": ["Anthropic", "Claude Opus 4.5", "Tristan", "VLIW", "SIMD"], "alternates": {"html": "https://wpnews.pro/news/deep-dive-anthropic-s-performance-take-home-the-one-claude-beat-humans-at", "markdown": "https://wpnews.pro/news/deep-dive-anthropic-s-performance-take-home-the-one-claude-beat-humans-at.md", "text": "https://wpnews.pro/news/deep-dive-anthropic-s-performance-take-home-the-one-claude-beat-humans-at.txt", "jsonld": "https://wpnews.pro/news/deep-dive-anthropic-s-performance-take-home-the-one-claude-beat-humans-at.jsonld"}}