1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
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.numbers.core.Norm;
23 import org.apache.commons.rng.UniformRandomProvider;
24 import org.apache.commons.rng.simple.RandomSource;
25 import org.openjdk.jmh.annotations.Benchmark;
26 import org.openjdk.jmh.annotations.BenchmarkMode;
27 import org.openjdk.jmh.annotations.Fork;
28 import org.openjdk.jmh.annotations.Measurement;
29 import org.openjdk.jmh.annotations.Mode;
30 import org.openjdk.jmh.annotations.OutputTimeUnit;
31 import org.openjdk.jmh.annotations.Param;
32 import org.openjdk.jmh.annotations.Scope;
33 import org.openjdk.jmh.annotations.Setup;
34 import org.openjdk.jmh.annotations.State;
35 import org.openjdk.jmh.annotations.Warmup;
36 import org.openjdk.jmh.infra.Blackhole;
37
38
39
40
41 @BenchmarkMode(Mode.AverageTime)
42 @OutputTimeUnit(TimeUnit.NANOSECONDS)
43 @Warmup(iterations = 5, time = 1, timeUnit = TimeUnit.SECONDS)
44 @Measurement(iterations = 5, time = 1, timeUnit = TimeUnit.SECONDS)
45 @State(Scope.Benchmark)
46 @Fork(value = 1, jvmArgs = {"-server", "-Xms512M", "-Xmx512M"})
47 public class NormPerformance {
48
49
50
51 @State(Scope.Benchmark)
52 public static class VectorArrayInput {
53
54
55 @Param("100000")
56 private int samples;
57
58
59 @Param("-550")
60 private int minExp;
61
62
63 @Param("+550")
64 private int maxExp;
65
66
67 @Param("26")
68 private int vectorExpRange;
69
70
71 private double[][] vectors;
72
73
74
75
76 public double[][] getVectors() {
77 return vectors;
78 }
79
80
81
82 @Setup
83 public void createVectors() {
84 final UniformRandomProvider rng = RandomSource.XO_RO_SHI_RO_1024_PP.create();
85
86 vectors = new double[samples][];
87 for (int i = 0; i < vectors.length; ++i) {
88
89
90 final int vMidExp = rng.nextInt(maxExp - minExp + 1) + minExp;
91 final int vExpRadius = vectorExpRange / 2;
92 final int vMinExp = vMidExp - vExpRadius;
93 final int vMaxExp = vMidExp + vExpRadius;
94
95 vectors[i] = DoubleUtils.randomArray(getLength(), vMinExp, vMaxExp, rng);
96 }
97 }
98
99
100
101
102 protected int getLength() {
103 return 3;
104 }
105 }
106
107
108
109 @State(Scope.Benchmark)
110 public static class VectorArrayInput2D extends VectorArrayInput {
111
112
113 @Override
114 protected int getLength() {
115 return 2;
116 }
117 }
118
119
120
121
122
123
124 private static void eval(final ToDoubleFunction<double[]> fn,
125 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
134
135
136
137
138 private static void eval(final Norm fn,
139 final VectorArrayInput input,
140 final Blackhole bh) {
141 final double[][] vectors = input.getVectors();
142 for (int i = 0; i < vectors.length; ++i) {
143 bh.consume(fn.of(vectors[i]));
144 }
145 }
146
147
148
149
150
151 private static double directEuclideanNorm(final double[] v) {
152 double n = 0;
153 for (int i = 0; i < v.length; i++) {
154 n += v[i] * v[i];
155 }
156 return Math.sqrt(n);
157 }
158
159
160
161
162
163 @Benchmark
164 public void baseline(final VectorArrayInput input, final Blackhole bh) {
165 eval(v -> 0d, input, bh);
166 }
167
168
169
170
171
172
173 @Benchmark
174 public void directEuclideanArray(final VectorArrayInput input, final Blackhole bh) {
175 eval(NormPerformance::directEuclideanNorm, input, bh);
176 }
177
178
179
180
181
182 @Benchmark
183 public void hypot(final VectorArrayInput2D input, final Blackhole bh) {
184 eval(v -> Math.hypot(v[0], v[1]), input, bh);
185 }
186
187
188
189
190
191 @Benchmark
192 public void euclidean2d(final VectorArrayInput2D input, final Blackhole bh) {
193 eval(v -> Norm.L2.of(v[0], v[1]), input, bh);
194 }
195
196
197
198
199
200 @Benchmark
201 public void euclidean3d(final VectorArrayInput input, final Blackhole bh) {
202 eval(v -> Norm.L2.of(v[0], v[1], v[2]), input, bh);
203 }
204
205
206
207
208
209 @Benchmark
210 public void euclideanArray(final VectorArrayInput input, final Blackhole bh) {
211 eval(Norm.L2, input, bh);
212 }
213 }