summaryrefslogtreecommitdiff
path: root/src/main/java/org/linaro/benchmarks/micro/intrinsics/MathIntrinsics.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/java/org/linaro/benchmarks/micro/intrinsics/MathIntrinsics.java')
-rw-r--r--src/main/java/org/linaro/benchmarks/micro/intrinsics/MathIntrinsics.java367
1 files changed, 367 insertions, 0 deletions
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;
+ }
+}