Benchmarks
Three workloads, four implementations each
All measurements are wall-clock time. CPU runs use a single Intel Core i7 thread and an OpenMP build on 8 cores. GPU runs use an NVIDIA RTX 3060. Both axes are logarithmic — slopes tell you scaling behavior, vertical gaps tell you raw speedup.
Mandelbrot set
Per-pixel escape-time iteration. Every pixel is independent, with no shared state and no reduction — the textbook case where a GPU should crush a CPU.
Dot product
Multiply two long vectors element-wise and sum the results. Trivially parallel arithmetic — but the naive GPU implementation is bottlenecked by atomicAdd contention and PCIe overhead.
Heat equation (2D Jacobi)
Each cell averages its four neighbors, repeated over many time steps. High arithmetic intensity per byte moved — the kind of structured workload GPUs are designed for.
How we measured
- Warm-up: Each kernel runs once before timing to amortize JIT compilation, GPU context init, and page faults.
- Repetitions: 10 runs per data point. We report the median.
- Transfer cost: GPU timings include host↔device memcpy. This is the honest number for a one-shot computation.
- Compiler:
g++ -O3 -fopenmpfor CPU,nvcc -O3 -arch=sm_86for GPU.