mirror of
https://github.com/VolmitSoftware/Iris.git
synced 2026-07-17 12:23:48 +00:00
105 lines
4.3 KiB
Markdown
105 lines
4.3 KiB
Markdown
# 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.
|