From d4f8b5d3c760c4bdd0e3a38caa3b0f5aadda7e82 Mon Sep 17 00:00:00 2001 From: Sayed Adel Date: Mon, 6 Feb 2023 09:33:02 +0200 Subject: [PATCH] BENCH: Clean up ufunc_strides --- benchmarks/benchmarks/bench_ufunc_strides.py | 242 ++++++++----------- 1 file changed, 103 insertions(+), 139 deletions(-) diff --git a/benchmarks/benchmarks/bench_ufunc_strides.py b/benchmarks/benchmarks/bench_ufunc_strides.py index 3bf9ef659e30..ae03fab9faab 100644 --- a/benchmarks/benchmarks/bench_ufunc_strides.py +++ b/benchmarks/benchmarks/bench_ufunc_strides.py @@ -2,159 +2,123 @@ import numpy as np -UNARY_UFUNCS = [obj for obj in np.core.umath.__dict__.values() if - isinstance(obj, np.ufunc)] -UNARY_OBJECT_UFUNCS = [uf for uf in UNARY_UFUNCS if "O->O" in uf.types] -UNARY_OBJECT_UFUNCS.remove(getattr(np, 'invert')) +UFUNCS = [obj for obj in np.core.umath.__dict__.values() if + isinstance(obj, np.ufunc)] +UFUNCS_UNARY = [uf for uf in UFUNCS if "O->O" in uf.types] -stride = [1, 2, 4] -stride_out = [1, 2, 4] -dtype = ['e', 'f', 'd'] - -class Unary(Benchmark): - params = [UNARY_OBJECT_UFUNCS, stride, stride_out, dtype] - param_names = ['ufunc', 'stride_in', 'stride_out', 'dtype'] - timeout = 10 - - def setup(self, ufuncname, stride, stride_out, dtype): - np.seterr(all='ignore') - try: - self.f = ufuncname - except AttributeError: - raise NotImplementedError(f"No ufunc {ufuncname} found") from None - N = 100000 - self.arr_out = np.empty(stride_out*N, dtype) - self.arr = np.random.rand(stride*N).astype(dtype) - if (ufuncname.__name__ == 'arccosh'): - self.arr = 1.0 + self.arr - - def time_ufunc(self, ufuncname, stride, stride_out, dtype): - self.f(self.arr[::stride], self.arr_out[::stride_out]) - -class AVX_UFunc_log(Benchmark): - params = [stride, dtype] - param_names = ['stride', 'dtype'] - timeout = 10 - - def setup(self, stride, dtype): - np.seterr(all='ignore') - N = 10000 - self.arr = np.array(np.random.random_sample(stride*N), dtype=dtype) - - def time_log(self, stride, dtype): - np.log(self.arr[::stride]) - - -binary_ufuncs = [ - 'maximum', 'minimum', 'fmax', 'fmin' -] -binary_dtype = ['f', 'd'] - -class Binary(Benchmark): - param_names = ['ufunc', 'stride_in0', 'stride_in1', 'stride_out', 'dtype'] - params = [binary_ufuncs, stride, stride, stride_out, binary_dtype] +class _AbstractBinary(Benchmark): + params = [] + param_names = ['ufunc', 'stride_in0', 'stride_in1' 'stride_out', 'dtype'] timeout = 10 + arrlen = 10000 + + def setup(self, ufunc, stride_in0, stride_in1, stride_out, dtype): + ufunc_insig = f'{dtype}{dtype}->' + if ufunc_insig+dtype not in ufunc.types: + for st_sig in (ufunc_insig, dtype): + test = [sig for sig in ufunc.types if sig.startswith(st_sig)] + if test: + break + if not test: + raise NotImplementedError( + f"Ufunc {ufunc} doesn't support binary input of dtype {dtype}" + ) from None + tin, tout = test[0].split('->') + else: + tin = dtype + dtype + tout = dtype + + self.ufunc_args = [] + for dt, stride in zip(tin, (stride_in0, stride_in1)): + if dt in 'efdFD': + self.ufunc_args += [ + np.random.rand(stride*self.arrlen).astype(dt)[::stride] + ] + else: + self.ufunc_args += [np.ones(stride*self.arrlen, dt)[::stride]] + + for dt in tout: + self.ufunc_args += [np.empty(stride_out*self.arrlen, dt)[::stride_out]] - def setup(self, ufuncname, stride_in0, stride_in1, stride_out, dtype): np.seterr(all='ignore') - try: - self.f = getattr(np, ufuncname) - except AttributeError: - raise NotImplementedError(f"No ufunc {ufuncname} found") from None - N = 100000 - self.arr1 = np.array(np.random.rand(stride_in0*N), dtype=dtype) - self.arr2 = np.array(np.random.rand(stride_in1*N), dtype=dtype) - self.arr_out = np.empty(stride_out*N, dtype) - - def time_ufunc(self, ufuncname, stride_in0, stride_in1, stride_out, dtype): - self.f(self.arr1[::stride_in0], self.arr2[::stride_in1], - self.arr_out[::stride_out]) - -binary_int_ufuncs = ['maximum', 'minimum'] -binary_int_dtype = ['b', 'B', 'h', 'H', 'i', 'I', 'l', 'L', 'q', 'Q'] - -class BinaryInt(Binary): - - param_names = ['ufunc', 'stride_in0', 'stride_in1', 'stride_out', 'dtype'] - params = [binary_int_ufuncs, stride, stride, stride_out, binary_int_dtype] - -class AVX_ldexp(Benchmark): - - params = [dtype, stride] - param_names = ['dtype', 'stride'] - timeout = 10 - - def setup(self, dtype, stride): - np.seterr(all='ignore') - self.f = getattr(np, 'ldexp') - N = 10000 - self.arr1 = np.array(np.random.rand(stride*N), dtype=dtype) - self.arr2 = np.array(np.random.rand(stride*N), dtype='i') - - def time_ufunc(self, dtype, stride): - self.f(self.arr1[::stride], self.arr2[::stride]) - -cmplx_bfuncs = ['add', - 'subtract', - 'multiply', - 'divide'] -cmplxstride = [1, 2, 4] -cmplxdtype = ['F', 'D'] - -class BinaryComplex(Benchmark): - params = [cmplx_bfuncs, cmplxstride, cmplxstride, cmplxstride, cmplxdtype] - param_names = ['bfunc', 'stride_in0', 'stride_in1' 'stride_out', 'dtype'] - timeout = 10 - - def setup(self, bfuncname, stride_in0, stride_in1, stride_out, dtype): - np.seterr(all='ignore') - try: - self.f = getattr(np, bfuncname) - except AttributeError: - raise NotImplementedError(f"No bfunc {bfuncname} found") from None - N = 10000 - self.arr1 = np.ones(stride_in0*N, dtype) - self.arr2 = np.ones(stride_in1*N, dtype) - self.arr_out = np.empty(stride_out*N, dtype) - - def time_ufunc(self, bfuncname, stride_in0, stride_in1, stride_out, + def time_ufunc(self, ufunc, stride_in0, stride_in1, stride_out, dtype): - self.f(self.arr1[::stride_in0], self.arr2[::stride_in1], - self.arr_out[::stride_out]) + ufunc(*self.ufunc_args) - def time_ufunc_scalar_in0(self, bfuncname, stride_in0, stride_in1, + def time_ufunc_scalar_in0(self, ufunc, stride_in0, stride_in1, stride_out, dtype): - self.f(self.arr1[0], self.arr2[::stride_in1], - self.arr_out[::stride_out]) + ufunc(self.ufunc_args[0][0], *self.ufunc_args[1:]) - def time_ufunc_scalar_in1(self, bfuncname, stride_in0, stride_in1, + def time_ufunc_scalar_in1(self, ufunc, stride_in0, stride_in1, stride_out, dtype): - self.f(self.arr1[::stride_in0], self.arr2[0], - self.arr_out[::stride_out]) + ufunc(self.ufunc_args[0], self.ufunc_args[1][0], *self.ufunc_args[2:]) -cmplx_ufuncs = ['reciprocal', - 'absolute', - 'square', - 'conjugate'] - -class UnaryComplex(Benchmark): - params = [cmplx_ufuncs, cmplxstride, cmplxstride, cmplxdtype] - param_names = ['bfunc', 'stride_in', 'stride_out', 'dtype'] +class _AbstractUnary(Benchmark): + params = [] + param_names = ['ufunc', 'stride_in', 'stride_out', 'dtype'] timeout = 10 + arrlen = 10000 + + def setup(self, ufunc, stride_in, stride_out, dtype): + if dtype in 'efdFD': + arr_in = np.random.rand(stride_in*self.arrlen).astype(dtype) + else: + arr_in = np.ones(stride_in*self.arrlen, dtype) + self.ufunc_args = [arr_in[::stride_in]] + + ufunc_insig = f'{dtype}->' + if ufunc_insig+dtype not in ufunc.types: + test = [sig for sig in ufunc.types if sig.startswith(ufunc_insig)] + if not test: + raise NotImplementedError( + f"Ufunc {ufunc} doesn't support unary input of dtype {dtype}" + ) from None + tout = test[0].split('->')[1] + else: + tout = dtype + + for dt in tout: + self.ufunc_args += [np.empty(stride_out*self.arrlen, dt)[::stride_out]] - def setup(self, bfuncname, stride_in, stride_out, dtype): np.seterr(all='ignore') - try: - self.f = getattr(np, bfuncname) - except AttributeError: - raise NotImplementedError(f"No bfunc {bfuncname} found") from None - N = 10000 - self.arr1 = np.ones(stride_in*N, dtype) - self.arr_out = np.empty(stride_out*N, dtype) - - def time_ufunc(self, bfuncname, stride_in, stride_out, dtype): - self.f(self.arr1[::stride_in], self.arr_out[::stride_out]) + + def time_ufunc(self, ufunc, stride_in, stride_out, dtype): + ufunc(*self.ufunc_args) + +class UnaryFP(_AbstractUnary): + params = [UFUNCS_UNARY, [1, 2, 4], [1, 2, 4], ['e', 'f', 'd']] + + def setup(self, ufunc, stride_in, stride_out, dtype): + _AbstractUnary.setup(self, ufunc, stride_in, stride_out, dtype) + if (ufunc.__name__ == 'arccosh'): + self.ufunc_args[0] += 1.0 + +class BinaryFP(_AbstractBinary): + params = [ + [np.maximum, np.minimum, np.fmax, np.fmin, np.ldexp], + [1, 2, 4], [1, 2, 4], [1, 2, 4], ['f', 'd'] + ] + +class BinaryComplex(_AbstractBinary): + params = [ + [np.add, np.subtract, np.multiply, np.divide], + [1, 2, 4], [1, 2, 4], [1, 2, 4], + ['F', 'D'] + ] + +class UnaryComplex(_AbstractUnary): + params = [ + [np.reciprocal, np.absolute, np.square, np.conjugate], + [1, 2, 4], [1, 2, 4], ['F', 'D'] + ] + +class BinaryInt(_AbstractBinary): + params = [ + [np.maximum, np.minimum], + [1, 2], [1, 2], [1, 2], + ['b', 'B', 'h', 'H', 'i', 'I', 'l', 'L', 'q', 'Q'] + ] class Mandelbrot(Benchmark): def f(self,z):