From 06cd5344a806040c2e836dfa7a808f84d0de1215 Mon Sep 17 00:00:00 2001 From: Manolis Papadakis Date: Mon, 14 Aug 2023 14:14:28 -0700 Subject: [PATCH] Fix random test failures in CPU-only runs (#1025) * Anticipate some test failures when cuRand is not available * Ensure input to unstable sort algorithms contains no duplicates * Add mergesort to stable sort methods --- cunumeric/random/legacy.py | 3 +-- tests/integration/test_argsort.py | 31 +++++++++++++---------- tests/integration/test_random_creation.py | 11 ++++++-- 3 files changed, 27 insertions(+), 18 deletions(-) diff --git a/cunumeric/random/legacy.py b/cunumeric/random/legacy.py index c0568136b..4070653e8 100644 --- a/cunumeric/random/legacy.py +++ b/cunumeric/random/legacy.py @@ -111,7 +111,6 @@ def randint( -------- Multiple GPUs, Multiple CPUs """ - if not isinstance(low, int): raise NotImplementedError("'low' must be an integer") if high is not None and not isinstance(high, int): @@ -126,7 +125,7 @@ def randint( dtype = np.dtype(np.int64) # TODO: randint must support unsigned integer dtypes as well if dtype.kind != "i": - raise TypeError( + raise NotImplementedError( "cunumeric.random.randint must be given an integer dtype" ) if isinstance(size, int): diff --git a/tests/integration/test_argsort.py b/tests/integration/test_argsort.py index bdc816c04..b36de0d16 100644 --- a/tests/integration/test_argsort.py +++ b/tests/integration/test_argsort.py @@ -58,8 +58,9 @@ (DIM, DIM, DIM), ] -SORT_TYPES = ["quicksort", "mergesort", "stable"] -UNSTABLE_SORT_TYPE = ["heapsort"] +STABLE_SORT_TYPES = ["stable", "mergesort"] +UNSTABLE_SORT_TYPES = ["heapsort", "quicksort"] +SORT_TYPES = STABLE_SORT_TYPES + UNSTABLE_SORT_TYPES class TestArgSort(object): @@ -137,7 +138,7 @@ def test_basic_axis(self, size): assert np.array_equal(res_num, res_np) @pytest.mark.parametrize("size", SIZES) - @pytest.mark.parametrize("sort_type", SORT_TYPES) + @pytest.mark.parametrize("sort_type", STABLE_SORT_TYPES) def test_basic_axis_sort_type(self, size, sort_type): arr_np = np.random.randint(-100, 100, size) arr_num = num.array(arr_np) @@ -146,13 +147,14 @@ def test_basic_axis_sort_type(self, size, sort_type): res_num = num.argsort(arr_num, axis=axis, kind=sort_type) assert np.array_equal(res_num, res_np) - @pytest.mark.xfail @pytest.mark.parametrize("size", SIZES) - @pytest.mark.parametrize("sort_type", UNSTABLE_SORT_TYPE) + @pytest.mark.parametrize("sort_type", UNSTABLE_SORT_TYPES) def test_basic_axis_sort_type_unstable(self, size, sort_type): - # intermittent failed due to - # https://github.com/nv-legate/cunumeric/issues/782 - arr_np = np.random.randint(-100, 100, size) + # have to guarantee unique values in input + # see https://github.com/nv-legate/cunumeric/issues/782 + arr_np = np.arange(np.prod(size)) + np.random.shuffle(arr_np) + arr_np = arr_np.reshape(size) arr_num = num.array(arr_np) for axis in range(-arr_np.ndim + 1, arr_np.ndim): res_np = np.argsort(arr_np, axis=axis, kind=sort_type) @@ -171,7 +173,7 @@ def test_arr_basic_axis(self, size): assert np.array_equal(arr_np_copy, arr_num_copy) @pytest.mark.parametrize("size", SIZES) - @pytest.mark.parametrize("sort_type", SORT_TYPES) + @pytest.mark.parametrize("sort_type", STABLE_SORT_TYPES) def test_arr_basic_axis_sort(self, size, sort_type): arr_np = np.random.randint(-100, 100, size) arr_num = num.array(arr_np) @@ -182,13 +184,14 @@ def test_arr_basic_axis_sort(self, size, sort_type): arr_num_copy.argsort(axis=axis, kind=sort_type) assert np.array_equal(arr_np_copy, arr_num_copy) - @pytest.mark.xfail @pytest.mark.parametrize("size", SIZES) - @pytest.mark.parametrize("sort_type", UNSTABLE_SORT_TYPE) + @pytest.mark.parametrize("sort_type", UNSTABLE_SORT_TYPES) def test_arr_basic_axis_sort_unstable(self, size, sort_type): - # intermittent failed due to - # https://github.com/nv-legate/cunumeric/issues/782 - arr_np = np.random.randint(-100, 100, size) + # have to guarantee unique values in input + # see https://github.com/nv-legate/cunumeric/issues/782 + arr_np = np.arange(np.prod(size)) + np.random.shuffle(arr_np) + arr_np = arr_np.reshape(size) arr_num = num.array(arr_np) for axis in range(-arr_num.ndim + 1, arr_num.ndim): arr_np_copy = arr_np diff --git a/tests/integration/test_random_creation.py b/tests/integration/test_random_creation.py index a69d96b11..f4bdecec7 100644 --- a/tests/integration/test_random_creation.py +++ b/tests/integration/test_random_creation.py @@ -246,12 +246,15 @@ def test_randint_float_range(low, high): @pytest.mark.xfail( - not EAGER_TEST, reason="cuNumeric raises NotImplementedError" + not num.runtime.has_curand or not EAGER_TEST, + reason="cuNumeric raises NotImplementedError", ) @pytest.mark.parametrize("size", ALL_RNG_SIZES, ids=str) @pytest.mark.parametrize("low, high", [(1000, 65535), (0, 1024)], ids=str) @pytest.mark.parametrize("dtype", UINT_DTYPES, ids=str) def test_randint_uint(low, high, dtype, size): + # NotImplementedError: cunumeric.random.randint must be given an integer + # dtype # NotImplementedError: type for random.integers has to be int64 or int32 # or int16 arr_np, arr_num = gen_random_from_both( @@ -287,7 +290,8 @@ def test_randint_distribution(low, high, size, dtype): @pytest.mark.xfail( - not EAGER_TEST, reason="cuNumeric raises NotImplementedError" + not num.runtime.has_curand or not EAGER_TEST, + reason="cuNumeric raises NotImplementedError", ) @pytest.mark.parametrize("size", (1024, 1025)) def test_randint_bool(size): @@ -297,6 +301,9 @@ def test_randint_bool(size): arr_num, np.mean(arr_np), np.std(arr_np), mean_tol=0.05 ) # NumPy pass + # cuNumeric not num.runtime.has_curand: + # NotImplementedError: cunumeric.random.randint must be given an integer + # dtype # cuNumeric LEGATE_TEST=1 or size > 1024: # NotImplementedError: type for random.integers has to be int64 or int32 # or int16