From 8b0635434e848c03be68def6b09959786b2dcb5c Mon Sep 17 00:00:00 2001 From: asmhatre Date: Sun, 26 Jul 2026 11:47:20 +0000 Subject: [PATCH] Add JMH benchmark for the masked filter --- .../com/ankurm/vectorapi/MaskedBench.java | 47 +++++++++++++++++++ 1 file changed, 47 insertions(+) create mode 100644 jmh/src/main/java/com/ankurm/vectorapi/MaskedBench.java diff --git a/jmh/src/main/java/com/ankurm/vectorapi/MaskedBench.java b/jmh/src/main/java/com/ankurm/vectorapi/MaskedBench.java new file mode 100644 index 0000000..77ed0f9 --- /dev/null +++ b/jmh/src/main/java/com/ankurm/vectorapi/MaskedBench.java @@ -0,0 +1,47 @@ +package com.ankurm.vectorapi; + +import jdk.incubator.vector.*; +import org.openjdk.jmh.annotations.*; +import java.util.Random; +import java.util.concurrent.TimeUnit; + +/** JMH version of the masked filter-and-sum: the headline speedup case. */ +@BenchmarkMode(Mode.AverageTime) +@OutputTimeUnit(TimeUnit.NANOSECONDS) +@State(Scope.Thread) +@Warmup(iterations = 5, time = 1) +@Measurement(iterations = 5, time = 1) +@Fork(1) +public class MaskedBench { + static final VectorSpecies SP = FloatVector.SPECIES_PREFERRED; + static final float THRESH = 0.5f; + float[] a; + + @Setup + public void setup() { + a = new float[8192]; + Random r = new Random(7); + for (int i = 0; i < a.length; i++) a[i] = r.nextFloat(); + } + + // Both methods return their result, so JMH consumes it and nothing is dead. + @Benchmark + public float scalarBranch() { + float sum = 0; + for (int i = 0; i < a.length; i++) if (a[i] > THRESH) sum += a[i]; + return sum; + } + + @Benchmark + public float vectorMasked() { + FloatVector acc = FloatVector.zero(SP); + int i = 0, bound = SP.loopBound(a.length); + for (; i < bound; i += SP.length()) { + var v = FloatVector.fromArray(SP, a, i); + acc = acc.add(v, v.compare(VectorOperators.GT, THRESH)); + } + float sum = acc.reduceLanes(VectorOperators.ADD); + for (; i < a.length; i++) if (a[i] > THRESH) sum += a[i]; + return sum; + } +}