hpc · advanced
SIMD & Auto-Vectorization
SIMD (Single Instruction, Multiple Data) executes one operation across a vector of elements — 8 floats per AVX instruction, 16 with AVX-512. Compilers auto-vectorize clean, countable, dependency-free loops at -O3 -march=native, emitting a packed body plus a scalar remainder. The biggest lever is data layout: Struct-of-Arrays gives the unit-stride access the vectorizer needs, while interleaved Array-of-Structs forces strided gathers that block it. Pointer aliasing and loop-carried dependencies silently defeat it too — annotate with __restrict, prefer reductions, and confirm with -fopt-info-vec / -fopt-info-vec-missed.
SIMD does one operation on many elements per instruction; -O3 -march=native auto-vectorizes simple unit-stride loops, but AoS layouts, loop-carried dependencies and pointer aliasing block it — use SoA, __restrict and reductions, and verify with -fopt-info-vec.
The code
// Scalar: the CPU adds ONE pair of floats per instructionfor (int i = 0; i < n; ++i) c[i] = a[i] + b[i];
// With -O3 the compiler AUTO-VECTORIZES this into SIMD:// one AVX instruction adds 8 floats at once (256 bits / 32).
struct P { float x, y, z;}; // AoS: x,y,z interleaved -> stridedstruct S { float *x, *y, *z;}; // SoA: each axis contiguous -> vectorizes
void add(float* __restrict c, // __restrict: 'these don't alias', const float* a, const float* b); // so it's safe to vectorizeWhat this lesson walks through
- 01Scalar baseline — one add per instruction
- 02-O3 auto-vectorizes — 8 lanes in ONE instruction
- 03Data layout decides it — SoA beats AoS
- 04Why it silently fails — aliasing
Written naively, the CPU processes one pair of floats per instruction: c[0]=a[0]+b[0], then c[1]=a[1]+b[1]… One lane at a time.
See it animated — step by step, at your own pace
Unlock the full interactive walkthrough of SIMD & Auto-Vectorization and 100+ animated C++ interview lessons.