memoize (reposting via ML)

H

Hal Fulton

(Reposting via ML as gateway apparently didn't send this through.)


I was trying to use memoize the other day (v 1.2 from Dan Berger --
is there a different/better one?). Ran into some problems...

In this dumb example, where I'm passing the same parameter every time,
the speed should *blaze*, should it not?

This doesn't work for me. I see no measurable speed difference in these
three cases. What am I doing wrong?

Thanks,
Hal

require 'memoize'

include Memoize

def zeta(x)
r2d = 360.0/(2.0*Math::pI) # Radians to degrees
2.0*(Math.sin(x/r2d))*(Math.cos(x/r2d))
end

puts Time.now
1000000.times { z = zeta(2.0) }
puts Time.now

memoize:)zeta)

puts Time.now
1000000.times { z = zeta(2.0) }
puts Time.now

memoize:)zeta,"z.cache")

puts Time.now
1000000.times { z = zeta(2.0) }
puts Time.now
 
M

MenTaLguY

This doesn't work for me. I see no measurable speed difference in these
three cases. What am I doing wrong?

It may be that (relative to the overhead of method calls, etc), the
calculation is less expensive than you suppose.

-mental
 
H

Hal Fulton

MenTaLguY said:
It may be that (relative to the overhead of method calls, etc), the
calculation is less expensive than you suppose.

C'est possible... but with the silly hash-based implementation in
TRW1, I saw a significant speedup of this same function. And
memoize is not *so* complicated...

James Edward Gray, are you listening? Don't you have a memoize of
your own? What does it do with this function?


Cheers,
Hal
 
B

Brian Buckley

------=_Part_19194_14061130.1138760311107
Content-Type: text/plain; charset=ISO-8859-1
Content-Transfer-Encoding: quoted-printable
Content-Disposition: inline

I added a "sleep 1" line to zeta to exaggerate the time of an uncached
method call.

It is working.

--Brian Buckley

def zeta(x)
sleep 1
r2d =3D 360.0/(2.0*Math::pI) # Radians to degrees
2.0*(Math.sin(x/r2d))*(Math.cos(x/r2d))
end

t1 =3D Time.now
10.times { z =3D zeta(2.0) }
t2 =3D Time.now

memoize:)zeta)

t3 =3D Time.now
10.times { z =3D zeta(2.0) }
t4 =3D Time.now

memoize:)zeta,"z.cache")
t5 =3D Time.now
10.times { z =3D zeta(2.0) }
t6 =3D Time.now

puts "#{t2 - t1}, #{t4 - t3}, #{t6 - t5}" # =3D> 10.0, 1.0, 0.0

------=_Part_19194_14061130.1138760311107--
 
J

James Edward Gray II

--Apple-Mail-3--602790037
Content-Transfer-Encoding: 7bit
Content-Type: text/plain;
charset=US-ASCII;
delsp=yes;
format=flowed

James Edward Gray, are you listening?

Yes, I am.
Don't you have a memoize of your own?

It's just a toy, but yes. I didn't bother packaging it up though,
since there didn't seem to be interest in it. I'll attach the
library to this message, in case you want to fiddle with it.
What does it do with this function?

Mine is maybe slightly faster, but it's really the same story.
Running with memoize.rb I see:

$ ruby hals_memoize.rb
Unmemoized:
4.436923 seconds.
Memoized:
5.266704 seconds.
Memoized (file):
5.324959 seconds.

My library shows:

$ ruby hals_memoize.rb
Unmemoized:
4.47798 seconds.
Memoized:
3.883453 seconds.

I have to agree with the others. The operations are just too fast.
You've got to get some processing or recursion in there to see a big
boost. Anything you can run 1,000,000 tests on without memoization
just isn't stressful enough to benefit from it much.

Anyway, here's the test I ran with my code:

require 'memoizable'

extend Memoizable

def zeta(x)
r2d = 360.0/(2.0*Math::pI) # Radians to degrees
2.0*(Math.sin(x/r2d))*(Math.cos(x/r2d))
end

puts "Unmemoized:"
start = Time.now
1000000.times { z = zeta(2.0) }
puts "#{Time.now - start} seconds."

memoize:)zeta)

puts "Memoized:"
start = Time.now
1000000.times { z = zeta(2.0) }
puts "#{Time.now - start} seconds."

__END__

And again the library is attached.

Sorry I wasn't more help.

James Edward Gray II


--Apple-Mail-3--602790037
Content-Transfer-Encoding: 7bit
Content-Type: text/x-ruby-script;
x-unix-mode=0644;
name="memoizable.rb"
Content-Disposition: attachment;
filename=memoizable.rb

#!/usr/local/bin/ruby -w

# memoizable.rb
#
# Created by James Edward Gray II on 2006-01-21.
# Copyright 2006 Gray Productions. All rights reserved.

#
# Have your class or module <tt>extend Memoizable</tt> to gain access to the
# #memoize method.
#
module Memoizable
#
# This method is used to replace a computationally expensive method with an
# equivalent method that will answer repeat calls for indentical arguments
# from a _cache_. To use, make sure the current class extends Memoizable,
# then call by passing the _name_ of the method you wish to cache results for.
#
# The _cache_ object can be any object supporting both #[] and #[]=. The keys
# used for the _cache_ are an Array of the arguments the method was called
# with and the values are just the returned results of the original method
# call. The default _cache_ is a simple Hash, providing in-memory storage.
#
def memoize( name, cache = Hash.new )
original = "__unmemoized_#{name}__"

#
# <tt>self.class</tt> is used for the top level, to modify Object, otherwise
# we just modify the Class or Module directly
#
([Class, Module].include?(self.class) ? self : self.class).class_eval do
alias_method original, name
private original
define_method(name) { |*args| cache[args] ||= send(original, *args) }
end
end
end

--Apple-Mail-3--602790037--
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Similar Threads


Members online

Forum statistics

Threads
473,969
Messages
2,570,161
Members
46,708
Latest member
SherleneF1

Latest Threads

Top