One kernel, four flavors — and a reality check on size
Once vector add works, swapping the operator gets you sub, mul, and div for free. The launch geometry, memory layout, and verification stay identical — only the ALU op changes. But the cost isn't always identical:
| Op | Body change | Notes |
|---|---|---|
| Add | C[i] = A[i] + B[i] | Baseline. |
| Sub | + → - | Same throughput as add — single FP unit. |
| Mul | + → * | Uses FMA pipelines, same throughput. |
| Div | + → / | 5–10× slower due to non-pipelined reciprocal. Guard against B[i] == 0 to avoid NaN/inf. |
VRAM Capacity Zones — what happens when you ask for too much
| Zone | What happens | Escape hatch |
|---|---|---|
| 🟢 Green: fits in VRAM | Full-speed, data resident on the GPU | No action needed |
| 🟡 Yellow: UVM paging | 10–50× slowdown as Unified Memory migrates pages | Process in chunks |
| 🔴 Red: hard alloc fail | cudaMalloc returns cudaErrorMemoryAllocation | Slice-and-stream loop |
| 🟣 Crimson: grid limit | gridDim.x exceeds 2³¹⁻¹ | Outer host loop, base-index arg |
Apple Silicon shifts the zones: there's no separate VRAM, so 'Green' extends to the entire unified pool minus what the OS and other apps are holding. The Yellow zone (paging to swap) still exists but kicks in much later.