General reduction test improvement and bug fixes.
Improved testing (UT_reduce.java):
- Add addint3D test.
- Execute 2D and 3D tests over a range of sizes.
Bug fixes:
- Fix bug in fz3 kernel (combiner function).
- Fix bug in UT_reduce_backward.java findMinAndMax test (copy fix from UT_reduce.java).
- In UT_reduce.java (which creates a very large number of Allocations), explicitly
invoke Allocation.destroy() to avoid out-of-native-memory problems.
Bug: 27299475
Change-Id: I939a329af9f92e57bc8aa4c22db2b56996f1ff88
(cherry picked from commit d41c224c3e1e31e29d225e51b994d689022cfd07)
diff --git a/java/tests/RsTest/src/com/android/rs/test/UT_reduce.java b/java/tests/RsTest/src/com/android/rs/test/UT_reduce.java
index 0769259..f6cfda1 100644
--- a/java/tests/RsTest/src/com/android/rs/test/UT_reduce.java
+++ b/java/tests/RsTest/src/com/android/rs/test/UT_reduce.java
@@ -14,10 +14,10 @@
* limitations under the License.
*/
-/* Same as UT_reduce_backward.java, except this test case exercises
- * pragmas before the functions (forward reference), and the other
- * test case exercises the pragmas after the functions (backward
- * reference).
+/* UT_reduce_backward.java is a much simpler version of this test
+ * case that exercises pragmas after the functions (backward
+ * reference), whereas this test case exercises the pragmas before
+ * the functions (forward reference).
*/
package com.android.rs.test;
@@ -27,8 +27,11 @@
import android.renderscript.*;
import android.util.Log;
import java.lang.Float;
+import java.lang.Math;
+import java.util.ArrayList;
import java.util.Arrays;
import java.util.Random;
+import static junit.framework.Assert.*;
public class UT_reduce extends UnitTest {
private static final String TAG = "reduce";
@@ -236,10 +239,13 @@
final int rsRslt = s.reduce_addint(inputAllocation).get();
final long rsTimeEnd = java.lang.System.currentTimeMillis();
- return result("addint1D",
- new timing(javaTimeStart, javaTimeEnd, rsTimeStart,
- copyTimeStart, kernelTimeStart, rsTimeEnd, inputAllocation),
- javaRslt, rsRslt);
+ final boolean success =
+ result("addint1D",
+ new timing(javaTimeStart, javaTimeEnd, rsTimeStart,
+ copyTimeStart, kernelTimeStart, rsTimeEnd, inputAllocation),
+ javaRslt, rsRslt);
+ inputAllocation.destroy();
+ return success;
}
private boolean addint2D(RenderScript RS, ScriptC_reduce s, int seed, int[] size) {
@@ -266,10 +272,47 @@
final int rsRslt = s.reduce_addint(inputAllocation).get();
final long rsTimeEnd = java.lang.System.currentTimeMillis();
- return result("addint2D",
- new timing(javaTimeStart, javaTimeEnd, rsTimeStart,
- copyTimeStart, kernelTimeStart, rsTimeEnd, inputAllocation),
- javaRslt, rsRslt);
+ final boolean success =
+ result("addint2D",
+ new timing(javaTimeStart, javaTimeEnd, rsTimeStart,
+ copyTimeStart, kernelTimeStart, rsTimeEnd, inputAllocation),
+ javaRslt, rsRslt);
+ inputAllocation.destroy();
+ return success;
+ }
+
+ private boolean addint3D(RenderScript RS, ScriptC_reduce s, int seed, int[] size) {
+ final int dimX = size[0];
+ final int dimY = size[1];
+ final int dimZ = size[2];
+
+ final int[] inputArray = createInputArrayInt(dimX * dimY * dimZ, seed, Integer.MAX_VALUE / (dimX * dimY * dimZ));
+
+ final long javaTimeStart = java.lang.System.currentTimeMillis();
+ final int javaRslt = addint(inputArray);
+ final long javaTimeEnd = java.lang.System.currentTimeMillis();
+
+ final long rsTimeStart = java.lang.System.currentTimeMillis();
+
+ Type.Builder typeBuilder = new Type.Builder(RS, Element.I32(RS));
+ typeBuilder.setX(dimX).setY(dimY).setZ(dimZ);
+ Allocation inputAllocation = Allocation.createTyped(RS, typeBuilder.create());
+
+ final long copyTimeStart = java.lang.System.currentTimeMillis();
+
+ inputAllocation.copy3DRangeFrom(0, 0, 0, dimX, dimY, dimZ, inputArray);
+
+ final long kernelTimeStart = java.lang.System.currentTimeMillis();
+ final int rsRslt = s.reduce_addint(inputAllocation).get();
+ final long rsTimeEnd = java.lang.System.currentTimeMillis();
+
+ final boolean success =
+ result("addint3D",
+ new timing(javaTimeStart, javaTimeEnd, rsTimeStart,
+ copyTimeStart, kernelTimeStart, rsTimeEnd, inputAllocation),
+ javaRslt, rsRslt);
+ inputAllocation.destroy();
+ return success;
}
///////////////////////////////////////////////////////////////////
@@ -334,10 +377,13 @@
final Float2 javaVal = new Float2(inputArray[javaRslt.x], inputArray[javaRslt.y]);
final Float2 rsVal = new Float2(inputArray[rsRslt.x], inputArray[rsRslt.y]);
- return result("findMinAndMax",
- new timing(javaTimeStart, javaTimeEnd, rsTimeStart,
- copyTimeStart, kernelTimeStart, rsTimeEnd, inputAllocation),
- javaVal, rsVal);
+ final boolean success =
+ result("findMinAndMax",
+ new timing(javaTimeStart, javaTimeEnd, rsTimeStart,
+ copyTimeStart, kernelTimeStart, rsTimeEnd, inputAllocation),
+ javaVal, rsVal);
+ inputAllocation.destroy();
+ return success;
}
///////////////////////////////////////////////////////////////////
@@ -394,6 +440,7 @@
Log.i(TAG,
"fz: java input[" + javaRslt + "] == " + inputArray[javaRslt] +
", rs input[" + rsRslt + "] == " + inputArray[javaRslt] + ": " + status);
+ inputAllocation.destroy();
return success;
}
@@ -437,6 +484,7 @@
Log.i(TAG,
"fz2: java input[" + javaRslt.x + ", " + javaRslt.y + "] == " + javaCellVal +
", rs input[" + rsRslt.x + ", " + rsRslt.y + "] == " + rsCellVal + ": " + status);
+ inputAllocation.destroy();
return success;
}
@@ -483,6 +531,7 @@
Log.i(TAG,
"fz3: java input[" + javaRslt.x + ", " + javaRslt.y + ", " + javaRslt.z + "] == " + javaCellVal +
", rs input[" + rsRslt.x + ", " + rsRslt.y + ", " + rsRslt.z + "] == " + rsCellVal + ": " + status);
+ inputAllocation.destroy();
return success;
}
@@ -506,6 +555,10 @@
long[] outputArray = new long[histogramBucketCount];
for (int i = 0; i < histogramBucketCount; ++i)
outputArray[i] = outputArrayMistyped[i] & (long)0xffffffff;
+
+ inputAllocation.destroy();
+ outputAllocation.destroy();
+
return outputArray;
}
@@ -513,9 +566,9 @@
final byte[] inputArray = createInputArrayByte(size[0], seed);
final long[] javaRslt = histogram(RS, inputArray);
- _RS_ASSERT("javaRslt unexpected length: " + javaRslt.length, javaRslt.length == histogramBucketCount);
+ assertEquals("javaRslt length", histogramBucketCount, javaRslt.length);
final long[] rsRslt = s.reduce_histogram(inputArray).get();
- _RS_ASSERT("rsRslt unexpected length: " + rsRslt.length, rsRslt.length == histogramBucketCount);
+ assertEquals("rsRslt length", histogramBucketCount, rsRslt.length);
return result("histogram_array", new timing(size[0]), javaRslt, rsRslt);
}
@@ -526,7 +579,7 @@
final long javaTimeStart = java.lang.System.currentTimeMillis();
final long[] javaRslt = histogram(RS, inputArray);
final long javaTimeEnd = java.lang.System.currentTimeMillis();
- _RS_ASSERT("javaRslt unexpected length: " + javaRslt.length, javaRslt.length == histogramBucketCount);
+ assertEquals("javaRslt length", histogramBucketCount, javaRslt.length);
final long rsTimeStart = java.lang.System.currentTimeMillis();
@@ -539,13 +592,16 @@
final long kernelTimeStart = java.lang.System.currentTimeMillis();
final long[] rsRslt = s.reduce_histogram(inputAllocation).get();
final long rsTimeEnd = java.lang.System.currentTimeMillis();
- _RS_ASSERT("rsRslt unexpected length: " + rsRslt.length, rsRslt.length == histogramBucketCount);
+ assertEquals("rsRslt length", histogramBucketCount, rsRslt.length);
// NOTE: The "java time" is actually for the RenderScript histogram intrinsic
- return result("histogram",
- new timing(javaTimeStart, javaTimeEnd, rsTimeStart,
- copyTimeStart, kernelTimeStart, rsTimeEnd, inputAllocation),
- javaRslt, rsRslt);
+ final boolean success =
+ result("histogram",
+ new timing(javaTimeStart, javaTimeEnd, rsTimeStart,
+ copyTimeStart, kernelTimeStart, rsTimeEnd, inputAllocation),
+ javaRslt, rsRslt);
+ inputAllocation.destroy();
+ return success;
}
//-----------------------------------------------------------------
@@ -571,7 +627,7 @@
///////////////////////////////////////////////////////////////////
private long sumgcd(final int in1[], final int in2[]) {
- _RS_ASSERT("sumgcd input length mismatch", in1.length == in2.length);
+ assertEquals("sumgcd input lengths", in1.length, in2.length);
long sum = 0;
for (int i = 0; i < in1.length; ++i) {
@@ -614,15 +670,43 @@
final long rsRslt = s.reduce_sumgcd(inputAllocationA, inputAllocationB).get();
final long rsTimeEnd = java.lang.System.currentTimeMillis();
- return result("sumgcd",
- new timing(javaTimeStart, javaTimeEnd, rsTimeStart, copyTimeStart, kernelTimeStart, rsTimeEnd,
- inputAllocationA, inputAllocationB),
- javaRslt, rsRslt);
+ final boolean success =
+ result("sumgcd",
+ new timing(javaTimeStart, javaTimeEnd, rsTimeStart, copyTimeStart, kernelTimeStart, rsTimeEnd,
+ inputAllocationA, inputAllocationB),
+ javaRslt, rsRslt);
+ inputAllocationA.destroy();
+ inputAllocationB.destroy();
+ return success;
}
///////////////////////////////////////////////////////////////////
- public static final int maxSeedsPerTest = 10;
+ // Return an array of sparse integer values from 0 to maxVal inclusive.
+ // The array consists of all values k*sparseness (k a nonnegative integer)
+ // that are less than maxVal, and maxVal itself. For example, if maxVal
+ // is 20 and sparseness is 6, then the result is { 0, 6, 12, 18, 20 };
+ // and if maxVal is 20 and sparseness is 10, then the result is { 0, 10, 20 }.
+ //
+ // The elements of the array are sorted in increasing order.
+ //
+ // maxVal -- must be nonnegative
+ // sparseness -- must be positive
+ private static int[] computeSizePoints(int maxVal, int sparseness) {
+ assertTrue((maxVal >= 0) && (sparseness > 0));
+
+ final boolean maxValIsExtra = ((maxVal % sparseness) != 0);
+ int[] result = new int[1 + maxVal/sparseness + (maxValIsExtra ? 1 : 0)];
+
+ for (int i = 0; i * sparseness <= maxVal; ++i)
+ result[i] = i * sparseness;
+ if (maxValIsExtra)
+ result[result.length - 1] = maxVal;
+
+ return result;
+ }
+
+ private static final int maxSeedsPerTest = 10;
static interface Test {
// A test execution is characterized by two properties: A seed
@@ -641,12 +725,23 @@
};
static class TestDescription {
- public TestDescription(String myTestName, Test myTest, int mySeed, int[] myDefSize, int[] myLog2MaxSize) {
+ public TestDescription(String myTestName, Test myTest, int mySeed, int[] myDefSize,
+ int myLog2MaxSize, int mySparseness) {
+ testName = myTestName;
+ test = myTest;
+ seed = mySeed;
+ defSize = myDefSize;
+ log2MaxSize = myLog2MaxSize;
+ sparseness = mySparseness;
+ };
+
+ public TestDescription(String myTestName, Test myTest, int mySeed, int[] myDefSize, int myLog2MaxSize) {
testName = myTestName;
test = myTest;
seed = mySeed;
defSize = myDefSize;
log2MaxSize = myLog2MaxSize;
+ sparseness = 1;
};
public TestDescription(String myTestName, Test myTest, int mySeed, int[] myDefSize) {
@@ -654,7 +749,8 @@
test = myTest;
seed = mySeed;
defSize = myDefSize;
- log2MaxSize = null;
+ log2MaxSize = -1;
+ sparseness = 1;
};
public final String testName;
@@ -665,12 +761,21 @@
public final int seed;
// If we're only going to run the test once, what size should
- // we use?
+ // we use? The length of the array is the number of
+ // dimensions of the input data.
public final int[] defSize;
// If we're going to run the test over a range of sizes, what
- // is the maximum size to use?
- public final int[] log2MaxSize;
+ // is the maximum size to use? (This constrains the number of
+ // cells of the input data, not the number of cells ALONG A
+ // PARTICULAR DIMENSION of the input data.)
+ public final int log2MaxSize;
+
+ // If we're going to run the test "exhaustively" over a range
+ // of sizes, what is the size of a step through the range?
+ //
+ // For 1D, must be 1.
+ public final int sparseness;
};
private boolean run(TestDescription td, RenderScript RS, ScriptC_reduce s, int seed, int[] size) {
@@ -688,20 +793,21 @@
// alloc and array variants of the same test will use the same
// seed, in case results need to be compared.
- new TestDescription("addint1D", this::addint1D, 0, new int[]{100000}, new int[]{20}),
- new TestDescription("addint1D_array", this::addint1D_array, 0, new int[]{100000}, new int[]{20}),
- new TestDescription("addint2D", this::addint2D, 1, new int[]{450, 225}),
- new TestDescription("findMinAndMax", this::findMinAndMax, 3, new int[]{100000}, new int[]{20}),
- new TestDescription("findMinAndMaxArray", this::findMinAndMax_array, 3, new int[]{100000}, new int[]{20}),
- new TestDescription("fz", this::fz, 4, new int[]{100000}, new int[]{20}),
- new TestDescription("fz_array", this::fz_array, 4, new int[]{100000}, new int[]{20}),
- new TestDescription("fz2", this::fz2, 5, new int[]{225, 450}),
- new TestDescription("fz3", this::fz3, 6, new int[]{59, 48, 37}),
- new TestDescription("histogram", this::histogram, 7, new int[]{100000}, new int[]{20}),
- new TestDescription("histogram_array", this::histogram_array, 7, new int[]{100000}, new int[]{20}),
- // might want to add: new TestDescription("mode", this::mode, 8, new int[]{100000}, new int[]{20}),
- new TestDescription("mode_array", this::mode_array, 8, new int[]{100000}, new int[]{20}),
- new TestDescription("sumgcd", this::sumgcd, 9, new int[]{1 << 16}, new int[]{20})
+ new TestDescription("addint1D", this::addint1D, 0, new int[]{100000}, 20),
+ new TestDescription("addint1D_array", this::addint1D_array, 0, new int[]{100000}, 20),
+ new TestDescription("addint2D", this::addint2D, 1, new int[]{450, 225}, 20, 3),
+ new TestDescription("addint3D", this::addint3D, 2, new int[]{37, 48, 49}, 20, 5),
+ new TestDescription("findMinAndMax", this::findMinAndMax, 3, new int[]{100000}, 20),
+ new TestDescription("findMinAndMaxArray", this::findMinAndMax_array, 3, new int[]{100000}, 20),
+ new TestDescription("fz", this::fz, 4, new int[]{100000}, 20),
+ new TestDescription("fz_array", this::fz_array, 4, new int[]{100000}, 20),
+ new TestDescription("fz2", this::fz2, 5, new int[]{225, 450}, 20, 3),
+ new TestDescription("fz3", this::fz3, 6, new int[]{59, 48, 37}, 20, 5),
+ new TestDescription("histogram", this::histogram, 7, new int[]{100000}, 20),
+ new TestDescription("histogram_array", this::histogram_array, 7, new int[]{100000}, 20),
+ // might want to add: new TestDescription("mode", this::mode, 8, new int[]{100000}, 20),
+ new TestDescription("mode_array", this::mode_array, 8, new int[]{100000}, 20),
+ new TestDescription("sumgcd", this::sumgcd, 9, new int[]{1 << 16}, 20)
};
private boolean runCorrectnessQuick(RenderScript RS, ScriptC_reduce s) {
@@ -714,67 +820,281 @@
return pass;
}
+ // NOTE: Each test execution gets maxSeedsPerTest, and there are
+ // up to 3 + 5*log2MaxSize test executions in the full (as opposed
+ // to quick) correctness run of a particular test description, and
+ // we need an additional seed for pseudorandom size generation.
+ // Assuming log2MaxSize does not exceed 32, then it should be
+ // sufficient to reserve 1 + (3+5*32)*maxSeedsPerTest seeds per
+ // TestDescription.
+ //
+ // See runCorrectness1D().
+ private static final int seedsPerTestDescriptionCorrectness1D = 1 + (3+5*32)*maxSeedsPerTest;
+
+ // NOTE: Each test execution gets maxSeedsPerTest, and there are
+ // about 11*((log2MaxSize+1)**2) test executions in the full (as
+ // opposed to quick) correctness run of a particular test
+ // description, and we need a seed for pseudorandom size
+ // generation. Assuming log2MaxSize does not exceed 32, then it
+ // should be sufficient to reserve 1 + 11*1089*maxSeedsPerTest
+ // seeds per TestDescription.
+ //
+ // See runCorrectness2D().
+ private static final int seedsPerTestDescriptionCorrectness2D = 1 + (11*1089)*maxSeedsPerTest;
+
+ // NOTE: Each test execution gets maxSeedsPerTest, and there are
+ // about 27*((log2MaxSize+1)**3) + 6*((log2MaxSize+1)**2) test
+ // executions in the full (as opposed to quick) correctness run of
+ // a particular test description, and we need a seed for (c).
+ // Assuming log2MaxSize does not exceed 32, then it should
+ // be sufficient to reserve 1 + (27*(33**3) + 6*(33**2))*maxSeedsPerTest
+ // seeds per TestDescription, which can be simplified upwards to
+ // 1 + (28*(33**3))*maxSeedsPerTest seeds per TestDescription.
+ private static final int seedsPerTestDescriptionCorrectness3D = 1 + (28*35937)*maxSeedsPerTest;
+
+ // Each test execution gets a certain number of seeds, and a full
+ // (as opposed to quick) correctness run of a particular
+ // TestDescription consists of some number of executions (each of
+ // which needs up to maxSeedsPerTest) and may require some
+ // additional seeds.
+ private static final int seedsPerTestDescriptionCorrectness =
+ Math.max(seedsPerTestDescriptionCorrectness1D,
+ Math.max(seedsPerTestDescriptionCorrectness2D,
+ seedsPerTestDescriptionCorrectness3D));
+
private boolean runCorrectness(RenderScript RS, ScriptC_reduce s) {
boolean pass = true;
for (TestDescription td : correctnessTests) {
- if (td.log2MaxSize == null) // TODO: Eventually this should never happen?
- continue;
+ switch (td.defSize.length) {
+ case 1:
+ pass &= runCorrectness1D(td, RS, s);
+ break;
+ case 2:
+ pass &= runCorrectness2D(td, RS, s);
+ break;
+ case 3:
+ pass &= runCorrectness3D(td, RS, s);
+ break;
+ default:
+ assertTrue("unexpected defSize.length " + td.defSize.length, false);
+ pass &= false;
+ break;
+ }
+ }
- if (td.log2MaxSize.length == 1) {
- final int log2MaxSize = td.log2MaxSize[0];
- // We will execute the test with the following sizes:
- // (a) Each power of 2 from zero (2**0) up to log2MaxSize (2**log2MaxSize)
- // (b) Each size from (a) +/-1
- // (c) 2 random sizes between adjacent points in (a)
- int[] testSizes = new int[
- /* a */ (1 + log2MaxSize) +
- /* b */ 2*(1 + log2MaxSize) +
- /* c */ 2*log2MaxSize];
+ return pass;
+ }
- // NOTE: Each test execution gets maxSeedsPerTest, and
- // there are up to 3 + 5*log2MaxSize test executions
- // of a test, and we need a seed for (c). Assuming
- // log2MaxSize does not exceed 32, then it should be
- // sufficient to reserve 1 + 5*32*maxSeedsPerTest seeds
- // per TestDescription.
- final int seedForPickingTestSizes = td.seed * (1 + 5*32*maxSeedsPerTest);
+ private boolean runCorrectness1D(TestDescription td, RenderScript RS, ScriptC_reduce s) {
+ assertEquals(1, td.sparseness);
+ final int log2MaxSize = td.log2MaxSize;
+ assertTrue(log2MaxSize >= 0);
- int nextTestIdx = 0;
+ boolean pass = true;
- // Fill in (a) and (b)
- for (int i = 0; i <= log2MaxSize; ++i) {
- final int pwrOf2 = 1 << i;
- testSizes[nextTestIdx++] = pwrOf2; /* a */
- testSizes[nextTestIdx++] = pwrOf2 - 1; /* b */
- testSizes[nextTestIdx++] = pwrOf2 + 1; /* b */
+ // We will execute the test with the following sizes:
+ // (a) Each power of 2 from zero (2**0) up to log2MaxSize (2**log2MaxSize)
+ // (b) Each size from (a) +/-1
+ // (c) 2 random sizes between each pair of adjacent points in (a)
+ int[] testSizes = new int[
+ /* a */ (1 + log2MaxSize) +
+ /* b */ 2*(1 + log2MaxSize) +
+ /* c */ 2*log2MaxSize];
+ // See seedsPerTestDescriptionCorrectness1D
+
+ final int seedForPickingTestSizes = td.seed * seedsPerTestDescriptionCorrectness;
+
+ int nextTestIdx = 0;
+
+ // Fill in (a) and (b)
+ for (int i = 0; i <= log2MaxSize; ++i) {
+ final int pwrOf2 = 1 << i;
+ testSizes[nextTestIdx++] = pwrOf2; /* a */
+ testSizes[nextTestIdx++] = pwrOf2 - 1; /* b */
+ testSizes[nextTestIdx++] = pwrOf2 + 1; /* b */
+ }
+
+ // Fill in (c)
+ Random r = new Random(seedForPickingTestSizes);
+ for (int i = 0; i < log2MaxSize; ++i) {
+ final int lo = (1 << i) + 1;
+ final int hi = 1 << (i + 1);
+
+ if (lo < hi) {
+ for (int j = 0; j < 2; ++j) {
+ testSizes[nextTestIdx++] = r.nextInt(hi - lo) + lo;
}
+ }
+ }
- // Fill in (c)
- Random r = new Random(seedForPickingTestSizes);
- for (int i = 0; i < log2MaxSize; ++i) {
- final int lo = (1 << i) + 1;
- final int hi = 1 << (i + 1);
+ Arrays.sort(testSizes);
- if (lo < hi) {
- for (int j = 0; j < 2; ++j) {
- testSizes[nextTestIdx++] = r.nextInt(hi - lo) + lo;
- }
- }
- }
+ int[] lastTestSizeArg = new int[]{-1};
+ for (int i = 0; i < testSizes.length; ++i) {
+ if ((testSizes[i] > 0) && (testSizes[i] != lastTestSizeArg[0])) {
+ lastTestSizeArg[0] = testSizes[i];
+ final int seedForTestExecution = seedForPickingTestSizes + 1 + i*maxSeedsPerTest;
+ pass &= run(td, RS, s, seedForTestExecution, lastTestSizeArg);
+ }
+ }
- Arrays.sort(testSizes);
+ return pass;
+ }
- int[] lastTestSizeArg = new int[]{-1};
- for (int i = 0; i < testSizes.length; ++i) {
- if ((testSizes[i] > 0) && (testSizes[i] != lastTestSizeArg[0])) {
- lastTestSizeArg[0] = testSizes[i];
- final int seedForTestExecution = seedForPickingTestSizes + 1 + i*maxSeedsPerTest;
- pass &= run(td, RS, s, seedForTestExecution, lastTestSizeArg);
+ private boolean runCorrectness2D(TestDescription td, RenderScript RS, ScriptC_reduce s) {
+ final int log2MaxSize = td.log2MaxSize, maxSize = 1 << log2MaxSize, sparseness = td.sparseness;
+ assertTrue((log2MaxSize >= 0) && (sparseness >= 1));
+
+ boolean pass = true;
+
+ final int[] sizePoints = computeSizePoints(log2MaxSize, sparseness);
+
+ // We will execute the test with the following sizes:
+ // (a) Each dimension at a power of 2 from sizePoints[]
+ /// such that the sum of the exponents does not exceed
+ // log2MaxSize
+ // (b) Each size from (a) with one or both dimensions +/-1,
+ // except where this would exceed 2**log2MaxSize
+ // (c) Approximately 2*(sizePoints.length**2) random sizes
+ ArrayList<int[]> testSizesList = new ArrayList<int[]>();
+ // See seedsPerTestDescriptionCorrectness2D
+
+ final int seedForPickingTestSizes = td.seed * seedsPerTestDescriptionCorrectness;
+
+ // Fill in (a) and (b)
+ for (int i : sizePoints) {
+ final int iPwrOf2 = 1 << i;
+ for (int iDelta = -1; iDelta <= 1; ++iDelta) {
+ final int iSize = iPwrOf2 + iDelta;
+ for (int j : sizePoints) {
+ final int jPwrOf2 = 1 << j;
+ for (int jDelta = -1; jDelta <= 1; ++jDelta) {
+ final int jSize = jPwrOf2 + jDelta;
+ if ((long)iSize * (long)jSize <= maxSize)
+ testSizesList.add(new int[]{iSize, jSize});
}
}
}
- // TODO: lengths 2 and 3, and assert otherwise
+ }
+
+ // Fill in (c)
+ Random r = new Random(seedForPickingTestSizes);
+ for (int i : sizePoints) {
+ for (int j : sizePoints) {
+ final int size0 = 1 + r.nextInt(1 << i);
+ final int size1 = 1 + r.nextInt(maxSize / size0);
+
+ testSizesList.add(new int[]{size0, size1});
+ testSizesList.add(new int[]{size1, size0});
+ }
+ }
+
+ int[][] testSizes = testSizesList.toArray(new int[0][]);
+ Arrays.sort(testSizes,
+ (a, b) -> {
+ final int comp0 = ((Integer)a[0]).compareTo(b[0]);
+ return (comp0 != 0 ? comp0 : ((Integer)a[1]).compareTo(b[1]));
+ });
+
+ int[] lastTestSizeArg = null;
+ for (int i = 0; i < testSizes.length; ++i) {
+ if ((testSizes[i][0] <= 0) || (testSizes[i][1] <= 0))
+ continue;
+ if ((lastTestSizeArg != null) &&
+ (testSizes[i][0] == lastTestSizeArg[0]) &&
+ (testSizes[i][1] == lastTestSizeArg[1]))
+ continue;
+ lastTestSizeArg = testSizes[i];
+ final int seedForTestExecution = seedForPickingTestSizes + 1 + i*maxSeedsPerTest;
+ pass &= run(td, RS, s, seedForTestExecution, lastTestSizeArg);
+ }
+
+ return pass;
+ }
+
+ private boolean runCorrectness3D(TestDescription td, RenderScript RS, ScriptC_reduce s) {
+ final int log2MaxSize = td.log2MaxSize, maxSize = 1 << log2MaxSize, sparseness = td.sparseness;
+ assertTrue((log2MaxSize >= 0) && (sparseness >= 1));
+
+ boolean pass = true;
+
+ final int[] sizePoints = computeSizePoints(log2MaxSize, sparseness);
+
+ // We will execute the test with the following sizes:
+ // (a) Each dimension at a power of 2 from sizePoints[]
+ /// such that the sum of the exponents does not exceed
+ // log2MaxSize
+ // (b) Each size from (a) with one or both dimensions +/-1,
+ // except where this would exceed 2**log2MaxSize
+ // (c) Approximately 6*(sizePoints.length**2) random sizes
+ ArrayList<int[]> testSizesList = new ArrayList<int[]>();
+ // See seedsPerTestDescriptionCorrectness3D
+
+ final int seedForPickingTestSizes = td.seed * seedsPerTestDescriptionCorrectness;
+
+ // Fill in (a) and (b)
+ for (int i : sizePoints) {
+ final int iPwrOf2 = 1 << i;
+ for (int iDelta = -1; iDelta <= 1; ++iDelta) {
+ final int iSize = iPwrOf2 + iDelta;
+ for (int j : sizePoints) {
+ final int jPwrOf2 = 1 << j;
+ for (int jDelta = -1; jDelta <= 1; ++jDelta) {
+ final int jSize = jPwrOf2 + jDelta;
+ for (int k : sizePoints) {
+ final int kPwrOf2 = 1 << k;
+ for (int kDelta = -1; kDelta <= 1; ++kDelta) {
+ final int kSize = kPwrOf2 + kDelta;
+ if ((long)iSize * (long)jSize * (long)kSize <= maxSize)
+ testSizesList.add(new int[]{iSize, jSize, kSize});
+ }
+ }
+ }
+ }
+ }
+ }
+
+ // Fill in (c)
+ Random r = new Random(seedForPickingTestSizes);
+ for (int i : sizePoints) {
+ for (int j : sizePoints) {
+ final int size0 = 1 + r.nextInt(1 << i);
+ final int size1 = 1 + r.nextInt(Math.min(1 << j, maxSize / size0));
+ final int size2 = 1 + r.nextInt(maxSize / (size0*size1));
+
+ testSizesList.add(new int[]{size0, size1, size2});
+ testSizesList.add(new int[]{size0, size2, size1});
+ testSizesList.add(new int[]{size1, size0, size2});
+ testSizesList.add(new int[]{size1, size2, size0});
+ testSizesList.add(new int[]{size2, size0, size1});
+ testSizesList.add(new int[]{size2, size1, size0});
+ }
+ }
+
+ int[][] testSizes = testSizesList.toArray(new int[0][]);
+ Arrays.sort(testSizes,
+ (a, b) -> {
+ int comp = ((Integer)a[0]).compareTo(b[0]);
+ if (comp == 0)
+ comp = ((Integer)a[1]).compareTo(b[1]);
+ if (comp == 0)
+ comp = ((Integer)a[2]).compareTo(b[2]);
+ return comp;
+ });
+
+ int[] lastTestSizeArg = null;
+ for (int i = 0; i < testSizes.length; ++i) {
+ if ((testSizes[i][0] <= 0) || (testSizes[i][1] <= 0) || (testSizes[i][2] <= 0))
+ continue;
+ if ((lastTestSizeArg != null) &&
+ (testSizes[i][0] == lastTestSizeArg[0]) &&
+ (testSizes[i][1] == lastTestSizeArg[1]) &&
+ (testSizes[i][2] == lastTestSizeArg[2]))
+ continue;
+ lastTestSizeArg = testSizes[i];
+ final int seedForTestExecution = seedForPickingTestSizes + 1 + i*maxSeedsPerTest;
+ pass &= run(td, RS, s, seedForTestExecution, lastTestSizeArg);
}
return pass;
@@ -783,6 +1103,7 @@
private final TestDescription[] performanceTests = {
new TestDescription("addint1D", this::addint1D, 0, new int[]{100000 << 10}),
new TestDescription("addint2D", this::addint2D, 1, new int[]{450 << 5, 225 << 5}),
+ new TestDescription("addint3D", this::addint3D, 2, new int[]{37 << 3, 48 << 3, 49 << 3}),
new TestDescription("findMinAndMax", this::findMinAndMax, 3, new int[]{100000 << 9}),
new TestDescription("fz", this::fz, 4, new int[]{100000 << 10}),
new TestDescription("fz2", this::fz2, 5, new int[]{225 << 5, 450 << 5}),
@@ -825,3 +1146,5 @@
failTest();
}
}
+
+// TODO: Add machinery for easily running fuller (i.e., non-sparse) testing.
diff --git a/java/tests/RsTest/src/com/android/rs/test/UT_reduce_backward.java b/java/tests/RsTest/src/com/android/rs/test/UT_reduce_backward.java
index 6a50d2b..e42b200 100644
--- a/java/tests/RsTest/src/com/android/rs/test/UT_reduce_backward.java
+++ b/java/tests/RsTest/src/com/android/rs/test/UT_reduce_backward.java
@@ -14,10 +14,10 @@
* limitations under the License.
*/
-/* Same as UT_reduce.java, except this test case exercises
- * pragmas after the functions (backward reference), and the other
- * test case exercises the pragmas before the functions (forward
- * reference).
+/* This is a much simpler version of UT_reduce.java that
+ * exercises pragmas after the functions (backward reference),
+ * whereas the other test case exercises the pragmas before the
+ * functions (forward reference).
*/
package com.android.rs.test;
@@ -74,6 +74,16 @@
return success;
}
+ private boolean result(String testName, Float2 javaRslt, Float2 rsRslt) {
+ final boolean success = (javaRslt.x == rsRslt.x) && (javaRslt.y == rsRslt.y);
+ Log.i(TAG,
+ testName +
+ ": java (" + javaRslt.x + ", " + javaRslt.y + ")" +
+ ", rs (" + rsRslt.x + ", " + rsRslt.y + ")" +
+ ": " + (success ? "PASSED" : "FAILED"));
+ return success;
+ }
+
private boolean result(String testName, Int2 javaRslt, Int2 rsRslt) {
final boolean success = (javaRslt.x == rsRslt.x) && (javaRslt.y == rsRslt.y);
Log.i(TAG,
@@ -145,7 +155,13 @@
final Int2 javaRslt = findMinAndMax(input);
final Int2 rsRslt = s.reduce_findMinAndMax(input).get();
- return result("findMinAndMax", javaRslt, rsRslt);
+ // Note that the Java and RenderScript algorithms are not
+ // guaranteed to find the same cells -- but they should
+ // find cells of the same value.
+ final Float2 javaVal = new Float2(input[javaRslt.x], input[javaRslt.y]);
+ final Float2 rsVal = new Float2(input[rsRslt.x], input[rsRslt.y]);
+
+ return result("findMinAndMax", javaVal, rsVal);
}
///////////////////////////////////////////////////////////////////
diff --git a/java/tests/RsTest/src/com/android/rs/test/reduce.rs b/java/tests/RsTest/src/com/android/rs/test/reduce.rs
index 97b45e0..0947d41 100644
--- a/java/tests/RsTest/src/com/android/rs/test/reduce.rs
+++ b/java/tests/RsTest/src/com/android/rs/test/reduce.rs
@@ -121,7 +121,7 @@
}
static void fz3Combine(int3 *accum, const int3 *accum2) {
- if (accum->x >= 0) *accum = *accum2;
+ if (accum2->x >= 0) *accum = *accum2;
}
/////////////////////////////////////////////////////////////////////////