[Tutor] A fun puzzle

Kent Johnson kent37 at tds.net
Fri Aug 24 19:22:31 CEST 2007


Dick Moores wrote:
>>> This time I added "xrange(10, end, 10)" and did the timing using 
>>> the template in the timeit module:
>>> template = """
>>> def inner(_it, _timer):
>>>      _t0 = _timer()
>>>      from itertools import chain
>>>      end = 1000000
>>>      for _i in _it:
>>>          for x in chain(xrange(1, end, 10), xrange(2, end, 10),
>>>          xrange(3, end, 10), xrange(4, end, 10), xrange(5, end, 10),
>>>          xrange(6, end, 10), xrange(7, end, 10), xrange(8, end, 10),
>>>          xrange(9, end, 10), xrange(10, end, 10)):
>>>              pass
>>>      _t1 = _timer()
>>>      return _t1 - _t0
>>> """
>>> This gets always close to 71 msec per loop.
>>>
>>> template = """
>>> def inner(_it, _timer):
>>>      _t0 = _timer()
>>>      end = 1000000
>>>      for _i in _it:
>>>          for x in xrange(end):
>>>              pass
>>>      _t1 = _timer()
>>>      return _t1 - _t0
>>> """
>>> This gets always close to 84 msec per loop.
>>> So they're not the same! And yours is the faster one! Because 
>>> itertools.chain() is written in C, I suppose.
>> That is very strange. I did a simple timer with time.time() and 
>> found that my original (1-9) version was consistently a little 
>> slower than the simple xrange(). And xrange is written in C too, and 
>> the chain version adds a layer over xrange. You should check your 
>> code carefully, that is a very surprising result.
> 
> Yes, surprising. But the templates pasted above are exactly what I 
> used in 2 copies of timeit.py. I don't know what to check. Can you 
> see what's wrong?  I just ran both of those again, with very similar results.

So you actually pasted that code into timeit.py? That is a pretty 
unconventional use of the module! I wonder if there is something strange 
going on there?

Using timeit more conventionally I get unsurprising results. This program:

from timeit import Timer

setup = 'from itertools import chain'
stmt = '''end = 1000000
for x in chain(xrange(1, end, 10), xrange(2, end, 10),
     xrange(3, end, 10), xrange(4, end, 10), xrange(5, end, 10),
     xrange(6, end, 10), xrange(7, end, 10), xrange(8, end, 10),
     xrange(9, end, 10), xrange(10, end, 10)):
         pass
'''

print min(Timer(stmt, setup=setup).repeat(number=10))

stmt = '''end = 1000000
for x in xrange(end):
     pass
'''

print min(Timer(stmt).repeat(number=10))


has output:
0.497083902359
0.359513998032

which is more in line with what I would expect.

I can't account for the variations between different timing methods.

Kent


More information about the Tutor mailing list