Evolutionary Kernel Generation Documentation
This document explains the evolutionary kernel generation system for CAKE2, accessible through the cake_evo Claude Code agent.
Table of Contents
- Quick Start
- How to Use cake_evo
- How Inspirations and Diversity Work
- Subagent Execution
- Result Evaluation
- Troubleshooting
Quick Start
Prerequisites
- CANN 8.3+ and NPU hardware required
- Local CANN environment for compilation
Using cake_evo Agent
# 1. Create working directory
mkdir genop
cp -r .claude genop/
cd genop
# 2. Start Claude Code
opencode
# 3. Select cake_evo agent (press Tab)
# 4. Describe your operator
Example interaction:
User: Generate a FastGELU activation function operator with evolution.
Formula: y = x / (1 + exp(-1.702 * |x|)) * exp(0.851 * (x - |x|))
Agent: I'll set up evolutionary kernel generation for FastGELU.
Configuration (press Enter for defaults):
- Max rounds [2]:
- Parallel candidates [3]:
- Target speedup [1.5]:
Starting evolution...
Output Structure
output/FastGELU_evo_20260213_143022/
├── shared/ # Generated once (steps 1-4)
│ ├── FastGELU_op_desc.json
│ ├── FastGELU_reference.py
│ ├── FastGELU_functional.py
│ └── FastGELUCustom/ # CMake project template
├── round_1/
│ ├── parallel_0/ # Variant 0 (steps 5-9)
│ │ ├── FastGELU_op_desc.json # (copied from shared)
│ │ ├── FastGELU_reference.py # (copied from shared)
│ │ ├── FastGELU_dsl.py # (unique per variant)
│ │ ├── FastGELUCustom/ # (kernel code modified)
│ │ └── evaluation_results.json
│ ├── parallel_1/ # Variant 1
│ └── parallel_2/ # Variant 2
├── round_2/ # Next round with inspirations
How to Use cake_evo
Agent Workflow
The cake_evo agent orchestrates evolutionary optimization through these steps:
1. Configuration
Agent prompts for:
- Operator name: Short identifier (e.g., "FastGELU")
- Operator description: Natural language or formal spec
- Max rounds: Number of evolution cycles (default: 2)
- Parallel candidates: Variants per round (default: 3)
- Target speedup: Goal speedup vs PyTorch (default: 1.5x)
2. Environment Detection
Agent automatically detects local CANN environment:
- Requires
npu-smiand CANN 8.3+ installation - Uses local NPU compilation
3. Shared Pre-Generation (run once)
Agent runs steps 1-4 once and saves to a shared/ directory:
- Generates operator description JSON
- Creates PyTorch reference
- Converts to functional API
- Generates Ascend call code and CMake project
These outputs are identical across all variants and rounds, so they are generated once and copied to each parallel directory.
4. Round 1: Parallel Kernel Generation (from step 5)
Agent copies shared files to each round_1/parallel_{p}/ directory, then spawns N parallel subagents (default: 3), each starting from DSL generation:
- Creates DSL baseline
- Applies DSL lowering passes
- Reviews and fixes AscendC code
- Compiles and evaluates locally
Meta-Prompt Cycling: Each subagent receives a different meta-prompt for diversity:
- Subagent 0:
meta_prompts/general.txt - Subagent 1:
meta_prompts/elementwise.txt - Subagent 2:
meta_prompts/general.txt(cycles)
5. Classification
After Round 1, agent classifies implementations into tiers:
| Tier | Percentage | Selection Strategy |
|---|---|---|
| Good | Top 30% | Exploitation (best performance) |
| Medium | Middle 40% | Balanced exploration |
| Poor | Bottom 30% | Diverse exploration |
6. Inspiration Selection
Agent samples from all tiers for next round:
- 1 from Good tier: Best performer (exploitation)
- 1 from Medium tier: Alternative approach (exploration)
7. Round 2+: Evolution
Agent copies shared files again, then spawns new subagents with inspirations:
- Same operator description
- Plus: Code from selected implementations
- Plus: Performance metrics and insights
- Different meta-prompts for diversity
8. Termination
Evolution stops when:
- Target speedup achieved
- Max rounds reached
- No successful implementations
How Inspirations and Diversity Work
The Core Mechanism
Round 1: Pure Exploration
Shared artifacts (op_desc, reference, functional, CMake project) are already in each parallel directory. Each subagent receives:
Pre-generated files in output directory:
{op_name}_op_desc.json, {op_name}_reference.py,
{op_name}_functional.py, {op_name}Custom/
Meta-Prompt: general.txt (or elementwise.txt, etc.)
- Memory access optimization
- Parallelization strategies
- Vectorization opportunities
Execute skills: dsl_baseline → dsl_lowering → review → eval
Result: 3 implementations with different approaches
Round 2: Informed Exploration
All subagents receive inspirations plus different meta-prompts:
Operator Description:
[Same as Round 1]
=== INSPIRATIONS ===
Inspiration 1: round_1_parallel_0 (1.8x speedup)
DSL Code: [double buffering implementation]
AscendC Code: [vectorized operations]
Key optimizations:
- Uses double buffering for memory
- Vectorizes inner loops
Inspiration 2: round_1_parallel_1 (1.3x speedup)
DSL Code: [row-wise processing]
AscendC Code: [simple memory access]
Key optimizations:
- Row-wise tiling
- Simplified logic
=== END INSPIRATIONS ===
Meta-Prompt: general.txt (different for each subagent)
[Optimization hints]
Instruction: Learn from inspirations and explore new approaches
Execute skills: op_desc → pytorch → dsl → ascendc → eval
How Diversity Emerges
Same inspirations + Different meta-prompts = Different approaches
- Subagent 0 (general.txt): Combines double buffering with cache optimization
- Subagent 1 (elementwise.txt): Focuses on wider SIMD operations
- Subagent 2 (reduction.txt): Explores different reduction patterns (if applicable)
Tiered Sampling Benefits
- Exploitation: Good tier ensures we keep improving
- Exploration: Medium/Poor tiers prevent local optima
- Diversity: Different approaches may work for different operators
- Robustness: System doesn't get stuck on single strategy
Example Evolution
Round 1 Results
parallel_0: 1.3x (basic tiling) → Poor tier
parallel_1: 1.8x (double buffering) → Good tier ✓ Selected
parallel_2: 1.5x (row-wise processing) → Medium tier ✓ Selected
Round 2 Results (with inspirations)
parallel_0: 2.1x (combined best ideas) → Good tier ✓ Best overall!
parallel_1: 1.9x (improved vectorization) → Good tier
parallel_2: 1.7x (different memory layout) → Medium tier
Improvement: 1.8x → 2.1x (17% gain from evolution)
Subagent Execution
Parallel Execution Model
The cake_evo agent first runs shared steps 1-4, then uses Claude Code's Task tool to spawn parallel subagents from step 5:
Agent runs steps 1-4 once → shared/ directory
↓
Agent copies shared files to each parallel directory
↓
Agent spawns 3 subagents simultaneously (from step 5):
├─ Subagent 0 (background) → output/round_1/parallel_0/
├─ Subagent 1 (background) → output/round_1/parallel_1/
└─ Subagent 2 (background) → output/round_1/parallel_2/
Agent waits for all to complete, then evaluates results
Subagent Prompt Structure
Each subagent receives:
- Pre-generated files: op_desc, reference, functional, CMake project (already in output directory)
- Inspirations (Round 2+): Previous successful implementations
- Meta-prompt: Optimization hints (rotates)
- Output directory: Isolated workspace
- Skill sequence: Steps 5-9 to execute
- Local compilation mode: Uses CANN environment
Skill Execution
Shared Steps (run once by cake_evo agent)
op_desc_generation- Generate operator JSONreference_generation- Create PyTorch referencefunctional_conversion- Convert to functional APIascend_call_generation- Generate host code
Per-Variant Steps (run by each parallel subagent)
Local Mode
dsl_baseline_generation- Generate DSL baselinedsl_lowering- Apply lowering passesascendc_code_review- Check coding standards, review and fix codeascendc_evaluation- Compile and evaluate locally
Result Collection
After all subagents complete, agent:
- Reads
evaluation_results.jsonfrom each directory - Extracts:
speedup,compilation_success,precision_passed - Reads generated code: DSL and AscendC
- Classifies into tiers
- Selects inspirations for next round
Result Evaluation
Evaluation Metrics
Each implementation is scored on:
1. Compilation Success
- ✅ Success: Code compiles without errors
- ❌ Failure: Compilation errors → Score = 0
2. Correctness
- ✅ Pass: Output matches PyTorch reference (99%+ match)
- ❌ Fail: Output mismatch → Score reduced
3. Performance
- Speedup =
pytorch_time / ascendc_time - Higher is better (>1.0x means faster than PyTorch)
Scoring System
| Condition | Score | Interpretation |
|---|---|---|
| Compilation failed | 0 | Not usable |
| Runtime error | 100 | Compiles but crashes |
| Precision failed | 200 | Runs but wrong output |
| All tests passed | 300 | Correct implementation |
| Speedup ≥ 2.0x | 350 | Optimal performance |
Typical Speedup Ranges
| Operator Type | Expected Speedup |
|---|---|
| Element-wise | 2-5x |
| Reductions | 1.5-3x |
| Fused ops | 3-10x |
| Matrix ops | 1.2-2x |
Classification Algorithm
def classify_implementations(implementations):
# Filter valid (speedup > 0, compiled successfully)
valid = [impl for impl in implementations if impl.speedup > 0]
# Sort by speedup (descending)
valid.sort(key=lambda x: x.speedup, reverse=True)
# Calculate tier sizes
total = len(valid)
good_count = max(1, int(total * 0.3))
medium_count = max(1, int(total * 0.4))
return {
'good': valid[:good_count],
'medium': valid[good_count:good_count + medium_count],
'poor': valid[good_count + medium_count:]
}
Troubleshooting
Common Issues
All Subagents Failed
Symptom: No successful implementations in round
Possible Causes:
- Operator description too vague
- CANN environment issues
- NPU memory issues
Solutions:
- Check
output/round_X/parallel_Y/execution.logfor errors - Verify operator description is detailed
- Check CANN installation
- Verify NPU availability with
npu-smi
Low Speedup
Symptom: Best implementation slower than PyTorch
Possible Causes:
- Operator is memory-bound (hard to optimize)
- Small tensor sizes (overhead dominates)
- PyTorch already well-optimized
Solutions:
- Increase
parallel_numfor more exploration - Increase
max_roundsfor more iterations - Try different meta-prompts manually
- Consider operator characteristics
Compilation Failures
Symptom: AscendC compilation errors
Solutions:
# Check CANN installation
ascend-doctor
# Verify NPU devices
npu-smi info
# Check environment variables
echo $ASCEND_TOOLKIT_HOME
echo $LD_LIBRARY_PATH
Subagent Timeout
Symptom: Subagent takes >30 minutes
Causes:
- Complex operator requiring many compilation iterations
- NPU under heavy load
Solutions:
- Be patient (complex ops take time)
- Check NPU utilization with
npu-smi - Reduce
parallel_numto decrease load
Best Practices
- Start small: Use 2 rounds, 3 parallel candidates initially
- Monitor progress: Check
PROGRESS.md(updated by task-progress skill) for overall status - Inspect failures: Read execution logs for failed subagents
- Set realistic targets: 1.5-2x speedup is typical, not 10x
- Detailed descriptions: More detail = better results
Debugging Commands
# View evolution progress
cat output/*_evo_*/PROGRESS.md
# Check specific subagent output
cat output/FastGELU_evo_*/round_1/parallel_0/execution.log
# View evaluation results
cat output/FastGELU_evo_*/round_1/parallel_0/evaluation_results.json
# Check all speedups in a round
grep "speedup" output/FastGELU_evo_*/round_1/*/evaluation_results.json
# Monitor NPU usage
npu-smi info -l
Summary
Key Concepts
- Evolutionary optimization: Multiple rounds of parallel generation
- Tiered sampling: Selection from good/medium/poor tiers for diversity
- Inspirations: Learning from previous successful implementations
- Meta-prompts: Different optimization hints for diverse approaches
- Agent-based: Interactive workflow through Claude Code
Workflow Recap
1. User describes operator to cake_evo agent
2. Agent detects local CANN environment
3. Agent runs shared steps 1-4 once (op_desc → reference → functional → ascend_call)
4. Round 1: Copy shared files, spawn N parallel subagents from step 5
5. Agent classifies results into tiers
6. Agent selects inspirations from all tiers
7. Round 2+: Copy shared files, generate variants with inspirations
8. Repeat until target achieved
9. Return top implementations
When to Use Evolution
- Complex operators: Multiple optimization strategies possible
- Performance-critical: Need best-in-class performance
- Uncertain approach: Not sure which optimization works best
- Learning: Want to explore different implementations
When NOT to Use Evolution
- Simple operators: Single obvious implementation
- Time-constrained: Need results quickly (use regular
cakeagent) - Good-enough performance: 1.2x speedup sufficient
For more details, see:
evolution/README.md- Module documentation.claude/agents/cake_evo.md- Agent definitionCLAUDE.md- Project overview