On Wed, Jan 19, 2022 at 7:33 AM Stefan van der Walt <stef...@berkeley.edu>
wrote:

> On Tue, Jan 18, 2022, at 21:55, Warren Weckesser wrote:
> > expr = 'z.real**2 + z.imag**2'
> >
> > z = generate_sample(n, rng)
>
> 🤔 If I duplicate the `z = ...` line, I get the fast result throughout.
> If, however, I use `generate_sample(1, rng)` (or any other value than `n`),
> it does not improve matters.
>
> Could this be a memory caching issue?
>

I can also reproduce that, but only on my Linux boxes.  My MacMini does not
notice the difference.

Interestingly enough, you don't even need an additional call to
`generate_sample(n, rng)`. If one use `z = np.empty(...)` and then do an
assignment, like:

z = np.empty(n, dtype=np.complex128)
z[:] = generate_sample(n, rng)

then everything runs at the same speed:

numpy version 1.20.3

 142.3667 microseconds
 142.3717 microseconds
 142.3781 microseconds

 142.7593 microseconds
 142.3579 microseconds
 142.3231 microseconds

As another data point, by doing the same operation but using numexpr I am
not seeing any difference either, not even on Linux:

numpy version 1.20.3
numexpr version 2.8.1

  95.6513 microseconds
  88.1804 microseconds
  97.1322 microseconds

 105.0833 microseconds
 100.5555 microseconds
 100.5654 microseconds

[it is rather like a bit the other way around, the second iteration seems a
hair faster]
See the numexpr script below.

I am totally puzzled here.

"""
import timeit
import numpy as np
import numexpr as ne


def generate_sample(n, rng):
    return rng.normal(scale=1000, size=2*n).view(np.complex128)


print(f'numpy version {np.__version__}')
print(f'numexpr version {ne.__version__}')
print()

rng = np.random.default_rng()
n = 250000
timeit_reps = 10000

expr = 'ne.evaluate("zreal**2 + zimag**2")'

z = generate_sample(n, rng)
zreal = z.real
zimag = z.imag
for _ in range(3):
    t = timeit.timeit(expr, globals=globals(), number=timeit_reps)
    print(f"{1e6*t/timeit_reps:9.4f} microseconds")
print()

z = generate_sample(n, rng)
zreal = z.real
zimag = z.imag
for _ in range(3):
    t = timeit.timeit(expr, globals=globals(), number=timeit_reps)
    print(f"{1e6*t/timeit_reps:9.4f} microseconds")
print()
"""

-- 
Francesc Alted
_______________________________________________
NumPy-Discussion mailing list -- numpy-discussion@python.org
To unsubscribe send an email to numpy-discussion-le...@python.org
https://mail.python.org/mailman3/lists/numpy-discussion.python.org/
Member address: arch...@mail-archive.com

Reply via email to