From a81357907916bf0c3ebdecbc0c5c6ff96d5cdb3b Mon Sep 17 00:00:00 2001 From: Ryosuke Okuta Date: Thu, 16 Jul 2020 04:12:43 +0900 Subject: [PATCH 1/6] Fix different dtype input case in histogram --- .../statistics_tests/test_histogram.py | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/tests/cupy_tests/statistics_tests/test_histogram.py b/tests/cupy_tests/statistics_tests/test_histogram.py index 9d1395259aa..c1646b9b1ff 100644 --- a/tests/cupy_tests/statistics_tests/test_histogram.py +++ b/tests/cupy_tests/statistics_tests/test_histogram.py @@ -364,6 +364,23 @@ def test_histogram_range_float(self, xp, dtype): assert int(h.sum()) == 10 return h, b + @testing.for_all_dtypes_combination(['dtype_a', 'dtype_b'], + no_bool=True, no_complex=True) + @testing.numpy_cupy_array_equal() + def test_histogram_with_bins(self, xp, dtype_a, dtype_b): + x = testing.shaped_arange((10,), xp, dtype_a) + bins = testing.shaped_arange((10,), xp, dtype_a) + + if xp is numpy: + return xp.histogram(x, bins)[0] + + # xp is cupy, first ensure we really use CUB + cub_func = 'cupy.statistics.histogram.cub.device_histogram' + with testing.AssertFunctionIsCalled(cub_func): + xp.histogram(x, bins) + # ...then perform the actual computation + return xp.histogram(x, bins)[0] + @testing.gpu @testing.parameterize(*testing.product( From 0ac2c4dcaabbf103b450232648712bbaa5ca15eb Mon Sep 17 00:00:00 2001 From: Ryosuke Okuta Date: Thu, 16 Jul 2020 10:27:44 +0900 Subject: [PATCH 2/6] Update tests/cupy_tests/statics_tests/test_histogram.py Co-authored-by: Leo Fang --- tests/cupy_tests/statistics_tests/test_histogram.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/cupy_tests/statistics_tests/test_histogram.py b/tests/cupy_tests/statistics_tests/test_histogram.py index c1646b9b1ff..f236ebb1516 100644 --- a/tests/cupy_tests/statistics_tests/test_histogram.py +++ b/tests/cupy_tests/statistics_tests/test_histogram.py @@ -369,7 +369,7 @@ def test_histogram_range_float(self, xp, dtype): @testing.numpy_cupy_array_equal() def test_histogram_with_bins(self, xp, dtype_a, dtype_b): x = testing.shaped_arange((10,), xp, dtype_a) - bins = testing.shaped_arange((10,), xp, dtype_a) + bins = testing.shaped_arange((4,), xp, dtype_a) if xp is numpy: return xp.histogram(x, bins)[0] From 6d476642903c54646484a8e0974cb3b428e4b0ec Mon Sep 17 00:00:00 2001 From: Ryosuke Okuta Date: Thu, 16 Jul 2020 10:46:05 +0900 Subject: [PATCH 3/6] Fix --- cupy/_statistics/histogram.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/cupy/_statistics/histogram.py b/cupy/_statistics/histogram.py index 2c26b47a217..9ec05f9bd49 100644 --- a/cupy/_statistics/histogram.py +++ b/cupy/_statistics/histogram.py @@ -224,7 +224,8 @@ def histogram(x, bins=10, range=None, weights=None, density=False): # Need to ensure the dtype of bin_edges as it's needed for both # the CUB call and the correction later assert isinstance(bin_edges, cupy.ndarray) - if numpy.issubdtype(x.dtype, numpy.integer): + if (isinstance(bins, int) + or numpy.issubdtype(x.dtype, numpy.integer)): bin_type = numpy.float else: bin_type = numpy.result_type(bin_edges.dtype, x.dtype) @@ -233,6 +234,7 @@ def histogram(x, bins=10, range=None, weights=None, density=False): bin_type = numpy.float32 x = x.astype(bin_type, copy=False) acc_bin_edge = bin_edges.astype(bin_type, copy=True) + # CUB's upper bin boundary is exclusive for all bins, including # the last bin, so we must shift it to comply with NumPy if x.dtype.kind in 'ui': From 40dd5d42537cca76e0a1ea8c53bc2e75cd394aa6 Mon Sep 17 00:00:00 2001 From: Ryosuke Okuta Date: Thu, 16 Jul 2020 10:46:58 +0900 Subject: [PATCH 4/6] Fix and add test --- .../statistics_tests/test_histogram.py | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/tests/cupy_tests/statistics_tests/test_histogram.py b/tests/cupy_tests/statistics_tests/test_histogram.py index f236ebb1516..e4f3b967b1e 100644 --- a/tests/cupy_tests/statistics_tests/test_histogram.py +++ b/tests/cupy_tests/statistics_tests/test_histogram.py @@ -369,7 +369,7 @@ def test_histogram_range_float(self, xp, dtype): @testing.numpy_cupy_array_equal() def test_histogram_with_bins(self, xp, dtype_a, dtype_b): x = testing.shaped_arange((10,), xp, dtype_a) - bins = testing.shaped_arange((4,), xp, dtype_a) + bins = testing.shaped_arange((4,), xp, dtype_b) if xp is numpy: return xp.histogram(x, bins)[0] @@ -381,6 +381,23 @@ def test_histogram_with_bins(self, xp, dtype_a, dtype_b): # ...then perform the actual computation return xp.histogram(x, bins)[0] + @testing.for_all_dtypes_combination(['dtype_a', 'dtype_b'], + no_bool=True, no_complex=True) + @testing.numpy_cupy_array_equal() + def test_histogram_with_bins2(self, xp, dtype_a, dtype_b): + x = testing.shaped_arange((10,), xp, dtype_a) + bins = testing.shaped_arange((4,), xp, dtype_b) + + if xp is numpy: + return xp.histogram(x, bins)[1] + + # xp is cupy, first ensure we really use CUB + cub_func = 'cupy.statistics.histogram.cub.device_histogram' + with testing.AssertFunctionIsCalled(cub_func): + xp.histogram(x, bins) + # ...then perform the actual computation + return xp.histogram(x, bins)[1] + @testing.gpu @testing.parameterize(*testing.product( From 79bdbc3386eabad27820c8877000dec1c0b14fa3 Mon Sep 17 00:00:00 2001 From: Ryosuke Okuta Date: Wed, 26 Aug 2020 13:42:56 +0900 Subject: [PATCH 5/6] Fix --- cupy/_statistics/histogram.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/cupy/_statistics/histogram.py b/cupy/_statistics/histogram.py index 9ec05f9bd49..2c26b47a217 100644 --- a/cupy/_statistics/histogram.py +++ b/cupy/_statistics/histogram.py @@ -224,8 +224,7 @@ def histogram(x, bins=10, range=None, weights=None, density=False): # Need to ensure the dtype of bin_edges as it's needed for both # the CUB call and the correction later assert isinstance(bin_edges, cupy.ndarray) - if (isinstance(bins, int) - or numpy.issubdtype(x.dtype, numpy.integer)): + if numpy.issubdtype(x.dtype, numpy.integer): bin_type = numpy.float else: bin_type = numpy.result_type(bin_edges.dtype, x.dtype) @@ -234,7 +233,6 @@ def histogram(x, bins=10, range=None, weights=None, density=False): bin_type = numpy.float32 x = x.astype(bin_type, copy=False) acc_bin_edge = bin_edges.astype(bin_type, copy=True) - # CUB's upper bin boundary is exclusive for all bins, including # the last bin, so we must shift it to comply with NumPy if x.dtype.kind in 'ui': From 306ed6feca731211582a54480d6d8ec498248ccd Mon Sep 17 00:00:00 2001 From: Ryosuke Okuta Date: Wed, 16 Sep 2020 16:52:43 +0900 Subject: [PATCH 6/6] Fix module name --- tests/cupy_tests/statistics_tests/test_histogram.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/cupy_tests/statistics_tests/test_histogram.py b/tests/cupy_tests/statistics_tests/test_histogram.py index e4f3b967b1e..2f2a8a55be0 100644 --- a/tests/cupy_tests/statistics_tests/test_histogram.py +++ b/tests/cupy_tests/statistics_tests/test_histogram.py @@ -375,7 +375,7 @@ def test_histogram_with_bins(self, xp, dtype_a, dtype_b): return xp.histogram(x, bins)[0] # xp is cupy, first ensure we really use CUB - cub_func = 'cupy.statistics.histogram.cub.device_histogram' + cub_func = 'cupy._statistics.histogram.cub.device_histogram' with testing.AssertFunctionIsCalled(cub_func): xp.histogram(x, bins) # ...then perform the actual computation @@ -392,7 +392,7 @@ def test_histogram_with_bins2(self, xp, dtype_a, dtype_b): return xp.histogram(x, bins)[1] # xp is cupy, first ensure we really use CUB - cub_func = 'cupy.statistics.histogram.cub.device_histogram' + cub_func = 'cupy._statistics.histogram.cub.device_histogram' with testing.AssertFunctionIsCalled(cub_func): xp.histogram(x, bins) # ...then perform the actual computation