[sage-devel] Re: Customizing hash for an instance of ?

Sat, 10 Sep 2011 10:11:27 -0700

Hi!

I think I have solved the main problem!!

I am now able to do:

  sage: class Foo:
  ....:     __metaclass__ = FastHash
  ....:     def __hash__(self):
  ....:         print "computing hash"
  ....:         return id(self)
  ....:
  sage: f = Foo()

When calling the hash for the first time, it is computed:
  sage: hash(f)
  computing hash
  91791312

The second time, it is taken from cache:
  sage: hash(f)
  91791312

It is quite fast:
  sage: %timeit hash(f)
  625 loops, best of 3: 557 ns per loop

Compare that timing with "the same" class without metaclass:
  sage: class Bar:
  ....:     def __hash__(self):
  ....:         return id(self)
  ....:
  sage: b = Bar()
  sage: hash(b)
  91765648
  sage: %timeit hash(b)
  625 loops, best of 3: 1.06 µs per loop

Another example. I create a fast-hash version of a univariate
polynomial class:
  sage: MyPolyRing = FastHash(QQ['x'].__class__)
  sage: P = MyPolyRing(QQ,'y')
  sage: P
  Univariate Polynomial Ring in y over Rational Field

The hash is the same as the "slow" hash:
  sage: Q = QQ['y']
  sage: hash(P)
  7267929297229424747
  sage: P is Q
  False
  sage: hash(Q) == hash(P)
  True

It is faster:
  sage: %timeit hash(P)
  625 loops, best of 3: 560 ns per loop
  sage: %timeit hash(Q)
  625 loops, best of 3: 3.13 µs per loop

And even better: The speed-up is available *after* initialisation as
well!
  sage: Q.__class__ = FastHash(Q.__class__)
  sage: %timeit hash(Q)
  625 loops, best of 3: 562 ns per loop

Conclusion: What I did might be a convenient way to take an existing
Python class and speed-up its __hash__ using Cython.
Todo: Pickling.

Best regards,
Simon

-- 
To post to this group, send an email to sage-devel@googlegroups.com
To unsubscribe from this group, send an email to 
sage-devel+unsubscr...@googlegroups.com
For more options, visit this group at http://groups.google.com/group/sage-devel
URL: http://www.sagemath.org

Reply via email to