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.

Embarrassingly parallel

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.

Reduction · memory-bound

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.

Stencil · iterative

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.

Methodology

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 -fopenmp for CPU, nvcc -O3 -arch=sm_86 for GPU.