473,765 Members | 1,969 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

Profiling weirdness: Timer.timeit(), fibonacci and memoization

I am not clear about the results here.
from timeit import Timer
import Decorators

def fib(n):
a, b = 1, 0
while n:
a, b, n = b, a+b, n-1
return b

@Decorators.mem oize
def fibmem(nbr):
if nbr 1:
return fibmem(nbr-1) + fibmem(nbr-2)
if nbr == 1:
return 1
if nbr == 0:
return 0

s = 100

t1 = Timer('fib(s)', 'from __main__ import fib, s')
t2 = Timer('fibmem(s )', 'from __main__ import fibmem, s')
t1.repeat(numbe r=1)
t2.repeat(numbe r=1)
print t1.timeit()
print t2.timeit()

>>>
35.3092010297
1.6516613145
>>>

So memoization is 20+ times faster than the idiomatic way?
Or am I missing something here?
Ok for fun I added memoization to the idiomatic one:

from timeit import Timer
import Decorators

@Decorators.mem oize
def fib(n):
a, b = 1, 0
while n:
a, b, n = b, a+b, n-1
return b

@Decorators.mem oize
def fibmem(nbr):
if nbr 1:
return fibmem(nbr-1) + fibmem(nbr-2)
if nbr == 1:
return 1
if nbr == 0:
return 0

s = 100

t1 = Timer('fib(s)', 'from __main__ import fib, s')
t2 = Timer('fibmem(s )', 'from __main__ import fibmem, s')
t1.repeat(numbe r=1)
t2.repeat(numbe r=1)
print t1.timeit()
print t2.timeit()
didn't think it would make a difference there but it certainly did.

>>>
1.59592657726
1.60179436213
>>============= =============== ==== RESTART =============== =============== ==
2.66468922726
3.0870236301
>>============= =============== ==== RESTART =============== =============== ==
1.62921684181
1.51585159566
>>============= =============== ==== RESTART =============== =============== ==
1.49457319296
1.60948472501
>>============= =============== ==== RESTART =============== =============== ==
1.48718203012
1.6645559701
>>>
Aug 2 '08 #1
7 1996
Nothing weird about this ...
The difference will become larger as your input value becomes larger.

You can easily understand why if you try to calculate fib(10) by hand,
i.e. work through the algorithm with pencil and paper,
then compare the work you have to do to the memoized version which just
takes fib(9) and fib(8) from memory and adds them together.

Best regards,
Stefaan.
Aug 2 '08 #2
Stefaan Himpe wrote in news:2m******** ************@ne wsfe16.ams2 in
comp.lang.pytho n:
Nothing weird about this ...
The difference will become larger as your input value becomes larger.

You can easily understand why if you try to calculate fib(10) by hand,
i.e. work through the algorithm with pencil and paper,
then compare the work you have to do to the memoized version which just
takes fib(9) and fib(8) from memory and adds them together.
I think you missed the point.

The problem is that the un-decorated, loop only version takes
35 seconds when called by timeit.Timer. However if you apply
the decorator it takes less that a second. In *both* cases
the function (fib) only gets called once.

Note, I timed the call fib(100) with time.clock() and got a
value of less than 1 ms, the memozed version takes about 10
times longer.

So the question is: whats going on with timeit.Timer ?

Rob.
--
http://www.victim-prime.dsl.pipex.com/
Aug 2 '08 #3
On Sat, 02 Aug 2008 06:02:02 -0700, ssecorp wrote:
I am not clear about the results here.
from timeit import Timer
import Decorators

def fib(n):
a, b = 1, 0
while n:
a, b, n = b, a+b, n-1
return b
[...]
s = 100

t1 = Timer('fib(s)', 'from __main__ import fib, s')
t2 = Timer('fibmem(s )', 'from __main__ import fibmem, s')
t1.repeat(numbe r=1)
t2.repeat(numbe r=1)
print t1.timeit()
print t2.timeit()
35.3092010297
1.6516613145

So memoization is 20+ times faster than the idiomatic way? Or am I
missing something here?
Memoization *can be* faster, not *is* -- memoization requires work, and
if it is more work to look something up than to calculate it, then it
will be a pessimation instead of an optimization. That's probably less of
an issue with high-level languages like Python, but in low level
languages you would need to start thinking about processor caches and all
sorts of complications.

But I digress... in Python, yes, I would expect a significant speedup
with memoization. That's why people use it.
Ok for fun I added memoization to the idiomatic one:
[...]
didn't think it would make a difference there but it certainly did.

1.59592657726
1.60179436213
Just curious, but why don't you show the results of the call to repeat()?
It makes me uncomfortable to see somebody showing only half their output.

But yes, with memoization, the lookup to find the Fibonacci number should
decrease the time it takes to calculate the Fibonacci number. I'm not
sure why you are surprised. Regardless of which Fibonacci algorithm you
are using, the Timer object is essentially timing one million lookups,
minus 100 calculations of the Fibonacci number. The 999,900 cache lookups
will dominate the time, far outweighing the 100 calculations, regardless
of which method of calculation you choose. That's why the results are
almost identical.

--
Steven
Aug 3 '08 #4
On Sat, 02 Aug 2008 16:14:11 -0500, Rob Williscroft wrote:
Stefaan Himpe wrote in news:2m******** ************@ne wsfe16.ams2 in
comp.lang.pytho n:
>Nothing weird about this ...
The difference will become larger as your input value becomes larger.

You can easily understand why if you try to calculate fib(10) by hand,
i.e. work through the algorithm with pencil and paper, then compare the
work you have to do to the memoized version which just takes fib(9) and
fib(8) from memory and adds them together.

I think you missed the point.

The problem is that the un-decorated, loop only version takes 35 seconds
when called by timeit.Timer. However if you apply the decorator it
takes less that a second. In *both* cases the function (fib) only gets
called once.
I think you are completely misreading the results of the Timeit calls.
That's not correct: you're calling it one million times, not once.

You should apply a "sanity check" to results. At the interactive console,
call the undecorated fib(100) once. Does it take 35 seconds? If so, your
computer is terribly slow -- on mine, it returns instantly.

Note that in your email, you showed only half the output:
[quote]
t1 = Timer('fib(s)', 'from __main__ import fib, s')
t2 = Timer('fibmem(s )', 'from __main__ import fibmem, s')
t1.repeat(numbe r=1)
t2.repeat(numbe r=1)
print t1.timeit()
print t2.timeit()

>>>
35.3092010297
1.6516613145
[end quote]

You had two calls to Timer.repeat() methods, and you didn't show the
output. *They* call the Fibonacci functions once. When I do that, I get
output looking like this:
>>t1 = Timer('fib(s)', 'from __main__ import fib, s')
t1.repeat(num ber=1)
[7.9870223999023 438e-05, 5.5074691772460 938e-05, 5.4121017456054 688e-05]

You then call the Timer.timeit() method, which calls the function one
million times by default. That's the output you show: notice that 35s
divided by one million is 3.5e-05s, around what I get using the repeat()
method. There's no mystery.

Note, I timed the call fib(100) with time.clock() and got a value of
less than 1 ms, the memozed version takes about 10 times longer.
You shouldn't give much credence to timing results from calling a
function once (unless the function does a *lot* of work). Your operating
system is doing all sorts of work in the background. It can easily
interrupt your process mid-calculation to do something else, and your
timing code will then include that. You'll then wrongly conclude that the
function is slower than it really is.

Also, keep in mind that time.clock() is likely to be significantly less
accurate if you are using Linux. The timeit module automatically choose
the best function to use (time.clock vs time.time) for you.
So the question is: whats going on with timeit.Timer ?
As far as I can see, nothing. I think you have misunderstood the results
you got.

--
Steven
Aug 3 '08 #5
I think you are confusing 2 people in this thread but that doesn't
really matter.
What surprised me was that I didn't think fib would benefit from
memoization because it didn't repeat the same calculations. fibmem
without memoization is the classic naive implementation that grows
exponentially and obv that would benefit from memoization.
from timeit import Timer
import Decorators

@Decorators.mem oize
def fib(n):
a, b = 1, 0
while n:
a, b, n = b, a+b, n-1
return b

@Decorators.mem oize
def fibmem(nbr):
if nbr 1:
return fibmem(nbr-1) + fibmem(nbr-2)
if nbr == 1:
return 1
if nbr == 0:
return 0

s = 100
t1 = Timer('fib(s)', 'from __main__ import fib, s')
t2 = Timer('fibmem(s )', 'from __main__ import fibmem, s')
print t1.repeat(numbe r=1)
print t2.repeat(numbe r=1)
print t1.timeit()
print t2.timeit()

>>>
[4.8888895097002 557e-005, 3.6317464929201 785e-006,
3.0730162632401 604e-006]
[0.0014432001832 635141, 5.5873022968000 452e-006,
3.0730162632417 596e-006]
1.4421612244
1.34121264015
>>>
Aug 3 '08 #6
Steven D'Aprano wrote in news:00******** **************@ news.astraweb.c om in
comp.lang.pytho n:
>So the question is: whats going on with timeit.Timer ?

As far as I can see, nothing. I think you have misunderstood the results
you got.
No, the answer is that is it repeats a million times. It might better be
called repeat_one_mill ion_times().

Or put another way, myself and the OP misinterpreted what the call
t1.repeat( number = 1 ) did.

its a confusing API.

For the OP:

The call t1.timeit() is equivalent to t1.repeat( number = 1000000 ).

So it bennefits from memoization because the call *is* repeated, not
just called once like you intended.

Rob.
--
http://www.victim-prime.dsl.pipex.com/
Aug 3 '08 #7
On Sun, 03 Aug 2008 09:46:45 -0500, Rob Williscroft wrote:
Steven D'Aprano wrote in news:00******** **************@ news.astraweb.c om
in comp.lang.pytho n:
>>So the question is: whats going on with timeit.Timer ?

As far as I can see, nothing. I think you have misunderstood the
results you got.

No, the answer is that is it repeats a million times. It might better
be called repeat_one_mill ion_times().
But that would be seriously broken if you call it like this:

Timer.repeat_on e_million_times (5, 1000)

It doesn't repeat one million times. It repeats five times, of 1000 loops
each.

Or put another way, myself and the OP misinterpreted what the call
t1.repeat( number = 1 ) did.

its a confusing API.
There's certainly confusion happening. Perhaps reading the doc strings
might clear up some confusion? help(Timer.repe at) and help(Timer.time it)
state very clearly that they default to one million iterations.

For the OP:

The call t1.timeit() is equivalent to t1.repeat( number = 1000000 ).
No it isn't. Try running the code and looking at the results it gives.

t1.repeat(numbe r=10**6) returns a list of three numbers. The function is
called *three* million times in total.

t1.timeit() returns a single number.

In fact, t1.timeit() is equivalent to
t1.repeat(repea t=1, number=1000000) , (apart from it being in a list).
That can be written more simply as: t1.repeat(1)
--
Steven
Aug 3 '08 #8

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

2
1130
by: 42zeros | last post by:
I would like a function to be executed every x often. I was just wondering how to pass the following code correctly. my object t just doesn't know what checkMail is. How can I tell it that checkMail is a member of the class MyApp? thanks in advance, code is below class MyApp(wx.App):
2
7039
by: laurenq uantrell | last post by:
I have been using the following function to test the speed of various functions, however, quite often the return value is zero. I'm hoping someone can help improve on this. Function TimeIt() As Single On Error GoTo CodeErr 'PURPOSE: Times a process in seconds from start to finish 'USAGE: msgbox TimeIt Dim sngStart As Single
1
5668
by: martinm69x | last post by:
Hey all, I've been working on the code for a kernel timer which will report real time, CPU time, user time and kernel time on the operation of fibonacci method. The way im doing it is keeping track of the parent and two child times (using fork()). I can get parent times to come up, however i do not think they are
1
2134
by: Dongsheng Ruan | last post by:
Hi Does anybody know how to pass multiple arguments to the function tested in timeit.timer() in python? I googled and found how to pass one argument: x=10000 mytime = timeit.Timer( setup="from Createlst import createlst", stmt=
3
5527
by: silverburgh.meryl | last post by:
Hi, I have a function in my python like this: def callFunc(line, no): # some code And I want to do a performance test like this: for line in f: for i in range(int(count)): t1 = timeit.Timer("callFunc(line, i)","from __main__
3
1343
by: rah | last post by:
what is code for fibonacci in memoization version and Dynamic programming
19
5210
by: colin | last post by:
Hi, Im trying to time some parts of my code using the Stopwatch class, but it is so slow, I tried the QueryPerformanceFrequency() but this seems to be just as slow, if I just simply call this function in a loop it takes 21 ticks with a reported frequency of 3.5mhz its is about 6us wich is over 12k instructions on my 2ghz cpu. this negates the idea of having a high res timer ...
7
3505
by: cnb | last post by:
This must be because of implementation right? Shouldn't reduce be faster since it iterates once over the list? doesnt sum first construct the list then sum it? ----------------------- reduce with named function: 37.9864357062 reduce with nested, named function: 39.4710288598 reduce with lambda: 39.2463927678 sum comprehension: 25.9530121845
0
9568
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However, people are often confused as to whether an ONU can Work As a Router. In this blog post, we’ll explore What is ONU, What Is Router, ONU & Router’s main usage, and What is the difference between ONU and Router. Let’s take a closer look ! Part I. Meaning of...
0
9399
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can effortlessly switch the default language on Windows 10 without reinstalling. I'll walk you through it. First, let's disable language synchronization. With a Microsoft account, language settings sync across devices. To prevent any complications,...
1
9955
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows Update option using the Control Panel or Settings app; it automatically checks for updates and installs any it finds, whether you like it or not. For most users, this new feature is actually very convenient. If you want to control the update process,...
0
9833
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each protocol has its own unique characteristics and advantages, but as a user who is planning to build a smart home system, I am a bit confused by the choice of these technologies. I'm particularly interested in Zigbee because I've heard it does some...
0
8831
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing, and deployment—without human intervention. Imagine an AI that can take a project description, break it down, write the code, debug it, and then launch it, all on its own.... Now, this would greatly impact the work of software developers. The idea...
1
7378
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new presenter, Adolph Dupré who will be discussing some powerful techniques for using class modules. He will explain when you may want to use classes instead of User Defined Types (UDT). For example, to manage the data in unbound forms. Adolph will...
0
6649
by: conductexam | last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and then checking html paragraph one by one. At the time of converting from word file to html my equations which are in the word document file was convert into image. Globals.ThisAddIn.Application.ActiveDocument.Select();...
0
5421
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
2
3531
muto222
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.