Skip to content

Commit 2f8c221

Browse files
amCap1712Paul Sandoz
authored andcommitted
8273681: Add Vector API vs Arrays.mismatch intrinsic benchmark
Reviewed-by: psandoz
1 parent 17f7a45 commit 2f8c221

File tree

1 file changed

+229
-0
lines changed

1 file changed

+229
-0
lines changed
Lines changed: 229 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,229 @@
1+
/*
2+
* Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved.
3+
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+
*
5+
* This code is free software; you can redistribute it and/or modify it
6+
* under the terms of the GNU General Public License version 2 only, as
7+
* published by the Free Software Foundation.
8+
*
9+
* This code is distributed in the hope that it will be useful, but WITHOUT
10+
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11+
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12+
* version 2 for more details (a copy is included in the LICENSE file that
13+
* accompanied this code).
14+
*
15+
* You should have received a copy of the GNU General Public License version
16+
* 2 along with this work; if not, write to the Free Software Foundation,
17+
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18+
*
19+
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20+
* or visit www.oracle.com if you need additional information or have any
21+
* questions.
22+
*
23+
*/
24+
25+
package org.openjdk.bench.jdk.incubator.vector;
26+
27+
28+
import jdk.incubator.vector.ByteVector;
29+
import jdk.incubator.vector.DoubleVector;
30+
import jdk.incubator.vector.IntVector;
31+
import jdk.incubator.vector.LongVector;
32+
import jdk.incubator.vector.VectorMask;
33+
import jdk.incubator.vector.VectorOperators;
34+
import jdk.incubator.vector.VectorSpecies;
35+
import org.openjdk.jmh.annotations.Benchmark;
36+
import org.openjdk.jmh.annotations.Fork;
37+
import org.openjdk.jmh.annotations.OutputTimeUnit;
38+
import org.openjdk.jmh.annotations.Param;
39+
import org.openjdk.jmh.annotations.Scope;
40+
import org.openjdk.jmh.annotations.Setup;
41+
import org.openjdk.jmh.annotations.State;
42+
import org.openjdk.jmh.infra.BenchmarkParams;
43+
44+
import java.util.Arrays;
45+
import java.util.concurrent.TimeUnit;
46+
import java.util.random.RandomGenerator;
47+
48+
@OutputTimeUnit(TimeUnit.MILLISECONDS)
49+
@State(Scope.Thread)
50+
@Fork(jvmArgsPrepend = {"--add-modules=jdk.incubator.vector"})
51+
public class ArrayMismatchBenchmark {
52+
53+
@Param({"9", "257", "100000"})
54+
int size;
55+
56+
@Param({"0.5", "1.0"})
57+
double prefix;
58+
59+
byte[] byteData1;
60+
byte[] byteData2;
61+
62+
int[] intData1;
63+
int[] intData2;
64+
65+
long[] longData1;
66+
long[] longData2;
67+
68+
double[] doubleData1;
69+
double[] doubleData2;
70+
71+
static final VectorSpecies<Byte> BYTE_SPECIES_PREFERRED = ByteVector.SPECIES_PREFERRED;
72+
static final VectorSpecies<Integer> INT_SPECIES_PREFERRED = IntVector.SPECIES_PREFERRED;
73+
static final VectorSpecies<Double> FLOAT_SPECIES_PREFERRED = DoubleVector.SPECIES_PREFERRED;
74+
static final VectorSpecies<Long> LONG_SPECIES_PREFERRED = LongVector.SPECIES_PREFERRED;
75+
76+
@Setup
77+
public void setup(BenchmarkParams params) {
78+
RandomGenerator random = RandomGenerator.getDefault();
79+
int common = (int) (prefix * size);
80+
81+
if (params.getBenchmark().endsWith("Byte")) {
82+
byteData1 = new byte[size];
83+
byteData2 = new byte[size];
84+
random.nextBytes(byteData1);
85+
random.nextBytes(byteData2);
86+
87+
byte[] commonBytes = new byte[common];
88+
random.nextBytes(commonBytes);
89+
90+
System.arraycopy(commonBytes, 0, byteData1, 0, common);
91+
System.arraycopy(commonBytes, 0, byteData2, 0, common);
92+
} else if (params.getBenchmark().endsWith("Int")) {
93+
intData1 = random.ints(size).toArray();
94+
intData2 = random.ints(size).toArray();
95+
96+
int[] commonInts = random.ints(common).toArray();
97+
System.arraycopy(commonInts, 0, intData1, 0, common);
98+
System.arraycopy(commonInts, 0, intData2, 0, common);
99+
} else if (params.getBenchmark().endsWith("Double")) {
100+
doubleData1 = random.doubles(size).toArray();
101+
doubleData2 = random.doubles(size).toArray();
102+
103+
double[] commonDoubles = random.doubles(common).toArray();
104+
System.arraycopy(commonDoubles, 0, doubleData1, 0, common);
105+
System.arraycopy(commonDoubles, 0, doubleData2, 0, common);
106+
} else if (params.getBenchmark().endsWith("Long")) {
107+
longData1 = random.longs(size).toArray();
108+
longData2 = random.longs(size).toArray();
109+
110+
long[] commonLongs = random.longs(common).toArray();
111+
System.arraycopy(commonLongs, 0, longData1, 0, common);
112+
System.arraycopy(commonLongs, 0, longData2, 0, common);
113+
}
114+
}
115+
116+
@Benchmark
117+
public int mismatchIntrinsicByte() {
118+
return Arrays.mismatch(byteData1, byteData2);
119+
}
120+
121+
@Benchmark
122+
public int mismatchVectorByte() {
123+
int length = Math.min(byteData1.length, byteData2.length);
124+
int index = 0;
125+
for (; index < BYTE_SPECIES_PREFERRED.loopBound(length); index += BYTE_SPECIES_PREFERRED.length()) {
126+
ByteVector vector1 = ByteVector.fromArray(BYTE_SPECIES_PREFERRED, byteData1, index);
127+
ByteVector vector2 = ByteVector.fromArray(BYTE_SPECIES_PREFERRED, byteData2, index);
128+
VectorMask<Byte> mask = vector1.compare(VectorOperators.NE, vector2);
129+
if (mask.anyTrue()) {
130+
return index + mask.firstTrue();
131+
}
132+
}
133+
// process the tail
134+
int mismatch = -1;
135+
for (int i = index; i < length; ++i) {
136+
if (byteData1[i] != byteData2[i]) {
137+
mismatch = i;
138+
break;
139+
}
140+
}
141+
return mismatch;
142+
}
143+
144+
@Benchmark
145+
public int mismatchIntrinsicInt() {
146+
return Arrays.mismatch(intData1, intData2);
147+
}
148+
149+
@Benchmark
150+
public int mismatchVectorInt() {
151+
int length = Math.min(intData1.length, intData2.length);
152+
int index = 0;
153+
for (; index < INT_SPECIES_PREFERRED.loopBound(length); index += INT_SPECIES_PREFERRED.length()) {
154+
IntVector vector1 = IntVector.fromArray(INT_SPECIES_PREFERRED, intData1, index);
155+
IntVector vector2 = IntVector.fromArray(INT_SPECIES_PREFERRED, intData2, index);
156+
VectorMask<Integer> mask = vector1.compare(VectorOperators.NE, vector2);
157+
if (mask.anyTrue()) {
158+
return index + mask.firstTrue();
159+
}
160+
}
161+
// process the tail
162+
int mismatch = -1;
163+
for (int i = index; i < length; ++i) {
164+
if (intData1[i] != intData2[i]) {
165+
mismatch = i;
166+
break;
167+
}
168+
}
169+
return mismatch;
170+
}
171+
172+
@Benchmark
173+
public int mismatchIntrinsicDouble() {
174+
return Arrays.mismatch(doubleData1, doubleData2);
175+
}
176+
177+
@Benchmark
178+
public int mismatchVectorDouble() {
179+
int length = Math.min(doubleData1.length, doubleData2.length);
180+
int index = 0;
181+
for (; index < FLOAT_SPECIES_PREFERRED.loopBound(length); index += FLOAT_SPECIES_PREFERRED.length()) {
182+
DoubleVector vector1 = DoubleVector.fromArray(FLOAT_SPECIES_PREFERRED, doubleData1, index);
183+
DoubleVector vector2 = DoubleVector.fromArray(FLOAT_SPECIES_PREFERRED, doubleData2, index);
184+
VectorMask<Double> mask = vector1.compare(VectorOperators.NE, vector2);
185+
if (mask.anyTrue()) {
186+
return index + mask.firstTrue();
187+
}
188+
}
189+
// process the tail
190+
int mismatch = -1;
191+
for (int i = index; i < length; ++i) {
192+
if (doubleData1[i] != doubleData2[i]) {
193+
mismatch = i;
194+
break;
195+
}
196+
}
197+
return mismatch;
198+
}
199+
200+
@Benchmark
201+
public int mismatchIntrinsicLong() {
202+
return Arrays.mismatch(longData1, longData2);
203+
}
204+
205+
@Benchmark
206+
public int mismatchVectorLong() {
207+
int length = Math.min(longData1.length, longData2.length);
208+
int index = 0;
209+
for (; index < LONG_SPECIES_PREFERRED.loopBound(length); index += LONG_SPECIES_PREFERRED.length()) {
210+
LongVector vector1 = LongVector.fromArray(LONG_SPECIES_PREFERRED, longData1, index);
211+
LongVector vector2 = LongVector.fromArray(LONG_SPECIES_PREFERRED, longData2, index);
212+
VectorMask<Long> mask = vector1.compare(VectorOperators.NE, vector2);
213+
if (mask.anyTrue()) {
214+
return index + mask.firstTrue();
215+
}
216+
}
217+
// process the tail
218+
int mismatch = -1;
219+
for (int i = index; i < length; ++i) {
220+
if (longData1[i] != longData2[i]) {
221+
mismatch = i;
222+
break;
223+
}
224+
}
225+
return mismatch;
226+
}
227+
228+
}
229+

0 commit comments

Comments
 (0)