diff options
Diffstat (limited to 'benchmarks')
-rw-r--r-- | benchmarks/README.rst | 8 | ||||
-rw-r--r-- | benchmarks/benchmarks/bench_function_base.py | 28 | ||||
-rw-r--r-- | benchmarks/benchmarks/bench_io.py | 4 | ||||
-rw-r--r-- | benchmarks/benchmarks/bench_lib.py | 5 | ||||
-rw-r--r-- | benchmarks/benchmarks/bench_ma.py | 4 | ||||
-rw-r--r-- | benchmarks/benchmarks/bench_overrides.py | 61 | ||||
-rw-r--r-- | benchmarks/benchmarks/bench_reduce.py | 6 | ||||
-rw-r--r-- | benchmarks/benchmarks/bench_shape_base.py | 8 |
8 files changed, 107 insertions, 17 deletions
diff --git a/benchmarks/README.rst b/benchmarks/README.rst index f4f0b0de9..b67994ce0 100644 --- a/benchmarks/README.rst +++ b/benchmarks/README.rst @@ -60,3 +60,11 @@ Some things to consider: - Preparing arrays etc. should generally be put in the ``setup`` method rather than the ``time_`` methods, to avoid counting preparation time together with the time of the benchmarked operation. + +- Be mindful that large arrays created with ``np.empty`` or ``np.zeros`` might + not be allocated in physical memory until the memory is accessed. If this is + desired behaviour, make sure to comment it in your setup function. If + you are benchmarking an algorithm, it is unlikely that a user will be + executing said algorithm on a newly created empty/zero array. One can force + pagefaults to occur in the setup phase either by calling ``np.ones`` or + ``arr.fill(value)`` after creating the array, diff --git a/benchmarks/benchmarks/bench_function_base.py b/benchmarks/benchmarks/bench_function_base.py index a45525793..9ef03262b 100644 --- a/benchmarks/benchmarks/bench_function_base.py +++ b/benchmarks/benchmarks/bench_function_base.py @@ -105,14 +105,6 @@ class Sort(Benchmark): self.equal = np.ones(10000) self.many_equal = np.sort(np.arange(10000) % 10) - # quicksort median of 3 worst case - self.worst = np.arange(1000000) - x = self.worst - while x.size > 3: - mid = x.size // 2 - x[mid], x[-2] = x[-2], x[mid] - x = x[:-2] - def time_sort(self): np.sort(self.e) @@ -128,9 +120,6 @@ class Sort(Benchmark): def time_sort_many_equal(self): self.many_equal.sort() - def time_sort_worst(self): - np.sort(self.worst) - def time_argsort(self): self.e.argsort() @@ -138,6 +127,23 @@ class Sort(Benchmark): self.o.argsort() +class SortWorst(Benchmark): + def setup(self): + # quicksort median of 3 worst case + self.worst = np.arange(1000000) + x = self.worst + while x.size > 3: + mid = x.size // 2 + x[mid], x[-2] = x[-2], x[mid] + x = x[:-2] + + def time_sort_worst(self): + np.sort(self.worst) + + # Retain old benchmark name for backward compatability + time_sort_worst.benchmark_name = "bench_function_base.Sort.time_sort_worst" + + class Where(Benchmark): def setup(self): self.d = np.arange(20000) diff --git a/benchmarks/benchmarks/bench_io.py b/benchmarks/benchmarks/bench_io.py index ce30c4345..879f9b69e 100644 --- a/benchmarks/benchmarks/bench_io.py +++ b/benchmarks/benchmarks/bench_io.py @@ -21,6 +21,10 @@ class Copy(Benchmark): def time_memcpy(self, typename): self.d[...] = self.e_d + def time_memcpy_large_out_of_place(self, typename): + l = np.ones(1024**2, dtype=np.dtype(typename)) + l.copy() + def time_cont_assign(self, typename): self.d[...] = 1 diff --git a/benchmarks/benchmarks/bench_lib.py b/benchmarks/benchmarks/bench_lib.py index 83f26c9d1..e6c91a27c 100644 --- a/benchmarks/benchmarks/bench_lib.py +++ b/benchmarks/benchmarks/bench_lib.py @@ -19,7 +19,10 @@ class Pad(Benchmark): ] def setup(self, shape, pad_width, mode): - self.array = np.empty(shape) + # avoid np.zeros or np.empty's lazy allocation. + # np.full causes pagefaults to occur during setup + # instead of during the benchmark + self.array = np.full(shape, 0) def time_pad(self, shape, pad_width, mode): np.pad(self.array, pad_width, mode) diff --git a/benchmarks/benchmarks/bench_ma.py b/benchmarks/benchmarks/bench_ma.py index d313f01dc..aff78df0a 100644 --- a/benchmarks/benchmarks/bench_ma.py +++ b/benchmarks/benchmarks/bench_ma.py @@ -89,7 +89,9 @@ class Concatenate(Benchmark): ] def setup(self, mode, n): - normal = np.zeros((n, n), int) + # avoid np.zeros's lazy allocation that cause page faults during benchmark. + # np.fill will cause pagefaults to happen during setup. + normal = np.full((n, n), 0, int) unmasked = np.ma.zeros((n, n), int) masked = np.ma.array(normal, mask=True) diff --git a/benchmarks/benchmarks/bench_overrides.py b/benchmarks/benchmarks/bench_overrides.py new file mode 100644 index 000000000..2cb94c95c --- /dev/null +++ b/benchmarks/benchmarks/bench_overrides.py @@ -0,0 +1,61 @@ +from __future__ import absolute_import, division, print_function + +from .common import Benchmark + +from numpy.core.overrides import array_function_dispatch +import numpy as np + + +def _broadcast_to_dispatcher(array, shape, subok=None): + return (array,) + + +@array_function_dispatch(_broadcast_to_dispatcher) +def mock_broadcast_to(array, shape, subok=False): + pass + + +def _concatenate_dispatcher(arrays, axis=None, out=None): + for array in arrays: + yield array + if out is not None: + yield out + + +@array_function_dispatch(_concatenate_dispatcher) +def mock_concatenate(arrays, axis=0, out=None): + pass + + +class DuckArray(object): + def __array_function__(self, func, types, args, kwargs): + pass + + +class ArrayFunction(Benchmark): + + def setup(self): + self.numpy_array = np.array(1) + self.numpy_arrays = [np.array(1), np.array(2)] + self.many_arrays = 500 * self.numpy_arrays + self.duck_array = DuckArray() + self.duck_arrays = [DuckArray(), DuckArray()] + self.mixed_arrays = [np.array(1), DuckArray()] + + def time_mock_broadcast_to_numpy(self): + mock_broadcast_to(self.numpy_array, ()) + + def time_mock_broadcast_to_duck(self): + mock_broadcast_to(self.duck_array, ()) + + def time_mock_concatenate_numpy(self): + mock_concatenate(self.numpy_arrays, axis=0) + + def time_mock_concatenate_many(self): + mock_concatenate(self.many_arrays, axis=0) + + def time_mock_concatenate_duck(self): + mock_concatenate(self.duck_arrays, axis=0) + + def time_mock_concatenate_mixed(self): + mock_concatenate(self.mixed_arrays, axis=0) diff --git a/benchmarks/benchmarks/bench_reduce.py b/benchmarks/benchmarks/bench_reduce.py index 353eb980c..ffc148cd2 100644 --- a/benchmarks/benchmarks/bench_reduce.py +++ b/benchmarks/benchmarks/bench_reduce.py @@ -29,8 +29,10 @@ class AddReduceSeparate(Benchmark): class AnyAll(Benchmark): def setup(self): - self.zeros = np.zeros(100000, bool) - self.ones = np.ones(100000, bool) + # avoid np.zeros's lazy allocation that would + # cause page faults during benchmark + self.zeros = np.full(100000, 0, bool) + self.ones = np.full(100000, 0, bool) def time_all_fast(self): self.zeros.all() diff --git a/benchmarks/benchmarks/bench_shape_base.py b/benchmarks/benchmarks/bench_shape_base.py index 716d1f9b5..e48ea0adb 100644 --- a/benchmarks/benchmarks/bench_shape_base.py +++ b/benchmarks/benchmarks/bench_shape_base.py @@ -23,7 +23,9 @@ class Block(Benchmark): self.four_1d = np.ones(6 * n) self.five_0d = np.ones(1 * n) self.six_1d = np.ones(5 * n) - self.zero_2d = np.zeros((2 * n, 6 * n)) + # avoid np.zeros's lazy allocation that might cause + # page faults during benchmark + self.zero_2d = np.full((2 * n, 6 * n), 0) self.one = np.ones(3 * n) self.two = 2 * np.ones((3, 3 * n)) @@ -31,7 +33,9 @@ class Block(Benchmark): self.four = 4 * np.ones(3 * n) self.five = 5 * np.ones(1 * n) self.six = 6 * np.ones(5 * n) - self.zero = np.zeros((2 * n, 6 * n)) + # avoid np.zeros's lazy allocation that might cause + # page faults during benchmark + self.zero = np.full((2 * n, 6 * n), 0) def time_block_simple_row_wise(self, n): np.block([self.a_2d, self.b_2d]) |