#14214: Cythoned homsets
----------------------------------------------+-----------------------------
       Reporter:  SimonKing                   |         Owner:  tbd             
                 
           Type:  enhancement                 |        Status:  needs_work      
                 
       Priority:  major                       |     Milestone:  sage-5.10       
                 
      Component:  performance                 |    Resolution:                  
                 
       Keywords:  Hom, cython, cached method  |   Work issues:  How to store 
domain and codomain?
Report Upstream:  N/A                         |     Reviewers:                  
                 
        Authors:  Simon King                  |     Merged in:                  
                 
   Dependencies:  #14159, #12951, #13184      |      Stopgaps:                  
                 
----------------------------------------------+-----------------------------

Comment (by nbruin):

 I guess our discussion got side-tracked a little bit:
  - For `_domain` and `_codomain` there is no reason to use lazy_attribute.
 In absence of a dict (where our code doesn't matter) we need a descriptor
 that looks up the value elsewhere.
  - what we should really have a `cdef public` because then one and the
 same location is fast from C ''and'' python writes the python access code
 for us. But for that we have inheritance problems at the moment.

 Then there's the second bit, cythonization of lazy_attribute:
  - a proper cythonized version of lazy_attribute is faster in all cases,
 mostly by a factor 2 as far as I could see. Even with required
 `__cached_methods` storage, I get attribute retrieval (once cached) of
 `84.6 ns` rather than `547 ns`

 That actually means you COULD put a cythonized lazy_attribute on `_domain`
 and `_codomain`. The overhead compared to a custom nondatadescriptor is
 minimal, and within a factor 2 of a `dict` lookup. Here's the code I mean:

 {{{
 cdef class LazyAttribute:
     cdef public f
     cdef public str __name__
     def __init__(self,f):
         self.f=f
         self.__name__=f.__name__
     def __get__(self,a,cls):
         cdef CM
         cdef result
         if a is None:
             return lazy_attribute(self.f)
         try:
             # __cached_methods is supposed to be a public Cython
 attribute.
             # Apparently, these are *not* subject to name mangling.
             CM = getattr(a, '__cached_methods')
             if CM is None:
                 CM = {}
                 setattr(a, '__cached_methods', CM)
         except AttributeError,msg:
             CM = None
         if CM is not None:
             try:
                 return CM[self.__name__]
             except KeyError:
                 pass
         result = self.f(a)
         if result is NotImplemented:
             # Workaround: we make sure that cls is the class
             # where the lazy attribute self is actually defined.
             # This avoids running into an infinite loop
             # See About descriptor specifications
             for supercls in cls.__mro__:
                 if self.f.__name__ in supercls.__dict__ and self is
 supercls.__dict__[self.__name__]:
                     cls = supercls
             return getattr(super(cls, a),self.__name__)
         try:
             setattr(a, self.__name__, result)
         except AttributeError:
             if CM is not None:
                 CM[self.f.__name__] = result
                 return result
             raise
         return result
 }}}

 There's a bit of clean-up to do on this concerning returning a documented
 object when requested on the bare class. It works now, but only by reusing
 the old implementation. Is returning the descriptor object itself on the
 bare class customary/desirable behaviour?

-- 
Ticket URL: <http://trac.sagemath.org/sage_trac/ticket/14214#comment:52>
Sage <http://www.sagemath.org>
Sage: Creating a Viable Open Source Alternative to Magma, Maple, Mathematica, 
and MATLAB

-- 
You received this message because you are subscribed to the Google Groups 
"sage-trac" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To post to this group, send email to [email protected].
Visit this group at http://groups.google.com/group/sage-trac?hl=en.
For more options, visit https://groups.google.com/groups/opt_out.


Reply via email to