17

Chapter 17 — Scalar vs. std::experimental::simd, AoS vs. SoA

SIMD parallelizes across data inside one thread, and data layout decides whether vectorization is even available before a compiler flag or vector type enters the picture.

Demo 17Source on GitHub ↗

The full source for this example lives in examples/concurrency/17-simd/ — clone the repo, cd in, and ./demo.sh.

Chapter reference: Doc 17 — SIMD and Data Parallelism

What it shows

One fixed particle dataset gets the identical pos += vel * dt recurrence applied three ways: array-of-structs with a scalar loop (strided, defeats vectorization outright), struct-of-arrays with a scalar loop (contiguous, still no explicit vector type), and struct-of-arrays with explicit std::experimental::simd — libstdc++’s production-usable portable vector type today, deliberately not the unshipped C++26 std::simd. Built without -march=native, the three variants perform the exact same sequence of multiply-then-add operations batched differently, so their final positions are checked for a bit-identical hash rather than a floating-point tolerance — any mismatch is a hard failure regardless of layout or vectorization. soa_simd beating soa_scalar is reported as a soft signal, since the margin depends on the build’s actual vector width.

Running it

cd examples/concurrency/17-simd
./demo.sh            # build + run simd_particles + verify.lua
./demo.sh --clean    # remove the image