diff options
author | Antony Lee <anntzer.lee@gmail.com> | 2021-08-02 20:37:30 +0200 |
---|---|---|
committer | Antony Lee <anntzer.lee@gmail.com> | 2021-08-03 20:37:57 +0200 |
commit | 557bb33ff71c6aae64a85e58d2b78b2c8877a0f5 (patch) | |
tree | a913025052d310a8466cc7e66e2462660481073e /numpy/ma/core.py | |
parent | f25905b5d25a2fca1e23adad11d4597a1e658276 (diff) | |
download | numpy-557bb33ff71c6aae64a85e58d2b78b2c8877a0f5.tar.gz |
PERF: Avoid using `@recursive`.
None of the functions decorated with `@recursive` actually need to close
over internal variables, so they can be lifted to become toplevel
recursive functions which avoid the need for an `@recursive` decorator.
(No change was made to the logic of any of the functions.)
As it turns out, the `@recursive` decorator adds a lot of overhead:
`python runtests.py --bench bench_io` reports a ~15-20% perf gain(!)
for `loadtxt` from this PR. (`_recursive_mask_or` seems less likely to
matter performance-wise, but I also lifted it out for good measure...
and just deleted the decorator's implementation.)
Diffstat (limited to 'numpy/ma/core.py')
-rw-r--r-- | numpy/ma/core.py | 22 |
1 files changed, 10 insertions, 12 deletions
diff --git a/numpy/ma/core.py b/numpy/ma/core.py index 431114fe0..d2150919f 100644 --- a/numpy/ma/core.py +++ b/numpy/ma/core.py @@ -39,7 +39,6 @@ from numpy.compat import ( ) from numpy import expand_dims from numpy.core.numeric import normalize_axis_tuple -from numpy.core._internal import recursive __all__ = [ @@ -1685,6 +1684,16 @@ def make_mask_none(newshape, dtype=None): return result +def _recursive_mask_or(m1, m2, newmask): + names = m1.dtype.names + for name in names: + current1 = m1[name] + if current1.dtype.names is not None: + _recursive_mask_or(current1, m2[name], newmask[name]) + else: + umath.logical_or(current1, m2[name], newmask[name]) + + def mask_or(m1, m2, copy=False, shrink=True): """ Combine two masks with the ``logical_or`` operator. @@ -1722,17 +1731,6 @@ def mask_or(m1, m2, copy=False, shrink=True): """ - @recursive - def _recursive_mask_or(self, m1, m2, newmask): - names = m1.dtype.names - for name in names: - current1 = m1[name] - if current1.dtype.names is not None: - self(current1, m2[name], newmask[name]) - else: - umath.logical_or(current1, m2[name], newmask[name]) - return - if (m1 is nomask) or (m1 is False): dtype = getattr(m2, 'dtype', MaskType) return make_mask(m2, copy=copy, shrink=shrink, dtype=dtype) |