summaryrefslogtreecommitdiff
path: root/numpy/ma/core.py
diff options
context:
space:
mode:
authorAntony Lee <anntzer.lee@gmail.com>2021-08-02 20:37:30 +0200
committerAntony Lee <anntzer.lee@gmail.com>2021-08-03 20:37:57 +0200
commit557bb33ff71c6aae64a85e58d2b78b2c8877a0f5 (patch)
treea913025052d310a8466cc7e66e2462660481073e /numpy/ma/core.py
parentf25905b5d25a2fca1e23adad11d4597a1e658276 (diff)
downloadnumpy-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.py22
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)