Re: [matplotlib-devel] Experiments and questions / OpenGL backend

2011-07-29 Thread Nicolas Rougier


I just did it using the regular python profiler (and a pyglet backend because 
glut cannot be easily profiled).
Here are some results for exactly 1000 frames displayed:

> python -m cProfile  -s cumulative test_backend_pyglet.py
 7723453 function calls (7596399 primitive calls) in 16.583 seconds

   Ordered by: cumulative time

   ncalls  tottime  percall  cumtime  percall filename:lineno(function)
10.0040.004   16.587   16.587 test_backend_pyglet.py:1()
10.0000.000   14.000   14.000 pyplot.py:123(show)
10.0000.000   14.000   14.000 backend_pyglet.py:214(show)
10.0000.000   13.951   13.951 __init__.py:115(run)
10.0000.000   13.951   13.951 base.py:117(run)
10.0090.009   13.949   13.949 base.py:149(_run_estimated)
 10000.0180.000   13.6390.014 base.py:244(idle)
1119/11160.0090.000   13.3780.012 event.py:318(dispatch_event)
 10040.0060.000   13.3400.013 __init__.py:1148(dispatch_event)
 10000.0020.000   13.3260.013 backend_pyglet.py:319(on_draw)
 10000.0130.000   13.3240.013 backend_pyglet.py:324(draw)
 10000.0040.000   13.0010.013 
backend_pyglet.py:342(_render_figure)
6/10000.2040.000   12.9770.013 artist.py:53(draw_wrapper)
 10000.0230.000   12.9700.013 figure.py:805(draw)
 10000.0460.000   12.7750.013 axes.py:1866(draw)
 20000.0460.000   11.7910.006 axis.py:1029(draw)
10.0980.0008.5210.001 axis.py:219(draw)
210000.7100.0006.4670.000 lines.py:463(draw)
20.0300.0002.3010.000 
transforms.py:2234(get_transformed_points_and_affine)
210000.0930.0002.2450.000 transforms.py:2224(_revalidate)
10.0010.0012.0812.081 pylab.py:1()
10.0010.0012.0802.080 pylab.py:215()
 12/60.0070.0012.0360.339 {__import__}
10.0010.0011.9371.937 pyplot.py:15()
10.0000.0001.9351.935 __init__.py:14(pylab_setup)
10.0010.0011.9311.931 backend_pyglet.py:55()
10.0110.0111.9291.929 __init__.py:94()
68000/640000.4500.0001.8240.000 transforms.py:1732(transform)
150000.3810.0001.7260.000 text.py:514(draw)
 20000.0350.0001.7110.001 axis.py:977(_get_tick_bboxes)
10.0910.0001.6680.000 text.py:713(get_window_extent)
646050.6940.0001.5200.000 path.py:83(__init__)
240000.0670.0001.4910.000 
transforms.py:1155(transform_path_non_affine)
200410.4350.0001.4300.000 lines.py:386(recache)
440000.1180.0001.3850.000 
transforms.py:1761(transform_non_affine)
   1644521.3400.0001.3400.000 {numpy.core.multiarray.array}
20.0760.0001.1370.000 
transforms.py:1119(transform_point)


It does not seem to have superfluous call to the various methods (even if the 
plot is a simple 3 points line, there is a lot to draw) and maybe this means an 
efficient OpenGL backend would require some cache system to avoid repeating 
"useless" operations.


Nicolas


On Jul 28, 2011, at 3:15 PM, Michael Droettboom wrote:

> Have you tried running it in the Python profiler?  I find this script [1] in 
> combination with kcachegrind to be very useful in answering these kinds of 
> questions.
> 
> [1] http://codespeak.net/pypy/dist/pypy/tool/lsprofcalltree.py
> 
> Mike
> 
> On 07/28/2011 07:16 AM, Nicolas Rougier wrote:
>> 
>> 
>> 
>> I've created a fork at: https://github.com/rougier/matplotlib/tree/gl-backend
>> 
>> The name of the backend is glut (it requires OpenGL) and does not display 
>> anything, it only measures fps.
>> 
>> It seems to be stuck at 100fps with the following test script:
>> 
>> import matplotlib
>> matplotlib.use('glut')
>> from pylab import *
>> plot([1,2,3])
>> show()
>> 
>> while the same do-nothing window directly in pyOpenGL is around 2000fps on 
>> the same machine.
>> 
>> I would like to understand why this is so slow and if it can be fixed.
>> 
>> 
>> 
>> Nicolas
>> 
>> 
>> 
>> 
>> 
>> 
>> On Jul 27, 2011, at 3:28 PM, Benjamin Root wrote:
>> 
>>> 
>>> 
>>> On Wednesday, July 27, 2011, Nicolas Rougier  
>>> wrote:
>>> >
>>> >
>>> > Hi all,
>>> >
>>> > I've been testing various idea around the idea of a GL backend, and I 
>>> > would have a few questions.
>>> > First, I tried to use the backend template to quickly test an empty 
>>> > pyglet backend and I've been quite surprised by the bad performances. 
>>> > Without drawing anything, I can hardly reach 100FPS and I wonder if I did 
>>> > something wrong ? (The backend is available backend_pyglet.py 
>>> >  and the test file is 
>>> > at test_backend_pygle

Re: [matplotlib-devel] Matplotlib-devel Digest, Vol 62, Issue 11

2011-07-29 Thread David Kaplan
Hi,

I will be on vacation with limited email from July 14 to August 7, 2011.

Bonjour,

Je serai en conge du 14 juillet jusqu'au 7 aout, 2011.

--
Got Input?   Slashdot Needs You.
Take our quick survey online.  Come on, we don't ask for help often.
Plus, you'll get a chance to win $100 to spend on ThinkGeek.
http://p.sf.net/sfu/slashdot-survey
___
Matplotlib-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/matplotlib-devel


Re: [matplotlib-devel] Experiments and questions / OpenGL backend

2011-07-29 Thread Michael Droettboom

Nicolas,

I'm not sure how you've reached your conclusion.

The 21,000 calls to Line2D.draw (i.e. 21 per frame) are easily explained 
since each grid line (or tick) is in fact a line.


The 10,000 calls to Tick.draw (i.e. 10 per frame) are because there are 
10 tick labels.


likewise for Text.draw etc. and on down the list.

I don't see how any of these objects could be drawn without calling 
draw. ;)  There actually already is caching that occurs rendering text, 
for example.  None of these calls are strictly "useless".


If animation speed is important, there are tricks in the 
examples/animation directory that show how to reuse the ticks from a 
previous draw and only update the data (i.e. eliminate many of these 
"useless" draw calls).  But they are tricks -- they don't work for the 
general case of "anything in this plot may change at any time".


But I think you are comparing apples to oranges in your speed 
comparison.  You say a "do-nothing" loop in PyOpenGL runs at around 2000 
fps, and a "do-nothing" loop in matplotlib runs about 100fps.  But, of 
course, the matplotlib test case is actually doing a great deal even 
with the backend doing nothing -- it is doing all of the work of laying 
out the plot, which is the majority of time spent getting a plot to the 
screen.  And that all work happens in Python -- its speed is what it is 
and is acceptable in many contexts -- but no backend work is going to 
improve what's going on in the core.


I should warn you that previous attempts to speed up matplotlib using 
hardware acceleration have failed to produce much fruit because the 
backends actually do fairly little work by design in matplotlib.  The 
actual act of rendering paths into pixels on screen (i.e. what happens 
in the backend) is a small fraction of the run time, even when using a 
software renderer (eg. Agg).  Here's a useful benchmark that renders a 
plot a bunch of times to memory:


  import sys
  import matplotlib
  matplotlib.use(sys.argv[-1])
  from pylab import *
  import numpy
  plot(numpy.arange(int(sys.argv[-2])))
  for i in xrange(1000):
  draw()

and the results (on my 2.33GHz Intel E6550):

> time python test_backend_speed.py 3 agg

real0m15.211s
user0m15.009s
sys 0m0.136s

# Here "backend_pyglet" is the do-nothing backend you sent to the list 
in a previous e-mail

> time python test_backend_speed.py 3 module://backend_pyglet

real0m14.038s
user0m13.713s
sys 0m0.256s

> time python test_backend_speed.py 100 agg

real0m23.038s
user0m22.845s
sys 0m0.132s

> time python test_backend_speed.py 100 module://backend_pyglet

real0m15.251s
user0m14.837s
sys 0m0.304s

So you see the actual work in the backend can be a fairly small fraction 
of the total runtime -- that gives one an idea of the upper bound on the 
speed improvement that any backend could make without digging into the 
matplotlib core and making improvements there.


In fairness, my test is not measuring the time to (once rendering the 
plot) blit it to the screen.  I suspect OpenGL will have an advantage 
there.  It may even be possible as a mid-way solution to create an 
Agg/OpenGL backend that used Agg for rendering and OpenGL -- that's 
something that would be really useful just to have another nice 
cross-platform GUI backend.


The other important thing to note about this benchmark is that as the 
size of the data increases, the proportion of time spent in the backend 
increases.


I'm also worried (and I have no numbers to back this up) that a pyglet 
or PyOpenGL backend may actually be slower if the work to convert paths 
from matplotlib's path.Path format to the format understood by pyglet 
and/or PyOpenGL happens in Python, as your preliminary code 
backend_pyglet.py does in draw_path (i.e. looping over each vertex in a 
Python loop.)  In the Agg backend, that happens in C++ on-the-fly 
without copying the data -- see src/path_converters.h.  This code is 
exposed to Python through matplotlib._path.cleanup_path, but that does 
require copying memory, which for large data sets may be a limiting 
factor.  So you may end up needing to write the backend in C++ to really 
beat the current Agg backend, but I'd love to be proven wrong.


I hope this helps to better illustrate what you're seeing, and I don't 
mean to discourage you in implementing an OpenGL-based backend (which 
would be very nice to have for portability reasons among others).  But I 
hope this also illustrates that if the end goal is simply to "go 
faster", this may be somewhat like putting racing tires on a car without 
replacing the engine.


Cheers,
Mike

On 07/29/2011 03:09 AM, Nicolas Rougier wrote:



I just did it using the regular python profiler (and a pyglet backend 
because glut cannot be easily profiled).

Here are some results for exactly 1000 frames displayed:

> python -m cProfile  -s cumulative test_backend_pyglet.py
 7723453 function calls (7596399 primitive calls) in 16.583 

Re: [matplotlib-devel] Matplotlib-devel Digest, Vol 62, Issue 12

2011-07-29 Thread David Kaplan
Hi,

I will be on vacation with limited email from July 14 to August 7, 2011.

Bonjour,

Je serai en conge du 14 juillet jusqu'au 7 aout, 2011.

--
Got Input?   Slashdot Needs You.
Take our quick survey online.  Come on, we don't ask for help often.
Plus, you'll get a chance to win $100 to spend on ThinkGeek.
http://p.sf.net/sfu/slashdot-survey
___
Matplotlib-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/matplotlib-devel


Re: [matplotlib-devel] Experiments and questions / OpenGL backend

2011-07-29 Thread Benjamin Root
On Fri, Jul 29, 2011 at 11:05 AM, Michael Droettboom wrote:

> **
> Nicolas,
>
> I'm not sure how you've reached your conclusion.
>
> The 21,000 calls to Line2D.draw (i.e. 21 per frame) are easily explained
> since each grid line (or tick) is in fact a line.
>
> The 10,000 calls to Tick.draw (i.e. 10 per frame) are because there are 10
> tick labels.
>
> likewise for Text.draw etc. and on down the list.
>
> I don't see how any of these objects could be drawn without calling draw.
> ;)  There actually already is caching that occurs rendering text, for
> example.  None of these calls are strictly "useless".
>
> If animation speed is important, there are tricks in the examples/animation
> directory that show how to reuse the ticks from a previous draw and only
> update the data (i.e. eliminate many of these "useless" draw calls).  But
> they are tricks -- they don't work for the general case of "anything in this
> plot may change at any time".
>
> But I think you are comparing apples to oranges in your speed comparison.
> You say a "do-nothing" loop in PyOpenGL runs at around 2000 fps, and a
> "do-nothing" loop in matplotlib runs about 100fps.  But, of course, the
> matplotlib test case is actually doing a great deal even with the backend
> doing nothing -- it is doing all of the work of laying out the plot, which
> is the majority of time spent getting a plot to the screen.  And that all
> work happens in Python -- its speed is what it is and is acceptable in many
> contexts -- but no backend work is going to improve what's going on in the
> core.
>
> I should warn you that previous attempts to speed up matplotlib using
> hardware acceleration have failed to produce much fruit because the backends
> actually do fairly little work by design in matplotlib.  The actual act of
> rendering paths into pixels on screen (i.e. what happens in the backend) is
> a small fraction of the run time, even when using a software renderer (eg.
> Agg).  Here's a useful benchmark that renders a plot a bunch of times to
> memory:
>
>   import sys
>   import matplotlib
>   matplotlib.use(sys.argv[-1])
>   from pylab import *
>   import numpy
>   plot(numpy.arange(int(sys.argv[-2])))
>   for i in xrange(1000):
>   draw()
>
> and the results (on my 2.33GHz Intel E6550):
>
> > time python test_backend_speed.py 3 agg
>
> real0m15.211s
> user0m15.009s
> sys 0m0.136s
>
> # Here "backend_pyglet" is the do-nothing backend you sent to the list in a
> previous e-mail
> > time python test_backend_speed.py 3 module://backend_pyglet
>
> real0m14.038s
> user0m13.713s
> sys 0m0.256s
>
> > time python test_backend_speed.py 100 agg
>
> real0m23.038s
> user0m22.845s
> sys 0m0.132s
>
> > time python test_backend_speed.py 100 module://backend_pyglet
>
> real0m15.251s
> user0m14.837s
> sys 0m0.304s
>
> So you see the actual work in the backend can be a fairly small fraction of
> the total runtime -- that gives one an idea of the upper bound on the speed
> improvement that any backend could make without digging into the matplotlib
> core and making improvements there.
>
> In fairness, my test is not measuring the time to (once rendering the plot)
> blit it to the screen.  I suspect OpenGL will have an advantage there.  It
> may even be possible as a mid-way solution to create an Agg/OpenGL backend
> that used Agg for rendering and OpenGL -- that's something that would be
> really useful just to have another nice cross-platform GUI backend.
>
> The other important thing to note about this benchmark is that as the size
> of the data increases, the proportion of time spent in the backend
> increases.
>
> I'm also worried (and I have no numbers to back this up) that a pyglet or
> PyOpenGL backend may actually be slower if the work to convert paths from
> matplotlib's path.Path format to the format understood by pyglet and/or
> PyOpenGL happens in Python, as your preliminary code backend_pyglet.py does
> in draw_path (i.e. looping over each vertex in a Python loop.)  In the Agg
> backend, that happens in C++ on-the-fly without copying the data -- see
> src/path_converters.h.  This code is exposed to Python through
> matplotlib._path.cleanup_path, but that does require copying memory, which
> for large data sets may be a limiting factor.  So you may end up needing to
> write the backend in C++ to really beat the current Agg backend, but I'd
> love to be proven wrong.
>
> I hope this helps to better illustrate what you're seeing, and I don't mean
> to discourage you in implementing an OpenGL-based backend (which would be
> very nice to have for portability reasons among others).  But I hope this
> also illustrates that if the end goal is simply to "go faster", this may be
> somewhat like putting racing tires on a car without replacing the engine.
>
> Cheers,
> Mike
>
>
Nicolas,

I would like to add to Mike's comments by making it clear why I am
interested in having OpenGL for matplotlib.  It is not for speed

Re: [matplotlib-devel] Experiments and questions / OpenGL backend

2011-07-29 Thread Nicolas Rougier


I'm sorry to have used the term "useless" since it was not what I meant. In 
fact, after profiling the simple draw example, I realized there were a lot of 
necessary operations that were not quite visible from my "external" point of 
view. I was just thinking "why the hell is it so slow to draw some lines and 
ticks". I think you explained very clearly the actual situation. Also, I've 
been coded glumpy that mix matplotlib and OpenGL (for imshow operations only) 
quite efficiently and I thought something similar could be done for regular 
plot. Anyway, I will try to code further the GL backend without paying too much 
attention to speed right now.

Thanks a lot for all the explanations.


Nicolas


On Jul 29, 2011, at 6:05 PM, Michael Droettboom wrote:

> Nicolas,
> 
> I'm not sure how you've reached your conclusion.
> 
> The 21,000 calls to Line2D.draw (i.e. 21 per frame) are easily explained 
> since each grid line (or tick) is in fact a line.
> 
> The 10,000 calls to Tick.draw (i.e. 10 per frame) are because there are 10 
> tick labels.
> 
> likewise for Text.draw etc. and on down the list.
> 
> I don't see how any of these objects could be drawn without calling draw. ;)  
> There actually already is caching that occurs rendering text, for example.  
> None of these calls are strictly "useless".
> 
> If animation speed is important, there are tricks in the examples/animation 
> directory that show how to reuse the ticks from a previous draw and only 
> update the data (i.e. eliminate many of these "useless" draw calls).  But 
> they are tricks -- they don't work for the general case of "anything in this 
> plot may change at any time".
> 
> But I think you are comparing apples to oranges in your speed comparison.  
> You say a "do-nothing" loop in PyOpenGL runs at around 2000 fps, and a 
> "do-nothing" loop in matplotlib runs about 100fps.  But, of course, the 
> matplotlib test case is actually doing a great deal even with the backend 
> doing nothing -- it is doing all of the work of laying out the plot, which is 
> the majority of time spent getting a plot to the screen.  And that all work 
> happens in Python -- its speed is what it is and is acceptable in many 
> contexts -- but no backend work is going to improve what's going on in the 
> core.
> 
> I should warn you that previous attempts to speed up matplotlib using 
> hardware acceleration have failed to produce much fruit because the backends 
> actually do fairly little work by design in matplotlib.  The actual act of 
> rendering paths into pixels on screen (i.e. what happens in the backend) is a 
> small fraction of the run time, even when using a software renderer (eg. 
> Agg).  Here's a useful benchmark that renders a plot a bunch of times to 
> memory:
> 
>   import sys
>   import matplotlib
>   matplotlib.use(sys.argv[-1])
>   from pylab import *
>   import numpy
>   plot(numpy.arange(int(sys.argv[-2])))
>   for i in xrange(1000):
>   draw()
> 
> and the results (on my 2.33GHz Intel E6550):
> 
> > time python test_backend_speed.py 3 agg
> 
> real0m15.211s
> user0m15.009s
> sys 0m0.136s
> 
> # Here "backend_pyglet" is the do-nothing backend you sent to the list in a 
> previous e-mail
> > time python test_backend_speed.py 3 module://backend_pyglet
> 
> real0m14.038s
> user0m13.713s
> sys 0m0.256s
> 
> > time python test_backend_speed.py 100 agg
> 
> real0m23.038s
> user0m22.845s
> sys 0m0.132s
> 
> > time python test_backend_speed.py 100 module://backend_pyglet
> 
> real0m15.251s
> user0m14.837s
> sys 0m0.304s
> 
> So you see the actual work in the backend can be a fairly small fraction of 
> the total runtime -- that gives one an idea of the upper bound on the speed 
> improvement that any backend could make without digging into the matplotlib 
> core and making improvements there.
> 
> In fairness, my test is not measuring the time to (once rendering the plot) 
> blit it to the screen.  I suspect OpenGL will have an advantage there.  It 
> may even be possible as a mid-way solution to create an Agg/OpenGL backend 
> that used Agg for rendering and OpenGL -- that's something that would be 
> really useful just to have another nice cross-platform GUI backend.
> 
> The other important thing to note about this benchmark is that as the size of 
> the data increases, the proportion of time spent in the backend increases.
> 
> I'm also worried (and I have no numbers to back this up) that a pyglet or 
> PyOpenGL backend may actually be slower if the work to convert paths from 
> matplotlib's path.Path format to the format understood by pyglet and/or 
> PyOpenGL happens in Python, as your preliminary code backend_pyglet.py does 
> in draw_path (i.e. looping over each vertex in a Python loop.)  In the Agg 
> backend, that happens in C++ on-the-fly without copying the data -- see 
> src/path_converters.h.  This code is exposed to Python through 
> matplotlib._path.cleanup_path, but that does r

Re: [matplotlib-devel] Matplotlib-devel Digest, Vol 62, Issue 13

2011-07-29 Thread David Kaplan
Hi,

I will be on vacation with limited email from July 14 to August 7, 2011.

Bonjour,

Je serai en conge du 14 juillet jusqu'au 7 aout, 2011.

--
Got Input?   Slashdot Needs You.
Take our quick survey online.  Come on, we don't ask for help often.
Plus, you'll get a chance to win $100 to spend on ThinkGeek.
http://p.sf.net/sfu/slashdot-survey
___
Matplotlib-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/matplotlib-devel


Re: [matplotlib-devel] Experiments and questions / OpenGL backend

2011-07-29 Thread Nicolas Rougier
> 
> Nicolas,
> 
> I would like to add to Mike's comments by making it clear why I am interested 
> in having OpenGL for matplotlib.  It is not for speed.  The last time I 
> checked, a good portion of time is actually spent on the axis tickers and 
> automatic limits.  So, if speed is your goal, then that might be the better 
> place to look.
> 
> No, my main interest in OpenGL is to relax matplotlib's 2D limitation.  At 
> the core of matplotlib is a 2D layering engine that was perfectly suited for 
> 2D graphing.  mplot3d then takes advantage of that layering feature to 
> hack-on 3D functionality.  However, as has been noted many, many times, this 
> does not always produce correct results.  I would love for the 2D layering 
> core to have some sort of logic where if the OpenGL backend is in use, and if 
> 3D art objects are detected, then bypass the dimension reduction that is done 
> in the layering engine and send the full 3D data over to OpenGL and let it 
> figure out the correct 2D projection.
> 
> However, I am not an OpenGL programmer and I wouldn't even know where to 
> start.  That is why I am very happy to see someone give this another try.  
> Also, as a side note, in discussions with Ryan May (who did the previous 
> attempt at using pyglet), the main reason he discontinued development at that 
> time was because the text rendering in pyglet was very poor and not 
> anti-aliased.  Do you have any indication if that has improved or not?
> 
> Ben Root

As I just posted, I will try to complete the GL backend (using standard GL and 
GLUT). For the font rendering, I think freetype-py can be used to offer decent 
rendering with antialiasing (see http://code.google.com/p/freetype-py/, all 
examples rendered without LCD filtering). But I do not know if it can compares 
with agg text rendering.
If not, I could cache glyphs produced by the agg renderer and just use them.


Nicolas


--
Got Input?   Slashdot Needs You.
Take our quick survey online.  Come on, we don't ask for help often.
Plus, you'll get a chance to win $100 to spend on ThinkGeek.
http://p.sf.net/sfu/slashdot-survey
___
Matplotlib-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/matplotlib-devel