8000 MAINT: Large overhead in some random functions #15460 · numpy/numpy@a15dc30 · GitHub
[go: up one dir, main page]

Skip to content

Commit a15dc30

Browse files
committed
MAINT: Large overhead in some random functions #15460
slow calls to np.dtype.name replaced with np.dtype, mtrand.pyx and _generator.pyx updated, test test_warns_byteorder updated before: %timeit rs.random(): 520 ns ± 33.1 ns per loop %timeit rg.random(): 6.36 µs ± 222 ns per loop after: %timeit rs.random(): 453 ns ± 6.95 ns per loop %timeit rg.random(): 594 ns ± 9.66 ns per loop
1 parent 85be00a commit a15dc30

File tree

3 files changed

+53
-59
lines changed

3 files changed

+53
-59
lines changed

numpy/random/_generator.pyx

Lines changed: 35 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@ from libc.stdint cimport (uint8_t, uint16_t, uint32_t, uint64_t,
1717
from ._bounded_integers cimport (_rand_bool, _rand_int32, _rand_int64,
1818
_rand_int16, _rand_int8, _rand_uint64, _rand_uint32, _rand_uint16,
1919
_rand_uint8, _gen_mask)
20-
from ._bounded_integers import _integers_types
2120
from ._pcg64 import PCG64
2221
from numpy.random cimport bitgen_t
2322
from ._common cimport (POISSON_LAM_MAX, CONS_POSITIVE, CONS_NONE,
@@ -312,13 +311,13 @@ cdef class Generator:
312311
313312
"""
314313
cdef double temp
315-
key = np.dtype(dtype).name
316-
if key == 'float64':
314+
_dtype = np.dtype(dtype)
315+
if _dtype == np.float64:
317316
return double_fill(&random_standard_uniform_fill, &self._bitgen, size, self.lock, out)
318-
elif key == 'float32':
317+
elif _dtype == np.float32:
319318
return float_fill(&random_standard_uniform_fill_f, &self._bitgen, size, self.lock, out)
320319
else:
321-
raise TypeError('Unsupported dtype "%s" for random' % key)
320+
raise TypeError('Unsupported dtype %r for random' % _dtype)
322321

323322
def beta(self, a, b, size=None):
324323
"""
@@ -454,20 +453,20 @@ cdef class Generator:
454453
>>> n = np.random.default_rng().standard_exponential((3, 8000))
455454
456455
"""
457-
key = np.dtype(dtype).name
458-
if key == 'float64':
456+
_dtype = np.dtype(dtype)
457+
if _dtype == np.float64:
459458
if method == u'zig':
460459
return double_fill(&random_standard_exponential_fill, &self._bitgen, size, self.lock, out)
461460
else:
462461
return double_fill(&random_standard_exponential_inv_fill, &self._bitgen, size, self.lock, out)
463-
elif key == 'float32':
462+
elif _dtype == np.float32:
464463
if method == u'zig':
465464
return float_fill(&random_standard_exponential_fill_f, &self._bitgen, size, self.lock, out)
466465
else:
467466
return float_fill(&random_standard_exponential_inv_fill_f, &self._bitgen, size, self.lock, out)
468467
else:
469-
raise TypeError('Unsupported dtype "%s" for standard_exponential'
470-
% key)
468+
raise TypeError('Unsupported dtype %r for standard_exponential'
469+
% _dtype)
471470

472471
def integers(self, low, high=None, size=None, dtype=np.int64, endpoint=False):
473472
"""
@@ -559,39 +558,39 @@ cdef class Generator:
559558
high = low
560559
low = 0
561560

562-
dt = np.dtype(dtype)
563-
key = dt.name
564-
if key not in _integers_types:
565-
raise TypeError('Unsupported dtype "%s" for integers' % key)
566-
if not dt.isnative:
567-
raise ValueError('Providing a dtype with a non-native byteorder '
568-
'is not supported. If you require '
569-
'platform-independent byteorder, call byteswap '
570-
'when required.')
561+
_dtype = np.dtype(dtype)
571562

572563
# Implementation detail: the old API used a masked method to generate
573564
# bounded uniform integers. Lemire's method is preferable since it is
574565
# faster. randomgen allows a choice, we will always use the faster one.
575566
cdef bint _masked = False
576567

577-
if key == 'int32':
568+
if _dtype == np.int32:
578569
ret = _rand_int32(low, high, size, _masked, endpoint, &self._bitgen, self.lock)
579-
elif key == 'int64':
570+
elif _dtype == np.int64:
580571
ret = _rand_int64(low, high, size, _masked, endpoint, &self._bitgen, self.lock)
581-
elif key == 'int16':
572+
elif _dtype == np.int16:
582573
ret = _rand_int16(low, high, size, _masked, endpoint, &self._bitgen, self.lock)
583-
elif key == 'int8':
574+
elif _dtype == np.int8:
584575
ret = _rand_int8(low, high, size, _masked, endpoint, &self._bitgen, self.lock)
585-
elif key == 'uint64':
576+
elif _dtype == np.uint64:
586577
ret = _rand_uint64(low, high, size, _masked, endpoint, &self._bitgen, self.lock)
587-
elif key == 'uint32':
578+
elif _dtype == np.uint32:
588579
ret = _rand_uint32(low, high, size, _masked, endpoint, &self._bitgen, self.lock)
589-
elif key == 'uint16':
580+
elif _dtype == np.uint16:
590581
ret = _rand_uint16(low, high, size, _masked, endpoint, &self._bitgen, self.lock)
591-
elif key == 'uint8':
582+
elif _dtype == np.uint8:
592583
ret = _rand_uint8(low, high, size, _masked, endpoint, &self._bitgen, self.lock)
593-
elif key == 'bool':
584+
elif _dtype == np.bool_:
594585
ret = _rand_bool(low, high, size, _masked, endpoint, &self._bitgen, self.lock)
586+
elif not _dtype.isnative:
587+
raise ValueError('Providing a dtype with a non-native byteorder '
588+
'is not supported. If you require '
589+
'platform-independent byteorder, call byteswap '
590+
'when required.')
591+
else:
592+
raise TypeError('Unsupported dtype %r for integers' % _dtype)
593+
595594

596595
if size is None and dtype in (bool, int, np.compat.long):
597596
if np.array(ret).shape == ():
@@ -1041,14 +1040,14 @@ cdef class Generator:
10411040
[ 0.39924804, 4.68456316, 4.99394529, 4.84057254]]) # random
10421041
10431042
"""
1044-
key = np.dtype(dtype).name
1045-
if key == 'float64':
1043+
_dtype = np.dtype(dtype)
1044+
if _dtype == np.float64:
10461045
return double_fill(&random_standard_normal_fill, &self._bitgen, size, self.lock, out)
1047-
elif key == 'float32':
1046+
elif _dtype == np.float32:
10481047
return float_fill(&random_standard_normal_fill_f, &self._bitgen, size, self.lock, out)
10491048

10501049
else:
1051-
raise TypeError('Unsupported dtype "%s" for standard_normal' % key)
1050+
raise TypeError('Unsupported dtype %r for standard_normal' % _dtype)
10521051

10531052
def normal(self, loc=0.0, scale=1.0, size=None):
10541053
"""
@@ -1230,19 +1229,19 @@ cdef class Generator:
12301229
12311230
"""
12321231
cdef void *func
1233-
key = np.dtype(dtype).name
1234-
if key == 'float64':
1232+
_dtype = np.dtype(dtype)
1233+
if _dtype == np.float64:
12351234
return cont(&random_standard_gamma, &self._bitgen, size, self.lock, 1,
12361235
shape, 'shape', CONS_NON_NEGATIVE,
12371236
0.0, '', CONS_NONE,
12381237
0.0, '', CONS_NONE,
12391238
out)
1240-
if key == 'float32':
1239+
if _dtype == np.float32:
12411240
return cont_f(&random_standard_gamma_f, &self._bitgen, size, self.lock,
12421241
shape, 'shape', CONS_NON_NEGATIVE,
12431242
out)
12441243
else:
1245-
raise TypeError('Unsupported dtype "%s" for standard_gamma' % key)
1244+
raise TypeError('Unsupported dtype %r for standard_gamma' % _dtype)
12461245

12471246
def gamma(self, shape, scale=1.0, size=None):
12481247
"""

numpy/random/mtrand.pyx

Lines changed: 17 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@ from libc.stdint cimport int64_t, uint64_t
1515
from ._bounded_integers cimport (_rand_bool, _rand_int32, _rand_int64,
1616
_rand_int16, _rand_int8, _rand_uint64, _rand_uint32, _rand_uint16,
1717
_rand_uint8,)
18-
from ._bounded_integers import _integers_types
1918
from ._mt19937 import MT19937 as _MT19937
2019
from numpy.random cimport bitgen_t
2120
from ._common cimport (POISSON_LAM_MAX, CONS_POSITIVE, CONS_NONE,
@@ -724,17 +723,7 @@ cdef class RandomState:
724723
high = low
725724
low = 0
726725

727-
dt = np.dtype(dtype)
728-
key = dt.name
729-
if key not in _integers_types:
730-
raise TypeError('Unsupported dtype "%s" for randint' % key)
731-
if not dt.isnative:
732-
# numpy 1.17.0, 2019-05-28
733-
warnings.warn('Providing a dtype with a non-native byteorder is '
734-
'not supported. If you require platform-independent '
735-
'byteorder, call byteswap when required.\nIn future '
736-
'version, providing byteorder will raise a '
737-
'ValueError', DeprecationWarning)
726+
_dtype = np.dtype(dtype)
738727

739728
# Implementation detail: the use a masked method to generate
740729
# bounded uniform integers. Lemire's method is preferable since it is
@@ -743,24 +732,31 @@ cdef class RandomState:
743732
cdef bint _masked = True
744733
cdef bint _endpoint = False
745734

746-
if key == 'int32':
735+
if _dtype == np.int32:
747736
ret = _rand_int32(low, high, size, _masked, _endpoint, &self._bitgen, self.lock)
748-
elif key == 'int64':
737+
elif _dtype == np.int64:
749738
ret = _rand_int64(low, high, size, _masked, _endpoint, &self._bitgen, self.lock)
750-
elif key == 'int16':
739+
elif _dtype == np.int16:
751740
ret = _rand_int16(low, high, size, _masked, _endpoint, &self._bitgen, self.lock)
752-
elif key == 'int8':
741+
elif _dtype == np.int8:
753742
ret = _rand_int8(low, high, size, _masked, _endpoint, &self._bitgen, self.lock)
754-
elif key == 'uint64':
743+
elif _dtype == np.uint64:
755744
ret = _rand_uint64(low, high, size, _masked, _endpoint, &self._bitgen, self.lock)
756-
elif key == 'uint32':
745+
elif _dtype == np.uint32:
757746
ret = _rand_uint32(low, high, size, _masked, _endpoint, &self._bitgen, self.lock)
758-
elif key == 'uint16':
747+
elif _dtype == np.uint16:
759748
ret = _rand_uint16(low, high, size, _masked, _endpoint, &self._bitgen, self.lock)
760-
elif key == 'uint8':
749+
elif _dtype == np.uint8:
761750
ret = _rand_uint8(low, high, size, _masked, _endpoint, &self._bitgen, self.lock)
762-
elif key == 'bool':
751+
elif _dtype == np.bool_:
763752
426B ret = _rand_bool(low, high, size, _masked, _endpoint, &self._bitgen, self.lock)
753+
elif not _dtype.isnative:
754+
raise ValueError('Providing a dtype with a non-native byteorder '
755+
'is not supported. If you require '
756+
'platform-independent byteorder, call byteswap '
757+
'when required.')
758+
else:
759+
raise TypeError('Unsupported dtype %r for randint' % _dtype)
764760

765761
if size is None and dtype in (bool, int, np.compat.long):
766762
if np.array(ret).shape == ():

numpy/random/tests/test_randomstate_regression.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -163,8 +163,7 @@ def __array__(self):
163163
def test_warns_byteorder(self):
164164
# GH 13159
165165
other_byteord_dt = '<i4' if sys.byteorder == 'big' else '>i4'
166-
with pytest.deprecated_call(match='non-native byteorder is not'):
167-
random.randint(0, 200, size=10, dtype=other_byteord_dt)
166+
assert_raises(ValueError, random.randint, 0, 200, size=10, dtype=other_byteord_dt)
168167

169168
def test_named_argument_initialization(self):
170169
# GH 13669

0 commit comments

Comments
 (0)
0