diff options
Diffstat (limited to 'src/main/java/org/linaro/benchmarks/micro/intrinsics')
3 files changed, 709 insertions, 0 deletions
diff --git a/src/main/java/org/linaro/benchmarks/micro/intrinsics/CRC32Bench.java b/src/main/java/org/linaro/benchmarks/micro/intrinsics/CRC32Bench.java new file mode 100644 index 0000000..3d8d817 --- /dev/null +++ b/src/main/java/org/linaro/benchmarks/micro/intrinsics/CRC32Bench.java @@ -0,0 +1,70 @@ +/* + * Copyright (C) 2016 Linaro Limited. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +/* + * Description: Simple loops around CRC32 intrinsics. + * Main Focus: CRC32-related intrinsics. + */ + +package org.linaro.benchmarks.micro.intrinsics; + +import java.util.Random; +import java.util.zip.CRC32; +import org.openjdk.jmh.annotations.*; +import java.util.concurrent.TimeUnit; + +@BenchmarkMode(Mode.AverageTime) +@OutputTimeUnit(TimeUnit.MICROSECONDS) +@State(Scope.Benchmark) + +public class CRC32Bench { + private byte []bytes = new byte[8192]; + private CRC32 crc32 = new CRC32(); + private static final int iterCount = 100; + private static final int loopSize = 3000; + + public CRC32Bench() { + Random rnd = new Random(0); + rnd.nextBytes(bytes); + } + + @Benchmark + public void jmhTimeUpdateInt() { + benchUpdateInt(); + } + + @Benchmark + public void jmhTimeUpdateBytes() { + benchUpdateBytes(); + } + + public void benchUpdateInt() { + int count = loopSize * 230; + crc32.reset(); + for (int i = 0; i < count; i++) { + crc32.update(i); + } + } + + public void benchUpdateBytes() { + crc32.reset(); + + for (int i = 0; i < loopSize*100; i++) { + crc32.update(bytes); + } + } +} diff --git a/src/main/java/org/linaro/benchmarks/micro/intrinsics/Intrinsics.java b/src/main/java/org/linaro/benchmarks/micro/intrinsics/Intrinsics.java new file mode 100644 index 0000000..f43d977 --- /dev/null +++ b/src/main/java/org/linaro/benchmarks/micro/intrinsics/Intrinsics.java @@ -0,0 +1,272 @@ +/* + * Copyright (c) 2015, ARM Limited. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package org.linaro.benchmarks.micro.intrinsics; + +import java.lang.System; +import java.util.EnumMap; +import java.util.Map; +import java.util.Random; +import org.openjdk.jmh.annotations.*; +import java.util.concurrent.TimeUnit; + +@BenchmarkMode(Mode.AverageTime) +@OutputTimeUnit(TimeUnit.NANOSECONDS) +@State(Scope.Benchmark) + +public class Intrinsics { + + /* Invoke each intrinsic in question the same no. of times */ + private static final int NUM_INVOKES = 128; + + /* Random pool size. + * Use a power of two to make the modulo operations below fast. */ + private static final int NUM_RANDS = 1024; + + /* Pre-allocated pool of random integers from [0, Integer.MAX_VALUE) */ + private static final int[] rand = new int[NUM_RANDS]; + + static { + // Allocate a pool of random integers to use in benchmarks that + // want to try and force branch mispredicts without the overhead + // of calling random.nextInt in times code. Same seed every time. + Random random = new Random(42L); + for (int i = 0; i < NUM_RANDS; i++) { + rand[i] = random.nextInt(Integer.MAX_VALUE); + } + } + + /** + * NumberOfLeadingZeros. + **/ + + private static int[] resultsNumberOfLeadingZerosInteger = new int[NUM_INVOKES]; + private static int[] resultsNumberOfLeadingZerosLong = new int[NUM_INVOKES]; + private static int[] resultsNumberOfLeadingZerosIntegerRandom = new int[NUM_INVOKES]; + private static int[] resultsNumberOfLeadingZerosLongRandom = new int[NUM_INVOKES]; + + @Benchmark + public void jmhTimeNumberOfLeadingZerosInteger() { + for (int i = 0; i < NUM_INVOKES; ++i) { + resultsNumberOfLeadingZerosInteger[i] = + Integer.numberOfLeadingZeros(0x80000000 >>> i); + } + } + + @Benchmark + public void jmhTimeNumberOfLeadingZerosLong() { + for (int i = 0; i < NUM_INVOKES; ++i) { + resultsNumberOfLeadingZerosLong[i] = + Long.numberOfLeadingZeros(0x8000000000000000L >>> i); + } + } + + @Benchmark + public void jmhTimeNumberOfLeadingZerosIntegerRandom() { + for (int i = 0; i < NUM_INVOKES; ++i) { + resultsNumberOfLeadingZerosIntegerRandom[i] = + Integer.numberOfLeadingZeros(rand[i % NUM_RANDS] >>> rand[i % NUM_RANDS]); + } + } + + @Benchmark + public void jmhTimeNumberOfLeadingZerosLongRandom() { + for (int i = 0; i < NUM_INVOKES; ++i) { + resultsNumberOfLeadingZerosLongRandom[i] = + Long.numberOfLeadingZeros(1 << (rand[i % NUM_RANDS] % Long.SIZE)); + } + } + + /** + * NumberOfTrailingZeros. + **/ + + private static int[] resultsNumberOfTrailingZerosInteger = new int[NUM_INVOKES]; + private static int[] resultsNumberOfTrailingZerosLong = new int[NUM_INVOKES]; + private static int[] resultsNumberOfTrailingZerosIntegerRandom = new int[NUM_INVOKES]; + private static int[] resultsNumberOfTrailingZerosLongRandom = new int[NUM_INVOKES]; + + @Benchmark + public void jmhTimeNumberOfTrailingZerosInteger() { + for (int i = 0; i < NUM_INVOKES; ++i) { + resultsNumberOfTrailingZerosInteger[i] = + Integer.numberOfTrailingZeros(0x80000000 >>> i); + } + } + + @Benchmark + public void jmhTimeNumberOfTrailingZerosLong() { + for (int i = 0; i < NUM_INVOKES; ++i) { + resultsNumberOfTrailingZerosLong[i] = + Long.numberOfTrailingZeros(0x8000000000000000L >>> i); + } + } + + @Benchmark + public void jmhTimeNumberOfTrailingZerosIntegerRandom() { + for (int i = 0; i < NUM_INVOKES; ++i) { + resultsNumberOfTrailingZerosIntegerRandom[i] = + Integer.numberOfTrailingZeros(rand[i % NUM_RANDS] >>> rand[i % NUM_RANDS]); + } + } + + @Benchmark + public void jmhTimeNumberOfTrailingZerosLongRandom() { + for (int i = 0; i < NUM_INVOKES; ++i) { + resultsNumberOfTrailingZerosLongRandom[i] = + Long.numberOfTrailingZeros(1 << (rand[i % NUM_RANDS] % Long.SIZE)); + } + } + + /** + * BitCount. + **/ + + // both Integer and Long's bitCount() return int type. + private static int[] resultsBitCountInteger = new int[NUM_INVOKES]; + private static int[] resultsBitCountLong = new int[NUM_INVOKES]; + private static int[] resultsBitCountIntegerRandom = new int[NUM_INVOKES]; + private static int[] resultsBitCountLongRandom = new int[NUM_INVOKES]; + + @Benchmark + public void jmhTimeBitCountInteger() { + for (int i = 0; i < NUM_INVOKES; ++i) { + resultsBitCountInteger[i] = Integer.bitCount(0x1234abcd); + } + } + + @Benchmark + public void jmhTimeBitCountLong() { + for (int i = 0; i < NUM_INVOKES; ++i) { + resultsBitCountLong[i] = Long.bitCount(0x1234abcd1234abcdL); + } + } + + @Benchmark + public void jmhTimeBitCountIntegerRandom() { + for (int i = 0; i < NUM_INVOKES; ++i) { + resultsBitCountIntegerRandom[i] = Integer.bitCount(rand[i % NUM_RANDS]); + } + } + + @Benchmark + public void jmhTimeBitCountLongRandom() { + for (int i = 0; i < NUM_INVOKES; ++i) { + resultsBitCountLongRandom[i] = + Long.bitCount((long)rand[i % NUM_RANDS] << 32 + rand[i % NUM_RANDS]); + } + } + + /** + * RotateRight. + **/ + + private static int[] resultsRotateRightInteger = new int[NUM_INVOKES]; + private static int[] resultsRotateRightIntegerConstant = new int[NUM_INVOKES]; + private static long[] resultsRotateRightLong = new long[NUM_INVOKES]; + private static long[] resultsRotateRightLongConstant = new long[NUM_INVOKES]; + + @Benchmark + public void jmhTimeRotateRightInteger() { + for (int i = 0; i < NUM_INVOKES; ++i) { + resultsRotateRightInteger[i] = Integer.rotateRight(0xFF0000DD, i); + } + } + + @Benchmark + public void jmhTimeRotateRightIntegerConstant() { + for (int i = 0; i < NUM_INVOKES; ++i) { + resultsRotateRightIntegerConstant[i] = Integer.rotateRight(0xFF0000DD, 16); + } + } + + @Benchmark + public void jmhTimeRotateRightLong() { + for (int i = 0; i < NUM_INVOKES; ++i) { + resultsRotateRightLong[i] = Long.rotateRight(0xBBAAAADDFF0000DDL, i); + } + } + + @Benchmark + public void jmhTimeRotateRightLongConstant() { + for (int i = 0; i < NUM_INVOKES; ++i) { + resultsRotateRightLongConstant[i] = Long.rotateRight(0xBBAAAADDFF0000DDL, 48); + } + } + + /** + * RotateLeft. + **/ + + private static int[] resultsRotateLeftInteger = new int[NUM_INVOKES]; + private static int[] resultsRotateLeftIntegerConstant = new int[NUM_INVOKES]; + private static long[] resultsRotateLeftLong = new long[NUM_INVOKES]; + private static long[] resultsRotateLeftLongConstant = new long[NUM_INVOKES]; + + @Benchmark + public void jmhTimeRotateLeftInteger() { + for (int i = 0; i < NUM_INVOKES; ++i) { + resultsRotateLeftInteger[i] = Integer.rotateLeft(0xFF0000DD, i); + } + } + + @Benchmark + public void jmhTimeRotateLeftIntegerConstant() { + for (int i = 0; i < NUM_INVOKES; ++i) { + resultsRotateLeftIntegerConstant[i] = Integer.rotateLeft(0xFF0000DD, 16); + } + } + + @Benchmark + public void jmhTimeRotateLeftLong() { + for (int i = 0; i < NUM_INVOKES; ++i) { + resultsRotateLeftLong[i] = Long.rotateLeft(0xBBAAAADDFF0000DDL, i); + } + } + + @Benchmark + public void jmhTimeRotateLeftLongConstant() { + for (int i = 0; i < NUM_INVOKES; ++i) { + resultsRotateLeftLongConstant[i] = Long.rotateLeft(0xBBAAAADDFF0000DDL, 48); + } + } + + /** + * RotateRandom. + **/ + + private static int[] resultsRotateRandomInteger = new int[NUM_INVOKES]; + private static long[] resultsRotateRandomLong = new long[NUM_INVOKES]; + + @Benchmark + public void jmhTimeRotateRandomInteger() { + for (int i = 0; i < NUM_INVOKES; ++i) { + resultsRotateRandomInteger[i] = (rand[i % NUM_RANDS] % 2 > 0) + ? Integer.rotateLeft(0xFF0000DD, rand[i % NUM_RANDS]) + : Integer.rotateRight(0xFF0000DD, rand[i % NUM_RANDS]); + } + } + + @Benchmark + public void jmhTimeRotateRandomLong() { + for (int i = 0; i < NUM_INVOKES; ++i) { + resultsRotateRandomLong[i] = (rand[i % NUM_RANDS] % 2 > 0) + ? Long.rotateLeft(0xBBAAAADDFF0000DDL, rand[i % NUM_RANDS]) + : Long.rotateRight(0xBBAAAADDFF0000DDL, rand[i % NUM_RANDS]); + } + } +} diff --git a/src/main/java/org/linaro/benchmarks/micro/intrinsics/MathIntrinsics.java b/src/main/java/org/linaro/benchmarks/micro/intrinsics/MathIntrinsics.java new file mode 100644 index 0000000..a1a86a6 --- /dev/null +++ b/src/main/java/org/linaro/benchmarks/micro/intrinsics/MathIntrinsics.java @@ -0,0 +1,367 @@ +/* + * Copyright (c) 2016, Linaro Limited. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +/* + * Description: Simple loops around math-related intrinsics: rounding, min/max, etc. + * Main Focus: Math-related intrinsics. + */ + +package org.linaro.benchmarks.micro.intrinsics; + +import java.lang.System; +import java.util.Random; +import org.openjdk.jmh.annotations.*; +import java.util.concurrent.TimeUnit; + +@BenchmarkMode(Mode.AverageTime) +@OutputTimeUnit(TimeUnit.NANOSECONDS) +@State(Scope.Benchmark) + +public class MathIntrinsics { + // The java.util.Random only generates random float/double numbers between 0 and 1. + // So we implement our own random floating point numbers here, + // based on a well known quick and dirty approach. + static final class MyRandom extends Random { + static int im = 139968; + static int ia = 3877; + static int ic = 29573; + static int seed = 0; + + public double nextDouble() { + double scale = 1000.0d / im; + seed = (seed * ia + ic) % im; + return scale * seed; + } + + public float nextFloat() { + float scale = 1000.0f / im; + seed = (seed * ia + ic) % im; + return scale * seed; + } + } + + /* Invoke each intrinsic in question the same no. of times */ + private static final int NUM_INVOKES = 64; + + /* Random pool size. + * Use a power of two to make the modulo operations below fast. */ + private static final int NUM_RANDS = 1024; + + /* Pre-allocated pool of random numbers. */ + private static final float[] rand_float = new float[NUM_RANDS]; + private static final double[] rand_double = new double[NUM_RANDS]; + + private static final float[] rand_pos_float = new float[NUM_RANDS]; + private static final double[] rand_pos_double = new double[NUM_RANDS]; + + private static final float[] rand_neg_float = new float[NUM_RANDS]; + private static final double[] rand_neg_double = new double[NUM_RANDS]; + + private static final int[] rand_int = new int[NUM_RANDS]; + private static final long[] rand_long = new long[NUM_RANDS]; + + // These are written but not read. The computation routines below store their + // result to these static variables to ensure the computation code is not + // removed by DCE. + private static float res_float; + private static double res_double; + private static int res_int; + private static long res_long; + + static { + MyRandom rand = new MyRandom(); + + for (int i = 0; i < NUM_RANDS; i++) { + rand_int[i] = rand.nextInt(); + rand_long[i] = rand.nextLong(); + + rand_pos_float[i] = rand.nextFloat(); + rand_pos_double[i] = rand.nextDouble(); + + rand_neg_float[i] = rand.nextFloat() * -1f; + rand_neg_double[i] = rand.nextDouble() * -1f; + + if (rand.nextInt() % 2 == 0) { + rand_float[i] = rand_pos_float[i]; + rand_double[i] = rand_pos_double[i]; + } else { + rand_float[i] = rand_neg_float[i]; + rand_double[i] = rand_neg_double[i]; + } + } + } + + @Benchmark + public void jmhTimeRoundPositiveFloat() { + int res = 0; + for (int i = 0; i < NUM_INVOKES; ++i) { + res += Math.round(rand_pos_float[i % NUM_RANDS]); + } + res_int = res; + } + + @Benchmark + public void jmhTimeRoundNegativeFloat() { + int res = 0; + for (int i = 0; i < NUM_INVOKES; ++i) { + res += Math.round(rand_neg_float[i % NUM_RANDS]); + } + res_int = res; + } + + @Benchmark + public void jmhTimeRoundFloat() { + int res = 0; + for (int i = 0; i < NUM_INVOKES; ++i) { + res += Math.round(rand_float[i % NUM_RANDS]); + } + res_int = res; + } + + @Benchmark + public void jmhTimeRoundPositiveDouble() { + long res = 0; + for (int i = 0; i < NUM_INVOKES; ++i) { + res += Math.round(rand_pos_double[i % NUM_RANDS]); + } + res_double = res; + } + + @Benchmark + public void jmhTimeRoundNegativeDouble() { + long res = 0; + for (int i = 0; i < NUM_INVOKES; ++i) { + res += Math.round(rand_neg_double[i % NUM_RANDS]); + } + res_long = res; + } + + @Benchmark + public void jmhTimeRoundDouble() { + long res = 0; + for (int i = 0; i < NUM_INVOKES; ++i) { + res += Math.round(rand_double[i % NUM_RANDS]); + } + res_double = res; + } + + @Benchmark + public void jmhTimeFloorPositiveFloat() { + float res = 0.0f; + for (int i = 0; i < NUM_INVOKES; ++i) { + res += Math.floor(rand_pos_float[i % NUM_RANDS]); + } + res_float = res; + } + + @Benchmark + public void jmhTimeFloorNegativeFloat() { + float res = 0.0f; + for (int i = 0; i < NUM_INVOKES; ++i) { + res += Math.floor(rand_neg_float[i % NUM_RANDS]); + } + res_float = res; + } + + @Benchmark + public void jmhTimeFloorFloat() { + float res = 0.0f; + for (int i = 0; i < NUM_INVOKES; ++i) { + res += Math.floor(rand_float[i % NUM_RANDS]); + } + res_float = res; + } + + @Benchmark + public void jmhTimeFloorPositiveDouble() { + double res = 0.0; + for (int i = 0; i < NUM_INVOKES; ++i) { + res += Math.floor(rand_pos_double[i % NUM_RANDS]); + } + res_double = res; + } + + @Benchmark + public void jmhTimeFloorNegativeDouble() { + double res = 0.0; + for (int i = 0; i < NUM_INVOKES; ++i) { + res += Math.floor(rand_neg_double[i % NUM_RANDS]); + } + res_double = res; + } + + @Benchmark + public void jmhTimeFloorDouble() { + double res = 0.0; + for (int i = 0; i < NUM_INVOKES; ++i) { + res += Math.floor(rand_double[i % NUM_RANDS]); + } + res_double = res; + } + + @Benchmark + public void jmhTimeCeilPositiveFloat() { + float res = 0.0f; + for (int i = 0; i < NUM_INVOKES; ++i) { + res += Math.ceil(rand_pos_float[i % NUM_RANDS]); + } + res_float = res; + } + + @Benchmark + public void jmhTimeCeilNegativeFloat() { + float res = 0.0f; + for (int i = 0; i < NUM_INVOKES; ++i) { + res += Math.ceil(rand_neg_float[i % NUM_RANDS]); + } + res_float = res; + } + + @Benchmark + public void jmhTimeCeilFloat() { + float res = 0.0f; + for (int i = 0; i < NUM_INVOKES; ++i) { + res += Math.ceil(rand_float[i % NUM_RANDS]); + } + res_float = res; + } + + @Benchmark + public void jmhTimeCeilPositiveDouble() { + double res = 0.0; + for (int i = 0; i < NUM_INVOKES; ++i) { + res += Math.ceil(rand_pos_double[i % NUM_RANDS]); + } + res_double = res; + } + + + @Benchmark + public void jmhTimeCeilNegativeDouble() { + double res = 0.0; + for (int i = 0; i < NUM_INVOKES; ++i) { + res += Math.ceil(rand_neg_double[i % NUM_RANDS]); + } + res_double = res; + } + + @Benchmark + public void jmhTimeCeilDouble() { + double res = 0.0; + for (int i = 0; i < NUM_INVOKES; ++i) { + res += Math.ceil(rand_double[i % NUM_RANDS]); + } + res_double = res; + } + + @Benchmark + public void jmhTimeRint() { + double res = 0.0; + for (int i = 0; i < NUM_INVOKES; ++i) { + res += Math.rint(rand_double[i % NUM_RANDS]); + } + res_double = res; + } + + @Benchmark + public void jmhTimeMinDouble() { + double res = 0.0; + for (int i = 0; i < NUM_INVOKES; ++i) { + double a = rand_double[i % NUM_RANDS]; + double b = rand_double[(i + 1) % NUM_RANDS]; + res += Math.min(a, b); + } + res_double = res; + } + + @Benchmark + public void jmhTimeMaxDouble() { + double res = 0.0; + for (int i = 0; i < NUM_INVOKES; ++i) { + double a = rand_double[i % NUM_RANDS]; + double b = rand_double[(i + 1) % NUM_RANDS]; + res += Math.max(a, b); + } + res_double = res; + } + + @Benchmark + public void jmhTimeMinFloat() { + float res = 0.0f; + for (int i = 0; i < NUM_INVOKES; ++i) { + float a = rand_float[i % NUM_RANDS]; + float b = rand_float[(i + 1) % NUM_RANDS]; + res += Math.min(a, b); + } + res_float = res; + } + + @Benchmark + public void jmhTimeMaxFloat() { + float res = 0.0f; + for (int i = 0; i < NUM_INVOKES; ++i) { + float a = rand_float[i % NUM_RANDS]; + float b = rand_float[(i + 1) % NUM_RANDS]; + res += Math.max(a, b); + } + res_float = res; + } + + @Benchmark + public void jmhTimeMinLong() { + long res = 0; + for (int i = 0; i < NUM_INVOKES; ++i) { + long a = rand_long[i % NUM_RANDS]; + long b = rand_long[(i + 1) % NUM_RANDS]; + res += Math.min(a, b); + } + res_long = res; + } + + @Benchmark + public void jmhTimeMaxLong() { + long res = 0; + for (int i = 0; i < NUM_INVOKES; ++i) { + long a = rand_long[i % NUM_RANDS]; + long b = rand_long[(i + 1) % NUM_RANDS]; + res += Math.max(a, b); + } + res_long = res; + } + + @Benchmark + public void jmhTimeMinInt() { + int res = 0; + for (int i = 0; i < NUM_INVOKES; ++i) { + int a = rand_int[i % NUM_RANDS]; + int b = rand_int[(i + 1) % NUM_RANDS]; + res += Math.min(a, b); + } + res_int = res; + } + + @Benchmark + public void jmhTimeMaxInt() { + int res = 0; + for (int i = 0; i < NUM_INVOKES; ++i) { + int a = rand_int[i % NUM_RANDS]; + int b = rand_int[(i + 1) % NUM_RANDS]; + res += Math.max(a, b); + } + res_int = res; + } +} |