[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