On 22 October 2013 13:00, Steven D'Aprano <steve+comp.lang.pyt...@pearwood.info> wrote: > On Tue, 22 Oct 2013 10:14:16 +0100, Oscar Benjamin wrote: > >> On 22 October 2013 00:41, Steven D'Aprano >> <steve+comp.lang.pyt...@pearwood.info> wrote: >>> >>> Are you suggesting that gcc is not a decent compiler? >> >> No. >> >>> If "optimize away >>> to the null program" is such an obvious thing to do, why doesn't the >>> most popular C compiler in the [FOSS] world do it? >> >> It does if you pass the appropriate optimisation setting (as shown in >> haypo's comment). I should have been clearer. > > "C can do nothing 10 times faster than Python!" -- well, okay, but what > does that tell you about my long-running web server app? Benchmarks at > the best of time are only suggestive, benchmarks for null programs are > even less useful.
This is precisely my point. They should show a benchmark that is not semantically equivalent to the null program. I modified their example to do that so that it wasn't simply a case of removing dead code and then found that the C version performed 6-7 times faster than the PyPy version. Had they simply stated that I would have been impressed. At the bottom of this post I show a much better benchmark that shows how PyPy can come very close to C performance for intensive floating point computation. Note that although it is simple the benchmark actually produces a result and none of the computation can be skipped as dead code (why would I put that in?). Also note that both the C binary and the script produce exactly the same numeric output. It's also a simple example of numerical integration - something that is often a bottleneck in scientific computation. For the benchmark I find that the gcc -O3 binary runs in 4.6s and PyPy runs the script in 6.9s (CPython 2.7 takes 600 seconds). That is impressive and makes me think that there may be no need for me to use C for things like that. To be sure I'd have to scale it up a bit to see what happens when I break it apart into many functions and use lists in PyPy vs arrays in C. > [...] >> They are more than carefully crafted. They are useless and misleading. >> It's reasonable to contrive of a simple CPU-intensive programming >> problem for benchmarking. But the program should do *something* even if >> it is contrived. Both programs here consist *entirely* of dead code. > > But since the dead code is *not* eliminated, it is actually executed. If > it's executed, it's not really dead, is it? Does it really matter that > you don't do anything with the result? I'm with Maciej on this one -- > *executing* the code given is faster in PyPy than in C, at least for this > C compiler. Maybe C is faster to not execute it. Is that really an > interesting benchmark? "C does nothing ten times faster than PyPy does > something!" I don't think it is reasonable to compare those things and I was joking when I said that the optimised C version was 600 times faster because this is an absurd benchmark - see the much better one below. > Given a sufficiently advanced static analyser, PyPy could probably > special-case programs that do nothing. Then you're in a race to compare > the speed at which the PyPy runtime environment can start up and do > nothing, versus a stand-alone executable that has to start up and do > nothing. If this is a benchmark that people care about, I suggest they > need to get out more :-) Like Chris I have also had situations where startup time mattered and it can vary substantially between different interpreters and binaries. I have GNU Octave on Windows and it literally takes 20 seconds to start up. Matlab is worse: it takes about 1 minute so I don't tend to use it for CLI scripts much. Oscar The benchmark: $ cat euler.py #!/usr/bin/env pypy import math def main(): x = 1 v = 0 t = 0 T = 1 dt = 2**-30 while t < T: dxdt = v dvdt = - x x += dt * dxdt v += dt * dvdt t += dt print('t = %.2e' % t) print('x = %.2e' % x) print('v = %.2e' % v) print('x_err = %.e' % (x - math.cos(t))) print('x_err = %.2e' % (v + math.sin(t))) main() $ time pypy euler.py t = 1.00e+00 x = 5.40e-01 v = -8.41e-01 x_err = 3e-10 x_err = -3.92e-10 real 0m6.907s user 0m0.076s sys 0m0.045s $ cat euler.c #include <stdio.h> #include <math.h> int main() { double x = 1; double v = 0; double t = 0; double T = 1; double dt = pow(2, -30); double dxdt, dvdt; while (t < T) { dxdt = v; dvdt = - x; x += dt * dxdt; v += dt * dvdt; t += dt; } printf("t = %.2e\n", t); printf("x = %.2e\n", x); printf("v = %.2e\n", v); printf("x_err = %.e\n", x - cos(t)); printf("x_err = %.2e\n", v + sin(t)); return 0; } $ gcc -O3 euler.c $ time ./a.exe t = 1.00e+000 x = 5.40e-001 v = -8.41e-001 x_err = 3e-010 x_err = -3.92e-010 real 0m4.609s user 0m0.015s sys 0m0.000s $ time python euler.py # CPython 2.7 t = 1.00e+00 x = 5.40e-01 v = -8.41e-01 x_err = 3e-10 x_err = -3.92e-10 real 9m51.818s user 0m0.015s sys 0m0.015s -- https://mail.python.org/mailman/listinfo/python-list