Skip to content
Permalink
Browse files
8266518: Refactor and expand scatter/gather tests
Reviewed-by: sviswanathan
  • Loading branch information
Paul Sandoz committed Jun 18, 2021
1 parent f9c8c1c commit dab00ee59b73bcd5b8632d127b3d0a324e48e4e5
Showing 72 changed files with 6,402 additions and 5,306 deletions.
@@ -108,20 +108,6 @@ public String toString() {
i -> ((i % 5) == 0));
})
);
static final List<IntFunction<int[]>> INDEX_GENERATORS = List.of(
withToString("index[i -> i]", (int s) -> {
return fillInts(s,
i -> i);
}),
withToString("index[i -> size - i - 1]", (int s) -> {
return fillInts(s,
i -> s - i - 1);
}),
withToString("index[i -> (i % 2) == 0 ? i : s - i - 1]", (int s) -> {
return fillInts(s,
i -> (i % 2) == 0 ? i : s - i - 1);
})
);

interface IntOp {
int apply(int i);
@@ -161,9 +147,8 @@ static int[] fillInts(int[] a, IntOp f) {
fb -> List.of(fa, fb))).collect(Collectors.toList());

static final List<BiFunction<Integer,Integer,int[]>> INT_SHUFFLE_GENERATORS = List.of(
withToStringBi("shuffle[random]", (Integer l, Integer m) -> {
return RAND.ints(l, 0, m).toArray();
})
withToStringBi("shuffle[random]",
(Integer l, Integer m) -> RAND.ints(l, 0, m).toArray())
);

interface RangeIntOp {
@@ -202,17 +187,10 @@ static int[] fillRangeInts(int[] a, int min, int max, RangeIntOp f) {
);

static final List<BiFunction<Integer,Integer,int[]>> INT_INDEX_GENERATORS = List.of(
withToStringBi("index[random]", (Integer l, Integer m) -> {
return RAND.ints(l, 0, m).toArray();
})
withToStringBi("index[random]",
(Integer l, Integer m) -> RAND.ints(l, 0, m).toArray())
);

static int countTrailingFalse(boolean[] m) {
int i;
for (i = m.length - 1; i >= 0 && !m[i]; i--);
return m.length - 1 - i;
}

static boolean isIndexOutOfBoundsForMask(boolean[] mask, int offset, int length) {
return isIndexOutOfBoundsForMask(mask, offset, length, 1);
}
@@ -42,6 +42,7 @@
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.ReadOnlyBufferException;
import java.util.Arrays;
import java.util.List;
import java.util.function.*;

@@ -50,13 +51,11 @@ public class Byte128VectorLoadStoreTests extends AbstractVectorTest {
static final VectorSpecies<Byte> SPECIES =
ByteVector.SPECIES_128;

static final int INVOC_COUNT = Integer.getInteger("jdk.incubator.vector.test.loop-iterations", 10);
static final int INVOC_COUNT = Integer.getInteger("jdk.incubator.vector.test.loop-iterations", 100);


static final int BUFFER_REPS = Integer.getInteger("jdk.incubator.vector.test.buffer-vectors", 25000 / 128);

static final int BUFFER_SIZE = Integer.getInteger("jdk.incubator.vector.test.buffer-size", BUFFER_REPS * (128 / 8));

static void assertArraysEquals(byte[] r, byte[] a, boolean[] mask) {
int i = 0;
try {
@@ -178,25 +177,6 @@ public Object[][] byteMaskProviderForIOOBE() {
toArray(Object[][]::new);
}

@DataProvider
public Object[][] byteIndexMapProvider() {
return INDEX_GENERATORS.stream().
flatMap(fim -> BYTE_GENERATORS.stream().map(fa -> {
return new Object[] {fa, fim};
})).
toArray(Object[][]::new);
}

@DataProvider
public Object[][] byteIndexMapMaskProvider() {
return BOOLEAN_MASK_GENERATORS.stream().
flatMap(fm -> INDEX_GENERATORS.stream().
flatMap(fim -> BYTE_GENERATORS.stream().map(fa -> {
return new Object[] {fa, fim, fm};
}))).
toArray(Object[][]::new);
}

@DataProvider
public Object[][] byteByteBufferProvider() {
return BYTE_GENERATORS.stream().
@@ -1038,4 +1018,281 @@ static void loadStoreMaskBooleanArray(IntFunction<byte[]> fa,
}
assertArraysEquals(r, a, mask);
}


// Gather/Scatter load/store tests

static void assertGatherArraysEquals(byte[] r, byte[] a, int[] indexMap) {
int i = 0;
int j = 0;
try {
for (; i < a.length; i += SPECIES.length()) {
j = i;
for (; j < i + SPECIES.length(); j++) {
Assert.assertEquals(r[j], a[i + indexMap[j]]);
}
}
} catch (AssertionError e) {
Assert.assertEquals(r[j], a[i + indexMap[j]], "at index #" + j);
}
}

static void assertGatherArraysEquals(byte[] r, byte[] a, int[] indexMap, boolean[] mask) {
int i = 0;
int j = 0;
try {
for (; i < a.length; i += SPECIES.length()) {
j = i;
for (; j < i + SPECIES.length(); j++) {
Assert.assertEquals(r[j], mask[j % SPECIES.length()] ? a[i + indexMap[j]]: (byte) 0);
}
}
} catch (AssertionError e) {
Assert.assertEquals(r[i], mask[j % SPECIES.length()] ? a[i + indexMap[j]]: (byte) 0, "at index #" + j);
}
}

static void assertScatterArraysEquals(byte[] r, byte[] a, int[] indexMap, boolean[] mask) {
byte[] expected = new byte[r.length];

// Store before checking, since the same location may be stored to more than once
for (int i = 0; i < a.length; i += SPECIES.length()) {
for (int j = i; j < i + SPECIES.length(); j++) {
if (mask[j % SPECIES.length()]) {
expected[i + indexMap[j]] = a[j];
}
}
}

Assert.assertEquals(r, expected);
}

static void assertScatterArraysEquals(byte[] r, byte[] a, int[] indexMap) {
byte[] expected = new byte[r.length];

// Store before checking, since the same location may be stored to more than once
for (int i = 0; i < a.length; i += SPECIES.length()) {
for (int j = i; j < i + SPECIES.length(); j++) {
expected[i + indexMap[j]] = a[j];
}
}

Assert.assertEquals(r, expected);
}

@DataProvider
public Object[][] gatherScatterProvider() {
return INT_INDEX_GENERATORS.stream().
flatMap(fs -> BYTE_GENERATORS.stream().map(fa -> {
return new Object[] {fa, fs};
})).
toArray(Object[][]::new);
}

@DataProvider
public Object[][] gatherScatterMaskProvider() {
return BOOLEAN_MASK_GENERATORS.stream().
flatMap(fs -> INT_INDEX_GENERATORS.stream().flatMap(fm ->
BYTE_GENERATORS.stream().map(fa -> {
return new Object[] {fa, fm, fs};
}))).
toArray(Object[][]::new);
}


@Test(dataProvider = "gatherScatterProvider")
static void gather(IntFunction<byte[]> fa, BiFunction<Integer,Integer,int[]> fs) {
byte[] a = fa.apply(SPECIES.length());
int[] b = fs.apply(a.length, SPECIES.length());
byte[] r = new byte[a.length];

for (int ic = 0; ic < INVOC_COUNT; ic++) {
for (int i = 0; i < a.length; i += SPECIES.length()) {
ByteVector av = ByteVector.fromArray(SPECIES, a, i, b, i);
av.intoArray(r, i);
}
}

assertGatherArraysEquals(r, a, b);
}

@Test(dataProvider = "gatherScatterMaskProvider")
static void gatherMask(IntFunction<byte[]> fa, BiFunction<Integer,Integer,int[]> fs, IntFunction<boolean[]> fm) {
byte[] a = fa.apply(SPECIES.length());
int[] b = fs.apply(a.length, SPECIES.length());
byte[] r = new byte[a.length];
boolean[] mask = fm.apply(SPECIES.length());
VectorMask<Byte> vmask = VectorMask.fromArray(SPECIES, mask, 0);

for (int ic = 0; ic < INVOC_COUNT; ic++) {
for (int i = 0; i < a.length; i += SPECIES.length()) {
ByteVector av = ByteVector.fromArray(SPECIES, a, i, b, i, vmask);
av.intoArray(r, i);
}
}

assertGatherArraysEquals(r, a, b, mask);
}

@Test(dataProvider = "gatherScatterProvider")
static void scatter(IntFunction<byte[]> fa, BiFunction<Integer,Integer,int[]> fs) {
byte[] a = fa.apply(SPECIES.length());
int[] b = fs.apply(a.length, SPECIES.length());
byte[] r = new byte[a.length];

for (int ic = 0; ic < INVOC_COUNT; ic++) {
for (int i = 0; i < a.length; i += SPECIES.length()) {
ByteVector av = ByteVector.fromArray(SPECIES, a, i);
av.intoArray(r, i, b, i);
}
}

assertScatterArraysEquals(r, a, b);
}

@Test(dataProvider = "gatherScatterMaskProvider")
static void scatterMask(IntFunction<byte[]> fa, BiFunction<Integer,Integer,int[]> fs, IntFunction<boolean[]> fm) {
byte[] a = fa.apply(SPECIES.length());
int[] b = fs.apply(a.length, SPECIES.length());
byte[] r = new byte[a.length];
boolean[] mask = fm.apply(SPECIES.length());
VectorMask<Byte> vmask = VectorMask.fromArray(SPECIES, mask, 0);

for (int ic = 0; ic < INVOC_COUNT; ic++) {
for (int i = 0; i < a.length; i += SPECIES.length()) {
ByteVector av = ByteVector.fromArray(SPECIES, a, i);
av.intoArray(r, i, b, i, vmask);
}
}

assertScatterArraysEquals(r, a, b, mask);
}


static void assertGatherArraysEquals(boolean[] r, boolean[] a, int[] indexMap) {
int i = 0;
int j = 0;
try {
for (; i < a.length; i += SPECIES.length()) {
j = i;
for (; j < i + SPECIES.length(); j++) {
Assert.assertEquals(r[j], a[i + indexMap[j]]);
}
}
} catch (AssertionError e) {
Assert.assertEquals(r[j], a[i + indexMap[j]], "at index #" + j);
}
}

static void assertGatherArraysEquals(boolean[] r, boolean[] a, int[] indexMap, boolean[] mask) {
int i = 0;
int j = 0;
try {
for (; i < a.length; i += SPECIES.length()) {
j = i;
for (; j < i + SPECIES.length(); j++) {
Assert.assertEquals(r[j], mask[j % SPECIES.length()] ? a[i + indexMap[j]]: false);
}
}
} catch (AssertionError e) {
Assert.assertEquals(r[i], mask[j % SPECIES.length()] ? a[i + indexMap[j]]: false, "at index #" + j);
}
}

static void assertScatterArraysEquals(boolean[] r, boolean[] a, int[] indexMap, boolean[] mask) {
boolean[] expected = new boolean[r.length];

// Store before checking, since the same location may be stored to more than once
for (int i = 0; i < a.length; i += SPECIES.length()) {
for (int j = i; j < i + SPECIES.length(); j++) {
if (mask[j % SPECIES.length()]) {
expected[i + indexMap[j]] = a[j];
}
}
}

Assert.assertEquals(r, expected);
}

static void assertScatterArraysEquals(boolean[] r, boolean[] a, int[] indexMap) {
boolean[] expected = new boolean[r.length];

// Store before checking, since the same location may be stored to more than once
for (int i = 0; i < a.length; i += SPECIES.length()) {
for (int j = i; j < i + SPECIES.length(); j++) {
expected[i + indexMap[j]] = a[j];
}
}

Assert.assertEquals(r, expected);
}

@Test(dataProvider = "gatherScatterProvider")
static void booleanGather(IntFunction<byte[]> fa, BiFunction<Integer,Integer,int[]> fs) {
boolean[] a = convertToBooleanArray(fa.apply(SPECIES.length()));
int[] b = fs.apply(a.length, SPECIES.length());
boolean[] r = new boolean[a.length];

for (int ic = 0; ic < INVOC_COUNT; ic++) {
for (int i = 0; i < a.length; i += SPECIES.length()) {
ByteVector av = ByteVector.fromBooleanArray(SPECIES, a, i, b, i);
av.intoBooleanArray(r, i);
}
}

assertGatherArraysEquals(r, a, b);
}

@Test(dataProvider = "gatherScatterMaskProvider")
static void booleanGatherMask(IntFunction<byte[]> fa, BiFunction<Integer,Integer,int[]> fs, IntFunction<boolean[]> fm) {
boolean[] a = convertToBooleanArray(fa.apply(SPECIES.length()));
int[] b = fs.apply(a.length, SPECIES.length());
boolean[] r = new boolean[a.length];
boolean[] mask = fm.apply(SPECIES.length());
VectorMask<Byte> vmask = VectorMask.fromArray(SPECIES, mask, 0);

for (int ic = 0; ic < INVOC_COUNT; ic++) {
for (int i = 0; i < a.length; i += SPECIES.length()) {
ByteVector av = ByteVector.fromBooleanArray(SPECIES, a, i, b, i, vmask);
av.intoBooleanArray(r, i);
}
}

assertGatherArraysEquals(r, a, b, mask);
}

@Test(dataProvider = "gatherScatterProvider")
static void booleanScatter(IntFunction<byte[]> fa, BiFunction<Integer,Integer,int[]> fs) {
boolean[] a = convertToBooleanArray(fa.apply(SPECIES.length()));
int[] b = fs.apply(a.length, SPECIES.length());
boolean[] r = new boolean[a.length];

for (int ic = 0; ic < INVOC_COUNT; ic++) {
for (int i = 0; i < a.length; i += SPECIES.length()) {
ByteVector av = ByteVector.fromBooleanArray(SPECIES, a, i);
av.intoBooleanArray(r, i, b, i);
}
}

assertScatterArraysEquals(r, a, b);
}

@Test(dataProvider = "gatherScatterMaskProvider")
static void booleanScatterMask(IntFunction<byte[]> fa, BiFunction<Integer,Integer,int[]> fs, IntFunction<boolean[]> fm) {
boolean[] a = convertToBooleanArray(fa.apply(SPECIES.length()));
int[] b = fs.apply(a.length, SPECIES.length());
boolean[] r = new boolean[a.length];
boolean[] mask = fm.apply(SPECIES.length());
VectorMask<Byte> vmask = VectorMask.fromArray(SPECIES, mask, 0);

for (int ic = 0; ic < INVOC_COUNT; ic++) {
for (int i = 0; i < a.length; i += SPECIES.length()) {
ByteVector av = ByteVector.fromBooleanArray(SPECIES, a, i);
av.intoBooleanArray(r, i, b, i, vmask);
}
}

assertScatterArraysEquals(r, a, b, mask);
}

}

0 comments on commit dab00ee

Please sign in to comment.