Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
package jmh;
import jdk.incubator.vector.ByteVector;
import jdk.incubator.vector.Vector;
import jdk.incubator.vector.VectorMask;
import jdk.incubator.vector.VectorOperators;
import jdk.incubator.vector.VectorShuffle;
import jdk.incubator.vector.VectorSpecies;
import org.openjdk.jmh.annotations.Benchmark;
import org.openjdk.jmh.annotations.BenchmarkMode;
import org.openjdk.jmh.annotations.Fork;
import org.openjdk.jmh.annotations.Measurement;
import org.openjdk.jmh.annotations.Mode;
import org.openjdk.jmh.annotations.OutputTimeUnit;
import org.openjdk.jmh.annotations.Param;
import org.openjdk.jmh.annotations.Setup;
import org.openjdk.jmh.annotations.State;
import org.openjdk.jmh.annotations.Warmup;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.util.Random;
import java.util.concurrent.TimeUnit;
@BenchmarkMode(Mode.AverageTime)
@Warmup(iterations = 5, time = 500, timeUnit = TimeUnit.MILLISECONDS)
@Measurement(iterations = 10, time = 500, timeUnit = TimeUnit.MILLISECONDS)
@State(org.openjdk.jmh.annotations.Scope.Thread)
@OutputTimeUnit(TimeUnit.NANOSECONDS)
@Fork(value = 1, jvmArgsAppend = {
"--add-modules=jdk.incubator.foreign,jdk.incubator.vector"})
public class BufferByteToShort {
private static final VectorSpecies<Byte> SPECIES = VectorSpecies.ofLargestShape(byte.class);
@Param("1024")
private int size;
ByteBuffer src, dst;
static final VectorShuffle<Byte> EXPANDING_SHUFFLE_LO;
static final VectorShuffle<Byte> EXPANDING_SHUFFLE_HI;
static final VectorMask<Byte> EXPANDING_MASK;
static {
EXPANDING_SHUFFLE_LO = SPECIES.shuffleFromArray(expandShuffle(0), 0);
EXPANDING_SHUFFLE_HI = SPECIES.shuffleFromArray(expandShuffle(SPECIES.length() / 2), 0);
EXPANDING_MASK = SPECIES.loadMask(expandMask(), 0);
}
static int[] expandShuffle(int index) {
int[] shuffle = new int[SPECIES.length()];
for (int i = 0; i < SPECIES.length(); i += 2) {
shuffle[i] = index++;
shuffle[i + 1] = -1;
}
return shuffle;
}
static boolean[] expandMask() {
boolean[] mask = new boolean[SPECIES.length()];
for (int i = 0; i < SPECIES.length(); i += 2) {
mask[i] = true;
}
return mask;
}
@Setup
public void setup() {
byte[] bytes = new byte[size];
new Random().nextBytes(bytes);
src = ByteBuffer.wrap(bytes);
dst = ByteBuffer.allocate(size * 2);
}
@Benchmark
public ByteBuffer scalarRelative() {
src.clear();
dst.clear();
while (src.hasRemaining()) {
dst.putShort((short) (src.get() << 8));
}
return dst;
}
@Benchmark
public ByteBuffer scalarAbsolute() {
for (int i = 0; i < size; i++) {
short s = (short) (src.get(i) << 8);
dst.putShort(i << 1, s);
}
return dst;
}
@Benchmark
public ByteBuffer vectorConvert() {
int length = SPECIES.length();
int loopBound = SPECIES.loopBound(size);
int si = 0;
int di = 0;
for (; si < loopBound; si += length) {
ByteVector srcVec = ByteVector.fromByteBuffer(SPECIES, src, si, ByteOrder.nativeOrder());
srcVec.convert(VectorOperators.B2S, 0)
.lanewise(VectorOperators.LSHL, 8)
.intoByteBuffer(dst, di, ByteOrder.nativeOrder());
di += length;
srcVec.convert(VectorOperators.B2S, 1)
.lanewise(VectorOperators.LSHL, 8)
.intoByteBuffer(dst, di, ByteOrder.nativeOrder());
di += length;
}
return dst;
}
@Benchmark
public ByteBuffer vectorShuffleZero() {
int length = SPECIES.length();
int loopBound = SPECIES.loopBound(size);
int si = 0;
int di = 0;
Vector<Byte> zero = SPECIES.zero();
for (; si < loopBound; si += length) {
ByteVector srcVec = ByteVector.fromByteBuffer(SPECIES, src, si, ByteOrder.nativeOrder());
srcVec.rearrange(EXPANDING_SHUFFLE_LO, zero).intoByteBuffer(dst, di, ByteOrder.nativeOrder());
di += length;
srcVec.rearrange(EXPANDING_SHUFFLE_HI, zero).intoByteBuffer(dst, di, ByteOrder.nativeOrder());
di += length;
}
return dst;
}
@Benchmark
public ByteBuffer vectorShuffleMask() {
int length = SPECIES.length();
int loopBound = SPECIES.loopBound(size);
int si = 0;
int di = 0;
for (; si < loopBound; si += length) {
ByteVector srcVec = ByteVector.fromByteBuffer(SPECIES, src, si, ByteOrder.nativeOrder());
srcVec.rearrange(EXPANDING_SHUFFLE_LO, EXPANDING_MASK).intoByteBuffer(dst, di, ByteOrder.nativeOrder());
di += length;
srcVec.rearrange(EXPANDING_SHUFFLE_HI, EXPANDING_MASK).intoByteBuffer(dst, di, ByteOrder.nativeOrder());
di += length;
}
return dst;
}
/*
# JMH version: 1.31
# VM version: JDK 18-internal, OpenJDK 64-Bit Server VM, 18-internal+0-adhoc.sandoz.panama-vector
# VM invoker: /Users/sandoz/Projects/jdk/panama-vector/build/macosx-x86_64-server-release/images/jdk/bin/java
# VM options: -XX:-TieredCompilation --add-modules=jdk.incubator.foreign,jdk.incubator.vector
Benchmark (size) Mode Cnt Score Error Units
BufferByteToShort.scalarAbsolute 1024 avgt 10 676.276 ± 2.455 ns/op
BufferByteToShort.scalarRelative 1024 avgt 10 1896.754 ± 40.293 ns/op
BufferByteToShort.vectorConvert 1024 avgt 10 108.458 ± 0.622 ns/op
BufferByteToShort.vectorShuffleMask 1024 avgt 10 154.176 ± 0.592 ns/op
BufferByteToShort.vectorShuffleZero 1024 avgt 10 1572.366 ± 8.717 ns/op
*/
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment