Files
Brian Neumann-Fopiano 402bcb04fe dd
2026-07-10 04:05:24 -04:00
..
d
2026-07-08 17:55:14 -04:00
dd
2026-07-10 04:05:24 -04:00
dd
2026-07-10 04:05:24 -04:00
dd
2026-07-10 04:05:24 -04:00
dd
2026-07-10 04:05:24 -04:00
dd
2026-07-10 04:05:24 -04:00

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.