16

I can not understand the difference between number and repeat in timeit library, so would you kindly tell me what is the difference between them?

Vasu Deo.S
  • 1,820
  • 1
  • 11
  • 23
mark080
  • 389
  • 3
  • 11

2 Answers2

15

repeat specifies the number of samples to take.

number specifies the number of times to repeat the code for each sample.

Internally there is a loop like this:

samples = []
for _ in range(repeat):
    # start timer
    for _ in range(number):
        do_work()
    # end timer
    samples.append(duration)
Dan D.
  • 73,243
  • 15
  • 104
  • 123
  • 1
    Great Answer (+1), btw can you explain why would one use `repeat` over `number`, or like what is the use case of each? – Vasu Deo.S Jun 26 '19 at 00:14
  • @VasuDeo.S It is related on how to handle the noise properties of a *runtime* measurement for a process managed by a typical OS on a typical hardware. – norok2 Jun 26 '19 at 00:21
  • 1
    @norok2 In Layman's terms, does that mean taking several results/tests in order to flatten(get rid of) the difference produced between each result. or Averaging of some kind in order to get to the mean of the results. – Vasu Deo.S Jun 26 '19 at 00:28
  • @VasuDeo.S In Layman's terms, it means that taking two loops instead of one will allow greater flexibility on the statistics (averaging or other) you could run, which will ultimately allow you to better estimate (and hence correct for) the error you make with a `end_timer - start_timer`-type approach for measuring the execution time of some code. – norok2 Jun 26 '19 at 00:34
  • How is the average calculated in this case? Average of each of the `n` iterations and then average of `r` experiments? – Abhijit Sarkar Jun 14 '23 at 19:03
2

Whenever you do a statistical experiment (in this case a timing experiment) you want to repeat (or replicate) the experiment in order to be able to quantify uncertainty.

Now IPython's %timeit has two parameters:

  • n, the number of loops (samples)
  • r, the number of repeats (replications of the experiment)

One single experiment returns the timing of n loops (that means you will need to divide that value by n to obtain the average timing over all loops).

The experiment is repeated r times.

Uncertainty or uncontrolled variation is given by standard deviation over the r experiments.

This can be seen in this line in the source code (self.loops is the n):

timings =  [dt / self.loops for dt in all_runs]

From https://github.com/ipython/ipython/blob/master/IPython/core/magics/execution.py:

class TimeitResult(object):
    """
    Object returned by the timeit magic with info about the run.
    Contains the following attributes :
    loops: (int) number of loops done per measurement
    repeat: (int) number of times the measurement has been repeated
    best: (float) best execution time / number
    all_runs: (list of float) execution time of each run (in s)
    compile_time: (float) time of statement compilation (s)
    """
    def __init__(self, loops, repeat, best, worst, all_runs, compile_time, precision):
        self.loops = loops
        self.repeat = repeat
        self.best = best
        self.worst = worst
        self.all_runs = all_runs
        self.compile_time = compile_time
        self._precision = precision
        self.timings = [ dt / self.loops for dt in all_runs] 

@property
def average(self):
    return math.fsum(self.timings) / len(self.timings)

@property
def stdev(self):
    mean = self.average
    return (math.fsum([(x - mean) ** 2 for x in self.timings]) / len(self.timings)) ** 0.5

Default n and r

Note that the default number of loops is one million and the default repeat is 7, so I would say for all daily needs it is convenient to use %timeit specifying smaller values, otherwise the timing might take too long/use up too many resources.

Should I use %time instead?

Still, even for a quick timing I wouldn't use the basic %time (just one run) because the timing of a single execution/run could be influenced by many contingent factors.

user2314737
  • 27,088
  • 20
  • 102
  • 114
  • How is the average calculated in this case? Average of each of the `n` iterations and then average of `r` experiments? – Abhijit Sarkar Jun 14 '23 at 19:03
  • 1
    The average of averages is computed. For each experiment (_run_) the execution time is divided by the number of loops (average over loops). These averages are saved in the list `self.timings` and an average over these is computed (average over runs). – user2314737 Jun 14 '23 at 20:36
  • This answer is misleading. The `timeit.repeat` documentation states as much https://docs.python.org/3/library/timeit.html#timeit.Timer.repeat . You should only take the `min`, not the `mean` – Sebastian Wozny Jul 12 '23 at 09:53