Python is darn fast (was: How fast is Python)

Tim Hochberg tim.hochberg at ieee.org
Sun Aug 24 22:40:24 CEST 2003


Michele Simionato wrote:
> I finally came to the conclusion that the exceeding good performance
> of Psyco was due to the fact that the function was called a million
> times with the *same* argument. Evidently Psyco is smart enough to
> notice that. Changing the argument at each call
> (erfc(0.456) -> i/1000000.0) slows down Python+Psyco at 1/4 of C speed. 
> Psyco improves Python performance by an order of magnitude, but still it 
> is not enough :-(

This is not suprising. Last I checked, Psyco does not fully compile 
floating point expressions. If, I rememeber correctly (though every time 
try to delve too deeply into Psyco my brains start oozing out my ears), 
there are three ways a in which a given chunk of code evaluated. At one 
level, which I'll call #1, Psyco generates the machine code(*) for the 
expression. At a second level, Psyco calls out to C helper functions, 
but still works with unboxed values. At the third level, Psyco punts and 
  creates a Python object and hands things off to the interpreter.

Most integer functions operate at level #1, so they tend to be quite 
fast. Most floating point operations operate at level #2, so they have a 
certain amount of overhead, but are still much faster than unpsyco 
(sane?) Python. I believe the reason for this is that x86 floating point 
operations are very messy, so Armin punted...

(*) Armin is working on virtual machine implementation of Psyco, so it 
should be available on non x86 machines soon.

FWIW,

-tim


> I was too optimistic!
> 
> Here I my numbers for Python 2.3, Psyco 1.0, Red Hat Linux 7.3, 
> Pentium II 366 MHz:
> 
> $ time p23 erf.py
> real    0m3.245s
> user    0m3.164s
> sys     0m0.037s
> 
> This is more than four times slower than optimized C:
> 
> $ gcc erf.c -lm -O3
> $ time ./a.out
> real    0m0.742s
> user    0m0.725s
> sys     0m0.002s
>  
> Here is the situation for pure Python
> 
> $time p23 erf.jy
> real    0m27.470s
> user    0m27.162s
> sys     0m0.023s
> 
> and, just for fun, here is Jython performance:
> 
> $ time jython erf.jy
> real    0m44.395s
> user    0m42.602s
> sys     0m0.389s
> 
> ----------------------------------------------------------------------
> 
> $ cat erf.py
> import math
> import psyco
> psyco.full()
> 
> def erfc(x):
>     exp = math.exp
> 
>     p  =  0.3275911
>     a1 =  0.254829592
>     a2 = -0.284496736
>     a3 =  1.421413741
>     a4 = -1.453152027
>     a5 =  1.061405429
> 
>     t = 1.0 / (1.0 + p*x)
>     erfcx = ( (a1 + (a2 + (a3 +
>                           (a4 + a5*t)*t)*t)*t)*t ) * exp(-x*x)
>     return erfcx
> 
> def main():
>     erg = 0.0
> 
>     for i in xrange(1000000):
>         erg += erfc(i/1000000.0)
> 
> if __name__ == '__main__':
>     main()
> 
> --------------------------------------------------------------------------
> 
> # python/jython version = same without "import psyco; psyco.full()"
> 
> --------------------------------------------------------------------------
> 
> $cat erf.c
> #include <stdio.h>
> #include <math.h>
> 
> double erfc( double x )
> {
>     double p, a1, a2, a3, a4, a5;
>     double t, erfcx;
> 
>     p  =  0.3275911;
>     a1 =  0.254829592;
>     a2 = -0.284496736;
>     a3 =  1.421413741;
>     a4 = -1.453152027;
>     a5 =  1.061405429;
> 
>     t = 1.0 / (1.0 + p*x);
>     erfcx = ( (a1 + (a2 + (a3 +
>      (a4 + a5*t)*t)*t)*t)*t ) * exp(-x*x);
> 
>     return erfcx;
> }
> 
> int main()
> {
>     double erg=0.0;
>     int i;
> 
>     for(i=0; i<1000000; i++)
>     {
>        erg = erg + erfc(i/1000000.0);
>     }
> 
>     return 0;
> }
> 
> Michele Simionato, Ph. D.
> MicheleSimionato at libero.it
> http://www.phyast.pitt.edu/~micheles/
> ---- Currently looking for a job ----





More information about the Python-list mailing list