15

I want to test the processing time between 2 identical lists, specifically for a normal list and a numpy list. My code is

import timeit
import numpy as np

t = timeit.Timer("range(1000)")
print t.timeit()

u = timeit.Timer("np.arange(1000)")
print u.timeit()

Calculation for t is fine, but for u NameError: global name 'np' is not defined is listed.

How should I code it to get the processing time?

user3211991
  • 441
  • 2
  • 8
  • 13

3 Answers3

16

The timeit.Timer class can be used in two different ways.

It can either take source code to be compiled an executed—in which case, the code is executed in a fresh environment where only the setup code has been run, or it can take a callable, in which case the callable is just called (in your current environment, like any other callable).

So, you have two options:

u = timeit.Timer("np.arange(1000)", setup='import numpy as np')

… or …

u = timeit.Timer(lambda: np.arange(1000))

In the first case, the fact that you happen to have done an import numpy as np is irrelevant; it has no effect on the environment in which np.arange(1000) is compiled and executed (and thus you must include it in the setup=... bit).

In the second case, the fact that you've done an import numpy as np obviously is relevant—it affects the environment in which your code, including the lambda: np.arange(1000), gets evaluated.

Community
  • 1
  • 1
abarnert
  • 354,177
  • 51
  • 601
  • 671
5

Use setup parameter:

u = timeit.Timer("np.arange(1000)", setup='import numpy as np')
ndpu
  • 22,225
  • 6
  • 54
  • 69
  • Thanks for the code. Now that I know the time, do you know why is the time in a normal list (10.4s), much longer than a array (1.9s)? – user3211991 Jan 19 '14 at 11:47
  • @user3211991 range(1000) creates list in memory, try to replace range(1000) with xrange(1000), http://stackoverflow.com/questions/94935/what-is-the-difference-between-range-and-xrange – ndpu Jan 19 '14 at 11:52
  • See also http://stackoverflow.com/questions/10698858/built-in-range-or-numpy-arange-which-is-more-efficient for more details in the efficiency between range and np.arange – Ffisegydd Jan 19 '14 at 11:54
  • @user3211991: That's really a completely separate question… but generally, creating 1000 Python `int` objects plus a list to hold them all will take longer than creating and initializing an array of 1000 C `int` objects. That's half the point of NumPy—not "boxing" each value in a Python object saves all the boxing and unboxing time. (The other half of the point is that it also saves the memory for those 1000 "boxes". And the third half—because NumPy is cool enough to have more than 100% goodness—is that it offers nice APIs for element-wise operations.) – abarnert Jan 19 '14 at 12:01
4

To use imported libraries with timeit you have to import them using the setup keyword argument (docs):

import timeit

# Doesn't require setup kwarg as range doesn't need to be imported.
t = timeit.Timer("range(1000)")
print t.timeit()

# Requires the import of numpy (as np) through the setup kwarg.
u = timeit.Timer("np.arange(1000)", setup = 'import numpy as np')
print(u.timeit())

The setup keyword argument allows you to setup your code, such as importing external libraries or importing functions from your code through the use of from __main__ import func.

Ffisegydd
  • 51,807
  • 15
  • 147
  • 125
  • 2
    No, you don't have to import them using the `setup` keyword argument. If you pass a callable instead of code to be compiled, the callable has already been compiled in your normal environment (including any `import` statements) and runs just fine. – abarnert Jan 19 '14 at 11:58