Files
Brian Neumann-Fopiano 402bcb04fe dd
2026-07-10 04:05:24 -04:00

4.3 KiB

Iris SIMD Kernel Benchmark

Standalone, portable microbenchmark that measures whether Iris's SIMD (Java Vector API) kernels actually beat their scalar equivalents on the CPU it runs on. The Volmit dev/test machines are Apple Silicon, where the wide-SIMD path (4+ double lanes) does not exist. Copy the built artifact to a Windows/x86 box (AVX2 = 4 lanes, AVX-512 = 8 lanes) and run it to get real numbers for that CPU.

The six kernel classes are copied verbatim (logic byte-for-byte) from Iris/core/.../util/simd/. This tool is intentionally a duplicate so it builds and runs on its own with no Gradle, no VolmLib, and no Iris on the classpath.

Requirements

  • JDK 25 (the tool is compiled with --release 25).
  • The JDK must ship the jdk.incubator.vector incubator module (Temurin, Oracle, and all standard OpenJDK builds do).

How to run

Windows:

run.bat

macOS / Linux:

./run.sh

The run scripts compile the sources and create the ignored simd-bench.jar locally when it is missing. Use build.bat or ./build.sh to rebuild it explicitly.

Or invoke directly (the --add-modules flag is required because the Vector API is still an incubator module):

java --add-modules jdk.incubator.vector -jar simd-bench.jar

Mode flag

By default it runs both (scalar and vector head-to-head in one run). You can also do a two-run A/B:

run.bat --mode scalar
run.bat --mode vector
run.bat --mode both      (default)

--mode=scalar syntax works too. The correctness cross-check only runs in both mode (it needs both implementations).

How to read the output

  • Header prints the JVM, os.arch, CPU count, and the preferred vector width. DoubleVector pref: N lanes is the SIMD width for double on this CPU (2 on 128-bit NEON, 4 on AVX2, 8 on AVX-512).
  • noise SIMD gate (aligned && doubleLanes>=4) mirrors the real profitability gate in Iris's VectorNoiseKernels2D. It reports ENABLED on 4+ lane CPUs and DISABLED on 2-lane NEON. This tool ignores the gate and force-measures the raw vector kernel anyway, so you see the real number even where Iris would gate SIMD off.
  • Correctness cross-check runs each kernel once with both impls on identical input and confirms they agree (roundToInt/noise are bit-exact; sum differs only by floating-point reduction order, checked with a relative tolerance). If anything says MISMATCH, do not trust the timing numbers below it.
  • speedup = scalar ns/op / vector ns/op. > 1.0 means SIMD is faster on this CPU; < 1.0 means SIMD is slower. Verdict column: SIMD FASTER / SIMD SLOWER / NEUTRAL (within ~5%).
  • ns/op for the array kernels is one full-array invocation (256 or 1024 doubles). For noise it is one 256-element simplexFractalFBM call.
  • The trailing Checksum lines exist only to keep the JIT from deleting the measured work. Ignore their values.

Harness notes (why the numbers are trustworthy)

  • Each op is warmed up 50,000 times before timing so the JIT has compiled the hot path.
  • Every kernel output is folded into a running checksum (printed at the end) so no measured call is dead-code-eliminated.
  • One input element is perturbed per iteration (a cheap store keyed off the loop counter) so the JIT cannot hoist a "constant" result out of the timing loop. This perturbation is identical for scalar and vector, so the comparison stays fair; it adds a tiny fixed cost to both sides that very slightly compresses the ratio on the cheapest kernels.
  • Each (kernel, impl) is timed over 10 rounds; the minimum ns/op is reported (least-noisy statistic for a microbenchmark).
  • Scalar and vector see the same seeded input for a given kernel.

Caveats

  • This is an isolated-kernel vacuum microbench, not full worldgen. It says whether the raw kernel is faster on this CPU, not what end-to-end generation throughput will be (cache behavior, allocation, and surrounding code differ in the real engine).
  • Effort 1 array kernels (roundToInt / sum / max) run unconditionally in real Iris. Effort 2 noise (simplexFractalFBM) is currently unwired in Iris and gated to 4+ double lanes; this tool force-measures it regardless.
  • Vector-API auto-vectorization and cost depend heavily on the JDK version and CPU. Run on the actual target hardware; do not extrapolate across machines.