
Hello,
I am giving some introduction tutorials to numpy and we notices a big difference in speed between nuumpy and math for trigonometric operations:
In [3]: %timeit numpy.sin(1) 100000 loops, best of 3: 2.27 us per loop
In [4]: %timeit math.sin(1) 10000000 loops, best of 3: 92.3 ns per loop
While not surprising, I did not expect numpy to be so much slower (25x)...
Is this normal ? Cheers,

On Mon, Jun 3, 2013 at 6:29 AM, Jerome Kieffer Jerome.Kieffer@esrf.fr wrote:
Hello,
I am giving some introduction tutorials to numpy and we notices a big difference in speed between nuumpy and math for trigonometric operations:
In [3]: %timeit numpy.sin(1) 100000 loops, best of 3: 2.27 us per loop
In [4]: %timeit math.sin(1) 10000000 loops, best of 3: 92.3 ns per loop
While not surprising, I did not expect numpy to be so much slower (25x)...
It is a known limitation of numpy scalars. As soon as you use array that are not tiny, the speed difference disappears and then favors numpy arrays (around 50 on my own machine, but that's platform specific).
David

On Mon, 3 Jun 2013 07:33:23 +0100 David Cournapeau cournape@gmail.com wrote:
While not surprising, I did not expect numpy to be so much slower (25x)...
It is a known limitation of numpy scalars. As soon as you use array that are not tiny, the speed difference disappears and then favors numpy arrays (around 50 on my own machine, but that's platform specific).
Thanks for the figure and the explanation.

On 3 June 2013 08:33, David Cournapeau cournape@gmail.com wrote:
(around 50 on my own machine, but that's platform specific).
In my machine, it is around 10. You also have to be aware of the data container: it is not the same to iterate over lists than over arrays.
In [6]: a = np.arange(50)
In [7]: %timeit np.sin(a) 100000 loops, best of 3: 3.95 us per loop
In [8]: %timeit np.array([math.sin(i) for i in a]) # We are working with arrays, we keep the array output. 10000 loops, best of 3: 32.9 us per loop
In [9]: %timeit [math.sin(i) for i in a] # Keep the list output. 10000 loops, best of 3: 21.3 us per loop
But, if you stick to lists:
In [12]: b = range(50)
In [13]: %timeit [math.sin(i) for i in b] 100000 loops, best of 3: 12.4 us per loop
In any case, switching between iterators and numpy functions is, in my opinion, error prone. I would use math only for scalars, and numpy for the rest, except if optimisation is needed (as a last step). For the record, another interesting example:
In [18]: a = np.arange(10)
In [19]: b = range(10)
In [20]: %timeit a + b ## Mixed container 100000 loops, best of 3: 10.4 us per loop
In [21]: %timeit [i + j for i, j in zip(a, b)] 100000 loops, best of 3: 12 us per loop
In [22]: %timeit a + a ## Pure array 1000000 loops, best of 3: 1.23 us per loop
In [23]: %timeit [i + j for i, j in zip(a, a)] 100000 loops, best of 3: 7.21 us per loop
In [24]: %timeit b + b ## Pure list 1000000 loops, best of 3: 197 ns per loop ## OOOOPS
In [25]: %timeit [i + j for i, j in zip(b, b)] 100000 loops, best of 3: 1.68 us per loop
Here, b + b is just attaching the lists, not adding them. In a program, that may be an error due to forgotten conversion.
Out of curiosity, VPython, a visual package oriented to beginners, has its own functions that redirect to math if applied on scalars and to numpy otherwise.
David.
participants (3)
-
David Cournapeau
-
Daπid
-
Jerome Kieffer