View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *      http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  package org.apache.commons.numbers.examples.jmh.core;
18  
19  import java.util.concurrent.TimeUnit;
20  import java.util.function.ToDoubleFunction;
21  
22  import org.apache.commons.rng.UniformRandomProvider;
23  import org.apache.commons.rng.simple.RandomSource;
24  import org.openjdk.jmh.annotations.Benchmark;
25  import org.openjdk.jmh.annotations.BenchmarkMode;
26  import org.openjdk.jmh.annotations.Fork;
27  import org.openjdk.jmh.annotations.Measurement;
28  import org.openjdk.jmh.annotations.Mode;
29  import org.openjdk.jmh.annotations.OutputTimeUnit;
30  import org.openjdk.jmh.annotations.Param;
31  import org.openjdk.jmh.annotations.Scope;
32  import org.openjdk.jmh.annotations.Setup;
33  import org.openjdk.jmh.annotations.State;
34  import org.openjdk.jmh.annotations.Warmup;
35  import org.openjdk.jmh.infra.Blackhole;
36  
37  /**
38   * Execute benchmarks for the algorithms in the {@link EuclideanNormAlgorithms} class.
39   */
40  @BenchmarkMode(Mode.AverageTime)
41  @OutputTimeUnit(TimeUnit.NANOSECONDS)
42  @Warmup(iterations = 5, time = 1, timeUnit = TimeUnit.SECONDS)
43  @Measurement(iterations = 5, time = 1, timeUnit = TimeUnit.SECONDS)
44  @State(Scope.Benchmark)
45  @Fork(value = 1, jvmArgs = {"-server", "-Xms512M", "-Xmx512M"})
46  public class EuclideanNormAlgorithmPerformance {
47  
48      /** String indicating double exponents with very low negative values, likely to underflow. */
49      private static final String LOW = "low";
50  
51      /** String indicating double exponents with mid-level values which will not overflow or underflow. */
52      private static final String MID = "mid";
53  
54      /** String indicating double exponents with very high positive values, likely to overflow. */
55      private static final String HIGH = "high";
56  
57      /** String indicating double exponents over a very wide range of values. */
58      private static final String FULL = "full";
59  
60      /** Class providing input vectors for benchmarks.
61       */
62      @State(Scope.Benchmark)
63      public static class VectorArrayInput {
64  
65          /** The number of samples. */
66          @Param("100000")
67          private int samples;
68  
69          /** The length of each vector. */
70          @Param("100")
71          private int vectorLength;
72  
73          /** The type of double values placed in the vector arrays. */
74          @Param({LOW, MID, HIGH, FULL})
75          private String type;
76  
77          /** Array of input vectors. */
78          private double[][] vectors;
79  
80          /** Get the input vectors.
81           * @return input vectors
82           */
83          public double[][] getVectors() {
84              return vectors;
85          }
86  
87          /** Create the input vectors for the instance.
88           */
89          @Setup
90          public void createVectors() {
91              final UniformRandomProvider rng = RandomSource.XO_RO_SHI_RO_1024_PP.create();
92  
93              int minExp;
94              int maxExp;
95  
96              switch (type) {
97              case LOW:
98                  minExp = -530;
99                  maxExp = -510;
100                 break;
101             case MID:
102                 minExp = -10;
103                 maxExp = +10;
104                 break;
105             case HIGH:
106                 minExp = +510;
107                 maxExp = +530;
108                 break;
109             default:
110                 throw new IllegalArgumentException("Invalid vector type: " + type);
111             }
112 
113             vectors = new double[samples][];
114             for (int i = 0; i < vectors.length; ++i) {
115                 vectors[i] = DoubleUtils.randomArray(vectorLength, minExp, maxExp, rng);
116             }
117         }
118     }
119 
120     /** Evaluate a norm computation method with the given input.
121      * @param fn function to evaluate
122      * @param input computation input
123      * @param bh blackhole
124      */
125     private static void eval(final ToDoubleFunction<double[]> fn, final VectorArrayInput input,
126             final Blackhole bh) {
127         final double[][] vectors = input.getVectors();
128         for (int i = 0; i < vectors.length; ++i) {
129             bh.consume(fn.applyAsDouble(vectors[i]));
130         }
131     }
132 
133     /** Compute the performance of the {@link EuclideanNormAlgorithms.Exact} class.
134      * @param input benchmark input
135      * @param bh blackhole
136      */
137     @Benchmark
138     public void exact(final VectorArrayInput input, final Blackhole bh) {
139         eval(new EuclideanNormAlgorithms.Exact(), input, bh);
140     }
141 
142     /** Compute the performance of the {@link EuclideanNormAlgorithms.Direct} class.
143      * @param input benchmark input
144      * @param bh blackhole
145      */
146     @Benchmark
147     public void direct(final VectorArrayInput input, final Blackhole bh) {
148         eval(new EuclideanNormAlgorithms.Direct(), input, bh);
149     }
150 
151     /** Compute the performance of the {@link EuclideanNormAlgorithms.Enorm} class.
152      * @param input benchmark input
153      * @param bh blackhole
154      */
155     @Benchmark
156     public void enorm(final VectorArrayInput input, final Blackhole bh) {
157         eval(new EuclideanNormAlgorithms.Enorm(), input, bh);
158     }
159 
160     /** Compute the performance of the {@link EuclideanNormAlgorithms.EnormMod} class.
161      * @param input benchmark input
162      * @param bh blackhole
163      */
164     @Benchmark
165     public void enormMod(final VectorArrayInput input, final Blackhole bh) {
166         eval(new EuclideanNormAlgorithms.EnormMod(), input, bh);
167     }
168 
169     /** Compute the performance of the {@link EuclideanNormAlgorithms.EnormModKahan} class.
170      * @param input benchmark input
171      * @param bh blackhole
172      */
173     @Benchmark
174     public void enormModKahan(final VectorArrayInput input, final Blackhole bh) {
175         eval(new EuclideanNormAlgorithms.EnormModKahan(), input, bh);
176     }
177 
178     /** Compute the performance of the {@link EuclideanNormAlgorithms.EnormModExt} class.
179      * @param input benchmark input
180      * @param bh blackhole
181      */
182     @Benchmark
183     public void enormModExt(final VectorArrayInput input, final Blackhole bh) {
184         eval(new EuclideanNormAlgorithms.EnormModExt(), input, bh);
185     }
186 
187     /** Compute the performance of the {@link EuclideanNormAlgorithms.ExtendedPrecisionLinearCombination} class.
188      * @param input benchmark input
189      * @param bh blackhole
190      */
191     @Benchmark
192     public void extLinear(final VectorArrayInput input, final Blackhole bh) {
193         eval(new EuclideanNormAlgorithms.ExtendedPrecisionLinearCombination(), input, bh);
194     }
195 
196     /** Compute the performance of the {@link EuclideanNormAlgorithms.ExtendedPrecisionLinearCombinationMod} class.
197      * @param input benchmark input
198      * @param bh blackhole
199      */
200     @Benchmark
201     public void extLinearMod(final VectorArrayInput input, final Blackhole bh) {
202         eval(new EuclideanNormAlgorithms.ExtendedPrecisionLinearCombinationMod(), input, bh);
203     }
204 
205     /** Compute the performance of the {@link EuclideanNormAlgorithms.ExtendedPrecisionLinearCombinationSinglePass}
206      * class.
207      * @param input benchmark input
208      * @param bh blackhole
209      */
210     @Benchmark
211     public void extLinearSinglePass(final VectorArrayInput input, final Blackhole bh) {
212         eval(new EuclideanNormAlgorithms.ExtendedPrecisionLinearCombinationSinglePass(), input, bh);
213     }
214 
215     /** Compute the performance of the {@link EuclideanNormAlgorithms.ExtendedPrecisionLinearCombinationSqrt2}
216      * class.
217      * @param input benchmark input
218      * @param bh blackhole
219      */
220     @Benchmark
221     public void extLinearSqrt2(final VectorArrayInput input, final Blackhole bh) {
222         eval(new EuclideanNormAlgorithms.ExtendedPrecisionLinearCombinationSqrt2(), input, bh);
223     }
224 }