Hi,

During the last few weeks I've spent time optimizing code, among other
things.  A surprising number of random things I look at in Sage are
too slow by a factor of 10-100,
usually due to programming style.    One way to help to remedy that
would be to write a book or article about how to program Cython +
Python *efficiently*, and avoid the numerous traps.  Basically, one
false move in Python when implementing mathematics algorithms can
knock you down by a factor of 10-100 in speed.   As an example of
this, try multiplying polynomials in ZZ['x'] in Sage right now:

sage: R.<x> = ZZ[]
sage: timeit('x*x',number=10^6)
1000000 loops, best of 3: 1.96 µs per loop

FLINT could do that multiply in a few hundred nanoseconds, so why does
it take 2 microseconds (2000 nanoseconds)?  Because the code is
complicated and general, but was written without any thought about
efficiency.  By making a few changes (really making the code less
clever), I get:

sage: timeit('x*x', number=10^6)
1000000 loops, best of 3: 687 ns per loop


The categories implementation as it is in Sage must be changed or
removed.  There, I got your attention.

A few months ago some code was added to Sage by the combinat folks
called "categories".  I recently learned ObjectiveC, and found out
that this idea of "categories" goes back to smalltalk at least, and
was fully implemented in ObjectiveC in the mid 1980s.  It has little
to do with category theory in the sense of mathematics, though is
related.   Basically, it is a way to attach a bunch of generic methods
to a class without using inheritance.   So far so good.

The combinat folks implemented this programming idea in Sage not by
changing the Python languge, but by defining a custom __getattr__
method at sticking it in the base classes for Sage parents and
elements.   The problem: this means that every single method lookup on
every single Sage object seem to now have about 1500nanoseconds added
to it in completely unnecessary overhead.   Most of what Sage does is
call functions, so this is a huge, huge problem.   Try it out for
yourself:

 (1) Start up Sage and try this:

flat:~ wstein$ sage-4.4.4
----------------------------------------------------------------------
| Sage Version 4.4.4, Release Date: 2010-06-23                       |
| Type notebook() for the GUI, and license() for information.        |
----------------------------------------------------------------------
sage: QQ.testit = 'foobar'
sage: timeit('QQ.testit',number=10^6)
1000000 loops, best of 3: 2.43 µs per loop
sage: timeit('QQ.testit',number=10^6)
1000000 loops, best of 3: 2.53 µs per loop


This is on my OS X laptop, so your timings may be different.

  (2) Now go into SAGE_ROOT/devel/sage/sage/structure/parent.pyx
and change the line

    def __getattr__(self, name):

to

    def x__getattr__(self, name):

then restart sage with "sage -br"


----------------------------------------------------------------------
| Sage Version 4.4.4, Release Date: 2010-06-23                       |
| Type notebook() for the GUI, and license() for information.        |
----------------------------------------------------------------------
sage: QQ.testit = 'foobar'
sage: timeit('QQ.testit',number=10^6)
1000000 loops, best of 3: 1.53 µs per loop
sage: timeit('QQ.testit',number=10^6)
1000000 loops, best of 3: 1.54 µs per loop

----

This is a major problem.  The best solution I can think of at present
is to remove these methods from the top level of Sage, then add
objects like Parent_cat and Element_cat, and put them there.  Then
change all the combinat objects to derive from those classes.  I'm not
sure this would work though.

Anyway, a slowdown of more than 1 microsecond on everything throughout
sage is absolutely unacceptable.

So, big question -- am I just confused?  It seems impossible that
nobody noticed this before, or that people made a conscious decision
to let this code in if it slows down Sage this much.   (I.e., my guess
is that nobody even bothered to benchmark the code when refereeing
it.)

Robert B: since you were the one who decided to let this into Sage,
and since I know you know Python insanely well, am I just missing
something here?  It seems to me like this one patch is a huge drain on
Sage's performance...     So much so that I'm personally tempted to
just remove it for my own work.   But maybe I'm just missing something
obvious.

 --William

-- 
William Stein
Associate Professor of Mathematics
University of Washington
http://wstein.org

-- 
You received this message because you are subscribed to the Google Groups 
"sage-combinat-devel" group.
To post to this group, send email to sage-combinat-de...@googlegroups.com.
To unsubscribe from this group, send email to 
sage-combinat-devel+unsubscr...@googlegroups.com.
For more options, visit this group at 
http://groups.google.com/group/sage-combinat-devel?hl=en.

Reply via email to