import unittest import numpy import pytest import cupy from cupy import testing from cupy.testing._loops import _wraps_partial import cupyx def numpy_cupyx_array_equal(target_func, name='func'): _mod = (cupy, numpy) _numpy_funcs = { 'empty': numpy.empty, 'empty_like': numpy.empty_like, 'zeros': numpy.zeros, 'zeros_like': numpy.zeros_like, } _cupy_funcs = { 'empty': cupyx.empty_pinned, 'empty_like': cupyx.empty_like_pinned, 'zeros': cupyx.zeros_pinned, 'zeros_like': cupyx.zeros_like_pinned, } def _get_test_func(xp, func): if xp is numpy: return _numpy_funcs[func] elif xp is cupy: return _cupy_funcs[func] else: assert False def _check_pinned_mem_used(a, xp): if xp is cupy: assert isinstance(a.base, cupy.cuda.PinnedMemoryPointer) assert a.base.ptr == a.ctypes.data def decorator(impl): @_wraps_partial(impl, name) def test_func(self, *args, **kw): out = [] for xp in _mod: func = _get_test_func(xp, target_func) kw[name] = func a = impl(self, *args, **kw) _check_pinned_mem_used(a, xp) out.append(a) numpy.testing.assert_array_equal(*out) return test_func return decorator # test_empty_scalar_none is removed # test_zeros_scalar_none is removed class TestBasic(unittest.TestCase): @testing.for_CF_orders() @testing.for_all_dtypes() @numpy_cupyx_array_equal(target_func='empty') def test_empty(self, dtype, order, func): a = func((2, 3, 4), dtype=dtype, order=order) a.fill(0) return a @testing.slow def test_empty_huge_size(self): a = cupyx.empty_pinned((1024, 2048, 1024), dtype='b') a.fill(123) assert (a == 123).all() # Free huge memory for slow test del a cupy.get_default_pinned_memory_pool().free_all_blocks() @testing.slow def test_empty_huge_size_fill0(self): a = cupyx.empty_pinned((1024, 2048, 1024), dtype='b') a.fill(0) assert (a == 0).all() # Free huge memory for slow test del a cupy.get_default_pinned_memory_pool().free_all_blocks() @testing.for_CF_orders() @testing.for_all_dtypes() @numpy_cupyx_array_equal(target_func='empty') def test_empty_scalar(self, dtype, order, func): a = func((), dtype=dtype, order=order) a.fill(0) return a @testing.for_CF_orders() @testing.for_all_dtypes() @numpy_cupyx_array_equal(target_func='empty') def test_empty_int(self, dtype, order, func): a = func(3, dtype=dtype, order=order) a.fill(0) return a @testing.slow def test_empty_int_huge_size(self): a = cupyx.empty_pinned(2 ** 31, dtype='b') a.fill(123) assert (a == 123).all() # Free huge memory for slow test del a cupy.get_default_pinned_memory_pool().free_all_blocks() @testing.slow def test_empty_int_huge_size_fill0(self): a = cupyx.empty_pinned(2 ** 31, dtype='b') a.fill(0) assert (a == 0).all() # Free huge memory for slow test del a cupy.get_default_pinned_memory_pool().free_all_blocks() @testing.for_orders('CFAK') @testing.for_all_dtypes() @numpy_cupyx_array_equal(target_func='empty_like') def test_empty_like(self, dtype, order, func): a = testing.shaped_arange((2, 3, 4), numpy, dtype) b = func(a, order=order) b.fill(0) return b @testing.for_orders('CFAK') @testing.for_all_dtypes() @numpy_cupyx_array_equal(target_func='empty_like') def test_empty_like_contiguity(self, dtype, order, func): a = testing.shaped_arange((2, 3, 4), numpy, dtype) b = func(a, order=order) b.fill(0) if order in ['f', 'F']: assert b.flags.f_contiguous else: assert b.flags.c_contiguous return b @testing.for_orders('CFAK') @testing.for_all_dtypes() @numpy_cupyx_array_equal(target_func='empty_like') def test_empty_like_contiguity2(self, dtype, order, func): a = testing.shaped_arange((2, 3, 4), numpy, dtype) a = numpy.asfortranarray(a) b = func(a, order=order) b.fill(0) if order in ['c', 'C']: assert b.flags.c_contiguous else: assert b.flags.f_contiguous return b @testing.for_orders('CFAK') @testing.for_all_dtypes() @numpy_cupyx_array_equal(target_func='empty_like') def test_empty_like_contiguity3(self, dtype, order, func): a = testing.shaped_arange((2, 3, 4), numpy, dtype) # test strides that are both non-contiguous and non-descending a = a[:, ::2, :].swapaxes(0, 1) b = func(a, order=order) b.fill(0) if order in ['k', 'K', None]: assert not b.flags.c_contiguous assert not b.flags.f_contiguous elif order in ['f', 'F']: assert not b.flags.c_contiguous assert b.flags.f_contiguous else: assert b.flags.c_contiguous assert not b.flags.f_contiguous return b @testing.for_all_dtypes() def test_empty_like_K_strides(self, dtype): # test strides that are both non-contiguous and non-descending; # also test accepting cupy.ndarray a = testing.shaped_arange((2, 3, 4), numpy, dtype) a = a[:, ::2, :].swapaxes(0, 1) b = numpy.empty_like(a, order='K') b.fill(0) # GPU case ag = testing.shaped_arange((2, 3, 4), cupy, dtype) ag = ag[:, ::2, :].swapaxes(0, 1) bg = cupyx.empty_like_pinned(ag, order='K') bg.fill(0) # make sure NumPy and CuPy strides agree assert b.strides == bg.strides @testing.with_requires('numpy>=1.19') @testing.for_all_dtypes() def test_empty_like_invalid_order(self, dtype): a = testing.shaped_arange((2, 3, 4), numpy, dtype) with pytest.raises(ValueError): cupyx.empty_like_pinned(a, order='Q') def test_empty_like_subok(self): a = testing.shaped_arange((2, 3, 4), numpy) with pytest.raises(TypeError): cupyx.empty_like_pinned(a, subok=True) @testing.for_CF_orders() def test_empty_zero_sized_array_strides(self, order): a = numpy.empty((1, 0, 2), dtype='d', order=order) b = cupyx.empty_pinned((1, 0, 2), dtype='d', order=order) assert b.strides == a.strides @testing.for_CF_orders() @testing.for_all_dtypes() @numpy_cupyx_array_equal(target_func='zeros') def test_zeros(self, dtype, order, func): return func((2, 3, 4), dtype=dtype, order=order) @testing.for_CF_orders() @testing.for_all_dtypes() @numpy_cupyx_array_equal(target_func='zeros') def test_zeros_scalar(self, dtype, order, func): return func((), dtype=dtype, order=order) @testing.for_CF_orders() @testing.for_all_dtypes() @numpy_cupyx_array_equal(target_func='zeros') def test_zeros_int(self, dtype, order, func): return func(3, dtype=dtype, order=order) @testing.for_CF_orders() def test_zeros_strides(self, order): a = numpy.zeros((2, 3), dtype='d', order=order) b = cupyx.zeros_pinned((2, 3), dtype='d', order=order) assert b.strides == a.strides @testing.for_orders('CFAK') @testing.for_all_dtypes() @numpy_cupyx_array_equal(target_func='zeros_like') def test_zeros_like(self, dtype, order, func): a = numpy.ndarray((2, 3, 4), dtype=dtype) return func(a, order=order) def test_zeros_like_subok(self): a = numpy.ndarray((2, 3, 4)) with pytest.raises(TypeError): cupyx.zeros_like_pinned(a, subok=True) @testing.parameterize( *testing.product({ 'shape': [4, (4, ), (4, 2), (4, 2, 3), (5, 4, 2, 3)], }) ) class TestBasicReshape(unittest.TestCase): @testing.with_requires('numpy>=1.17.0') @testing.for_orders('CFAK') @testing.for_all_dtypes() @numpy_cupyx_array_equal(target_func='empty_like') def test_empty_like_reshape(self, dtype, order, func): a = testing.shaped_arange((2, 3, 4), numpy, dtype) b = func(a, order=order, shape=self.shape) b.fill(0) return b @testing.for_CF_orders() @testing.for_all_dtypes() def test_empty_like_reshape_cupy_only(self, dtype, order): a = testing.shaped_arange((2, 3, 4), cupy, dtype) b = cupyx.empty_like_pinned(a, shape=self.shape) b.fill(0) c = cupyx.empty_pinned(self.shape, order=order, dtype=dtype) c.fill(0) numpy.testing.assert_array_equal(b, c) @testing.with_requires('numpy>=1.17.0') @testing.for_orders('CFAK') @testing.for_all_dtypes() @numpy_cupyx_array_equal(target_func='empty_like') def test_empty_like_reshape_contiguity(self, dtype, order, func): a = testing.shaped_arange((2, 3, 4), numpy, dtype) b = func(a, order=order, shape=self.shape) b.fill(0) if order in ['f', 'F']: assert b.flags.f_contiguous else: assert b.flags.c_contiguous return b @testing.for_orders('CFAK') @testing.for_all_dtypes() def test_empty_like_reshape_contiguity_cupy_only(self, dtype, order): a = testing.shaped_arange((2, 3, 4), cupy, dtype) b = cupyx.empty_like_pinned(a, order=order, shape=self.shape) b.fill(0) c = cupyx.empty_pinned(self.shape) c.fill(0) if order in ['f', 'F']: assert b.flags.f_contiguous else: assert b.flags.c_contiguous numpy.testing.assert_array_equal(b, c) @testing.with_requires('numpy>=1.17.0') @testing.for_orders('CFAK') @testing.for_all_dtypes() @numpy_cupyx_array_equal(target_func='empty_like') def test_empty_like_reshape_contiguity2(self, dtype, order, func): a = testing.shaped_arange((2, 3, 4), numpy, dtype) a = numpy.asfortranarray(a) b = func(a, order=order, shape=self.shape) b.fill(0) shape = self.shape if not numpy.isscalar(self.shape) else (self.shape,) if (order in ['c', 'C'] or (order in ['k', 'K', None] and len(shape) != a.ndim)): assert b.flags.c_contiguous else: assert b.flags.f_contiguous return b @testing.for_orders('CFAK') @testing.for_all_dtypes() def test_empty_like_reshape_contiguity2_cupy_only(self, dtype, order): a = testing.shaped_arange((2, 3, 4), cupy, dtype) a = cupy.asfortranarray(a) b = cupyx.empty_like_pinned(a, order=order, shape=self.shape) b.fill(0) c = cupyx.empty_pinned(self.shape) c.fill(0) shape = self.shape if not numpy.isscalar(self.shape) else (self.shape,) if (order in ['c', 'C'] or (order in ['k', 'K', None] and len(shape) != a.ndim)): assert b.flags.c_contiguous else: assert b.flags.f_contiguous numpy.testing.assert_array_equal(b, c) @testing.with_requires('numpy>=1.17.0') @testing.for_orders('CFAK') @testing.for_all_dtypes() @numpy_cupyx_array_equal(target_func='empty_like') def test_empty_like_reshape_contiguity3(self, dtype, order, func): a = testing.shaped_arange((2, 3, 4), numpy, dtype) # test strides that are both non-contiguous and non-descending a = a[:, ::2, :].swapaxes(0, 1) b = func(a, order=order, shape=self.shape) b.fill(0) shape = self.shape if not numpy.isscalar(self.shape) else (self.shape,) if len(shape) == 1: assert b.flags.c_contiguous assert b.flags.f_contiguous elif order in ['k', 'K', None] and len(shape) == a.ndim: assert not b.flags.c_contiguous assert not b.flags.f_contiguous elif order in ['f', 'F']: assert not b.flags.c_contiguous assert b.flags.f_contiguous else: assert b.flags.c_contiguous assert not b.flags.f_contiguous return b @testing.for_orders('CFAK') @testing.for_all_dtypes() def test_empty_like_reshape_contiguity3_cupy_only(self, dtype, order): a = testing.shaped_arange((2, 3, 4), cupy, dtype) # test strides that are both non-contiguous and non-descending a = a[:, ::2, :].swapaxes(0, 1) b = cupyx.empty_like_pinned(a, order=order, shape=self.shape) b.fill(0) shape = self.shape if not numpy.isscalar(self.shape) else (self.shape,) if len(shape) == 1: assert b.flags.c_contiguous assert b.flags.f_contiguous elif order in ['k', 'K', None] and len(shape) == a.ndim: assert not b.flags.c_contiguous assert not b.flags.f_contiguous elif order in ['f', 'F']: assert not b.flags.c_contiguous assert b.flags.f_contiguous else: assert b.flags.c_contiguous assert not b.flags.f_contiguous c = cupyx.zeros_pinned(self.shape) c.fill(0) testing.assert_array_equal(b, c) @testing.with_requires('numpy>=1.17.0') @testing.for_all_dtypes() def test_empty_like_K_strides_reshape(self, dtype): # test strides that are both non-contiguous and non-descending a = testing.shaped_arange((2, 3, 4), numpy, dtype) a = a[:, ::2, :].swapaxes(0, 1) b = cupyx.empty_like_pinned(a, order='K', shape=self.shape) b.fill(0) # GPU case ag = testing.shaped_arange((2, 3, 4), cupy, dtype) ag = ag[:, ::2, :].swapaxes(0, 1) bg = cupyx.empty_like_pinned(ag, order='K', shape=self.shape) bg.fill(0) # make sure NumPy and CuPy strides agree assert b.strides == bg.strides return @testing.with_requires('numpy>=1.17.0') @testing.for_orders('CFAK') @testing.for_all_dtypes() @numpy_cupyx_array_equal(target_func='zeros_like') def test_zeros_like_reshape(self, dtype, order, func): a = numpy.ndarray((2, 3, 4), dtype=dtype) return func(a, order=order, shape=self.shape) @testing.for_CF_orders() @testing.for_all_dtypes() def test_zeros_like_reshape_cupy_only(self, dtype, order): a = testing.shaped_arange((2, 3, 4), cupy, dtype) b = cupyx.zeros_like_pinned(a, shape=self.shape) c = cupyx.zeros_pinned(self.shape, order=order, dtype=dtype) numpy.testing.assert_array_equal(b, c)